Simulating User Events
In this page:
Simulating a Click
userEvent.click(element) simulates a real user clicking an element, including the full sequence of events a browser would actually fire (pointerdown, mousedown, focus, etc.), more accurately than the more basic fireEvent.click, which only fires a single click event.
Note: Always await userEvent methods — they return Promises to accurately model the timing of real interactions.
Warning: In newer versions of the library, you must call userEvent.setup() first and use the returned object, rather than calling userEvent.click directly.
Example: Simulating a Click
// Run in your local React project (npm install required)
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Counter from './Counter';
test('increments on click', async () => {
const user = userEvent.setup();
render(<Counter />);
await user.click(screen.getByText('Increment'));
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
Simulating Typing into an Input
userEvent.type(element, text) simulates a user typing character by character, triggering the same sequence of keyboard and input events a real keystroke would, which is more realistic than setting an input's value directly.
Note: This realism matters for components with logic tied to individual keystrokes, like a live character counter or format-as-you-type input.
Warning: Typing simulated this way is genuinely character-by-character, so it can make tests slightly slower than directly setting a value — usually a worthwhile tradeoff for accuracy.
Example: Simulating Typing into an Input
// Run in your local React project (npm install required)
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import SearchBox from './SearchBox';
test('updates as user types', async () => {
const user = userEvent.setup();
render(<SearchBox />);
await user.type(screen.getByRole('textbox'), 'react');
expect(screen.getByDisplayValue('react')).toBeInTheDocument();
});
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
Testing a Full Form Submission Flow
Combining several userEvent calls in sequence lets you simulate a complete realistic flow — typing into fields, then clicking submit — mirroring exactly what a real person would do, and verifying the resulting behavior (like a success message appearing).
Note: Chain userEvent calls with await between each step, mirroring the real order a user would perform them in.
Warning: Forgetting to await each userEvent call in a multi-step flow can cause steps to race each other, producing flaky, inconsistent test results.
Example: Testing a Full Form Submission Flow
// Run in your local React project (npm install required)
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import LoginForm from './LoginForm';
test('submits the login form', async () => {
const user = userEvent.setup();
render(<LoginForm />);
await user.type(screen.getByLabelText('Email'), '[email protected]');
await user.click(screen.getByRole('button', { name: 'Log In' }));
expect(await screen.findByText('Welcome back!')).toBeInTheDocument();
});
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
- Using fireEvent for typing when userEvent more accurately simulates real keystroke-by-keystroke typing behavior.
- Forgetting that most userEvent methods are async and need await.
- Not setting up userEvent with userEvent.setup() in newer versions of the library before using it.
- @testing-library/user-event simulates real user interactions more realistically than the lower-level fireEvent API.
- userEvent.click, userEvent.type, and similar methods are async and should be awaited.
- userEvent.setup() creates a user-event instance, typically called once at the top of a test.
- Simulating realistic interactions catches bugs that a more artificial fireEvent might miss.
Requires npm install @testing-library/user-event — runs in a Node test environment, not this browser sandbox.
Chapter Quiz — Complete all 9 topics to unlock
0/9 topics done
Complete these topics first: