From b116df8886f8e74ed6f411fa50eb98d012b106d7 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Tue, 11 Jun 2024 16:01:34 +0200 Subject: [PATCH 01/11] add delay to test --- src/react/hooks/__tests__/useQuery.test.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/react/hooks/__tests__/useQuery.test.tsx b/src/react/hooks/__tests__/useQuery.test.tsx index f900f61bbda..e35dda97e03 100644 --- a/src/react/hooks/__tests__/useQuery.test.tsx +++ b/src/react/hooks/__tests__/useQuery.test.tsx @@ -23,6 +23,7 @@ import { mockSingleLink, tick, wait, + MockedResponse, } from "../../../testing"; import { QueryResult } from "../../types/types"; import { useQuery } from "../useQuery"; @@ -1925,18 +1926,21 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the } `; - const mocks = [ + const mocks: MockedResponse[] = [ { request: { query }, result: { data: { hello: "world 1" } }, + delay: 3, }, { request: { query }, result: { data: { hello: "world 2" } }, + delay: 3, }, { request: { query }, result: { data: { hello: "world 3" } }, + delay: 3, }, ]; From fae760c33120ab6f2245c956dd621f1d2c8f575f Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Tue, 11 Jun 2024 17:00:45 +0200 Subject: [PATCH 02/11] wip --- .../hooks/__tests__/useLazyQuery.test.tsx | 73 ++++++++++-------- src/react/hooks/__tests__/useQuery.test.tsx | 77 +++++++++++-------- 2 files changed, 90 insertions(+), 60 deletions(-) diff --git a/src/react/hooks/__tests__/useLazyQuery.test.tsx b/src/react/hooks/__tests__/useLazyQuery.test.tsx index 34981cf9b4e..d41444953d4 100644 --- a/src/react/hooks/__tests__/useLazyQuery.test.tsx +++ b/src/react/hooks/__tests__/useLazyQuery.test.tsx @@ -42,7 +42,7 @@ describe("useLazyQuery Hook", () => { { request: { query: helloQuery }, result: { data: { hello: "world" } }, - delay: 20, + delay: 50, }, ]; const { result } = renderHook(() => useLazyQuery(helloQuery), { @@ -147,26 +147,29 @@ describe("useLazyQuery Hook", () => { } ); - expect(result.current[1].loading).toBe(false); - expect(result.current[1].called).toBe(false); + let currentResult = result.current[1]; + expect(currentResult.loading).toBe(false); + expect(currentResult.called).toBe(false); const execute = result.current[0]; setTimeout(() => execute()); await waitFor( () => { - expect(result.current[1].loading).toBe(true); + currentResult = result.current[1]; + expect(currentResult.loading).toBe(true); }, { interval: 1 } ); - expect(result.current[1].called).toBe(true); + expect(currentResult.called).toBe(true); await waitFor( () => { - expect(result.current[1].loading).toBe(false); + currentResult = result.current[1]; + expect(currentResult.loading).toBe(false); }, { interval: 1 } ); - expect(result.current[1].called).toBe(true); + expect(currentResult.called).toBe(true); }); it("should use variables defined in hook options (if any), when running the lazy execution function", async () => { @@ -552,43 +555,48 @@ describe("useLazyQuery Hook", () => { ), }); - expect(result.current[1].loading).toBe(false); - expect(result.current[1].data).toBe(undefined); + let currentResult = result.current[1]; + expect(currentResult.loading).toBe(false); + expect(currentResult.data).toBe(undefined); const execute = result.current[0]; setTimeout(() => execute()); await waitFor( () => { - expect(result.current[1].loading).toBe(true); + currentResult = result.current[1]; + expect(currentResult.loading).toBe(true); }, { interval: 1 } ); await waitFor( () => { - expect(result.current[1].loading).toBe(false); + currentResult = result.current[1]; + expect(currentResult.loading).toBe(false); }, { interval: 1 } ); - expect(result.current[1].data).toEqual({ hello: "world" }); + expect(currentResult.data).toEqual({ hello: "world" }); setTimeout(() => execute({ query: query2 })); await waitFor( () => { - expect(result.current[1].loading).toBe(true); + currentResult = result.current[1]; + expect(currentResult.loading).toBe(true); }, { interval: 1 } ); await waitFor( () => { - expect(result.current[1].loading).toBe(false); + currentResult = result.current[1]; + expect(currentResult.loading).toBe(false); }, { interval: 1 } ); - expect(result.current[1].data).toEqual({ name: "changed" }); + expect(currentResult.data).toEqual({ name: "changed" }); }); it('should fetch data each time the execution function is called, when using a "network-only" fetch policy', async () => { @@ -833,50 +841,55 @@ describe("useLazyQuery Hook", () => { {children} ), }); + let currentResult = result.current[1]; - expect(result.current[1].loading).toBe(false); - expect(result.current[1].data).toBe(undefined); - expect(result.current[1].previousData).toBe(undefined); + expect(currentResult.loading).toBe(false); + expect(currentResult.data).toBe(undefined); + expect(currentResult.previousData).toBe(undefined); const execute = result.current[0]; setTimeout(() => execute({ variables: { id: 1 } })); await waitFor( () => { - expect(result.current[1].loading).toBe(true); + currentResult = result.current[1]; + expect(currentResult.loading).toBe(true); }, { interval: 1 } ); - expect(result.current[1].data).toBe(undefined); - expect(result.current[1].previousData).toBe(undefined); + expect(currentResult.data).toBe(undefined); + expect(currentResult.previousData).toBe(undefined); await waitFor( () => { - expect(result.current[1].loading).toBe(false); + currentResult = result.current[1]; + expect(currentResult.loading).toBe(false); }, { interval: 1 } ); - expect(result.current[1].data).toEqual(data1); - expect(result.current[1].previousData).toBe(undefined); + expect(currentResult!.data).toEqual(data1); + expect(currentResult!.previousData).toBe(undefined); setTimeout(() => execute({ variables: { id: 2 } })); await waitFor( () => { - expect(result.current[1].loading).toBe(true); + currentResult = result.current[1]; + expect(currentResult.loading).toBe(true); }, { interval: 1 } ); - expect(result.current[1].data).toBe(undefined); - expect(result.current[1].previousData).toEqual(data1); + expect(currentResult.data).toBe(undefined); + expect(currentResult.previousData).toEqual(data1); await waitFor( () => { - expect(result.current[1].loading).toBe(false); + currentResult = result.current[1]; + expect(currentResult.loading).toBe(false); }, { interval: 1 } ); - expect(result.current[1].data).toEqual(data2); - expect(result.current[1].previousData).toEqual(data1); + expect(currentResult.data).toEqual(data2); + expect(currentResult.previousData).toEqual(data1); }); it("should work with cache-and-network fetch policy", async () => { diff --git a/src/react/hooks/__tests__/useQuery.test.tsx b/src/react/hooks/__tests__/useQuery.test.tsx index e35dda97e03..86138cceb33 100644 --- a/src/react/hooks/__tests__/useQuery.test.tsx +++ b/src/react/hooks/__tests__/useQuery.test.tsx @@ -770,6 +770,7 @@ describe("useQuery Hook", () => { { request: { query: query1 }, result: { data: allPeopleData }, + delay: 3, }, { request: { query: query2 }, @@ -811,6 +812,7 @@ describe("useQuery Hook", () => { ); await waitFor( () => { + // flaky here too expect(result.current[1].loading).toBe(true); }, { interval: 1 } @@ -1841,18 +1843,21 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the hello } `; - const mocks = [ + const mocks: MockedResponse[] = [ { request: { query }, result: { data: { hello: "world 1" } }, + delay: 10, }, { request: { query }, result: { data: { hello: "world 2" } }, + delay: 10, }, { request: { query }, result: { data: { hello: "world 3" } }, + delay: 10, }, ]; @@ -1869,22 +1874,25 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the ); const { result, unmount } = renderHook( - () => useQuery(query, { pollInterval: 10 }), + () => useQuery(query, { pollInterval: 20 }), { wrapper } ); - expect(result.current.loading).toBe(true); - expect(result.current.data).toBe(undefined); + let currentResult = result.current; + expect(currentResult.loading).toBe(true); + expect(currentResult.data).toBe(undefined); await waitFor( () => { - expect(result.current.loading).toBe(false); + currentResult = result.current; + expect(currentResult.loading).toBe(false); }, { interval: 1 } ); await waitFor( () => { - expect(result.current.data).toEqual({ hello: "world 1" }); + currentResult = result.current; + expect(currentResult.data).toEqual({ hello: "world 1" }); }, { interval: 1 } ); @@ -1906,7 +1914,7 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the const newRequestCount = requestSpy.mock.calls.length; expect(newRequestCount).toBeGreaterThan(requestCount); }, - { interval: 1, timeout: 20 } + { interval: 1, timeout: 40 } ) ).rejects.toThrow(); @@ -2082,18 +2090,21 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the } `; - const mocks = [ + const mocks: MockedResponse[] = [ { request: { query }, result: { data: { hello: "world 1" } }, + delay: 3, }, { request: { query }, result: { data: { hello: "world 2" } }, + delay: 3, }, { request: { query }, result: { data: { hello: "world 3" } }, + delay: 3, }, ]; @@ -3738,63 +3749,69 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the { wrapper } ); - expect(result.current.loading).toBe(true); - expect(result.current.data).toBe(undefined); - expect(result.current.error).toBe(undefined); + let currentResult = result.current; + expect(currentResult.loading).toBe(true); + expect(currentResult.data).toBe(undefined); + expect(currentResult.error).toBe(undefined); await waitFor( () => { - expect(result.current.loading).toBe(false); + currentResult = result.current; + expect(currentResult.loading).toBe(false); }, { interval: 1 } ); - expect(result.current.data).toBe(undefined); - expect(result.current.error).toBeInstanceOf(ApolloError); - expect(result.current.error!.message).toBe("same error"); + expect(currentResult.data).toBe(undefined); + expect(currentResult.error).toBeInstanceOf(ApolloError); + expect(currentResult.error!.message).toBe("same error"); - result.current.refetch(); + currentResult.refetch(); await waitFor( () => { - expect(result.current.loading).toBe(true); + currentResult = result.current; + expect(currentResult.loading).toBe(true); }, { interval: 1 } ); - expect(result.current.data).toBe(undefined); - expect(result.current.error).toBe(undefined); + expect(currentResult.data).toBe(undefined); + expect(currentResult.error).toBe(undefined); await waitFor( () => { - expect(result.current.loading).toBe(false); + currentResult = result.current; + expect(currentResult.loading).toBe(false); }, { interval: 1 } ); - expect(result.current.data).toEqual({ hello: "world" }); - expect(result.current.error).toBe(undefined); + expect(currentResult.data).toEqual({ hello: "world" }); + expect(currentResult.error).toBe(undefined); const catchFn = jest.fn(); - result.current.refetch().catch(catchFn); + currentResult.refetch().catch(catchFn); await waitFor( () => { - expect(result.current.loading).toBe(true); + currentResult = result.current; + expect(currentResult.loading).toBe(true); }, { interval: 1 } ); - expect(result.current.data).toEqual({ hello: "world" }); - expect(result.current.error).toBe(undefined); + expect(currentResult.data).toEqual({ hello: "world" }); + expect(currentResult.error).toBe(undefined); await waitFor( () => { - expect(result.current.loading).toBe(false); + currentResult = result.current; + expect(currentResult.loading).toBe(false); }, { interval: 1 } ); // TODO: Is this correct behavior here? - expect(result.current.data).toEqual({ hello: "world" }); - expect(result.current.error).toBeInstanceOf(ApolloError); - expect(result.current.error!.message).toBe("same error"); + expect(currentResult.data).toEqual({ hello: "world" }); + expect(currentResult.error).toBeInstanceOf(ApolloError); + expect(currentResult.error!.message).toBe("same error"); expect(catchFn.mock.calls.length).toBe(1); expect(catchFn.mock.calls[0].length).toBe(1); From 572ccc939305378598660c487623a0fd12d2a3dd Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 12 Jun 2024 14:54:57 +0200 Subject: [PATCH 03/11] rewrite some tests with profiler --- src/react/hooks/__tests__/useQuery.test.tsx | 248 ++++++++------------ 1 file changed, 96 insertions(+), 152 deletions(-) diff --git a/src/react/hooks/__tests__/useQuery.test.tsx b/src/react/hooks/__tests__/useQuery.test.tsx index 86138cceb33..fe9d941a26f 100644 --- a/src/react/hooks/__tests__/useQuery.test.tsx +++ b/src/react/hooks/__tests__/useQuery.test.tsx @@ -783,77 +783,49 @@ describe("useQuery Hook", () => { link, cache: new InMemoryCache(), }); + const ProfiledHook = profileHook(() => [ + useQuery(query1, { fetchPolicy: "no-cache" }), + useQuery(query2), + ]); + const { rerender } = render(, { + wrapper: ({ children }) => ( + {children} + ), + }); - const { result, rerender } = renderHook( - () => [useQuery(query1, { fetchPolicy: "no-cache" }), useQuery(query2)], - { - wrapper: ({ children }) => ( - {children} - ), - } - ); - - expect(result.current[0].loading).toBe(true); - expect(result.current[0].data).toBe(undefined); - expect(result.current[1].loading).toBe(true); - expect(result.current[1].data).toBe(undefined); + { + const [result0, result1] = await ProfiledHook.takeSnapshot(); + expect(result0.loading).toBe(true); + expect(result0.data).toStrictEqual(undefined); + expect(result1.loading).toBe(true); + expect(result1.data).toStrictEqual(undefined); + } - await waitFor( - () => { - expect(result.current[0].loading).toBe(false); - }, - { interval: 1 } - ); - await waitFor( - () => { - expect(result.current[0].data).toEqual(allPeopleData); - }, - { interval: 1 } - ); - await waitFor( - () => { - // flaky here too - expect(result.current[1].loading).toBe(true); - }, - { interval: 1 } - ); - await waitFor( - () => { - expect(result.current[1].data).toBe(undefined); - }, - { interval: 1 } - ); + { + const [result0, result1] = await ProfiledHook.takeSnapshot(); + expect(result0.loading).toBe(false); + expect(result0.data).toStrictEqual(allPeopleData); + expect(result1.loading).toBe(true); + expect(result1.data).toStrictEqual(undefined); + } - await waitFor( - () => { - expect(result.current[0].loading).toBe(false); - }, - { interval: 1 } - ); - await waitFor( - () => { - expect(result.current[0].data).toEqual(allPeopleData); - }, - { interval: 1 } - ); - await waitFor( - () => { - expect(result.current[1].loading).toBe(false); - }, - { interval: 1 } - ); - await waitFor( - () => { - expect(result.current[1].data).toEqual(allThingsData); - }, - { interval: 1 } - ); + { + const [result0, result1] = await ProfiledHook.takeSnapshot(); + expect(result0.loading).toBe(false); + expect(result0.data).toStrictEqual(allPeopleData); + expect(result1.loading).toBe(false); + expect(result1.data).toStrictEqual(allThingsData); + } - rerender(); - expect(result.current[0].loading).toBe(false); - expect(result.current[0].data).toEqual(allPeopleData); - expect(result.current[1].loading).toBe(false); - expect(result.current[1].data).toEqual(allThingsData); + rerender(); + { + const [result0, result1] = await ProfiledHook.takeSnapshot(); + expect(result0.loading).toBe(false); + expect(result0.data).toStrictEqual(allPeopleData); + expect(result1.loading).toBe(false); + expect(result1.data).toStrictEqual(allThingsData); + } + await expect(ProfiledHook).not.toRerender(); }); it("changing queries", async () => { @@ -1873,33 +1845,24 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the ); - const { result, unmount } = renderHook( - () => useQuery(query, { pollInterval: 20 }), - { wrapper } + const ProfiledHook = profileHook(() => + useQuery(query, { pollInterval: 20 }) ); - let currentResult = result.current; - expect(currentResult.loading).toBe(true); - expect(currentResult.data).toBe(undefined); + const { unmount } = render(, { wrapper }); - await waitFor( - () => { - currentResult = result.current; - expect(currentResult.loading).toBe(false); - }, - { interval: 1 } - ); - await waitFor( - () => { - currentResult = result.current; - expect(currentResult.data).toEqual({ hello: "world 1" }); - }, - { interval: 1 } - ); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toBe(undefined); + } - await waitFor(() => { + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toEqual({ hello: "world 1" }); expect(requestSpy).toHaveBeenCalled(); - }); + } const requestCount = requestSpy.mock.calls.length; expect(requestCount).toBeGreaterThan(0); @@ -3744,74 +3707,55 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the ); - const { result } = renderHook( - () => useQuery(query, { notifyOnNetworkStatusChange: true }), - { wrapper } - ); - - let currentResult = result.current; - expect(currentResult.loading).toBe(true); - expect(currentResult.data).toBe(undefined); - expect(currentResult.error).toBe(undefined); - - await waitFor( - () => { - currentResult = result.current; - expect(currentResult.loading).toBe(false); - }, - { interval: 1 } - ); - - expect(currentResult.data).toBe(undefined); - expect(currentResult.error).toBeInstanceOf(ApolloError); - expect(currentResult.error!.message).toBe("same error"); - - currentResult.refetch(); - - await waitFor( - () => { - currentResult = result.current; - expect(currentResult.loading).toBe(true); - }, - { interval: 1 } + const ProfiledHook = profileHook(() => + useQuery(query, { notifyOnNetworkStatusChange: true }) ); - expect(currentResult.data).toBe(undefined); - expect(currentResult.error).toBe(undefined); + render(, { wrapper }); - await waitFor( - () => { - currentResult = result.current; - expect(currentResult.loading).toBe(false); - }, - { interval: 1 } - ); - expect(currentResult.data).toEqual({ hello: "world" }); - expect(currentResult.error).toBe(undefined); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toBe(undefined); + expect(result.error).toBe(undefined); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toBe(undefined); + expect(result.error).toBeInstanceOf(ApolloError); + expect(result.error!.message).toBe("same error"); + } + ProfiledHook.getCurrentSnapshot().refetch(); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toBe(undefined); + expect(result.error).toBe(undefined); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toEqual({ hello: "world" }); + expect(result.error).toBe(undefined); + } const catchFn = jest.fn(); - currentResult.refetch().catch(catchFn); + ProfiledHook.getCurrentSnapshot().refetch().catch(catchFn); - await waitFor( - () => { - currentResult = result.current; - expect(currentResult.loading).toBe(true); - }, - { interval: 1 } - ); - expect(currentResult.data).toEqual({ hello: "world" }); - expect(currentResult.error).toBe(undefined); - - await waitFor( - () => { - currentResult = result.current; - expect(currentResult.loading).toBe(false); - }, - { interval: 1 } - ); - // TODO: Is this correct behavior here? - expect(currentResult.data).toEqual({ hello: "world" }); - expect(currentResult.error).toBeInstanceOf(ApolloError); - expect(currentResult.error!.message).toBe("same error"); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toEqual({ hello: "world" }); + expect(result.error).toBe(undefined); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + // TODO: Is this correct behavior here? + expect(result.data).toEqual({ hello: "world" }); + expect(result.error).toBeInstanceOf(ApolloError); + expect(result.error!.message).toBe("same error"); + } expect(catchFn.mock.calls.length).toBe(1); expect(catchFn.mock.calls[0].length).toBe(1); From 5f04f7419fd527b0e79d71e17f656dabe70d560a Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 12 Jun 2024 15:08:19 +0200 Subject: [PATCH 04/11] refactor tests to use the profiler --- .../hooks/__tests__/useLazyQuery.test.tsx | 189 ++++++++---------- src/react/hooks/__tests__/useQuery.test.tsx | 1 + 2 files changed, 83 insertions(+), 107 deletions(-) diff --git a/src/react/hooks/__tests__/useLazyQuery.test.tsx b/src/react/hooks/__tests__/useLazyQuery.test.tsx index d41444953d4..6d2c10cd51c 100644 --- a/src/react/hooks/__tests__/useLazyQuery.test.tsx +++ b/src/react/hooks/__tests__/useLazyQuery.test.tsx @@ -137,39 +137,35 @@ describe("useLazyQuery Hook", () => { }, ]; - const { result } = renderHook( + const ProfiledHook = profileHook( // skip isn’t actually an option on the types - () => useLazyQuery(helloQuery, { skip: true } as any), - { - wrapper: ({ children }) => ( - {children} - ), - } + () => useLazyQuery(helloQuery, { skip: true } as any) ); + render(, { + wrapper: ({ children }) => ( + {children} + ), + }); - let currentResult = result.current[1]; - expect(currentResult.loading).toBe(false); - expect(currentResult.called).toBe(false); - const execute = result.current[0]; + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.called).toBe(false); + } + const execute = ProfiledHook.getCurrentSnapshot()[0]; setTimeout(() => execute()); - await waitFor( - () => { - currentResult = result.current[1]; - expect(currentResult.loading).toBe(true); - }, - { interval: 1 } - ); - expect(currentResult.called).toBe(true); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.called).toBe(true); + } - await waitFor( - () => { - currentResult = result.current[1]; - expect(currentResult.loading).toBe(false); - }, - { interval: 1 } - ); - expect(currentResult.called).toBe(true); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.called).toBe(true); + } }); it("should use variables defined in hook options (if any), when running the lazy execution function", async () => { @@ -547,7 +543,8 @@ describe("useLazyQuery Hook", () => { ]; const cache = new InMemoryCache(); - const { result } = renderHook(() => useLazyQuery(query1), { + const ProfiledHook = profileHook(() => useLazyQuery(query1)); + render(, { wrapper: ({ children }) => ( {children} @@ -555,48 +552,37 @@ describe("useLazyQuery Hook", () => { ), }); - let currentResult = result.current[1]; - expect(currentResult.loading).toBe(false); - expect(currentResult.data).toBe(undefined); - const execute = result.current[0]; + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toBe(undefined); + } + const execute = ProfiledHook.getCurrentSnapshot()[0]; setTimeout(() => execute()); - await waitFor( - () => { - currentResult = result.current[1]; - expect(currentResult.loading).toBe(true); - }, - { interval: 1 } - ); - - await waitFor( - () => { - currentResult = result.current[1]; - expect(currentResult.loading).toBe(false); - }, - { interval: 1 } - ); - expect(currentResult.data).toEqual({ hello: "world" }); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + } + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toEqual({ hello: "world" }); + } setTimeout(() => execute({ query: query2 })); - await waitFor( - () => { - currentResult = result.current[1]; - expect(currentResult.loading).toBe(true); - }, - { interval: 1 } - ); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + } - await waitFor( - () => { - currentResult = result.current[1]; - expect(currentResult.loading).toBe(false); - }, - { interval: 1 } - ); - expect(currentResult.data).toEqual({ name: "changed" }); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toEqual({ name: "changed" }); + } }); it('should fetch data each time the execution function is called, when using a "network-only" fetch policy', async () => { @@ -836,60 +822,49 @@ describe("useLazyQuery Hook", () => { }, ]; - const { result } = renderHook(() => useLazyQuery(CAR_QUERY_BY_ID), { + const ProfiledHook = profileHook(() => useLazyQuery(CAR_QUERY_BY_ID)); + render(, { wrapper: ({ children }) => ( {children} ), }); - let currentResult = result.current[1]; - expect(currentResult.loading).toBe(false); - expect(currentResult.data).toBe(undefined); - expect(currentResult.previousData).toBe(undefined); - const execute = result.current[0]; + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toBe(undefined); + expect(result.previousData).toBe(undefined); + } + const execute = ProfiledHook.getCurrentSnapshot()[0]; setTimeout(() => execute({ variables: { id: 1 } })); - await waitFor( - () => { - currentResult = result.current[1]; - expect(currentResult.loading).toBe(true); - }, - { interval: 1 } - ); - expect(currentResult.data).toBe(undefined); - expect(currentResult.previousData).toBe(undefined); - - await waitFor( - () => { - currentResult = result.current[1]; - expect(currentResult.loading).toBe(false); - }, - { interval: 1 } - ); - expect(currentResult!.data).toEqual(data1); - expect(currentResult!.previousData).toBe(undefined); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toBe(undefined); + expect(result.previousData).toBe(undefined); + } + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result!.data).toEqual(data1); + expect(result!.previousData).toBe(undefined); + } setTimeout(() => execute({ variables: { id: 2 } })); - await waitFor( - () => { - currentResult = result.current[1]; - expect(currentResult.loading).toBe(true); - }, - { interval: 1 } - ); - expect(currentResult.data).toBe(undefined); - expect(currentResult.previousData).toEqual(data1); - - await waitFor( - () => { - currentResult = result.current[1]; - expect(currentResult.loading).toBe(false); - }, - { interval: 1 } - ); - expect(currentResult.data).toEqual(data2); - expect(currentResult.previousData).toEqual(data1); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toBe(undefined); + expect(result.previousData).toEqual(data1); + } + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toEqual(data2); + expect(result.previousData).toEqual(data1); + } }); it("should work with cache-and-network fetch policy", async () => { diff --git a/src/react/hooks/__tests__/useQuery.test.tsx b/src/react/hooks/__tests__/useQuery.test.tsx index fe9d941a26f..a9664a02472 100644 --- a/src/react/hooks/__tests__/useQuery.test.tsx +++ b/src/react/hooks/__tests__/useQuery.test.tsx @@ -3588,6 +3588,7 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the { interval: 1 } ); expect(result.current.data).toBe(undefined); + // TODO expect(result.current.error).toBe(undefined); await waitFor( From f5555a0eb2b7996fd9e3805e3342b3d2182be788 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 12 Jun 2024 15:46:09 +0200 Subject: [PATCH 05/11] more tests --- src/react/hooks/__tests__/useQuery.test.tsx | 160 ++++++++++---------- 1 file changed, 82 insertions(+), 78 deletions(-) diff --git a/src/react/hooks/__tests__/useQuery.test.tsx b/src/react/hooks/__tests__/useQuery.test.tsx index a9664a02472..f17d67529a5 100644 --- a/src/react/hooks/__tests__/useQuery.test.tsx +++ b/src/react/hooks/__tests__/useQuery.test.tsx @@ -3559,48 +3559,43 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the ); - const { result } = renderHook( - () => useQuery(query, { notifyOnNetworkStatusChange: true }), - { wrapper } + const ProfiledHook = profileHook(() => + useQuery(query, { notifyOnNetworkStatusChange: true }) ); + render(, { wrapper }); - expect(result.current.loading).toBe(true); - expect(result.current.data).toBe(undefined); - expect(result.current.error).toBe(undefined); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toBe(undefined); + expect(result.error).toBe(undefined); + } - await waitFor( - () => { - expect(result.current.loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current.data).toBe(undefined); - expect(result.current.error).toBeInstanceOf(ApolloError); - expect(result.current.error!.message).toBe("error 1"); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toBe(undefined); + expect(result.error).toBeInstanceOf(ApolloError); + expect(result.error!.message).toBe("error 1"); + } const catchFn = jest.fn(); + ProfiledHook.getCurrentSnapshot().refetch().catch(catchFn); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toBe(undefined); + // TODO + expect(result.error).toBe(undefined); + } - result.current.refetch().catch(catchFn); - await waitFor( - () => { - expect(result.current.loading).toBe(true); - }, - { interval: 1 } - ); - expect(result.current.data).toBe(undefined); - // TODO - expect(result.current.error).toBe(undefined); - - await waitFor( - () => { - expect(result.current.loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current.data).toBe(undefined); - expect(result.current.error).toBeInstanceOf(ApolloError); - expect(result.current.error!.message).toBe("error 2"); - + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toBe(undefined); + expect(result.error).toBeInstanceOf(ApolloError); + expect(result.error!.message).toBe("error 2"); + } expect(catchFn.mock.calls.length).toBe(1); expect(catchFn.mock.calls[0].length).toBe(1); expect(catchFn.mock.calls[0][0]).toBeInstanceOf(ApolloError); @@ -6061,63 +6056,72 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the { request: { query }, result: { data: { hello: "world 1" } }, + delay: 3, }, { request: { query }, result: { data: { hello: "world 2" } }, + delay: 3, }, { request: { query }, result: { data: { hello: "world 3" } }, + delay: 3, }, ]; const cache = new InMemoryCache(); const onCompleted = jest.fn(); - const { result } = renderHook( - () => - useQuery(query, { - onCompleted, - notifyOnNetworkStatusChange: true, - pollInterval: 10, - }), - { - wrapper: ({ children }) => ( - - {children} - - ), - } - ); - - expect(result.current.loading).toBe(true); - - await waitFor( - () => { - expect(result.current.data).toEqual({ hello: "world 1" }); - }, - { interval: 1 } - ); - expect(result.current.loading).toBe(false); - expect(onCompleted).toHaveBeenCalledTimes(1); - - await waitFor( - () => { - expect(result.current.data).toEqual({ hello: "world 2" }); - }, - { interval: 1 } + const ProfiledHook = profileHook(() => + useQuery(query, { + onCompleted, + notifyOnNetworkStatusChange: true, + pollInterval: 110, + }) ); - expect(result.current.loading).toBe(false); - expect(onCompleted).toHaveBeenCalledTimes(2); + render(, { + wrapper: ({ children }) => ( + + {children} + + ), + }); - await waitFor( - () => { - expect(result.current.data).toEqual({ hello: "world 3" }); - }, - { interval: 1 } - ); - expect(result.current.loading).toBe(false); - expect(onCompleted).toHaveBeenCalledTimes(3); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.data).toEqual(undefined); + expect(result.loading).toBe(true); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.data).toEqual({ hello: "world 1" }); + expect(result.loading).toBe(false); + expect(onCompleted).toHaveBeenCalledTimes(1); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.data).toEqual({ hello: "world 1" }); + expect(result.loading).toBe(true); + expect(onCompleted).toHaveBeenCalledTimes(1); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.data).toEqual({ hello: "world 2" }); + expect(result.loading).toBe(false); + expect(onCompleted).toHaveBeenCalledTimes(2); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.data).toEqual({ hello: "world 2" }); + expect(result.loading).toBe(true); + expect(onCompleted).toHaveBeenCalledTimes(2); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.data).toEqual({ hello: "world 3" }); + expect(result.loading).toBe(false); + expect(onCompleted).toHaveBeenCalledTimes(3); + } }); // This test was added for issue https://github.com/apollographql/apollo-client/issues/9794 From 8769d33b851496a9ef5274eab9f24140f735385c Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Fri, 21 Jun 2024 16:07:00 +0200 Subject: [PATCH 06/11] make more tests less flimsy --- .../hooks/__tests__/useLazyQuery.test.tsx | 255 ++++++++---------- src/react/hooks/__tests__/useQuery.test.tsx | 231 ++++++++-------- src/testing/internal/index.ts | 1 + src/testing/internal/skipActWarnings.ts | 8 + 4 files changed, 224 insertions(+), 271 deletions(-) create mode 100644 src/testing/internal/skipActWarnings.ts diff --git a/src/react/hooks/__tests__/useLazyQuery.test.tsx b/src/react/hooks/__tests__/useLazyQuery.test.tsx index 6d2c10cd51c..bf2c49c803a 100644 --- a/src/react/hooks/__tests__/useLazyQuery.test.tsx +++ b/src/react/hooks/__tests__/useLazyQuery.test.tsx @@ -26,8 +26,6 @@ import { useLazyQuery } from "../useLazyQuery"; import { QueryResult } from "../../types/types"; import { profileHook } from "../../../testing/internal"; -const IS_REACT_18 = React.version.startsWith("18"); - describe("useLazyQuery Hook", () => { const helloQuery: TypedDocumentNode<{ hello: string; @@ -100,32 +98,34 @@ describe("useLazyQuery Hook", () => { }, ]; - const { result } = renderHook(() => useLazyQuery(helloQuery), { + const ProfiledHook = profileHook(() => useLazyQuery(helloQuery)); + + render(, { wrapper: ({ children }) => ( {children} ), }); - expect(result.current[1].loading).toBe(false); - expect(result.current[1].called).toBe(false); - const execute = result.current[0]; + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.called).toBe(false); + } + + const execute = ProfiledHook.getCurrentSnapshot()[0]; setTimeout(() => execute()); - await waitFor( - () => { - expect(result.current[1].loading).toBe(true); - }, - { interval: 1 } - ); - expect(result.current[1].called).toBe(true); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.called).toBe(true); + } - await waitFor( - () => { - expect(result.current[1].loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current[1].called).toBe(true); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.called).toBe(true); + } }); it("should override `skip` if lazy mode execution function is called", async () => { @@ -183,36 +183,34 @@ describe("useLazyQuery Hook", () => { }, ]; - const { result } = renderHook( - () => - useLazyQuery(query, { - variables: { id: 1 }, - }), - { - wrapper: ({ children }) => ( - {children} - ), - } + const ProfiledHook = profileHook(() => + useLazyQuery(query, { + variables: { id: 1 }, + }) ); + render(, { + wrapper: ({ children }) => ( + {children} + ), + }); - const execute = result.current[0]; - setTimeout(() => execute()); - - await waitFor( - () => { - expect(result.current[1].loading).toBe(true); - }, - { interval: 1 } - ); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + } - await waitFor( - () => { - expect(result.current[1].loading).toBe(false); - }, - { interval: 1 } - ); + const execute = ProfiledHook.getCurrentSnapshot()[0]; + setTimeout(() => execute()); - expect(result.current[1].data).toEqual({ hello: "world 1" }); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + } + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toEqual({ hello: "world 1" }); + } }); it("should use variables passed into lazy execution function, overriding similar variables defined in Hook options", async () => { @@ -599,54 +597,48 @@ describe("useLazyQuery Hook", () => { }, ]; - const { result } = renderHook( - () => - useLazyQuery(helloQuery, { - fetchPolicy: "network-only", - }), - { - wrapper: ({ children }) => ( - {children} - ), - } + const ProfiledHook = profileHook(() => + useLazyQuery(helloQuery, { + fetchPolicy: "network-only", + }) ); - expect(result.current[1].loading).toBe(false); - const execute = result.current[0]; + render(, { + wrapper: ({ children }) => ( + {children} + ), + }); + + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + } + const execute = ProfiledHook.getCurrentSnapshot()[0]; setTimeout(() => execute()); - await waitFor( - () => { - expect(result.current[1].loading).toBe(true); - }, - { interval: 1 } - ); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + } - await waitFor( - () => { - expect(result.current[1].loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current[1].data).toEqual({ hello: "world 1" }); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toEqual({ hello: "world 1" }); + } setTimeout(() => execute()); - await waitFor( - () => { - expect(result.current[1].loading).toBe(true); - }, - { interval: 1 } - ); - expect(result.current[1].data).toEqual({ hello: "world 1" }); - - await waitFor( - () => { - expect(result.current[1].loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current[1].data).toEqual({ hello: "world 2" }); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toEqual({ hello: "world 1" }); + } + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toEqual({ hello: "world 2" }); + } }); it("should persist previous data when a query is re-run", async () => { @@ -1757,72 +1749,39 @@ describe("useLazyQuery Hook", () => { ), }); - const { result } = renderHook( - () => - useLazyQuery(helloQuery, { - errorPolicy, - }), - { - wrapper: ({ children }) => ( - {children} - ), - } + const ProfiledHook = profileHook(() => + useLazyQuery(helloQuery, { + errorPolicy, + }) ); + render(, { + wrapper: ({ children }) => ( + {children} + ), + }); - const execute = result.current[0]; - expect(result.current[1].loading).toBe(false); - expect(result.current[1].networkStatus).toBe(NetworkStatus.ready); - expect(result.current[1].data).toBeUndefined(); - + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.networkStatus).toBe(NetworkStatus.ready); + expect(result.data).toBeUndefined(); + } + const execute = ProfiledHook.getCurrentSnapshot()[0]; setTimeout(execute); - await waitFor( - () => { - expect(result.current[1].loading).toBe(true); - }, - { interval: 1 } - ); - await waitFor( - () => { - if (IS_REACT_18) { - expect(result.current[1].networkStatus).toBe(NetworkStatus.loading); - } else { - expect(result.current[1].networkStatus).toBe(NetworkStatus.error); - } - }, - { interval: 1 } - ); - await waitFor( - () => { - expect(result.current[1].data).toBeUndefined(); - }, - { interval: 1 } - ); - - await waitFor( - () => { - expect(result.current[1].loading).toBe(false); - }, - { interval: 1 } - ); - await waitFor( - () => { - expect(result.current[1].networkStatus).toBe(NetworkStatus.error); - }, - { interval: 1 } - ); - await waitFor( - () => { - expect(result.current[1].data).toBeUndefined(); - }, - { interval: 1 } - ); - await waitFor( - () => { - expect(result.current[1].error!.message).toBe("from the network"); - }, - { interval: 1 } - ); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.networkStatus).toBe(NetworkStatus.loading); + expect(result.data).toBeUndefined(); + } + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.networkStatus).toBe(NetworkStatus.error); + expect(result.data).toBeUndefined(); + expect(result.error!.message).toBe("from the network"); + } } // For errorPolicy:"none", we expect result.error to be defined and diff --git a/src/react/hooks/__tests__/useQuery.test.tsx b/src/react/hooks/__tests__/useQuery.test.tsx index f17d67529a5..43dcb12c656 100644 --- a/src/react/hooks/__tests__/useQuery.test.tsx +++ b/src/react/hooks/__tests__/useQuery.test.tsx @@ -31,6 +31,7 @@ import { useMutation } from "../useMutation"; import { createProfiler, profileHook, + skipActWarnings, spyOnConsole, } from "../../../testing/internal"; import { useApolloClient } from "../useApolloClient"; @@ -2120,7 +2121,7 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the unmount(); await expect(ProfiledHook).not.toRerender({ timeout: 50 }); - + // TODO rarely seeing 3 here investigate further expect(requestSpy).toHaveBeenCalledTimes(2); expect(onErrorFn).toHaveBeenCalledTimes(0); }); @@ -5183,42 +5184,35 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the ); - const { result } = renderHook( - () => - useQuery(query, { - variables: { id: 1 }, - notifyOnNetworkStatusChange: true, - }), - { wrapper } - ); - - expect(result.current.loading).toBe(true); - expect(result.current.data).toBe(undefined); - - await waitFor( - () => { - expect(result.current.loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current.data).toEqual({ hello: "world 1" }); - - result.current.refetch({ id: 2 }); - await waitFor( - () => { - expect(result.current.loading).toBe(true); - }, - { interval: 1 } + const ProfiledHook = profileHook(() => + useQuery(query, { + variables: { id: 1 }, + notifyOnNetworkStatusChange: true, + }) ); - expect(result.current.data).toBe(undefined); - await waitFor( - () => { - expect(result.current.loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current.data).toEqual({ hello: "world 2" }); + render(, { wrapper }); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toBe(undefined); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toEqual({ hello: "world 1" }); + } + ProfiledHook.getCurrentSnapshot().refetch({ id: 2 }); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toBe(undefined); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toEqual({ hello: "world 2" }); + } }); it("refetching after an error", async () => { @@ -5246,69 +5240,61 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the const cache = new InMemoryCache(); - const { result } = renderHook( - () => - useQuery(query, { - notifyOnNetworkStatusChange: true, - }), - { - wrapper: ({ children }) => ( - - {children} - - ), - } + const ProfiledHook = profileHook(() => + useQuery(query, { + notifyOnNetworkStatusChange: true, + }) ); - expect(result.current.loading).toBe(true); - expect(result.current.data).toBe(undefined); - - await waitFor( - () => { - expect(result.current.loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current.error).toBe(undefined); - expect(result.current.data).toEqual({ hello: "world 1" }); + render(, { + wrapper: ({ children }) => ( + + {children} + + ), + }); - result.current.refetch(); - await waitFor( - () => { - expect(result.current.loading).toBe(true); - }, - { interval: 1 } - ); - expect(result.current.error).toBe(undefined); - expect(result.current.data).toEqual({ hello: "world 1" }); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toBe(undefined); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.error).toBe(undefined); + expect(result.data).toEqual({ hello: "world 1" }); + } - await waitFor( - () => { - expect(result.current.loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current.error).toBeInstanceOf(ApolloError); - expect(result.current.data).toEqual({ hello: "world 1" }); + ProfiledHook.getCurrentSnapshot().refetch(); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.error).toBe(undefined); + expect(result.data).toEqual({ hello: "world 1" }); + } + await waitFor(() => {}, { interval: 1 }); - result.current.refetch(); - await waitFor( - () => { - expect(result.current.loading).toBe(true); - }, - { interval: 1 } - ); - expect(result.current.error).toBe(undefined); - expect(result.current.data).toEqual({ hello: "world 1" }); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.error).toBeInstanceOf(ApolloError); + expect(result.data).toEqual({ hello: "world 1" }); + } - await waitFor( - () => { - expect(result.current.loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current.error).toBe(undefined); - expect(result.current.data).toEqual({ hello: "world 2" }); + ProfiledHook.getCurrentSnapshot().refetch(); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.error).toBe(undefined); + expect(result.data).toEqual({ hello: "world 1" }); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.error).toBe(undefined); + expect(result.data).toEqual({ hello: "world 2" }); + } }); describe("refetchWritePolicy", () => { @@ -6618,43 +6604,42 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the {children} ); - const { result } = renderHook( - () => - useQuery(query, { - partialRefetch: true, - notifyOnNetworkStatusChange: true, - }), - { wrapper } + const ProfiledHook = profileHook(() => + useQuery(query, { + partialRefetch: true, + notifyOnNetworkStatusChange: true, + }) ); - expect(result.current.loading).toBe(true); - expect(result.current.data).toBe(undefined); - expect(result.current.error).toBe(undefined); - expect(result.current.networkStatus).toBe(NetworkStatus.loading); + render(, { wrapper }); - await waitFor( - () => { - expect(result.current.networkStatus).toBe(NetworkStatus.refetch); - }, - { interval: 1 } - ); - expect(result.current.loading).toBe(true); - expect(result.current.error).toBe(undefined); - expect(result.current.data).toBe(undefined); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toBe(undefined); + expect(result.error).toBe(undefined); + expect(result.networkStatus).toBe(NetworkStatus.loading); + } - expect(consoleSpy.error).toHaveBeenCalledTimes(1); - expect(consoleSpy.error.mock.calls[0][0]).toMatch("Missing field"); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.networkStatus).toBe(NetworkStatus.refetch); + expect(result.loading).toBe(true); + expect(result.error).toBe(undefined); + expect(result.data).toBe(undefined); + } - await waitFor( - () => { - expect(result.current.networkStatus).toBe(NetworkStatus.ready); - }, - { interval: 1 } - ); + const calls = skipActWarnings(consoleSpy.error.mock.calls); + expect(calls.length).toBe(1); + expect(calls[0][0]).toMatch("Missing field"); - expect(result.current.loading).toBe(false); - expect(result.current.data).toEqual({ hello: "world" }); - expect(result.current.error).toBe(undefined); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.networkStatus).toBe(NetworkStatus.ready); + expect(result.loading).toBe(false); + expect(result.data).toEqual({ hello: "world" }); + expect(result.error).toBe(undefined); + } }); }); diff --git a/src/testing/internal/index.ts b/src/testing/internal/index.ts index 9f8b3faae9a..71368bee0d6 100644 --- a/src/testing/internal/index.ts +++ b/src/testing/internal/index.ts @@ -20,3 +20,4 @@ export type { RenderWithMocksOptions, } from "./renderHelpers.js"; export { renderWithClient, renderWithMocks } from "./renderHelpers.js"; +export { skipActWarnings } from "./skipActWarnings.js"; diff --git a/src/testing/internal/skipActWarnings.ts b/src/testing/internal/skipActWarnings.ts new file mode 100644 index 00000000000..1e4cd4e1c94 --- /dev/null +++ b/src/testing/internal/skipActWarnings.ts @@ -0,0 +1,8 @@ +export function skipActWarnings(mockCalls: any[][]) { + return mockCalls.filter( + (call) => + !call[0].startsWith( + "Warning: An update to %s inside a test was not wrapped in act(...).\n" + ) + ); +} From 1260d36875dabf405666ac665547fe09ec1eb989 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Fri, 21 Jun 2024 17:41:53 +0200 Subject: [PATCH 07/11] more flaky tests --- src/react/hooks/__tests__/useQuery.test.tsx | 367 ++++++++++---------- 1 file changed, 186 insertions(+), 181 deletions(-) diff --git a/src/react/hooks/__tests__/useQuery.test.tsx b/src/react/hooks/__tests__/useQuery.test.tsx index 43dcb12c656..97d8eca31aa 100644 --- a/src/react/hooks/__tests__/useQuery.test.tsx +++ b/src/react/hooks/__tests__/useQuery.test.tsx @@ -1968,6 +1968,7 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the await expect(ProfiledHook).not.toRerender({ timeout: 50 }); + // TODO rarely seeing 3 here (also old `useQuery` implementation) expect(requestSpy).toHaveBeenCalledTimes(2); expect(onErrorFn).toHaveBeenCalledTimes(0); }); @@ -5273,7 +5274,6 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the expect(result.error).toBe(undefined); expect(result.data).toEqual({ hello: "world 1" }); } - await waitFor(() => {}, { interval: 1 }); { const result = await ProfiledHook.takeSnapshot(); @@ -5550,73 +5550,67 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the {children} ); - - const { result } = renderHook( - () => - useQuery(query, { - variables: { min: 0, max: 12 }, - notifyOnNetworkStatusChange: true, - // Intentionally not passing refetchWritePolicy. - }), - { wrapper } + const ProfiledHook = profileHook(() => + useQuery(query, { + variables: { min: 0, max: 12 }, + notifyOnNetworkStatusChange: true, + // Intentionally not passing refetchWritePolicy. + }) ); - expect(result.current.loading).toBe(true); - expect(result.current.error).toBe(undefined); - expect(result.current.data).toBe(undefined); - expect(typeof result.current.refetch).toBe("function"); + render(, { wrapper }); - await waitFor( - () => { - expect(result.current.loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current.error).toBeUndefined(); - expect(result.current.data).toEqual({ primes: [2, 3, 5, 7, 11] }); - expect(mergeParams).toEqual([[void 0, [2, 3, 5, 7, 11]]]); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.error).toBe(undefined); + expect(result.data).toBe(undefined); + expect(typeof result.refetch).toBe("function"); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.error).toBeUndefined(); + expect(result.data).toEqual({ primes: [2, 3, 5, 7, 11] }); + expect(mergeParams.shift()).toEqual([void 0, [2, 3, 5, 7, 11]]); + } const thenFn = jest.fn(); - result.current.refetch({ min: 12, max: 30 }).then(thenFn); + ProfiledHook.getCurrentSnapshot() + .refetch({ min: 12, max: 30 }) + .then(thenFn); - await waitFor( - () => { - expect(result.current.loading).toBe(true); - }, - { interval: 1 } - ); - expect(result.current.error).toBe(undefined); - expect(result.current.data).toEqual({ - // We get the stale data because we configured keyArgs: false. - primes: [2, 3, 5, 7, 11], - }); - - // This networkStatus is setVariables instead of refetch because we - // called refetch with new variables. - expect(result.current.networkStatus).toBe(NetworkStatus.setVariables); - - await waitFor( - () => { - expect(result.current.loading).toBe(false); - }, - { interval: 1 } - ); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.error).toBe(undefined); + expect(result.data).toEqual({ + // We get the stale data because we configured keyArgs: false. + primes: [2, 3, 5, 7, 11], + }); + // This networkStatus is setVariables instead of refetch because we + // called refetch with new variables. + expect(result.networkStatus).toBe(NetworkStatus.setVariables); + } - expect(result.current.error).toBe(undefined); - expect(result.current.data).toEqual({ primes: [13, 17, 19, 23, 29] }); - expect(mergeParams).toEqual([ - [undefined, [2, 3, 5, 7, 11]], - // Without refetchWritePolicy: "overwrite", this array will be - // all 10 primes (2 through 29) together. - [undefined, [13, 17, 19, 23, 29]], - ]); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.error).toBe(undefined); + expect(result.data).toEqual({ primes: [13, 17, 19, 23, 29] }); + expect(mergeParams.shift()).toEqual( + // Without refetchWritePolicy: "overwrite", this array will be + // all 10 primes (2 through 29) together. + [undefined, [13, 17, 19, 23, 29]] + ); - expect(thenFn).toHaveBeenCalledTimes(1); - expect(thenFn).toHaveBeenCalledWith({ - loading: false, - networkStatus: NetworkStatus.ready, - data: { primes: [13, 17, 19, 23, 29] }, - }); + expect(thenFn).toHaveBeenCalledTimes(1); + expect(thenFn).toHaveBeenCalledWith({ + loading: false, + networkStatus: NetworkStatus.ready, + data: { primes: [13, 17, 19, 23, 29] }, + }); + } }); }); @@ -6352,83 +6346,92 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the ); const onError = jest.fn(); - const { result } = renderHook( - () => ({ - mutation: useMutation(mutation, { - optimisticResponse: { addCar: carData }, - update(cache, { data }) { - cache.modify({ - fields: { - cars(existing, { readField }) { - const newCarRef = cache.writeFragment({ - data: data!.addCar, - fragment: gql` - fragment NewCar on Car { - id - make - model - } - `, - }); - - if ( - existing.some( - (ref: Reference) => - readField("id", ref) === data!.addCar.id - ) - ) { - return existing; - } - - return [...existing, newCarRef]; - }, + const ProfiledHook = profileHook(() => ({ + mutation: useMutation(mutation, { + optimisticResponse: { addCar: carData }, + update(cache, { data }) { + cache.modify({ + fields: { + cars(existing, { readField }) { + const newCarRef = cache.writeFragment({ + data: data!.addCar, + fragment: gql` + fragment NewCar on Car { + id + make + model + } + `, + }); + + if ( + existing.some( + (ref: Reference) => + readField("id", ref) === data!.addCar.id + ) + ) { + return existing; + } + + return [...existing, newCarRef]; }, - }); - }, - onError, - }), - query: useQuery(query), + }, + }); + }, + onError, }), - { wrapper } - ); - - expect(result.current.query.loading).toBe(true); - const mutate = result.current.mutation[0]; + query: useQuery(query), + })); + render(, { wrapper }); - await waitFor( - () => { - expect(result.current.query.loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current.query.loading).toBe(false); - expect(result.current.query.data).toEqual(carsData); + { + const { query } = await ProfiledHook.takeSnapshot(); + expect(query.loading).toBe(true); + } + const mutate = ProfiledHook.getCurrentSnapshot().mutation[0]; + { + const { query } = await ProfiledHook.takeSnapshot(); + expect(query.loading).toBe(false); + expect(query.loading).toBe(false); + expect(query.data).toEqual(carsData); + } act(() => void mutate()); - // The mutation ran and is loading the result. The query stays at not - // loading as nothing has changed for the query, but optimistic data is - // rendered. - expect(result.current.mutation[1].loading).toBe(true); - expect(result.current.query.loading).toBe(false); - expect(result.current.query.data).toEqual(allCarsData); + { + // The mutation ran and is loading the result. The query stays at not + // loading as nothing has changed for the query, but optimistic data is + // rendered. + let { query, mutation } = await ProfiledHook.takeSnapshot(); + + while (!mutation[1].loading) { + // useMutation seems to sometimes have an extra render + // before it enters `loading` state - this test doesn't test + // that part of that hook so we just work around it + ({ query, mutation } = await ProfiledHook.takeSnapshot()); + } + expect(mutation[1].loading).toBe(true); + expect(query.loading).toBe(false); + expect(query.data).toEqual(allCarsData); + } expect(onError).toHaveBeenCalledTimes(0); - await tick(); - // The mutation ran and is loading the result. The query stays at - // not loading as nothing has changed for the query. - expect(result.current.mutation[1].loading).toBe(true); - expect(result.current.query.loading).toBe(false); - - await waitFor(() => { - expect(result.current.mutation[1].loading).toBe(false); - }); + { + const { query, mutation } = await ProfiledHook.takeSnapshot(); + // The mutation ran and is loading the result. The query stays at + // not loading as nothing has changed for the query. + expect(mutation[1].loading).toBe(true); + expect(query.loading).toBe(false); + } - // The mutation has completely finished, leaving the query with access to - // the original cache data. - expect(result.current.mutation[1].loading).toBe(false); - expect(result.current.query.loading).toBe(false); - expect(result.current.query.data).toEqual(carsData); + { + const { query, mutation } = await ProfiledHook.takeSnapshot(); + // The mutation has completely finished, leaving the query with access to + // the original cache data. + expect(mutation[1].loading).toBe(false); + expect(query.loading).toBe(false); + expect(query.data).toEqual(carsData); + } expect(onError).toHaveBeenCalledTimes(1); expect(onError.mock.calls[0][0].message).toBe("Oh no!"); @@ -7903,66 +7906,68 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the ); - const { result, rerender } = renderHook( - ({ gender }) => - useQuery(query, { - variables: { gender }, - fetchPolicy: "network-only", - }), - { wrapper, initialProps: { gender: "all" } } + const ProfiledHook = profileHook(({ gender }: { gender: string }) => + useQuery(query, { + variables: { gender }, + fetchPolicy: "network-only", + }) ); + const { rerender } = render(, { wrapper }); - expect(result.current.loading).toBe(true); - expect(result.current.networkStatus).toBe(NetworkStatus.loading); - expect(result.current.data).toBe(undefined); - - await waitFor( - () => { - expect(result.current.loading).toBe(false); - }, - { interval: 1 } - ); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.networkStatus).toBe(NetworkStatus.loading); + expect(result.data).toBe(undefined); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.networkStatus).toBe(NetworkStatus.ready); + expect(result.data).toEqual({ + people: peopleData.map(({ gender, ...person }) => person), + }); + } + await waitFor(() => {}, { interval: 1 }); - expect(result.current.networkStatus).toBe(NetworkStatus.ready); - expect(result.current.data).toEqual({ - people: peopleData.map(({ gender, ...person }) => person), - }); + rerender(); - rerender({ gender: "female" }); - expect(result.current.loading).toBe(true); - expect(result.current.networkStatus).toBe(NetworkStatus.setVariables); - expect(result.current.data).toBe(undefined); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.networkStatus).toBe(NetworkStatus.setVariables); + expect(result.data).toBe(undefined); + } - await waitFor( - () => { - expect(result.current.loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current.networkStatus).toBe(NetworkStatus.ready); - expect(result.current.data).toEqual({ - people: peopleData - .filter((person) => person.gender === "female") - .map(({ gender, ...person }) => person), - }); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.networkStatus).toBe(NetworkStatus.ready); + expect(result.data).toEqual({ + people: peopleData + .filter((person) => person.gender === "female") + .map(({ gender, ...person }) => person), + }); + } - rerender({ gender: "nonbinary" }); - expect(result.current.loading).toBe(true); - expect(result.current.networkStatus).toBe(NetworkStatus.setVariables); - expect(result.current.data).toBe(undefined); + rerender(); - await waitFor( - () => { - expect(result.current.loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current.networkStatus).toBe(NetworkStatus.ready); - expect(result.current.data).toEqual({ - people: peopleData - .filter((person) => person.gender === "nonbinary") - .map(({ gender, ...person }) => person), - }); + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.networkStatus).toBe(NetworkStatus.setVariables); + expect(result.data).toBe(undefined); + } + { + const result = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.networkStatus).toBe(NetworkStatus.ready); + expect(result.data).toEqual({ + people: peopleData + .filter((person) => person.gender === "nonbinary") + .map(({ gender, ...person }) => person), + }); + } }); }); From 25ff067b36bd4ec3833a2d71f74c8aed75e2944f Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Fri, 21 Jun 2024 18:03:00 +0200 Subject: [PATCH 08/11] cleanup --- src/react/hooks/__tests__/useLazyQuery.test.tsx | 4 ++-- src/react/hooks/__tests__/useQuery.test.tsx | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/react/hooks/__tests__/useLazyQuery.test.tsx b/src/react/hooks/__tests__/useLazyQuery.test.tsx index bf2c49c803a..809985d3a69 100644 --- a/src/react/hooks/__tests__/useLazyQuery.test.tsx +++ b/src/react/hooks/__tests__/useLazyQuery.test.tsx @@ -839,8 +839,8 @@ describe("useLazyQuery Hook", () => { { const [, result] = await ProfiledHook.takeSnapshot(); expect(result.loading).toBe(false); - expect(result!.data).toEqual(data1); - expect(result!.previousData).toBe(undefined); + expect(result.data).toEqual(data1); + expect(result.previousData).toBe(undefined); } setTimeout(() => execute({ variables: { id: 2 } })); diff --git a/src/react/hooks/__tests__/useQuery.test.tsx b/src/react/hooks/__tests__/useQuery.test.tsx index 97d8eca31aa..8ab7a8f7f8c 100644 --- a/src/react/hooks/__tests__/useQuery.test.tsx +++ b/src/react/hooks/__tests__/useQuery.test.tsx @@ -3587,7 +3587,6 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the const result = await ProfiledHook.takeSnapshot(); expect(result.loading).toBe(true); expect(result.data).toBe(undefined); - // TODO expect(result.error).toBe(undefined); } @@ -7928,7 +7927,6 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the people: peopleData.map(({ gender, ...person }) => person), }); } - await waitFor(() => {}, { interval: 1 }); rerender(); From 7d926405f8407e7424db863200ca83f9673abfa6 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Mon, 24 Jun 2024 12:22:18 +0200 Subject: [PATCH 09/11] fix another flaky test --- .../hooks/__tests__/useLazyQuery.test.tsx | 91 +++++++++---------- 1 file changed, 42 insertions(+), 49 deletions(-) diff --git a/src/react/hooks/__tests__/useLazyQuery.test.tsx b/src/react/hooks/__tests__/useLazyQuery.test.tsx index 809985d3a69..08f94df5c60 100644 --- a/src/react/hooks/__tests__/useLazyQuery.test.tsx +++ b/src/react/hooks/__tests__/useLazyQuery.test.tsx @@ -655,62 +655,55 @@ describe("useLazyQuery Hook", () => { }, ]; - const { result } = renderHook( - () => - useLazyQuery(helloQuery, { - notifyOnNetworkStatusChange: true, - }), - { - wrapper: ({ children }) => ( - {children} - ), - } + const ProfiledHook = profileHook(() => + useLazyQuery(helloQuery, { + notifyOnNetworkStatusChange: true, + }) ); - expect(result.current[1].loading).toBe(false); - expect(result.current[1].data).toBe(undefined); - expect(result.current[1].previousData).toBe(undefined); - const execute = result.current[0]; + render(, { + wrapper: ({ children }) => ( + {children} + ), + }); + + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toBe(undefined); + expect(result.previousData).toBe(undefined); + } + const execute = ProfiledHook.getCurrentSnapshot()[0]; setTimeout(() => execute()); - await waitFor( - () => { - expect(result.current[1].loading).toBe(true); - }, - { interval: 1 } - ); - expect(result.current[1].data).toBe(undefined); - expect(result.current[1].previousData).toBe(undefined); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toBe(undefined); + expect(result.previousData).toBe(undefined); + } - await waitFor( - () => { - expect(result.current[1].loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current[1].data).toEqual({ hello: "world 1" }); - expect(result.current[1].previousData).toBe(undefined); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toEqual({ hello: "world 1" }); + expect(result.previousData).toBe(undefined); + } - const refetch = result.current[1].refetch; + const refetch = ProfiledHook.getCurrentSnapshot()[1].refetch; setTimeout(() => refetch!()); - - await waitFor( - () => { - expect(result.current[1].loading).toBe(true); - }, - { interval: 1 } - ); - expect(result.current[1].data).toEqual({ hello: "world 1" }); - expect(result.current[1].previousData).toEqual({ hello: "world 1" }); - - await waitFor( - () => { - expect(result.current[1].loading).toBe(false); - }, - { interval: 1 } - ); - expect(result.current[1].data).toEqual({ hello: "world 2" }); - expect(result.current[1].previousData).toEqual({ hello: "world 1" }); + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(true); + expect(result.data).toEqual({ hello: "world 1" }); + expect(result.previousData).toEqual({ hello: "world 1" }); + } + { + const [, result] = await ProfiledHook.takeSnapshot(); + expect(result.loading).toBe(false); + expect(result.data).toEqual({ hello: "world 2" }); + expect(result.previousData).toEqual({ hello: "world 1" }); + } }); it("should allow for the query to start with polling", async () => { From 6a0c3a620dc24163ce1699f1b959f46d5df458f0 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Tue, 2 Jul 2024 11:21:06 +0200 Subject: [PATCH 10/11] review feedback --- src/react/hooks/__tests__/useQuery.test.tsx | 11 ++++++++--- src/testing/internal/index.ts | 1 - src/testing/internal/skipActWarnings.ts | 8 -------- 3 files changed, 8 insertions(+), 12 deletions(-) delete mode 100644 src/testing/internal/skipActWarnings.ts diff --git a/src/react/hooks/__tests__/useQuery.test.tsx b/src/react/hooks/__tests__/useQuery.test.tsx index 8ab7a8f7f8c..bfcd534c7e3 100644 --- a/src/react/hooks/__tests__/useQuery.test.tsx +++ b/src/react/hooks/__tests__/useQuery.test.tsx @@ -30,13 +30,14 @@ import { useQuery } from "../useQuery"; import { useMutation } from "../useMutation"; import { createProfiler, + disableActWarnings, profileHook, - skipActWarnings, spyOnConsole, } from "../../../testing/internal"; import { useApolloClient } from "../useApolloClient"; import { useLazyQuery } from "../useLazyQuery"; +const IS_REACT_17 = React.version.startsWith("17"); const IS_REACT_19 = React.version.startsWith("19"); describe("useQuery Hook", () => { @@ -6576,6 +6577,7 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the }); it("should attempt a refetch when data is missing, partialRefetch is true and addTypename is false for the cache", async () => { + using _disabledActWarnings = disableActWarnings(); using consoleSpy = spyOnConsole("error"); const query = gql` { @@ -6631,8 +6633,11 @@ This is pure coincidence though, and the useQuery rewrite that doesn't break the expect(result.data).toBe(undefined); } - const calls = skipActWarnings(consoleSpy.error.mock.calls); - expect(calls.length).toBe(1); + const calls = consoleSpy.error.mock.calls; + if (!IS_REACT_17) { + // React 17 doesn't know `IS_REACT_ACT_ENVIRONMENT` yet, so it will log a warning that we don't care about. + expect(calls.length).toBe(1); + } expect(calls[0][0]).toMatch("Missing field"); { diff --git a/src/testing/internal/index.ts b/src/testing/internal/index.ts index 71368bee0d6..9f8b3faae9a 100644 --- a/src/testing/internal/index.ts +++ b/src/testing/internal/index.ts @@ -20,4 +20,3 @@ export type { RenderWithMocksOptions, } from "./renderHelpers.js"; export { renderWithClient, renderWithMocks } from "./renderHelpers.js"; -export { skipActWarnings } from "./skipActWarnings.js"; diff --git a/src/testing/internal/skipActWarnings.ts b/src/testing/internal/skipActWarnings.ts deleted file mode 100644 index 1e4cd4e1c94..00000000000 --- a/src/testing/internal/skipActWarnings.ts +++ /dev/null @@ -1,8 +0,0 @@ -export function skipActWarnings(mockCalls: any[][]) { - return mockCalls.filter( - (call) => - !call[0].startsWith( - "Warning: An update to %s inside a test was not wrapped in act(...).\n" - ) - ); -} From 92246c614b98d63ba6fead338f6a39299e693dce Mon Sep 17 00:00:00 2001 From: phryneas Date: Tue, 2 Jul 2024 17:12:04 +0000 Subject: [PATCH 11/11] Clean up Prettier, Size-limit, and Api-Extractor --- .size-limits.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.size-limits.json b/.size-limits.json index b13d95f84a8..09bf55362fa 100644 --- a/.size-limits.json +++ b/.size-limits.json @@ -1,4 +1,4 @@ { - "dist/apollo-client.min.cjs": 39605, + "dist/apollo-client.min.cjs": 39604, "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 32852 }