Skip to content
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

@testing-library/react behaves differently when dealing with Suspense in React 18 and React 19 #1375

Open
0xc14m1z opened this issue Jan 9, 2025 · 5 comments

Comments

@0xc14m1z
Copy link

0xc14m1z commented Jan 9, 2025

  • @testing-library/react version: 16.1.0
  • Testing Framework and version: jest 29.7.0
  • DOM Environment: jsdom 29.7.0

Relevant code or config:

render(
  <Suspense fallback="fallback">
    <TestComponent />
  </Suspense>
);

expect(screen.getByText("fallback")).toBeInTheDocument();
expect(await screen.findByText("resolved")).toBeInTheDocument();

What you did:

We're upgrading our codebase from React 18.3.1 to React 19.0.0.

What happened:

Over 300 tests started to fail because of suspended components kept rendering their fallbacks and never their children.

Reproduction:

In this repo we created a minimal reproduction for the issue we're facing.

It contains a folder react-18 and a folder react-19 that contains the same dependencies, configuration and code, except for the React version.

In both code bases there's the same test. It passes on the React 18 project, but fails in 2 different ways in the React 19 one.

Run npm test in each folder to see the output.

Problem description:

By default, a test that uses Suspense gets stuck rendering the fallback on React 19.

RTL emits a warning to wrap the render method in an awaited act. Following the suggestion leads the component to un-suspend, but make it impossible to assert against its fallback.

Suggested solution:

We don't have a solution for this problem, but we think RTL should behave the same with React 18 and React 19.

@MatanBobi
Copy link
Member

Thanks @0xc14m1z.
@eps1lon I think we should move forwards with the open PR we have for await act.. Wdyt?

@centraldogma99
Copy link

centraldogma99 commented Jan 10, 2025

I am also experiencing a similar issue. Same test code worked in React 18, but broken after upgrading to React 19.

Prerequisites

  • Using fake timers.
  • The component under test fetches data and displays a suspense fallback during the fetch.

Steps to Reproduce

  1. Create a test case that renders a specific component and uses a findBy query to locate specific text displayed after the data fetch completes.
  2. Copy and paste the the case multiple times within the same file.
  3. Run the test file.
  4. Only the first test case executed passes, while the others fail. The failing test cases remain in a suspended state. Occasionally, test cases other than the first one also pass, but this is intermittent.

Workaround

(This seems to not apply to all cases, but I am noting it just for reference)
I replaced the findBy query with the following workaround:

Before

await screen.findByRole('heading', { level: 1 });

After

const temp = globalThis.IS_REACT_ACT_ENVIRONMENT;
globalThis.IS_REACT_ACT_ENVIRONMENT = false;
const result = await vi.waitFor(() => {
  screen.getByRole('heading', { level: 1 });
});
globalThis.IS_REACT_ACT_ENVIRONMENT = temp;

@eps1lon
Copy link
Member

eps1lon commented Jan 10, 2025

I think we should move forwards with the open PR we have for await act.. Wdyt?

That's the plan for January. Just need to find time.

In the meantime, you can unblock yourselves by wrapping the updates that suspend in await act(async () => { ... }). The passed callback to act must be async in those cases.

@flq
Copy link

flq commented Jan 10, 2025

We have about 3'000 frontend tests - while "only" 10% are currently failing, I'm afraid we'll have to wait and see what happens next. I sill find it weird though that a "render" call on a component tree that starts being suspended seems to starve to death with the children never being rendered.

@0xc14m1z
Copy link
Author

0xc14m1z commented Jan 10, 2025

Thanks @eps1lon for taking care of this.

We're going to postpone the upgrade because we have around 300 tests failing because of this issue.
Some of them assert against the fallback, so they'll fail anyway when wrapping the suspended updates with the async act.

The workaround would have to be reverted once the issue is fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants