import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import type { ReactNode } from "react"; import { MutationIntentProvider } from "../../src/presentation/adapters/query/mutation-intent-provider.tsx"; import { QueryInvalidationProvider } from "../../src/presentation/adapters/query/query-invalidation-provider.tsx"; import type { MutationIntentFactory } from "../../src/application/ports/mutation-intent-factory.ts"; import type { QueryInvalidationCoordinator } from "../../src/contracts/query-invalidation.ts"; /** * The provider stack `useApplicationQuery` needs, in the order the running app * assembles it (`ServerStateGenerationProvider`). * * A component test that renders a screen reading server state has to supply * this or the render throws "No QueryClient set" — which is not a test-harness * quirk but the same failure the app would produce if it were mounted without * its query layer. */ export function renderWithQueryProviders(children: ReactNode): ReactNode { const client = new QueryClient({ defaultOptions: { // Deterministic: a component test asserts on one settled render, so a // retry would only turn a real failure into a timeout. queries: { retry: false, staleTime: 0, gcTime: Infinity }, mutations: { retry: false }, }, }); const coordinator: QueryInvalidationCoordinator = { async invalidate(topics) { for (const topic of topics) { await client.invalidateQueries({ queryKey: [topic], exact: false, refetchType: "active", }); } }, beginMutation() { return { release: async () => {} }; }, async resetLocal() { await client.cancelQueries(); client.clear(); }, dispose() {}, }; let sequence = 0; const mutationIntentFactory: MutationIntentFactory = Object.freeze({ create(input) { sequence += 1; return Object.freeze({ intentId: `intent-${sequence}`, operationId: input.operationId, canonicalInputIdentity: input.canonicalInputIdentity, ...(input.requiresIdempotencyKey ? { idempotencyKey: `key-${sequence}` } : {}), createdAtMonotonicMs: sequence, }); }, }); return ( {children} ); }