// Wiki-Ansicht: Übersichts-/Schlagwort-Seiten, Dokumentseite, Leerzustände. import { beforeEach, describe, expect, it, vi } from "vitest"; import { initWikiView } from "./wiki-view"; function setup() { document.body.innerHTML = `
`; const onLink = vi.fn(); const view = initWikiView(document.getElementById("w")!, onLink); return { view, onLink }; } const doc = (name: string, extra: object = {}) => ({ name, title: name.toUpperCase(), description: null, tags: [], date: "2026-07-19", backlinks: 0, ...extra, }); const page = JSON.stringify({ kind: "page", home: "/tmp/archiv", tag: null, total: 3, tags: [ { name: "adr", count: 2 }, { name: "infra", count: 1 }, ], recent: [doc("neu")], folders: [ { name: "", docs: [doc("wurzel-doc", { backlinks: 2, tags: ["adr"] })] }, { name: "konzepte", docs: [doc("neu"), doc("alt")] }, ], }); describe("initWikiView — Seiten", () => { it("rendert Kopf, Chips, Zuletzt- und Ordner-Sektionen", () => { const { view } = setup(); view.set(page); expect(document.querySelector(".wiki-head-title")!.textContent).toBe("Archiv"); expect(document.querySelector(".wiki-head-right")!.textContent).toBe("3 Dokumente"); const chips = [...document.querySelectorAll(".wiki-chips .wiki-chip")].map( (c) => c.textContent, ); expect(chips).toEqual(["Alle", "#adr 2", "#infra 1"]); const eyebrows = [...document.querySelectorAll(".wiki-folder")].map( (e) => e.textContent, ); expect(eyebrows).toEqual(["Zuletzt", "Wurzel", "konzepte/"]); expect(document.querySelector(".wiki-doc-back")!.textContent).toBe("↩ 2"); }); it("Dokumentzeile öffnet das Dokument, Tag-Chip die Tag-Seite", () => { const { view, onLink } = setup(); view.set(page); const rows = document.querySelectorAll(".wiki-doc"); rows[1].click(); // Wurzel-Dokument (nach der Zuletzt-Zeile) expect(onLink).toHaveBeenCalledWith("wurzel-doc"); rows[1].querySelector(".wiki-doc-tags .wiki-chip")!.click(); expect(onLink).toHaveBeenCalledWith("tag:adr"); document.querySelector(".wiki-chips .wiki-chip")!.click(); expect(onLink).toHaveBeenCalledWith("tag:"); }); it("Tag-Seite: Titel, aktiver Chip, Leerfall", () => { const { view } = setup(); view.set( JSON.stringify({ kind: "page", home: "/a", tag: "adr", total: 0, tags: [{ name: "adr", count: 1 }], recent: [], folders: [], }), ); expect(document.querySelector(".wiki-head-title")!.textContent).toBe("#adr"); const active = document.querySelector(".wiki-chip.active")!; expect(active.textContent).toBe("#adr 1"); expect(document.querySelector(".wiki-empty strong")!.textContent).toBe( "Keine Dokumente mit #adr.", ); }); it("leeres Archiv erklärt das Archivieren", () => { const { view } = setup(); view.set( JSON.stringify({ kind: "page", home: "/a", tag: null, total: 0, tags: [], recent: [], folders: [], }), ); expect(document.querySelector(".wiki-empty")!.textContent).toContain( "Das Archiv ist leer.", ); }); }); describe("initWikiView — Dokument und Leerzustand", () => { beforeEach(() => { document.body.innerHTML = ""; }); it("rendert Markdown, Rücksprung, Tags und Backlinks", () => { const { view, onLink } = setup(); view.set( JSON.stringify({ kind: "doc", home: "/a", relpath: "konzepte/2026-07-19_1000-x.md", name: "x", title: "X", tags: ["adr"], backlinks: ["anderes-doc"], markdown: "# Überschrift\n\nText mit [[ziel|Label]].\n", }), ); expect(document.querySelector(".wiki-body h1")!.textContent).toBe("Überschrift"); const wiki = document.querySelector(".wiki-body a.wiki")!; expect(wiki.textContent).toBe("Label"); wiki.click(); expect(onLink).toHaveBeenCalledWith("ziel"); document.querySelector(".wiki-back")!.click(); expect(onLink).toHaveBeenCalledWith("tag:"); const back = document.querySelector(".wiki-backlinks a")!; back.click(); expect(onLink).toHaveBeenCalledWith("anderes-doc"); }); it("leerer Puffer bietet den Übersichts-Einstieg", () => { const { view, onLink } = setup(); view.set(""); expect(view.empty()).toBe(true); document.querySelector(".wiki-empty .wiki-chip")!.click(); expect(onLink).toHaveBeenCalledWith("tag:"); view.set(page); expect(view.empty()).toBe(false); }); });