/* Unit tests for markdown twin provenance covering computeContentHash; buildMarkdownTwinFrontmatter; buildMarkdownTwin. Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only. RFC-1311: Compass header sweep — declares the markdown suite's contract for test-file scaffold coverage. */ import { describe, expect, it } from "vitest"; import { AUDIENCE_BY_PAGE_TYPE, buildMarkdownTwin, buildMarkdownTwinFrontmatter, computeContentHash, parseMarkdownTwinFrontmatter, verifyMarkdownTwinHash, type MarkdownTwinProvenance, } from "../semantic/markdown-twin-provenance.ts"; const baseProvenance: MarkdownTwinProvenance = { canonical: "https://example.com/de/page", language: "de", lastModified: "2024-01-15", license: "CC-BY-4.0", generator: "test", sourceKind: "authored", }; describe("computeContentHash", () => { it("produces sha256: prefix", () => { expect(computeContentHash("body text").startsWith("sha256:")).toBe(true); }); it("is deterministic for same input", () => { expect(computeContentHash("body")).toBe(computeContentHash("body")); }); it("normalizes trailing whitespace", () => { expect(computeContentHash("body\n\n")).toBe(computeContentHash("body")); }); it("normalizes CRLF to LF", () => { expect(computeContentHash("a\r\nb")).toBe(computeContentHash("a\nb")); }); }); describe("buildMarkdownTwinFrontmatter", () => { it("includes all core provenance fields", () => { const fm = buildMarkdownTwinFrontmatter(baseProvenance, "sha256:abc"); expect(fm).toContain('canonical: "https://example.com/de/page"'); expect(fm).toContain('language: "de"'); expect(fm).toContain('lastModified: "2024-01-15"'); expect(fm).toContain('contentHash: "sha256:abc"'); expect(fm).toContain('license: "CC-BY-4.0"'); expect(fm).toContain('generator: "test"'); expect(fm).toContain('sourceKind: "authored"'); expect(fm).toContain('schema: "gogol.markdown-twin@2"'); }); it("emits null for lastModified when null", () => { const fm = buildMarkdownTwinFrontmatter( { ...baseProvenance, lastModified: null }, "sha256:abc", ); expect(fm).toContain("lastModified: null"); }); it("includes pageId when provided", () => { const fm = buildMarkdownTwinFrontmatter({ ...baseProvenance, pageId: "about" }, "sha256:abc"); expect(fm).toContain('pageId: "about"'); }); it("includes sourceInputs when provided", () => { const fm = buildMarkdownTwinFrontmatter( { ...baseProvenance, sourceInputs: ["file1.md", "file2.md"] }, "sha256:abc", ); expect(fm).toContain("sourceInputs:"); expect(fm).toContain('"file1.md"'); }); it("includes semantic meta when provided", () => { const fm = buildMarkdownTwinFrontmatter( { ...baseProvenance, semantic: { id: "page-1", route: "/de/page", title: "Page", type: "content", domain: "content", audience: "general", lang: "de", metaDescription: "A page", priority: 0.7, tags: ["tag1"], }, }, "sha256:abc", ); expect(fm).toContain('id: "page-1"'); expect(fm).toContain('type: "content"'); expect(fm).toContain("priority: 0.7"); }); }); describe("buildMarkdownTwin", () => { it("produces frontmatter + body", () => { const twin = buildMarkdownTwin("# Hello\n\nWorld", baseProvenance); expect(twin.startsWith("---\n")).toBe(true); expect(twin).toContain("# Hello"); expect(twin).toContain("World"); }); }); describe("parseMarkdownTwinFrontmatter", () => { it("round-trips buildMarkdownTwin output", () => { const body = "# Hello\n\nWorld"; const twin = buildMarkdownTwin(body, baseProvenance); const parsed = parseMarkdownTwinFrontmatter(twin); expect(parsed).not.toBeNull(); expect(parsed!.frontmatter.canonical).toBe("https://example.com/de/page"); expect(parsed!.frontmatter.language).toBe("de"); expect(parsed!.body).toBe("# Hello\n\nWorld\n"); }); it("returns null for no frontmatter", () => { expect(parseMarkdownTwinFrontmatter("just text")).toBeNull(); }); }); describe("verifyMarkdownTwinHash", () => { it("verifies correct hash", () => { const twin = buildMarkdownTwin("# Hello", baseProvenance); expect(verifyMarkdownTwinHash(twin)).toBe(true); }); it("fails for tampered body", () => { const twin = buildMarkdownTwin("# Hello", baseProvenance); const tampered = twin.replace("# Hello", "# Tampered"); expect(verifyMarkdownTwinHash(tampered)).toBe(false); }); }); describe("AUDIENCE_BY_PAGE_TYPE", () => { it("maps home to general", () => { expect(AUDIENCE_BY_PAGE_TYPE.home).toBe("general"); }); it("maps projects to developer", () => { expect(AUDIENCE_BY_PAGE_TYPE.projects).toBe("developer"); }); it("maps legal to business_owner", () => { expect(AUDIENCE_BY_PAGE_TYPE.legal).toBe("business_owner"); }); });