/* Unit tests for canonical uri covering RFC-1075 AC-4: deriveCanonicalUri is pure and deterministic. 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 canonical suite's contract for test-file scaffold coverage. */ import { describe, it, expect } from "vitest"; import { deriveCanonicalUri } from "../canonical-uri.ts"; describe("RFC-1075 AC-4: deriveCanonicalUri is pure and deterministic", () => { it("returns undefined for undefined siteOrigin", () => { expect(deriveCanonicalUri(undefined, "business")).toBeUndefined(); expect(deriveCanonicalUri(undefined, "offering", "off-1")).toBeUndefined(); }); it("returns undefined for empty siteOrigin", () => { expect(deriveCanonicalUri("", "business")).toBeUndefined(); expect(deriveCanonicalUri("", "offering", "off-1")).toBeUndefined(); }); it("derives business URI without entityId — RFC-1115 .json form", () => { expect(deriveCanonicalUri("https://example.example", "business")).toBe( "https://example.example/.well-known/entity/business.json", ); }); it("derives offering URI with entityId — RFC-1115 .json form", () => { expect(deriveCanonicalUri("https://example.example", "offering", "off-1")).toBe( "https://example.example/.well-known/entity/offering/off-1.json", ); }); it("slugifies URI-form entityId to its last path segment", () => { // PBP entity IDs are URIs; the canonical entity URI must embed a slug, // not the raw URI (which would produce a double-scheme, non-FS-safe path). expect( deriveCanonicalUri( "https://example.example", "offering", "https://example.example/id/offerings/automation", ), ).toBe("https://example.example/.well-known/entity/offering/automation.json"); }); it("returns undefined for offering without entityId", () => { expect(deriveCanonicalUri("https://example.example", "offering")).toBeUndefined(); expect(deriveCanonicalUri("https://example.example", "offering", "")).toBeUndefined(); }); it("strips trailing slashes from siteOrigin", () => { expect(deriveCanonicalUri("https://example.example/", "business")).toBe( "https://example.example/.well-known/entity/business.json", ); expect(deriveCanonicalUri("https://example.example//", "business")).toBe( "https://example.example/.well-known/entity/business.json", ); }); it("is deterministic — same inputs always produce same output", () => { const inputs = ["https://example.example", "https://example.example/"] as const; for (const origin of inputs) { const a = deriveCanonicalUri(origin, "offering", "off-1"); const b = deriveCanonicalUri(origin, "offering", "off-1"); expect(a).toBe(b); } }); it("is side-effect-free — does not mutate inputs", () => { const origin = "https://example.example"; const before = origin; deriveCanonicalUri(origin, "business"); expect(origin).toBe(before); }); });