React Testing Library focuses on testing components from the user's perspective. Instead of asking whether a specific internal function was called, the test asks whether the user can see text, click a button, enter data, and observe the expected result.
Why React Testing Library?
The library encourages tests that resemble real usage. Prefer accessible roles, labels, visible text, and user interactions over querying component internals.
render(<LoginForm />);
expect(
screen.getByRole("button", { name: /login/i })
).toBeInTheDocument();
User interaction
const user = userEvent.setup();
await user.type(
screen.getByLabelText(/email/i),
"ravi@example.com"
);
await user.click(
screen.getByRole("button", { name: /login/i })
);
Complete login component test
it("shows validation error for empty email", async () => {
const user = userEvent.setup();
render(<LoginForm />);
await user.click(
screen.getByRole("button", { name: /login/i })
);
expect(
await screen.findByText("Email is required")
).toBeInTheDocument();
});
Query priority
Prefer queries that represent how a user or assistive technology identifies an element.
- getByRole
- getByLabelText
- getByText
- getByPlaceholderText when necessary
- getByTestId as a last-resort testing hook
Testing loading and success
render(<Products />);
expect(
screen.getByText("Loading products...")
).toBeInTheDocument();
expect(
await screen.findByText("Laptop")
).toBeInTheDocument();
Testing Redux connected components
render(
<Provider store={store}>
<Cart />
</Provider>
);
expect(
screen.getByText(/cart/i)
).toBeInTheDocument();
Testing a form
const user = userEvent.setup();
render(<EmployeeForm />);
await user.type(
screen.getByLabelText(/first name/i),
"Ravi"
);
await user.type(
screen.getByLabelText(/email/i),
"ravi@example.com"
);
await user.click(
screen.getByRole("button", { name: /save/i })
);
expect(
await screen.findByText(/employee created/i)
).toBeInTheDocument();
Output
PASS EmployeeForm.test.jsx
✓ submits valid employee details
✓ displays required-field validation
✓ disables save while submitting
✓ displays server validation error
Common mistakes
- Testing component state variables directly.
- Using CSS selectors when an accessible role is available.
- Using getByTestId for everything.
- Not awaiting asynchronous user interactions.
- Making tests depend on exact DOM structure.
Interview questions
- Why React Testing Library?
- getByRole vs getByTestId?
- How do you test async UI?
- How do you test forms?
- How do you test a component connected to Redux?