Files
cyclone/src/components/drill/PayerPeekContent.test.tsx
T

80 lines
3.1 KiB
TypeScript

// @vitest-environment happy-dom
// PayerPeekContent uses useQuery internally via usePayerSummary. We mock
// that hook here so the component can be rendered without standing up a
// real QueryClient — same pattern as useClaimDetail.test.ts.
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
import { afterEach, describe, it, expect, vi } from "vitest";
import { cleanup, render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import type { ReactNode } from "react";
import { PayerPeekContent } from "@/components/drill/PayerPeekContent";
// Mock the hook BEFORE the import above is resolved (vitest hoists
// `vi.mock` to the top of the file regardless of where it appears
// syntactically).
vi.mock("@/hooks/usePayerSummary", () => ({
usePayerSummary: vi.fn(),
}));
// Importing after vi.mock so we get the mocked reference.
import { usePayerSummary } from "@/hooks/usePayerSummary";
// happy-dom keeps `document.body` between tests; without cleanup,
// `screen.getByText(...)` would find nodes from earlier renders.
afterEach(() => cleanup());
// The component renders <Link>, which requires a router context. A bare
// MemoryRouter with no initialEntries is enough — the test asserts on the
// generated href, not on navigation.
function withRouter(node: ReactNode) {
return <MemoryRouter>{node}</MemoryRouter>;
}
const SAMPLE_PAYER = {
payer_id: "SKCO0",
name: "CO Medicaid",
claim_count: 1247,
billed_total: 548000,
received_total: 521000,
denial_rate: 0.042,
top_providers: [{ npi: "1881068062", count: 184 }],
} as const;
describe("PayerPeekContent", () => {
it("renders loading skeleton while fetching", () => {
// Idle / in-flight state — `data` undefined, `isLoading` true.
// The component renders <Skeleton variant="row" /> rows and no text,
// so the regex match for /claims/i must come back null (the
// "View all claims" link only renders once data is present).
(usePayerSummary as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
data: undefined,
isLoading: true,
});
render(withRouter(<PayerPeekContent payerId="SKCO0" />));
expect(screen.queryByText(/claims/i)).toBeNull();
});
it("renders summary stats when data loads", () => {
(usePayerSummary as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
data: SAMPLE_PAYER,
isLoading: false,
});
render(withRouter(<PayerPeekContent payerId="SKCO0" />));
expect(screen.getByText("CO Medicaid")).toBeTruthy();
// fmt.num(1247) === "1,247" — the "184 claims" line also matches this
// regex, but getByText with a regex is fine because we only assert
// existence.
expect(screen.getByText(/1,247/)).toBeTruthy();
expect(screen.getByText("$548,000")).toBeTruthy();
// denial_rate is a fraction (0.042); fmt.pct(payer.denial_rate * 100)
// yields "4.2%".
expect(screen.getByText("4.2%")).toBeTruthy();
const link = screen.getByRole("link", { name: /view all claims/i });
expect(link.getAttribute("href")).toBe("/claims?payer=SKCO0");
});
});