user-event: Update of the @testing-library/react version to 14.0.0 throws "act" warnings

  • @testing-library/react version: 14.0.0
  • Testing Framework and version: jest 29.4.2
  • DOM Environment: @testing-library/jest-dom: 5.16.5

Relevant code or config:

   const saveButton = screen.getByRole('button', { name: /save/i });
    await waitFor(() => expect(saveButton).toBeEnabled());
    await testUser.click(saveButton);

What you did:

I upgraded the version of @testing-library/react from 13.4.0 to 14.0.0. And I started having problems in all the tests of my application. Before this update this did not happen.

What happened:

I’m getting more act warnings now with @testing-library@14.0.0. Tested with await waitFor, and still throwing act warnings with userEvent that triggers a state change. Captura de Pantalla 2023-02-20 a la(s) 18 29 41 Captura de Pantalla 2023-02-20 a la(s) 18 29 13

Reproduction:

You can fork to reproduce the issue: here: https://codesandbox.io/s/act-warning-wait-for-react-18-forked-6jurf2

Problem description:

The state update (setState()) seems to make the test library think that act is incomplete, even though it is. This happens for every unit test where an event is fired, such as userEvent.click() or userEvent.upload().

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 47
  • Comments: 28 (8 by maintainers)

Commits related to this issue

Most upvoted comments

I have the same issue, wrapping testUser.click(saveButton) inside an act call resolves the issue. The problem is that this will have major impact on our codebase. I am wondering why this is now needed. It’s not listed in the release notes as breaking change so I’d say it should not break moving from 13.x.x to 14.0.0.

+1, but I’ll add: I’m not just getting warnings, my tests are now failing after the upgrade. So it’s not just the verbosity of the warnings that are the problem, it’s the changed behavior.

I also noticed that I’m seeing these act warnings on updates I do via @testing-library/user-event.

I do like how testing-library takes care of wrapping its own calls in act in all the obvious places. I don’t think expecting callers to wrap all their calls in act now is a good solution. (And if that is the plan, then it’s a breaking change that would need to be in the docs.)

I think @ph-fritsche hit the nail on the head here 🚀

I experienced lots of erroneous act warnings after updating @testing-library/react to version 14.

  "@testing-library/react": "^14.0.0",
  "@testing-library/user-event": "^14.4.3",

I’m assuming this is due to @testing-library/react depending on @testing-library/dom version ^9.0.0, and @testing-library/user-event having a peer dependency on @testing-library/dom version >=7.21.4. This led to @testing-library/dom resolving to version 8.11.1.

  "node_modules/@testing-library/react": {
    "version": "14.0.0",
    "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.0.0.tgz",
    "integrity": "sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==",
    "dev": true,
    "dependencies": {
      "@babel/runtime": "^7.12.5",
      "@testing-library/dom": "^9.0.0",
      "@types/react-dom": "^18.0.0"
    },
    "engines": {
      "node": ">=14"
    },
    "peerDependencies": {
      "react": "^18.0.0",
      "react-dom": "^18.0.0"
    }
  },
  "node_modules/@testing-library/user-event": {
    "version": "14.4.3",
    "dev": true,
    "license": "MIT",
    "engines": {
      "node": ">=12",
      "npm": ">=6"
    },
    "peerDependencies": {
      "@testing-library/dom": ">=7.21.4"
    }
  }

Overriding @testing-library/dom to version ^9.0.1 fixed all of the erroneous act warnings I was experiencing as mentioned here.

  "overrides": {
    "@testing-library/dom": "^9.0.1"
   }

Thanks for the awesome library. Hopefully this helps someone else.

I think @ph-fritsche hit the nail on the head here 🚀

I experienced lots of erroneous act warnings after updating @testing-library/react to version 14. Thanks for the awesome library. Hopefully this helps someone else.

Thanks. I experienced the same. It was caused by eslint-plugin-jest-dom which is still using version 8. For yarn I needed to add a resolution to fix it

I see different issues being mixed up here.

  1. If you use e.g. @testing-library/react and @testing-library/user-event, those need to resolve @testing-library/dom to the same copy.

    See https://testing-library.com/docs/user-event/install:

    Note that @testing-library/user-event requires @testing-library/dom.

    If you use one of the framework wrappers, it is important that @testing-library/dom is resolved to the same installation required by the framework wrapper of your choice.
    Usually this means that if you use one of the framework wrappers, you should not add @testing-library/dom to your project dependencies.

    With recent versions of npm you need to run npm dedup.

  2. If you use fake timers, you need to tell @testing-library/user-event how to wind the timer.

    See https://testing-library.com/docs/user-event/options#advancetimers:

    If you are using fake timers, you need to advance your timers when we internally delay subsequent code.

     (delay: number) => Promise<void> | void
    

    default: () => Promise.resolve()

    With Jest’s fake timers you need to setup user-event with {advanceTimers: jest.advanceTimersByTime}.

  3. If you get act warnings after updating React, you might have brittle test code that expects an undefined order of execution to be the same on every test run.

    See https://twitter.com/ph_fritsche/status/1626279438496280576:

    Do not just add act() calls until React shuts up!
    https://ph-fritsche.github.io/blog/post/react-act

I think this may not be resolved for User Event.

// Temporary workaround for testing library's act() not working with userEvent
export async function actWrappedUserEvent(event: Promise<void>): Promise<void> {
  return await act(async () => {
    await event;
  });
}
await actWrappedUserEvent(user.click(submitButton));

the error isnt causing any tests to fail but the only way ive keep the error from bubbling up is to wrap it in an act

Just returning any promise is just masking the issue. It works with pushing it to the next microtask here, but it might fail when you run the same test in a slightly different environment. There you might need to await any other number of additional microtasks, which makes this a randomly working workaround™.

The correct way to fix with is to create a promise that resolves when the state update is applied. Fake timers complicate this a little bit.

await waitFor(() => expect(screen.getByRole('checkbox')).toBeChecked(), {
  timeout: 10000, // Allow the callback to run ten times
  interval: 1000, // Increase the interval
})

I’ve updated the library to version 14.0.0 to fix some act warnings that were being thrown and I’m glad to report that the new release has indeed fixed them.

One shouldn’t need to wrap @testing-library/user-event calls with act as that’s already done for you.

I’d start with a simple test case and see if you are following all the requirements since recently there was a recent addition of setup on user-event library, or maybe you are also using an old version of react?

I could also be wrong and there might be a bug, but wanted to say that it’s working as expected for me without any “missing act” being logged. It’s important to see a reproducible scenario where this is happening as otherwise it’s possible you are missing something on your tests setup.

Overriding @testing-library/dom to version ^9.0.1 fixed all of the erroneous act warnings I was experiencing as mentioned here.

  "overrides": {
    "@testing-library/dom": "^9.0.1"
   }

This worked for me, we are using yarn and we had to add resolutions instead of overrides.

Thank you @louis-young

"resolutions": {
    "postcss": "^8.3.6",
    "@testing-library/dom": "^9.0.1"
  }

I think I managed to extract the issue into reproducible test https://github.com/artursvonda/rtl-14-act-repro. Let me know if this helps. As you see in the test, I’m not doing anything funky.

Thanks for confirming this is not expected. I finally managed to fix the issue on my project by deleting my package-lock.json and node-modules and re-running npm install.