test.content/core/renderers/wiki.renderer.test.ts
test.content/core/renderers/wiki.renderer.test.ts is a file in Codebase Testing. 158 lines of code and 0 definitions.
import { ANATOMY_PAGE, FAQ_PAGE, METHODOLOGY_PAGE } from "@banes-lab/web/core/ids/page.ids.ts";
import type { Attribution, ChapterSource, PageSources, ShapeInput } from "@banes-lab/content/types/chapter.types.ts";
import { METHODOLOGY_REPOSITORY, SITE_URL, tabLink } from "@banes-lab/web/core/assets/link.assets.ts";
import { READING_TAB, TREE_TAB } from "@banes-lab/web/core/ids/anatomy.ids.ts";
import { describe, expect, it } from "vitest";
import { isSiteOnly, pageStemOf, renderWiki, wikiResolver } from "@banes-lab/content/core/renderers/wiki.renderer.ts";
import { attributionLine } from "@banes-lab/content/core/renderers/markdown.renderer.ts";
const ATTRIBUTION: Attribution = {
author: "Author",
copyright: "© 2025 ",
coveredBy: "Documentation is covered by ",
licenseName: "CC BY-SA 4.0",
licenseUrl: "https://creativecommons.org/licenses/by-sa/4.0/",
work: " - Work",
};
const INTRODUCTION: ChapterSource = {
first: true,
label: "Introduction",
markdown:
"# Page\n\nIntro alternate, see [the model](/disciplined-methodology/mental-model#loop), [the faq](/faq) and [a term](/ontology#architecture-x).\n",
tab: "introduction",
};
const MODEL: ChapterSource = {
first: false,
label: "Mental Model",
markdown: "# Mental model\n\nFirst alternate, back to [home](/disciplined-methodology#top).\n",
tab: "mental-model",
};
const OBSERVATION: ChapterSource = {
first: false,
label: "Observation",
markdown: "# Observation\n\nSecond alternate.\n",
tab: "observation",
};
const SOURCES: ChapterSource[] = [INTRODUCTION, MODEL, OBSERVATION];
const FAQ: ChapterSource[] = [{ first: true, label: "FAQ", markdown: "# FAQ\n\nQuestions.\n", tab: FAQ_PAGE }];
const SINGLE: ShapeInput = { pages: [{ label: "Method", page: METHODOLOGY_PAGE, sources: SOURCES }], readme: null };
const MANY: ShapeInput = {
pages: [
{ label: "Method", page: METHODOLOGY_PAGE, sources: SOURCES },
{ label: "FAQ", page: FAQ_PAGE, sources: FAQ },
],
readme: null,
};
describe("pageStemOf", () => {
it("numbers a page in reading order and joins the label's words with hyphens, prefixed by its group when the group adds a word", () => {
expect(pageStemOf(MODEL, 1)).toBe("01-Mental-Model");
expect(pageStemOf(OBSERVATION, 12)).toBe("12-Observation");
expect(pageStemOf(OBSERVATION, 3, "Method")).toBe("03-Method.Observation");
expect(pageStemOf(FAQ[0] ?? MODEL, 4, "FAQ")).toBe("04-FAQ");
});
});
describe("wikiResolver", () => {
it("maps a rendered route to its stem, the front page's own route to Home when it holds no numbered page, and the rest to nothing", () => {
const pages = [
{ group: "Method", hosted: true, href: "01-Mental-Model", page: METHODOLOGY_PAGE, source: MODEL },
];
const resolve = wikiResolver(pages, METHODOLOGY_PAGE);
expect(resolve(METHODOLOGY_PAGE, "mental-model")).toBe("01-Mental-Model");
expect(resolve(METHODOLOGY_PAGE, null)).toBe("Home");
expect(resolve(FAQ_PAGE, null)).toBeNull();
});
});
describe("renderWiki over one page", () => {
const pages = renderWiki(SINGLE, ATTRIBUTION);
const files = pages.map((page) => page.file);
it("writes Home, one numbered page per tab, the sidebar and the footer", () => {
expect(files).toStrictEqual([
"Home.md",
"01-Mental-Model.md",
"02-Observation.md",
"_Sidebar.md",
"_Footer.md",
]);
});
it("opens Home with the page alternate and closes it with the reading path", () => {
const home = pages[0]?.body ?? "";
expect(home.startsWith("# Page")).toBe(true);
expect(home).toContain("- [Mental Model](01-Mental-Model)\n- [Observation](02-Observation)");
});
it("rewrites a root-relative link to the wiki page that holds it, Home included, or to the site", () => {
expect(pages[0]?.body).toContain("[the model](01-Mental-Model#loop)");
expect(pages[0]?.body).toContain("[the faq](https://banes-lab.com/faq)");
expect(pages[0]?.body).toContain("[a term](https://banes-lab.com/ontology#architecture-x)");
expect(pages[1]?.body).toContain("[home](Home#top)");
});
it("links each page to its neighbors, Home standing in before the first", () => {
expect(pages[1]?.body).toContain("[Home](Home) · [Observation](02-Observation)");
expect(pages[2]?.body.trimEnd().endsWith("[Mental Model](01-Mental-Model)")).toBe(true);
});
it("lists Home, the reading path and the repository links in the sidebar", () => {
const sidebar = pages[3]?.body ?? "";
expect(sidebar).toContain("[Home](Home)");
expect(sidebar).toContain("- [Mental Model](01-Mental-Model)");
expect(sidebar).toContain(`[Repository](${METHODOLOGY_REPOSITORY})`);
expect(sidebar).toContain(`[Discussions](${METHODOLOGY_REPOSITORY}/discussions)`);
});
it("carries the attribution line as the footer", () => {
expect(pages[4]?.body.trimEnd()).toBe(attributionLine(ATTRIBUTION));
});
});
describe("renderWiki over every teaching page", () => {
const pages = renderWiki(MANY, ATTRIBUTION);
it("numbers every tab of every page in order, first tabs included, prefixed by the page, and groups the reading path", () => {
expect(pages.map((page) => page.file)).toStrictEqual([
"Home.md",
"01-Method.Introduction.md",
"02-Method.Mental-Model.md",
"03-Method.Observation.md",
"04-FAQ.md",
"_Sidebar.md",
"_Footer.md",
]);
expect(pages[0]?.body).toContain("**Method**\n- [Introduction](01-Method.Introduction)");
expect(pages[0]?.body).toContain("**FAQ**\n- [FAQ](04-FAQ)");
expect(pages[0]?.body.startsWith("# Page")).toBe(true);
});
it("resolves a link to another teaching page to its numbered wiki page", () => {
expect(pages[0]?.body).toContain("[the faq](04-FAQ)");
expect(pages[2]?.body).toContain("[home](01-Method.Introduction#top)");
});
});
describe("renderWiki over a page with a site-only tab", () => {
const anatomy: PageSources = {
label: "Anatomy",
page: ANATOMY_PAGE,
sources: [
{
first: true,
label: "Reading",
markdown: "# Reading\n\nSee [the tree](/anatomy/tree#file-x).\n",
tab: READING_TAB,
},
{ first: false, label: "Source tree", markdown: "# Tree\n", tab: TREE_TAB },
],
};
const pages = renderWiki(
{ pages: [{ label: "Method", page: METHODOLOGY_PAGE, sources: SOURCES }, anatomy], readme: null },
ATTRIBUTION,
);
it("keeps the derived tab off the wiki, lists it as a site link in the reading path and resolves links to it there", () => {
expect(isSiteOnly(ANATOMY_PAGE, TREE_TAB)).toBe(true);
expect(isSiteOnly(ANATOMY_PAGE, READING_TAB)).toBe(false);
expect(pages.map((page) => page.file)).toStrictEqual([
"Home.md",
"01-Method.Introduction.md",
"02-Method.Mental-Model.md",
"03-Method.Observation.md",
"04-Anatomy.Reading.md",
"_Sidebar.md",
"_Footer.md",
]);
const tree = `${SITE_URL}${tabLink(ANATOMY_PAGE, TREE_TAB)}`;
expect(pages[0]?.body).toContain(`**Anatomy**\n- [Reading](04-Anatomy.Reading)\n- [Source tree](${tree})`);
expect(pages[4]?.body).toContain(`[the tree](${tree}#file-x)`);
expect(pages[4]?.body.trimEnd().endsWith("[Observation](03-Method.Observation)")).toBe(true);
});
});