import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { cleanup, render } from "@testing-library/react"; import type { ReactNode } from "react"; import { afterEach, vi } from "vitest"; afterEach(cleanup); /** Same defaults as the app's Providers, but retries fire immediately. */ export function testQueryClient() { return new QueryClient({ defaultOptions: { queries: { staleTime: 0, retry: 1, retryDelay: 0 }, mutations: { retry: false }, }, }); } export function renderWithQuery(ui: ReactNode, client = testQueryClient()) { const wrapper = ({ children }: { children: ReactNode }) => ( {children} ); return { client, ...render(ui, { wrapper }) }; } type Handler = (init: RequestInit | undefined) => Response | Promise; /** * Stubs global fetch with handlers keyed by "METHOD /path". Unmatched requests fail the * test loudly instead of hitting the network. */ export function stubFetch(routes: Record) { const fetchMock = vi.fn(async (input: RequestInfo | URL, init?: RequestInit) => { const url = new URL(String(input), "http://localhost"); const key = `${init?.method ?? "GET"} ${url.pathname}`; const handler = routes[key]; if (!handler) throw new Error(`Unexpected fetch: ${key}`); return handler(init); }); vi.stubGlobal("fetch", fetchMock); return fetchMock; } export const json = (body: unknown, status = 200) => Response.json(body, { status }); export const calls = (fetchMock: ReturnType, key: string) => fetchMock.mock.calls.filter( ([input, init]) => `${init?.method ?? "GET"} ${new URL(String(input), "http://localhost").pathname}` === key, );