Skip to content

Commit

Permalink
Add tests to ensure suspense fragment is torn down
Browse files Browse the repository at this point in the history
  • Loading branch information
jerelmiller committed Dec 19, 2024
1 parent 9aa3eed commit ef27883
Showing 1 changed file with 111 additions and 1 deletion.
112 changes: 111 additions & 1 deletion src/react/hooks/__tests__/useSuspenseFragment.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
import { spyOnConsole } from "../../../testing/internal";
import { renderHook } from "@testing-library/react";
import { InvariantError } from "ts-invariant";
import { MockedProvider } from "../../../testing";
import { MockedProvider, wait } from "../../../testing";
import { expectTypeOf } from "expect-type";

function createDefaultRenderStream<TData = unknown>() {
Expand Down Expand Up @@ -1456,6 +1456,116 @@ test("updates child fragments for cache updates to masked fields", async () => {
await expect(takeRender).not.toRerender();
});

test("tears down the subscription on unmount", async () => {
interface ItemFragment {
__typename: "Item";
id: number;
text: string;
}

const fragment: TypedDocumentNode<ItemFragment> = gql`
fragment ItemFragment on Item {
id
text
}
`;

const cache = new InMemoryCache();
const client = new ApolloClient({ cache });

client.writeFragment({
fragment,
data: { __typename: "Item", id: 1, text: "Item #1" },
});

using _disabledAct = disableActEnvironment();
const { unmount, takeSnapshot } = await renderHookToSnapshotStream(
() =>
useSuspenseFragment({ fragment, from: { __typename: "Item", id: 1 } }),
{
wrapper: ({ children }) => (
<ApolloProvider client={client}>{children}</ApolloProvider>
),
}
);

{
const { data } = await takeSnapshot();

expect(data).toEqual({ __typename: "Item", id: 1, text: "Item #1" });
}

expect(cache["watches"].size).toBe(1);

unmount();
// We need to wait a tick since the cleanup is run in a setTimeout to
// prevent strict mode bugs.
await wait(0);

expect(cache["watches"].size).toBe(0);
});

test("tears down all watches when rendering multiple records", async () => {
interface ItemFragment {
__typename: "Item";
id: number;
text: string;
}

const fragment: TypedDocumentNode<ItemFragment> = gql`
fragment ItemFragment on Item {
id
text
}
`;

const cache = new InMemoryCache();
const client = new ApolloClient({ cache });

client.writeFragment({
fragment,
data: { __typename: "Item", id: 1, text: "Item #1" },
});

client.writeFragment({
fragment,
data: { __typename: "Item", id: 2, text: "Item #2" },
});

using _disabledAct = disableActEnvironment();
const { unmount, rerender, takeSnapshot } = await renderHookToSnapshotStream(
({ id }) =>
useSuspenseFragment({ fragment, from: { __typename: "Item", id } }),
{
initialProps: { id: 1 },
wrapper: ({ children }) => (
<ApolloProvider client={client}>{children}</ApolloProvider>
),
}
);

{
const { data } = await takeSnapshot();

expect(data).toEqual({ __typename: "Item", id: 1, text: "Item #1" });
}

await rerender({ id: 2 });

{
const { data } = await takeSnapshot();

expect(data).toEqual({ __typename: "Item", id: 2, text: "Item #2" });
}

unmount();
// We need to wait a tick since the cleanup is run in a setTimeout to
// prevent strict mode bugs.
await wait(0);

expect(cache["watches"].size).toBe(0);
});

describe.skip("type tests", () => {
test("returns TData when from is a non-null value", () => {
const fragment: TypedDocumentNode<{ foo: string }> = gql``;
Expand Down

0 comments on commit ef27883

Please sign in to comment.