@esmx/router-vue
Version:
Vue integration for @esmx/router - A universal router that works seamlessly with both Vue 2.7+ and Vue 3
351 lines (350 loc) • 13.2 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import { beforeEach, describe, expect, it, vi } from "vitest";
import { computed, nextTick, ref } from "vue";
import { version } from "vue";
import {
createDependentProxy,
createSymbolProperty,
isESModule,
isVue3,
resolveComponent
} from "./util.mjs";
describe("util.ts - Utility Functions", () => {
describe("isVue3", () => {
it("should correctly identify Vue 3", () => {
expect(isVue3).toBe(version.startsWith("3."));
expect(typeof isVue3).toBe("boolean");
});
it("should be consistent with Vue version check", () => {
const expectedResult = version.startsWith("3.");
expect(isVue3).toBe(expectedResult);
});
});
describe("createSymbolProperty", () => {
let testSymbol;
let symbolProperty;
let testInstance;
beforeEach(() => {
testSymbol = Symbol("test-symbol");
symbolProperty = createSymbolProperty(testSymbol);
testInstance = {};
});
describe("set method", () => {
it("should set value using symbol as key", () => {
const testValue = "test-value";
symbolProperty.set(testInstance, testValue);
expect(testInstance[testSymbol]).toBe(testValue);
});
it("should handle different value types", () => {
const stringValue = "string-value";
const numberValue = 42;
const objectValue = { key: "value" };
const arrayValue = [1, 2, 3];
const stringProperty = createSymbolProperty(
Symbol("string")
);
const numberProperty = createSymbolProperty(
Symbol("number")
);
const objectProperty = createSymbolProperty(
Symbol("object")
);
const arrayProperty = createSymbolProperty(
Symbol("array")
);
stringProperty.set(testInstance, stringValue);
numberProperty.set(testInstance, numberValue);
objectProperty.set(testInstance, objectValue);
arrayProperty.set(testInstance, arrayValue);
expect(stringProperty.get(testInstance)).toBe(stringValue);
expect(numberProperty.get(testInstance)).toBe(numberValue);
expect(objectProperty.get(testInstance)).toBe(objectValue);
expect(arrayProperty.get(testInstance)).toBe(arrayValue);
});
it("should overwrite existing value", () => {
const firstValue = "first-value";
const secondValue = "second-value";
symbolProperty.set(testInstance, firstValue);
expect(symbolProperty.get(testInstance)).toBe(firstValue);
symbolProperty.set(testInstance, secondValue);
expect(symbolProperty.get(testInstance)).toBe(secondValue);
});
});
describe("get method", () => {
it("should return undefined for non-existent symbol", () => {
const result = symbolProperty.get(testInstance);
expect(result).toBeUndefined();
});
it("should return correct value after setting", () => {
const testValue = "retrieved-value";
symbolProperty.set(testInstance, testValue);
const result = symbolProperty.get(testInstance);
expect(result).toBe(testValue);
});
it("should return undefined after value is deleted", () => {
const testValue = "temporary-value";
symbolProperty.set(testInstance, testValue);
delete testInstance[testSymbol];
const result = symbolProperty.get(testInstance);
expect(result).toBeUndefined();
});
});
describe("symbol isolation", () => {
it("should not interfere with different symbols", () => {
const symbol1 = Symbol("symbol1");
const symbol2 = Symbol("symbol2");
const property1 = createSymbolProperty(symbol1);
const property2 = createSymbolProperty(symbol2);
const value1 = "value1";
const value2 = "value2";
property1.set(testInstance, value1);
property2.set(testInstance, value2);
expect(property1.get(testInstance)).toBe(value1);
expect(property2.get(testInstance)).toBe(value2);
expect(property1.get(testInstance)).not.toBe(value2);
expect(property2.get(testInstance)).not.toBe(value1);
});
it("should work with multiple instances", () => {
const instance1 = {};
const instance2 = {};
const testValue1 = "instance1-value";
const testValue2 = "instance2-value";
symbolProperty.set(instance1, testValue1);
symbolProperty.set(instance2, testValue2);
expect(symbolProperty.get(instance1)).toBe(testValue1);
expect(symbolProperty.get(instance2)).toBe(testValue2);
});
});
describe("type safety", () => {
it("should maintain type information through generic", () => {
const interfaceSymbol = Symbol("interface");
const interfaceProperty = createSymbolProperty(interfaceSymbol);
const testObject = { name: "test", count: 5 };
interfaceProperty.set(testInstance, testObject);
const result = interfaceProperty.get(testInstance);
expect(result).toEqual(testObject);
expect(result == null ? void 0 : result.name).toBe("test");
expect(result == null ? void 0 : result.count).toBe(5);
});
});
});
describe("isESModule", () => {
describe("should return true for ES modules", () => {
it("should identify module with __esModule property", () => {
const esModule = { __esModule: true };
expect(isESModule(esModule)).toBe(true);
});
it("should identify module with Symbol.toStringTag", () => {
const esModule = { [Symbol.toStringTag]: "Module" };
expect(isESModule(esModule)).toBe(true);
});
it("should identify module with both properties", () => {
const esModule = {
__esModule: true,
[Symbol.toStringTag]: "Module"
};
expect(isESModule(esModule)).toBe(true);
});
it("should handle truthy __esModule values", () => {
const testCases = [
{ __esModule: true },
{ __esModule: 1 },
{ __esModule: "true" },
{ __esModule: {} },
{ __esModule: [] }
];
testCases.forEach((moduleObj) => {
expect(isESModule(moduleObj)).toBe(true);
});
});
});
describe("should return false for non-ES modules", () => {
it("should return false for null", () => {
expect(isESModule(null)).toBe(false);
});
it("should return false for undefined", () => {
expect(isESModule(void 0)).toBe(false);
});
it("should return false for plain objects", () => {
const plainObject = { key: "value" };
expect(isESModule(plainObject)).toBe(false);
});
it("should return false for objects with falsy __esModule", () => {
const testCases = [
{ __esModule: false },
{ __esModule: 0 },
{ __esModule: "" },
{ __esModule: null },
{ __esModule: void 0 }
];
testCases.forEach((moduleObj) => {
expect(isESModule(moduleObj)).toBe(false);
});
});
it("should return false for objects with wrong Symbol.toStringTag", () => {
const testCases = [
{ [Symbol.toStringTag]: "Object" },
{ [Symbol.toStringTag]: "Function" },
{ [Symbol.toStringTag]: "Array" },
{ [Symbol.toStringTag]: "" },
{ [Symbol.toStringTag]: null }
];
testCases.forEach((moduleObj) => {
expect(isESModule(moduleObj)).toBe(false);
});
});
it("should return false for primitive values", () => {
const primitives = [42, "string", true, false, Symbol("test")];
primitives.forEach((primitive) => {
expect(isESModule(primitive)).toBe(false);
});
});
it("should return false for functions and arrays", () => {
const nonObjects = [
() => {
},
() => {
},
[],
[1, 2, 3],
/* @__PURE__ */ new Date()
];
nonObjects.forEach((nonObj) => {
expect(isESModule(nonObj)).toBe(false);
});
});
});
});
describe("resolveComponent", () => {
describe("should return default export or module itself", () => {
it("should return null for falsy values", () => {
expect(resolveComponent(null)).toBeNull();
expect(resolveComponent(void 0)).toBeNull();
expect(resolveComponent(false)).toBeNull();
expect(resolveComponent(0)).toBeNull();
expect(resolveComponent("")).toBeNull();
});
it("should return default export if available", () => {
const defaultExport = { name: "DefaultComponent" };
const module = {
__esModule: true,
default: defaultExport,
other: "value"
};
expect(resolveComponent(module)).toBe(defaultExport);
});
it("should return the module itself if no default export", () => {
const module = {
__esModule: true,
someExport: "value",
otherExport: 42
};
expect(resolveComponent(module)).toBe(module);
});
it("should handle modules with Symbol.toStringTag", () => {
const defaultExport = { name: "SymbolDefaultComponent" };
const module = {
[Symbol.toStringTag]: "Module",
default: defaultExport
};
expect(resolveComponent(module)).toBe(defaultExport);
});
it("should return non-module objects as is", () => {
const nonModule = { prop: "value" };
expect(resolveComponent(nonModule)).toBe(nonModule);
});
it("should handle various component types", () => {
const functionComponent = () => ({ name: "FunctionComponent" });
expect(resolveComponent(functionComponent)).toBe(
functionComponent
);
class ClassComponent {
constructor() {
__publicField(this, "name", "ClassComponent");
}
}
const classInstance = new ClassComponent();
expect(resolveComponent(classInstance)).toBe(classInstance);
});
});
});
describe("createDependentProxy", () => {
it("should return original property values", () => {
const original = { foo: "bar", count: 42 };
const dep = ref(false);
const proxy = createDependentProxy(original, dep);
expect(proxy.foo).toBe("bar");
expect(proxy.count).toBe(42);
});
it("should handle method calls correctly", () => {
const original = {
items: [1, 2, 3],
getItems() {
return this.items;
}
};
const dep = ref(false);
const proxy = createDependentProxy(original, dep);
expect(proxy.getItems()).toEqual([1, 2, 3]);
expect(proxy.getItems()).toBe(original.items);
});
it("should handle nested property access", () => {
const original = {
nested: {
value: "nested-value"
}
};
const dep = ref(false);
const proxy = createDependentProxy(original, dep);
expect(proxy.nested.value).toBe("nested-value");
});
it("should allow property modification", () => {
const original = { value: "original" };
const dep = ref(false);
const proxy = createDependentProxy(original, dep);
proxy.value = "modified";
expect(proxy.value).toBe("modified");
expect(original.value).toBe("modified");
});
it("should trigger computed updates when dependency changes", async () => {
const original = { value: "test" };
const dep = ref(false);
const proxy = createDependentProxy(original, dep);
const computedValue = computed(() => {
return proxy.value + "-" + String(dep.value);
});
expect(computedValue.value).toBe("test-false");
dep.value = true;
await nextTick();
expect(computedValue.value).toBe("test-true");
proxy.value = "updated";
dep.value = false;
await nextTick();
expect(computedValue.value).toBe("updated-false");
});
it("should handle special properties", () => {
const symbol = Symbol("test");
const original = {
[symbol]: "symbol-value"
};
const dep = ref(false);
const proxy = createDependentProxy(original, dep);
expect(proxy[symbol]).toBe("symbol-value");
});
it("should read the dependency on property access", () => {
const original = { value: "test" };
const dep = ref(false);
const spy = vi.fn();
const depValue = dep.value;
vi.spyOn(dep, "value", "get").mockImplementation(() => {
spy();
return depValue;
});
const proxy = createDependentProxy(original, dep);
proxy.value;
expect(spy).toHaveBeenCalled();
});
});
});