r-util-js/packages/vue3/test/dispatch.test.ts

135 lines
5.1 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import { dispatch } from "../src/vue-helper";
/**
* 创建模拟的 Vue ComponentPublicInstance
*/
function createMockInstance(
componentName?: string,
parent?: any,
root?: any,
) {
const instance = {
$parent: parent ?? null,
$root: root ?? null,
$options: { componentName: componentName ?? null },
$emit: vi.fn(),
};
return instance;
}
describe("dispatch", () => {
it("应在祖先组件中找到匹配的 componentName 并触发事件", () => {
const targetComponentName = "FormComponent";
const grandParent = createMockInstance(targetComponentName);
const parent = createMockInstance(undefined, grandParent, grandParent);
const thisArg = createMockInstance(undefined, parent, grandParent);
// thisArg.$parent → parent, parent.$parent → grandParent
parent.$parent = grandParent;
dispatch(thisArg, targetComponentName as any, "validate", { field: "name" });
expect(grandParent.$emit).toHaveBeenCalledWith("validate", { field: "name" });
});
it("应从直接父组件开始查找", () => {
const targetComponentName = "DirectParent";
const parent = createMockInstance(targetComponentName);
const thisArg = createMockInstance(undefined, parent, parent);
dispatch(thisArg, targetComponentName as any, "change", null);
expect(parent.$emit).toHaveBeenCalledWith("change", null);
});
it("当没有父组件且有根组件时,应从根组件开始查找", () => {
const targetComponentName = "RootComponent";
const root = createMockInstance(targetComponentName);
const thisArg = createMockInstance(undefined, null, root);
dispatch(thisArg, targetComponentName as any, "init", undefined);
expect(root.$emit).toHaveBeenCalledWith("init", undefined);
});
it("当 thisArg.$parent 和 thisArg.$root 都为 null 时,应直接返回", () => {
const thisArg = createMockInstance(undefined, null, null);
const targetComponentName = "FormComponent" as any;
// 不应抛出错误
expect(() => dispatch(thisArg, targetComponentName, "validate", {})).not.toThrow();
});
it("当找不到匹配的祖先组件时,不应触发任何事件", () => {
const grandParent = createMockInstance("OtherComponent");
const parent = createMockInstance("AnotherComponent", grandParent, grandParent);
const thisArg = createMockInstance(undefined, parent, grandParent);
dispatch(thisArg, "NonExistentComponent" as any, "validate", {});
expect(grandParent.$emit).not.toHaveBeenCalled();
expect(parent.$emit).not.toHaveBeenCalled();
});
it("应在多级父组件链中找到匹配的祖先", () => {
const targetComponentName = "GrandGrandParent";
const grandGrandParent = createMockInstance(targetComponentName);
const grandParent = createMockInstance("GrandParent", grandGrandParent, grandGrandParent);
const parent = createMockInstance("Parent", grandParent, grandGrandParent);
const thisArg = createMockInstance(undefined, parent, grandGrandParent);
dispatch(thisArg, targetComponentName as any, "submit", { data: "test" });
expect(grandGrandParent.$emit).toHaveBeenCalledWith("submit", { data: "test" });
expect(grandParent.$emit).not.toHaveBeenCalled();
expect(parent.$emit).not.toHaveBeenCalled();
});
it("找到的第一个匹配组件后,不应继续向上查找", () => {
const targetComponentName = "Parent";
const grandParent = createMockInstance(targetComponentName); // 更上层也有同名组件
const parent = createMockInstance(targetComponentName, grandParent, grandParent);
const thisArg = createMockInstance(undefined, parent, grandParent);
dispatch(thisArg, targetComponentName as any, "click", true);
// 应该触发 parent 的事件,而非 grandParent 的
expect(parent.$emit).toHaveBeenCalledWith("click", true);
expect(grandParent.$emit).not.toHaveBeenCalled();
});
it("应支持传递各种类型的参数", () => {
const parent = createMockInstance("Target");
const thisArg = createMockInstance(undefined, parent, parent);
// 字符串
dispatch(thisArg, "Target" as any, "event1", "hello");
expect(parent.$emit).toHaveBeenCalledWith("event1", "hello");
// 数字
dispatch(thisArg, "Target" as any, "event2", 42);
expect(parent.$emit).toHaveBeenCalledWith("event2", 42);
// 数组
dispatch(thisArg, "Target" as any, "event3", [1, 2, 3]);
expect(parent.$emit).toHaveBeenCalledWith("event3", [1, 2, 3]);
// undefined
dispatch(thisArg, "Target" as any, "event4", undefined);
expect(parent.$emit).toHaveBeenCalledWith("event4", undefined);
});
it("当祖先组件的 componentName 为 undefined 时,应跳过继续查找", () => {
const targetComponentName = "TargetComponent";
const grandParent = createMockInstance(targetComponentName);
// parent 没有 componentName
const parent = createMockInstance(undefined, grandParent, grandParent);
const thisArg = createMockInstance(undefined, parent, grandParent);
dispatch(thisArg, targetComponentName as any, "save", {});
expect(grandParent.$emit).toHaveBeenCalledWith("save", {});
});
});