test.web/presentation/renderers/page.renderer.test.ts
test.web/presentation/renderers/page.renderer.test.ts is a file in Codebase Testing. 267 lines of code and 0 definitions.
import "@banes-lab/web/presentation/records/home.record.ts";
import "@banes-lab/web/presentation/records/grammar.record.ts";
import { GRAMMAR_PAGE, HOME_PAGE } from "@banes-lab/web/core/ids/page.ids.ts";
import {
HOME_PATH,
SITE_URL,
markdownTwinPath,
pagePath,
payloadTwinPath,
tabLink,
} from "@banes-lab/web/core/assets/link.assets.ts";
import { MISSING_PAGE_TITLE, SITE_NAME } from "@banes-lab/web/configuration/strings/page.strings.ts";
import { ROBOTS_INDEX, ROBOTS_NOINDEX } from "@banes-lab/web/configuration/constants/document.constants.ts";
import {
applyHead,
headOf,
holdsHead,
recordHead,
secondaryTab,
sourceHead,
tabHead,
} from "@banes-lab/web/presentation/renderers/page.renderer.ts";
import { describe, expect, it } from "vitest";
import { loadPage, loadedPage } from "@banes-lab/web/domain/registries/page.registry.ts";
import { GRAMMAR_TABS } from "@banes-lab/web/core/generated/grammar.page.generated.ts";
import { MISSING_SHARE } from "@banes-lab/web/configuration/strings/report.strings.ts";
import { SHARE_IMAGES } from "@banes-lab/web/core/generated/share.generated.ts";
await loadPage(HOME_PAGE);
await loadPage(GRAMMAR_PAGE);
const getPage = loadedPage;
const UNKNOWN = "no-such-page";
const DESCRIPTION_SLOT = 'meta[name="description"]';
const OG_URL_SLOT = 'meta[property="og:url"]';
const OG_TYPE_SLOT = 'meta[property="og:type"]';
const OG_IMAGE_SLOT = 'meta[property="og:image"]';
const OG_IMAGE_ALT_SLOT = 'meta[property="og:image:alt"]';
const OG_VIDEO_SLOT = 'meta[property="og:video"]';
const TWITTER_IMAGE_SLOT = 'meta[name="twitter:image"]';
const ROBOTS_SLOT = 'meta[name="robots"]';
const CANONICAL_SLOT = 'link[rel="canonical"]';
const MARKDOWN_ALTERNATE_SLOT = 'link[rel="alternate"][type="text/markdown"]';
const JSON_ALTERNATE_SLOT = 'link[rel="alternate"][type="application/json"]';
const SCHEMA_SLOT = 'script[type="application/ld+json"]';
const headDocument = function headDocument(): Document {
const root = document.implementation.createHTMLDocument();
const description = root.createElement("meta");
description.setAttribute("name", "description");
const openGraphUrl = root.createElement("meta");
openGraphUrl.setAttribute("property", "og:url");
const openGraphType = root.createElement("meta");
openGraphType.setAttribute("property", "og:type");
const openGraphImage = root.createElement("meta");
openGraphImage.setAttribute("property", "og:image");
const openGraphImageAlt = root.createElement("meta");
openGraphImageAlt.setAttribute("property", "og:image:alt");
const twitterImage = root.createElement("meta");
twitterImage.setAttribute("name", "twitter:image");
const robots = root.createElement("meta");
robots.setAttribute("name", "robots");
const canonical = root.createElement("link");
canonical.setAttribute("rel", "canonical");
const markdownTwin = root.createElement("link");
markdownTwin.setAttribute("rel", "alternate");
markdownTwin.setAttribute("type", "text/markdown");
const jsonTwin = root.createElement("link");
jsonTwin.setAttribute("rel", "alternate");
jsonTwin.setAttribute("type", "application/json");
const schema = root.createElement("script");
schema.setAttribute("type", "application/ld+json");
root.head.append(
description,
openGraphUrl,
openGraphType,
openGraphImage,
openGraphImageAlt,
twitterImage,
robots,
canonical,
markdownTwin,
jsonTwin,
schema,
);
return root;
};
describe("headOf", () => {
it("titles a registered page with the site name and carries its description", () => {
const home = getPage(HOME_PAGE);
const head = headOf(HOME_PAGE, home);
expect(head.title).toContain(SITE_NAME);
expect(head.description).toBe(home?.description);
expect(head.path).toBe(HOME_PATH);
});
it("falls back to the missing-page title for an unregistered page and keeps it out of the index", () => {
expect(headOf(UNKNOWN).title.startsWith(MISSING_PAGE_TITLE)).toBe(true);
expect(headOf(UNKNOWN).robots).toBe(ROBOTS_NOINDEX);
expect(headOf(HOME_PAGE, getPage(HOME_PAGE)).robots).toBe(ROBOTS_INDEX);
});
it("describes a secondary tab by its own path, label and opening text", () => {
const grammar = getPage(GRAMMAR_PAGE);
const [first, second] = GRAMMAR_TABS;
const head = headOf(GRAMMAR_PAGE, grammar, tabLink(GRAMMAR_PAGE, second?.id ?? ""));
expect(head.path).toBe(tabLink(GRAMMAR_PAGE, second?.id ?? ""));
expect(head.title.startsWith(second?.label ?? "")).toBe(true);
expect(head.description.length).toBeGreaterThan(0);
expect(headOf(GRAMMAR_PAGE, grammar, tabLink(GRAMMAR_PAGE, first?.id ?? "")).path).toBe(pagePath(GRAMMAR_PAGE));
});
it("dates the web page of a page and of a tab with the dates it was given", () => {
const grammar = getPage(GRAMMAR_PAGE);
const [, second] = GRAMMAR_TABS;
const dates = { modified: "2026-10-07", published: "2026-09-30" };
for (const path of [pagePath(GRAMMAR_PAGE), tabLink(GRAMMAR_PAGE, second?.id ?? "")]) {
const page = headOf(GRAMMAR_PAGE, grammar, path, dates).schema["@graph"].find(
(entity) => entity["@type"] === "WebPage",
);
expect([page?.["datePublished"], page?.["dateModified"]]).toStrictEqual([
"2026-09-30T00:00:00+00:00",
"2026-10-07T00:00:00+00:00",
]);
}
});
});
describe("holdsHead", () => {
it("holds a head whose canonical names the path, and not a head for another path or with no canonical", () => {
const root = headDocument();
applyHead(root, headOf(GRAMMAR_PAGE, getPage(GRAMMAR_PAGE)));
expect(holdsHead(root, pagePath(GRAMMAR_PAGE))).toBe(true);
expect(holdsHead(root, HOME_PATH)).toBe(false);
expect(holdsHead(document.implementation.createHTMLDocument(), HOME_PATH)).toBe(false);
});
});
describe("secondaryTab", () => {
it("names every tab but the first, and nothing for a document page", () => {
const grammar = getPage(GRAMMAR_PAGE);
const home = getPage(HOME_PAGE);
const [first, second] = GRAMMAR_TABS;
expect(grammar === undefined ? null : secondaryTab(grammar, tabLink(GRAMMAR_PAGE, second?.id ?? ""))?.id).toBe(
second?.id,
);
expect(
grammar === undefined ? null : secondaryTab(grammar, tabLink(GRAMMAR_PAGE, first?.id ?? "")),
).toBeUndefined();
expect(home === undefined ? null : secondaryTab(home, tabLink(HOME_PAGE, "anything"))).toBeUndefined();
});
});
describe("tabHead", () => {
it("joins the tab label, the page title and the site name", () => {
const grammar = getPage(GRAMMAR_PAGE);
const [, second] = GRAMMAR_TABS;
if (grammar === undefined || second === undefined) {
throw new Error(GRAMMAR_PAGE);
}
expect(tabHead(grammar, second).title).toBe(`${second.label} — ${grammar.title} — ${SITE_NAME}`);
});
});
describe("sourceHead", () => {
it("indexes a source page under its own path and points its alternates at the catalog leaf", () => {
const subject = {
alternates: { json: "/json/source/tree/a.ts", markdown: "/source/tree/a.ts.md" },
description: "a.ts is a file in Site.",
language: "typescript",
license: null,
name: "a.ts",
path: "/anatomy/tree/file-a-ts",
repository: null,
tabPath: "/anatomy/tree",
tabTitle: "Site",
title: "Site — a.ts — Bane's Lab",
trail: [{ label: "Site", path: "/anatomy/tree" }],
};
const head = sourceHead(subject);
expect([head.path, head.title, head.description]).toStrictEqual([
subject.path,
subject.title,
subject.description,
]);
const root = headDocument();
applyHead(root, head);
const markdown = root.querySelector('link[rel="alternate"][type="text/markdown"]')?.getAttribute("href");
expect(markdown?.endsWith(subject.alternates.markdown)).toBe(true);
});
});
describe("recordHead", () => {
it("indexes a record page under its own path with the ontology banner and its record leaf as alternates", () => {
const subject = {
aliases: [],
alternates: { json: "/json/records/lexicon/cache", markdown: "/records/lexicon/cache.md" },
code: null,
collection: { label: "Lexicon", path: "/ontology/lexicon" },
description: "A store that answers again without the work.",
facts: [],
kind: "term",
layer: null,
name: "Cache",
path: "/records/lexicon/cache",
placement: null,
relations: [],
section: null,
summary: "A store that answers again without the work.",
title: "Cache — Lexicon — Bane's Lab",
};
const head = recordHead(subject);
expect([head.path, head.title, head.robots]).toStrictEqual([subject.path, subject.title, ROBOTS_INDEX]);
const root = headDocument();
applyHead(root, head);
const json = root.querySelector('link[rel="alternate"][type="application/json"]')?.getAttribute("href");
expect(json?.endsWith(subject.alternates.json)).toBe(true);
});
});
describe("applyHead", () => {
it("writes the title, description, canonical, open graph url and type into the document head", () => {
const root = headDocument();
const head = headOf(HOME_PAGE, getPage(HOME_PAGE));
applyHead(root, head);
expect(root.title).toBe(head.title);
expect(root.querySelector(DESCRIPTION_SLOT)?.getAttribute("content")).toBe(head.description);
expect(root.querySelector(OG_URL_SLOT)?.getAttribute("content")).toBe(SITE_URL + HOME_PATH);
expect(root.querySelector(OG_TYPE_SLOT)?.getAttribute("content")).toBe("website");
expect(root.querySelector(ROBOTS_SLOT)?.getAttribute("content")).toBe(ROBOTS_INDEX);
expect(root.querySelector(CANONICAL_SLOT)?.getAttribute("href")).toBe(SITE_URL + HOME_PATH);
expect(JSON.parse(root.querySelector(SCHEMA_SLOT)?.textContent ?? "")).toStrictEqual(head.schema);
applyHead(root, headOf(GRAMMAR_PAGE, getPage(GRAMMAR_PAGE)));
expect(root.querySelector(OG_TYPE_SLOT)?.getAttribute("content")).toBe("article");
});
it("serves each page the share image its card renders, and the home card for an unknown page", () => {
const home = SHARE_IMAGES.get(HOME_PAGE);
const grammarShare = SHARE_IMAGES.get(GRAMMAR_PAGE);
const grammar = getPage(GRAMMAR_PAGE);
const [, second] = GRAMMAR_TABS;
if (home === undefined || grammarShare === undefined || grammar === undefined || second === undefined) {
throw new Error(GRAMMAR_PAGE);
}
const root = headDocument();
applyHead(root, headOf(HOME_PAGE, getPage(HOME_PAGE)));
expect(root.querySelector(OG_IMAGE_SLOT)?.getAttribute("content")).toBe(SITE_URL + home.source);
expect(root.querySelector(TWITTER_IMAGE_SLOT)?.getAttribute("content")).toBe(SITE_URL + home.source);
expect(root.querySelector(OG_IMAGE_ALT_SLOT)?.getAttribute("content")).toBe(home.alt);
applyHead(root, headOf(GRAMMAR_PAGE, grammar));
expect(root.querySelector(OG_IMAGE_SLOT)?.getAttribute("content")).toBe(SITE_URL + grammarShare.source);
expect(tabHead(grammar, second).banner).toStrictEqual(grammarShare);
expect(headOf(UNKNOWN).banner).toStrictEqual(home);
});
it("refuses loudly a page the share map holds no image for", () => {
const home = getPage(HOME_PAGE);
if (home === undefined) {
throw new Error(HOME_PAGE);
}
expect(() => headOf(UNKNOWN, { ...home, id: UNKNOWN })).toThrow(MISSING_SHARE + UNKNOWN);
});
it("points the alternate links at the route's Markdown alternate and JSON payload, and drops them for an unindexed page", () => {
const root = headDocument();
const tab = tabLink(GRAMMAR_PAGE, GRAMMAR_TABS[1]?.id ?? "");
applyHead(root, headOf(GRAMMAR_PAGE, getPage(GRAMMAR_PAGE), tab));
expect(root.querySelector(MARKDOWN_ALTERNATE_SLOT)?.getAttribute("href")).toBe(
SITE_URL + markdownTwinPath(tab),
);
expect(root.querySelector(JSON_ALTERNATE_SLOT)?.getAttribute("href")).toBe(SITE_URL + payloadTwinPath(tab));
applyHead(root, headOf(UNKNOWN));
expect(root.querySelector(MARKDOWN_ALTERNATE_SLOT)?.hasAttribute("href")).toBe(false);
expect(root.querySelector(JSON_ALTERNATE_SLOT)?.hasAttribute("href")).toBe(false);
});
it("declares no video, so a platform shows the animated image rather than a player", () => {
const root = headDocument();
applyHead(root, headOf(HOME_PAGE, getPage(HOME_PAGE)));
expect(root.querySelector(OG_VIDEO_SLOT)).toBeNull();
expect(root.querySelector(OG_IMAGE_SLOT)?.getAttribute("content")?.endsWith(".gif")).toBe(true);
});
});