diff --git a/__tests__/lib/career-guides.test.ts b/__tests__/lib/career-guides.test.ts new file mode 100644 index 000000000..cda26fb64 --- /dev/null +++ b/__tests__/lib/career-guides.test.ts @@ -0,0 +1,37 @@ +import { loadCareerGuides } from "@/lib/career-guides"; + +describe("career-guides", () => { + describe("loadCareerGuides", () => { + const guides = loadCareerGuides(); + + it("yields two distinct 6333 entries, one per branch", () => { + const entries = guides.filter((g) => g.code === "6333"); + expect(entries).toHaveLength(2); + + const navy = entries.find((g) => g.branch === "Navy"); + expect(navy?.title).toBe("Aviation Maintenance Officer"); + expect(navy?.slug).toBe("6333"); + expect(navy?.rank).toBe("Officer"); + + const marine = entries.find((g) => g.branch === "Marine Corps"); + expect(marine?.title).toBe("Aviation Electronics Technician"); + expect(marine?.slug).toBe("marine_corps:6333"); + expect(marine?.rank).toBe("Enlisted"); + }); + + it("resolves branch-prefixed pathway data before the bare code", () => { + const navy = guides.find((g) => g.code === "6333" && g.branch === "Navy"); + const marine = guides.find((g) => g.code === "6333" && g.branch === "Marine Corps"); + + // Navy officer entry keeps the management-flavored bare "6333" pathways + expect(navy?.civilian).toBe("Aircraft Maintenance Manager"); + // Marine technician entry resolves its own "marine_corps:6333" pathways + expect(marine?.civilian).toBe("Avionics Technician"); + }); + + it("gives every guide a unique slug", () => { + const slugs = guides.map((g) => g.slug); + expect(new Set(slugs).size).toBe(slugs.length); + }); + }); +}); diff --git a/src/containers/career-guides/grid-view.tsx b/src/containers/career-guides/grid-view.tsx index 93deeb963..4369a5ba5 100644 --- a/src/containers/career-guides/grid-view.tsx +++ b/src/containers/career-guides/grid-view.tsx @@ -14,7 +14,7 @@ const GuideCard = ({ g }: { g: GuideEntry }) => { return ( { const family = detectFamily(entry.title); const certs = entry.civilian_certs ?? []; - // Pathway lookup: try raw code first, then full key - const matches = pathways[code] ?? pathways[stripBranchPrefix(key)] ?? []; + // Pathway lookup: exact full key first (branch-prefixed entries), then bare code + const matches = pathways[key] ?? pathways[code] ?? pathways[stripBranchPrefix(key)] ?? []; const top = matches[0]; const civilian = top?.role ?? entry.title; const salaries = matches.map((m) => m.avgSalary).filter((s) => typeof s === "number"); @@ -142,6 +142,7 @@ export const loadCareerGuides = (): GuideEntry[] => { guides.push({ code, + slug: key.toLowerCase(), title: entry.title, branch, rank, diff --git a/src/pages/career-guides/[mos].tsx b/src/pages/career-guides/[mos].tsx index d1a47e454..05dcc7f29 100644 --- a/src/pages/career-guides/[mos].tsx +++ b/src/pages/career-guides/[mos].tsx @@ -146,6 +146,11 @@ export const getStaticProps: GetStaticProps = async ({ params }) => { const training = trainingMap[mosCode]; if (!training) return { notFound: true }; + // Branch-prefixed keys (e.g. "marine_corps:6333") disambiguate code collisions + // across branches; display only the bare code. + const colonIdx = mosCode.indexOf(":"); + const displayCode = colonIdx === -1 ? mosCode : mosCode.slice(colonIdx + 1); + const techBundle = techPathwaysMap[mosCode]; const techPathway: TechPathway | null = techBundle ? { @@ -171,7 +176,7 @@ export const getStaticProps: GetStaticProps = async ({ params }) => { : null; const detail = buildDetail({ - code: mosCode, + code: displayCode, training, certs: certsMap[mosCode] || { direct_qualifies: [],