Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react testing userEvent vs fireEvent

I'm currently investigating the poor performance of some unit tests and found that use of userEvent.action() to be more computationally expensive than the equivalent fireEvent.action(). Although I've solved the original problem, a survey of our code base has several other examples that I'm investigating.

I've found explanations of why userEvent is less performant than fireEvent - React Testing Library: When to use userEvent.click and when to use fireEvent - but am still investigating where instances of the former can be replaced by the latter.

We have several examples of things like:

const user = userEvent.setup()
await user.type(field, '{escape}')

which I was guessing I could replace by something like:

fireEvent.keyPress(field, '{escape}')

However, when I do the replacement, then subsequent checks such as:

await waitFor(() => expect(...).toBeVisible)

no longer work.

My guess is that I'm misunderstanding something about the async/not_async nature of the two constructs, but can anyone offer an explanation or point me in the right direction. Also (and this might only be for personal interest if I should really be using userEvent) is there a fireEvent method I could/should use other than .keyPress() to generate the effect I'm looking for?

like image 271
Phil S Avatar asked Dec 05 '25 13:12

Phil S


1 Answers

Have you set fakeTimers in your jest.config.js? Because I believe that makes a big difference:

  fakeTimers: {
    enableGlobally: true,
  },

It is my understanding that if you can use userEvent instead of fireEvent, you should probably do that. So replacing them with fireEvent seems like the wrong strategy to me. You might gain some speed, but is that really worth the risk you get by having less accurate tests? You probably already looked at this threat, but in case you haven't: https://github.com/testing-library/user-event/discussions/977

I think you will probably be able to resolve your error by wrapping fireEvent in async act and awaiting that (as opposed to the regular act it is wrapped in):

await act(async() =>{
  fireEvent.keyPress(field, '{escape}')
}) 

There is a slight difference between doing this and await waitFor(). awaiting fireEvent waits until all the async code that it triggers is finished, whereas await waitFor waits until the assertion has finished. Which is not a great explanation, but in practice I have noticed some differences, so it might help. I based it on ccfz's answer in this threat: https://github.com/callstack/react-native-testing-library/issues/379

The libraries recommend to keep using userEvent though (I use RNTL wich is a bit more explicit about it, but I believe that it works the same).

React Testing Library: This is why you should use user-event to test interaction with your components. full docs https://testing-library.com/docs/user-event/intro/

React Native Testing Library: "In contrast, User Event provides realistic event simulation for main user interactions like press or type. Each of the interactions will trigger a sequence of events corresponding to React Native runtime behavior. These events will be invoked only on host elements, and will automatically receive event data corresponding to each event." https://callstack.github.io/react-native-testing-library/docs/user-event

like image 160
Mister_CK Avatar answered Dec 11 '25 12:12

Mister_CK