← Workflows

阅读中文版本

Set Up React Testing Library with Vitest

Configure React Testing Library with Vite and Vitest for fast component testing covering installation and test setup.

beginner~20 minreacttestingvitesttddfrontend

Objective

Configure a React project with Vitest and React Testing Library, write a component test that verifies rendering and interaction, and run it successfully with coverage reporting.

Environment

  • Node.js 20+ with pnpm (or npm)
  • Existing Vite + React project
  • Terminal with shell access (bash/zsh/PowerShell)

Steps

1. Install testing dependencies

Add vitest, @testing-library/react, @testing-library/jest-dom, @testing-library/user-event, and jsdom as dev dependencies

Expected state: package.json includes vitest ^2.x, @testing-library/react ^16.x, @testing-library/jest-dom ^6.x in devDependencies

2. Configure Vitest

Add a test section to vite.config.ts (or create vitest.config.ts) with the React plugin and jsdom environment

Expected state: vite.config.ts has a test block: { environment: 'jsdom', globals: true, setupFiles: './src/test/setup.ts' }

3. Create test setup file

Create src/test/setup.ts to import '@testing-library/jest-dom/vitest' for extended matchers like toBeInTheDocument()

Expected state: src/test/setup.ts exists with the jest-dom import

4. Write your first component test

Create a test file that imports a simple React component, renders it, and asserts it appears in the document

Expected state: File src/components/__tests__/Counter.test.tsx exists and passes when vitest runs

5. Run tests

Execute vitest in run mode, then with --coverage

Expected state: Test output shows 1 passed, 1 total. Coverage report shows component coverage above 80%.

Decision points

Do you use TypeScript?

  • Yes
  • No

Yes — add @vitest/coverage-v8 and configure 'types: ["vitest/globals"]' in tsconfig.json

Do you need component snapshot testing?

  • Yes, add @snaplet/snapshot or vitest snapshot
  • No

No for new projects — prefer user-observable assertions over snapshots for maintainability.

Expected outcome

A working Vitest + RTL setup where `pnpm test` runs component tests and they pass correctly.

Verification

Run `pnpm test` in your project root. Expected: PASS with 1+ test case and coverage report.

Cleanup

Remove any test scaffold files you don't need. The configuration is additive and can remain.

Workflow Overview

You will set up React Testing Library (RTL) with Vitest in a Vite-based React project. The process takes about 20 minutes and requires only npm/pnpm commands and a few config file edits.

Step 1: Install Dependencies

pnpm add -D vitest @testing-library/react @testing-library/jest-dom \
  @testing-library/user-event jsdom @vitest/coverage-v8

Verify in package.json that all packages appear in devDependencies.

Step 2: Configure Vitest

Update vite.config.ts:

/// <reference types="vitest/config" />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: './src/test/setup.ts',
    css: true,
  },
});

Step 3: Create Setup File

Create src/test/setup.ts:

import '@testing-library/jest-dom/vitest';

This gives you matchers like toBeInTheDocument(), toHaveTextContent(), toBeEnabled().

Step 4: Write Your First Test

Create src/components/Counter.tsx:

import { useState } from 'react';
export function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>Count: {count}</button>;
}

Test it in src/components/__tests__/Counter.test.tsx:

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

test('increments on click', async () => {
  const user = userEvent.setup();
  render(<Counter />);
  const button = screen.getByRole('button');
  expect(button).toHaveTextContent('Count: 0');
  await user.click(button);
  expect(button).toHaveTextContent('Count: 1');
});

Step 5: Run and Verify

pnpm test --run
# or with coverage:
pnpm test -- --coverage

Expected output:

Test Files  1 passed (1)
      Tests  1 passed (1)
   Start at  15:42:01
   Duration  1.23s

Troubleshooting

Cause Fix
"document is not defined" Add environment: 'jsdom' to test config
Cannot find module '@testing-library/react' Re-run pnpm install and check devDependencies
toHaveTextContent is not a function Add setupFiles and confirm @testing-library/jest-dom/vitest import
describe is not defined Set globals: true or import from vitest