user-event: Error thrown when using react hooks
Description
Given a react component using hooks When a you attempt to use a user event e.g. type Then you receive the error below
Warning: An update to %s inside a test was not wrapped in act(...).
Reason
As far as I understand this is because we are using the fireEvent from @testing-library/dom directly and not from @testing-library/react which means that it is not being in act.
Solution
A possible solution would be to allow for the user to provide a fireEvent implementation or allow for this to be configured in test setup
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 2
- Comments: 40 (20 by maintainers)
This issue is still happening. Why is this lib still using the
fireEventfrom the@testing-library/dom? Any idea if that’s going to be changed/fixed?If I strip it right back, all is fine:
BasicForm.js:
BasicForm.test.js:
The problem is only present when I use
handleSubmitfrom react-hook-form:BasicForm.js:
npm run test BasicForm:
I think there’s a use case that still necessitates events to be wrapped in
act.If using a third-party library that triggers async logic that you have no method of
awaiting, theactwarning seems to show up.As a concrete example, I’m referring to the
validatefunction of react-hook-form. Since the state update that eventually occurs when the library validates an input is asynchronous, the state update eventually happens outside of anactcall (or at least that’s what my guess is).I’ve tested it and this works with no errors:
And this
console.errors theactwarning:If there’s a RTL async utility that I should be using and am just missing here, I’m all ears 🙂
I’m not sure how I feel about option 3.
user-eventonly exposes 3 methods. I think I’d rather see it more mature and cover more use cases.I’ll add that if you’re seeing act warnings, it’s not because user-event doesn’t handle act. Actually, the fact that
fireEventis wrapped byactis technically unnecessary because React already automatically flushes effects after it calls event handlers.For example: https://github.com/kentcdodds/user-event-act (no act warnings happen in those tests).
So as long as you’re using RTL’s async utilities then you should be solid. Often I find that these warnings show up when someone has a test that doesn’t wait for side-effects to finish (like having one test that verifies that a loading spinner shows up, but doesn’t wait for the loading to actually complete and does that in another test. These tests should be combined… I think I’ll blog about this today).
So the urgency for me on this issue is very low because I don’t think it should be even necessary.
I’m waiting for https://github.com/testing-library/react-testing-library/issues/281 to be closed to decided what to do here. Also, following #119 we might add support to Vue which would prevent us from importing from
@testing-library/react.For now, I prefer not to address this issue, but it’s something I want to get solved in the near future.
Thanks for bringing it up!
@testing-library/reactwrapsfireEventinact. See https://github.com/testing-library/react-testing-library/pull/685 So if the change happens synchronously when triggering the event, the change will happen inside anact.But if the event handler returns and executes the change per timeout/promise you need to wait for the change. And then you need to wrap that change in
actyourself.Your example does not really test anything in your system under test. So it is hard to tell if you should just wrap it in
actor take a different approach.@matburnham I’m creating a new issue with your example, hope you don’t mind.
I’m hitting this when using react-hook-forms and userEvent.click too, since this issue is closed and is not exactly the same (not specific about react-hook-forms) should we create a new one?
Can you simplify it further so it’s not using any dependencies?
It’s likely that
react-bootstraphas a side effect that’s causing this issue.Note also,
userEvent.clickis synchronous, so you shouldn’t have toawaitit at all.This should be passing without needing
actnow 😃I have same issue of
actwarnings when using both user-event and react-hook-form with it’s async form validation. The only workaround I’ve found is wrappinguserEvent.type()withact()calls. I am not sure whether the issue is actually with user-event or react-hook-forms.My general observation is that if I use
userEvent.type(input, 'some text)early in the test, and later there are couple of other async actions (like mocked network calls, but not other user-event actions) & relatedawait wait()calls then theactwarning does NOT appear. However in shorter tests theactwarning appears and I actually have to wrap my user-event actions withact()calls.I believe there are three (main) paths here. Some food for thought:
user-eventas is, trying to provide as much compatibility to different frameworks as possible. They are not that different after all.fireEventversion intouser-event.user-eventwith DOM Testing Library. DTL has become the source of truth for the whole Testing Library ecosystem (and that’s great), so this option would keep things as consistent as possible.That looks reasonable to me.
I’d rather not have any configuration if possible. I prefer to wait for the two issues I mention to be resolved before doing anything here