Refactor breadcrumbs to use factory-based route renderers

This commit is contained in:
2026-04-09 12:08:36 +01:00
parent 5f6dde782a
commit 062cd23463
7 changed files with 813 additions and 382 deletions
+106 -160
View File
@@ -17,6 +17,12 @@ import {
buildBreadcrumbRendererMaps, buildBreadcrumbRendererMaps,
resolveMappedRouteRenderer as resolveMappedRouteRendererByMaps resolveMappedRouteRenderer as resolveMappedRouteRendererByMaps
} from "../lib/routing/breadcrumbRouteMaps"; } from "../lib/routing/breadcrumbRouteMaps";
import {
createSimpleRouteRenderers,
createSimpleLinkTextPairRenderers,
createSimpleMyPortalRouteRenderers
} from "../lib/routing/breadcrumbRendererFactories";
const Breadcrumbs = (props) => { const Breadcrumbs = (props) => {
const { const {
currentView, currentView,
@@ -98,133 +104,27 @@ const Breadcrumbs = (props) => {
const getStaticTextCrumbLabel = (path) => { const getStaticTextCrumbLabel = (path) => {
const staticTextCrumbByPath = { const staticTextCrumbByPath = {
"/account/register": t("account:register-new-account-heading"), "/account/register": () =>
"/dns": t("dnsCommon:service-name"), t("account:register-new-account-heading"),
"/dnsapplications": t("dnsCommon:service-name"), "/dns": () => t("dnsCommon:service-name"),
"/dns/application-process": "Guidance", "/dnsapplications": () => t("dnsCommon:service-name"),
"/dns/help": "Help", "/dns/application-process": () => "Guidance",
"/dns/contact-us": t("common:footer-contact-us-link-label"), "/dns/help": () => "Help",
"/dns/applications": t("dnsApplications:page-title"), "/dns/contact-us": () => t("common:footer-contact-us-link-label"),
"/help/cookies": t("cookies:cookie-breadcrumb"), "/dns/applications": () => t("dnsApplications:page-title"),
"/privacy": t("common:footer-privacy-link-label"), "/help/cookies": () => t("cookies:cookie-breadcrumb"),
"/accessibility": t("common:footer-accessibility-link-label"), "/privacy": () => t("common:footer-privacy-link-label"),
"/details-about-cookies": t("cookies:cookie-policy-title-heading"), "/accessibility": () => t("common:footer-accessibility-link-label"),
"/auth/signin": t("auth:auth-page-title"), "/details-about-cookies": () =>
"/auth/verify-request": t("auth:auth-check-email-page-title"), t("cookies:cookie-policy-title-heading"),
"/auth/error": t("auth:auth-error-signin-error-title") "/auth/signin": () => t("auth:auth-page-title"),
"/auth/verify-request": () => t("auth:auth-check-email-page-title"),
"/auth/error": () => t("auth:auth-error-signin-error-title")
}; };
return staticTextCrumbByPath[path] || null; return staticTextCrumbByPath[path] || null;
}; };
const simpleRouteRenderersByPath = {
"/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"))
};
const simpleLinkTextPairRenderersByPath = {
"/addresssearchresults": () => (
<>
{renderLinkCrumb(
isWelsh
? router.locale + "/chwiliadcyfeiriadau"
: "/addresssearch",
t("common:breadcrumb-address-search")
)}
{renderTextCrumb(t("common:breadcrumb-address-search-results"))}
</>
),
"/advancedsearchresults": () => (
<>
{renderLinkCrumb(
isWelsh
? router.locale + "/advancedsearch"
: "/advancedsearch",
t("common:breadcrumb-advanced-search")
)}
{renderTextCrumb(
t("common:breadcrumb-advanced-search-results")
)}
</>
)
};
const simpleMyPortalRouteRenderersByPath = {
"/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"))}
</>
)
};
const mappedRouteRendererMaps = buildBreadcrumbRendererMaps({
simpleRouteRenderersByPath,
simpleLinkTextPairRenderersByPath,
simpleMyPortalRouteRenderersByPath
});
const resolveMappedRouteRenderer = (path) => {
return resolveMappedRouteRendererByMaps(path, mappedRouteRendererMaps);
};
const renderMappedRoute = (path, resolver = resolveMappedRouteRenderer) => {
const routeRenderer = resolver(path);
return routeRenderer ? routeRenderer() : null;
};
const renderMyPortalCrumb = () => ( const renderMyPortalCrumb = () => (
<li className="govuk-breadcrumbs__list-item"> <li className="govuk-breadcrumbs__list-item">
<Link href={myPortalHref} className="govuk-breadcrumbs__link"> <Link href={myPortalHref} className="govuk-breadcrumbs__link">
@@ -288,7 +188,7 @@ const Breadcrumbs = (props) => {
<> <>
{renderLinkCrumb( {renderLinkCrumb(
isWelsh isWelsh
? router.locale + "/dnsapplications" ? `${router.locale}/dnsapplications`
: "/dnsapplications", : "/dnsapplications",
t("dnsCommon:service-name") t("dnsCommon:service-name")
)} )}
@@ -296,6 +196,52 @@ const Breadcrumbs = (props) => {
</> </>
); );
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 mappedRouteRendererMaps = buildBreadcrumbRendererMaps({
simpleRouteRenderersByPath,
simpleLinkTextPairRenderersByPath,
simpleMyPortalRouteRenderersByPath
});
const resolveMappedRouteRenderer = (path) => {
return resolveMappedRouteRendererByMaps(path, mappedRouteRendererMaps);
};
const renderMappedRoute = (path, resolver = resolveMappedRouteRenderer) => {
const routeRenderer = resolver(path);
return routeRenderer ? routeRenderer() : null;
};
const { breadcrumbHref, caseResultsHref, breadcrumbLabel } = const { breadcrumbHref, caseResultsHref, breadcrumbLabel } =
resolveCaseBreadcrumbState({ resolveCaseBreadcrumbState({
query: router.query, query: router.query,
@@ -305,6 +251,9 @@ const Breadcrumbs = (props) => {
addressLabel: t("common:breadcrumb-address-search-results"), addressLabel: t("common:breadcrumb-address-search-results"),
defaultLabel: t("common:breadcrumb-search-results") defaultLabel: t("common:breadcrumb-search-results")
}); });
const staticTextCrumbLabel = getStaticTextCrumbLabel(pathname);
return ( return (
<> <>
<nav <nav
@@ -321,7 +270,9 @@ const Breadcrumbs = (props) => {
)} )}
{renderMappedRoute(pathname)} {renderMappedRoute(pathname)}
{isPath("/newappeal") && <></>} {isPath("/newappeal") && <></>}
{isPath("/newappeal/[appealtypes]") && ( {isPath("/newappeal/[appealtypes]") && (
<> <>
{appealType.currentSection > 1 && {appealType.currentSection > 1 &&
@@ -342,6 +293,7 @@ const Breadcrumbs = (props) => {
))} ))}
</> </>
)} )}
{isPath("/myportal/[appealtypes]") && ( {isPath("/myportal/[appealtypes]") && (
<> <>
{appealType.currentSection > 1 && {appealType.currentSection > 1 &&
@@ -359,6 +311,7 @@ const Breadcrumbs = (props) => {
))} ))}
</> </>
)} )}
{isPath("/newappeal/selectappeal") && ( {isPath("/newappeal/selectappeal") && (
<> <>
{renderLinkCrumb( {renderLinkCrumb(
@@ -374,17 +327,19 @@ const Breadcrumbs = (props) => {
</li> </li>
</> </>
)} )}
{isPath("/myportal/case") && ( {isPath("/myportal/case") && (
<> <>
{renderLinkCrumb( {renderLinkCrumb(
isWelsh isWelsh
? "/" + router.locale + "/fymhorth" ? `/${router.locale}/fymhorth`
: "/myportal", : "/myportal",
t("common:breadcrumb-my-portal") t("common:breadcrumb-my-portal")
)} )}
{renderCaseReferenceCrumb(currentReference)} {renderCaseReferenceCrumb(currentReference)}
</> </>
)} )}
{isPath("/case/[ticketnumber]") && ( {isPath("/case/[ticketnumber]") && (
<> <>
{renderLinkCrumb( {renderLinkCrumb(
@@ -394,24 +349,19 @@ const Breadcrumbs = (props) => {
{renderCaseReferenceCrumb(fallbackSearchTitle)} {renderCaseReferenceCrumb(fallbackSearchTitle)}
</> </>
)} )}
{isPath("/case/id/[incident]") && ( {isPath("/case/id/[incident]") && (
<> <>
{renderLinkCrumb( {renderLinkCrumb(
isWelsh isWelsh
? "/" + ? `/${router.locale}/chwiliadcyfeiriadau`
router.locale +
"/chwiliadcyfeiriadau"
: "/addresssearch", : "/addresssearch",
t("common:breadcrumb-address-search") t("common:breadcrumb-address-search")
)} )}
{renderLinkCrumb( {renderLinkCrumb(
isWelsh isWelsh
? "/" + ? `/${router.locale}/canlyniadaucyfeiriadau?${nestedSearchString}`
router.locale + : `/addresssearchresults?${nestedSearchString}`,
"/canlyniadaucyfeiriadau?" +
nestedSearchString
: "/addresssearchresults?" +
nestedSearchString,
t( t(
"common:breadcrumb-address-search-results" "common:breadcrumb-address-search-results"
) )
@@ -419,37 +369,31 @@ const Breadcrumbs = (props) => {
{renderCaseReferenceCrumb(currentReference)} {renderCaseReferenceCrumb(currentReference)}
</> </>
)} )}
{isPath("/myportal/case/id/[incident]") && ( {isPath("/myportal/case/id/[incident]") && (
<> <>
{" "}
{renderMyPortalCrumb()} {renderMyPortalCrumb()}
{renderLinkCrumb( {renderLinkCrumb(
isWelsh isWelsh
? "/" + ? `/${router.locale}/fymhorth/chwiliadcyfeiriadau`
router.locale +
"/fymhorth/chwiliadcyfeiriadau"
: "/myportal/addresssearch", : "/myportal/addresssearch",
t("common:breadcrumb-address-search") t("common:breadcrumb-address-search")
)} )}
{renderLinkCrumb( {renderLinkCrumb(
isWelsh isWelsh
? "/" + ? `/${router.locale}/fymhorth/canlyniadaucyfeiriadau?${nestedSearchString}`
router.locale + : `/myportal/addresssearchresults?${nestedSearchString}`,
"/fymhorth/canlyniadaucyfeiriadau?" +
nestedSearchString
: "/myportal/addresssearchresults?" +
nestedSearchString,
t( t(
"common:breadcrumb-address-search-results" "common:breadcrumb-address-search-results"
), ),
() => { () => {
// spinnerState();
router.back(); router.back();
} }
)} )}
{renderCaseReferenceCrumb(currentReference)} {renderCaseReferenceCrumb(currentReference)}
</> </>
)} )}
{isPath("/myportal/case/[ticketnumber]") && ( {isPath("/myportal/case/[ticketnumber]") && (
<> <>
{renderMyPortalCrumb()} {renderMyPortalCrumb()}
@@ -460,6 +404,7 @@ const Breadcrumbs = (props) => {
{renderCaseReferenceCrumb(caseReferenceDisplay)} {renderCaseReferenceCrumb(caseReferenceDisplay)}
</> </>
)} )}
{isPath("/myportal/dnsdetails") && ( {isPath("/myportal/dnsdetails") && (
<> <>
{renderMyPortalCrumb()} {renderMyPortalCrumb()}
@@ -470,11 +415,12 @@ const Breadcrumbs = (props) => {
{renderCaseReferenceCrumb(currentReference)} {renderCaseReferenceCrumb(currentReference)}
</> </>
)} )}
{isPath("/myportal/dns/[developmentName]") && ( {isPath("/myportal/dns/[developmentName]") && (
<> <>
{renderLinkCrumb( {renderLinkCrumb(
isWelsh isWelsh
? router.locale + "/fymhorth" ? `${router.locale}/fymhorth`
: "/myportal", : "/myportal",
t("common:breadcrumb-my-portal") t("common:breadcrumb-my-portal")
)} )}
@@ -485,28 +431,22 @@ const Breadcrumbs = (props) => {
{renderCaseReferenceCrumb(caseReferenceDisplay)} {renderCaseReferenceCrumb(caseReferenceDisplay)}
</> </>
)} )}
{isPath("/case") && ( {isPath("/case") && (
<> <>
{renderLinkCrumb( {renderLinkCrumb(
isWelsh isWelsh
? router.locale + ? `${router.locale}/searchresults?q=${router.query.q}&page=${router.query.page}`
"/searchresults?q=" + : `/searchresults?q=${router.query.q}&page=${router.query.page}`,
router.query.q +
"&page=" +
router.query.page
: "/searchresults?q=" +
router.query.q +
"&page=" +
router.query.page,
t("common:breadcrumb-search-results"), t("common:breadcrumb-search-results"),
() => { () => {
// spinnerState();
router.back(); router.back();
} }
)} )}
{renderCaseReferenceCrumb(currentReference)} {renderCaseReferenceCrumb(currentReference)}
</> </>
)} )}
{isPath("/myportal/representation") && ( {isPath("/myportal/representation") && (
<> <>
{currentView.representationSubmit === true && {currentView.representationSubmit === true &&
@@ -515,6 +455,7 @@ const Breadcrumbs = (props) => {
renderBackCrumb(() => { renderBackCrumb(() => {
setRepresentationSubmit(qcount); setRepresentationSubmit(qcount);
})} })}
{currentView.representationSubmit !== true && {currentView.representationSubmit !== true &&
hasRepDetails && hasRepDetails &&
repDetails?.representationType !== repDetails?.representationType !==
@@ -522,6 +463,7 @@ const Breadcrumbs = (props) => {
renderBackCrumb(() => { renderBackCrumb(() => {
setRepresentationSubmit(false); setRepresentationSubmit(false);
})} })}
{currentView.representationSubmit !== true && {currentView.representationSubmit !== true &&
hasRepDetails && hasRepDetails &&
repDetails?.representationType === repDetails?.representationType ===
@@ -535,6 +477,7 @@ const Breadcrumbs = (props) => {
})} })}
</> </>
)} )}
{isPath("/account/personaldetails") && ( {isPath("/account/personaldetails") && (
<> <>
{renderLinkCrumb( {renderLinkCrumb(
@@ -546,6 +489,7 @@ const Breadcrumbs = (props) => {
</li> </li>
</> </>
)} )}
{isPath("/account/changepassword") && ( {isPath("/account/changepassword") && (
<> <>
{renderLinkCrumb( {renderLinkCrumb(
@@ -557,15 +501,18 @@ const Breadcrumbs = (props) => {
</li> </li>
</> </>
)} )}
{isPath("/dnsdetails") && {isPath("/dnsdetails") &&
renderDnsCaseReferenceCrumbs(currentReference)} renderDnsCaseReferenceCrumbs(currentReference)}
{isPath("/dns/[developmentName]") && {isPath("/dns/[developmentName]") &&
renderDnsCaseReferenceCrumbs(caseReferenceDisplay)} renderDnsCaseReferenceCrumbs(caseReferenceDisplay)}
{isPath("/dns/application-view") && ( {isPath("/dns/application-view") && (
<> <>
{renderLinkCrumb( {renderLinkCrumb(
isWelsh isWelsh
? router.locale + "/dns/applications" ? `${router.locale}/dns/applications`
: "/dns/applications", : "/dns/applications",
t("dnsApplicationView:page-parent-title") t("dnsApplicationView:page-parent-title")
)} )}
@@ -574,8 +521,9 @@ const Breadcrumbs = (props) => {
</li> </li>
</> </>
)} )}
{getStaticTextCrumbLabel(pathname) &&
renderTextCrumb(getStaticTextCrumbLabel(pathname))} {staticTextCrumbLabel &&
renderTextCrumb(staticTextCrumbLabel)}
</ol> </ol>
</div> </div>
</nav> </nav>
@@ -595,13 +543,11 @@ const mapDispatchToProps = (dispatch) => {
updateField: (form, field, newValue) => updateField: (form, field, newValue) =>
dispatch(change(form, field, newValue)), dispatch(change(form, field, newValue)),
setRepresentationCapacity: (representationCapacity) => { setRepresentationCapacity: (representationCapacity) => {
//dispatch(reset("representationForm"));
dispatch(setRepresentationCapacity(representationCapacity)); dispatch(setRepresentationCapacity(representationCapacity));
}, },
setRepresentationSubmit: (representationSubmit) => { setRepresentationSubmit: (representationSubmit) => {
dispatch(setRepresentationSubmit(representationSubmit)); dispatch(setRepresentationSubmit(representationSubmit));
}, },
setCurrentView: (currentView) => { setCurrentView: (currentView) => {
dispatch(setCurrentView(currentView)); dispatch(setCurrentView(currentView));
}, },
+1 -1
View File
@@ -16,7 +16,7 @@ module.exports = {
"/myportal/contactus": ["newappeal", "account", "common"], "/myportal/contactus": ["newappeal", "account", "common"],
"/error": ["common", "home", "myportal"], "/error": ["common", "home", "myportal"],
"/furtherdetails": ["common", "home", "myportal"], "/furtherdetails": ["common", "home", "myportal"],
"/myportal": ["myportal", "common", "home", "case"], "/myportal": ["myportal", "common", "home", "case", "auth"],
"/myportal/viewall": ["search", "myportal", "case"], "/myportal/viewall": ["search", "myportal", "case"],
"/myportal/advancedsearch": ["search", "myportal"], "/myportal/advancedsearch": ["search", "myportal"],
"/myportal/advancedsearchresults": ["search", "myportal", "case"], "/myportal/advancedsearchresults": ["search", "myportal", "case"],
+107
View File
@@ -0,0 +1,107 @@
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"))
});
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"))}
</>
)
});
+8
View File
@@ -21,8 +21,16 @@ export const resolveSearchResultsHref = ({
const routeState = normalizeRouteStateQuery(query); const routeState = normalizeRouteStateQuery(query);
const { viewAll, advanced, address, key } = routeState; const { viewAll, advanced, address, key } = routeState;
const base = hasSession ? "/myportal" : ""; const base = hasSession ? "/myportal" : "";
const hasSearchQuery =
typeof query?.q === "string" && query.q.trim().length > 0;
if (fallbackToMyPortalWhenNoFlags && !viewAll && !advanced && !address) { if (fallbackToMyPortalWhenNoFlags && !viewAll && !advanced && !address) {
if (hasSearchQuery) {
return {
pathname: `${base}/searchresults`,
query
};
}
return { return {
pathname: "/myportal" pathname: "/myportal"
}; };
@@ -1,49 +1,156 @@
const assert = require("assert"); const assert = require("assert");
const fs = require("fs");
const { const path = require("path");
buildBreadcrumbRendererMaps, const vm = require("vm");
getMappedRendererByPath,
resolveMappedRouteRenderer
} = require("../../lib/routing/breadcrumbRouteMaps");
const tests = []; const tests = [];
const test = (name, fn) => tests.push({ name, fn }); const test = (name, fn) => tests.push({ name, fn });
test("breadcrumbRouteMaps/buildBreadcrumbRendererMaps preserves explicit map order", async () => { const helperModulePath = path.join(
const mapA = { "/a": () => "A" }; __dirname,
const mapB = { "/b": () => "B" }; "..",
const mapC = { "/c": () => "C" }; "..",
"lib",
"routing",
"breadcrumbRouteMaps.js"
);
const result = buildBreadcrumbRendererMaps({ const loadHelpers = () => {
simpleRouteRenderersByPath: mapA, const source = fs.readFileSync(helperModulePath, "utf8");
simpleLinkTextPairRenderersByPath: mapB,
simpleMyPortalRouteRenderersByPath: mapC const transformedSource = `
${source
.replace(/export const /g, "const ")
.replace(/export function /g, "function ")}
module.exports = {
buildBreadcrumbRendererMaps,
resolveMappedRouteRenderer
};
`;
const sandbox = {
module: { exports: {} },
exports: {},
require,
__dirname: path.dirname(helperModulePath),
__filename: helperModulePath,
console
};
vm.runInNewContext(transformedSource, sandbox, {
filename: helperModulePath
}); });
assert.strictEqual(result[0], mapA); return sandbox.module.exports;
assert.strictEqual(result[1], mapB); };
assert.strictEqual(result[2], mapC);
test("buildBreadcrumbRendererMaps returns grouped maps in explicit precedence order", () => {
const { buildBreadcrumbRendererMaps } = loadHelpers();
const simpleRouteRenderersByPath = {
"/alpha": () => "alpha"
};
const simpleLinkTextPairRenderersByPath = {
"/beta": () => "beta"
};
const simpleMyPortalRouteRenderersByPath = {
"/gamma": () => "gamma"
};
const result = buildBreadcrumbRendererMaps({
simpleRouteRenderersByPath,
simpleLinkTextPairRenderersByPath,
simpleMyPortalRouteRenderersByPath
});
assert.ok(Array.isArray(result), "Expected grouped maps array");
assert.strictEqual(result.length, 3, "Expected three grouped route maps");
assert.strictEqual(
result[0],
simpleRouteRenderersByPath,
"Expected simple route renderers first"
);
assert.strictEqual(
result[1],
simpleLinkTextPairRenderersByPath,
"Expected simple link-text pair renderers second"
);
assert.strictEqual(
result[2],
simpleMyPortalRouteRenderersByPath,
"Expected my-portal route renderers third"
);
}); });
test("breadcrumbRouteMaps/getMappedRendererByPath returns mapped renderer or null", async () => { test("resolveMappedRouteRenderer returns renderer from first matching grouped map", () => {
const renderer = () => "ok"; const { buildBreadcrumbRendererMaps, resolveMappedRouteRenderer } =
const map = { "/x": renderer }; loadHelpers();
assert.strictEqual(getMappedRendererByPath("/x", map), renderer);
assert.strictEqual(getMappedRendererByPath("/missing", map), null);
});
test("breadcrumbRouteMaps/resolveMappedRouteRenderer honors map precedence", async () => {
const firstRenderer = () => "first"; const firstRenderer = () => "first";
const secondRenderer = () => "second"; const secondRenderer = () => "second";
const result = resolveMappedRouteRenderer("/same", [ const maps = buildBreadcrumbRendererMaps({
{ "/same": firstRenderer }, simpleRouteRenderersByPath: {
{ "/same": secondRenderer } "/known": firstRenderer
]); },
simpleLinkTextPairRenderersByPath: {
"/known": secondRenderer
},
simpleMyPortalRouteRenderersByPath: {}
});
assert.strictEqual(result, firstRenderer); const result = resolveMappedRouteRenderer("/known", maps);
assert.strictEqual(resolveMappedRouteRenderer("/none", []), null);
assert.strictEqual(
result,
firstRenderer,
"Expected resolver to use first matching map by precedence order"
);
});
test("resolveMappedRouteRenderer returns renderer from later grouped map when earlier maps do not match", () => {
const { buildBreadcrumbRendererMaps, resolveMappedRouteRenderer } =
loadHelpers();
const myPortalRenderer = () => "myportal";
const maps = buildBreadcrumbRendererMaps({
simpleRouteRenderersByPath: {},
simpleLinkTextPairRenderersByPath: {},
simpleMyPortalRouteRenderersByPath: {
"/myportal/searchresults": myPortalRenderer
}
});
const result = resolveMappedRouteRenderer("/myportal/searchresults", maps);
assert.strictEqual(
result,
myPortalRenderer,
"Expected resolver to return matching renderer from later grouped map"
);
});
test("resolveMappedRouteRenderer returns null for unmapped path", () => {
const { buildBreadcrumbRendererMaps, resolveMappedRouteRenderer } =
loadHelpers();
const maps = buildBreadcrumbRendererMaps({
simpleRouteRenderersByPath: {
"/known": () => "known"
},
simpleLinkTextPairRenderersByPath: {},
simpleMyPortalRouteRenderersByPath: {}
});
const result = resolveMappedRouteRenderer("/unknown", maps);
assert.strictEqual(
result,
null,
"Expected null when no grouped map contains the path"
);
}); });
const run = async () => { const run = async () => {
@@ -5,58 +5,75 @@ const path = require("path");
const tests = []; const tests = [];
const test = (name, fn) => tests.push({ name, fn }); const test = (name, fn) => tests.push({ name, fn });
const loadBreadcrumbSource = () => { const loadSource = (...parts) => {
const filePath = path.join( const filePath = path.join(__dirname, "..", "..", ...parts);
__dirname,
"..",
"..",
"components",
"breadcrumbs.js"
);
return fs.readFileSync(filePath, "utf8"); return fs.readFileSync(filePath, "utf8");
}; };
test("breadcrumbs/simple-link-text map includes address and advanced search result routes", async () => { const loadBreadcrumbSource = () => loadSource("components", "breadcrumbs.js");
const source = loadBreadcrumbSource();
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( assert.strictEqual(
source.includes('"/addresssearchresults": () => ('), source.includes('"/addresssearchresults": () => ('),
true, true,
"Expected /addresssearchresults to be mapped in getSimpleLinkTextPairRenderer" "Expected /addresssearchresults to be mapped in createSimpleLinkTextPairRenderers"
); );
assert.strictEqual( assert.strictEqual(
source.includes('"/advancedsearchresults": () => ('), source.includes('"/advancedsearchresults": () => ('),
true, true,
"Expected /advancedsearchresults to be mapped in getSimpleLinkTextPairRenderer" "Expected /advancedsearchresults to be mapped in createSimpleLinkTextPairRenderers"
); );
assert.strictEqual( assert.strictEqual(
source.includes('"/myportal/searchresults": () => ('), source.includes('"/myportal/searchresults": () => ('),
true, true,
"Expected /myportal/searchresults to be mapped in getSimpleMyPortalRouteRenderer" "Expected /myportal/searchresults to be mapped in createSimpleMyPortalRouteRenderers"
); );
assert.strictEqual( assert.strictEqual(
source.includes('"/myportal/viewall": () =>'), source.includes('"/myportal/viewall": () =>'),
true, true,
"Expected /myportal/viewall to be mapped in getSimpleMyPortalRouteRenderer" "Expected /myportal/viewall to be mapped in createSimpleMyPortalRouteRenderers"
); );
assert.strictEqual( assert.strictEqual(
source.includes('"/myportal/advancedsearchresults": () => ('), source.includes('"/myportal/advancedsearchresults": () => ('),
true, true,
"Expected /myportal/advancedsearchresults to be mapped in getSimpleMyPortalRouteRenderer" "Expected /myportal/advancedsearchresults to be mapped in createSimpleMyPortalRouteRenderers"
); );
assert.strictEqual( assert.strictEqual(
source.includes('"/myportal/addresssearchresults": () => ('), source.includes('"/myportal/addresssearchresults": () => ('),
true, true,
"Expected /myportal/addresssearchresults to be mapped in getSimpleMyPortalRouteRenderer" "Expected /myportal/addresssearchresults to be mapped in createSimpleMyPortalRouteRenderers"
); );
}); });
test("breadcrumbs/merged resolver renders mapped routes through single helper invocation", async () => { test("breadcrumbs/component composes mapped routes via imported factories and shared resolver", async () => {
const source = loadBreadcrumbSource(); const source = loadBreadcrumbSource();
assert.strictEqual( assert.strictEqual(
@@ -66,30 +83,80 @@ test("breadcrumbs/merged resolver renders mapped routes through single helper in
); );
assert.strictEqual( assert.strictEqual(
source.includes( source.includes('from "../lib/routing/breadcrumbRendererFactories"'),
"const mappedRouteRendererMaps = buildBreadcrumbRendererMaps({" true,
"Expected breadcrumbs to import breadcrumb renderer factories"
);
assert.strictEqual(
/createSimpleRouteRenderers/.test(source),
true,
"Expected breadcrumbs to reference createSimpleRouteRenderers"
);
assert.strictEqual(
/createSimpleLinkTextPairRenderers/.test(source),
true,
"Expected breadcrumbs to reference createSimpleLinkTextPairRenderers"
);
assert.strictEqual(
/createSimpleMyPortalRouteRenderers/.test(source),
true,
"Expected breadcrumbs to reference createSimpleMyPortalRouteRenderers"
);
assert.strictEqual(
/const\s+simpleRouteRenderersByPath\s*=\s*createSimpleRouteRenderers\s*\(/.test(
source
),
true,
"Expected breadcrumbs to build simple route renderers from factory"
);
assert.strictEqual(
/const\s+simpleLinkTextPairRenderersByPath\s*=\s*createSimpleLinkTextPairRenderers\s*\(/.test(
source
),
true,
"Expected breadcrumbs to build link-text pair renderers from factory"
);
assert.strictEqual(
/const\s+simpleMyPortalRouteRenderersByPath\s*=\s*createSimpleMyPortalRouteRenderers\s*\(/.test(
source
),
true,
"Expected breadcrumbs to build my-portal route renderers from factory"
);
assert.strictEqual(
/const\s+mappedRouteRendererMaps\s*=\s*buildBreadcrumbRendererMaps\s*\(/.test(
source
), ),
true, true,
"Expected grouped mapped route renderer map composition to use helper builder" "Expected grouped mapped route renderer map composition to use helper builder"
); );
assert.strictEqual( assert.strictEqual(
source.includes( /return\s+resolveMappedRouteRendererByMaps\s*\(\s*path\s*,\s*mappedRouteRendererMaps\s*\)/.test(
"return resolveMappedRouteRendererByMaps(path, mappedRouteRendererMaps);" source
), ),
true, true,
"Expected resolver to delegate to shared route-map resolver helper" "Expected resolver to delegate to shared route-map resolver helper"
); );
assert.strictEqual( assert.strictEqual(
source.includes("const resolveMappedRouteRenderer = (path) =>"), /const\s+resolveMappedRouteRenderer\s*=\s*\(\s*path\s*\)\s*=>/.test(
source
),
true, true,
"Expected unified mapped route resolver helper to exist" "Expected unified mapped route resolver helper to exist"
); );
assert.strictEqual( assert.strictEqual(
source.includes( /const\s+renderMappedRoute\s*=\s*\(\s*path\s*,\s*resolver\s*=\s*resolveMappedRouteRenderer\s*\)\s*=>/.test(
"const renderMappedRoute = (path, resolver = resolveMappedRouteRenderer) =>" source
), ),
true, true,
"Expected reusable renderMappedRoute helper to exist" "Expected reusable renderMappedRoute helper to exist"
@@ -112,13 +179,24 @@ test("breadcrumbs/merged resolver renders mapped routes through single helper in
false, false,
"Expected /myportal/addresssearchresults explicit branch to be removed after mapping" "Expected /myportal/addresssearchresults explicit branch to be removed after mapping"
); );
});
test("breadcrumbs/map builder preserves route map ordering", async () => {
const source = loadBreadcrumbSource();
const mapBuilderCallIndex = source.indexOf( const mapBuilderCallIndex = source.indexOf(
"const mappedRouteRendererMaps = buildBreadcrumbRendererMaps({" "const mappedRouteRendererMaps = buildBreadcrumbRendererMaps({"
); );
assert.notStrictEqual(
mapBuilderCallIndex,
-1,
"Expected grouped map builder call to exist"
);
const mapBuilderSlice = source.slice( const mapBuilderSlice = source.slice(
mapBuilderCallIndex, mapBuilderCallIndex,
mapBuilderCallIndex + 300 mapBuilderCallIndex + 500
); );
const simpleRouteOrderIndex = mapBuilderSlice.indexOf( const simpleRouteOrderIndex = mapBuilderSlice.indexOf(
+350 -165
View File
@@ -1,187 +1,372 @@
const assert = require("assert");
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const vm = require("vm"); const vm = require("vm");
const assert = require("assert");
const rootDir = path.resolve(__dirname, "..", "..");
const loadRouteStateModule = () => {
const filePath = path.join(rootDir, "lib", "routing", "routeState.js");
let source = fs.readFileSync(filePath, "utf8");
source = source.replace(/export const\s+/g, "const ");
source +=
"\nmodule.exports = { normalizeRouteStateQuery, resolveSearchResultsHref, resolveSearchBreadcrumbLabel, isDnsRoutePath, resolveCaseBreadcrumbState };\n";
const context = {
module: { exports: {} },
exports: {},
require
};
vm.runInNewContext(source, context, { filename: filePath });
return context.module.exports;
};
const tests = []; const tests = [];
const test = (name, fn) => tests.push({ name, fn }); const test = (name, fn) => tests.push({ name, fn });
test("routing/routeState normalizes va/adv/ads flags and key", async () => { const helperModulePath = path.join(
const mod = loadRouteStateModule(); __dirname,
"..",
"..",
"lib",
"routing",
"routeState.js"
);
const normalized = mod.normalizeRouteStateQuery({ const toPlain = (value) => JSON.parse(JSON.stringify(value));
va: "true",
adv: "false", const loadHelpers = () => {
ads: "true", const source = fs.readFileSync(helperModulePath, "utf8");
key: "myCases"
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
}); });
assert.deepStrictEqual(JSON.parse(JSON.stringify(normalized)), { return sandbox.module.exports;
viewAll: true, };
advanced: false,
address: true, test("normalizeRouteStateQuery maps known boolean query flags", () => {
key: "myCases" const { normalizeRouteStateQuery } = loadHelpers();
});
assert.deepStrictEqual(
toPlain(
normalizeRouteStateQuery({
va: "true",
adv: "false",
ads: "true",
key: "myCases"
})
),
{
viewAll: true,
advanced: false,
address: true,
key: "myCases"
}
);
}); });
test("routing/routeState resolves view-all href when va=true", async () => { test("resolveSearchResultsHref falls back to myportal when no flags and no search query exist for signed-in user", () => {
const mod = loadRouteStateModule(); const { resolveSearchResultsHref } = loadHelpers();
const href = mod.resolveSearchResultsHref({ assert.deepStrictEqual(
query: { va: "true", key: "myCases", adv: "true" }, toPlain(
hasSession: true resolveSearchResultsHref({
}); query: {},
hasSession: true,
assert.deepStrictEqual(JSON.parse(JSON.stringify(href)), { fallbackToMyPortalWhenNoFlags: true
pathname: "/myportal/viewall", })
query: { key: "myCases" } ),
}); {
pathname: "/myportal"
}
);
}); });
test("routing/routeState resolves advanced/address/default result hrefs", async () => { test("resolveSearchResultsHref preserves public searchresults route when search query exists and no flags are set", () => {
const mod = loadRouteStateModule(); const { resolveSearchResultsHref } = loadHelpers();
const advancedHref = mod.resolveSearchResultsHref({ assert.deepStrictEqual(
query: { adv: "true", q: "abc" }, toPlain(
hasSession: false resolveSearchResultsHref({
}); query: { q: "abc" },
const addressHref = mod.resolveSearchResultsHref({ hasSession: false,
query: { ads: "true", q: "abc" }, fallbackToMyPortalWhenNoFlags: true
hasSession: true })
}); ),
const defaultHref = mod.resolveSearchResultsHref({ {
query: { q: "abc" }, pathname: "/searchresults",
hasSession: true query: { q: "abc" }
}); }
);
assert.deepStrictEqual(JSON.parse(JSON.stringify(advancedHref)), {
pathname: "/advancedsearchresults",
query: { adv: "true", q: "abc" }
});
assert.deepStrictEqual(JSON.parse(JSON.stringify(addressHref)), {
pathname: "/myportal/addresssearchresults",
query: { ads: "true", q: "abc" }
});
assert.deepStrictEqual(JSON.parse(JSON.stringify(defaultHref)), {
pathname: "/myportal/searchresults",
query: { q: "abc" }
});
}); });
test("routing/routeState supports fallback to /myportal when no route flags", async () => { test("resolveSearchResultsHref preserves myportal searchresults route when search query exists and no flags are set for signed-in user", () => {
const mod = loadRouteStateModule(); const { resolveSearchResultsHref } = loadHelpers();
const href = mod.resolveSearchResultsHref({ assert.deepStrictEqual(
query: { q: "abc" }, toPlain(
hasSession: false, resolveSearchResultsHref({
fallbackToMyPortalWhenNoFlags: true query: { q: "abc" },
}); hasSession: true,
fallbackToMyPortalWhenNoFlags: true
assert.deepStrictEqual(JSON.parse(JSON.stringify(href)), { })
pathname: "/myportal" ),
}); {
});
test("routing/routeState supports DNS route override", async () => {
const mod = loadRouteStateModule();
const href = mod.resolveSearchResultsHref({
query: { adv: "true", q: "abc" },
hasSession: true,
isDnsRoute: true
});
assert.deepStrictEqual(JSON.parse(JSON.stringify(href)), {
pathname: "/myportal/dnsapplications"
});
});
test("routing/routeState resolves breadcrumb label using key and route flags", async () => {
const mod = loadRouteStateModule();
const getViewAllLabel = (key) =>
({ myCases: "My Cases", watchedCases: "Watched Cases" })[key] || null;
const fromViewAll = mod.resolveSearchBreadcrumbLabel({
query: { va: "true", key: "myCases" },
getViewAllLabel,
advancedLabel: "Advanced",
addressLabel: "Address",
defaultLabel: "Search"
});
const fromAdvanced = mod.resolveSearchBreadcrumbLabel({
query: { adv: "true" },
getViewAllLabel,
advancedLabel: "Advanced",
addressLabel: "Address",
defaultLabel: "Search"
});
const fromDefault = mod.resolveSearchBreadcrumbLabel({
query: {},
getViewAllLabel,
advancedLabel: "Advanced",
addressLabel: "Address",
defaultLabel: "Search"
});
assert.strictEqual(fromViewAll, "My Cases");
assert.strictEqual(fromAdvanced, "Advanced");
assert.strictEqual(fromDefault, "Search");
});
test("routing/routeState identifies dns and myportal dns route prefixes", async () => {
const mod = loadRouteStateModule();
assert.strictEqual(mod.isDnsRoutePath("/dns"), true);
assert.strictEqual(mod.isDnsRoutePath("/dns/development"), true);
assert.strictEqual(mod.isDnsRoutePath("/myportal/dns"), true);
assert.strictEqual(mod.isDnsRoutePath("/myportal/dns/applications"), true);
assert.strictEqual(mod.isDnsRoutePath("/case/123"), false);
});
test("routing/routeState resolves bundled case breadcrumb state", async () => {
const mod = loadRouteStateModule();
const getViewAllLabel = (key) => ({ myCases: "My Cases" })[key] || null;
const state = mod.resolveCaseBreadcrumbState({
query: { va: "true", key: "myCases" },
hasSession: true,
getViewAllLabel,
advancedLabel: "Advanced",
addressLabel: "Address",
defaultLabel: "Search"
});
assert.deepStrictEqual(JSON.parse(JSON.stringify(state)), {
breadcrumbHref: {
pathname: "/myportal/viewall",
query: { key: "myCases" }
},
caseResultsHref: {
pathname: "/myportal/searchresults", pathname: "/myportal/searchresults",
query: { va: "true", key: "myCases" } query: { q: "abc" }
}, }
breadcrumbLabel: "My Cases" );
}); });
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 () => { const run = async () => {
@@ -193,7 +378,7 @@ const run = async () => {
} }
console.log( console.log(
`Phase 22 route-state helper tests passed (${passed}/${tests.length}).` `Phase 22 route-state-helper tests passed (${passed}/${tests.length}).`
); );
}; };