22541 extract new appeal breadcrumb branch into mapped renderer group
This commit is contained in:
@@ -213,6 +213,7 @@ const Breadcrumbs = (props) => {
|
|||||||
simpleRouteRenderersByPath,
|
simpleRouteRenderersByPath,
|
||||||
simpleLinkTextPairRenderersByPath,
|
simpleLinkTextPairRenderersByPath,
|
||||||
simpleMyPortalRouteRenderersByPath,
|
simpleMyPortalRouteRenderersByPath,
|
||||||
|
newAppealRouteRenderersByPath,
|
||||||
caseDetailRouteRenderersByPath,
|
caseDetailRouteRenderersByPath,
|
||||||
detailAndAccountRouteRenderersByPath
|
detailAndAccountRouteRenderersByPath
|
||||||
} = createMappedRouteRendererGroups({
|
} = createMappedRouteRendererGroups({
|
||||||
@@ -242,6 +243,7 @@ const Breadcrumbs = (props) => {
|
|||||||
simpleRouteRenderersByPath,
|
simpleRouteRenderersByPath,
|
||||||
simpleLinkTextPairRenderersByPath,
|
simpleLinkTextPairRenderersByPath,
|
||||||
simpleMyPortalRouteRenderersByPath,
|
simpleMyPortalRouteRenderersByPath,
|
||||||
|
newAppealRouteRenderersByPath,
|
||||||
caseDetailRouteRenderersByPath,
|
caseDetailRouteRenderersByPath,
|
||||||
detailAndAccountRouteRenderersByPath
|
detailAndAccountRouteRenderersByPath
|
||||||
});
|
});
|
||||||
@@ -306,22 +308,6 @@ const Breadcrumbs = (props) => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isPath("/newappeal/selectappeal") && (
|
|
||||||
<>
|
|
||||||
{renderLinkCrumb(
|
|
||||||
myPortalHref,
|
|
||||||
t("newappeal:parent-page-title")
|
|
||||||
)}
|
|
||||||
{renderLinkCrumb(
|
|
||||||
myPortalHref,
|
|
||||||
t("newappeal:page-title")
|
|
||||||
)}
|
|
||||||
<li className="govuk-breadcrumbs__list-item">
|
|
||||||
Select Appeal
|
|
||||||
</li>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{isPath("/myportal/case/id/[incident]") && (
|
{isPath("/myportal/case/id/[incident]") && (
|
||||||
<>
|
<>
|
||||||
{renderMyPortalCrumb()}
|
{renderMyPortalCrumb()}
|
||||||
|
|||||||
@@ -107,6 +107,21 @@ export const createSimpleMyPortalRouteRenderers = ({
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const createNewAppealRouteRenderers = ({
|
||||||
|
t,
|
||||||
|
myPortalHref,
|
||||||
|
renderLinkCrumb,
|
||||||
|
renderTextCrumb
|
||||||
|
}) => ({
|
||||||
|
"/newappeal/selectappeal": () => (
|
||||||
|
<>
|
||||||
|
{renderLinkCrumb(myPortalHref, t("newappeal:parent-page-title"))}
|
||||||
|
{renderLinkCrumb(myPortalHref, t("newappeal:page-title"))}
|
||||||
|
{renderTextCrumb("Select Appeal")}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
export const createCaseDetailRouteRenderers = ({
|
export const createCaseDetailRouteRenderers = ({
|
||||||
t,
|
t,
|
||||||
router,
|
router,
|
||||||
@@ -396,6 +411,13 @@ export const createMappedRouteRendererGroups = ({
|
|||||||
renderMyPortalSectionCrumbs
|
renderMyPortalSectionCrumbs
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const newAppealRouteRenderersByPath = createNewAppealRouteRenderers({
|
||||||
|
t,
|
||||||
|
myPortalHref,
|
||||||
|
renderLinkCrumb,
|
||||||
|
renderTextCrumb
|
||||||
|
});
|
||||||
|
|
||||||
const caseDetailRouteRenderersByPath = createCaseDetailRouteRenderers({
|
const caseDetailRouteRenderersByPath = createCaseDetailRouteRenderers({
|
||||||
t,
|
t,
|
||||||
router,
|
router,
|
||||||
@@ -430,6 +452,7 @@ export const createMappedRouteRendererGroups = ({
|
|||||||
simpleRouteRenderersByPath,
|
simpleRouteRenderersByPath,
|
||||||
simpleLinkTextPairRenderersByPath,
|
simpleLinkTextPairRenderersByPath,
|
||||||
simpleMyPortalRouteRenderersByPath,
|
simpleMyPortalRouteRenderersByPath,
|
||||||
|
newAppealRouteRenderersByPath,
|
||||||
caseDetailRouteRenderersByPath,
|
caseDetailRouteRenderersByPath,
|
||||||
detailAndAccountRouteRenderersByPath
|
detailAndAccountRouteRenderersByPath
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,12 +16,14 @@ const buildBreadcrumbRendererMaps = ({
|
|||||||
simpleRouteRenderersByPath,
|
simpleRouteRenderersByPath,
|
||||||
simpleLinkTextPairRenderersByPath,
|
simpleLinkTextPairRenderersByPath,
|
||||||
simpleMyPortalRouteRenderersByPath,
|
simpleMyPortalRouteRenderersByPath,
|
||||||
|
newAppealRouteRenderersByPath,
|
||||||
caseDetailRouteRenderersByPath,
|
caseDetailRouteRenderersByPath,
|
||||||
detailAndAccountRouteRenderersByPath
|
detailAndAccountRouteRenderersByPath
|
||||||
}) => [
|
}) => [
|
||||||
simpleRouteRenderersByPath,
|
simpleRouteRenderersByPath,
|
||||||
simpleLinkTextPairRenderersByPath,
|
simpleLinkTextPairRenderersByPath,
|
||||||
simpleMyPortalRouteRenderersByPath,
|
simpleMyPortalRouteRenderersByPath,
|
||||||
|
newAppealRouteRenderersByPath,
|
||||||
caseDetailRouteRenderersByPath,
|
caseDetailRouteRenderersByPath,
|
||||||
detailAndAccountRouteRenderersByPath
|
detailAndAccountRouteRenderersByPath
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -602,6 +602,42 @@ Follow-ups:
|
|||||||
- Next slice option A (larger): evaluate whether any remaining deterministic inline branches can be extracted without violating callback/state constraints.
|
- Next slice option A (larger): evaluate whether any remaining deterministic inline branches can be extracted without violating callback/state constraints.
|
||||||
- Next slice option B (smaller): add a focused helper-level precedence test where earlier map contains falsy/non-function values and later maps contain valid renderers.
|
- Next slice option B (smaller): add a focused helper-level precedence test where earlier map contains falsy/non-function values and later maps contain valid renderers.
|
||||||
|
|
||||||
|
### CL-22541-T: breadcrumbs larger slice — new-appeal mapped group extraction (`/newappeal/selectappeal`)
|
||||||
|
|
||||||
|
date: 2026-04-09
|
||||||
|
author: Cline
|
||||||
|
scope: `lib/routing/{breadcrumbRendererFactories,breadcrumbRouteMaps}.js`, `components/breadcrumbs.js`, `tests/phase22/{breadcrumb-route-maps-helper,breadcrumbs-route-map-structure}.test.cjs`
|
||||||
|
type: change
|
||||||
|
rationale: Execute the next larger deterministic refactor slice by extracting callback-free new-appeal breadcrumb branching into a dedicated mapped renderer group and extending map-order guardrails.
|
||||||
|
impact: Refactor-only structural extraction plus precedence-test hardening; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||||
|
status: completed
|
||||||
|
|
||||||
|
Summary:
|
||||||
|
|
||||||
|
- Added `createNewAppealRouteRenderers(...)` in `lib/routing/breadcrumbRendererFactories.js`.
|
||||||
|
- Mapped `/newappeal/selectappeal` into the new grouped renderer factory.
|
||||||
|
- Extended grouped composition return from `createMappedRouteRendererGroups(...)` with `newAppealRouteRenderersByPath`.
|
||||||
|
- Updated `lib/routing/breadcrumbRouteMaps.js` to include `newAppealRouteRenderersByPath` in explicit map precedence ordering.
|
||||||
|
- Updated `components/breadcrumbs.js` to consume/pass `newAppealRouteRenderersByPath` into map builder.
|
||||||
|
- Removed now-redundant inline `isPath("/newappeal/selectappeal")` branch from component JSX.
|
||||||
|
- Expanded tests:
|
||||||
|
- `tests/phase22/breadcrumbs-route-map-structure.test.cjs`
|
||||||
|
- assert new factory export and mapped route presence
|
||||||
|
- assert inline branch removal
|
||||||
|
- assert updated map-order invariant (simple -> link-text -> myportal -> new-appeal -> case detail -> detail/account)
|
||||||
|
- `tests/phase22/breadcrumb-route-maps-helper.test.cjs`
|
||||||
|
- assert six-map ordering contract and updated grouped precedence wiring.
|
||||||
|
|
||||||
|
Validation:
|
||||||
|
|
||||||
|
- `npx eslint lib/routing/breadcrumbRendererFactories.js lib/routing/breadcrumbRouteMaps.js components/breadcrumbs.js tests/phase22/breadcrumb-route-maps-helper.test.cjs tests/phase22/breadcrumbs-route-map-structure.test.cjs tests/phase22/index.test.cjs` -> pass.
|
||||||
|
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||||
|
|
||||||
|
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 smaller slice candidate: add helper-level test coverage for unexpected non-function map values and explicit skip behavior (defensive precedence guard).
|
||||||
|
|
||||||
### 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
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ test("buildBreadcrumbRendererMaps returns grouped maps in explicit precedence or
|
|||||||
const simpleMyPortalRouteRenderersByPath = {
|
const simpleMyPortalRouteRenderersByPath = {
|
||||||
"/gamma": () => "gamma"
|
"/gamma": () => "gamma"
|
||||||
};
|
};
|
||||||
|
const newAppealRouteRenderersByPath = {
|
||||||
|
"/eta": () => "eta"
|
||||||
|
};
|
||||||
const caseDetailRouteRenderersByPath = {
|
const caseDetailRouteRenderersByPath = {
|
||||||
"/delta": () => "delta"
|
"/delta": () => "delta"
|
||||||
};
|
};
|
||||||
@@ -68,12 +71,13 @@ test("buildBreadcrumbRendererMaps returns grouped maps in explicit precedence or
|
|||||||
simpleRouteRenderersByPath,
|
simpleRouteRenderersByPath,
|
||||||
simpleLinkTextPairRenderersByPath,
|
simpleLinkTextPairRenderersByPath,
|
||||||
simpleMyPortalRouteRenderersByPath,
|
simpleMyPortalRouteRenderersByPath,
|
||||||
|
newAppealRouteRenderersByPath,
|
||||||
caseDetailRouteRenderersByPath,
|
caseDetailRouteRenderersByPath,
|
||||||
detailAndAccountRouteRenderersByPath
|
detailAndAccountRouteRenderersByPath
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.ok(Array.isArray(result), "Expected grouped maps array");
|
assert.ok(Array.isArray(result), "Expected grouped maps array");
|
||||||
assert.strictEqual(result.length, 5, "Expected five grouped route maps");
|
assert.strictEqual(result.length, 6, "Expected six grouped route maps");
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
result[0],
|
result[0],
|
||||||
simpleRouteRenderersByPath,
|
simpleRouteRenderersByPath,
|
||||||
@@ -91,13 +95,18 @@ test("buildBreadcrumbRendererMaps returns grouped maps in explicit precedence or
|
|||||||
);
|
);
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
result[3],
|
result[3],
|
||||||
caseDetailRouteRenderersByPath,
|
newAppealRouteRenderersByPath,
|
||||||
"Expected case detail route renderers fourth"
|
"Expected new-appeal route renderers fourth"
|
||||||
);
|
);
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
result[4],
|
result[4],
|
||||||
|
caseDetailRouteRenderersByPath,
|
||||||
|
"Expected case detail route renderers fifth"
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
result[5],
|
||||||
detailAndAccountRouteRenderersByPath,
|
detailAndAccountRouteRenderersByPath,
|
||||||
"Expected detail and account route renderers fifth"
|
"Expected detail and account route renderers sixth"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -116,6 +125,7 @@ test("resolveMappedRouteRenderer returns renderer from first matching grouped ma
|
|||||||
"/known": secondRenderer
|
"/known": secondRenderer
|
||||||
},
|
},
|
||||||
simpleMyPortalRouteRenderersByPath: {},
|
simpleMyPortalRouteRenderersByPath: {},
|
||||||
|
newAppealRouteRenderersByPath: {},
|
||||||
caseDetailRouteRenderersByPath: {},
|
caseDetailRouteRenderersByPath: {},
|
||||||
detailAndAccountRouteRenderersByPath: {}
|
detailAndAccountRouteRenderersByPath: {}
|
||||||
});
|
});
|
||||||
@@ -138,6 +148,9 @@ test("resolveMappedRouteRenderer returns renderer from later grouped map when ea
|
|||||||
const maps = buildBreadcrumbRendererMaps({
|
const maps = buildBreadcrumbRendererMaps({
|
||||||
simpleRouteRenderersByPath: {},
|
simpleRouteRenderersByPath: {},
|
||||||
simpleLinkTextPairRenderersByPath: {},
|
simpleLinkTextPairRenderersByPath: {},
|
||||||
|
newAppealRouteRenderersByPath: {
|
||||||
|
"/newappeal/selectappeal": () => "newappeal"
|
||||||
|
},
|
||||||
simpleMyPortalRouteRenderersByPath: {},
|
simpleMyPortalRouteRenderersByPath: {},
|
||||||
caseDetailRouteRenderersByPath: {},
|
caseDetailRouteRenderersByPath: {},
|
||||||
detailAndAccountRouteRenderersByPath: {
|
detailAndAccountRouteRenderersByPath: {
|
||||||
@@ -164,6 +177,7 @@ test("resolveMappedRouteRenderer returns null for unmapped path", () => {
|
|||||||
},
|
},
|
||||||
simpleLinkTextPairRenderersByPath: {},
|
simpleLinkTextPairRenderersByPath: {},
|
||||||
simpleMyPortalRouteRenderersByPath: {},
|
simpleMyPortalRouteRenderersByPath: {},
|
||||||
|
newAppealRouteRenderersByPath: {},
|
||||||
caseDetailRouteRenderersByPath: {},
|
caseDetailRouteRenderersByPath: {},
|
||||||
detailAndAccountRouteRenderersByPath: {}
|
detailAndAccountRouteRenderersByPath: {}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -36,6 +36,12 @@ test("breadcrumbs/factory module includes expected mapped route definitions", as
|
|||||||
"Expected my-portal route renderer factory export"
|
"Expected my-portal route renderer factory export"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
source.includes("export const createNewAppealRouteRenderers ="),
|
||||||
|
true,
|
||||||
|
"Expected new-appeal route renderer factory export"
|
||||||
|
);
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
source.includes("export const createCaseDetailRouteRenderers ="),
|
source.includes("export const createCaseDetailRouteRenderers ="),
|
||||||
true,
|
true,
|
||||||
@@ -84,6 +90,12 @@ test("breadcrumbs/factory module includes expected mapped route definitions", as
|
|||||||
"Expected /myportal/addresssearchresults to be mapped in createSimpleMyPortalRouteRenderers"
|
"Expected /myportal/addresssearchresults to be mapped in createSimpleMyPortalRouteRenderers"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
source.includes('"/newappeal/selectappeal": () => ('),
|
||||||
|
true,
|
||||||
|
"Expected /newappeal/selectappeal to be mapped in createNewAppealRouteRenderers"
|
||||||
|
);
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
source.includes('"/case/[ticketnumber]": () =>'),
|
source.includes('"/case/[ticketnumber]": () =>'),
|
||||||
true,
|
true,
|
||||||
@@ -173,7 +185,7 @@ test("breadcrumbs/component composes mapped routes via imported factories and sh
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
/const\s+\{[\s\S]*simpleRouteRenderersByPath[\s\S]*detailAndAccountRouteRenderersByPath[\s\S]*\}\s*=\s*createMappedRouteRendererGroups\s*\(/.test(
|
/const\s+\{[\s\S]*simpleRouteRenderersByPath[\s\S]*newAppealRouteRenderersByPath[\s\S]*detailAndAccountRouteRenderersByPath[\s\S]*\}\s*=\s*createMappedRouteRendererGroups\s*\(/.test(
|
||||||
source
|
source
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
@@ -254,6 +266,12 @@ test("breadcrumbs/component composes mapped routes via imported factories and sh
|
|||||||
"Expected /case/id/[incident] explicit branch to be removed after mapping"
|
"Expected /case/id/[incident] explicit branch to be removed after mapping"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
source.includes('isPath("/newappeal/selectappeal")'),
|
||||||
|
false,
|
||||||
|
"Expected /newappeal/selectappeal explicit branch to be removed after mapping"
|
||||||
|
);
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
source.includes('isPath("/myportal/case/[ticketnumber]")'),
|
source.includes('isPath("/myportal/case/[ticketnumber]")'),
|
||||||
false,
|
false,
|
||||||
@@ -330,6 +348,9 @@ test("breadcrumbs/map builder preserves route map ordering", async () => {
|
|||||||
const simpleMyPortalOrderIndex = mapBuilderSlice.indexOf(
|
const simpleMyPortalOrderIndex = mapBuilderSlice.indexOf(
|
||||||
"simpleMyPortalRouteRenderersByPath"
|
"simpleMyPortalRouteRenderersByPath"
|
||||||
);
|
);
|
||||||
|
const newAppealOrderIndex = mapBuilderSlice.indexOf(
|
||||||
|
"newAppealRouteRenderersByPath"
|
||||||
|
);
|
||||||
const caseDetailOrderIndex = mapBuilderSlice.indexOf(
|
const caseDetailOrderIndex = mapBuilderSlice.indexOf(
|
||||||
"caseDetailRouteRenderersByPath"
|
"caseDetailRouteRenderersByPath"
|
||||||
);
|
);
|
||||||
@@ -341,10 +362,11 @@ test("breadcrumbs/map builder preserves route map ordering", async () => {
|
|||||||
simpleRouteOrderIndex >= 0 &&
|
simpleRouteOrderIndex >= 0 &&
|
||||||
simpleLinkTextPairOrderIndex > simpleRouteOrderIndex &&
|
simpleLinkTextPairOrderIndex > simpleRouteOrderIndex &&
|
||||||
simpleMyPortalOrderIndex > simpleLinkTextPairOrderIndex &&
|
simpleMyPortalOrderIndex > simpleLinkTextPairOrderIndex &&
|
||||||
caseDetailOrderIndex > simpleMyPortalOrderIndex &&
|
newAppealOrderIndex > simpleMyPortalOrderIndex &&
|
||||||
|
caseDetailOrderIndex > newAppealOrderIndex &&
|
||||||
detailAndAccountOrderIndex > caseDetailOrderIndex,
|
detailAndAccountOrderIndex > caseDetailOrderIndex,
|
||||||
true,
|
true,
|
||||||
"Expected map builder call to preserve explicit route-map ordering (simple -> link-text -> myportal -> case detail -> detail/account)"
|
"Expected map builder call to preserve explicit route-map ordering (simple -> link-text -> myportal -> new-appeal -> case detail -> detail/account)"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user