How to Use userEvent in Testing Library with React
Use
userEvent from @testing-library/user-event to simulate real user interactions in React tests. Import it, then call methods like click() or type() on elements to mimic user behavior.Syntax
The userEvent object provides methods to simulate user actions on DOM elements in React tests. You first import userEvent from @testing-library/user-event. Then you call methods like click(element), type(element, text), or clear(element) to mimic user input.
Each method takes the target element as the first argument. For typing, the second argument is the string to enter.
javascript
import userEvent from '@testing-library/user-event'; // Example usage: await userEvent.click(buttonElement); await userEvent.type(inputElement, 'Hello');
Example
This example shows a simple React component with an input and a button. The test uses userEvent.type to enter text and userEvent.click to submit. It verifies the displayed output updates accordingly.
javascript
import React, { useState } from 'react'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; function Greeting() { const [name, setName] = useState(''); const [greet, setGreet] = useState(''); const handleClick = () => { setGreet(`Hello, ${name}!`); }; return ( <div> <input aria-label="name-input" value={name} onChange={e => setName(e.target.value)} /> <button onClick={handleClick}>Greet</button> <p>{greet}</p> </div> ); } // Test test('userEvent types and clicks correctly', async () => { render(<Greeting />); const input = screen.getByLabelText('name-input'); const button = screen.getByRole('button', { name: 'Greet' }); await userEvent.type(input, 'Alice'); await userEvent.click(button); expect(screen.getByText('Hello, Alice!')).toBeInTheDocument(); });
Output
Test passes with greeting text 'Hello, Alice!' displayed after typing and clicking.
Common Pitfalls
- Not awaiting
userEvent.typecan cause flaky tests because typing is async. - Using
fireEventinstead ofuserEventmisses realistic user behavior like delays and events sequence. - For controlled inputs, ensure the component updates state on
onChangeto reflect typed text.
javascript
/* Wrong: missing await on userEvent.type */ userEvent.type(input, 'Bob'); userEvent.click(button); /* Right: await userEvent.type to complete typing */ await userEvent.type(input, 'Bob'); await userEvent.click(button);
Quick Reference
| Method | Description | Usage Example |
|---|---|---|
| click(element) | Simulates a mouse click on the element | await userEvent.click(button) |
| type(element, text) | Types text into an input or textarea asynchronously | await userEvent.type(input, 'Hello') |
| clear(element) | Clears the value of an input or textarea | await userEvent.clear(input) |
| dblClick(element) | Simulates a double click | await userEvent.dblClick(button) |
| hover(element) | Simulates mouse hover | await userEvent.hover(div) |
| unhover(element) | Simulates mouse leaving element | await userEvent.unhover(div) |
Key Takeaways
Import userEvent from '@testing-library/user-event' to simulate user actions in React tests.
Always await userEvent.type because it is asynchronous and mimics real typing delays.
Use userEvent methods like click and type to test user interactions realistically.
Avoid fireEvent for typing and clicking as userEvent better simulates real user behavior.
Ensure your React components update state on input changes to reflect userEvent typing.