Vitest Cheatsheet

Configuration

Use this Vitest reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Config File Locations (checked in order)

  1. vitest.config.ts / .js / .mts / .mjs (highest priority)
  2. vite.config.ts with a test block (via /// <reference types="vitest" />)

There is no JSON config — Vitest config is always a JS/TS module.

Full Config Reference

// vitest.config.ts
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],

  test: {
    // --- File Discovery ---
    include: ['src/**/*.{test,spec}.{ts,tsx,js,jsx}'],
    exclude: ['node_modules', 'dist', 'e2e/**', '**/*.d.ts'],

    // --- Environment ---
    environment: 'node',         // 'jsdom' | 'happy-dom' | 'edge-runtime'
    environmentOptions: {
      jsdom: { url: 'http://localhost' },
    },

    // --- Globals ---
    globals: true,               // inject describe/it/expect globally

    // --- Setup ---
    setupFiles: ['./src/test/setup.ts'],
    globalSetup: './src/test/globalSetup.ts',

    // --- Timeouts ---
    testTimeout: 5_000,          // ms per test (default 5000)
    hookTimeout: 10_000,         // ms per hook (default 10000)
    teardownTimeout: 10_000,

    // --- Retry & Bail ---
    retry: 0,                    // retry flaky tests N times
    bail: 0,                     // stop after N failures (0 = run all)

    // --- Reporters ---
    reporters: ['verbose'],      // 'default' | 'verbose' | 'dot' | 'json' | 'tap' | 'junit'
    outputFile: {
      json: './test-results/results.json',
      junit: './test-results/junit.xml',
    },

    // --- Coverage ---
    coverage: {
      provider: 'v8',
      reporter: ['text', 'html', 'lcov'],
      reportsDirectory: './coverage',
      include: ['src/**/*.{ts,tsx}'],
      exclude: ['src/**/*.test.*', 'src/test/**'],
      thresholds: { lines: 80, functions: 80, branches: 70, statements: 80 },
    },

    // --- Mock Behavior ---
    clearMocks: false,           // .mockClear() before each test
    mockReset: false,            // .mockReset() before each test (Jest calls this resetMocks)
    restoreMocks: false,         // .mockRestore() before each test
    unstubEnvs: false,
    unstubGlobals: false,

    // --- Snapshots ---
    snapshotFormat: {            // pretty-format options
      printBasicPrototype: false,
    },
    resolveSnapshotPath: (testPath, ext) => testPath + ext,
    // update snapshots via the CLI: vitest -u (there is no updateSnapshot key)

    // --- Concurrency ---
    pool: 'threads',             // 'threads' | 'forks' | 'vmThreads' | 'vmForks'
    poolOptions: {
      threads: {
        singleThread: false,
        isolate: true,
        useAtomics: false,
      },
      forks: {
        singleFork: false,
        isolate: true,
      },
    },
    maxWorkers: '50%',           // number or percentage of CPUs
    minWorkers: 1,
    fileParallelism: true,       // run test files in parallel

    // --- Isolation ---
    isolate: true,               // fresh module registry per file
    sequence: {
      shuffle: false,            // randomize test order
      seed: 42,                  // seed for shuffle
      concurrent: false,
      hooks: 'stack',            // 'stack' | 'list' | 'parallel'
    },

    // --- Watch ---
    forceRerunTriggers: ['**/package.json/**', '**/vite.config.*'],

    // --- Shard (CI parallelism) ---
    shard: null,                 // set via CLI: --shard=1/4

    // --- TypeCheck ---
    typecheck: {
      enabled: false,
      checker: 'tsc',            // 'tsc' | 'vue-tsc'
      include: ['**/*.test-d.ts'],
      tsconfig: './tsconfig.json',
    },

    // --- Browser Mode (Vitest 4: instances, not name) ---
    browser: {
      enabled: false,
      provider: playwright(),    // import { playwright } from '@vitest/browser-playwright'
      headless: true,
      instances: [{ browser: 'chromium' }],
    },

    // --- Benchmarks ---
    benchmark: {
      include: ['**/*.bench.ts'],
      reporters: ['default'],
    },

    // --- Deps ---
    deps: {
      optimizer: {
        ssr: { enabled: true },
        web: { enabled: true },
      },
      interopDefault: true,
      moduleDirectories: ['node_modules'],
    },

    // --- Alias (mirrors vite resolve.alias) ---
    // Prefer setting at top-level resolve.alias
  },

  resolve: {
    alias: {
      '@': '/src',
    },
  },
})

Environment Per File (Docblock)

// @vitest-environment jsdom
import { describe, it, expect } from 'vitest'
// this file runs in jsdom regardless of global config

Inline Test Options

// vitest.config.ts
export default defineConfig({
  test: {
    // Per-test options via the second argument:
    // it('slow', { timeout: 10_000 }, fn)
  },
})

Pool Options: When to Use Each

PoolUse When
threads (default)Most projects; fastest
forksNeed process.env isolation; native add-ons
vmThreadsStrict module isolation between tests in same worker
vmForksStrict isolation + native modules

Shard Configuration (CI Parallelism)

# Run 4 parallel CI jobs, each running a quarter of tests:
vitest run --shard=1/4
vitest run --shard=2/4
vitest run --shard=3/4
vitest run --shard=4/4
# GitHub Actions matrix example
strategy:
  matrix:
    shard: [1, 2, 3, 4]
steps:
  - run: vitest run --shard=${{ matrix.shard }}/4

Extending Config for Multiple Environments

// vitest.config.ts
import { defineConfig, mergeConfig } from 'vitest/config'
import base from './vitest.base.config'

export default mergeConfig(base, defineConfig({
  test: {
    environment: 'jsdom',
    include: ['src/components/**/*.test.tsx'],
  },
}))

TypeScript Paths Alias

// vitest.config.ts
import { defineConfig } from 'vitest/config'
import tsconfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
  plugins: [tsconfigPaths()],
  test: { globals: true },
})

Projects (Monorepo) Config

test.projects replaces the old workspace file (vitest.workspace.ts / defineWorkspace — deprecated in 3.2, removed in Vitest 4):

// vitest.config.ts
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    projects: [
      'packages/*/vitest.config.ts',
      {
        test: {
          name: 'shared-utils',
          root: './packages/utils',
          environment: 'node',
        },
      },
    ],
  },
})