From 34fa14ffc625cd9aec24020e0780d25995b88e26 Mon Sep 17 00:00:00 2001 From: Horizontal42 <75383519+Horizontal42@users.noreply.github.com> Date: Wed, 8 Jul 2026 15:43:03 +0300 Subject: [PATCH] add tests for extensions.ts Covers makeApi's delegation to the engine and runExtensions' per-script error isolation (one bad extension shouldn't stop the rest from loading). --- src/extensions.test.ts | 108 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/extensions.test.ts diff --git a/src/extensions.test.ts b/src/extensions.test.ts new file mode 100644 index 0000000..41691ec --- /dev/null +++ b/src/extensions.test.ts @@ -0,0 +1,108 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import { makeApi, runExtensions } from "./extensions"; +import { SumEngine } from "./engine"; + +describe("extensions", () => { + let mockEngine: any; + + beforeEach(() => { + mockEngine = { + setVariable: vi.fn(), + addUnit: vi.fn(), + addFunction: vi.fn(), + }; + }); + + describe("makeApi", () => { + it("delegates setVariable to engine", () => { + const api = makeApi(mockEngine as SumEngine); + api.setVariable("myVar", 42); + expect(mockEngine.setVariable).toHaveBeenCalledWith("myVar", 42); + }); + + it("delegates addUnit to engine", () => { + const api = makeApi(mockEngine as SumEngine); + const spec = { id: "testUnit", phrases: "tests", baseUnitId: "USD", ratio: 1 }; + api.addUnit(spec); + expect(mockEngine.addUnit).toHaveBeenCalledWith(spec); + }); + + it("delegates addFunction to engine", () => { + const api = makeApi(mockEngine as SumEngine); + const spec = { id: "testFunc", phrases: "test" }; + const fn = () => 42; + api.addFunction(spec, fn); + expect(mockEngine.addFunction).toHaveBeenCalledWith(spec, fn); + }); + }); + + describe("runExtensions", () => { + let consoleErrorSpy: any; + + beforeEach(() => { + consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); + }); + + afterEach(() => { + consoleErrorSpy.mockRestore(); + }); + + it("runs scripts successfully using numi api", () => { + const scripts = [ + { + name: "script1", + code: "numi.setVariable('var1', 10);", + }, + { + name: "script2", + code: "numi.addUnit({ id: 'unit1', phrases: 'u', baseUnitId: 'USD', ratio: 1 });", + }, + ]; + + runExtensions(mockEngine as SumEngine, scripts); + + expect(mockEngine.setVariable).toHaveBeenCalledWith("var1", 10); + expect(mockEngine.addUnit).toHaveBeenCalledWith({ id: "unit1", phrases: "u", baseUnitId: "USD", ratio: 1 }); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + }); + + it("swallows errors and logs to console.error", () => { + const scripts = [ + { + name: "script1", + code: "throw new Error('test error');", + }, + ]; + + runExtensions(mockEngine as SumEngine, scripts); + + expect(consoleErrorSpy).toHaveBeenCalledWith( + "extension script1 failed:", + expect.any(Error) + ); + }); + + it("continues running other scripts if one fails", () => { + const scripts = [ + { + name: "script1", + code: "numi.setVariable('var1', 10);", + }, + { + name: "script2", + code: "throw new Error('boom');", + }, + { + name: "script3", + code: "numi.setVariable('var3', 30);", + }, + ]; + + runExtensions(mockEngine as SumEngine, scripts); + + expect(mockEngine.setVariable).toHaveBeenCalledWith("var1", 10); + expect(mockEngine.setVariable).toHaveBeenCalledWith("var3", 30); + expect(consoleErrorSpy).toHaveBeenCalledTimes(1); + }); + }); +});