Skip to content

Component Testing

A component test mounts a single UI component (button, form, card) or a small cluster of them and asserts on what the user sees and does — text, roles, interactions — without booting the whole application, real network or a real browser.

It sits between unit and integration: real rendering, but a scoped surface. In the testing trophy it is part of the wide middle layer.

Use it for

  • Interactive components: forms, dropdowns, modals, tables
  • Conditional rendering, empty/loading/error states
  • Accessibility basics: roles, labels, keyboard interaction

Avoid it when

  • The component has no behaviour (pure presentational markup) → a visual regression or snapshot is enough
  • You need routing, data fetching and several pages → that is end-to-end
Tool Ecosystem Notes
React Testing Library React Query by role/text, user-centric
Testing Library (Vue/Svelte/Solid/Angular) Multi Same guiding principles
Storybook Multi Develop and catalog components in isolation
Storybook Test Runner Multi Run stories as tests
Chromatic / Percy Multi Visual + interaction review of stories
Vitest browser mode Multi Real browser, in-process
Cypress Component Testing Multi Component tests in a real browser
Playwright CT React/Vue/Svelte Experimental component testing
Vue Test Utils, Angular TestBed per-framework Official mounting helpers
Terminal window
npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Counter } from './Counter';
it('increments when the button is clicked', async () => {
render(<Counter />);
await userEvent.click(screen.getByRole('button', { name: /increment/i }));
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
  • Query like a user. Prefer getByRole, getByLabelText over test IDs and CSS classes — the queries themselves enforce accessibility.
  • Assert what the user sees, not component internals or state variables.
  • Drive interaction with userEvent, not by dispatching raw events.
  • Cover the states: empty, loading, error, disabled.
  • Do not snapshot the whole tree. Large snapshots break on every styling change and nobody reads them.

Self-assessment quiz

Pick one answer per question, then press Check answers.

  1. Where does component testing sit relative to unit and integration testing?
  2. Which query style does Testing Library recommend?
  3. What is Storybook primarily used for?
  4. Why is a whole-tree snapshot an anti-pattern?