test.web/presentation/renderers/glossary.renderer.test.ts
test.web/presentation/renderers/glossary.renderer.test.ts is a file in Codebase Testing. 82 lines of code and 0 definitions.
import { ARCH_ANCHOR, LAYER_ANCHOR } from "@banes-lab/web/core/ids/ontology.ids.ts";
import { describe, expect, it } from "vitest";
import {
lettersOf,
renderGlossaryTab,
renderLetterJumps,
sortedEntries,
} from "@banes-lab/web/presentation/renderers/glossary.renderer.ts";
import { ARCHITECTURE_TABS } from "@banes-lab/web/core/generated/architecture.page.generated.ts";
import { GLOSSARY_ENTRIES } from "@banes-lab/web/configuration/strings/glossary.strings.ts";
import { GLOSSARY_LETTER_PREFIX } from "@banes-lab/web/configuration/constants/glossary.constants.ts";
import { GLOSSARY_TAB } from "@banes-lab/web/core/ids/architecture.ids.ts";
import type { GlossaryEntry } from "@banes-lab/web/types/block.types.ts";
import { ONTOLOGY_PAGE } from "@banes-lab/web/core/ids/page.ids.ts";
import type { Tab } from "@banes-lab/web/types/document.types.ts";
import { pagePath } from "@banes-lab/web/core/assets/link.assets.ts";
const FIXTURE: readonly GlossaryEntry[] = [
{ description: "Second.", term: "Beta" },
{ code: "AL", description: "First.", domains: ["One", "Two"], term: "Alpha" },
{ description: "Third.", term: "Bravo" },
];
const glossaryTab = function glossaryTab(): Tab {
const tab = ARCHITECTURE_TABS.find((candidate) => candidate.id === GLOSSARY_TAB);
if (tab === undefined) {
throw new Error("the architecture page declares no glossary tab");
}
return tab;
};
describe("sortedEntries and lettersOf", () => {
it("sorts by term and lists each leading letter once", () => {
expect(sortedEntries(FIXTURE).map((entry) => entry.term)).toStrictEqual(["Alpha", "Beta", "Bravo"]);
expect(lettersOf(FIXTURE)).toStrictEqual(["A", "B"]);
});
it("holds every glossary term unique", () => {
const terms = GLOSSARY_ENTRIES.map((entry) => entry.term);
expect(new Set(terms).size).toBe(terms.length);
});
it("joins every entry to the ontology: a record for its term, or the layer it is placed on", () => {
const ontology = pagePath(ONTOLOGY_PAGE);
for (const entry of GLOSSARY_ENTRIES) {
expect(entry.href, entry.term).toBeDefined();
expect(entry.href?.startsWith(ontology), entry.term).toBe(true);
expect(entry.domains?.length ?? 0, entry.term).toBeGreaterThan(0);
}
});
it("derives the kind of a joined entry from its record and keeps the page's own placement over the record's layer", () => {
const joined = GLOSSARY_ENTRIES.filter((entry) => entry.href?.includes(ARCH_ANCHOR) === true);
expect(joined.length).toBeGreaterThan(0);
for (const entry of joined) {
expect(entry.domains?.length, entry.term).toBe(2);
}
expect(GLOSSARY_ENTRIES.find((entry) => entry.term === "Encapsulation")?.domains).toStrictEqual([
"principle",
"Structural Core",
]);
expect(GLOSSARY_ENTRIES.find((entry) => entry.term === "YAGNI")?.domains).toStrictEqual([
"principle",
"Evolution Principles",
]);
expect(GLOSSARY_ENTRIES.find((entry) => entry.term === "Single Owner")?.href).toContain(LAYER_ANCHOR);
});
});
describe("renderGlossaryTab", () => {
const article = renderGlossaryTab(glossaryTab());
it("renders the map section in the chapter shape before the letter groups, and one jump per letter for the footer", () => {
const sections = [...article.querySelectorAll("section")];
const map = sections.findIndex((section) => section.classList.contains("chapter-section-paired"));
const glossary = sections.findIndex((section) => section.classList.contains("glossary-section"));
expect(map).toBeGreaterThan(-1);
expect(glossary).toBeGreaterThan(map);
expect(sections[map]?.querySelectorAll(".chapter-panel").length).toBeGreaterThan(0);
expect(article.querySelector(".glossary-diagrams")).toBeNull();
expect(article.querySelectorAll(".glossary-group")).toHaveLength(lettersOf(GLOSSARY_ENTRIES).length);
expect(renderLetterJumps(glossaryTab())).toHaveLength(lettersOf(GLOSSARY_ENTRIES).length);
});
it("renders one term per entry with its code and domains, under an addressable letter", () => {
expect(article.querySelectorAll(".glossary-term")).toHaveLength(GLOSSARY_ENTRIES.length);
expect(article.querySelector(`#${GLOSSARY_LETTER_PREFIX}A`)).not.toBeNull();
expect(article.querySelectorAll(".glossary-code").length).toBeGreaterThan(0);
expect(article.querySelectorAll(".glossary-domains")).toHaveLength(GLOSSARY_ENTRIES.length);
});
});