@asimojs/asimo
Version:
Asynchronous dependency manager for Typescript projects
250 lines (220 loc) • 8.73 kB
text/typescript
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { interfaceId, asm as rsm } from "../asimo";
import { AsmContext } from "../asimo.types";
import { _CalculatorService } from "./calculator";
import { Adder, AdderIID } from "./adder";
import { CalculatorIID } from "./types";
import { _MultiplierImpl, MultiplierIID } from "./multiplier";
describe("Asimo Logs", () => {
let asm: AsmContext,
logs: string[] = [];
const console1 = globalThis.console;
const AdderIID2 = interfaceId<Adder>("asimo.src.tests.Adder2");
function mockGlobalConsole() {
globalThis.console = Object.create(console1, {
log: {
writable: true,
configurable: true,
value: (...args: any[]) => {
if (Array.isArray(args[0])) {
logs.push(...args[0]);
} else {
logs.push(args[0].replace(/\%c/g, ""));
}
},
},
});
return logs;
}
function resetGlobalConsole() {
globalThis.console = console1;
}
function createContext() {
const c = rsm.createChildContext("test");
// override calculator service
c.registerService(CalculatorIID, async () => new _CalculatorService());
return c;
}
beforeEach(() => {
// run tests in an independent context
mockGlobalConsole();
logs = [];
asm = createContext();
asm.logger = globalThis.console;
});
afterEach(() => {
resetGlobalConsole();
});
it("should log errors on the console by default", async () => {
expect(logs.join("")).toBe("");
let err = "";
try {
await asm.fetch("asimo.src.tests.Calc123");
} catch (ex) {
err = ex.message;
}
expect(logs.join("")).toBe(
'ASM [/asm/test] Interface not found: "asimo.src.tests.Calc123"',
);
expect(err).toBe('ASM [/asm/test] Interface not found: "asimo.src.tests.Calc123"');
logs = [];
try {
const add = await asm.fetch(AdderIID2);
} catch (ex) {
err = ex.message;
}
expect(logs.join("")).toBe('ASM [/asm/test] Interface not found: "asimo.src.tests.Adder2"');
expect(err).toBe('ASM [/asm/test] Interface not found: "asimo.src.tests.Adder2"');
});
it("should log errors when fetching multiple iids (1 error)", async () => {
expect(logs.join("")).toBe("");
let err = "";
try {
await asm.fetch(CalculatorIID, AdderIID2);
} catch (ex) {
err = ex.message;
}
expect(logs.join("")).toBe('ASM [/asm/test] Interface not found: "asimo.src.tests.Adder2"');
expect(err).toBe('ASM [/asm/test] Interface not found: "asimo.src.tests.Adder2"');
logs = [];
});
it("should log errors when fetching multiple iids (>1 error)", async () => {
expect(logs.join("")).toBe("");
asm.registerService(AdderIID2, () => 123 as any);
let err = "";
try {
await asm.fetch(AdderIID2);
} catch (ex) {
err = ex.message;
}
expect(logs.join(";")).toBe(
'ASM [/asm/test] Invalid factory output: "asimo.src.tests.Adder2";ASM [/asm/test] Interface not found: "asimo.src.tests.Adder2"',
);
expect(err).toBe('ASM [/asm/test] Interface not found: "asimo.src.tests.Adder2"');
logs = [];
});
it("should log errors when get doesn't find one or multipe object", async () => {
asm.registerObject(CalculatorIID, {} as any);
let err = "";
try {
asm.get(AdderIID2);
} catch (ex) {
err = ex.message;
}
expect(logs.join(";")).toBe('ASM [/asm/test] Object not found: "asimo.src.tests.Adder2"');
logs = [];
err = "";
try {
asm.get(CalculatorIID, AdderIID2);
} catch (ex) {
err = ex.message;
}
expect(logs.join(";")).toBe('ASM [/asm/test] Object not found: "asimo.src.tests.Adder2"');
logs = [];
err = "";
try {
asm.get(AdderIID, AdderIID2);
} catch (ex) {
err = ex.message;
}
expect(logs.join(";")).toBe(
'ASM [/asm/test] Objects not found: ["asimo.src.tests.Adder", "asimo.src.tests.Adder2"]',
);
});
it("should not log when logger is null", async () => {
asm.logger = null;
expect(logs.join("")).toBe("");
try {
await asm.fetch("asimo.src.tests.Calc123");
} catch (ex) {}
expect(logs.join("")).toBe("");
logs = [];
try {
const add = await asm.fetch(AdderIID2);
expect(add).toBe(null);
} catch (ex) {}
expect(logs.join("")).toBe("");
asm.logger = console;
});
it("should validate iids", async () => {
logs = [];
asm.registerService(123 as any, () => 123);
expect(logs.join("")).toBe("ASM [/asm/test] [registerService] Invalid interface id: 123");
logs = [];
asm.registerService({ ns: "" }, () => 123);
expect(logs.join("")).toBe(
'ASM [/asm/test] [registerService] Invalid interface id: {"ns":""}',
);
logs = [];
asm.registerService({ ns: 234 as any }, () => 123);
expect(logs.join("")).toBe(
'ASM [/asm/test] [registerService] Invalid interface id: {"ns":234}',
);
logs = [];
asm.registerService(undefined as any, () => 123);
expect(logs.join("")).toBe(
"ASM [/asm/test] [registerService] Invalid interface id: undefined",
);
});
it("should validate factories and group loaders", async () => {
logs = [];
asm.registerService(CalculatorIID, 123 as any);
expect(logs.join("")).toBe("ASM [/asm/test] [registerService] Invalid factory: 123");
logs = [];
asm.registerFactory(CalculatorIID, 123 as any);
expect(logs.join("")).toBe("ASM [/asm/test] [registerFactory] Invalid factory: 123");
logs = [];
asm.registerGroup([CalculatorIID], 123 as any);
expect(logs.join("")).toBe("ASM [/asm/test] [registerGroup] Invalid group loader: 123");
});
it("should logState in the console", async () => {
const c2 = asm.createChildContext("context2");
c2.registerService(CalculatorIID, async () => new _CalculatorService());
c2.registerService(MultiplierIID, () => new _MultiplierImpl());
c2.logState();
expect(logs).toEqual([
"Context /asm/test/context2:",
"+ asimo.src.tests.Calculator [service]: not loaded",
"+ asimo.src.tests.Multiplier [service]: not loaded",
"Context /asm/test:",
"+ asimo.src.tests.Calculator [service]: not loaded",
"Context /asm:",
"+ asimo.src.tests.Calculator [service]: not loaded",
"+ asimo.src.tests.Adder [service]: not loaded",
"+ asimo.src.tests.Multiplier [object]",
]);
logs = [];
const mult = await c2.fetch(MultiplierIID);
expect(mult.multiply(2, 4)).toBe(8);
c2.logState();
expect(logs).toEqual([
"Context /asm/test/context2:",
"+ asimo.src.tests.Calculator [service]: not loaded",
"+ asimo.src.tests.Multiplier [service]: loaded", // loaded here
"Context /asm/test:",
"+ asimo.src.tests.Calculator [service]: not loaded",
"Context /asm:",
"+ asimo.src.tests.Calculator [service]: not loaded",
"+ asimo.src.tests.Adder [service]: not loaded",
"+ asimo.src.tests.Multiplier [object]",
]);
});
it("should logState in an output array", async () => {
const c2 = asm.createChildContext("context2");
const out: string[] = [];
const [mult, adder] = await c2.fetch(MultiplierIID, AdderIID);
expect(mult.multiply(2, 4)).toBe(8);
expect(adder(5, 4)).toBe(9);
c2.logState(out);
expect(logs).toEqual([]);
expect(out).toEqual([
"Context /asm/test/context2 [empty]",
"Context /asm/test:",
"+ asimo.src.tests.Calculator [service]: not loaded",
"Context /asm:",
"+ asimo.src.tests.Calculator [service]: not loaded",
"+ asimo.src.tests.Adder [service]: loaded", // loaded
"+ asimo.src.tests.Multiplier [object]",
]);
});
});