Files
tech-log-frontend/tests/component/server-state-generation-provider.test.tsx

81 lines
2.8 KiB
TypeScript

// @vitest-environment jsdom
import { act, render, waitFor } from "@testing-library/react";
import { QueryClient, useQueryClient } from "@tanstack/react-query";
import { describe, expect, it } from "vitest";
import { createServerStateScopeRuntime } from "../../src/adapters/query-cache/server-state-scope-runtime.ts";
import { createServerStateGenerationStore } from "../../src/bootstrap/server-state-generation-store.ts";
import { ServerStateGenerationProvider } from "../../src/presentation/adapters/query/server-state-generation-provider.tsx";
describe("server-state generation provider", () => {
it("remounts consumers with the QueryClient owned by the READY generation", async () => {
const store = createServerStateGenerationStore(() => {
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
});
return {
queryClient,
queryInvalidation: {
invalidate: async () => {},
beginMutation: () => ({ release: async () => {} }),
resetLocal: async () => {
await queryClient.cancelQueries();
queryClient.clear();
},
dispose() {},
},
crossContextStatus: () => "DEGRADED_LOCAL_ONLY" as const,
};
});
let sessionListener: () => void = () => {};
let token = 0;
const scope = createServerStateScopeRuntime({
session: {
subscribe(listener) {
sessionListener = listener;
return () => {};
},
},
queryInvalidation: { resetLocal: () => store.resetCurrent() },
activateNextGeneration: () => store.activateNext(),
tokenFactory: () =>
`scope-generation-provider-${String(token++).padStart(4, "0")}`,
});
const renderedClients: QueryClient[] = [];
const mutationIntentFactory = Object.freeze({
create() {
throw new Error("mutation intent is unused by this provider test");
},
});
function Probe() {
renderedClients.push(useQueryClient());
return <div>generation-content</div>;
}
render(
<ServerStateGenerationProvider
store={store}
scope={scope}
mutationIntentFactory={mutationIntentFactory}
transitionFallback={<div>scope-transition</div>}
>
<Probe />
</ServerStateGenerationProvider>,
);
const firstClient = renderedClients.at(-1);
if (!firstClient) throw new Error("expected initial QueryClient");
act(() => sessionListener());
await waitFor(() => expect(scope.getPhase()).toBe("READY"));
await waitFor(() =>
expect(renderedClients.at(-1)).toBe(store.getSnapshot().queryClient),
);
expect(renderedClients.at(-1)).not.toBe(firstClient);
scope.dispose();
store.dispose();
});
});