React Testing Library userEvent
`userEvent` simulates realistic user interactions such as typing, clicking, tabbing, and selecting in React tests. It is generally preferred for testing behavior through the same interaction patterns a real user would perform.
`@testing-library/user-event` provides interaction APIs that model browser user behavior more closely than directly calling DOM methods. Common operations include `click`, `type`, `clear`, `tab`, `selectOptions`, and keyboard interactions.
A typical test creates a `user` instance with `userEvent.setup()`, then awaits interaction methods such as `await user.click(button)` or `await user.type(input, "hello")`. The asynchronous API allows the library to model the sequence of events involved in interactions.
The main testing principle is to interact with the UI through accessible elements and then assert what the user can observe. For example, a test can type into a textbox, click a submit button, and verify that a confirmation message appears.
`userEvent` is different from low-level event utilities because an interaction can produce multiple browser events and intermediate behavior. This makes tests more representative of actual usage, while still keeping them focused on observable application behavior.
Key points
- Use `userEvent.setup()` to create a user interaction instance.
- Prefer `await user.click(...)`, `await user.type(...)`, and similar APIs for interactions.
- Test through accessible UI elements rather than component implementation details.
- `userEvent` models higher-level interactions more realistically than directly firing isolated events.
Interview questions
What is `userEvent` in React Testing Library?
`userEvent` is a library for simulating user interactions in tests. It provides APIs for actions such as clicking, typing, tabbing, and selecting options. These interactions are designed to resemble how a real user operates the UI. Tests can then assert the resulting observable behavior.
How do you normally use `userEvent` in a test?
First, create a user instance with `userEvent.setup()`. Then render the component and locate its controls with Testing Library queries. Perform interactions such as `await user.type(...)` or `await user.click(...)`. Finally, assert the UI state or output produced by those interactions.
Why is `userEvent` often preferred over `fireEvent`?
`fireEvent` focuses on dispatching an individual DOM event, whereas `userEvent` represents a higher-level action a user performs. A real interaction can involve multiple events and intermediate browser behavior. Using `userEvent` can therefore expose problems that a single manually dispatched event would not reproduce. The choice should still match the behavior the test needs to exercise.
Why do `userEvent` calls commonly use `await`?
Many `userEvent` interactions are asynchronous because the library models interaction steps rather than simply dispatching one event. Awaiting the operation ensures the simulated interaction has completed before the test makes its assertion. This helps avoid race conditions where the assertion runs before the UI has processed the interaction. The exact behavior can depend on the interaction and library version.
How would you test keyboard navigation with `userEvent`?
I would render the relevant UI and use accessible queries to locate the elements involved. Then I would call keyboard-oriented APIs such as `await user.tab()` or `await user.keyboard(...)`. I would assert observable results such as which element has focus or whether a control becomes available. This keeps the test centered on the keyboard behavior a user experiences.