Skip to content

FALLBACK_THROTTLE_MS slows tests down significantly - could it be configurable? #30408

Open
@phryneas

Description

@phryneas

Summary

Hi there 👋,

we encountered a massive slowdown in the Apollo Client React hooks test suite - especially on the suspense-related tests - when we started testing for React 19.

One file specifically went up from a 10s execution time to 80s.

Further discussion on twitter and later in an issue in testing library revealed that this slowdown relates to React 19 being more strict with the throttle of the Suspense fallback, and that every suspense fallback shown in a test now slows down the test by an additional 300ms.

While I generally agree with testing close to the original implementation, in our case this massively slows down our local development and significantly increases the CI minutes used (it sums up over all tests to an additional 2 minutes for every CI run).

Changing everything to mocked timers is something that would honestly be very painful (even if only on affected tests), and if it would really need to be done on a global scale as indicated by @eps1lon in that issue, I believe it would just be completely out of the question in many cases - it would require rewriting thousands of tests, even if not suspense-related.

Would you be willing to make FALLBACK_THROTTLE_MS configurable, similar to IS_REACT_ACT_ENVIRONMENT?

I did patch the timeout for our test suite, and could verify that it almost brings execution times back down to the original - I kept the timeout at a for tests more reasonable 10ms, so we go from 10s on React 18 to 15s on React 19 now.

I would happily submit a PR if you would consider this.

Reproduction

You can see this happening in this reproduction (runnable repo here: https://github.com/phryneas/react-19-reproduction-slow-tests):

test("does not timeout", async () => {
  const initialPromise = Promise.resolve("test");
  console.time("executing component render");
  console.time("got past the `use` call");
  console.time("assertion succeeded");

  function Component() {
    console.timeLog("executing component render");
    const renderResult = use(initialPromise);
    console.timeLog("got past the `use` call", renderResult);
    return <div>{renderResult}</div>;
  }

  render(
    <Suspense fallback={<div>loading</div>}>
      <Component />
    </Suspense>
  );

  await waitFor(() => {
    screen.getByText("test");
    console.timeLog("assertion succeeded");
  });
});

Which logs

    executing component render: 4 ms

    executing component render: 51 ms

    got past the `use` call: 53 ms test

    assertion succeeded: 340 ms

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions