Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

React Component Tests with Vitest

React Component Tests with Vitest

~15 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

EXACTLY as block 11 of the Symfony course explained WHY tests build confidence, the SAME principle applies to React – Vitest (the test framework MATCHING Vite) AND React Testing Library are TODAY's standard.

Installing the tools

npm install --save-dev vitest @testing-library/react @testing-library/jest-dom jsdom

Configuring Vite for tests

vite.config.ts (excerpt)
export default defineConfig({
  plugins: [react()],
  test: {
    environment: 'jsdom',
    setupFiles: './src/test-setup.ts',
  },
});
src/test-setup.ts
import '@testing-library/jest-dom';

environment: 'jsdom' simulates a browser DOM in Node.js, WITHOUT starting a REAL browser – FAST enough to run HUNDREDS of tests in seconds.

The first component test

src/components/CreateProjectForm.test.tsx
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import CreateProjectForm from './CreateProjectForm';

function renderWithQueryClient(ui: React.ReactElement) {
  const queryClient = new QueryClient();

  return render(
    <QueryClientProvider client={queryClient}>{ui}</QueryClientProvider>,
  );
}

describe('CreateProjectForm', () => {
  it('shows an input field and a button', () => {
    renderWithQueryClient(<CreateProjectForm />);

    expect(screen.getByPlaceholderText('Project name')).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /create project/i })).toBeInTheDocument();
  });
});

renderWithQueryClient WRAPS the component WITH the SAME QueryClientProvider from chapter 73 – CreateProjectForm uses useCreateProject (chapter 78) INTERNALLY, which would ABORT with a runtime error WITHOUT a provider.

Simulating user interaction

it('updates the input field while typing', async () => {
  const user = userEvent.setup();
  renderWithQueryClient(<CreateProjectForm />);

  const input = screen.getByPlaceholderText('Project name');
  await user.type(input, 'New Project');

  expect(input).toHaveValue('New Project');
});

@testing-library/user-event simulates REAL keyboard/mouse events (keystroke BY keystroke) instead of fireEvent's SYNTHETIC events – CLOSER to actual user behavior, EXACTLY THE philosophy behind Testing Library: "test HOW a user uses the application".

Running the tests

npm run test

Tipp: getByRole instead of getByTestId is DELIBERATELY Testing Library's RECOMMENDED choice – IT SIMULTANEOUSLY checks THAT the component is ACCESSIBLE (screen readers use the SAME ARIA roles), A USEFUL side effect of good tests.