feat(batchdiff): remit rows drill to RemitDrawer
This commit is contained in:
@@ -29,6 +29,7 @@ vi.mock("@/lib/api", () => ({
|
||||
isConfigured: true,
|
||||
listBatches: vi.fn(),
|
||||
getBatchDiff: vi.fn(),
|
||||
getRemittance: vi.fn(),
|
||||
},
|
||||
ApiError: class ApiError extends Error {
|
||||
constructor(public status: number, message: string) {
|
||||
@@ -180,6 +181,13 @@ function makeDiffPayload(): BatchDiffResponse {
|
||||
describe("BatchDiff page", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
// Default for the per-remit detail fetch — the drawer fetches
|
||||
// this whenever `?remit=` is in the URL. Return a never-resolving
|
||||
// promise so the drawer stays in the loading state; the smoke
|
||||
// test only asserts the drawer mounts, not the loaded data.
|
||||
(
|
||||
api.getRemittance as unknown as ReturnType<typeof vi.fn>
|
||||
).mockReturnValue(new Promise(() => {}));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -189,6 +197,42 @@ describe("BatchDiff page", () => {
|
||||
.happyDOM.setURL("http://localhost/batch-diff");
|
||||
});
|
||||
|
||||
it("SP21 Task 4.5: deep-link ?remit=ID opens the RemitDrawer on mount", async () => {
|
||||
// Pre-set the URL with `?remit=`. The page doesn't surface any
|
||||
// per-remit rows (the diff payload is claim-level), but the
|
||||
// drawer must still mount so the URL contract is honored.
|
||||
//
|
||||
// `useRemitDrawerUrlState` reads `window.location.search`
|
||||
// (NOT React Router's search params) so we have to set the
|
||||
// global window URL via happyDOM AND give MemoryRouter an
|
||||
// initial entry — both stay in lockstep.
|
||||
(window as unknown as { happyDOM: { setURL: (u: string) => void } })
|
||||
.happyDOM.setURL("http://localhost/batch-diff?remit=REM-7");
|
||||
(
|
||||
api.listBatches as unknown as ReturnType<typeof vi.fn>
|
||||
).mockResolvedValue([BATCH_A, BATCH_B]);
|
||||
|
||||
const { unmount } = renderIntoContainer(
|
||||
<BatchDiff />,
|
||||
["/batch-diff?remit=REM-7"],
|
||||
);
|
||||
|
||||
// Page header must be present + drawer must be open.
|
||||
await waitFor(
|
||||
() => !!document.querySelector('[data-testid="batch-diff-page"]'),
|
||||
"page header mounted",
|
||||
);
|
||||
await waitFor(
|
||||
() => !!document.querySelector('[data-testid="remit-drawer"]'),
|
||||
"remit drawer mounted via deep link",
|
||||
);
|
||||
expect(
|
||||
document.querySelector('[data-testid="remit-drawer"]'),
|
||||
).not.toBeNull();
|
||||
|
||||
unmount();
|
||||
});
|
||||
|
||||
it("renders the awaiting-picks empty state when no batches are selected", async () => {
|
||||
(api.listBatches as unknown as ReturnType<typeof vi.fn>).mockResolvedValue([
|
||||
BATCH_A, BATCH_B,
|
||||
|
||||
@@ -21,8 +21,10 @@ import {
|
||||
BatchDiffView,
|
||||
BatchDiffViewSkeleton,
|
||||
} from "@/components/BatchDiffView";
|
||||
import { RemitDrawer } from "@/components/RemitDrawer";
|
||||
import { useBatches } from "@/hooks/useBatches";
|
||||
import { useBatchDiff } from "@/hooks/useBatchDiff";
|
||||
import { useRemitDrawerUrlState } from "@/hooks/useRemitDrawerUrlState";
|
||||
import type { BatchSummary as ApiBatchSummary } from "@/lib/api";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
@@ -269,6 +271,14 @@ export function BatchDiff() {
|
||||
// BrowserRouter (production) symmetric: both update the
|
||||
// useSearchParams hook on every navigation.
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
// SP21 Phase 4 Task 4.5: mount the RemitDrawer so a deep link to
|
||||
// /batch-diff?remit=REM-1 opens the drawer in-place. The BatchDiff
|
||||
// data model (BatchClaimDiffSummary) is a claim-level projection —
|
||||
// there are no per-remit IDs in the diff payload to wrap, so no
|
||||
// click-to-drill is wired here. The drawer still mounts so the
|
||||
// `?remit=` URL contract is honored when the user lands on this
|
||||
// page with the param set (e.g. from an external link).
|
||||
const { remitId, open, close } = useRemitDrawerUrlState();
|
||||
const { a, b } = useMemo(
|
||||
() => readIdsFromParams(searchParams),
|
||||
[searchParams],
|
||||
@@ -835,6 +845,24 @@ export function BatchDiff() {
|
||||
<span>{ready ? "A vs B" : "awaiting picks"}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* SP21 Phase 4 Task 4.5: RemitDrawer mount. There are no
|
||||
per-remit rows in the diff payload (the page is a
|
||||
claim-level projection), so this drawer is for deep-link
|
||||
support only — clicking a claim row does not open it.
|
||||
When the user lands on /batch-diff?remit=REM-1, the drawer
|
||||
opens in-place. The `remits` list is empty so j/k is a
|
||||
no-op while the drawer is open. */}
|
||||
<RemitDrawer
|
||||
remitId={remitId}
|
||||
remits={[]}
|
||||
onClose={close}
|
||||
onNavigate={open}
|
||||
onToggleHelp={() => {
|
||||
// BatchDiff has no cheatsheet surface; `?` is a no-op
|
||||
// here, but the prop is required by the drawer's contract.
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user