-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
React 18. set state in finally throws "act" warning, though test is passing #1051
Comments
I encountered something similar while using Formik, I suspect this is related. Here is a repo which reproduces this issue: This only happens on the new version of RTL and React 18. |
I'm using react-hook-form and experience the same act warning. Using either The only thing that worked is to wrap act with sleep. await act(async () => {
await new Promise((resolve) => {
setTimeout(resolve, 50);
});
}); credit to https://bufferings.hatenablog.com/entry/2021/11/18/015809 |
- migrate react-testing-library to support react 18 ([unsolved warning](testing-library/react-testing-library#1051)) - vitest to 0.10.0
- migrate react-testing-library to support react 18 ([unsolved warning](testing-library/react-testing-library#1051)) - vitest to 0.10.0
- migrate react-testing-library to support react 18 ([unsolved warning](testing-library/react-testing-library#1051)) - vitest to 0.10.0
This comment was marked as off-topic.
This comment was marked as off-topic.
It doesn't look like this bug report has enough info for one of us to reproduce it. Please provide a CodeSandbox (https://react.new), or a link to a repository on GitHub. Here are some tips for providing a minimal example: https://stackoverflow.com/help/mcve |
Hey guys, i made some tests because I am having the same problem:
This way it works fine:
But if I change to userEvent, I get the act() warning all over again.
|
I am having a similar problem after updating to |
@eps1lon I replicated our issue here: https://codesandbox.io/s/rtl-react-18-act-issue-forked-l0bcj2?file=/src/__tests__/App.test.js. You can see this error when you run tests and check the output in the console. In our case it's triggered by a component that uses We're getting these warnings/errors in other places as well (e.g. we had 2 |
I'm running into the same problem upgrading my App to React 18, and RTL to 13.3.0. In my case, I've even got a test which triggers an Even if I add |
Based on my tests, it looks like Edit: Note that calling
|
We found that pinning the version of |
Having struggled with a lot of
On removing the dependency from our For info, currently using:
|
Just to add to this, we've noticed our tests riddled with act errors since moving to react 18. I've been able to solve most by swapping getBy to findBys and using waitFors however it has been a pain updating pretty much every test. In addition, I also had to enable |
Like others have mentioned, we're also seeing this pervasively after upgrading to react 18 and latest RTL.
Hoping for a solution that doesn't involve wrapping all our tests in additional Edit: In my case, it seems it's caused by remix-run/react-router#7634 as we're also upgrading to react router v6 as part of this. The Just putting this here in case it helps any one else dropping by. |
react-testing-library/src/pure.js Lines 19 to 24 in 9171163
It looks like this is the culprit, it disables the "act environment" while running waitFor .This doesn't make sense to me, any particular reason for doing this @eps1lon? |
Because we're not acting when we wait for something to happen. Anything wrapped in More detailed explainer: #937 (comment) |
Is this documented somewhere?
Do we need to flush state updates? Don't they run anyway when they can? |
I guess the documentation for
If inside an |
I appreciate all the additional info here, both from maintainers and other users. I have never really wrapped my head around Is it something we as consumers should be doing differently in our tests? Something that needs to change on the React side? Something that needs to change in react-testing-library? Some combination of things? Something else entirely? Not clear yet? I'm essentially delaying my upgrade to React 18, as a result of this issue, but it's not quite clear to me what the eventual fix will be. So if someone is able to add some clarity there, I would really appreciate that. 🙏 |
I have a test roughly like this: setup();
await userEvent.click(someButton);
await waitFor(() =>
expect(getCell()).toHaveTextContent('...');
); Clicking the button triggers an function with an API call roughly like this: async function onClick() {
try {
setLoading(true);
const data = await api('POST', ...);
// update the swr cache with the new data
// this is what will update the DOM
await mutate(...);
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
} The test works fine, but React still gives me an What I had to do was setup();
await userEvent.click(someButton);
await waitForElementToBeRemoved(someSpinner);
expect(getCell()).toHaveTextContent('...'); Now the
🤷♂️ |
- https://floating-ui.com/docs/react-dom#testing - https://testing-library.com/docs/user-event/intro/#difference-to-fireevent - testing-library/react-testing-library#1051 - Switch from fireEvent to userEvent for floating-ui tests. - Because floating-ui styling is applied async, a state update occurs in a Promise microtask leading to errors and warnings after upgrading React. - Migrating to userEvent solves this issue. - Some snapshot updates required as async styling unrelated to test that was not previously applied now is.
We are able to spot-fix tests by wrapping in act, but tests then fail previously passing cases with strange outputs that do not match manual testing. Not to mention in our large-ish codebase, its nigh impossible to manually update the 1000+ tests we have... |
To be sure I'm not missing anything, I created two small codesandboxes with the same test. In https://codesandbox.io/s/act-warning-waitfor-react-17-btzykv import { render, screen, waitFor } from "@testing-library/react";
import App from "./App";
import userEvent from "@testing-library/user-event";
describe("app", () => {
it("turns on", async () => {
render(<App />);
await userEvent.click(screen.getByText("Turn on"));
// I'm aware of find*, but the point is about `waitFor`
await waitFor(async () => {
screen.getByText("It is on");
});
// that's just here so the test doesn't finish prematurely
await new Promise((resolve) => {
setTimeout(resolve, 300);
});
});
}); The component under test, shows some text on click after a few ms import { useState } from "react";
import "./styles.css";
export default function App() {
const [isOn, setIsOn] = useState(false);
return (
<div className="App">
{isOn && <div>It is on</div>}
<button
onClick={() => {
setTimeout(() => {
setIsOn(true);
}, 1000);
}}
>
Turn on
</button>
</div>
);
} The same setup with https://codesandbox.io/s/act-warning-wait-for-react-18-w4e521 @eps1lon is this really the intended behaviour from now on or am I missing/misunderstanding something? It also seems like Example sandbox for this behaviour: https://codesandbox.io/s/act-warning-wait-for-react-18-forked-nc2mm8?file=/src/App.test.js |
* This reverts commit 5015f26. * Wait until testing-library/react-testing-library#1051 gets fixed.
It was already mentioned by others, but making sure that we only have one version of If you use yarn, you can run |
I just upgraded |
@intercaetera It's not runnable. Even after fixing the lockfile ( The repro from @szimek worked i.e. I could reproduce the bug with their repro. It also had problems though since it didn't have a lockfile. NPM couldn't even install it anymore. Only yarn succeeded. The 3rd repro from @robin-drexler finally worked (though still missing a lockfile). However, it's a clear example of a missing - await new Promise((resolve) => {
- setTimeout(resolve, 300);
+ await act(async () => {
+ await new Promise((resolve) => {
+ setTimeout(resolve, 300);
+ }); In the future, please make sure repros are minimal and runnable indefinitely in the futre (e.g. they have a lockfile ensuring the same install, they have a Node.js version. The repro from @szimek looks like a duplicate to #1125 so I'll close this issue once we land #1137 |
Fixed in #1137 |
I'm getting more Tested version: |
|
+1 |
For people still having issues, please file a new one and include a minimal, cloneable reproduction. Just a list of dependencies is not sufficient. |
@testing-library/react
version: 13.1.1Relevant code or config:
What you did:
NOTE: This error only shows up after updating to react 18 and testing library to 13.1.1, this was not an issue in earlier version.
setSubmitting toggles the button disability. When the promise is complete, it turns the re-enables the button. so the test is doing a waitFor button to be re-enabled.
the promise looks more like this
dispatch(makePayment(paymentInfo)) returns a promise, with a catch inside.
so the whole promise chain looks like this
promisedFunction().then(() => do something).catch(error => show error). then(() => componentLevel).catch(do nothing here).finally(reset state)
What happened:
the "act" error is thrown, even though i've added a waitFor and that is passing to prove that that statement has already been rendered.
Problem description:
set state in finally seems to cause testing library to think act is incomplete, even though it is.
currently solving the error by putting the set state inside of catch
However, there's the WET code, i had to put the set state into handlePaymentSuccess too, to achieve the same results.
The text was updated successfully, but these errors were encountered: