From 04dc8fd2b9718d1624cda61e744950ac575b78d3 Mon Sep 17 00:00:00 2001 From: robbond Date: Thu, 9 Apr 2026 09:58:22 +0100 Subject: [PATCH] 22541 extract simple link-text breadcrumb route map and add structure tests --- components/breadcrumbs.js | 72 ++++++++++--------- memory-bank/change-log.md | 31 ++++++++ .../breadcrumbs-route-map-structure.test.cjs | 71 ++++++++++++++++++ tests/phase22/index.test.cjs | 2 + 4 files changed, 144 insertions(+), 32 deletions(-) create mode 100644 tests/phase22/breadcrumbs-route-map-structure.test.cjs diff --git a/components/breadcrumbs.js b/components/breadcrumbs.js index 9d6ffd51..0e4d513a 100644 --- a/components/breadcrumbs.js +++ b/components/breadcrumbs.js @@ -133,6 +133,39 @@ const Breadcrumbs = (props) => { return simpleRouteRenderersByPath[path] || null; }; + const getSimpleLinkTextPairRenderer = (path) => { + const simpleLinkTextPairRenderersByPath = { + "/addresssearchresults": () => ( + <> + {renderLinkCrumb( + isWelsh + ? router.locale + "/chwiliadcyfeiriadau" + : "/addresssearch", + t("common:breadcrumb-address-search") + )} + {renderTextCrumb( + t("common:breadcrumb-address-search-results") + )} + + ), + "/advancedsearchresults": () => ( + <> + {renderLinkCrumb( + isWelsh + ? router.locale + "/advancedsearch" + : "/advancedsearch", + t("common:breadcrumb-advanced-search") + )} + {renderTextCrumb( + t("common:breadcrumb-advanced-search-results") + )} + + ) + }; + + return simpleLinkTextPairRenderersByPath[path] || null; + }; + const renderMyPortalCrumb = () => (
  • @@ -235,6 +268,13 @@ const Breadcrumbs = (props) => { ? renderSimpleRoute() : null; })()} + {(() => { + const renderSimpleLinkTextPair = + getSimpleLinkTextPairRenderer(pathname); + return renderSimpleLinkTextPair + ? renderSimpleLinkTextPair() + : null; + })()} {isPath("/myportal/searchresults") && ( <> {renderAnchorCrumb( @@ -258,38 +298,6 @@ const Breadcrumbs = (props) => { renderMyPortalSectionCrumbs( t("common:footer-contact-us-link-label") )} - {isPath("/addresssearchresults") && ( - <> - {" "} - {renderLinkCrumb( - isWelsh - ? router.locale + "/chwiliadcyfeiriadau" - : "/addresssearch", - t("common:breadcrumb-address-search") - )} - {renderTextCrumb( - t( - "common:breadcrumb-address-search-results" - ) - )} - - )} - {isPath("/advancedsearchresults") && ( - <> - {" "} - {renderLinkCrumb( - isWelsh - ? router.locale + "/advancedsearch" - : "/advancedsearch", - t("common:breadcrumb-advanced-search") - )} - {renderTextCrumb( - t( - "common:breadcrumb-advanced-search-results" - ) - )} - - )} {isPath("/myportal/advancedsearchresults") && ( <> {renderMyPortalCrumb()} diff --git a/memory-bank/change-log.md b/memory-bank/change-log.md index 90f5a707..be7d909b 100644 --- a/memory-bank/change-log.md +++ b/memory-bank/change-log.md @@ -361,6 +361,37 @@ Follow-ups: - Next slice recommendation: extract a second tiny map for simple "link + text" pair routes (no callbacks, no side effects) to further shrink the conditional chain while keeping callback/dynamic branches explicit. +### CL-22541-M: breadcrumbs simple link+text pair map + focused structure coverage + +date: 2026-04-09 +author: Cline +scope: `components/breadcrumbs.js`, `tests/phase22/{breadcrumbs-route-map-structure,index}.test.cjs` +type: change +rationale: Execute the next bounded slice by extracting simple link+text pair route branches into a tiny renderer map and adding focused regression checks that mapped and dynamic callback branches remain in the intended structure. +impact: Refactor-only structural deduplication/readability improvement plus focused test coverage; no intended route/auth/session/API/EN-CY/a11y behavior change. +status: completed + +Summary: + +- Added `getSimpleLinkTextPairRenderer(path)` in `components/breadcrumbs.js` for simple no-callback "link + text" pair routes. +- Migrated these routes into the new pair map: + - `/addresssearchresults` + - `/advancedsearchresults` +- Kept dynamic/callback-driven branches explicit and untouched (e.g., `/myportal/case/id/[incident]` with `router.back()`). +- Added focused phase22 suite `tests/phase22/breadcrumbs-route-map-structure.test.cjs` asserting: + - mapped simple pair routes exist in the new map + - explicit dynamic callback branch remains present. +- Registered the new suite in `tests/phase22/index.test.cjs`. + +Validation: + +- `npx eslint components/breadcrumbs.js tests/phase22/index.test.cjs tests/phase22/breadcrumbs-route-map-structure.test.cjs` -> pass. +- `node tests/phase22/index.test.cjs` -> pass (combined suite, including new breadcrumbs-route-map tests 2/2). + +Follow-ups: + +- Next slice recommendation: introduce a tiny local `renderMappedRoute(path, resolver)` helper to remove repeated inline IIFE map invocations, then optionally merge simple maps under one top-level resolver while preserving explicit ordering and side-effect-free constraints. + ### CL-00X: 22500 `components/elements/index.js` Phase 1 helper extraction date: 2026-04-07 diff --git a/tests/phase22/breadcrumbs-route-map-structure.test.cjs b/tests/phase22/breadcrumbs-route-map-structure.test.cjs new file mode 100644 index 00000000..c3a6f99c --- /dev/null +++ b/tests/phase22/breadcrumbs-route-map-structure.test.cjs @@ -0,0 +1,71 @@ +const assert = require("assert"); +const fs = require("fs"); +const path = require("path"); + +const tests = []; +const test = (name, fn) => tests.push({ name, fn }); + +const loadBreadcrumbSource = () => { + const filePath = path.join( + __dirname, + "..", + "..", + "components", + "breadcrumbs.js" + ); + return fs.readFileSync(filePath, "utf8"); +}; + +test("breadcrumbs/simple-link-text map includes address and advanced search result routes", async () => { + const source = loadBreadcrumbSource(); + + assert.strictEqual( + source.includes('"/addresssearchresults": () => ('), + true, + "Expected /addresssearchresults to be mapped in getSimpleLinkTextPairRenderer" + ); + + assert.strictEqual( + source.includes('"/advancedsearchresults": () => ('), + true, + "Expected /advancedsearchresults to be mapped in getSimpleLinkTextPairRenderer" + ); +}); + +test("breadcrumbs/dynamic callback branch remains explicit for myportal case incident route", async () => { + const source = loadBreadcrumbSource(); + + assert.strictEqual( + source.includes('isPath("/myportal/case/id/[incident]")'), + true, + "Expected dynamic /myportal/case/id/[incident] breadcrumb branch to remain explicit" + ); + + assert.strictEqual( + source.includes("router.back();"), + true, + "Expected callback-driven router.back() behavior to remain explicit" + ); +}); + +const run = async () => { + let passed = 0; + + for (const currentTest of tests) { + await currentTest.fn(); + passed += 1; + } + + console.log( + `Phase 22 breadcrumbs-route-map tests passed (${passed}/${tests.length}).` + ); +}; + +module.exports = run; + +if (require.main === module) { + run().catch((error) => { + console.error(error); + process.exit(1); + }); +} diff --git a/tests/phase22/index.test.cjs b/tests/phase22/index.test.cjs index a8e2ea0f..b3996055 100644 --- a/tests/phase22/index.test.cjs +++ b/tests/phase22/index.test.cjs @@ -7,6 +7,7 @@ const runAuthRedirectSafetyTests = require("./auth-redirect-safety.test.cjs"); const runI18nRouteParityTests = require("./i18n-route-parity.test.cjs"); const runAzurestorageHelperTests = require("./azurestorage-helper-behaviour.test.cjs"); const runRouteStateHelperTests = require("./route-state-helper.test.cjs"); +const runBreadcrumbsRouteMapStructureTests = require("./breadcrumbs-route-map-structure.test.cjs"); const run = async () => { await runCoreTokenTests(); @@ -18,6 +19,7 @@ const run = async () => { await runI18nRouteParityTests(); await runAzurestorageHelperTests(); await runRouteStateHelperTests(); + await runBreadcrumbsRouteMapStructureTests(); console.log("Phase 22 combined suite passed."); };