Vitest Cheatsheet

Configuration

Use this Vitest reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

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',
        },
      },
    ],
  },
})