// @vitest-environment jsdom import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { flushView, renderView } from "./view-test-utils"; const sendMessageMock = vi.fn<(msg: unknown) => Promise>(); vi.mock("../../shared/bridge", () => ({ sendMessage: (msg: unknown) => sendMessageMock(msg), })); vi.mock("../components/RecoveryRuneBackground", () => ({ RecoveryRuneBackground: () => null, })); vi.mock("../codex/generate", () => { throw new Error("blocked heavy Codex module"); }); vi.mock("../codex/rs-loader", () => ({ getReedSolomon: vi.fn(async () => ({})), })); describe("CodexGenerateView", () => { let dispose: (() => void) | undefined; beforeEach(() => { document.body.innerHTML = ""; sendMessageMock.mockReset(); sendMessageMock.mockResolvedValue({ ok: true, data: { slotA: JSON.stringify({ slot: "a" }), slotB: null, lastModified: null, entryCount: 3, recoveryWords: [ "abandon", "ability", "able", "about", "above", "absent", "absorb", "abstract", "absurd", "abuse", "access", "accident", ], verifyCode: "PX-TEST-CODE", vaultUnlocked: true, }, }); vi.stubGlobal("chrome", { storage: { local: { set: vi.fn(), }, }, } as unknown as typeof chrome); }); afterEach(() => { dispose?.(); dispose = undefined; vi.unstubAllGlobals(); }); it("shows the recovery-word gate even if the heavy Codex module fails to load", async () => { const { CodexGenerateView } = await import("./CodexGenerateView"); const mounted = renderView( , ); dispose = mounted.dispose; await flushView(); await flushView(); expect(mounted.container.textContent).toContain("your recovery words."); expect(mounted.container.textContent).toContain("abandon"); expect(mounted.container.textContent).toContain("Failed to load Codex library"); }); it("PB-26-607: never renders a raw background error string", async () => { const RAW = "Error: ENOENT /vaults/slot-b.json at readSlot (vault.ts:884)"; sendMessageMock.mockResolvedValue({ ok: false, error: RAW }); const { CodexGenerateView } = await import("./CodexGenerateView"); const mounted = renderView( , ); dispose = mounted.dispose; await flushView(); await flushView(); expect(mounted.container.textContent).toContain("could not load vault data"); expect(mounted.container.textContent).not.toContain(RAW); expect(mounted.container.textContent).not.toContain("vault.ts"); }); });