feat(frontend): wire KeyboardCheatsheet into Claims page via ? toggle
This commit is contained in:
@@ -326,4 +326,98 @@ describe("Claims page drawer wiring", () => {
|
|||||||
await settle(() => !window.location.href.includes("?claim="));
|
await settle(() => !window.location.href.includes("?claim="));
|
||||||
expect(window.location.href).not.toContain("?claim=");
|
expect(window.location.href).not.toContain("?claim=");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("test_question_mark_toggles_cheatsheet", async () => {
|
||||||
|
// The cheatsheet keystroke is wired through `useDrawerKeyboard`
|
||||||
|
// (which lives inside ClaimDrawer and only enables when
|
||||||
|
// `claimId !== null`). Deep-link with `?claim=CLM-1` so the
|
||||||
|
// drawer mounts and the keyboard listener is active.
|
||||||
|
setLocation("http://localhost/claims?claim=CLM-1");
|
||||||
|
const { unmount } = renderClaims();
|
||||||
|
|
||||||
|
// Drawer must be open before we test the toggle.
|
||||||
|
await settle(
|
||||||
|
() => document.body.querySelector('[data-testid="claim-drawer"]') !== null
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
document.body.querySelector('[data-testid="claim-drawer"]')
|
||||||
|
).not.toBeNull();
|
||||||
|
|
||||||
|
// Cheatsheet starts closed.
|
||||||
|
expect(
|
||||||
|
document.body.querySelector('[data-testid="keyboard-cheatsheet"]')
|
||||||
|
).toBeNull();
|
||||||
|
|
||||||
|
// First `?` press: useDrawerKeyboard's handler flips `helpOpen`
|
||||||
|
// true on the page; the cheatsheet portals into document.body.
|
||||||
|
await act(async () => {
|
||||||
|
window.dispatchEvent(
|
||||||
|
new KeyboardEvent("keydown", { key: "?", bubbles: true })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await settle(
|
||||||
|
() =>
|
||||||
|
document.body.querySelector('[data-testid="keyboard-cheatsheet"]') !==
|
||||||
|
null
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
document.body.querySelector('[data-testid="keyboard-cheatsheet"]')
|
||||||
|
).not.toBeNull();
|
||||||
|
|
||||||
|
// Second `?` press: same handler flips `helpOpen` back to false;
|
||||||
|
// the cheatsheet unmounts. (The cheatsheet's own window-level
|
||||||
|
// listener explicitly returns early on `?` — it never pre-empts
|
||||||
|
// the parent's toggle, by design.)
|
||||||
|
await act(async () => {
|
||||||
|
window.dispatchEvent(
|
||||||
|
new KeyboardEvent("keydown", { key: "?", bubbles: true })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await settle(
|
||||||
|
() =>
|
||||||
|
document.body.querySelector('[data-testid="keyboard-cheatsheet"]') ===
|
||||||
|
null
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
document.body.querySelector('[data-testid="keyboard-cheatsheet"]')
|
||||||
|
).toBeNull();
|
||||||
|
|
||||||
|
// Unmount so the next test (which asserts the drawer is absent)
|
||||||
|
// doesn't see this test's still-open drawer leaking into
|
||||||
|
// document.body.
|
||||||
|
unmount();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("test_question_mark_does_nothing_when_drawer_closed", async () => {
|
||||||
|
// The `?` keystroke is owned by `useDrawerKeyboard`, which only
|
||||||
|
// attaches its `window` listener when `claimId !== null`. With no
|
||||||
|
// `?claim=` in the URL, the drawer is closed and `?` is a no-op
|
||||||
|
// — the cheatsheet must not appear.
|
||||||
|
setLocation("http://localhost/claims");
|
||||||
|
renderClaims();
|
||||||
|
|
||||||
|
// Wait for the table to populate (so the page is fully mounted).
|
||||||
|
await settle(
|
||||||
|
() => document.body.textContent?.includes("CLM-1") ?? false
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
document.body.querySelector('[data-testid="claim-drawer"]')
|
||||||
|
).toBeNull();
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
window.dispatchEvent(
|
||||||
|
new KeyboardEvent("keydown", { key: "?", bubbles: true })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// No cheatsheet should be present — and not just "not yet":
|
||||||
|
// flush a tick to make sure a delayed listener couldn't have
|
||||||
|
// snuck it in.
|
||||||
|
await act(async () => {
|
||||||
|
await new Promise((r) => setTimeout(r, 0));
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
document.body.querySelector('[data-testid="keyboard-cheatsheet"]')
|
||||||
|
).toBeNull();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
import { StatusBadge } from "@/components/StatusBadge";
|
import { StatusBadge } from "@/components/StatusBadge";
|
||||||
import { NewClaimDialog } from "@/components/NewClaimDialog";
|
import { NewClaimDialog } from "@/components/NewClaimDialog";
|
||||||
import { ClaimDrawer } from "@/components/ClaimDrawer";
|
import { ClaimDrawer } from "@/components/ClaimDrawer";
|
||||||
|
import { KeyboardCheatsheet } from "@/components/KeyboardCheatsheet";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
import { EmptyState } from "@/components/ui/empty-state";
|
import { EmptyState } from "@/components/ui/empty-state";
|
||||||
import { ErrorState } from "@/components/ui/error-state";
|
import { ErrorState } from "@/components/ui/error-state";
|
||||||
@@ -48,6 +49,7 @@ export function Claims() {
|
|||||||
const [npi, setNpi] = useState<string>(ALL);
|
const [npi, setNpi] = useState<string>(ALL);
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
|
const [helpOpen, setHelpOpen] = useState(false);
|
||||||
const searchRef = useRef<HTMLInputElement>(null);
|
const searchRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
// SP4 drawer wiring: the URL is the source of truth for "which claim is
|
// SP4 drawer wiring: the URL is the source of truth for "which claim is
|
||||||
@@ -114,9 +116,11 @@ export function Claims() {
|
|||||||
claims={items.map((c) => ({ id: c.id }))}
|
claims={items.map((c) => ({ id: c.id }))}
|
||||||
onClose={close}
|
onClose={close}
|
||||||
onNavigate={setClaimId}
|
onNavigate={setClaimId}
|
||||||
onToggleHelp={() => {
|
onToggleHelp={() => setHelpOpen((v) => !v)}
|
||||||
// T22 wires the KeyboardCheatsheet overlay; no-op for now.
|
/>
|
||||||
}}
|
<KeyboardCheatsheet
|
||||||
|
open={helpOpen}
|
||||||
|
onClose={() => setHelpOpen(false)}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
data-testid="claims-page-body"
|
data-testid="claims-page-body"
|
||||||
|
|||||||
Reference in New Issue
Block a user