@testing-library/react: render userEvent
Render components in a simulated DOM, query by role and label text, fire user interactions with userEvent, and assert on visible output.
@testing-library/react: render userEvent is a free Frontend Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Frontend Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Testing Library Philosophy
@testing-library encourages tests that resemble how users interact with the UI. Query by role, label, and text — not by implementation details like CSS class names or component internals.
Installing Testing Library
Install Testing Library for React and the userEvent package for user interaction simulation.
npm install -D @testing-library/react @testing-library/user-event @testing-library/jest-domrender() — Mount a Component
render(<Component />) mounts the component in a simulated DOM. It returns query functions to find elements.
import { render, screen } from '@testing-library/react';
import { Button } from './Button';
test('renders button with label', () => {
render(<Button label="Submit" onClick={() => {}} />);
expect(screen.getByRole('button', { name: 'Submit' })).toBeInTheDocument();
});Querying Elements
Prefer queries in this order: getByRole (accessible), getByLabelText, getByPlaceholderText, getByText, getByDisplayValue. Use queryBy* when testing non-existence. Use findBy* for async elements.
// Prefer (accessible):
screen.getByRole('button', { name: /submit/i });
screen.getByLabelText('Email');
// For text content:
screen.getByText('Welcome!');
// Existence check:
expect(screen.queryByText('Error')).not.toBeInTheDocument();
// Async appearance:
await screen.findByText('Data loaded');userEvent — Simulating User Actions
userEvent simulates real user interactions: typing, clicking, keyboard navigation. It's more realistic than the older fireEvent.
import userEvent from '@testing-library/user-event';
test('typing in input', async () => {
const user = userEvent.setup();
render(<SearchInput />);
const input = screen.getByRole('textbox', { name: /search/i });
await user.type(input, 'react hooks');
expect(input).toHaveValue('react hooks');
});Testing Form Submission
Fill in form fields and submit. Assert on the outcome — what the user sees after submission.
test('submitting the login form', async () => {
const onLogin = jest.fn();
const user = userEvent.setup();
render(<LoginForm onLogin={onLogin} />);
await user.type(screen.getByLabelText('Email'), 'alice@example.com');
await user.type(screen.getByLabelText('Password'), 'secret123');
await user.click(screen.getByRole('button', { name: /sign in/i }));
expect(onLogin).toHaveBeenCalledWith({ email: 'alice@example.com', password: 'secret123' });
});jest-dom Custom Matchers
@testing-library/jest-dom adds useful matchers: toBeInTheDocument(), toBeVisible(), toBeDisabled(), toHaveValue(), toHaveClass(), toHaveFocus().
Testing Async Component Updates
Use waitFor() or findBy* for elements that appear asynchronously (after a fetch, after a timeout).
test('shows data after loading', async () => {
render(<UserList />);
expect(screen.getByRole('status')).toHaveTextContent('Loading');
const items = await screen.findAllByRole('listitem');
expect(items).toHaveLength(3);
});Testing Loading and Error States
Mock the fetch response to test different states. MSW (Mock Service Worker) is the best tool for mocking API responses in tests.
Accessibility Testing
Testing Library naturally encourages accessibility — if you can't query an element by role or label, it's likely inaccessible. Use jest-axe for automated accessibility audits in tests.
Don't Test Implementation Details
Avoid: querying by CSS class names, importing component internal state, testing that specific methods were called. Test behaviour from the user's perspective: what they see and what happens when they interact.
Quick Check
Which Testing Library query function should be preferred for finding interactive elements?
Recap: @testing-library/react
render() mounts components in a simulated DOM. Query by role, label, and text — not implementation details. userEvent.setup() for realistic user interactions. findBy* for async elements. jest-dom for readable assertions. Test from the user's perspective: what they see and do. Accessible components are easier to test.
Frequently asked questions
Is the “@testing-library/react: render userEvent” lesson free?
Yes — the full text of “@testing-library/react: render userEvent” is free to read here on the web, and the Frontend Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Frontend Academy course, upgrade to CoddyKit PRO.
What will I learn in “@testing-library/react: render userEvent”?
Render components in a simulated DOM, query by role and label text, fire user interactions with userEvent, and assert on visible output. You practise Frontend Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Frontend Academy?
No prior experience is required. Frontend Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “@testing-library/react: render userEvent” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Frontend Academy lesson?
Yes. Every Frontend Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Jest Setup and Basic Tests
- @testing-library/react: render userEvent
- @testing-library/vue: mounting components
- Mocking Modules and API Calls