Refactor breadcrumbs to use factory-based route renderers

This commit is contained in:
2026-04-09 12:08:36 +01:00
parent 5f6dde782a
commit 062cd23463
7 changed files with 813 additions and 382 deletions
@@ -1,49 +1,156 @@
const assert = require("assert");
const {
buildBreadcrumbRendererMaps,
getMappedRendererByPath,
resolveMappedRouteRenderer
} = require("../../lib/routing/breadcrumbRouteMaps");
const fs = require("fs");
const path = require("path");
const vm = require("vm");
const tests = [];
const test = (name, fn) => tests.push({ name, fn });
test("breadcrumbRouteMaps/buildBreadcrumbRendererMaps preserves explicit map order", async () => {
const mapA = { "/a": () => "A" };
const mapB = { "/b": () => "B" };
const mapC = { "/c": () => "C" };
const helperModulePath = path.join(
__dirname,
"..",
"..",
"lib",
"routing",
"breadcrumbRouteMaps.js"
);
const result = buildBreadcrumbRendererMaps({
simpleRouteRenderersByPath: mapA,
simpleLinkTextPairRenderersByPath: mapB,
simpleMyPortalRouteRenderersByPath: mapC
const loadHelpers = () => {
const source = fs.readFileSync(helperModulePath, "utf8");
const transformedSource = `
${source
.replace(/export const /g, "const ")
.replace(/export function /g, "function ")}
module.exports = {
buildBreadcrumbRendererMaps,
resolveMappedRouteRenderer
};
`;
const sandbox = {
module: { exports: {} },
exports: {},
require,
__dirname: path.dirname(helperModulePath),
__filename: helperModulePath,
console
};
vm.runInNewContext(transformedSource, sandbox, {
filename: helperModulePath
});
assert.strictEqual(result[0], mapA);
assert.strictEqual(result[1], mapB);
assert.strictEqual(result[2], mapC);
return sandbox.module.exports;
};
test("buildBreadcrumbRendererMaps returns grouped maps in explicit precedence order", () => {
const { buildBreadcrumbRendererMaps } = loadHelpers();
const simpleRouteRenderersByPath = {
"/alpha": () => "alpha"
};
const simpleLinkTextPairRenderersByPath = {
"/beta": () => "beta"
};
const simpleMyPortalRouteRenderersByPath = {
"/gamma": () => "gamma"
};
const result = buildBreadcrumbRendererMaps({
simpleRouteRenderersByPath,
simpleLinkTextPairRenderersByPath,
simpleMyPortalRouteRenderersByPath
});
assert.ok(Array.isArray(result), "Expected grouped maps array");
assert.strictEqual(result.length, 3, "Expected three grouped route maps");
assert.strictEqual(
result[0],
simpleRouteRenderersByPath,
"Expected simple route renderers first"
);
assert.strictEqual(
result[1],
simpleLinkTextPairRenderersByPath,
"Expected simple link-text pair renderers second"
);
assert.strictEqual(
result[2],
simpleMyPortalRouteRenderersByPath,
"Expected my-portal route renderers third"
);
});
test("breadcrumbRouteMaps/getMappedRendererByPath returns mapped renderer or null", async () => {
const renderer = () => "ok";
const map = { "/x": renderer };
test("resolveMappedRouteRenderer returns renderer from first matching grouped map", () => {
const { buildBreadcrumbRendererMaps, resolveMappedRouteRenderer } =
loadHelpers();
assert.strictEqual(getMappedRendererByPath("/x", map), renderer);
assert.strictEqual(getMappedRendererByPath("/missing", map), null);
});
test("breadcrumbRouteMaps/resolveMappedRouteRenderer honors map precedence", async () => {
const firstRenderer = () => "first";
const secondRenderer = () => "second";
const result = resolveMappedRouteRenderer("/same", [
{ "/same": firstRenderer },
{ "/same": secondRenderer }
]);
const maps = buildBreadcrumbRendererMaps({
simpleRouteRenderersByPath: {
"/known": firstRenderer
},
simpleLinkTextPairRenderersByPath: {
"/known": secondRenderer
},
simpleMyPortalRouteRenderersByPath: {}
});
assert.strictEqual(result, firstRenderer);
assert.strictEqual(resolveMappedRouteRenderer("/none", []), null);
const result = resolveMappedRouteRenderer("/known", maps);
assert.strictEqual(
result,
firstRenderer,
"Expected resolver to use first matching map by precedence order"
);
});
test("resolveMappedRouteRenderer returns renderer from later grouped map when earlier maps do not match", () => {
const { buildBreadcrumbRendererMaps, resolveMappedRouteRenderer } =
loadHelpers();
const myPortalRenderer = () => "myportal";
const maps = buildBreadcrumbRendererMaps({
simpleRouteRenderersByPath: {},
simpleLinkTextPairRenderersByPath: {},
simpleMyPortalRouteRenderersByPath: {
"/myportal/searchresults": myPortalRenderer
}
});
const result = resolveMappedRouteRenderer("/myportal/searchresults", maps);
assert.strictEqual(
result,
myPortalRenderer,
"Expected resolver to return matching renderer from later grouped map"
);
});
test("resolveMappedRouteRenderer returns null for unmapped path", () => {
const { buildBreadcrumbRendererMaps, resolveMappedRouteRenderer } =
loadHelpers();
const maps = buildBreadcrumbRendererMaps({
simpleRouteRenderersByPath: {
"/known": () => "known"
},
simpleLinkTextPairRenderersByPath: {},
simpleMyPortalRouteRenderersByPath: {}
});
const result = resolveMappedRouteRenderer("/unknown", maps);
assert.strictEqual(
result,
null,
"Expected null when no grouped map contains the path"
);
});
const run = async () => {