import { describe, expect, test } from "bun:test"; import { defineAuthz, getAuthzCatalog } from "@wrnexus/authz"; import { applyAuthzManifestEarly, createProductionHandlers, type ProdManifest, } from "../src/prod.ts"; const EMPTY_MANIFEST: ProdManifest = { pages: [], api: [], realtime: [], middleware: [], components: [], layouts: [], }; describe("createProductionHandlers authorization wiring (the idempotent second pass)", () => { test("an empty (or absent) authz array yields an empty catalog, no error", () => { createProductionHandlers(EMPTY_MANIFEST, { authz: [] }); expect(getAuthzCatalog().permissions.size).toBe(0); createProductionHandlers(EMPTY_MANIFEST, {}); expect(getAuthzCatalog().permissions.size).toBe(0); }); test("a declaration with no default export warns and is skipped, not fatal", () => { const originalWarn = console.warn; const warnings: unknown[][] = []; console.warn = (...args: unknown[]) => { warnings.push(args); }; try { createProductionHandlers(EMPTY_MANIFEST, { authz: [ { source: "broken.ts", module: undefined }, { source: "ok.ts", module: defineAuthz({ permissions: { "post:read": {} } }), }, ], }); } finally { console.warn = originalWarn; } expect(getAuthzCatalog().permissions.has("post:read")).toBe(true); expect(getAuthzCatalog().permissions.size).toBe(1); expect(warnings.some((args) => args.some((arg) => String(arg).includes("broken.ts")))).toBe( true, ); }); test("a conflicting pair of declarations throws, naming both source files", () => { expect(() => createProductionHandlers(EMPTY_MANIFEST, { authz: [ { source: "a.ts", module: defineAuthz({ permissions: { "post:read": { risk: "low" } } }), }, { source: "b.ts", module: defineAuthz({ permissions: { "post:read": { risk: "high" } } }), }, ], }), ).toThrow(/WRN-AUTHZ-CONFLICT/); let thrown: unknown; try { createProductionHandlers(EMPTY_MANIFEST, { authz: [ { source: "a.ts", module: defineAuthz({ permissions: { "post:read": { risk: "low" } } }), }, { source: "b.ts", module: defineAuthz({ permissions: { "post:read": { risk: "high" } } }), }, ], }); } catch (error) { thrown = error; } expect(thrown).toBeInstanceOf(Error); const message = (thrown as Error).message; expect(message).toContain("a.ts"); expect(message).toContain("b.ts"); }); test("calling createProductionHandlers a second time with different declarations re-validates, not skips", () => { // Regression guard for the "skip merging if a catalog is already set" // trap: since setAuthzCatalog is a process-wide singleton, an earlier // test (or an earlier createProductionHandlers call in the same process) // can leave hasAuthzCatalog() true. This call must still independently // merge+validate its OWN opts.authz, not silently trust a stale catalog // left over from something else. createProductionHandlers(EMPTY_MANIFEST, { authz: [{ source: "first.ts", module: defineAuthz({ permissions: { "a:read": {} } }) }], }); expect(getAuthzCatalog().permissions.has("a:read")).toBe(true); createProductionHandlers(EMPTY_MANIFEST, { authz: [{ source: "second.ts", module: defineAuthz({ permissions: { "b:read": {} } }) }], }); expect(getAuthzCatalog().permissions.has("a:read")).toBe(false); expect(getAuthzCatalog().permissions.has("b:read")).toBe(true); }); }); describe("applyAuthzManifestEarly (the eager, silent pass called only by the generated .authz-setup.ts)", () => { test("sets the catalog from valid declarations", () => { applyAuthzManifestEarly([ { source: "early.ts", module: defineAuthz({ permissions: { "early:read": {} } }) }, ]); expect(getAuthzCatalog().permissions.has("early:read")).toBe(true); }); test("silently skips a missing default export — no warning, no throw", () => { const originalWarn = console.warn; let warnCalls = 0; console.warn = () => { warnCalls++; }; try { expect(() => applyAuthzManifestEarly([{ source: "broken.ts", module: undefined }]), ).not.toThrow(); } finally { console.warn = originalWarn; } expect(warnCalls).toBe(0); expect(getAuthzCatalog().permissions.size).toBe(0); }); test("still throws on a genuine conflict (fatal either way, just earlier)", () => { expect(() => applyAuthzManifestEarly([ { source: "a.ts", module: defineAuthz({ permissions: { "post:read": { risk: "low" } } }) }, { source: "b.ts", module: defineAuthz({ permissions: { "post:read": { risk: "high" } } }) }, ]), ).toThrow(/WRN-AUTHZ-CONFLICT/); }); });