-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Ensure variables are kept when refetching with a suspense hook that uses skipToken #12993
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 27 commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
00725ac
Add failing test to reproduce issue
jerelmiller 1e9819d
Fix issue where skipToken with refetchQueries would refetch empty var…
jerelmiller e58febc
Add test to ensure changing variables after skipToken suspends
jerelmiller 498c4c8
Add test to ensure cached value is honored
jerelmiller 1994e64
Swap order of tests
jerelmiller f7b0744
Add tests for skipToken with useSuspenseQuery
jerelmiller dfd7459
Add helper for useSuspenseQuery
jerelmiller 25803f7
Use helper in new tests
jerelmiller dfaf2a8
Add fix to useSuspenseQuery
jerelmiller 058b470
Remove unused imports
jerelmiller 642648e
Move tests to own folder
jerelmiller a7fe575
Deprecate old renderSuspenseHook helper
jerelmiller 9e151cc
Update tests to use render helper
jerelmiller 04a757c
Rename file to testUtils
jerelmiller ae8b132
Add a testUtils file for useBackgroundQuery
jerelmiller e6855c5
Move new tests to own file
jerelmiller 936789b
Allow custom delay for setupVariablesCase
jerelmiller 961bc04
Fix issue in React 18 with tests
jerelmiller a91b1de
Fix ignore path
jerelmiller e84a075
Create shared ignore list
jerelmiller d541c26
Add longer delay to skipToken tests
jerelmiller 68a4a22
Extract cache key to hook
jerelmiller c044493
Remove comment
jerelmiller 738a714
Fix formatting
jerelmiller 1db3a36
Add patch for type
jerelmiller 90b6791
Rename helper functions for clarity
jerelmiller a9b484d
Rename component names in snapshots
jerelmiller bb25972
Update deprecation message
jerelmiller 40eddcd
Adjust comment for typos and accuracy
jerelmiller b6f09c8
Add changeset
jerelmiller 09e72fc
Update size limits
jerelmiller 6ffc611
Upgrade react-render-stream and remove patch
jerelmiller 17abb5c
Fix type issues after upgrade
jerelmiller File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| diff --git a/node_modules/@testing-library/react-render-stream/dist/pure.d.cts b/node_modules/@testing-library/react-render-stream/dist/pure.d.cts | ||
| index 8964c27..8875af7 100644 | ||
| --- a/node_modules/@testing-library/react-render-stream/dist/pure.d.cts | ||
| +++ b/node_modules/@testing-library/react-render-stream/dist/pure.d.cts | ||
| @@ -306,4 +306,4 @@ declare namespace disableActEnvironment { | ||
| var defaultOptions: Required<DisableActEnvironmentOptions>; | ||
| } | ||
|
|
||
| -export { type Assertable, type RenderWithoutActAsync as AsyncRenderFn, type DisableActEnvironmentOptions, type NextRenderOptions, type RenderStream, type RenderStreamOptions, type RenderStreamWithRenderFn, type SnapshotStream, type SyncScreen, WaitForRenderTimeoutError, cleanup, createRenderStream, disableActEnvironment, renderHookToSnapshotStream, useTrackRenders }; | ||
| +export { type Assertable, type RenderWithoutActAsync as AsyncRenderFn, type DisableActEnvironmentOptions, type NextRenderOptions, type Render, type RenderStream, type RenderStreamOptions, type RenderStreamWithRenderFn, type SnapshotStream, type SyncScreen, WaitForRenderTimeoutError, cleanup, createRenderStream, disableActEnvironment, renderHookToSnapshotStream, useTrackRenders }; | ||
| diff --git a/node_modules/@testing-library/react-render-stream/dist/pure.d.ts b/node_modules/@testing-library/react-render-stream/dist/pure.d.ts | ||
| index 8964c27..8875af7 100644 | ||
| --- a/node_modules/@testing-library/react-render-stream/dist/pure.d.ts | ||
| +++ b/node_modules/@testing-library/react-render-stream/dist/pure.d.ts | ||
| @@ -306,4 +306,4 @@ declare namespace disableActEnvironment { | ||
| var defaultOptions: Required<DisableActEnvironmentOptions>; | ||
| } | ||
|
|
||
| -export { type Assertable, type RenderWithoutActAsync as AsyncRenderFn, type DisableActEnvironmentOptions, type NextRenderOptions, type RenderStream, type RenderStreamOptions, type RenderStreamWithRenderFn, type SnapshotStream, type SyncScreen, WaitForRenderTimeoutError, cleanup, createRenderStream, disableActEnvironment, renderHookToSnapshotStream, useTrackRenders }; | ||
| +export { type Assertable, type RenderWithoutActAsync as AsyncRenderFn, type DisableActEnvironmentOptions, type NextRenderOptions, type Render, type RenderStream, type RenderStreamOptions, type RenderStreamWithRenderFn, type SnapshotStream, type SyncScreen, WaitForRenderTimeoutError, cleanup, createRenderStream, disableActEnvironment, renderHookToSnapshotStream, useTrackRenders }; |
293 changes: 293 additions & 0 deletions
293
src/react/hooks/__tests__/useBackgroundQuery/skipToken.test.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,293 @@ | ||
| import { disableActEnvironment } from "@testing-library/react-render-stream"; | ||
| import React from "react"; | ||
| import { delay, of } from "rxjs"; | ||
|
|
||
| import { | ||
| ApolloClient, | ||
| ApolloLink, | ||
| InMemoryCache, | ||
| NetworkStatus, | ||
| } from "@apollo/client"; | ||
| import { skipToken, useBackgroundQuery } from "@apollo/client/react"; | ||
| import { | ||
| createClientWrapper, | ||
| createMockWrapper, | ||
| setupVariablesCase, | ||
| } from "@apollo/client/testing/internal"; | ||
|
|
||
| import { renderUseBackgroundQuery } from "./testUtils.js"; | ||
|
|
||
| // https://github.com/apollographql/apollo-client/issues/12989 | ||
| test("maintains variables when switching to `skipToken` and calling `refetchQueries` while skipped after initial request", async () => { | ||
| const { query } = setupVariablesCase(); | ||
|
|
||
| const client = new ApolloClient({ | ||
| link: new ApolloLink((operation) => { | ||
| return of( | ||
| operation.variables.id === "1" ? | ||
| { | ||
| data: { | ||
| character: { | ||
| __typename: "Character", | ||
| id: "1", | ||
| name: "Spider-Man", | ||
| }, | ||
| }, | ||
| } | ||
| : { | ||
| data: null, | ||
| errors: [ | ||
| { message: `Fetched wrong id: ${operation.variables.id}` }, | ||
| ], | ||
| } | ||
| ).pipe(delay(10)); | ||
| }), | ||
| cache: new InMemoryCache(), | ||
| }); | ||
|
|
||
| using _disabledAct = disableActEnvironment(); | ||
| const { rerender, takeRender } = await renderUseBackgroundQuery( | ||
| ({ id }) => | ||
| useBackgroundQuery( | ||
| query, | ||
| id === undefined ? skipToken : { variables: { id } } | ||
| ), | ||
| { | ||
| initialProps: { id: "1" as string | undefined }, | ||
| wrapper: createClientWrapper(client), | ||
| } | ||
| ); | ||
|
|
||
| { | ||
| const { renderedComponents } = await takeRender(); | ||
|
|
||
| expect(renderedComponents).toStrictEqual([ | ||
| "useBackgroundQuery", | ||
| "<Suspense />", | ||
| ]); | ||
| } | ||
|
|
||
| { | ||
| const { snapshot, renderedComponents } = await takeRender(); | ||
|
|
||
| expect(renderedComponents).toStrictEqual(["useReadQuery"]); | ||
| expect(snapshot).toStrictEqualTyped({ | ||
| data: { | ||
| character: { __typename: "Character", id: "1", name: "Spider-Man" }, | ||
| }, | ||
| dataState: "complete", | ||
| error: undefined, | ||
| networkStatus: NetworkStatus.ready, | ||
| }); | ||
| } | ||
|
|
||
| await rerender({ id: undefined }); | ||
|
|
||
| { | ||
| const { snapshot, renderedComponents } = await takeRender(); | ||
|
|
||
| expect(renderedComponents).toStrictEqual([ | ||
| "useBackgroundQuery", | ||
| "useReadQuery", | ||
| ]); | ||
| expect(snapshot).toStrictEqualTyped({ | ||
| data: { | ||
| character: { __typename: "Character", id: "1", name: "Spider-Man" }, | ||
| }, | ||
| dataState: "complete", | ||
| error: undefined, | ||
| networkStatus: NetworkStatus.ready, | ||
| }); | ||
| } | ||
|
|
||
| await expect(takeRender).not.toRerender(); | ||
|
|
||
| await expect( | ||
| client.refetchQueries({ include: [query] }) | ||
| ).resolves.toStrictEqualTyped([ | ||
| { | ||
| data: { | ||
| character: { __typename: "Character", id: "1", name: "Spider-Man" }, | ||
| }, | ||
| }, | ||
| ]); | ||
|
|
||
| await expect(takeRender).not.toRerender(); | ||
| }); | ||
|
|
||
| test("suspends and fetches when changing variables when no longer using skipToken", async () => { | ||
| const { query, mocks } = setupVariablesCase({ | ||
| delay: React.version.startsWith("18") ? 200 : 20, | ||
| }); | ||
|
|
||
| using _disabledAct = disableActEnvironment(); | ||
| const { rerender, takeRender } = await renderUseBackgroundQuery( | ||
| ({ id }) => | ||
| useBackgroundQuery( | ||
| query, | ||
| id === undefined ? skipToken : { variables: { id } } | ||
| ), | ||
| { | ||
| initialProps: { id: "1" as string | undefined }, | ||
| wrapper: createMockWrapper({ mocks }), | ||
| } | ||
| ); | ||
|
|
||
| { | ||
| const { renderedComponents } = await takeRender(); | ||
|
|
||
| expect(renderedComponents).toStrictEqual([ | ||
| "useBackgroundQuery", | ||
| "<Suspense />", | ||
| ]); | ||
| } | ||
|
|
||
| { | ||
| const { snapshot, renderedComponents } = await takeRender(); | ||
|
|
||
| expect(renderedComponents).toStrictEqual(["useReadQuery"]); | ||
| expect(snapshot).toStrictEqualTyped({ | ||
| data: { | ||
| character: { __typename: "Character", id: "1", name: "Spider-Man" }, | ||
| }, | ||
| dataState: "complete", | ||
| error: undefined, | ||
| networkStatus: NetworkStatus.ready, | ||
| }); | ||
| } | ||
|
|
||
| await rerender({ id: undefined }); | ||
|
|
||
| { | ||
| const { snapshot, renderedComponents } = await takeRender(); | ||
|
|
||
| expect(renderedComponents).toStrictEqual([ | ||
| "useBackgroundQuery", | ||
| "useReadQuery", | ||
| ]); | ||
| expect(snapshot).toStrictEqualTyped({ | ||
| data: { | ||
| character: { __typename: "Character", id: "1", name: "Spider-Man" }, | ||
| }, | ||
| dataState: "complete", | ||
| error: undefined, | ||
| networkStatus: NetworkStatus.ready, | ||
| }); | ||
| } | ||
|
|
||
| await rerender({ id: "2" }); | ||
|
|
||
| { | ||
| const { renderedComponents } = await takeRender(); | ||
|
|
||
| expect(renderedComponents).toStrictEqual([ | ||
| "useBackgroundQuery", | ||
| "<Suspense />", | ||
| ]); | ||
| } | ||
|
|
||
| { | ||
| const { snapshot } = await takeRender(); | ||
|
|
||
| expect(snapshot).toStrictEqualTyped({ | ||
| data: { | ||
| character: { __typename: "Character", id: "2", name: "Black Widow" }, | ||
| }, | ||
| dataState: "complete", | ||
| error: undefined, | ||
| networkStatus: NetworkStatus.ready, | ||
| }); | ||
| } | ||
|
|
||
| await expect(takeRender).not.toRerender(); | ||
| }); | ||
|
|
||
| test("does not suspend for data in the cache when changing variables when no longer using skipToken", async () => { | ||
| const { query, mocks } = setupVariablesCase(); | ||
|
|
||
| const cache = new InMemoryCache(); | ||
|
|
||
| cache.writeQuery({ | ||
| query, | ||
| data: { | ||
| character: { __typename: "Character", id: "2", name: "Cached Widow" }, | ||
| }, | ||
| variables: { id: "2" }, | ||
| }); | ||
|
|
||
| using _disabledAct = disableActEnvironment(); | ||
| const { rerender, takeRender } = await renderUseBackgroundQuery( | ||
| ({ id }) => | ||
| useBackgroundQuery( | ||
| query, | ||
| id === undefined ? skipToken : { variables: { id } } | ||
| ), | ||
| { | ||
| initialProps: { id: "1" as string | undefined }, | ||
| wrapper: createMockWrapper({ cache, mocks }), | ||
| } | ||
| ); | ||
|
|
||
| { | ||
| const { renderedComponents } = await takeRender(); | ||
|
|
||
| expect(renderedComponents).toStrictEqual([ | ||
| "useBackgroundQuery", | ||
| "<Suspense />", | ||
| ]); | ||
| } | ||
|
|
||
| { | ||
| const { snapshot, renderedComponents } = await takeRender(); | ||
|
|
||
| expect(renderedComponents).toStrictEqual(["useReadQuery"]); | ||
| expect(snapshot).toStrictEqualTyped({ | ||
| data: { | ||
| character: { __typename: "Character", id: "1", name: "Spider-Man" }, | ||
| }, | ||
| dataState: "complete", | ||
| error: undefined, | ||
| networkStatus: NetworkStatus.ready, | ||
| }); | ||
| } | ||
|
|
||
| await rerender({ id: undefined }); | ||
|
|
||
| { | ||
| const { snapshot, renderedComponents } = await takeRender(); | ||
|
|
||
| expect(renderedComponents).toStrictEqual([ | ||
| "useBackgroundQuery", | ||
| "useReadQuery", | ||
| ]); | ||
| expect(snapshot).toStrictEqualTyped({ | ||
| data: { | ||
| character: { __typename: "Character", id: "1", name: "Spider-Man" }, | ||
| }, | ||
| dataState: "complete", | ||
| error: undefined, | ||
| networkStatus: NetworkStatus.ready, | ||
| }); | ||
| } | ||
|
|
||
| await rerender({ id: "2" }); | ||
|
|
||
| { | ||
| const { snapshot, renderedComponents } = await takeRender(); | ||
|
|
||
| expect(renderedComponents).toStrictEqual([ | ||
| "useBackgroundQuery", | ||
| "useReadQuery", | ||
| ]); | ||
| expect(snapshot).toStrictEqualTyped({ | ||
| data: { | ||
| character: { __typename: "Character", id: "2", name: "Cached Widow" }, | ||
| }, | ||
| dataState: "complete", | ||
| error: undefined, | ||
| networkStatus: NetworkStatus.ready, | ||
| }); | ||
| } | ||
|
|
||
| await expect(takeRender).not.toRerender(); | ||
| }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR should fix the need for this: testing-library/react-render-stream-testing-library#15
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been released :)