22541 harden breadcrumb mapped route resolver against invalid entries
This commit is contained in:
@@ -1,5 +1,11 @@
|
|||||||
const getMappedRendererByPath = (path, routeRendererMap) =>
|
const getMappedRendererByPath = (path, routeRendererMap) => {
|
||||||
routeRendererMap[path] || null;
|
if (!routeRendererMap || typeof routeRendererMap !== "object") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const routeRenderer = routeRendererMap[path];
|
||||||
|
return typeof routeRenderer === "function" ? routeRenderer : null;
|
||||||
|
};
|
||||||
|
|
||||||
const resolveMappedRouteRenderer = (path, routeRendererMaps = []) => {
|
const resolveMappedRouteRenderer = (path, routeRendererMaps = []) => {
|
||||||
for (const routeRendererMap of routeRendererMaps) {
|
for (const routeRendererMap of routeRendererMaps) {
|
||||||
|
|||||||
@@ -638,6 +638,36 @@ Follow-ups:
|
|||||||
- Next larger slice candidate: evaluate extraction viability for `/case` branch only if callback/`router.back()` behavior can remain explicit and parity-safe.
|
- Next larger slice candidate: evaluate extraction viability for `/case` branch only if callback/`router.back()` behavior can remain explicit and parity-safe.
|
||||||
- Next smaller slice candidate: add helper-level test coverage for unexpected non-function map values and explicit skip behavior (defensive precedence guard).
|
- Next smaller slice candidate: add helper-level test coverage for unexpected non-function map values and explicit skip behavior (defensive precedence guard).
|
||||||
|
|
||||||
|
### CL-22541-U: breadcrumbs smaller slice — defensive mapped-route resolver hardening
|
||||||
|
|
||||||
|
date: 2026-04-09
|
||||||
|
author: Cline
|
||||||
|
scope: `lib/routing/breadcrumbRouteMaps.js`, `tests/phase22/breadcrumb-route-maps-helper.test.cjs`
|
||||||
|
type: change
|
||||||
|
rationale: Execute the queued smaller slice by hardening mapped-route lookup against malformed map entries and non-function values while keeping precedence behavior unchanged.
|
||||||
|
impact: Refactor-hardening only; no intended breadcrumb route behavior change for valid mapped renderers.
|
||||||
|
status: completed
|
||||||
|
|
||||||
|
Summary:
|
||||||
|
|
||||||
|
- Updated `getMappedRendererByPath(...)` to safely handle invalid route-map entries:
|
||||||
|
- returns `null` when map is missing/non-object
|
||||||
|
- returns `null` when mapped value is not a function
|
||||||
|
- Preserved existing resolver precedence semantics for valid function renderers.
|
||||||
|
- Added focused helper test asserting resolver skips:
|
||||||
|
- invalid map entries (`null`/`undefined`)
|
||||||
|
- non-function mapped values
|
||||||
|
and still resolves the first later valid renderer.
|
||||||
|
|
||||||
|
Validation:
|
||||||
|
|
||||||
|
- `npx eslint lib/routing/breadcrumbRouteMaps.js tests/phase22/breadcrumb-route-maps-helper.test.cjs tests/phase22/index.test.cjs` -> pass.
|
||||||
|
- `node tests/phase22/index.test.cjs` -> pass (combined suite; breadcrumb-route-maps-helper 5/5).
|
||||||
|
|
||||||
|
Follow-ups:
|
||||||
|
|
||||||
|
- Next larger slice: extract remaining callback-bearing deterministic branches into mapped route groups with callback injection, then update structure guards accordingly.
|
||||||
|
|
||||||
### CL-00X: 22500 `components/elements/index.js` Phase 1 helper extraction
|
### CL-00X: 22500 `components/elements/index.js` Phase 1 helper extraction
|
||||||
|
|
||||||
date: 2026-04-07
|
date: 2026-04-07
|
||||||
|
|||||||
@@ -191,6 +191,34 @@ test("resolveMappedRouteRenderer returns null for unmapped path", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("resolveMappedRouteRenderer skips invalid map entries and non-function renderer values", () => {
|
||||||
|
const { buildBreadcrumbRendererMaps, resolveMappedRouteRenderer } =
|
||||||
|
loadHelpers();
|
||||||
|
|
||||||
|
const validRenderer = () => "valid";
|
||||||
|
|
||||||
|
const maps = buildBreadcrumbRendererMaps({
|
||||||
|
simpleRouteRenderersByPath: {
|
||||||
|
"/known": "not-a-function"
|
||||||
|
},
|
||||||
|
simpleLinkTextPairRenderersByPath: null,
|
||||||
|
simpleMyPortalRouteRenderersByPath: {
|
||||||
|
"/known": validRenderer
|
||||||
|
},
|
||||||
|
newAppealRouteRenderersByPath: undefined,
|
||||||
|
caseDetailRouteRenderersByPath: {},
|
||||||
|
detailAndAccountRouteRenderersByPath: {}
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = resolveMappedRouteRenderer("/known", maps);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
result,
|
||||||
|
validRenderer,
|
||||||
|
"Expected resolver to skip invalid/non-function entries and return first valid renderer"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
let passed = 0;
|
let passed = 0;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user