/*
[RFC-0229] Unit tests for the canonical breadcrumb trail builder: ordering (Home → ancestors
→ self), dedupe against Home/self, site-name stripping, empty-ancestor flat trail, and the resolver
seam contract.
- 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 breadcrumbs suite's contract for test-file scaffold coverage.
*/
import { test, expect } from "vitest";
import {
buildBreadcrumbTrail,
stripSiteNameFromTitle,
surfaceAncestorPageIds,
type BreadcrumbAncestorResolver,
type BreadcrumbCrumb,
} from "../breadcrumbs.ts";
const HOME = "https://example.com/";
const SELF = "https://example.com/website/schreiner/muenchen/";
function resolverWith(ancestors: BreadcrumbCrumb[]): BreadcrumbAncestorResolver {
return { resolveAncestors: async () => ancestors };
}
test("flat trail when there are no ancestors: Home → self", async () => {
const trail = await buildBreadcrumbTrail({
pageId: "impressum",
pageTitle: "Impressum | Warpgogol",
selfUrl: "https://example.com/impressum/",
homeLabel: "Startseite",
homeUrl: HOME,
lang: "de",
defaultLang: "de",
resolver: resolverWith([]),
});
expect(trail.map((c) => c.name)).toEqual(["Startseite", "Impressum"]);
expect(trail[1]!.url).toBe("https://example.com/impressum/");
});
test("multi-level trail: Home → ancestors (root-first) → self, site name stripped", async () => {
const trail = await buildBreadcrumbTrail({
pageId: "website-local:schreiner:muenchen",
pageTitle: "Schreiner-Website in München | Warpgogol",
selfUrl: SELF,
homeLabel: "Startseite",
homeUrl: HOME,
lang: "de",
defaultLang: "de",
resolver: resolverWith([
{ name: "Website erstellen lassen", url: "https://example.com/website/" },
{ name: "Schreiner-Websites", url: "https://example.com/website/schreiner/" },
]),
});
expect(trail.map((c) => c.name)).toEqual([
"Startseite",
"Website erstellen lassen",
"Schreiner-Websites",
"Schreiner-Website in München",
]);
expect(trail[trail.length - 1]!.url).toBe(SELF);
});
test("ancestors collapsing onto Home or self are dropped", async () => {
const trail = await buildBreadcrumbTrail({
pageId: "p",
pageTitle: "Self",
selfUrl: SELF,
homeLabel: "Home",
homeUrl: HOME,
lang: "de",
defaultLang: "de",
resolver: resolverWith([
{ name: "Home dup", url: "https://example.com" }, // == Home after trailing-slash normalize
{ name: "Mid", url: "https://example.com/website/" },
{ name: "Self dup", url: SELF.replace(/\/$/, "") }, // == self after normalize
]),
});
expect(trail.map((c) => c.name)).toEqual(["Home", "Mid", "Self"]);
});
test("repeated ancestor URLs are deduped, blank names skipped", async () => {
const trail = await buildBreadcrumbTrail({
pageId: "p",
pageTitle: "Self",
selfUrl: SELF,
homeLabel: "Home",
homeUrl: HOME,
lang: "de",
defaultLang: "de",
resolver: resolverWith([
{ name: "A", url: "https://example.com/a/" },
{ name: "A again", url: "https://example.com/a" }, // same after normalize → dropped
{ name: " ", url: "https://example.com/b/" }, // blank name → dropped
]),
});
expect(trail.map((c) => c.name)).toEqual(["Home", "A", "Self"]);
});
test("stripSiteNameFromTitle trims a ' | Site' suffix only", () => {
expect(stripSiteNameFromTitle("Page | Site")).toBe("Page");
expect(stripSiteNameFromTitle("Just A Page")).toBe("Just A Page");
expect(stripSiteNameFromTitle("A | B | Site")).toBe("A | B");
});
test("surfaceAncestorPageIds derives the depth chain (root-first, excludes self)", () => {
// depth-2 page → [root, depth-1]
expect(surfaceAncestorPageIds("website-local:elektriker:heidelberg")).toEqual([
"website-local:_root",
"website-local:elektriker",
]);
// depth-3 page → [root, depth-1, depth-2]
expect(surfaceAncestorPageIds("website-service:elektriker:leistung:wallbox")).toEqual([
"website-service:_root",
"website-service:elektriker",
"website-service:elektriker:leistung",
]);
// depth-1 page → [root]
expect(surfaceAncestorPageIds("website-local:elektriker")).toEqual(["website-local:_root"]);
});
test("surfaceAncestorPageIds returns [] for the root landing and non-surface ids", () => {
expect(surfaceAncestorPageIds("website-local:_root")).toEqual([]);
expect(surfaceAncestorPageIds("impressum")).toEqual([]); // authored pageId, no colon
expect(surfaceAncestorPageIds("")).toEqual([]);
});