/*
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");
});
});