Testing React Components
Testing what users see and do, not implementation details - React Testing Library, queries, user-event, and mocking patterns.
What it is, in plain English: Testing React components means rendering them in a simulated DOM and asserting what a user would actually see and be able to do -- not checking internal state or implementation details. React Testing Library is the standard tool: it renders components, lets you query the result the way a user would find things (by visible text, label, or role), and simulates real user interactions like clicks and typing.
Testing what the user sees, not how it's built
React Testing Library's core philosophy: the more your tests resemble the way your software is used, the more confidence they give you. Instead of checking a component's internal state directly, you render it and interact with it the way a real user would -- finding buttons by their text, typing into inputs, clicking things.
Setup
// npm install -D @testing-library/react @testing-library/user-event vitest jsdom
// (jsdom simulates a browser DOM in Node.js, where tests actually run)A basic test
import { render, screen } from "@testing-library/react";
import { test, expect } from "vitest";
import Greeting from "./Greeting";
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
test("renders the greeting with the given name", () => {
render(<Greeting name="Alice" />);
// screen.getByText finds an element by its visible text:
expect(screen.getByText("Hello, Alice!")).toBeInTheDocument();
});Simulating user interaction
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
function Counter() {
const [count, setCount] = React.useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
test("increments when clicked", async () => {
const user = userEvent.setup();
render(<Counter />);
expect(screen.getByText("Count: 0")).toBeInTheDocument();
const button = screen.getByRole("button", { name: "Increment" });
await user.click(button); // simulates a REAL click — focus, mousedown, mouseup, click
expect(screen.getByText("Count: 1")).toBeInTheDocument();
});Testing forms
test("submits the form with typed values", async () => {
const user = userEvent.setup();
render(<LoginForm />);
const emailInput = screen.getByLabelText("Email");
await user.type(emailInput, "alice@example.com");
const submitButton = screen.getByRole("button", { name: "Log In" });
await user.click(submitButton);
expect(screen.getByText("Welcome, alice@example.com")).toBeInTheDocument();
});
Try It Yourself (JSX)
Official Sources
- Testing Library — React Testing Library
- Testing Library — Guiding Principles
- Testing Library — About Queries
- Mock Service Worker Documentation
The Codex links only to official documentation. No third-party tutorials.