diff --git a/src/components/dsm/dsm-page-header.tsx b/src/components/dsm/dsm-page-header.tsx
index 863b5feee5..1fe0bc2cbb 100644
--- a/src/components/dsm/dsm-page-header.tsx
+++ b/src/components/dsm/dsm-page-header.tsx
@@ -1,4 +1,4 @@
-import { BookOpenCheck } from "lucide-react";
+import { BookOpenCheck, type LucideIcon } from "lucide-react";
import type { ReactNode } from "react";
import { InformationPageBreadcrumbs } from "@/components/information-page-shell";
@@ -14,6 +14,8 @@ export function DsmPageHeader({
actions,
className,
breadcrumb = true,
+ homeIcon,
+ icon = BookOpenCheck,
}: {
eyebrow?: string;
title: string;
@@ -29,6 +31,8 @@ export function DsmPageHeader({
* header's title is a ``.
*/
breadcrumb?: boolean;
+ homeIcon?: LucideIcon | false;
+ icon?: LucideIcon | false;
}) {
return (
@@ -37,13 +41,17 @@ export function DsmPageHeader({
`InformationPageBreadcrumbs` (now itself a `Breadcrumb`), so the
`PageHeader` below is not given a second `breadcrumb` of its own. */}
{breadcrumb ? (
-
+
) : null}
({
+ useRouter: () => ({ push: vi.fn(), replace: vi.fn(), back: vi.fn() }),
+}));
+
+describe("DsmComparisonPage", () => {
+ const mdd = getDsmDiagnosis("major-depressive-disorder");
+ const bp2 = getDsmDiagnosis("bipolar-ii-disorder");
+
+ it("renders unified comparison without duplicate diagnosis cards when two slots are filled", () => {
+ if (!mdd || !bp2) {
+ throw new Error("Expected catalogue diagnoses for comparison test");
+ }
+
+ const summaries = listDsmDiagnosisSummaries();
+ const mddSummary = summaries.find((entry) => entry.slug === mdd.slug);
+ const bp2Summary = summaries.find((entry) => entry.slug === bp2.slug);
+ if (!mddSummary || !bp2Summary) {
+ throw new Error("Expected diagnosis summaries for comparison test");
+ }
+
+ render(
+ ,
+ );
+
+ expect(screen.getByRole("heading", { name: "Compare diagnoses", level: 1 })).toBeInTheDocument();
+ expect(screen.getByTestId("dsm-comparison-unified")).toBeInTheDocument();
+ expect(screen.getByTestId("dsm-comparison-ask-this")).toBeInTheDocument();
+ expect(screen.queryByLabelText("Selected diagnoses")).not.toBeInTheDocument();
+ expect(screen.getAllByRole("link", { name: /Open record/i })).toHaveLength(2);
+ expect(screen.getAllByRole("link", { name: /Differential review/i })).toHaveLength(2);
+ expect(
+ screen.getByText("Structured review aid — not a diagnostic score. Open each record for complete criteria."),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/tests/information-page-shell.dom.test.tsx b/tests/information-page-shell.dom.test.tsx
index e5aab2d62f..32e1e575a2 100644
--- a/tests/information-page-shell.dom.test.tsx
+++ b/tests/information-page-shell.dom.test.tsx
@@ -76,6 +76,20 @@ describe("InformationPageShell", () => {
expect(screen.getByText("Transport")).toHaveAttribute("aria-current", "page");
});
+ it("renders a text-only home crumb when homeIcon is false", () => {
+ render(
+ ,
+ );
+
+ const home = screen.getByRole("link", { name: "DSM-5 Diagnosis home" });
+ expect(home).toHaveAttribute("href", "/dsm");
+ expect(home.querySelector("svg")).toBeNull();
+ });
+
it("keeps a linked intermediate crumb a link after the fold onto Breadcrumb", () => {
// The DS `Breadcrumb` decides link-vs-text from `href`, not from position.
// Deciding on position would turn this middle crumb into dead text the
diff --git a/tests/ui-route-coverage.spec.ts b/tests/ui-route-coverage.spec.ts
index 1109050049..cf6847bcd2 100644
--- a/tests/ui-route-coverage.spec.ts
+++ b/tests/ui-route-coverage.spec.ts
@@ -440,7 +440,7 @@ test.describe("previously uncovered production routes", () => {
await expect(compare).toBeVisible();
await compare.click();
await expect(currentPage).toHaveURL(/\/dsm\/compare$/);
- await expect(currentPage.getByRole("heading", { name: "Compare DSM diagnoses", level: 1 })).toBeVisible();
+ await expect(currentPage.getByRole("heading", { name: "Compare diagnoses", level: 1 })).toBeVisible();
},
);
});
@@ -451,31 +451,21 @@ test.describe("previously uncovered production routes", () => {
"/dsm/compare?ids=major-depressive-disorder,bipolar-ii-disorder",
async (currentPage) => {
await expect(visibleByTestId(currentPage, "dsm-comparison-page")).toBeVisible();
- await expect(currentPage.getByRole("heading", { name: "Compare DSM diagnoses", level: 1 })).toBeVisible();
+ await expect(currentPage.getByRole("heading", { name: "Compare diagnoses", level: 1 })).toBeVisible();
},
async (currentPage) => {
// Scope to the visible comparison owner (#093): under Production UI load,
- // Next streaming can leave a hidden duplicate root, and same-route
- // search-param soft-nav has been observed to click without updating the
- // URL. Pin the visible tree and wait for navigation with the click
- // (DsmCompareRemoveLink uses location.assign for this hop).
+ // Next streaming can leave a hidden duplicate root. Removal lives on the
+ // shared compare slot strip (`Remove ${title}`), not the old
+ // `DsmCompareRemoveLink` row.
const pageRoot = visibleByTestId(currentPage, "dsm-comparison-page");
- const remove = pageRoot.getByRole("link", {
- name: "Remove Major depressive disorder from comparison",
+ const remove = pageRoot.getByRole("button", {
+ name: "Remove Major depressive disorder",
});
await expect(remove).toBeEnabled();
- // `DsmCompareRemoveLink` is a `` whose `onClick` calls
- // `preventDefault()` and then `window.location.assign(href)`. Before
- // hydration the anchor is a bare ``, so a click there races two
- // different navigations — the browser's native one, or React capturing
- // the discrete event for replay once the root hydrates — and neither is
- // guaranteed to leave the URL where this step asserts it. Waiting for
- // the handler makes the assign hop the only path the click can take.
await waitForReactEventHandler(remove);
- // Same-route `?ids=` assign can update the URL without a new document
- // load. `waitUntil: "domcontentloaded"` then hangs for 30s after the
- // hop already happened (Production UI on #2299: waitForURL timeout
- // while the heading assertion never ran). Wait for the URL only.
+ // Slot clear commits through `router.push` with compacted ids. Wait for
+ // the URL only — same-route `?ids=` soft-nav may not fire a document load.
await Promise.all([
currentPage.waitForURL(/\/dsm\/compare\?ids=bipolar-ii-disorder$/, {
timeout: 30_000,