import { describe, expect, it, vi } from "vitest"; import { runFontLocalize, stampFontVersions, type FontLocalizeIo } from "./fontLocalize.js"; function makeIo(input: string): { io: FontLocalizeIo; output: string[]; errors: string[]; } { const output: string[] = []; const errors: string[] = []; return { io: { readInput: async () => input, writeOutput: (value) => output.push(value), writeError: (value) => errors.push(value), }, output, errors, }; } describe("runFontLocalize", () => { it("writes only the localized document to stdout", async () => { const harness = makeIo("source"); const localize = vi.fn(async () => "localized"); const exitCode = await runFontLocalize(harness.io, localize); expect(exitCode).toBe(0); expect(localize).toHaveBeenCalledWith("source"); expect(harness.output).toEqual(["localized"]); expect(harness.errors).toEqual([]); }); it("rejects blank input without calling the resolver", async () => { const harness = makeIo(" \n"); const localize = vi.fn(async (html: string) => html); const exitCode = await runFontLocalize(harness.io, localize); expect(exitCode).toBe(2); expect(localize).not.toHaveBeenCalled(); expect(harness.output).toEqual([]); expect(harness.errors.join(" ")).toContain("input is empty"); }); it("fails without echoing source HTML or resolver details", async () => { const source = ''; const harness = makeIo(source); const localize = vi.fn(async () => { throw new Error(`fetch failed for ${source}`); }); const exitCode = await runFontLocalize(harness.io, localize); expect(exitCode).toBe(1); expect(harness.output).toEqual([]); expect(harness.errors.join(" ")).toContain("font localization failed (Error)"); expect(harness.errors.join(" ")).not.toContain("signed.example"); expect(harness.errors.join(" ")).not.toContain(""); }); it("fails closed when the resolver returns an empty document", async () => { const harness = makeIo("source"); const exitCode = await runFontLocalize(harness.io, async () => "\n"); expect(exitCode).toBe(1); expect(harness.output).toEqual([]); expect(harness.errors.join(" ")).toContain("empty output"); }); }); describe("stampFontVersions", () => { it("records producer and localizer versions inside the document head", () => { const stamped = stampFontVersions( "x", { producer: "0.8.15", localizer: "0.8.16" }, ); expect(stamped).toContain(''); expect(stamped).toContain(''); expect(stamped.indexOf("hyperframes-font-compiler-version")).toBeLessThan( stamped.indexOf(""), ); }); it("inserts both diagnostic stamps after a doctype when no head close exists", () => { const stamped = stampFontVersions("
x
", { producer: "0.8.15", localizer: "0.8.16", }); expect(stamped).toMatch( /^/, ); }); it("inserts both diagnostic stamps at the start when no head or doctype exists", () => { const stamped = stampFontVersions("
x
", { producer: "0.8.15