test.web/presentation/renderers/schema.renderer.test.ts
test.web/presentation/renderers/schema.renderer.test.ts is a file in Codebase Testing. 320 lines of code and 0 definitions.
import "@banes-lab/web/presentation/records/grammar.record.ts";
import { AUTHOR_GITHUB, AUTHOR_PROFILE, SITE_URL, pagePath, tabLink } from "@banes-lab/web/core/assets/link.assets.ts";
import {
AUTHOR_HANDLE,
COMPANY_CITY,
COMPANY_COUNTRY,
COMPANY_FOUNDED,
COMPANY_NAME,
COMPANY_NUMBER,
COMPANY_OWNER,
COMPANY_POSTAL_CODE,
COMPANY_STREET,
} from "@banes-lab/web/configuration/strings/company.strings.ts";
import { GRAMMAR_PAGE, HOME_PAGE } from "@banes-lab/web/core/ids/page.ids.ts";
import { describe, expect, it } from "vitest";
import {
recordSchemaOf,
schemaOf,
sectionSchemaOf,
sourceSchemaOf,
} from "@banes-lab/web/presentation/renderers/schema.renderer.ts";
import { GRAMMAR_TABS } from "@banes-lab/web/core/generated/grammar.page.generated.ts";
import { instantOf } from "@banes-lab/web/core/factories/schema.factory.ts";
import { loadPage } from "@banes-lab/web/domain/registries/page.registry.ts";
import { sectionHead } from "@banes-lab/web/presentation/renderers/page.renderer.ts";
const GRAMMAR = await loadPage(GRAMMAR_PAGE);
const TITLE = "Grammar — Bane's Lab";
const DESCRIPTION = "The grammar.";
const CRUMBS_FOR_TAB = 3;
const DATES = { modified: "2026-10-07", published: "2026-09-30" };
const typesOf = function typesOf(graph: readonly Readonly<Record<string, unknown>>[]): string[] {
return graph.map((entity) => String(entity["@type"]));
};
describe("sourceSchemaOf", () => {
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: "CC-BY-SA-4.0",
name: "a.ts",
path: "/anatomy/tree/file-a-ts",
repository: "https://code.x.test/a.ts",
tabPath: "/anatomy/tree",
tabTitle: "Site",
title: "Site · a.ts · Bane's Lab",
trail: [
{ label: "Site", path: "/anatomy/tree" },
{ label: "core", path: "/anatomy/tree/folder-core" },
],
};
it("trails the breadcrumb through the tab and every folder above the page", () => {
const page = sourceSchemaOf(subject)["@graph"].at(-1);
const items: unknown = Reflect.get(Object(page?.["breadcrumb"]), "itemListElement");
const names = Array.isArray(items) ? items.map((item: unknown) => Reflect.get(Object(item), "name")) : [];
expect(names).toStrictEqual(["Home", "Site", "core", "a.ts"]);
});
it("names the page's source code with its language, repository, license and tree", () => {
const page = sourceSchemaOf(subject)["@graph"].at(-1);
expect(page?.["@type"]).toBe("WebPage");
expect(page?.["url"]).toBe(SITE_URL + subject.path);
expect(page?.["mainEntity"]).toStrictEqual({
"@type": "SoftwareSourceCode",
codeRepository: subject.repository,
isPartOf: { "@id": SITE_URL + subject.tabPath },
license: subject.license,
name: subject.name,
programmingLanguage: subject.language,
});
});
it("leaves out what a folder or an unlicensed tree does not have", () => {
const page = sourceSchemaOf({ ...subject, language: null, license: null, repository: null })["@graph"].at(-1);
expect(page?.["mainEntity"]).toStrictEqual({
"@type": "SoftwareSourceCode",
isPartOf: { "@id": SITE_URL + subject.tabPath },
name: subject.name,
});
});
});
describe("recordSchemaOf", () => {
const subject = {
aliases: [],
alternates: { json: "/json/records/lexicon/cache", markdown: "/records/lexicon/cache.md" },
code: "CACHE",
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 (CACHE) — Lexicon — Bane's Lab",
};
it("names the record as a defined term in its collection's term set, under a three-crumb trail", () => {
const page = recordSchemaOf(subject)["@graph"].at(-1);
expect(page?.["url"]).toBe(SITE_URL + subject.path);
expect(page?.["mainEntity"]).toStrictEqual({
"@type": "DefinedTerm",
description: subject.summary,
inDefinedTermSet: { "@type": "DefinedTermSet", name: "Lexicon", url: `${SITE_URL}/ontology/lexicon` },
name: "Cache",
termCode: "CACHE",
url: SITE_URL + subject.path,
});
const crumbs = page?.["breadcrumb"];
expect(JSON.stringify(crumbs)).toContain("Lexicon");
});
it("leaves out the code and summary a record does not have", () => {
const page = recordSchemaOf({ ...subject, code: null, summary: null })["@graph"].at(-1);
const entity = page?.["mainEntity"];
expect(JSON.stringify(entity)).not.toContain("termCode");
expect(JSON.stringify(entity)).not.toContain("description");
});
});
const SECTION_SUBJECT = {
alternates: { json: "/json/ontology/lexicon/core", markdown: "/ontology/lexicon/core.md" },
description: "The 2 records of the Core section in Lexicon.",
name: "Core",
parts: [],
path: "/ontology/lexicon/core",
seed: {
intro: null,
kind: null,
name: "Core",
page: "ontology",
part: 1,
parts: 1,
records: 2,
rows: [0, 2] as const,
section: "core",
tab: "lexicon",
tabPath: "/ontology/lexicon",
tabTitle: "Lexicon",
},
title: "Core — Lexicon — Bane's Lab",
};
describe("sectionSchemaOf and sectionHead", () => {
it("names a section page's rows as an item list under its tab, and indexes it under its own path", () => {
const page = sectionSchemaOf(SECTION_SUBJECT)["@graph"].at(-1);
expect(page?.["mainEntity"]).toStrictEqual({ "@type": "ItemList", name: "Core", numberOfItems: 2 });
expect(JSON.stringify(page?.["breadcrumb"])).toContain("Lexicon");
const head = sectionHead(SECTION_SUBJECT);
expect([head.path, head.title, head.robots]).toStrictEqual([SECTION_SUBJECT.path, SECTION_SUBJECT.title, "index, follow"]);
});
});
describe("schemaOf", () => {
it("always carries the organization, the person, the site and the page, linked by id", () => {
const graph = schemaOf({ description: DESCRIPTION, path: pagePath(HOME_PAGE), title: TITLE })["@graph"];
expect(typesOf(graph)).toStrictEqual(["Organization", "Person", "WebSite", "WebPage"]);
const [organization, person, , page] = graph;
expect(organization?.["name"]).toBe(COMPANY_NAME);
expect(organization?.["sameAs"]).toStrictEqual([AUTHOR_GITHUB, AUTHOR_PROFILE]);
expect(organization?.["vatID"]).toBe(COMPANY_COUNTRY + COMPANY_NUMBER.split(".").join(""));
expect(organization?.["foundingDate"]).toBe(COMPANY_FOUNDED);
expect(organization?.["address"]).toStrictEqual({
"@type": "PostalAddress",
addressCountry: COMPANY_COUNTRY,
addressLocality: COMPANY_CITY,
postalCode: COMPANY_POSTAL_CODE,
streetAddress: COMPANY_STREET,
});
expect(organization?.["iso6523Code"]).toBe(`0208:${COMPANY_NUMBER.split(".").join("")}`);
expect(organization?.["numberOfEmployees"]).toStrictEqual({ "@type": "QuantitativeValue", value: 1 });
expect([person?.["name"], person?.["alternateName"]]).toStrictEqual([COMPANY_OWNER, AUTHOR_HANDLE]);
expect(typeof person?.["description"]).toBe("string");
expect(page?.["url"]).toBe(SITE_URL + pagePath(HOME_PAGE));
expect(page?.["breadcrumb"]).toBeUndefined();
});
it("adds a breadcrumb trail and the page's own entities for a registered page and its tab", () => {
const grammar = GRAMMAR;
const [, second] = GRAMMAR_TABS;
if (grammar === undefined || second === undefined) {
throw new Error(GRAMMAR_PAGE);
}
const path = tabLink(GRAMMAR_PAGE, second.id);
const graph = schemaOf({ definition: grammar, description: DESCRIPTION, path, tab: second, title: TITLE })[
"@graph"
];
expect(typesOf(graph)).toContain("CreativeWork");
const page = graph.find((entity) => entity["@type"] === "WebPage");
const trail: unknown = page?.["breadcrumb"];
expect(typeof trail === "object" && trail !== null && "itemListElement" in trail).toBe(true);
const items: unknown = typeof trail === "object" && trail !== null ? Reflect.get(trail, "itemListElement") : [];
expect(Array.isArray(items) ? items.length : 0).toBe(CRUMBS_FOR_TAB);
});
it("lists the tab's sections as parts of the page, each at its own fragment", () => {
const grammar = GRAMMAR;
const [, second] = GRAMMAR_TABS;
if (grammar === undefined || second === undefined) {
throw new Error(GRAMMAR_PAGE);
}
const path = tabLink(GRAMMAR_PAGE, second.id);
const graph = schemaOf({ definition: grammar, description: DESCRIPTION, path, tab: second, title: TITLE })[
"@graph"
];
const parts: unknown = graph.find((entity) => entity["@type"] === "WebPage")?.["hasPart"];
expect(parts).toStrictEqual(
second.sections.map((section) => ({
"@id": `${SITE_URL}${path}#${section.id}`,
"@type": "WebPageElement",
encoding: [
{
"@type": "MediaObject",
contentUrl: `${SITE_URL}/json/${GRAMMAR_PAGE}/${second.id}/${section.id}`,
encodingFormat: "application/json",
},
{
"@type": "MediaObject",
contentUrl: `${SITE_URL}${path}/${section.id}.md`,
encodingFormat: "text/markdown",
},
],
name: section.title,
url: `${SITE_URL}${path}#${section.id}`,
})),
);
});
it("dates the page and names a teaching tab as a dated tech article under its tab and page title", () => {
const grammar = GRAMMAR;
const [, second] = GRAMMAR_TABS;
if (grammar === undefined || second === undefined) {
throw new Error(GRAMMAR_PAGE);
}
const banner = { alt: "a", source: "/static/card.gif", stills: ["/static/wide.png", "/static/square.png"] };
const path = tabLink(GRAMMAR_PAGE, second.id);
const graph = schemaOf({
banner,
dates: DATES,
definition: grammar,
description: DESCRIPTION,
path,
tab: second,
title: TITLE,
})["@graph"];
const page = graph.find((entity) => entity["@type"] === "WebPage");
expect([page?.["datePublished"], page?.["dateModified"]]).toStrictEqual([
instantOf(DATES.published),
instantOf(DATES.modified),
]);
expect(page?.["mainEntity"]).toStrictEqual({
"@type": "TechArticle",
author: { "@id": `${SITE_URL}/#person` },
dateModified: instantOf(DATES.modified),
datePublished: instantOf(DATES.published),
headline: `${second.label} — ${grammar.title}`,
image: [`${SITE_URL}/static/wide.png`, `${SITE_URL}/static/square.png`],
inLanguage: "en",
publisher: { "@id": `${SITE_URL}/#organization` },
});
});
it("names no article on a page that does not declare one or has no banner, and no date it was not given", () => {
const grammar = GRAMMAR;
if (grammar === undefined) {
throw new Error(GRAMMAR_PAGE);
}
const path = pagePath(GRAMMAR_PAGE);
const banner = { alt: "a", source: "/static/card.gif", stills: [] };
const plain = schemaOf({ banner, definition: { ...grammar, article: false }, description: DESCRIPTION, path, title: TITLE });
const bare = schemaOf({ definition: grammar, description: DESCRIPTION, path, title: TITLE });
for (const graph of [plain["@graph"], bare["@graph"]]) {
const page = graph.find((entity) => entity["@type"] === "WebPage");
expect([page?.["mainEntity"], page?.["datePublished"], page?.["dateModified"]]).toStrictEqual([
undefined,
undefined,
undefined,
]);
}
});
it("names a profile page as a ProfilePage whose main entity is the site's person", () => {
const grammar = GRAMMAR;
if (grammar === undefined) {
throw new Error(GRAMMAR_PAGE);
}
const definition = { ...grammar, article: false, profile: true };
const graph = schemaOf({ definition, description: DESCRIPTION, path: pagePath(GRAMMAR_PAGE), title: TITLE })[
"@graph"
];
const page = graph.find((entity) => entity["url"] === SITE_URL + pagePath(GRAMMAR_PAGE));
expect([page?.["@type"], page?.["mainEntity"]]).toStrictEqual(["ProfilePage", { "@id": `${SITE_URL}/#person` }]);
const person = graph.find((entity) => entity["@type"] === "Person");
expect(person?.["url"]).toBe(`${SITE_URL}/about`);
});
it("dates a page's dataset with the page's modified day, and leaves its other entities as they are", () => {
const grammar = GRAMMAR;
if (grammar === undefined) {
throw new Error(GRAMMAR_PAGE);
}
const definition = { ...grammar, entities: [{ "@type": "Dataset", name: "d" }, { "@type": "CreativeWork" }] };
const path = pagePath(GRAMMAR_PAGE);
const graph = schemaOf({ dates: DATES, definition, description: DESCRIPTION, path, title: TITLE })["@graph"];
expect(graph.slice(-2)).toStrictEqual([
{ "@type": "Dataset", dateModified: instantOf(DATES.modified), name: "d" },
{ "@type": "CreativeWork" },
]);
const undated = schemaOf({ definition, description: DESCRIPTION, path, title: TITLE })["@graph"];
expect(undated.at(-2)).toStrictEqual({ "@type": "Dataset", name: "d" });
});
it("names the page's JSON payload, its Markdown version and its catalog index", () => {
const grammar = GRAMMAR;
if (grammar === undefined) {
throw new Error(GRAMMAR_PAGE);
}
const path = pagePath(GRAMMAR_PAGE);
const graph = schemaOf({ definition: grammar, description: DESCRIPTION, path, title: TITLE })["@graph"];
const encoding: unknown = graph.find((entity) => entity["@type"] === "WebPage")?.["encoding"];
const urls: unknown[] = Array.isArray(encoding)
? encoding.map((item: unknown) =>
typeof item === "object" && item !== null && "contentUrl" in item ? item.contentUrl : undefined,
)
: [];
expect(urls).toStrictEqual([
`${SITE_URL}/json/${GRAMMAR_PAGE}`,
`${SITE_URL}${path}.md`,
`${SITE_URL}/json/api/pages/${GRAMMAR_PAGE}`,
]);
});
});