React Testing Library's core render() function mounts a component into a real, JSDOM-simulated DOM, and its screen object provides query methods, like getByText, getByRole, and getByLabelText, that find elements the same way a real user would locate them, by visible text, accessible role, or associated label, rather than by internal component names or implementation-specific selectors. Its guiding philosophy, summarized in its own documentation, is that the more your tests resemble the way your software is actually used, the more confidence they can give you — paired with the userEvent library for realistically simulating clicks, typing, and other interactions, and Jest as the underlying test runner and assertion library.
1Understanding User-Centric Testing with React Testing Library
React Testing Library's core render() function mounts a component into a real, JSDOM-simulated DOM, and its screen object provides query methods, like getByText, getByRole, and getByLabelText, that find elements the same way a real user would locate them, by visible text, accessible role, or associated label, rather than by internal component names or implementation-specific selectors. Its guiding philosophy, summarized in its own documentation, is that the more your tests resemble the way your software is actually used, the more confidence they can give you — paired with the userEvent library for realistically simulating clicks, typing, and other interactions, and Jest as the underlying test runner and assertion library.
Prefer getByRole() over getByTestId() or a CSS-selector-based query whenever possible — querying by role most closely reflects how a real user, especially someone using a screen reader, actually perceives and interacts with an element, and it also nudges your markup toward being more accessible.
import { render, screen } from '@testing-library/react';
import Greeting from './Greeting';
test('renders a greeting for the given name', () => {
render(<Greeting name="Ana" />);
expect(screen.getByText('Hello, Ana!')).toBeInTheDocument();
});2Practical Example
Here is a real-world application of User-Centric Testing with React Testing Library showing how it is used in production React code.
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Counter from './Counter';
test('increments the count when the button is clicked', async () => {
render(<Counter />);
await userEvent.click(screen.getByRole('button', { name: /increment/i }));
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});3Best Practices
Follow these guidelines when working with User-Centric Testing with React Testing Library:
1. Query rendered elements the way a real user would, by visible text, label, or accessible role, rather than by internal implementation details like a component's name or an arbitrary CSS class
2. Use the userEvent library to simulate realistic user interactions, like typing and clicking, rather than firing low-level synthetic DOM events directly
3. Reserve data-testid attributes and getByTestId() as a last resort, specifically for elements with no other reasonable way to query them as a real user would identify them
Tip: Prefer getByRole() over getByTestId() or a CSS-selector-based query whenever possible — querying by role most closely reflects how a real user, especially someone using a screen reader, actually perceives and interacts with an element, and it also nudges your markup toward being more accessible.
import { render, screen } from '@testing-library/react';
import Greeting from './Greeting';
test('renders a greeting for the given name', () => {
render(<Greeting name="Ana" />);
expect(screen.getByText('Hello, Ana!')).toBeInTheDocument();
});