Vite + React + Vitest: a simple test setup you can copy in 10 minutes

# webdev# react# typescript# testing
Vite + React + Vitest: a simple test setup you can copy in 10 minutesHappy

A beginner-friendly, practical setup for testing React components in a Vite + TypeScript project with Vitest.

If you use Vite + React + TypeScript, the fastest way to add tests is Vitest.

In this post, I will show a clean setup you can copy.

Why this stack?

  • Vite: fast dev server
  • Vitest: test runner that feels like Jest, but faster in Vite projects
  • React Testing Library: test from user perspective

This setup works well with pnpm and small-to-medium frontend apps.


1) Install packages

pnpm add -D vitest jsdom @testing-library/react @testing-library/jest-dom @testing-library/user-event
Enter fullscreen mode Exit fullscreen mode

2) Update vite.config.ts

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

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

What this does:

  • jsdom gives a browser-like environment
  • setupFiles runs once before tests
  • globals: true lets you use describe, it, expect without importing every time

3) Create src/test/setup.ts

import '@testing-library/jest-dom'
Enter fullscreen mode Exit fullscreen mode

This adds helpers like toBeInTheDocument().


4) Add scripts to package.json

{
  "scripts": {
    "test": "vitest run",
    "test:watch": "vitest",
    "test:ui": "vitest --ui"
  }
}
Enter fullscreen mode Exit fullscreen mode

Use:

  • pnpm test for CI
  • pnpm test:watch while coding

5) Example component test

src/components/Counter.tsx

import { useState } from 'react'

export function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount((c) => c + 1)}>Increment</button>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

src/components/Counter.test.tsx

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

describe('Counter', () => {
  it('increments count when button is clicked', async () => {
    render(<Counter />)

    await userEvent.click(screen.getByRole('button', { name: /increment/i }))

    expect(screen.getByText('Count: 1')).toBeInTheDocument()
  })
})
Enter fullscreen mode Exit fullscreen mode

This test checks real behavior, not internal state details.


Common beginner mistakes

  1. Using node environment for React tests (use jsdom)
  2. Forgetting @testing-library/jest-dom setup
  3. Testing implementation details instead of visible UI behavior

Final tip

Start with one test per component for the core user action.
You do not need 100 tests on day one.
Small, stable tests are better than many fragile tests.

If you want, next step is adding coverage and running Vitest in CI.