Rendering and Querying Elements
In this page:
render(<Component />);
screen.getByRole("role", { name: "label" }); // throws if missing
screen.queryByText("text"); // null if missing
await screen.findByText("text"); // waits for async content
getBy vs. queryBy vs. findBy
getBy* throws an error immediately if no matching element exists, making it ideal for asserting something IS present. queryBy* returns null instead of throwing, making it the right choice for asserting something is ABSENT. findBy* returns a Promise and waits, ideal for elements that appear after an async action.
- A simple mental model:
- getBy for 'this should exist right now'
- queryBy for 'this should NOT exist'
- findBy for 'this will exist soon'.
Example: getBy vs. queryBy vs. findBy
// Run in your local React project (npm install required)
import { render, screen } from '@testing-library/react';
import Alert from './Alert';
test('alert is not shown initially', () => {
render(<Alert show={false} />);
expect(screen.queryByText('Warning!')).not.toBeInTheDocument();
});
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
Waiting for Async Content with findBy
When content appears after an asynchronous action (like a fetch resolving), findBy* queries return a Promise that repeatedly checks for the element until it appears or a timeout is reached, avoiding the need for manual waiting or arbitrary setTimeout calls in tests.
Example: Waiting for Async Content with findBy
// Run in your local React project (npm install required)
import { render, screen } from '@testing-library/react';
import UserProfile from './UserProfile';
test('shows user name after loading', async () => {
render(<UserProfile userId={1} />);
const name = await screen.findByText('Asha');
expect(name).toBeInTheDocument();
});
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
The Recommended Query Priority
Testing Library recommends a priority order for which query to reach for first: getByRole is preferred (it reflects real accessibility semantics), then getByLabelText for form fields, then getByText for general content, with test-ID-based queries as a last resort when nothing else fits.
Example: The Recommended Query Priority
// Run in your local React project (npm install required)
// Priority order (most to least preferred):
screen.getByRole('button', { name: 'Save' }); // 1st choice
screen.getByLabelText('Email address'); // 2nd choice
screen.getByText('Welcome back'); // 3rd choice
screen.getByTestId('save-button'); // last resort
- Using getByText for elements identified better by role, missing accessibility semantics the test could otherwise verify.
- Not knowing the difference between getBy, queryBy, and findBy — each behaves differently for missing or async elements.
- Overusing container.querySelector, bypassing Testing Library's user-centric query system entirely.
- getBy* queries throw if zero or multiple matches are found — use for elements expected to exist right now.
- queryBy* returns null instead of throwing — use to assert something does NOT exist.
- findBy* returns a Promise, waiting for an element to appear — use for content that shows up asynchronously.
- Query priority (recommended order): getByRole, getByLabelText, getByText, then more implementation-specific options.
Requires npm install @testing-library/react — 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: