+2
-1
@@ -32,7 +32,7 @@ RELAYPATH = "ar-hc-lz-pedw-test-uks-01"
|
||||
CRMURL = "ts-pedw.crm11.dynamics.com"
|
||||
CRMURL_VERSION = "v9.2"
|
||||
|
||||
# # //New PreProd
|
||||
# //New PreProd
|
||||
# CLIENT_ID = ab6c4678-b31a-4eb3-b429-e039120e488a
|
||||
# CLIENT_SECRET = VWY8Q~9EtRzGXpd8Xs~5OS1fej2IyVJ8JgTMncw3
|
||||
# RELAY_ROOT = https://ar-ns-lz-pedw-ppe-uks-01.servicebus.windows.net/ar-hc-lz-pedw-ppe-uks-01/
|
||||
@@ -271,3 +271,4 @@ HIDEERRORLOGS = false
|
||||
SHOWSIPS = true
|
||||
|
||||
ALLOWED_IPS=::1,203.0.113.42,198.51.100.17
|
||||
UPLOAD_BATCH_COUNT = 5
|
||||
@@ -59,3 +59,4 @@ GUARDRAILS.md
|
||||
ai-prompts/
|
||||
workflows/
|
||||
AI_CONTEXT.md
|
||||
pages/baracuda.min.html
|
||||
|
||||
+203
-913
File diff suppressed because it is too large
Load Diff
+13
-49
@@ -45,6 +45,10 @@ import {
|
||||
showRepsEnded,
|
||||
getBilingualText
|
||||
} from "./summary/utils/helpers";
|
||||
import {
|
||||
resolveSearchResultsHref,
|
||||
isDnsRoutePath
|
||||
} from "../../lib/routing/routeState";
|
||||
|
||||
import CaseNoticeBanner from "./caseNoticeBanner";
|
||||
import WatchModal from "./watchmodal";
|
||||
@@ -324,52 +328,15 @@ const CaseSummary = (props) => {
|
||||
|
||||
const zoom = isNaN(parseFloat(siteCoords.latitude)) ? 7 : 12;
|
||||
|
||||
const buildSearchHref = (router, session) => {
|
||||
const { va, adv, ads, key } = router.query;
|
||||
const isDnsRoute = isDnsRoutePath(router.pathname);
|
||||
|
||||
const isDnsRoute =
|
||||
router.pathname === "/dns" ||
|
||||
router.pathname.startsWith("/dns/") ||
|
||||
router.pathname === "/myportal/dns" ||
|
||||
router.pathname.startsWith("/myportal/dns/");
|
||||
|
||||
const base = session ? "/myportal" : "";
|
||||
|
||||
if (!va && !adv && !ads) {
|
||||
return {
|
||||
pathname: "/myportal"
|
||||
};
|
||||
}
|
||||
|
||||
if (isDnsRoute) {
|
||||
return {
|
||||
pathname: `${base}/dnsapplications`
|
||||
};
|
||||
}
|
||||
|
||||
if (va === "true") {
|
||||
return {
|
||||
pathname: "/myportal/viewall",
|
||||
query: { key }
|
||||
};
|
||||
}
|
||||
|
||||
if (adv === "true") {
|
||||
return {
|
||||
pathname: `${base}/advancedsearchresults`,
|
||||
query: router.query
|
||||
};
|
||||
}
|
||||
|
||||
if (ads === "true") {
|
||||
return {
|
||||
pathname: `${base}/addresssearchresults`,
|
||||
query: router.query
|
||||
};
|
||||
}
|
||||
|
||||
return { pathname: `${base}/searchresults`, query: router.query };
|
||||
};
|
||||
const searchHref = resolveSearchResultsHref({
|
||||
query: router.query,
|
||||
hasSession: Boolean(session),
|
||||
includeViewAll: true,
|
||||
fallbackToMyPortalWhenNoFlags: true,
|
||||
isDnsRoute
|
||||
});
|
||||
|
||||
let showDetailsBlock =
|
||||
showDetails == true ? (
|
||||
@@ -1043,10 +1010,7 @@ const CaseSummary = (props) => {
|
||||
|
||||
<Link
|
||||
className="govuk-button govuk-button--secondary"
|
||||
href={buildSearchHref(
|
||||
router,
|
||||
session
|
||||
)}
|
||||
href={searchHref}
|
||||
>
|
||||
{" "}
|
||||
{t(
|
||||
|
||||
@@ -523,9 +523,12 @@ const ViewAllResults = (props) => {
|
||||
? jsonpath({
|
||||
path:
|
||||
'$..[?(@ && @.value=="' +
|
||||
searchDetailsObj[key].value[0][
|
||||
"_pinswg_localplanningauthority_value@OData.Community.Display.V1.FormattedValuee"
|
||||
] +
|
||||
(searchDetailsObj[key][
|
||||
"_pinswg_localplanningauthority_value@OData.Community.Display.V1.FormattedValue"
|
||||
] ||
|
||||
searchDetailsObj[key]?.value[0][
|
||||
"_pinswg_localplanningauthority_value@OData.Community.Display.V1.FormattedValue"
|
||||
]) +
|
||||
'")].value_cy',
|
||||
json: transLookup,
|
||||
eval: true
|
||||
@@ -544,7 +547,7 @@ const ViewAllResults = (props) => {
|
||||
path:
|
||||
'$..[?(@ && @.value=="' +
|
||||
resultItem[
|
||||
"_pinswg_localplanningauthority_value@OData.Community.Display.V1.FormattedValuee"
|
||||
"_pinswg_localplanningauthority_value@OData.Community.Display.V1.FormattedValue"
|
||||
] +
|
||||
'")].value_cy',
|
||||
json: transLookup,
|
||||
|
||||
@@ -16,7 +16,7 @@ module.exports = {
|
||||
"/myportal/contactus": ["newappeal", "account", "common"],
|
||||
"/error": ["common", "home", "myportal"],
|
||||
"/furtherdetails": ["common", "home", "myportal"],
|
||||
"/myportal": ["myportal", "common", "home", "case"],
|
||||
"/myportal": ["myportal", "common", "home", "case", "auth"],
|
||||
"/myportal/viewall": ["search", "myportal", "case"],
|
||||
"/myportal/advancedsearch": ["search", "myportal"],
|
||||
"/myportal/advancedsearchresults": ["search", "myportal", "case"],
|
||||
|
||||
@@ -0,0 +1,618 @@
|
||||
import React from "react";
|
||||
|
||||
export const createSimpleRouteRenderers = ({
|
||||
t,
|
||||
renderTextCrumb,
|
||||
renderMyPortalSectionCrumbs
|
||||
}) => ({
|
||||
"/myportal": () => renderTextCrumb(t("myportal:page-title")),
|
||||
"/searchresults": () =>
|
||||
renderTextCrumb(t("common:breadcrumb-search-results")),
|
||||
"/advancedsearch": () =>
|
||||
renderTextCrumb(t("common:breadcrumb-advanced-search")),
|
||||
"/addresssearch": () =>
|
||||
renderTextCrumb(t("common:breadcrumb-address-search")),
|
||||
"/contactus": () =>
|
||||
renderTextCrumb(t("common:footer-contact-us-link-label")),
|
||||
"/viewall": () =>
|
||||
renderMyPortalSectionCrumbs(t("common:breadcrumb-your-cases")),
|
||||
"/myportal/dnsapplications": () =>
|
||||
renderMyPortalSectionCrumbs(t("dnsCommon:service-name")),
|
||||
"/dnsapplications": () => renderTextCrumb(t("dnsCommon:service-name"))
|
||||
});
|
||||
|
||||
export const createSimpleLinkTextPairRenderers = ({
|
||||
t,
|
||||
router,
|
||||
isWelsh,
|
||||
renderLinkCrumb,
|
||||
renderTextCrumb
|
||||
}) => ({
|
||||
"/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"))}
|
||||
</>
|
||||
)
|
||||
});
|
||||
|
||||
export const createSimpleMyPortalRouteRenderers = ({
|
||||
t,
|
||||
router,
|
||||
isWelsh,
|
||||
myPortalHref,
|
||||
currentViewState,
|
||||
getViewAllLabel,
|
||||
renderAnchorCrumb,
|
||||
renderLinkCrumb,
|
||||
renderTextCrumb,
|
||||
renderMyPortalCrumb,
|
||||
renderMyPortalSectionCrumbs
|
||||
}) => ({
|
||||
"/myportal/searchresults": () => (
|
||||
<>
|
||||
{renderAnchorCrumb(myPortalHref, t("common:breadcrumb-my-portal"))}
|
||||
{renderTextCrumb(t("common:breadcrumb-search-results"))}
|
||||
</>
|
||||
),
|
||||
"/myportal/addresssearch": () =>
|
||||
renderMyPortalSectionCrumbs(t("common:breadcrumb-address-search")),
|
||||
"/myportal/advancedsearch": () =>
|
||||
renderMyPortalSectionCrumbs(t("common:breadcrumb-advanced-search")),
|
||||
"/myportal/contactus": () =>
|
||||
renderMyPortalSectionCrumbs(t("common:footer-contact-us-link-label")),
|
||||
"/myportal/viewall": () =>
|
||||
renderMyPortalSectionCrumbs(
|
||||
getViewAllLabel(currentViewState.viewKey || router.query.key)
|
||||
),
|
||||
"/myportal/advancedsearchresults": () => (
|
||||
<>
|
||||
{renderMyPortalCrumb()}
|
||||
{renderLinkCrumb(
|
||||
isWelsh
|
||||
? `/${router.locale}/myportal/advancedsearch`
|
||||
: "/myportal/advancedsearch",
|
||||
t("common:breadcrumb-advanced-search")
|
||||
)}
|
||||
{renderTextCrumb(t("common:breadcrumb-advanced-search-results"))}
|
||||
</>
|
||||
),
|
||||
"/myportal/addresssearchresults": () => (
|
||||
<>
|
||||
{renderMyPortalCrumb()}
|
||||
{renderLinkCrumb(
|
||||
isWelsh
|
||||
? `/${router.locale}/fymhorth/chwiliadcyfeiriadau`
|
||||
: "/myportal/addresssearch",
|
||||
t("common:breadcrumb-address-search")
|
||||
)}
|
||||
{renderTextCrumb(t("common:breadcrumb-address-search-results"))}
|
||||
</>
|
||||
)
|
||||
});
|
||||
|
||||
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 createCallbackRouteRenderers = ({
|
||||
t,
|
||||
router,
|
||||
isWelsh,
|
||||
nestedSearchString,
|
||||
currentReference,
|
||||
renderMyPortalCrumb,
|
||||
renderLinkCrumb,
|
||||
renderCaseReferenceCrumb,
|
||||
onBack
|
||||
}) => ({
|
||||
"/myportal/case/id/[incident]": () => (
|
||||
<>
|
||||
{renderMyPortalCrumb()}
|
||||
{renderLinkCrumb(
|
||||
isWelsh
|
||||
? `/${router.locale}/fymhorth/chwiliadcyfeiriadau`
|
||||
: "/myportal/addresssearch",
|
||||
t("common:breadcrumb-address-search")
|
||||
)}
|
||||
{renderLinkCrumb(
|
||||
isWelsh
|
||||
? `/${router.locale}/fymhorth/canlyniadaucyfeiriadau?${nestedSearchString}`
|
||||
: `/myportal/addresssearchresults?${nestedSearchString}`,
|
||||
t("common:breadcrumb-address-search-results"),
|
||||
onBack
|
||||
)}
|
||||
{renderCaseReferenceCrumb(currentReference)}
|
||||
</>
|
||||
),
|
||||
|
||||
"/case": () => (
|
||||
<>
|
||||
{renderLinkCrumb(
|
||||
isWelsh
|
||||
? `${router.locale}/searchresults?q=${router.query.q}&page=${router.query.page}`
|
||||
: `/searchresults?q=${router.query.q}&page=${router.query.page}`,
|
||||
t("common:breadcrumb-search-results"),
|
||||
onBack
|
||||
)}
|
||||
{renderCaseReferenceCrumb(currentReference)}
|
||||
</>
|
||||
)
|
||||
});
|
||||
|
||||
export const createStepBackRouteRenderers = ({
|
||||
t,
|
||||
currentSection,
|
||||
onStepBack,
|
||||
onStepBackWithInlineClass,
|
||||
renderLinkCrumb,
|
||||
renderBackCrumb
|
||||
}) => ({
|
||||
"/newappeal/[appealtypes]": () => {
|
||||
if (currentSection <= 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (currentSection === 9999) {
|
||||
return renderLinkCrumb("/", t("common:service-name-breadcrumb"));
|
||||
}
|
||||
|
||||
return renderBackCrumb(
|
||||
onStepBackWithInlineClass,
|
||||
"govuk-breadcrumbs__link-item"
|
||||
);
|
||||
},
|
||||
|
||||
"/myportal/[appealtypes]": () => {
|
||||
if (currentSection <= 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (currentSection === 9999) {
|
||||
return renderLinkCrumb("/", t("common:service-name-breadcrumb"));
|
||||
}
|
||||
|
||||
return renderBackCrumb(onStepBack);
|
||||
}
|
||||
});
|
||||
|
||||
export const createRepresentationRouteRenderers = ({
|
||||
currentView,
|
||||
hasRepDetails,
|
||||
repDetails,
|
||||
showQuestionnaireSection,
|
||||
onRepresentationSubmitBackFromConfirmation,
|
||||
onRepresentationSubmitBackToDetails,
|
||||
onRepresentationQuestionnaireBack,
|
||||
renderBackCrumb
|
||||
}) => ({
|
||||
"/myportal/representation": () => (
|
||||
<>
|
||||
{currentView.representationSubmit === true &&
|
||||
currentView.representationSubmitConfirmation !== true &&
|
||||
renderBackCrumb(onRepresentationSubmitBackFromConfirmation)}
|
||||
|
||||
{currentView.representationSubmit !== true &&
|
||||
hasRepDetails &&
|
||||
repDetails?.representationType !== "Questionnaire" &&
|
||||
renderBackCrumb(onRepresentationSubmitBackToDetails)}
|
||||
|
||||
{currentView.representationSubmit !== true &&
|
||||
hasRepDetails &&
|
||||
repDetails?.representationType === "Questionnaire" &&
|
||||
showQuestionnaireSection > 1 &&
|
||||
renderBackCrumb(onRepresentationQuestionnaireBack)}
|
||||
</>
|
||||
)
|
||||
});
|
||||
|
||||
export const createCaseDetailRouteRenderers = ({
|
||||
t,
|
||||
router,
|
||||
isWelsh,
|
||||
currentReference,
|
||||
nestedSearchString,
|
||||
caseResultsHref,
|
||||
breadcrumbLabel,
|
||||
fallbackSearchTitle,
|
||||
caseReferenceDisplay,
|
||||
getViewAllLabel,
|
||||
renderLinkCrumb,
|
||||
renderCaseReferenceCrumb,
|
||||
renderMyPortalCrumb
|
||||
}) => ({
|
||||
"/myportal/case": () => (
|
||||
<>
|
||||
{renderLinkCrumb(
|
||||
isWelsh ? `/${router.locale}/fymhorth` : "/myportal",
|
||||
t("common:breadcrumb-my-portal")
|
||||
)}
|
||||
{renderCaseReferenceCrumb(currentReference)}
|
||||
</>
|
||||
),
|
||||
|
||||
"/case/id/[incident]": () => (
|
||||
<>
|
||||
{renderLinkCrumb(
|
||||
isWelsh
|
||||
? `/${router.locale}/chwiliadcyfeiriadau`
|
||||
: "/addresssearch",
|
||||
t("common:breadcrumb-address-search")
|
||||
)}
|
||||
{renderLinkCrumb(
|
||||
isWelsh
|
||||
? `/${router.locale}/canlyniadaucyfeiriadau?${nestedSearchString}`
|
||||
: `/addresssearchresults?${nestedSearchString}`,
|
||||
t("common:breadcrumb-address-search-results")
|
||||
)}
|
||||
{renderCaseReferenceCrumb(currentReference)}
|
||||
</>
|
||||
),
|
||||
|
||||
"/case/[ticketnumber]": () => {
|
||||
const { ads, adv, va, key } = router.query;
|
||||
|
||||
if (ads === "true") {
|
||||
return (
|
||||
<>
|
||||
{renderLinkCrumb(
|
||||
isWelsh
|
||||
? `/${router.locale}/chwiliadcyfeiriadau`
|
||||
: "/addresssearch",
|
||||
t("common:breadcrumb-address-search")
|
||||
)}
|
||||
{renderLinkCrumb(
|
||||
caseResultsHref,
|
||||
t("common:breadcrumb-address-search-results")
|
||||
)}
|
||||
{renderCaseReferenceCrumb(fallbackSearchTitle)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (adv === "true") {
|
||||
return (
|
||||
<>
|
||||
{renderLinkCrumb(
|
||||
isWelsh
|
||||
? `/${router.locale}/advancedsearch`
|
||||
: "/advancedsearch",
|
||||
t("common:breadcrumb-advanced-search")
|
||||
)}
|
||||
{renderLinkCrumb(
|
||||
caseResultsHref,
|
||||
t("common:breadcrumb-advanced-search-results")
|
||||
)}
|
||||
{renderCaseReferenceCrumb(fallbackSearchTitle)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (va === "true") {
|
||||
return (
|
||||
<>
|
||||
{renderLinkCrumb("/myportal/viewall", getViewAllLabel(key))}
|
||||
{renderCaseReferenceCrumb(fallbackSearchTitle)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{renderLinkCrumb(caseResultsHref, breadcrumbLabel)}
|
||||
{renderCaseReferenceCrumb(fallbackSearchTitle)}
|
||||
</>
|
||||
);
|
||||
},
|
||||
|
||||
"/myportal/case/[ticketnumber]": () => {
|
||||
const { ads, adv, va, key } = router.query;
|
||||
|
||||
if (ads === "true") {
|
||||
return (
|
||||
<>
|
||||
{renderMyPortalCrumb()}
|
||||
{renderLinkCrumb(
|
||||
isWelsh
|
||||
? `/${router.locale}/fymhorth/chwiliadcyfeiriadau`
|
||||
: "/myportal/addresssearch",
|
||||
t("common:breadcrumb-address-search")
|
||||
)}
|
||||
{renderLinkCrumb(
|
||||
caseResultsHref,
|
||||
t("common:breadcrumb-address-search-results")
|
||||
)}
|
||||
{renderCaseReferenceCrumb(caseReferenceDisplay)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (adv === "true") {
|
||||
return (
|
||||
<>
|
||||
{renderMyPortalCrumb()}
|
||||
{renderLinkCrumb(
|
||||
isWelsh
|
||||
? `/${router.locale}/myportal/advancedsearch`
|
||||
: "/myportal/advancedsearch",
|
||||
t("common:breadcrumb-advanced-search")
|
||||
)}
|
||||
{renderLinkCrumb(
|
||||
caseResultsHref,
|
||||
t("common:breadcrumb-advanced-search-results")
|
||||
)}
|
||||
{renderCaseReferenceCrumb(caseReferenceDisplay)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (va === "true") {
|
||||
return (
|
||||
<>
|
||||
{renderMyPortalCrumb()}
|
||||
{renderLinkCrumb("/myportal/viewall", getViewAllLabel(key))}
|
||||
{renderCaseReferenceCrumb(caseReferenceDisplay)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{renderMyPortalCrumb()}
|
||||
{renderLinkCrumb(caseResultsHref, breadcrumbLabel)}
|
||||
{renderCaseReferenceCrumb(caseReferenceDisplay)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export const createDetailAndAccountRouteRenderers = ({
|
||||
t,
|
||||
router,
|
||||
isWelsh,
|
||||
cyMyPortalHref,
|
||||
currentReference,
|
||||
caseReferenceDisplay,
|
||||
renderMyPortalCrumb,
|
||||
renderLinkCrumb,
|
||||
renderCaseReferenceCrumb,
|
||||
renderDnsCaseReferenceCrumbs
|
||||
}) => ({
|
||||
"/myportal/dnsdetails": () => (
|
||||
<>
|
||||
{renderMyPortalCrumb()}
|
||||
{renderLinkCrumb(
|
||||
"/myportal/dnsapplications",
|
||||
t("dnsCommon:service-name")
|
||||
)}
|
||||
{renderCaseReferenceCrumb(currentReference)}
|
||||
</>
|
||||
),
|
||||
|
||||
"/myportal/dns/[developmentName]": () => (
|
||||
<>
|
||||
{renderMyPortalCrumb()}
|
||||
{renderLinkCrumb(
|
||||
"/myportal/dnsapplications",
|
||||
t("dnsCommon:service-name")
|
||||
)}
|
||||
{renderCaseReferenceCrumb(caseReferenceDisplay)}
|
||||
</>
|
||||
),
|
||||
|
||||
"/dnsdetails": () => renderDnsCaseReferenceCrumbs(currentReference),
|
||||
|
||||
"/dns/[developmentName]": () =>
|
||||
renderDnsCaseReferenceCrumbs(caseReferenceDisplay),
|
||||
|
||||
"/dns/application-view": () => (
|
||||
<>
|
||||
{renderLinkCrumb(
|
||||
isWelsh
|
||||
? `/${router.locale}/dns/applications`
|
||||
: "/dns/applications",
|
||||
t("dnsApplicationView:page-parent-title")
|
||||
)}
|
||||
{renderLinkCrumb(
|
||||
isWelsh
|
||||
? `/${router.locale}/dnsapplications`
|
||||
: "/dnsapplications",
|
||||
t("dnsCommon:service-name")
|
||||
)}
|
||||
{renderCaseReferenceCrumb("TWA - Morlais Demonstration Zone")}
|
||||
</>
|
||||
),
|
||||
|
||||
"/account/personaldetails": () => (
|
||||
<>
|
||||
{renderLinkCrumb(cyMyPortalHref, t("common:breadcrumb-my-portal"))}
|
||||
<li className="govuk-breadcrumbs__list-item">
|
||||
{t("account:account-title")}
|
||||
</li>
|
||||
</>
|
||||
),
|
||||
|
||||
"/account/changepassword": () => (
|
||||
<>
|
||||
{renderLinkCrumb(cyMyPortalHref, t("common:breadcrumb-my-portal"))}
|
||||
<li className="govuk-breadcrumbs__list-item">
|
||||
Update your password
|
||||
</li>
|
||||
</>
|
||||
)
|
||||
});
|
||||
|
||||
export const createMappedRouteRendererGroups = ({
|
||||
t,
|
||||
router,
|
||||
isWelsh,
|
||||
myPortalHref,
|
||||
cyMyPortalHref,
|
||||
currentViewState,
|
||||
getViewAllLabel,
|
||||
caseResultsHref,
|
||||
breadcrumbLabel,
|
||||
fallbackSearchTitle,
|
||||
currentReference,
|
||||
nestedSearchString,
|
||||
caseReferenceDisplay,
|
||||
onBack,
|
||||
currentSection,
|
||||
onStepBack,
|
||||
onStepBackWithInlineClass,
|
||||
currentView,
|
||||
hasRepDetails,
|
||||
repDetails,
|
||||
showQuestionnaireSection,
|
||||
onRepresentationSubmitBackFromConfirmation,
|
||||
onRepresentationSubmitBackToDetails,
|
||||
onRepresentationQuestionnaireBack,
|
||||
renderAnchorCrumb,
|
||||
renderLinkCrumb,
|
||||
renderTextCrumb,
|
||||
renderCaseReferenceCrumb,
|
||||
renderMyPortalCrumb,
|
||||
renderMyPortalSectionCrumbs,
|
||||
renderDnsCaseReferenceCrumbs,
|
||||
renderBackCrumb
|
||||
}) => {
|
||||
const simpleRouteRenderersByPath = createSimpleRouteRenderers({
|
||||
t,
|
||||
renderTextCrumb,
|
||||
renderMyPortalSectionCrumbs
|
||||
});
|
||||
|
||||
const simpleLinkTextPairRenderersByPath = createSimpleLinkTextPairRenderers(
|
||||
{
|
||||
t,
|
||||
router,
|
||||
isWelsh,
|
||||
renderLinkCrumb,
|
||||
renderTextCrumb
|
||||
}
|
||||
);
|
||||
|
||||
const simpleMyPortalRouteRenderersByPath =
|
||||
createSimpleMyPortalRouteRenderers({
|
||||
t,
|
||||
router,
|
||||
isWelsh,
|
||||
myPortalHref,
|
||||
currentViewState,
|
||||
getViewAllLabel,
|
||||
renderAnchorCrumb,
|
||||
renderLinkCrumb,
|
||||
renderTextCrumb,
|
||||
renderMyPortalCrumb,
|
||||
renderMyPortalSectionCrumbs
|
||||
});
|
||||
|
||||
const newAppealRouteRenderersByPath = createNewAppealRouteRenderers({
|
||||
t,
|
||||
myPortalHref,
|
||||
renderLinkCrumb,
|
||||
renderTextCrumb
|
||||
});
|
||||
|
||||
const callbackRouteRenderersByPath = createCallbackRouteRenderers({
|
||||
t,
|
||||
router,
|
||||
isWelsh,
|
||||
nestedSearchString,
|
||||
currentReference,
|
||||
renderMyPortalCrumb,
|
||||
renderLinkCrumb,
|
||||
renderCaseReferenceCrumb,
|
||||
onBack
|
||||
});
|
||||
|
||||
const stepBackRouteRenderersByPath = createStepBackRouteRenderers({
|
||||
t,
|
||||
currentSection,
|
||||
onStepBack,
|
||||
onStepBackWithInlineClass,
|
||||
renderLinkCrumb,
|
||||
renderBackCrumb
|
||||
});
|
||||
|
||||
const representationRouteRenderersByPath =
|
||||
createRepresentationRouteRenderers({
|
||||
currentView,
|
||||
hasRepDetails,
|
||||
repDetails,
|
||||
showQuestionnaireSection,
|
||||
onRepresentationSubmitBackFromConfirmation,
|
||||
onRepresentationSubmitBackToDetails,
|
||||
onRepresentationQuestionnaireBack,
|
||||
renderBackCrumb
|
||||
});
|
||||
|
||||
const caseDetailRouteRenderersByPath = createCaseDetailRouteRenderers({
|
||||
t,
|
||||
router,
|
||||
isWelsh,
|
||||
currentReference,
|
||||
nestedSearchString,
|
||||
caseResultsHref,
|
||||
breadcrumbLabel,
|
||||
fallbackSearchTitle,
|
||||
caseReferenceDisplay,
|
||||
getViewAllLabel,
|
||||
renderLinkCrumb,
|
||||
renderCaseReferenceCrumb,
|
||||
renderMyPortalCrumb
|
||||
});
|
||||
|
||||
const detailAndAccountRouteRenderersByPath =
|
||||
createDetailAndAccountRouteRenderers({
|
||||
t,
|
||||
router,
|
||||
isWelsh,
|
||||
cyMyPortalHref,
|
||||
currentReference,
|
||||
caseReferenceDisplay,
|
||||
renderMyPortalCrumb,
|
||||
renderLinkCrumb,
|
||||
renderCaseReferenceCrumb,
|
||||
renderDnsCaseReferenceCrumbs
|
||||
});
|
||||
|
||||
return {
|
||||
simpleRouteRenderersByPath,
|
||||
simpleLinkTextPairRenderersByPath,
|
||||
simpleMyPortalRouteRenderersByPath,
|
||||
newAppealRouteRenderersByPath,
|
||||
callbackRouteRenderersByPath,
|
||||
stepBackRouteRenderersByPath,
|
||||
representationRouteRenderersByPath,
|
||||
caseDetailRouteRenderersByPath,
|
||||
detailAndAccountRouteRenderersByPath
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
const getMappedRendererByPath = (path, routeRendererMap) => {
|
||||
if (!routeRendererMap || typeof routeRendererMap !== "object") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const routeRenderer = routeRendererMap[path];
|
||||
return typeof routeRenderer === "function" ? routeRenderer : null;
|
||||
};
|
||||
|
||||
const resolveMappedRouteRenderer = (path, routeRendererMaps = []) => {
|
||||
for (const routeRendererMap of routeRendererMaps) {
|
||||
const routeRenderer = getMappedRendererByPath(path, routeRendererMap);
|
||||
if (routeRenderer) {
|
||||
return routeRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const buildBreadcrumbRendererMaps = ({
|
||||
simpleRouteRenderersByPath,
|
||||
simpleLinkTextPairRenderersByPath,
|
||||
simpleMyPortalRouteRenderersByPath,
|
||||
newAppealRouteRenderersByPath,
|
||||
callbackRouteRenderersByPath,
|
||||
stepBackRouteRenderersByPath,
|
||||
representationRouteRenderersByPath,
|
||||
caseDetailRouteRenderersByPath,
|
||||
detailAndAccountRouteRenderersByPath
|
||||
}) => [
|
||||
simpleRouteRenderersByPath,
|
||||
simpleLinkTextPairRenderersByPath,
|
||||
simpleMyPortalRouteRenderersByPath,
|
||||
newAppealRouteRenderersByPath,
|
||||
callbackRouteRenderersByPath,
|
||||
stepBackRouteRenderersByPath,
|
||||
representationRouteRenderersByPath,
|
||||
caseDetailRouteRenderersByPath,
|
||||
detailAndAccountRouteRenderersByPath
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
buildBreadcrumbRendererMaps,
|
||||
getMappedRendererByPath,
|
||||
resolveMappedRouteRenderer
|
||||
};
|
||||
@@ -0,0 +1,133 @@
|
||||
export const normalizeRouteStateQuery = (query = {}) => {
|
||||
const viewAll = query?.va === "true";
|
||||
const advanced = query?.adv === "true";
|
||||
const address = query?.ads === "true";
|
||||
|
||||
return {
|
||||
viewAll,
|
||||
advanced,
|
||||
address,
|
||||
key: query?.key
|
||||
};
|
||||
};
|
||||
|
||||
export const resolveSearchResultsHref = ({
|
||||
query = {},
|
||||
hasSession = false,
|
||||
includeViewAll = true,
|
||||
fallbackToMyPortalWhenNoFlags = false,
|
||||
isDnsRoute = false
|
||||
} = {}) => {
|
||||
const routeState = normalizeRouteStateQuery(query);
|
||||
const { viewAll, advanced, address, key } = routeState;
|
||||
const base = hasSession ? "/myportal" : "";
|
||||
const hasSearchQuery =
|
||||
typeof query?.q === "string" && query.q.trim().length > 0;
|
||||
|
||||
if (fallbackToMyPortalWhenNoFlags && !viewAll && !advanced && !address) {
|
||||
if (hasSearchQuery) {
|
||||
return {
|
||||
pathname: `${base}/searchresults`,
|
||||
query
|
||||
};
|
||||
}
|
||||
return {
|
||||
pathname: "/myportal"
|
||||
};
|
||||
}
|
||||
|
||||
if (isDnsRoute) {
|
||||
return {
|
||||
pathname: `${base}/dnsapplications`
|
||||
};
|
||||
}
|
||||
|
||||
if (includeViewAll && viewAll) {
|
||||
return {
|
||||
pathname: "/myportal/viewall",
|
||||
query: { key }
|
||||
};
|
||||
}
|
||||
|
||||
if (advanced) {
|
||||
return {
|
||||
pathname: `${base}/advancedsearchresults`,
|
||||
query
|
||||
};
|
||||
}
|
||||
|
||||
if (address) {
|
||||
return {
|
||||
pathname: `${base}/addresssearchresults`,
|
||||
query
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
pathname: `${base}/searchresults`,
|
||||
query
|
||||
};
|
||||
};
|
||||
|
||||
export const resolveSearchBreadcrumbLabel = ({
|
||||
query = {},
|
||||
getViewAllLabel = () => null,
|
||||
advancedLabel = "",
|
||||
addressLabel = "",
|
||||
defaultLabel = ""
|
||||
} = {}) => {
|
||||
const routeState = normalizeRouteStateQuery(query);
|
||||
const { viewAll, advanced, address, key } = routeState;
|
||||
|
||||
if (viewAll) {
|
||||
return getViewAllLabel(key);
|
||||
}
|
||||
|
||||
const keyedLabel = getViewAllLabel(key);
|
||||
if (keyedLabel) return keyedLabel;
|
||||
|
||||
if (advanced) return advancedLabel;
|
||||
if (address) return addressLabel;
|
||||
|
||||
return defaultLabel;
|
||||
};
|
||||
|
||||
export const isDnsRoutePath = (pathname = "") => {
|
||||
return (
|
||||
pathname === "/dns" ||
|
||||
pathname.startsWith("/dns/") ||
|
||||
pathname === "/myportal/dns" ||
|
||||
pathname.startsWith("/myportal/dns/")
|
||||
);
|
||||
};
|
||||
|
||||
export const resolveCaseBreadcrumbState = ({
|
||||
query = {},
|
||||
hasSession = false,
|
||||
getViewAllLabel = () => null,
|
||||
advancedLabel = "",
|
||||
addressLabel = "",
|
||||
defaultLabel = ""
|
||||
} = {}) => {
|
||||
return {
|
||||
breadcrumbHref: resolveSearchResultsHref({
|
||||
query,
|
||||
hasSession,
|
||||
includeViewAll: true,
|
||||
fallbackToMyPortalWhenNoFlags: true
|
||||
}),
|
||||
caseResultsHref: resolveSearchResultsHref({
|
||||
query,
|
||||
hasSession,
|
||||
includeViewAll: false,
|
||||
fallbackToMyPortalWhenNoFlags: false
|
||||
}),
|
||||
breadcrumbLabel: resolveSearchBreadcrumbLabel({
|
||||
query,
|
||||
getViewAllLabel,
|
||||
advancedLabel,
|
||||
addressLabel,
|
||||
defaultLabel
|
||||
})
|
||||
};
|
||||
};
|
||||
@@ -18,6 +18,900 @@ Follow-ups:
|
||||
|
||||
---
|
||||
|
||||
### CL-22541: breadcrumb/back-link route-state helper extraction (`va/adv/ads/key`)
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `lib/routing/routeState.js`, `components/breadcrumbs.js`, `components/case/summary.js`, `tests/phase22/{route-state-helper.test.cjs,index.test.cjs}`
|
||||
type: change
|
||||
rationale: Action Priority 3 refactor backlog item by extracting duplicated route-state decision logic (`va/adv/ads/key`) into a shared pure helper and reusing it from breadcrumb and case-summary back-link flows to reduce drift/regression risk.
|
||||
impact: Refactor-only decision-layer consolidation for search/case/myportal navigation; no auth/session/CSP/API contract changes; EN/CY behavior intended unchanged as helper only resolves route targets and preserves existing query forwarding behavior.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Created branch from `origin/SIPS-Development`: `22541-breadcrumb-route-state-helper`.
|
||||
- Added `lib/routing/routeState.js` with:
|
||||
- `normalizeRouteStateQuery(query)`
|
||||
- `resolveSearchResultsHref(options)`
|
||||
- Updated `components/breadcrumbs.js` to consume the shared helper for:
|
||||
- breadcrumb href resolution (`/myportal/viewall`, advanced/address/default results)
|
||||
- case-results breadcrumb target on `/case/[ticketnumber]`
|
||||
- preserving existing label selection behavior via normalized flags.
|
||||
- Updated `components/case/summary.js` to replace local `buildSearchHref` with shared helper output (`searchHref`), including DNS-route override and no-flag fallback behavior.
|
||||
- Added table-driven unit coverage in `tests/phase22/route-state-helper.test.cjs` and registered it in `tests/phase22/index.test.cjs`.
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint lib/routing/routeState.js components/breadcrumbs.js components/case/summary.js tests/phase22/route-state-helper.test.cjs tests/phase22/index.test.cjs` -> pass with 1 pre-existing warning in `components/case/summary.js` (`react-hooks/exhaustive-deps`).
|
||||
- `node tests/phase22/route-state-helper.test.cjs` -> pass (5/5).
|
||||
- `node tests/phase22/index.test.cjs` -> fails in existing auth suite (`tests/phase22/auth-redirect-safety.test.cjs`) with `ReferenceError: resolveLocale is not defined` in `pages/api/auth/[...nextauth].js`; unrelated to route-state changes.
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- If needed, triage/fix the existing phase22 auth redirect test harness failure separately to restore full combined suite execution.
|
||||
- Expand helper adoption in future slices to other navigation decision call sites if additional duplication emerges.
|
||||
|
||||
### CL-22541-B: breadcrumb route-state helper expansion (label + DNS path helper)
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `lib/routing/routeState.js`, `components/breadcrumbs.js`, `components/case/summary.js`, `tests/phase22/route-state-helper.test.cjs`
|
||||
type: change
|
||||
rationale: Continue Priority 3 breadcrumb refactor in a second bounded commit by extracting remaining repeated breadcrumb label and DNS-route-path decision logic into shared pure helpers.
|
||||
impact: Refactor-only extraction for navigation decision logic; no auth/session/CSP/API changes; no intended EN/CY behavior change beyond internal logic centralization.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Extended `lib/routing/routeState.js` with:
|
||||
- `resolveSearchBreadcrumbLabel(...)`
|
||||
- `isDnsRoutePath(pathname)`
|
||||
- Updated `components/breadcrumbs.js` to use `resolveSearchBreadcrumbLabel(...)` and removed inline label decision IIFE.
|
||||
- Updated `components/case/summary.js` to use `isDnsRoutePath(router.pathname)` and removed inline DNS path checks.
|
||||
- Expanded `tests/phase22/route-state-helper.test.cjs` with coverage for:
|
||||
- breadcrumb label resolution matrix
|
||||
- DNS path detection helper
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint lib/routing/routeState.js components/breadcrumbs.js components/case/summary.js tests/phase22/route-state-helper.test.cjs` -> pass with 1 pre-existing warning in `components/case/summary.js` (`react-hooks/exhaustive-deps`).
|
||||
- `node tests/phase22/route-state-helper.test.cjs` -> pass (7/7).
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next breadcrumbs slice can target incremental decomposition of large pathname branch rendering blocks in `components/breadcrumbs.js` into grouped render helpers with behavior parity.
|
||||
|
||||
### CL-22541-C: breadcrumb case-state bundling helper (single-call resolver)
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `lib/routing/routeState.js`, `components/breadcrumbs.js`, `tests/phase22/route-state-helper.test.cjs`
|
||||
type: change
|
||||
rationale: Continue Priority 3 breadcrumbs refactor by bundling repeatedly paired breadcrumb href/label resolution into one pure helper so component call sites stay thinner and less drift-prone.
|
||||
impact: Refactor-only centralization of existing route-state composition logic; no intended auth/session/API/i18n behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added `resolveCaseBreadcrumbState(...)` in `lib/routing/routeState.js` to return:
|
||||
- `breadcrumbHref`
|
||||
- `caseResultsHref`
|
||||
- `breadcrumbLabel`
|
||||
- Updated `components/breadcrumbs.js` to replace three separate helper invocations with one resolver call.
|
||||
- Extended `tests/phase22/route-state-helper.test.cjs` with bundled case-state resolver coverage.
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint lib/routing/routeState.js components/breadcrumbs.js tests/phase22/route-state-helper.test.cjs` -> pass.
|
||||
- `node tests/phase22/route-state-helper.test.cjs` -> pass (8/8).
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next bounded slice can extract grouped pathname render blocks from `components/breadcrumbs.js` (data-driven map or small render helpers) while preserving route parity.
|
||||
|
||||
### CL-22541-D: breadcrumbs shared my-portal crumb helper extraction
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`
|
||||
type: change
|
||||
rationale: Continue bounded breadcrumbs decomposition by extracting repeated my-portal breadcrumb `<li>` markup into one local render helper to reduce duplication and keep follow-on slices safer.
|
||||
impact: Refactor-only JSX deduplication in breadcrumb rendering; no intended route, auth/session, API, EN/CY, or accessibility behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added local `renderMyPortalCrumb()` helper in `components/breadcrumbs.js`.
|
||||
- Replaced repeated identical my-portal crumb JSX in multiple `/myportal/*` route branches with helper calls.
|
||||
- Kept special-case crumbs untouched where label/href differs (e.g. `newappeal` parent-title crumb, `cyMyPortalHref` account branches).
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint components/breadcrumbs.js` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next bounded slice can target additional repeated breadcrumb list-item patterns (e.g., repeated case-reference tail item blocks) with same behavior parity approach.
|
||||
|
||||
### CL-22541-E: breadcrumbs case-reference crumb helper extraction
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`
|
||||
type: change
|
||||
rationale: Continue bounded breadcrumbs decomposition by extracting repeated case-reference tail breadcrumb markup into one local helper and replacing repeated inline blocks.
|
||||
impact: Refactor-only JSX deduplication in breadcrumb rendering; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added local `renderCaseReferenceCrumb(referenceValue)` helper in `components/breadcrumbs.js`.
|
||||
- Replaced repeated `{t("common:breadcrumb-case-reference")}: ...` list-item blocks across case/dns route branches with helper calls.
|
||||
- Corrected initial over-wrap by using helper calls directly (so generated `<li>` is not nested in another `<li>`).
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint components/breadcrumbs.js` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next bounded slice can target remaining repeated linked breadcrumb list-item patterns (e.g., recurring address-search result link pairs) via small local render helpers.
|
||||
|
||||
### CL-22541-F: breadcrumbs multi-pattern helper bundle (text + link crumbs)
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`
|
||||
type: change
|
||||
rationale: Deliver a slightly larger bounded slice by extracting and reusing multiple breadcrumb rendering patterns (plain text crumb and linked crumb) across several route branches.
|
||||
impact: Refactor-only JSX deduplication and consistency improvement in breadcrumb rendering; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added reusable helpers in `components/breadcrumbs.js`:
|
||||
- `renderTextCrumb(label)`
|
||||
- `renderLinkCrumb(href, label, onClick)`
|
||||
- Replaced multiple repeated inline breadcrumb blocks across search/address/myportal/dns branches with helper calls.
|
||||
- Included onClick-capable link helper usage in the `/myportal/case/id/[incident]` address-results breadcrumb branch to preserve `router.back()` behavior.
|
||||
- Combined with existing `renderMyPortalCrumb` and `renderCaseReferenceCrumb` helpers for more consistent branch composition.
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint components/breadcrumbs.js` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next slice recommendation: extract remaining repeated inline link crumbs for case/DNS branches that still hardcode `<li><Link ...>` (e.g., `/myportal/case`, `/myportal/case/[ticketnumber]`, `/dnsdetails`, `/dns/[developmentName]`) to complete link-pattern consolidation.
|
||||
|
||||
### CL-22541-G: breadcrumbs inline Link-crumb consolidation bundle
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`
|
||||
type: change
|
||||
rationale: Continue the larger bounded breadcrumb refactor cadence by replacing the next batch of repeated inline `<li><Link ...>` crumbs with the shared link helper.
|
||||
impact: Refactor-only JSX deduplication and consistency improvement in breadcrumb rendering; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Reused `renderLinkCrumb(href, label, onClick)` for another broad set of previously inline Link crumbs, including:
|
||||
- service-name crumb in the shared shell
|
||||
- new appeal select-appeal parent/title crumbs
|
||||
- case and ticketnumber branches (`/myportal/case`, `/case/[ticketnumber]`, `/case/id/[incident]`, `/myportal/case/[ticketnumber]`)
|
||||
- additional myportal/dns/account branches (`/myportal/dns/[developmentName]`, `/dnsdetails`, `/dns/[developmentName]`, `/dns/application-view`, account crumbs)
|
||||
- Kept special behavior intact where needed (e.g., existing callback-based crumbs that already use helper `onClick`).
|
||||
- Increased consistency of crumb rendering style by routing most link crumbs through one helper.
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint components/breadcrumbs.js` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next slice recommendation: target remaining anchor/back-link duplication (`<a href="#">` and occasional `<a href={...}>`) by introducing a bounded helper for action/back crumbs while preserving existing non-Link semantics.
|
||||
|
||||
### CL-22541-H: breadcrumbs anchor/back-link helper consolidation bundle
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`
|
||||
type: change
|
||||
rationale: Continue the larger bounded breadcrumbs refactor cadence by extracting repeated anchor/back-link crumb markup into one local helper while preserving non-Link semantics.
|
||||
impact: Refactor-only JSX deduplication and consistency improvement in breadcrumb rendering; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added `renderAnchorCrumb(href, label, onClick, listItemClass)` in `components/breadcrumbs.js` for repeated `<a ...>` breadcrumb actions.
|
||||
- Replaced repeated anchor/back-link crumb blocks in:
|
||||
- `/myportal/searchresults` my-portal anchor crumb
|
||||
- `/newappeal/[appealtypes]` and `/myportal/[appealtypes]` step-back crumbs
|
||||
- `/myportal/representation` back-chevron action crumbs (all three state branches)
|
||||
- Preserved original click handlers, href values, and class semantics (`govuk-breadcrumbs__link-item`, `backChevron`) to keep behavior parity.
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint components/breadcrumbs.js` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next slice recommendation: consolidate remaining one-off inline breadcrumb `<li><Link ...>` blocks still present in edge branches (e.g., `/newappeal/[appealtypes]`, `/myportal/[appealtypes]`, `/case`) and consider introducing an optional `renderBackCrumb(...)` semantic wrapper for readability.
|
||||
|
||||
### CL-22541-I: breadcrumbs edge branch consolidation + semantic back-crumb wrapper
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`
|
||||
type: change
|
||||
rationale: Continue the same bounded breadcrumbs refactor cadence by consolidating remaining edge inline Link/back crumbs and introducing a semantic back-crumb wrapper for readability.
|
||||
impact: Refactor-only JSX deduplication/readability improvement; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added semantic helper `renderBackCrumb(onClick, listItemClass?)` that delegates to `renderAnchorCrumb(...)` with existing back-link text.
|
||||
- Replaced remaining one-off inline edge crumbs in:
|
||||
- `/newappeal/[appealtypes]` and `/myportal/[appealtypes]` (`currentSection === 9999` service-name link and back-link branch)
|
||||
- `/case` search-results link crumb (including existing `router.back()` callback)
|
||||
- `/myportal/representation` back-link branches now use `renderBackCrumb(...)`.
|
||||
- Preserved existing href targets, callback behavior, and class semantics (including special `govuk-breadcrumbs__link-item` usage).
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint components/breadcrumbs.js` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next slice recommendation: consider extracting a small, route-keyed breadcrumb branch map/helper grouping in `components/breadcrumbs.js` (purely structural) to reduce the long inline conditional chain while keeping one-slice behavior parity.
|
||||
|
||||
### CL-22541-J: breadcrumbs static text-only route crumb consolidation
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`
|
||||
type: change
|
||||
rationale: Continue the same bounded refactor cadence by consolidating repeated static text-only breadcrumb route branches into one route-label resolver.
|
||||
impact: Refactor-only structural deduplication/readability improvement; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added `getStaticTextCrumbLabel(path)` in `components/breadcrumbs.js` to centralize static text-only crumb labels by pathname.
|
||||
- Replaced repeated single-line static crumb branches with one generic render path:
|
||||
- `renderTextCrumb(getStaticTextCrumbLabel(pathname))` when mapping returns a label.
|
||||
- Consolidated static branch handling for routes including:
|
||||
- account register
|
||||
- DNS index/help/contact/applications process pages
|
||||
- cookies/privacy/accessibility/static auth routes.
|
||||
- Preserved route labels (including translation keys and legacy hardcoded labels where already present).
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint components/breadcrumbs.js` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next slice recommendation: extract a small grouped helper for recurring two-crumb route pairs (e.g., my-portal + section label, dns list + case reference) to reduce the remaining conditional chain while preserving explicit route behavior.
|
||||
|
||||
### CL-22541-K: breadcrumbs grouped two-crumb helper extraction
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`
|
||||
type: change
|
||||
rationale: Continue the same bounded refactor cadence by extracting recurring two-crumb patterns into small grouped helpers while preserving explicit route branches.
|
||||
impact: Refactor-only readability/deduplication improvement; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added grouped helper `renderMyPortalSectionCrumbs(sectionLabel)` for recurring my-portal + section text pairs.
|
||||
- Added grouped helper `renderDnsCaseReferenceCrumbs(referenceValue)` for recurring DNS applications link + case-reference pairs.
|
||||
- Replaced duplicated route branches with grouped helper usage for:
|
||||
- `/myportal/addresssearch`, `/myportal/advancedsearch`, `/myportal/contactus`
|
||||
- `/dnsdetails`, `/dns/[developmentName]`
|
||||
- Preserved existing href behavior (including EN/CY DNS applications link), labels, and case-reference rendering.
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint components/breadcrumbs.js` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next slice recommendation: extract a small route-to-renderer map for static single-branch crumbs (where branch has no bespoke side-effects) so the main JSX conditional chain shrinks further without altering explicit behavior in dynamic/sensitive branches.
|
||||
|
||||
### CL-22541-L: breadcrumbs simple-route renderer map introduction
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`
|
||||
type: change
|
||||
rationale: Continue bounded readability refactor by introducing a small route-to-renderer map for simple static branches, reducing conditional-chain length while preserving explicit dynamic branches.
|
||||
impact: Refactor-only structural deduplication/readability improvement; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added `getSimpleRouteRenderer(path)` in `components/breadcrumbs.js` for simple routes with no bespoke side effects.
|
||||
- Introduced a single invocation block that resolves and renders mapped simple routes when present.
|
||||
- Migrated simple route branches into the map, including:
|
||||
- `/myportal`, `/searchresults`, `/advancedsearch`, `/addresssearch`, `/contactus`
|
||||
- `/viewall`, `/myportal/dnsapplications`
|
||||
- Preserved existing label text, helper usage, and rendered crumb sequence semantics.
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint components/breadcrumbs.js` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||
|
||||
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-22541-N: breadcrumbs unified mapped-route resolver + widened structural guardrails
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`, `tests/phase22/breadcrumbs-route-map-structure.test.cjs`
|
||||
type: change
|
||||
rationale: Execute the requested wider next slice by removing duplicated mapped-route invocation patterns, introducing a single top-level mapped resolver with explicit precedence, and migrating an additional safe my-portal route group into map-driven rendering while preserving explicit dynamic/callback branches.
|
||||
impact: Refactor-only structural consolidation/readability improvement with widened mapped-route coverage and stronger structure guardrail tests; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added `getSimpleMyPortalRouteRenderer(path)` in `components/breadcrumbs.js` and migrated additional safe map-friendly routes:
|
||||
- `/myportal/searchresults`
|
||||
- `/myportal/addresssearch`
|
||||
- `/myportal/advancedsearch`
|
||||
- `/myportal/contactus`
|
||||
- `/myportal/viewall`
|
||||
- Added `resolveMappedRouteRenderer(path)` to unify map precedence under one resolver.
|
||||
- Added `renderMappedRoute(path, resolver?)` helper and replaced duplicated inline map IIFE invocations with a single call:
|
||||
- `{renderMappedRoute(pathname)}`
|
||||
- Kept dynamic/stateful callback branches explicit and unchanged, especially `/myportal/case/id/[incident]` (`router.back()`) and other callback/state driven branches.
|
||||
- Expanded `tests/phase22/breadcrumbs-route-map-structure.test.cjs` to assert:
|
||||
- new my-portal route-map entries are present
|
||||
- unified resolver/helper signatures are present
|
||||
- single mapped-route invocation is used in JSX
|
||||
- dynamic callback branch remains explicit.
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint components/breadcrumbs.js tests/phase22/breadcrumbs-route-map-structure.test.cjs tests/phase22/index.test.cjs` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite; breadcrumbs-route-map tests 3/3).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next wider slice candidate: move a second safe myportal results pair group (`/myportal/advancedsearchresults`, `/myportal/addresssearchresults`) into the unified mapped resolver where callback-free, then consider splitting resolver maps into a dedicated local constant section for improved scanability.
|
||||
|
||||
### CL-22541-O: breadcrumbs myportal results-pair migration into unified mapped resolver
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`, `tests/phase22/breadcrumbs-route-map-structure.test.cjs`
|
||||
type: change
|
||||
rationale: Execute the agreed next slice by migrating the remaining callback-free myportal results-pair branches into the unified mapped resolver so more safe branches are rendered through one consistent mapping flow.
|
||||
impact: Refactor-only structural consolidation/readability improvement; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Extended `getSimpleMyPortalRouteRenderer(path)` to include:
|
||||
- `/myportal/advancedsearchresults`
|
||||
- `/myportal/addresssearchresults`
|
||||
- Removed now-redundant explicit conditional branches for those two routes from the main JSX chain.
|
||||
- Kept callback/stateful branches explicit and unchanged (notably `/myportal/case/id/[incident]` with `router.back()`).
|
||||
- Expanded `tests/phase22/breadcrumbs-route-map-structure.test.cjs` guardrails to assert:
|
||||
- both myportal results-pair routes are mapped
|
||||
- legacy explicit `isPath(...)` branches for those routes are no longer present
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint components/breadcrumbs.js tests/phase22/breadcrumbs-route-map-structure.test.cjs tests/phase22/index.test.cjs` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite; breadcrumbs-route-map tests 3/3).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next wider slice candidate: split map resolver sections into clearly named grouped constants (simple/public/myportal) near one composition point, then optionally move map-only route renderers to a local pure helper module if continued growth impacts scanability.
|
||||
|
||||
### CL-22541-P: breadcrumbs grouped route-map constants + unified map composition point
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`, `tests/phase22/breadcrumbs-route-map-structure.test.cjs`
|
||||
type: change
|
||||
rationale: Execute the next wider slice by replacing per-group resolver functions with grouped route-map constants and a single composition array to further improve scanability while preserving route precedence semantics.
|
||||
impact: Refactor-only structural readability improvement; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Replaced function-based map accessors with grouped route-map constants in `components/breadcrumbs.js`:
|
||||
- `simpleRouteRenderersByPath`
|
||||
- `simpleLinkTextPairRenderersByPath`
|
||||
- `simpleMyPortalRouteRenderersByPath`
|
||||
- Added unified map composition point:
|
||||
- `mappedRouteRendererMaps` (ordered array preserving precedence)
|
||||
- `getMappedRendererByPath(path, routeRendererMap)` helper
|
||||
- Updated `resolveMappedRouteRenderer(path)` to iterate the composed map list while retaining previous resolution order and behavior.
|
||||
- Kept dynamic/callback branches explicit and unchanged outside map-driven paths.
|
||||
- Expanded structure tests to assert grouped map composition contracts (`mappedRouteRendererMaps`, `getMappedRendererByPath`) in addition to existing resolver and invocation guardrails.
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint components/breadcrumbs.js tests/phase22/breadcrumbs-route-map-structure.test.cjs tests/phase22/index.test.cjs` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite; breadcrumbs-route-map tests 3/3).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next slice option A (larger): extract map constants + resolver helpers into a local `lib/routing/breadcrumbRouteMaps.js` pure module with focused tests, keeping callback/stateful branch rendering in component.
|
||||
- Next slice option B (smaller): expand structure tests to assert explicit map ordering invariants so future reordering regressions are caught early.
|
||||
|
||||
### CL-22541-Q: breadcrumbs route-map helper module extraction + map-order invariants
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `lib/routing/breadcrumbRouteMaps.js`, `components/breadcrumbs.js`, `tests/phase22/{breadcrumb-route-maps-helper,breadcrumbs-route-map-structure,index}.test.cjs`
|
||||
type: change
|
||||
rationale: Execute both queued follow-up slices together by extracting map composition/resolution logic into a pure routing helper module and adding stronger structure + pure-helper guardrails for map-order precedence.
|
||||
impact: Refactor-only structural modularization and test hardening; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added new pure helper module `lib/routing/breadcrumbRouteMaps.js`:
|
||||
- `buildBreadcrumbRendererMaps(...)`
|
||||
- `getMappedRendererByPath(...)`
|
||||
- `resolveMappedRouteRenderer(...)`
|
||||
- Updated `components/breadcrumbs.js` to import/use shared helper logic:
|
||||
- map composition now via `buildBreadcrumbRendererMaps(...)`
|
||||
- resolver now delegates to `resolveMappedRouteRendererByMaps(...)`
|
||||
- dynamic/callback-sensitive explicit branches remain unchanged.
|
||||
- Added focused pure-helper tests in `tests/phase22/breadcrumb-route-maps-helper.test.cjs` for:
|
||||
- map build order
|
||||
- map lookup null/renderer behavior
|
||||
- resolver precedence behavior
|
||||
- Expanded `tests/phase22/breadcrumbs-route-map-structure.test.cjs` to assert:
|
||||
- component imports shared breadcrumb route-map helper module
|
||||
- resolver delegation uses helper module
|
||||
- map builder call preserves explicit ordering (simple -> link-text -> myportal)
|
||||
- Updated `tests/phase22/index.test.cjs` to include the new helper suite.
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint 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; breadcrumb-route-maps-helper 3/3; breadcrumbs-route-map 3/3).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next slice option A (larger): move per-path map object declarations out of `components/breadcrumbs.js` into module-level pure factories (still injected with `t/router/currentView`) to further shrink component body.
|
||||
- Next slice option B (smaller): add one focused parity test asserting mapped resolver fallback returns `null` in component rendering path for non-mapped routes (ensures no accidental render noise).
|
||||
|
||||
### CL-22541-R: breadcrumbs mapped-group factory composition + unmapped-route null parity guard
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `lib/routing/breadcrumbRendererFactories.js`, `components/breadcrumbs.js`, `tests/phase22/breadcrumbs-route-map-structure.test.cjs`
|
||||
type: change
|
||||
rationale: Execute both approved next slices in one commit by centralizing deterministic mapped route-group composition into a factory-level helper and adding explicit structure guard coverage for null fallback behavior on unmapped routes.
|
||||
impact: Refactor-only structural consolidation and test hardening; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added `createMappedRouteRendererGroups(...)` in `lib/routing/breadcrumbRendererFactories.js` to compose and return all deterministic mapped renderer groups in one place:
|
||||
- `simpleRouteRenderersByPath`
|
||||
- `simpleLinkTextPairRenderersByPath`
|
||||
- `simpleMyPortalRouteRenderersByPath`
|
||||
- `caseDetailRouteRenderersByPath`
|
||||
- `detailAndAccountRouteRenderersByPath`
|
||||
- Updated `components/breadcrumbs.js` to consume `createMappedRouteRendererGroups(...)` and remove local per-group factory composition boilerplate while preserving existing map precedence and resolver flow.
|
||||
- Expanded `tests/phase22/breadcrumbs-route-map-structure.test.cjs` to assert:
|
||||
- grouped renderer maps are composed via `createMappedRouteRendererGroups(...)`
|
||||
- mapped rendering path explicitly preserves null fallback (`routeRenderer ? routeRenderer() : null`)
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint lib/routing/breadcrumbRendererFactories.js components/breadcrumbs.js tests/phase22/breadcrumbs-route-map-structure.test.cjs tests/phase22/breadcrumb-route-maps-helper.test.cjs tests/phase22/index.test.cjs` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite; breadcrumbs-route-map 4/4).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next slice option A (larger): extract remaining deterministic inline branches (`/myportal/case`, `/case/id/[incident]` if kept deterministic after constraints review) only if they remain callback/state free.
|
||||
- Next slice option B (smaller): add one focused assertion in helper-level tests that empty grouped map entries are tolerated without affecting precedence resolution.
|
||||
|
||||
### CL-22541-S: breadcrumbs deterministic case-branch extraction (`/myportal/case`, `/case/id/[incident]`)
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `lib/routing/breadcrumbRendererFactories.js`, `components/breadcrumbs.js`, `tests/phase22/breadcrumbs-route-map-structure.test.cjs`
|
||||
type: change
|
||||
rationale: Execute the next deterministic extraction slice by migrating remaining callback-free case breadcrumb branches into the case-detail factory group while preserving map precedence and leaving stateful/callback routes inline.
|
||||
impact: Refactor-only structural extraction and test guardrail expansion; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Extended `createCaseDetailRouteRenderers(...)` in `lib/routing/breadcrumbRendererFactories.js` to map:
|
||||
- `/myportal/case`
|
||||
- `/case/id/[incident]`
|
||||
- Injected additional deterministic inputs required by these routes:
|
||||
- `currentReference`
|
||||
- `nestedSearchString`
|
||||
- Updated `createMappedRouteRendererGroups(...)` wiring to pass the new inputs to case-detail factory composition.
|
||||
- Updated `components/breadcrumbs.js` to pass `nestedSearchString` into grouped factory composition.
|
||||
- Removed now-redundant inline `isPath(...)` branches for:
|
||||
- `/myportal/case`
|
||||
- `/case/id/[incident]`
|
||||
- Expanded `tests/phase22/breadcrumbs-route-map-structure.test.cjs` to assert:
|
||||
- both new routes are mapped in `createCaseDetailRouteRenderers`
|
||||
- both inline branches are absent from `components/breadcrumbs.js`
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint lib/routing/breadcrumbRendererFactories.js components/breadcrumbs.js tests/phase22/breadcrumbs-route-map-structure.test.cjs tests/phase22/index.test.cjs` -> pass.
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite; breadcrumbs-route-map 4/4).
|
||||
|
||||
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 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-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-22541-V: breadcrumbs larger slice — callback route-group extraction (`/myportal/case/id/[incident]`, `/case`)
|
||||
|
||||
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 extraction slice by moving callback-bearing breadcrumb branches into a dedicated callback renderer map while preserving `router.back()` behavior through explicit callback injection.
|
||||
impact: Structural refactor with preserved callback semantics; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added `createCallbackRouteRenderers(...)` in `lib/routing/breadcrumbRendererFactories.js` to map:
|
||||
- `/myportal/case/id/[incident]`
|
||||
- `/case`
|
||||
- Introduced explicit callback injection (`onBack`) into grouped factory composition and route renderers, preserving `router.back()` behavior via injected callback.
|
||||
- Extended `createMappedRouteRendererGroups(...)` return with `callbackRouteRenderersByPath`.
|
||||
- Updated map builder in `lib/routing/breadcrumbRouteMaps.js` to include callback map in explicit precedence order:
|
||||
- simple -> link-text -> myportal -> new-appeal -> callback -> case detail -> detail/account.
|
||||
- Updated `components/breadcrumbs.js`:
|
||||
- pass `onBack: () => { router.back(); }` into grouped factory composition
|
||||
- include callback route map in `buildBreadcrumbRendererMaps(...)`
|
||||
- remove now-redundant inline `isPath("/myportal/case/id/[incident]")` and `isPath("/case")` branches.
|
||||
- Expanded tests:
|
||||
- `tests/phase22/breadcrumb-route-maps-helper.test.cjs`
|
||||
- update grouped map order assertions to seven maps including callback group.
|
||||
- `tests/phase22/breadcrumbs-route-map-structure.test.cjs`
|
||||
- assert callback factory export and mapped callback route presence
|
||||
- assert callback map inclusion in component grouped destructuring and map-order invariant
|
||||
- assert inline callback branches are removed while `router.back();` remains preserved.
|
||||
|
||||
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 smaller slice candidate: add a focused helper test for empty-string/whitespace path lookups to assert strict null behavior for non-exact keys.
|
||||
- Next larger slice candidate: evaluate whether `/newappeal/[appealtypes]` and `/myportal/[appealtypes]` back-link branches can be extracted with explicit callback/setter injection while preserving state-step semantics.
|
||||
|
||||
### CL-22541-W: breadcrumbs larger slice — step-back route-group extraction (`/newappeal/[appealtypes]`, `/myportal/[appealtypes]`)
|
||||
|
||||
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 extraction slice by moving step-based back-link branches into a dedicated mapped route group with explicit setter callback injection, preserving section-navigation semantics.
|
||||
impact: Structural refactor with preserved back-link and step-state behavior; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added `createStepBackRouteRenderers(...)` in `lib/routing/breadcrumbRendererFactories.js` to map:
|
||||
- `/newappeal/[appealtypes]`
|
||||
- `/myportal/[appealtypes]`
|
||||
- Preserved existing step semantics in mapped handlers:
|
||||
- no crumb when `currentSection <= 1`
|
||||
- service-name crumb when `currentSection === 9999`
|
||||
- back-link crumb with existing class parity (`govuk-breadcrumbs__link-item` for new-appeal flow)
|
||||
- Introduced explicit injected handlers (`onStepBack`, `onStepBackWithInlineClass`) and injected crumb renderer dependency (`renderBackCrumb`) into grouped factory composition.
|
||||
- Extended map builder in `lib/routing/breadcrumbRouteMaps.js` with `stepBackRouteRenderersByPath` and updated precedence order:
|
||||
- simple -> link-text -> myportal -> new-appeal -> callback -> step-back -> case detail -> detail/account.
|
||||
- Updated `components/breadcrumbs.js`:
|
||||
- pass `currentSection` and step-back callbacks into `createMappedRouteRendererGroups(...)`
|
||||
- include step-back map in `buildBreadcrumbRendererMaps(...)`
|
||||
- remove inline `isPath("/newappeal/[appealtypes]")` and `isPath("/myportal/[appealtypes]")` branches.
|
||||
- Expanded tests:
|
||||
- `tests/phase22/breadcrumb-route-maps-helper.test.cjs`
|
||||
- updated grouped map count/order to include step-back map (8 total)
|
||||
- `tests/phase22/breadcrumbs-route-map-structure.test.cjs`
|
||||
- assert step-back factory export + mapped route presence
|
||||
- assert grouped destructuring includes step-back map
|
||||
- assert inline step-back branches are removed
|
||||
- assert updated map-order invariant includes step-back group.
|
||||
|
||||
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 smaller slice candidate: add focused helper test for strict null behavior on empty-string/whitespace/non-exact path keys.
|
||||
- Next larger slice candidate: evaluate extractability of `/myportal/representation` back-link states via explicit callback injection, only if questionnaire/submit side-effects remain parity-safe and readable.
|
||||
|
||||
### CL-22541-X: breadcrumbs smaller slice — strict null lookup guard coverage (empty/whitespace/non-exact paths)
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `tests/phase22/breadcrumb-route-maps-helper.test.cjs`
|
||||
type: change
|
||||
rationale: Execute the queued smaller follow-up slice by hardening helper regression coverage for strict exact-match route lookup semantics.
|
||||
impact: Test-only hardening; no runtime route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added focused helper-level test case in `tests/phase22/breadcrumb-route-maps-helper.test.cjs`:
|
||||
- `resolveMappedRouteRenderer returns null for empty, whitespace, and non-exact path variants`
|
||||
- New assertions verify resolver returns `null` for:
|
||||
- empty path (`""`)
|
||||
- whitespace-only path (`" "`)
|
||||
- trailing/leading whitespace variants (`"/known "`, `" /known"`)
|
||||
- case-variant non-exact key (`"/KNOWN"`)
|
||||
- Confirms route-map resolver remains strict/exact and does not auto-trim or case-normalize lookup keys.
|
||||
|
||||
Validation:
|
||||
|
||||
- `npx eslint 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 6/6).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Next larger slice candidate remains `/myportal/representation` callback/state branch extraction only if side-effects can be injected/parity-preserved cleanly.
|
||||
|
||||
### CL-22541-Y: breadcrumbs larger slice — representation route-group extraction (`/myportal/representation`)
|
||||
|
||||
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 queued larger follow-up slice by extracting `/myportal/representation` callback/state breadcrumb branches into a dedicated mapped route group with explicit callback injection while preserving questionnaire/submit side-effects.
|
||||
impact: Structural refactor with preserved representation back-link state behavior; no intended route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added `createRepresentationRouteRenderers(...)` in `lib/routing/breadcrumbRendererFactories.js` mapping:
|
||||
- `/myportal/representation`
|
||||
- Preserved existing representation-state semantics in mapped handler:
|
||||
- submit/back from confirmation (`setRepresentationSubmit(qcount)`)
|
||||
- non-questionnaire back path (`setRepresentationSubmit(false)`)
|
||||
- questionnaire step-back path (`setShowQuestionnaireSection(showQuestionnaireSection - 1)` + `setRepresentationSubmit(false)`)
|
||||
- Introduced explicit injected state/callback dependencies into grouped composition:
|
||||
- `currentView`, `hasRepDetails`, `repDetails`, `showQuestionnaireSection`
|
||||
- `onRepresentationSubmitBackFromConfirmation`
|
||||
- `onRepresentationSubmitBackToDetails`
|
||||
- `onRepresentationQuestionnaireBack`
|
||||
- Extended `buildBreadcrumbRendererMaps(...)` in `lib/routing/breadcrumbRouteMaps.js` with `representationRouteRenderersByPath` and updated precedence order:
|
||||
- simple -> link-text -> myportal -> new-appeal -> callback -> step-back -> representation -> case detail -> detail/account.
|
||||
- Updated `components/breadcrumbs.js`:
|
||||
- pass representation state/callback injections into `createMappedRouteRendererGroups(...)`
|
||||
- include `representationRouteRenderersByPath` in map builder call
|
||||
- remove inline `isPath("/myportal/representation")` branch block.
|
||||
- Expanded tests:
|
||||
- `tests/phase22/breadcrumb-route-maps-helper.test.cjs`
|
||||
- updated map-count/order assertions to include representation group (9 total)
|
||||
- updated map build fixtures to include `representationRouteRenderersByPath`
|
||||
- `tests/phase22/breadcrumbs-route-map-structure.test.cjs`
|
||||
- assert representation factory export + mapped route presence
|
||||
- assert grouped destructuring includes representation map
|
||||
- assert inline representation branch removal
|
||||
- assert updated map-order invariant includes representation group.
|
||||
|
||||
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 smaller slice candidate: helper-level assertion for missing/undefined representation dependency values yielding no renderer output regressions.
|
||||
- Next larger slice candidate: evaluate whether remaining `/newappeal` edge branch can be absorbed into mapped grouping without reducing readability or explicitness.
|
||||
|
||||
### CL-22541-Z: breadcrumbs closure slice 1 — mapped-route precedence/callback invariants decision
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `memory-bank/decisions.md`
|
||||
type: change
|
||||
rationale: Execute closure slice 1 by documenting explicit architectural invariants for breadcrumb mapped-route precedence and callback injection contracts so future refactors remain safe and auditable.
|
||||
impact: Documentation/governance hardening only; no runtime route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added `D-006` to `memory-bank/decisions.md`.
|
||||
- Captured accepted invariant contracts for:
|
||||
- explicit breadcrumb map precedence ordering (9 groups)
|
||||
- callback/state behavior dependency injection requirement (no ad-hoc inline reintroduction)
|
||||
- structure test guardrails as contract checks for intentional future changes.
|
||||
|
||||
Validation:
|
||||
|
||||
- Documentation consistency review against current breadcrumb map structure and phase22 structure test expectations.
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Closure slice 2: add focused negative-path representation map/dependency tolerance test coverage.
|
||||
- Closure slice 3: resolve and guard remaining `/newappeal` inline edge branch treatment.
|
||||
|
||||
### CL-22541-Z2: breadcrumbs closure slice 2 — missing representation map negative-path guard
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `tests/phase22/breadcrumb-route-maps-helper.test.cjs`
|
||||
type: change
|
||||
rationale: Execute closure slice 2 by adding focused negative-path coverage ensuring resolver behavior remains stable when representation route-map dependency is missing from grouped map input.
|
||||
impact: Test hardening only; no runtime route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Added focused helper-level test:
|
||||
- `resolveMappedRouteRenderer tolerates missing representation map entry in grouped map input`
|
||||
- New assertions verify:
|
||||
- missing `representationRouteRenderersByPath` resolves `/myportal/representation` to `null`
|
||||
- later maps still resolve correctly (case detail fallback remains intact).
|
||||
|
||||
Validation:
|
||||
|
||||
- `node tests/phase22/breadcrumb-route-maps-helper.test.cjs` -> pass (7/7).
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Closure slice 3: resolve and guard remaining `/newappeal` inline edge branch treatment.
|
||||
|
||||
### CL-22541-Z3: breadcrumbs closure slice 3 — remove lingering `/newappeal` no-op inline branch
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`, `tests/phase22/breadcrumbs-route-map-structure.test.cjs`
|
||||
type: change
|
||||
rationale: Execute closure slice 3 by resolving the remaining inline `/newappeal` edge branch (a no-op render guard) and locking its removal with explicit structure coverage.
|
||||
impact: Refactor/test hardening only; no runtime route/auth/session/API/EN-CY/a11y behavior change.
|
||||
status: completed
|
||||
|
||||
Summary:
|
||||
|
||||
- Removed lingering no-op branch from breadcrumbs JSX:
|
||||
- deleted `{isPath("/newappeal") && <></>}`
|
||||
- Added structure guard assertion that `/newappeal` inline branch is absent.
|
||||
|
||||
Validation:
|
||||
|
||||
- `node tests/phase22/breadcrumbs-route-map-structure.test.cjs` -> pass (4/4).
|
||||
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
|
||||
|
||||
Follow-ups:
|
||||
|
||||
- Breadcrumb route-state extraction closure slices (1/2/3) complete.
|
||||
|
||||
### CL-00X: 22500 `components/elements/index.js` Phase 1 helper extraction
|
||||
|
||||
date: 2026-04-07
|
||||
|
||||
@@ -170,3 +170,40 @@ Related:
|
||||
- `context/test-coverage-map.md`
|
||||
- `context/current-state-scorecard.md`
|
||||
- `memory-bank/open-questions.md` (Q-002)
|
||||
|
||||
---
|
||||
|
||||
### D-006: Breadcrumb mapped-route precedence and callback injection invariants
|
||||
|
||||
date: 2026-04-09
|
||||
author: Cline
|
||||
scope: `components/breadcrumbs.js`, `lib/routing/{breadcrumbRendererFactories,breadcrumbRouteMaps}.js`, `tests/phase22/breadcrumbs-route-map-structure.test.cjs`
|
||||
type: decision
|
||||
rationale: Priority 3 route-state extraction moved most breadcrumb behavior into grouped mapped renderers; explicit invariants are required so future refactors do not silently reorder precedence or regress callback/state behavior.
|
||||
impact: Improves regression safety for search/case/myportal navigation by making map-order and callback injection constraints explicit.
|
||||
status: accepted
|
||||
|
||||
Decision:
|
||||
|
||||
- Preserve explicit mapped renderer precedence in this order unless a tested migration plan is approved:
|
||||
1. `simpleRouteRenderersByPath`
|
||||
2. `simpleLinkTextPairRenderersByPath`
|
||||
3. `simpleMyPortalRouteRenderersByPath`
|
||||
4. `newAppealRouteRenderersByPath`
|
||||
5. `callbackRouteRenderersByPath`
|
||||
6. `stepBackRouteRenderersByPath`
|
||||
7. `representationRouteRenderersByPath`
|
||||
8. `caseDetailRouteRenderersByPath`
|
||||
9. `detailAndAccountRouteRenderersByPath`
|
||||
- Callback/stateful breadcrumb behavior must be dependency-injected into factory groups (e.g. `onBack`, step-back callbacks, representation submit/questionnaire callbacks) rather than recreated as ad-hoc inline path branches.
|
||||
- Structural guardrails in `tests/phase22/breadcrumbs-route-map-structure.test.cjs` are considered contract tests for these invariants and must be updated in the same commit as intentional precedence/callback changes.
|
||||
|
||||
Consequences:
|
||||
|
||||
- Future breadcrumb extraction work remains predictable and test-auditable.
|
||||
- Accidental map-order drift or callback behavior inlining should be caught early by structure/helper tests.
|
||||
|
||||
Related:
|
||||
|
||||
- `memory-bank/change-log.md` (CL-22541-V, CL-22541-W, CL-22541-Y)
|
||||
- `tests/phase22/breadcrumbs-route-map-structure.test.cjs`
|
||||
|
||||
@@ -21,7 +21,7 @@ const loadAuthInternals = () => {
|
||||
source = source.replace(/import[\s\S]*?from\s+"[^"]+";\n?/g, "");
|
||||
source = source.replace(
|
||||
/export default NextAuthPEDW;\s*$/,
|
||||
"module.exports = { appendParamsAndPathToNewUrl, resolveLocale, authOptions, NextAuthPEDW };"
|
||||
"module.exports = { appendParamsAndPathToNewUrl, resolveRequestLocale, authOptions, NextAuthPEDW };"
|
||||
);
|
||||
|
||||
const context = {
|
||||
@@ -68,11 +68,11 @@ const loadAuthInternals = () => {
|
||||
return context.module.exports;
|
||||
};
|
||||
|
||||
test("auth/resolveLocale prefers query then body then cookie then default", async () => {
|
||||
test("auth/resolveRequestLocale prefers query then body then cookie then default", async () => {
|
||||
const mod = loadAuthInternals();
|
||||
|
||||
assert.strictEqual(
|
||||
mod.resolveLocale({
|
||||
mod.resolveRequestLocale({
|
||||
query: { locale: "cy" },
|
||||
body: { locale: "en" },
|
||||
cookies: { pedw_locale: "en" }
|
||||
@@ -81,7 +81,7 @@ test("auth/resolveLocale prefers query then body then cookie then default", asyn
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
mod.resolveLocale({
|
||||
mod.resolveRequestLocale({
|
||||
body: { locale: "cy" },
|
||||
cookies: { pedw_locale: "en" }
|
||||
}),
|
||||
@@ -89,13 +89,13 @@ test("auth/resolveLocale prefers query then body then cookie then default", asyn
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
mod.resolveLocale({
|
||||
mod.resolveRequestLocale({
|
||||
cookies: { pedw_locale: "cy" }
|
||||
}),
|
||||
"cy"
|
||||
);
|
||||
|
||||
assert.strictEqual(mod.resolveLocale({}), "en");
|
||||
assert.strictEqual(mod.resolveRequestLocale({}), "en");
|
||||
});
|
||||
|
||||
test("auth/redirect callback keeps relative URLs on same base", async () => {
|
||||
|
||||
@@ -0,0 +1,365 @@
|
||||
const assert = require("assert");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const vm = require("vm");
|
||||
|
||||
const tests = [];
|
||||
const test = (name, fn) => tests.push({ name, fn });
|
||||
|
||||
const helperModulePath = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"lib",
|
||||
"routing",
|
||||
"breadcrumbRouteMaps.js"
|
||||
);
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
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 newAppealRouteRenderersByPath = {
|
||||
"/eta": () => "eta"
|
||||
};
|
||||
const callbackRouteRenderersByPath = {
|
||||
"/theta": () => "theta"
|
||||
};
|
||||
const stepBackRouteRenderersByPath = {
|
||||
"/iota": () => "iota"
|
||||
};
|
||||
const representationRouteRenderersByPath = {
|
||||
"/kappa": () => "kappa"
|
||||
};
|
||||
const caseDetailRouteRenderersByPath = {
|
||||
"/delta": () => "delta"
|
||||
};
|
||||
const detailAndAccountRouteRenderersByPath = {
|
||||
"/epsilon": () => "epsilon"
|
||||
};
|
||||
|
||||
const result = buildBreadcrumbRendererMaps({
|
||||
simpleRouteRenderersByPath,
|
||||
simpleLinkTextPairRenderersByPath,
|
||||
simpleMyPortalRouteRenderersByPath,
|
||||
newAppealRouteRenderersByPath,
|
||||
callbackRouteRenderersByPath,
|
||||
stepBackRouteRenderersByPath,
|
||||
representationRouteRenderersByPath,
|
||||
caseDetailRouteRenderersByPath,
|
||||
detailAndAccountRouteRenderersByPath
|
||||
});
|
||||
|
||||
assert.ok(Array.isArray(result), "Expected grouped maps array");
|
||||
assert.strictEqual(result.length, 9, "Expected nine 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"
|
||||
);
|
||||
assert.strictEqual(
|
||||
result[3],
|
||||
newAppealRouteRenderersByPath,
|
||||
"Expected new-appeal route renderers fourth"
|
||||
);
|
||||
assert.strictEqual(
|
||||
result[4],
|
||||
callbackRouteRenderersByPath,
|
||||
"Expected callback route renderers fifth"
|
||||
);
|
||||
assert.strictEqual(
|
||||
result[5],
|
||||
stepBackRouteRenderersByPath,
|
||||
"Expected step-back route renderers sixth"
|
||||
);
|
||||
assert.strictEqual(
|
||||
result[6],
|
||||
representationRouteRenderersByPath,
|
||||
"Expected representation route renderers seventh"
|
||||
);
|
||||
assert.strictEqual(
|
||||
result[7],
|
||||
caseDetailRouteRenderersByPath,
|
||||
"Expected case detail route renderers eighth"
|
||||
);
|
||||
assert.strictEqual(
|
||||
result[8],
|
||||
detailAndAccountRouteRenderersByPath,
|
||||
"Expected detail and account route renderers ninth"
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveMappedRouteRenderer returns renderer from first matching grouped map", () => {
|
||||
const { buildBreadcrumbRendererMaps, resolveMappedRouteRenderer } =
|
||||
loadHelpers();
|
||||
|
||||
const firstRenderer = () => "first";
|
||||
const secondRenderer = () => "second";
|
||||
|
||||
const maps = buildBreadcrumbRendererMaps({
|
||||
simpleRouteRenderersByPath: {
|
||||
"/known": firstRenderer
|
||||
},
|
||||
simpleLinkTextPairRenderersByPath: {
|
||||
"/known": secondRenderer
|
||||
},
|
||||
simpleMyPortalRouteRenderersByPath: {},
|
||||
newAppealRouteRenderersByPath: {},
|
||||
callbackRouteRenderersByPath: {},
|
||||
stepBackRouteRenderersByPath: {},
|
||||
representationRouteRenderersByPath: {},
|
||||
caseDetailRouteRenderersByPath: {},
|
||||
detailAndAccountRouteRenderersByPath: {}
|
||||
});
|
||||
|
||||
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 detailRenderer = () => "detail";
|
||||
|
||||
const maps = buildBreadcrumbRendererMaps({
|
||||
simpleRouteRenderersByPath: {},
|
||||
simpleLinkTextPairRenderersByPath: {},
|
||||
newAppealRouteRenderersByPath: {
|
||||
"/newappeal/selectappeal": () => "newappeal"
|
||||
},
|
||||
simpleMyPortalRouteRenderersByPath: {},
|
||||
caseDetailRouteRenderersByPath: {},
|
||||
callbackRouteRenderersByPath: {},
|
||||
stepBackRouteRenderersByPath: {},
|
||||
representationRouteRenderersByPath: {},
|
||||
detailAndAccountRouteRenderersByPath: {
|
||||
"/account/personaldetails": detailRenderer
|
||||
}
|
||||
});
|
||||
|
||||
const result = resolveMappedRouteRenderer("/account/personaldetails", maps);
|
||||
|
||||
assert.strictEqual(
|
||||
result,
|
||||
detailRenderer,
|
||||
"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: {},
|
||||
newAppealRouteRenderersByPath: {},
|
||||
callbackRouteRenderersByPath: {},
|
||||
stepBackRouteRenderersByPath: {},
|
||||
representationRouteRenderersByPath: {},
|
||||
caseDetailRouteRenderersByPath: {},
|
||||
detailAndAccountRouteRenderersByPath: {}
|
||||
});
|
||||
|
||||
const result = resolveMappedRouteRenderer("/unknown", maps);
|
||||
|
||||
assert.strictEqual(
|
||||
result,
|
||||
null,
|
||||
"Expected null when no grouped map contains the path"
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveMappedRouteRenderer returns null for empty, whitespace, and non-exact path variants", () => {
|
||||
const { buildBreadcrumbRendererMaps, resolveMappedRouteRenderer } =
|
||||
loadHelpers();
|
||||
|
||||
const knownRenderer = () => "known";
|
||||
|
||||
const maps = buildBreadcrumbRendererMaps({
|
||||
simpleRouteRenderersByPath: {
|
||||
"/known": knownRenderer
|
||||
},
|
||||
simpleLinkTextPairRenderersByPath: {},
|
||||
simpleMyPortalRouteRenderersByPath: {},
|
||||
newAppealRouteRenderersByPath: {},
|
||||
callbackRouteRenderersByPath: {},
|
||||
stepBackRouteRenderersByPath: {},
|
||||
representationRouteRenderersByPath: {},
|
||||
caseDetailRouteRenderersByPath: {},
|
||||
detailAndAccountRouteRenderersByPath: {}
|
||||
});
|
||||
|
||||
assert.strictEqual(
|
||||
resolveMappedRouteRenderer("", maps),
|
||||
null,
|
||||
"Expected null for empty path lookup when no empty key is mapped"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
resolveMappedRouteRenderer(" ", maps),
|
||||
null,
|
||||
"Expected null for whitespace-only path lookup"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
resolveMappedRouteRenderer("/known ", maps),
|
||||
null,
|
||||
"Expected null for non-exact path variant with trailing whitespace"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
resolveMappedRouteRenderer(" /known", maps),
|
||||
null,
|
||||
"Expected null for non-exact path variant with leading whitespace"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
resolveMappedRouteRenderer("/KNOWN", maps),
|
||||
null,
|
||||
"Expected null for non-exact case-variant path lookup"
|
||||
);
|
||||
});
|
||||
|
||||
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,
|
||||
callbackRouteRenderersByPath: {},
|
||||
stepBackRouteRenderersByPath: {},
|
||||
representationRouteRenderersByPath: {},
|
||||
caseDetailRouteRenderersByPath: {},
|
||||
detailAndAccountRouteRenderersByPath: {}
|
||||
});
|
||||
|
||||
const result = resolveMappedRouteRenderer("/known", maps);
|
||||
|
||||
assert.strictEqual(
|
||||
result,
|
||||
validRenderer,
|
||||
"Expected resolver to skip invalid/non-function entries and return first valid renderer"
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveMappedRouteRenderer tolerates missing representation map entry in grouped map input", () => {
|
||||
const { buildBreadcrumbRendererMaps, resolveMappedRouteRenderer } =
|
||||
loadHelpers();
|
||||
|
||||
const caseDetailRenderer = () => "case-detail";
|
||||
|
||||
const maps = buildBreadcrumbRendererMaps({
|
||||
simpleRouteRenderersByPath: {},
|
||||
simpleLinkTextPairRenderersByPath: {},
|
||||
simpleMyPortalRouteRenderersByPath: {},
|
||||
newAppealRouteRenderersByPath: {},
|
||||
callbackRouteRenderersByPath: {},
|
||||
stepBackRouteRenderersByPath: {},
|
||||
representationRouteRenderersByPath: undefined,
|
||||
caseDetailRouteRenderersByPath: {
|
||||
"/case/[ticketnumber]": caseDetailRenderer
|
||||
},
|
||||
detailAndAccountRouteRenderersByPath: {}
|
||||
});
|
||||
|
||||
assert.strictEqual(
|
||||
resolveMappedRouteRenderer("/myportal/representation", maps),
|
||||
null,
|
||||
"Expected null when representation renderer map is missing"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
resolveMappedRouteRenderer("/case/[ticketnumber]", maps),
|
||||
caseDetailRenderer,
|
||||
"Expected later grouped map resolution to remain intact when representation map is missing"
|
||||
);
|
||||
});
|
||||
|
||||
const run = async () => {
|
||||
let passed = 0;
|
||||
|
||||
for (const currentTest of tests) {
|
||||
await currentTest.fn();
|
||||
passed += 1;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Phase 22 breadcrumb-route-maps-helper tests passed (${passed}/${tests.length}).`
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = run;
|
||||
|
||||
if (require.main === module) {
|
||||
run().catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,527 @@
|
||||
const assert = require("assert");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const tests = [];
|
||||
const test = (name, fn) => tests.push({ name, fn });
|
||||
|
||||
const loadSource = (...parts) => {
|
||||
const filePath = path.join(__dirname, "..", "..", ...parts);
|
||||
return fs.readFileSync(filePath, "utf8");
|
||||
};
|
||||
|
||||
const loadBreadcrumbSource = () => loadSource("components", "breadcrumbs.js");
|
||||
|
||||
const loadFactorySource = () =>
|
||||
loadSource("lib", "routing", "breadcrumbRendererFactories.js");
|
||||
|
||||
test("breadcrumbs/factory module includes expected mapped route definitions", async () => {
|
||||
const source = loadFactorySource();
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes("export const createSimpleRouteRenderers ="),
|
||||
true,
|
||||
"Expected simple route renderer factory export"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes("export const createSimpleLinkTextPairRenderers ="),
|
||||
true,
|
||||
"Expected link-text pair renderer factory export"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes("export const createSimpleMyPortalRouteRenderers ="),
|
||||
true,
|
||||
"Expected my-portal route renderer factory export"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes("export const createNewAppealRouteRenderers ="),
|
||||
true,
|
||||
"Expected new-appeal route renderer factory export"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes("export const createCallbackRouteRenderers ="),
|
||||
true,
|
||||
"Expected callback route renderer factory export"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes("export const createStepBackRouteRenderers ="),
|
||||
true,
|
||||
"Expected step-back route renderer factory export"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes("export const createRepresentationRouteRenderers ="),
|
||||
true,
|
||||
"Expected representation route renderer factory export"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes("export const createCaseDetailRouteRenderers ="),
|
||||
true,
|
||||
"Expected case detail route renderer factory export"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes("export const createDetailAndAccountRouteRenderers ="),
|
||||
true,
|
||||
"Expected detail and account route renderer factory export"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/addresssearchresults": () => ('),
|
||||
true,
|
||||
"Expected /addresssearchresults to be mapped in createSimpleLinkTextPairRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/advancedsearchresults": () => ('),
|
||||
true,
|
||||
"Expected /advancedsearchresults to be mapped in createSimpleLinkTextPairRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/myportal/searchresults": () => ('),
|
||||
true,
|
||||
"Expected /myportal/searchresults to be mapped in createSimpleMyPortalRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/myportal/viewall": () =>'),
|
||||
true,
|
||||
"Expected /myportal/viewall to be mapped in createSimpleMyPortalRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/myportal/advancedsearchresults": () => ('),
|
||||
true,
|
||||
"Expected /myportal/advancedsearchresults to be mapped in createSimpleMyPortalRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/myportal/addresssearchresults": () => ('),
|
||||
true,
|
||||
"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(
|
||||
source.includes('"/myportal/case/id/[incident]": () => ('),
|
||||
true,
|
||||
"Expected /myportal/case/id/[incident] to be mapped in createCallbackRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/case": () => ('),
|
||||
true,
|
||||
"Expected /case to be mapped in createCallbackRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/newappeal/[appealtypes]": () => {'),
|
||||
true,
|
||||
"Expected /newappeal/[appealtypes] to be mapped in createStepBackRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/myportal/[appealtypes]": () => {'),
|
||||
true,
|
||||
"Expected /myportal/[appealtypes] to be mapped in createStepBackRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/myportal/representation": () => ('),
|
||||
true,
|
||||
"Expected /myportal/representation to be mapped in createRepresentationRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/case/[ticketnumber]": () =>'),
|
||||
true,
|
||||
"Expected /case/[ticketnumber] to be mapped in createCaseDetailRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/myportal/case": () =>'),
|
||||
true,
|
||||
"Expected /myportal/case to be mapped in createCaseDetailRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/case/id/[incident]": () =>'),
|
||||
true,
|
||||
"Expected /case/id/[incident] to be mapped in createCaseDetailRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/myportal/case/[ticketnumber]": () =>'),
|
||||
true,
|
||||
"Expected /myportal/case/[ticketnumber] to be mapped in createCaseDetailRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/myportal/dnsdetails": () =>'),
|
||||
true,
|
||||
"Expected /myportal/dnsdetails to be mapped in createDetailAndAccountRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/myportal/dns/[developmentName]": () =>'),
|
||||
true,
|
||||
"Expected /myportal/dns/[developmentName] to be mapped in createDetailAndAccountRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/dnsdetails": () =>'),
|
||||
true,
|
||||
"Expected /dnsdetails to be mapped in createDetailAndAccountRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/dns/[developmentName]": () =>'),
|
||||
true,
|
||||
"Expected /dns/[developmentName] to be mapped in createDetailAndAccountRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/dns/application-view": () =>'),
|
||||
true,
|
||||
"Expected /dns/application-view to be mapped in createDetailAndAccountRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/account/personaldetails": () =>'),
|
||||
true,
|
||||
"Expected /account/personaldetails to be mapped in createDetailAndAccountRouteRenderers"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('"/account/changepassword": () =>'),
|
||||
true,
|
||||
"Expected /account/changepassword to be mapped in createDetailAndAccountRouteRenderers"
|
||||
);
|
||||
});
|
||||
|
||||
test("breadcrumbs/component composes mapped routes via imported factories and shared resolver", async () => {
|
||||
const source = loadBreadcrumbSource();
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('from "../lib/routing/breadcrumbRouteMaps"'),
|
||||
true,
|
||||
"Expected breadcrumbs to import shared breadcrumb route-map helper module"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('from "../lib/routing/breadcrumbRendererFactories"'),
|
||||
true,
|
||||
"Expected breadcrumbs to import breadcrumb renderer factories"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
/createMappedRouteRendererGroups/.test(source),
|
||||
true,
|
||||
"Expected breadcrumbs to reference createMappedRouteRendererGroups"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
/const\s+\{[\s\S]*simpleRouteRenderersByPath[\s\S]*newAppealRouteRenderersByPath[\s\S]*callbackRouteRenderersByPath[\s\S]*stepBackRouteRenderersByPath[\s\S]*representationRouteRenderersByPath[\s\S]*detailAndAccountRouteRenderersByPath[\s\S]*\}\s*=\s*createMappedRouteRendererGroups\s*\(/.test(
|
||||
source
|
||||
),
|
||||
true,
|
||||
"Expected breadcrumbs to compose grouped renderer maps via createMappedRouteRendererGroups"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
/const\s+mappedRouteRendererMaps\s*=\s*buildBreadcrumbRendererMaps\s*\(/.test(
|
||||
source
|
||||
),
|
||||
true,
|
||||
"Expected grouped mapped route renderer map composition to use helper builder"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
/return\s+resolveMappedRouteRendererByMaps\s*\(\s*path\s*,\s*mappedRouteRendererMaps\s*\)/.test(
|
||||
source
|
||||
),
|
||||
true,
|
||||
"Expected resolver to delegate to shared route-map resolver helper"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
/const\s+resolveMappedRouteRenderer\s*=\s*\(\s*path\s*\)\s*=>/.test(
|
||||
source
|
||||
),
|
||||
true,
|
||||
"Expected unified mapped route resolver helper to exist"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
/const\s+renderMappedRoute\s*=\s*\(\s*path\s*,\s*resolver\s*=\s*resolveMappedRouteRenderer\s*\)\s*=>/.test(
|
||||
source
|
||||
),
|
||||
true,
|
||||
"Expected reusable renderMappedRoute helper to exist"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes("return routeRenderer ? routeRenderer() : null;"),
|
||||
true,
|
||||
"Expected mapped renderer flow to return null for unmapped routes"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes("{renderMappedRoute(pathname)}"),
|
||||
true,
|
||||
"Expected breadcrumb JSX to use single mapped route render invocation"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes("const viewAllLabelResolver = labelsByKey[viewKey];"),
|
||||
true,
|
||||
"Expected view-all label lookup to resolve callable/non-callable map entries"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('return typeof viewAllLabelResolver === "function"'),
|
||||
true,
|
||||
"Expected view-all label resolver to invoke function-backed labels"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes(
|
||||
"const staticTextCrumbResolver = staticTextCrumbByPath[path];"
|
||||
),
|
||||
true,
|
||||
"Expected static text breadcrumb path lookup to resolve a callable label renderer"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes(
|
||||
"return staticTextCrumbResolver ? staticTextCrumbResolver() : null;"
|
||||
),
|
||||
true,
|
||||
"Expected static text breadcrumb resolver to invoke mapped label function"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/myportal/advancedsearchresults")'),
|
||||
false,
|
||||
"Expected /myportal/advancedsearchresults explicit branch to be removed after mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/myportal/addresssearchresults")'),
|
||||
false,
|
||||
"Expected /myportal/addresssearchresults explicit branch to be removed after mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/case/[ticketnumber]")'),
|
||||
false,
|
||||
"Expected /case/[ticketnumber] explicit branch to be removed after mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/myportal/case")'),
|
||||
false,
|
||||
"Expected /myportal/case explicit branch to be removed after mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/case/id/[incident]")'),
|
||||
false,
|
||||
"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(
|
||||
source.includes('isPath("/newappeal")'),
|
||||
false,
|
||||
"Expected /newappeal no-op explicit branch to be removed"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/newappeal/[appealtypes]")'),
|
||||
false,
|
||||
"Expected /newappeal/[appealtypes] explicit branch to be removed after step-back mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/myportal/[appealtypes]")'),
|
||||
false,
|
||||
"Expected /myportal/[appealtypes] explicit branch to be removed after step-back mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/myportal/representation")'),
|
||||
false,
|
||||
"Expected /myportal/representation explicit branch to be removed after representation mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/myportal/case/[ticketnumber]")'),
|
||||
false,
|
||||
"Expected /myportal/case/[ticketnumber] explicit branch to be removed after mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/myportal/dnsdetails")'),
|
||||
false,
|
||||
"Expected /myportal/dnsdetails explicit branch to be removed after mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/myportal/dns/[developmentName]")'),
|
||||
false,
|
||||
"Expected /myportal/dns/[developmentName] explicit branch to be removed after mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/dnsdetails")'),
|
||||
false,
|
||||
"Expected /dnsdetails explicit branch to be removed after mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/dns/[developmentName]")'),
|
||||
false,
|
||||
"Expected /dns/[developmentName] explicit branch to be removed after mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/dns/application-view")'),
|
||||
false,
|
||||
"Expected /dns/application-view explicit branch to be removed after mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/account/personaldetails")'),
|
||||
false,
|
||||
"Expected /account/personaldetails explicit branch to be removed after mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/account/changepassword")'),
|
||||
false,
|
||||
"Expected /account/changepassword explicit branch to be removed after mapping"
|
||||
);
|
||||
});
|
||||
|
||||
test("breadcrumbs/map builder preserves route map ordering", async () => {
|
||||
const source = loadBreadcrumbSource();
|
||||
|
||||
const mapBuilderCallIndex = source.indexOf(
|
||||
"const mappedRouteRendererMaps = buildBreadcrumbRendererMaps({"
|
||||
);
|
||||
|
||||
assert.notStrictEqual(
|
||||
mapBuilderCallIndex,
|
||||
-1,
|
||||
"Expected grouped map builder call to exist"
|
||||
);
|
||||
|
||||
const mapBuilderSlice = source.slice(
|
||||
mapBuilderCallIndex,
|
||||
mapBuilderCallIndex + 700
|
||||
);
|
||||
|
||||
const simpleRouteOrderIndex = mapBuilderSlice.indexOf(
|
||||
"simpleRouteRenderersByPath"
|
||||
);
|
||||
const simpleLinkTextPairOrderIndex = mapBuilderSlice.indexOf(
|
||||
"simpleLinkTextPairRenderersByPath"
|
||||
);
|
||||
const simpleMyPortalOrderIndex = mapBuilderSlice.indexOf(
|
||||
"simpleMyPortalRouteRenderersByPath"
|
||||
);
|
||||
const newAppealOrderIndex = mapBuilderSlice.indexOf(
|
||||
"newAppealRouteRenderersByPath"
|
||||
);
|
||||
const callbackOrderIndex = mapBuilderSlice.indexOf(
|
||||
"callbackRouteRenderersByPath"
|
||||
);
|
||||
const stepBackOrderIndex = mapBuilderSlice.indexOf(
|
||||
"stepBackRouteRenderersByPath"
|
||||
);
|
||||
const representationOrderIndex = mapBuilderSlice.indexOf(
|
||||
"representationRouteRenderersByPath"
|
||||
);
|
||||
const caseDetailOrderIndex = mapBuilderSlice.indexOf(
|
||||
"caseDetailRouteRenderersByPath"
|
||||
);
|
||||
const detailAndAccountOrderIndex = mapBuilderSlice.indexOf(
|
||||
"detailAndAccountRouteRenderersByPath"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
simpleRouteOrderIndex >= 0 &&
|
||||
simpleLinkTextPairOrderIndex > simpleRouteOrderIndex &&
|
||||
simpleMyPortalOrderIndex > simpleLinkTextPairOrderIndex &&
|
||||
newAppealOrderIndex > simpleMyPortalOrderIndex &&
|
||||
callbackOrderIndex > newAppealOrderIndex &&
|
||||
stepBackOrderIndex > callbackOrderIndex &&
|
||||
representationOrderIndex > stepBackOrderIndex &&
|
||||
caseDetailOrderIndex > representationOrderIndex &&
|
||||
detailAndAccountOrderIndex > caseDetailOrderIndex,
|
||||
true,
|
||||
"Expected map builder call to preserve explicit route-map ordering (simple -> link-text -> myportal -> new-appeal -> callback -> step-back -> representation -> case detail -> detail/account)"
|
||||
);
|
||||
});
|
||||
|
||||
test("breadcrumbs/callback-mapped branches preserve router.back behavior", async () => {
|
||||
const source = loadBreadcrumbSource();
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/myportal/case/id/[incident]")'),
|
||||
false,
|
||||
"Expected /myportal/case/id/[incident] explicit branch to be removed after callback mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes('isPath("/case")'),
|
||||
false,
|
||||
"Expected /case explicit branch to be removed after callback mapping"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
source.includes("router.back();"),
|
||||
true,
|
||||
"Expected callback-driven router.back() behavior to remain preserved"
|
||||
);
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
@@ -6,6 +6,9 @@ const runPortalServiceTests = require("./portal-service-behaviour.test.cjs");
|
||||
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 runBreadcrumbRouteMapsHelperTests = require("./breadcrumb-route-maps-helper.test.cjs");
|
||||
const runBreadcrumbsRouteMapStructureTests = require("./breadcrumbs-route-map-structure.test.cjs");
|
||||
|
||||
const run = async () => {
|
||||
await runCoreTokenTests();
|
||||
@@ -16,6 +19,9 @@ const run = async () => {
|
||||
await runAuthRedirectSafetyTests();
|
||||
await runI18nRouteParityTests();
|
||||
await runAzurestorageHelperTests();
|
||||
await runRouteStateHelperTests();
|
||||
await runBreadcrumbRouteMapsHelperTests();
|
||||
await runBreadcrumbsRouteMapStructureTests();
|
||||
console.log("Phase 22 combined suite passed.");
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,392 @@
|
||||
const assert = require("assert");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const vm = require("vm");
|
||||
|
||||
const tests = [];
|
||||
const test = (name, fn) => tests.push({ name, fn });
|
||||
|
||||
const helperModulePath = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"lib",
|
||||
"routing",
|
||||
"routeState.js"
|
||||
);
|
||||
|
||||
const toPlain = (value) => JSON.parse(JSON.stringify(value));
|
||||
|
||||
const loadHelpers = () => {
|
||||
const source = fs.readFileSync(helperModulePath, "utf8");
|
||||
|
||||
const transformedSource = `
|
||||
${source
|
||||
.replace(/export const /g, "const ")
|
||||
.replace(/export function /g, "function ")}
|
||||
|
||||
module.exports = {
|
||||
normalizeRouteStateQuery,
|
||||
resolveSearchResultsHref,
|
||||
resolveSearchBreadcrumbLabel,
|
||||
isDnsRoutePath,
|
||||
resolveCaseBreadcrumbState
|
||||
};
|
||||
`;
|
||||
|
||||
const sandbox = {
|
||||
module: { exports: {} },
|
||||
exports: {},
|
||||
require,
|
||||
__dirname: path.dirname(helperModulePath),
|
||||
__filename: helperModulePath,
|
||||
console
|
||||
};
|
||||
|
||||
vm.runInNewContext(transformedSource, sandbox, {
|
||||
filename: helperModulePath
|
||||
});
|
||||
|
||||
return sandbox.module.exports;
|
||||
};
|
||||
|
||||
test("normalizeRouteStateQuery maps known boolean query flags", () => {
|
||||
const { normalizeRouteStateQuery } = loadHelpers();
|
||||
|
||||
assert.deepStrictEqual(
|
||||
toPlain(
|
||||
normalizeRouteStateQuery({
|
||||
va: "true",
|
||||
adv: "false",
|
||||
ads: "true",
|
||||
key: "myCases"
|
||||
})
|
||||
),
|
||||
{
|
||||
viewAll: true,
|
||||
advanced: false,
|
||||
address: true,
|
||||
key: "myCases"
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveSearchResultsHref falls back to myportal when no flags and no search query exist for signed-in user", () => {
|
||||
const { resolveSearchResultsHref } = loadHelpers();
|
||||
|
||||
assert.deepStrictEqual(
|
||||
toPlain(
|
||||
resolveSearchResultsHref({
|
||||
query: {},
|
||||
hasSession: true,
|
||||
fallbackToMyPortalWhenNoFlags: true
|
||||
})
|
||||
),
|
||||
{
|
||||
pathname: "/myportal"
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveSearchResultsHref preserves public searchresults route when search query exists and no flags are set", () => {
|
||||
const { resolveSearchResultsHref } = loadHelpers();
|
||||
|
||||
assert.deepStrictEqual(
|
||||
toPlain(
|
||||
resolveSearchResultsHref({
|
||||
query: { q: "abc" },
|
||||
hasSession: false,
|
||||
fallbackToMyPortalWhenNoFlags: true
|
||||
})
|
||||
),
|
||||
{
|
||||
pathname: "/searchresults",
|
||||
query: { q: "abc" }
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveSearchResultsHref preserves myportal searchresults route when search query exists and no flags are set for signed-in user", () => {
|
||||
const { resolveSearchResultsHref } = loadHelpers();
|
||||
|
||||
assert.deepStrictEqual(
|
||||
toPlain(
|
||||
resolveSearchResultsHref({
|
||||
query: { q: "abc" },
|
||||
hasSession: true,
|
||||
fallbackToMyPortalWhenNoFlags: true
|
||||
})
|
||||
),
|
||||
{
|
||||
pathname: "/myportal/searchresults",
|
||||
query: { q: "abc" }
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveSearchResultsHref routes view-all requests to myportal viewall with key only", () => {
|
||||
const { resolveSearchResultsHref } = loadHelpers();
|
||||
|
||||
assert.deepStrictEqual(
|
||||
toPlain(
|
||||
resolveSearchResultsHref({
|
||||
query: {
|
||||
va: "true",
|
||||
key: "mySubmittedReps",
|
||||
q: "ignored"
|
||||
},
|
||||
hasSession: true,
|
||||
includeViewAll: true
|
||||
})
|
||||
),
|
||||
{
|
||||
pathname: "/myportal/viewall",
|
||||
query: { key: "mySubmittedReps" }
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveSearchResultsHref routes advanced requests to advancedsearchresults and preserves query", () => {
|
||||
const { resolveSearchResultsHref } = loadHelpers();
|
||||
|
||||
assert.deepStrictEqual(
|
||||
toPlain(
|
||||
resolveSearchResultsHref({
|
||||
query: { q: "abc", adv: "true", page: "2" },
|
||||
hasSession: false
|
||||
})
|
||||
),
|
||||
{
|
||||
pathname: "/advancedsearchresults",
|
||||
query: { q: "abc", adv: "true", page: "2" }
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveSearchResultsHref routes address requests to addresssearchresults and preserves query", () => {
|
||||
const { resolveSearchResultsHref } = loadHelpers();
|
||||
|
||||
assert.deepStrictEqual(
|
||||
toPlain(
|
||||
resolveSearchResultsHref({
|
||||
query: { postcode: "CF10", ads: "true" },
|
||||
hasSession: true
|
||||
})
|
||||
),
|
||||
{
|
||||
pathname: "/myportal/addresssearchresults",
|
||||
query: { postcode: "CF10", ads: "true" }
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveSearchResultsHref routes dns requests to dnsapplications", () => {
|
||||
const { resolveSearchResultsHref } = loadHelpers();
|
||||
|
||||
assert.deepStrictEqual(
|
||||
toPlain(
|
||||
resolveSearchResultsHref({
|
||||
query: { anything: "x" },
|
||||
hasSession: true,
|
||||
isDnsRoute: true
|
||||
})
|
||||
),
|
||||
{
|
||||
pathname: "/myportal/dnsapplications"
|
||||
}
|
||||
);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
toPlain(
|
||||
resolveSearchResultsHref({
|
||||
query: { anything: "x" },
|
||||
hasSession: false,
|
||||
isDnsRoute: true
|
||||
})
|
||||
),
|
||||
{
|
||||
pathname: "/dnsapplications"
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveSearchResultsHref defaults to searchresults and preserves query when no special route applies", () => {
|
||||
const { resolveSearchResultsHref } = loadHelpers();
|
||||
|
||||
assert.deepStrictEqual(
|
||||
toPlain(
|
||||
resolveSearchResultsHref({
|
||||
query: { q: "abc", page: "3" },
|
||||
hasSession: false
|
||||
})
|
||||
),
|
||||
{
|
||||
pathname: "/searchresults",
|
||||
query: { q: "abc", page: "3" }
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveSearchBreadcrumbLabel prioritizes view-all label, then keyed label, then advanced/address/default", () => {
|
||||
const { resolveSearchBreadcrumbLabel } = loadHelpers();
|
||||
|
||||
const getViewAllLabel = (key) => {
|
||||
const labels = {
|
||||
myCases: "My cases",
|
||||
watchedCases: "Watched cases"
|
||||
};
|
||||
return labels[key] || null;
|
||||
};
|
||||
|
||||
assert.strictEqual(
|
||||
resolveSearchBreadcrumbLabel({
|
||||
query: { va: "true", key: "myCases" },
|
||||
getViewAllLabel,
|
||||
advancedLabel: "Advanced search results",
|
||||
addressLabel: "Address search results",
|
||||
defaultLabel: "Search results"
|
||||
}),
|
||||
"My cases"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
resolveSearchBreadcrumbLabel({
|
||||
query: { key: "watchedCases" },
|
||||
getViewAllLabel,
|
||||
advancedLabel: "Advanced search results",
|
||||
addressLabel: "Address search results",
|
||||
defaultLabel: "Search results"
|
||||
}),
|
||||
"Watched cases"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
resolveSearchBreadcrumbLabel({
|
||||
query: { adv: "true" },
|
||||
getViewAllLabel,
|
||||
advancedLabel: "Advanced search results",
|
||||
addressLabel: "Address search results",
|
||||
defaultLabel: "Search results"
|
||||
}),
|
||||
"Advanced search results"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
resolveSearchBreadcrumbLabel({
|
||||
query: { ads: "true" },
|
||||
getViewAllLabel,
|
||||
advancedLabel: "Advanced search results",
|
||||
addressLabel: "Address search results",
|
||||
defaultLabel: "Search results"
|
||||
}),
|
||||
"Address search results"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
resolveSearchBreadcrumbLabel({
|
||||
query: {},
|
||||
getViewAllLabel,
|
||||
advancedLabel: "Advanced search results",
|
||||
addressLabel: "Address search results",
|
||||
defaultLabel: "Search results"
|
||||
}),
|
||||
"Search results"
|
||||
);
|
||||
});
|
||||
|
||||
test("isDnsRoutePath correctly identifies dns route families", () => {
|
||||
const { isDnsRoutePath } = loadHelpers();
|
||||
|
||||
assert.strictEqual(isDnsRoutePath("/dns"), true);
|
||||
assert.strictEqual(isDnsRoutePath("/dns/applications"), true);
|
||||
assert.strictEqual(isDnsRoutePath("/myportal/dns"), true);
|
||||
assert.strictEqual(isDnsRoutePath("/myportal/dns/example"), true);
|
||||
|
||||
assert.strictEqual(isDnsRoutePath("/searchresults"), false);
|
||||
assert.strictEqual(isDnsRoutePath("/myportal"), false);
|
||||
assert.strictEqual(isDnsRoutePath("/myportal/case/[ticketnumber]"), false);
|
||||
});
|
||||
|
||||
test("resolveCaseBreadcrumbState returns breadcrumb and case-results hrefs plus breadcrumb label", () => {
|
||||
const { resolveCaseBreadcrumbState } = loadHelpers();
|
||||
|
||||
const getViewAllLabel = (key) =>
|
||||
key === "mySubmittedReps" ? "Submitted representations" : null;
|
||||
|
||||
assert.deepStrictEqual(
|
||||
toPlain(
|
||||
resolveCaseBreadcrumbState({
|
||||
query: { q: "cas-", adv: "false" },
|
||||
hasSession: true,
|
||||
getViewAllLabel,
|
||||
advancedLabel: "Advanced search results",
|
||||
addressLabel: "Address search results",
|
||||
defaultLabel: "Search results"
|
||||
})
|
||||
),
|
||||
{
|
||||
breadcrumbHref: {
|
||||
pathname: "/myportal/searchresults",
|
||||
query: { q: "cas-", adv: "false" }
|
||||
},
|
||||
caseResultsHref: {
|
||||
pathname: "/myportal/searchresults",
|
||||
query: { q: "cas-", adv: "false" }
|
||||
},
|
||||
breadcrumbLabel: "Search results"
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveCaseBreadcrumbState distinguishes view-all breadcrumb from case-results href", () => {
|
||||
const { resolveCaseBreadcrumbState } = loadHelpers();
|
||||
|
||||
const getViewAllLabel = (key) =>
|
||||
key === "mySubmittedReps" ? "Submitted representations" : null;
|
||||
|
||||
assert.deepStrictEqual(
|
||||
toPlain(
|
||||
resolveCaseBreadcrumbState({
|
||||
query: { va: "true", key: "mySubmittedReps" },
|
||||
hasSession: true,
|
||||
getViewAllLabel,
|
||||
advancedLabel: "Advanced search results",
|
||||
addressLabel: "Address search results",
|
||||
defaultLabel: "Search results"
|
||||
})
|
||||
),
|
||||
{
|
||||
breadcrumbHref: {
|
||||
pathname: "/myportal/viewall",
|
||||
query: { key: "mySubmittedReps" }
|
||||
},
|
||||
caseResultsHref: {
|
||||
pathname: "/myportal/searchresults",
|
||||
query: { va: "true", key: "mySubmittedReps" }
|
||||
},
|
||||
breadcrumbLabel: "Submitted representations"
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const run = async () => {
|
||||
let passed = 0;
|
||||
|
||||
for (const currentTest of tests) {
|
||||
await currentTest.fn();
|
||||
passed += 1;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Phase 22 route-state-helper tests passed (${passed}/${tests.length}).`
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = run;
|
||||
|
||||
if (require.main === module) {
|
||||
run().catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user