React

Testing Library: the five tests you need

Five tests cover a React component with Testing Library: render by role, interaction, async wait, error state and form validation.

Key points

  • Tests query by role, not by class name or DOM order.
  • userEvent simulates real browser behaviour; fireEvent does not.
  • Five tests cover render, interaction, async, error and validation; beyond that they duplicate.

Five tests are enough for a React component: that it renders, that it answers a click, that it waits for data, that it shows the error and that it rejects an empty field.

The base rule

Testing Library, released under the MIT licence, queries the DOM the way a person would: by role, by label, by visible text. When a test cannot find a button by role, the component is often the inaccessible part, not the test.

The test that works as a model

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

test("invia l'email digitata", async () => {
  render();
  await userEvent.type(screen.getByLabelText("Email"), "[email protected]");
  await userEvent.click(screen.getByRole("button", { name: "Accedi" }));
  expect(onSubmit).toHaveBeenCalledWith({ email: "[email protected]" });
});

The test types with userEvent, which reproduces real events, and checks the call rather than the HTML: the internal markup can change without breaking the test.

The five tests

  • Render: getByRole finds the heading and the button; a failure means a missing role or label.
  • Interaction: a click changes the visible text, checked with findByText.
  • Async: a stubbed response arrives and the test awaits it, without setTimeout.
  • Error: the component throws and the error boundary shows the expected message.
  • Validation: submitting an empty form skips the callback and shows the message.

Installation

npm i -D vitest jsdom @testing-library/react @testing-library/user-event
npx vitest run

Vitest and jsdom are MIT, like Testing Library: no external service, and the tests run locally and in CI with the same command.

Live records in the catalogue

Three components worth their first tests today: input, multistep-form and call-to-action-cta. To browse by category start from 111,985 components.

The limitation

These tests do not tell you whether the component is fast, nor whether the layout holds on mobile: jsdom applies no CSS, computes no layout and measures no pixels. A green form test can coexist with a button another element covers on the real page.

Where to continue

The accessibility checklist is in accessible React components; how to read the docs is in React documentation; the library picture is in what React is; the measured comparison of React libraries is in React libraries 2026.

Frequently asked questions

How many tests does a component need?

Five, usually: render, interaction, async, error and validation. Beyond that you test details a refactor changes.

fireEvent or userEvent?

userEvent. It reproduces the real browser event sequence, while fireEvent fires one event and skips focus and keyboard.

Can I test CSS class names?

No, and it does not pay. Class names change with refactors; check visible text, roles and ARIA attributes.

Do these tests need a real browser?

For logic and interaction no, jsdom is enough. For layout, CSS and screenshots you need a browser, with Playwright or similar.

Is Testing Library free for commercial use?

Yes. It ships under the MIT licence, which allows commercial use and modification while keeping the copyright notice.