feat(batch-diff): claim ids drillable to /claims?claim=ID
This commit is contained in:
@@ -481,8 +481,184 @@ describe("BatchDiff page", () => {
|
||||
).toContain("pick a batch");
|
||||
unmount();
|
||||
});
|
||||
|
||||
it("SP21 Task 5.6: clicking an added-claim id navigates to /claims?claim=ID", async () => {
|
||||
// Each ClaimIdCell wraps its id text with DrillableCell, whose
|
||||
// onClick navigates to /claims?claim=ID. The MemoryRouter gives
|
||||
// us a router context so the navigation completes; we observe
|
||||
// it via the rendered pathname on a LocationTracker spy.
|
||||
(api.listBatches as unknown as ReturnType<typeof vi.fn>).mockResolvedValue([
|
||||
BATCH_A, BATCH_B,
|
||||
]);
|
||||
(api.getBatchDiff as unknown as ReturnType<typeof vi.fn>).mockResolvedValue(
|
||||
makeDiffPayload(),
|
||||
);
|
||||
|
||||
const captured: { pathname: string; search: string } = {
|
||||
pathname: "/batch-diff",
|
||||
search: "",
|
||||
};
|
||||
const Tracker = () => {
|
||||
const loc = useLocationSafe();
|
||||
React.useEffect(() => {
|
||||
captured.pathname = loc.pathname;
|
||||
captured.search = loc.search;
|
||||
}, [loc.pathname, loc.search]);
|
||||
return null;
|
||||
};
|
||||
|
||||
const { unmount } = renderIntoContainer(
|
||||
<>
|
||||
<Tracker />
|
||||
<BatchDiff />
|
||||
</>,
|
||||
[`/batch-diff?a=${BATCH_A.id}&b=${BATCH_B.id}`],
|
||||
);
|
||||
|
||||
await waitFor(
|
||||
() => !!document.querySelector('[data-testid="diff-added-row-CLM-3"]'),
|
||||
"added row rendered",
|
||||
);
|
||||
|
||||
const cell = document.querySelector(
|
||||
'[data-testid="diff-added-row-CLM-3"] [data-testid="diff-claim-id"]',
|
||||
);
|
||||
expect(cell).not.toBeNull();
|
||||
// DrillableCell wraps the id text in its own <button>; click the
|
||||
// nearest button ancestor so the drillable onClick fires.
|
||||
const drillBtn =
|
||||
(cell?.closest("button") as HTMLButtonElement | null) ?? null;
|
||||
expect(drillBtn).not.toBeNull();
|
||||
await act(async () => {
|
||||
drillBtn!.click();
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
await waitFor(
|
||||
() => captured.pathname === "/claims" && captured.search === "?claim=CLM-3",
|
||||
"navigation to /claims?claim=CLM-3",
|
||||
);
|
||||
unmount();
|
||||
});
|
||||
|
||||
it("SP21 Task 5.6: clicking a removed-claim id still navigates (ClaimDrawer handles 404)", async () => {
|
||||
// The diff can list claim ids that no longer exist in the DB
|
||||
// (Removed from A means "was in A, not in B" — the claim may
|
||||
// still exist or may have been purged). Either way, clicking
|
||||
// the id drills to /claims?claim=ID; the ClaimDrawer's 404
|
||||
// state (Phase 2) handles the missing-claim case. This test
|
||||
// only verifies the click path, not the drawer's 404 surface.
|
||||
(api.listBatches as unknown as ReturnType<typeof vi.fn>).mockResolvedValue([
|
||||
BATCH_A, BATCH_B,
|
||||
]);
|
||||
(api.getBatchDiff as unknown as ReturnType<typeof vi.fn>).mockResolvedValue(
|
||||
makeDiffPayload(),
|
||||
);
|
||||
|
||||
const captured: { pathname: string; search: string } = {
|
||||
pathname: "/batch-diff",
|
||||
search: "",
|
||||
};
|
||||
const Tracker = () => {
|
||||
const loc = useLocationSafe();
|
||||
React.useEffect(() => {
|
||||
captured.pathname = loc.pathname;
|
||||
captured.search = loc.search;
|
||||
}, [loc.pathname, loc.search]);
|
||||
return null;
|
||||
};
|
||||
|
||||
const { unmount } = renderIntoContainer(
|
||||
<>
|
||||
<Tracker />
|
||||
<BatchDiff />
|
||||
</>,
|
||||
[`/batch-diff?a=${BATCH_A.id}&b=${BATCH_B.id}`],
|
||||
);
|
||||
|
||||
await waitFor(
|
||||
() => !!document.querySelector('[data-testid="diff-removed-row-CLM-2"]'),
|
||||
"removed row rendered",
|
||||
);
|
||||
|
||||
const cell = document.querySelector(
|
||||
'[data-testid="diff-removed-row-CLM-2"] [data-testid="diff-claim-id"]',
|
||||
);
|
||||
const drillBtn =
|
||||
(cell?.closest("button") as HTMLButtonElement | null) ?? null;
|
||||
expect(drillBtn).not.toBeNull();
|
||||
await act(async () => {
|
||||
drillBtn!.click();
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
await waitFor(
|
||||
() => captured.pathname === "/claims" && captured.search === "?claim=CLM-2",
|
||||
"navigation to /claims?claim=CLM-2",
|
||||
);
|
||||
unmount();
|
||||
});
|
||||
|
||||
it("SP21 Task 5.6: clicking a changed-claim id navigates to /claims?claim=ID", async () => {
|
||||
// The Changed row uses the A-side id (per existing test
|
||||
// assertions). Drill should fire on that id.
|
||||
(api.listBatches as unknown as ReturnType<typeof vi.fn>).mockResolvedValue([
|
||||
BATCH_A, BATCH_B,
|
||||
]);
|
||||
(api.getBatchDiff as unknown as ReturnType<typeof vi.fn>).mockResolvedValue(
|
||||
makeDiffPayload(),
|
||||
);
|
||||
|
||||
const captured: { pathname: string; search: string } = {
|
||||
pathname: "/batch-diff",
|
||||
search: "",
|
||||
};
|
||||
const Tracker = () => {
|
||||
const loc = useLocationSafe();
|
||||
React.useEffect(() => {
|
||||
captured.pathname = loc.pathname;
|
||||
captured.search = loc.search;
|
||||
}, [loc.pathname, loc.search]);
|
||||
return null;
|
||||
};
|
||||
|
||||
const { unmount } = renderIntoContainer(
|
||||
<>
|
||||
<Tracker />
|
||||
<BatchDiff />
|
||||
</>,
|
||||
[`/batch-diff?a=${BATCH_A.id}&b=${BATCH_B.id}`],
|
||||
);
|
||||
|
||||
await waitFor(
|
||||
() => !!document.querySelector('[data-testid="diff-changed-row-CLM-1"]'),
|
||||
"changed row rendered",
|
||||
);
|
||||
|
||||
const cell = document.querySelector(
|
||||
'[data-testid="diff-changed-row-CLM-1"] [data-testid="diff-claim-id"]',
|
||||
);
|
||||
const drillBtn =
|
||||
(cell?.closest("button") as HTMLButtonElement | null) ?? null;
|
||||
expect(drillBtn).not.toBeNull();
|
||||
await act(async () => {
|
||||
drillBtn!.click();
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
await waitFor(
|
||||
() => captured.pathname === "/claims" && captured.search === "?claim=CLM-1",
|
||||
"navigation to /claims?claim=CLM-1",
|
||||
);
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
// SP21 Phase 5 Task 5.6: react-router-dom's `useLocation` hook, used
|
||||
// by the LocationTracker test helper below. Aliased to keep the import
|
||||
// block tidy alongside React + the page import.
|
||||
import { useLocation as useLocationSafe } from "react-router-dom";
|
||||
|
||||
// Keep `ApiError` referenced so the import isn't tree-shaken by
|
||||
// vitest's transformer when the mock factory above is hoisted.
|
||||
void ApiError;
|
||||
|
||||
Reference in New Issue
Block a user