// @vitest-environment happy-dom (globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true; import { describe, expect, it, vi, beforeEach } from "vitest"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { renderHook, waitFor } from "@testing-library/react"; import type { ReactNode } from "react"; // Mock the API module so the hook doesn't touch the real /api/acks endpoint. // The mock mirrors the wire shape that listAcks returns. vi.mock("@/lib/api", () => ({ api: { isConfigured: true, listAcks: vi.fn().mockResolvedValue({ items: [], total: 1161, returned: 0, has_more: false, aggregates: { accepted: 1156, rejected: 5, received: 1161 }, }), }, })); import { useAckStats } from "./useAckStats"; function withClient(): (props: { children: ReactNode }) => ReactNode { const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } }); return ({ children }) => ( {children} ); } describe("useAckStats", () => { beforeEach(() => { vi.clearAllMocks(); }); it("returns server-computed aggregates for sidebar badge use", async () => { const { result } = renderHook(() => useAckStats(), { wrapper: withClient() }); await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(result.current.data?.aggregates.rejected).toBe(5); expect(result.current.data?.aggregates.accepted).toBe(1156); }); it("calls listAcks with limit=1 so the lightweight payload is smallest", async () => { const { api } = await import("@/lib/api"); renderHook(() => useAckStats(), { wrapper: withClient() }); await waitFor(() => expect(api.listAcks).toHaveBeenCalled()); expect(api.listAcks).toHaveBeenCalledWith({ limit: 1 }); }); });