84 lines
2.6 KiB
TypeScript
84 lines
2.6 KiB
TypeScript
// @vitest-environment jsdom
|
|
|
|
import { act, render, screen, waitFor } from "@testing-library/react";
|
|
import { afterEach, describe, expect, it } from "vitest";
|
|
|
|
import { createServerStateScopeRuntime } from "../../src/adapters/query-cache/server-state-scope-runtime.ts";
|
|
import { ServerStateScopeProvider } from "../../src/presentation/adapters/query/server-state-scope-provider.tsx";
|
|
|
|
const activeRuntimes: Array<{ dispose(): void }> = [];
|
|
|
|
afterEach(() => {
|
|
for (const runtime of activeRuntimes.splice(0)) runtime.dispose();
|
|
});
|
|
|
|
function scopeFixture(resetLocal: () => Promise<void>) {
|
|
let sessionListener: () => void = () => {};
|
|
let token = 0;
|
|
const runtime = createServerStateScopeRuntime({
|
|
session: {
|
|
subscribe(listener) {
|
|
sessionListener = listener;
|
|
return () => {};
|
|
},
|
|
},
|
|
queryInvalidation: {
|
|
resetLocal,
|
|
},
|
|
tokenFactory: () => `scope-provider-token-${String(token++).padStart(4, "0")}`,
|
|
});
|
|
activeRuntimes.push(runtime);
|
|
return { runtime, triggerSessionChange: () => sessionListener() };
|
|
}
|
|
|
|
describe("server-state scope provider", () => {
|
|
it("removes previous-scope children synchronously while reset is pending", async () => {
|
|
let completeReset: () => void = () => {};
|
|
const reset = new Promise<void>((resolve) => {
|
|
completeReset = resolve;
|
|
});
|
|
const fixture = scopeFixture(async () => reset);
|
|
|
|
render(
|
|
<ServerStateScopeProvider
|
|
runtime={fixture.runtime}
|
|
transitionFallback={<div>scope-transition</div>}
|
|
>
|
|
<div>previous-account-secret</div>
|
|
</ServerStateScopeProvider>,
|
|
);
|
|
|
|
expect(screen.getByText("previous-account-secret")).toBeVisible();
|
|
|
|
act(() => fixture.triggerSessionChange());
|
|
|
|
expect(screen.queryByText("previous-account-secret")).toBeNull();
|
|
expect(screen.getByText("scope-transition")).toBeVisible();
|
|
|
|
completeReset();
|
|
await waitFor(() =>
|
|
expect(screen.getByText("previous-account-secret")).toBeVisible(),
|
|
);
|
|
});
|
|
|
|
it("never remounts previous-scope children after mandatory cleanup failure", async () => {
|
|
const fixture = scopeFixture(async () => {
|
|
throw new Error("reset failed");
|
|
});
|
|
render(
|
|
<ServerStateScopeProvider
|
|
runtime={fixture.runtime}
|
|
transitionFallback={<div>scope-transition</div>}
|
|
>
|
|
<div>previous-account-secret</div>
|
|
</ServerStateScopeProvider>,
|
|
);
|
|
|
|
act(() => fixture.triggerSessionChange());
|
|
|
|
await waitFor(() => expect(fixture.runtime.getPhase()).toBe("FAILED"));
|
|
expect(screen.queryByText("previous-account-secret")).toBeNull();
|
|
expect(screen.getByText("scope-transition")).toBeVisible();
|
|
});
|
|
});
|