/* Unit tests for slug covering slugUrl; slugId; HeadingSlugger. It also guards the documented public contract and regression-sensitive edge cases. Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only. RFC-0915: initial unit tests for canonical slug module. */ import { test, expect, describe } from "vitest"; import { slugUrl, slugId, HeadingSlugger } from "../index.ts"; describe("slugUrl", () => { test("German umlauts are expanded", () => { expect(slugUrl("München", "de")).toBe("muenchen"); expect(slugUrl("Köln", "de")).toBe("koeln"); expect(slugUrl("Düsseldorf", "de")).toBe("duesseldorf"); expect(slugUrl("ß", "de")).toBe("ss"); }); test("Ukrainian Cyrillic is transliterated", () => { expect(slugUrl("Київ", "uk")).toBe("kyiv"); expect(slugUrl("Львів", "uk")).toBe("lviv"); }); test("Default locale passes through", () => { expect(slugUrl("Hello World")).toBe("hello-world"); expect(slugUrl("Berlin", "en")).toBe("berlin"); expect(slugUrl("New York", "en")).toBe("new-york"); }); test("Returns entity for empty input", () => { expect(slugUrl("")).toBe("entity"); expect(slugUrl("!!!", "de")).toBe("entity"); }); test("Is idempotent", () => { const once = slugUrl("Frankfurt am Main", "de"); expect(slugUrl(once, "de")).toBe(once); }); }); describe("slugId", () => { test("Generates kebab-case ID from heading", () => { expect(slugId("Fazit")).toBe("fazit"); expect(slugId("Preisvergleich")).toBe("preisvergleich"); expect(slugId("FAQ & Antworten")).toBe("faq-and-antworten"); }); test("Returns entity for empty input", () => { expect(slugId("")).toBe("entity"); expect(slugId("!!!")).toBe("entity"); }); }); describe("HeadingSlugger", () => { test("First occurrence has no suffix", () => { const slugger = new HeadingSlugger(); expect(slugger.slug("Fazit")).toBe("fazit"); }); test("Second occurrence gets -1 suffix", () => { const slugger = new HeadingSlugger(); slugger.slug("Fazit"); expect(slugger.slug("Fazit")).toBe("fazit-1"); }); test("Third occurrence gets -2 suffix", () => { const slugger = new HeadingSlugger(); slugger.slug("Fazit"); slugger.slug("Fazit"); expect(slugger.slug("Fazit")).toBe("fazit-2"); }); test("Different headings do not collide", () => { const slugger = new HeadingSlugger(); expect(slugger.slug("Preis")).toBe("preis"); expect(slugger.slug("Fazit")).toBe("fazit"); }); });