import { test, expect } from "vitest"; import { buildPage, type PageEntry } from "../page.ts"; import { EMPTY_RUNTIME_CONTEXT } from "../../runtime/runtime-context.ts"; /* Unit tests for dev props validator covering its documented public contract and regression-sensitive edge cases. Do not test real propsSchema resolution here — see dev-props-validator's own schema-shape checks, exercised indirectly via props-contract.test.ts's validateExampleAgainstSchema (identical logic). RFC-1311: Compass header sweep — declares the dev suite's contract for test-file scaffold coverage. */ function fixtureEntry(): PageEntry { return { kind: "page", cosmicStar: "TestStar", title: "Test", description: "Test page", lang: "en", blocks: [ { id: "fixture-block", type: "FixturePlanet", props: { extra: "not-in-schema" }, }, ], }; } test("buildPage: validateProps is called with planetName, props, and blockId", async () => { const entry = fixtureEntry(); const ctx = EMPTY_RUNTIME_CONTEXT("en"); const calls: Array<{ planetName: string; props: Record; blockId: string | null; }> = []; const page = await buildPage(entry, ctx, { resolveImportPath: () => "@warpgogol/werkstatt-site/ui/sections/fixture-section.astro", validateProps: async (planetName, props, blockId) => { calls.push({ planetName, props, blockId }); }, }); expect(page.blocks.length).toBe(1); expect(calls.length).toBe(1); expect(calls[0]?.planetName).toBe("FixturePlanet"); expect(calls[0]?.blockId).toBe("fixture-block"); expect(calls[0]?.props).toEqual({ extra: "not-in-schema" }); }); test("buildPage: a validateProps throw (PAGE-PROPS-01) propagates and includes the block id", async () => { const entry = fixtureEntry(); const ctx = EMPTY_RUNTIME_CONTEXT("en"); try { await buildPage(entry, ctx, { resolveImportPath: () => "@warpgogol/werkstatt-site/ui/sections/fixture-section.astro", validateProps: async (_planetName, props, blockId) => { if ("extra" in props) { throw new Error( `[PAGE-PROPS-01] block "${blockId}" (FixturePlanet): unknown property "extra"`, ); } }, }); expect.fail("should have thrown"); } catch (error) { expect(error).toBeInstanceOf(Error); expect((error as Error).message).toMatch(/PAGE-PROPS-01/); expect((error as Error).message).toMatch(/fixture-block/); } }); test("buildPage: without validateProps, no hook is invoked (opt-in, zero behavior change)", async () => { const entry = fixtureEntry(); const ctx = EMPTY_RUNTIME_CONTEXT("en"); const page = await buildPage(entry, ctx, { resolveImportPath: () => "@warpgogol/werkstatt-site/ui/sections/fixture-section.astro", }); expect(page.blocks.length).toBe(1); });