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);
});