How to Set Up Vitest with TypeScript in a Vite Project

Testing is often skipped in the early stages of a project, but once components grow and logic gets complicated, having a test suite becomes essential. Setting up Vitest with TypeScript in a Vite-powered project is supposed to be easy. However, some combinations of dependencies, configuration files, and tooling quirks make the process feel more confusing than it should be. The goal here is to create a clean, working setup for unit and component tests using Vitest, TypeScript, and Vite, while avoiding common configuration errors that slow things down.

Install Required Packages

Start by installing the packages necessary for running tests. Vitest comes with most of what you need, but TypeScript support, mocking, and React testing may need additional packages.

Use this command:

npm install -D vitest @vitest/ui @vitest/coverage-v8 jsdom happy-dom

If the project uses React, include testing libraries too:

npm install -D @testing-library/react @testing-library/jest-dom

This setup allows for testing React components in a simulated browser-like environment using jsdom or happy-dom. The difference between them depends on performance and compatibility. For most projects, jsdom is the safer choice.

Configure vite.config.ts

Make sure the Vite config file is using the defineConfig helper. Add a test block in the configuration to define how Vitest should behave.

Here’s a complete example:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: './src/setupTests.ts',
    include: ['src/**/*.{test,spec}.{ts,tsx}'],
  },
})

A few important points here:

  • globals: true allows using describe, it, and expect without importing them manually.
  • environment: 'jsdom' simulates a DOM, which is important for UI tests.
  • setupFiles is optional but useful if you’re adding global test utilities like jest-dom.

Create Setup File

If you are using React Testing Library or adding global matchers, a setup file is helpful. Create src/setupTests.ts and include:

import '@testing-library/jest-dom'

This makes matchers like toBeInTheDocument() available in your tests.

Update tsconfig.json

TypeScript sometimes needs help resolving Vitest’s types. In the tsconfig.json, make sure the types array includes vitest:

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "Node",
    "esModuleInterop": true,
    "jsx": "react-jsx",
    "types": ["vitest"]
  },
  "include": ["src"]
}

This avoids errors like “Cannot find name ‘describe'” or “Cannot find name ‘expect'” when running or writing tests.

Write a Sample Test

Having a working test early confirms everything is set up correctly. Create a new file, for example src/components/Button.test.tsx:

import { render, screen } from '@testing-library/react'
import { describe, it, expect } from 'vitest'
import Button from './Button'

describe('Button', () => {
  it('renders with correct label', () => {
    render(<Button label="Click Me" />)
    expect(screen.getByText('Click Me')).toBeInTheDocument()
  })
})

This basic test checks that a button with the expected label is rendered. It’s a great starting point before diving into more complex logic.

Use UI Mode (Optional)

Vitest includes a UI mode that makes debugging easier. Run the following command:

npx vitest --ui

This opens a web interface where you can run and re-run tests visually, see errors and logs, and view test coverage if enabled.

Add Scripts to package.json

It helps to have shortcuts for running tests. Add these scripts:

"scripts": {
  "test": "vitest",
  "test:ui": "vitest --ui",
  "test:watch": "vitest --watch"
}

This allows running tests with npm run test or opening the UI with npm run test:ui.

File Structure Example

Below is a sample project structure that keeps everything organized:

Folder / FilePurpose
vite.config.tsVite and Vitest configuration
tsconfig.jsonTypeScript configuration
src/setupTests.tsGlobal test setup
src/components/React components
src/components/*.test.tsxComponent test files

Use with Coverage

For code coverage, add this to the test section of vite.config.ts:

coverage: {
  reporter: ['text', 'html'],
}

Then run:

npx vitest run --coverage

This gives a terminal summary and a full HTML report of which lines were tested.

Common Errors

Here are some common mistakes and how to fix them:

  • No defineConfig error – Usually happens if you’re using an old version of Vite or vite.config.ts is incorrectly written. Make sure the file is valid and Vite is up to date.
  • DOM errors in non-jsdom environment – Confirm that the environment is set to jsdom.
  • Test file not found – Ensure test filenames end with .test.ts, .spec.ts, .test.tsx, etc., and match the pattern in vite.config.ts.

Conclusion

Setting up Vitest with TypeScript in a Vite project doesn’t have to be difficult, but it does require careful alignment between tools. By configuring Vite properly, aligning the TypeScript setup, and writing a test early, the entire process becomes easier to manage. This structure works well for growing projects, especially when adding new features that depend on components behaving predictably. Once the environment is in place, writing useful unit tests becomes much faster and far more reliable — and there’s no better time to add that test than right after fixing a bug or finishing a new feature.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top