Vitest Cheatsheet

Plugins

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

How Vitest Uses Vite Plugins

Vitest runs on top of Vite, so any Vite plugin works inside the test run. Plugins are declared in the top-level plugins array of vite.config.ts / vitest.config.ts.

import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
import tsconfigPaths from 'vite-tsconfig-paths'

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

Common Plugins for Testing

@vitejs/plugin-react / @vitejs/plugin-vue

Required for JSX/TSX transformation in component tests.

npm install -D @vitejs/plugin-react
import react from '@vitejs/plugin-react'
plugins: [react()]

For Solid, Svelte, etc.:

npm install -D vite-plugin-solid
npm install -D @sveltejs/vite-plugin-svelte

vite-tsconfig-paths

Resolves TypeScript path aliases (@/components/...) without duplicating them in Vite config.

npm install -D vite-tsconfig-paths
import tsconfigPaths from 'vite-tsconfig-paths'
plugins: [tsconfigPaths()]

@vitest/ui

Interactive test runner in the browser with test tree, source, coverage overlay.

npm install -D @vitest/ui
vitest --ui
# opens http://localhost:51204/__vitest__/
// No plugin config needed — enabled via CLI flag

@vitest/coverage-v8 / @vitest/coverage-istanbul

Code coverage providers:

npm install -D @vitest/coverage-v8
# or
npm install -D @vitest/coverage-istanbul
test: {
  coverage: { provider: 'v8' }
}

Browser Mode (@vitest/browser-playwright)

Runs tests inside a real browser via Playwright or WebdriverIO. Vitest 4 splits providers into packages (@vitest/browser-playwright, @vitest/browser-webdriverio, @vitest/browser-preview) and replaces the removed browser.name with browser.instances:

npm install -D @vitest/browser-playwright playwright
npx playwright install chromium
import { playwright } from '@vitest/browser-playwright'

test: {
  browser: {
    enabled: true,
    provider: playwright(),
    headless: true,
    instances: [{ browser: 'chromium' }],
  }
}

unplugin-auto-import

Auto-import Vitest globals (like describe, it, expect) without explicit imports:

npm install -D unplugin-auto-import
import AutoImport from 'unplugin-auto-import/vite'

plugins: [
  AutoImport({
    imports: ['vitest'],
    dts: './src/auto-imports.d.ts',
  }),
]

Now you can write tests without import { describe, it, expect } from 'vitest'.

vite-plugin-checker

Type-check and lint in parallel with tests using vite-plugin-checker:

npm install -D vite-plugin-checker
import checker from 'vite-plugin-checker'

plugins: [
  checker({
    typescript: true,
    eslint: { lintCommand: 'eslint "./src/**/*.{ts,tsx}"' },
  }),
]

In test mode, checker runs in the background — type errors appear in the terminal alongside test output.

@storybook/addon-vitest

Run Storybook stories as Vitest tests (Storybook 9+; supersedes @storybook/experimental-addon-test and the old experimental plugin):

npx storybook add @storybook/addon-vitest
import { storybookTest } from '@storybook/addon-vitest/vitest-plugin'

plugins: [storybookTest({ configDir: '.storybook' })]
// Button.stories.ts — plays run as vitest tests automatically
export const Primary = {
  args: { label: 'Click me' },
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement)
    await userEvent.click(canvas.getByRole('button'))
    expect(canvas.getByText('clicked')).toBeVisible()
  },
}

vite-plugin-istanbul

Adds Istanbul instrumentation at the Vite transform level (alternative to the coverage provider approach):

npm install -D vite-plugin-istanbul
import istanbul from 'vite-plugin-istanbul'

plugins: [
  istanbul({
    include: 'src/*',
    exclude: ['node_modules', 'test/'],
    extension: ['.js', '.ts', '.vue'],
    requireEnv: true, // only instrument when VITE_COVERAGE=true
  }),
]

vite-plugin-mock (MSW Alternative)

Simple in-process request mocking via Vite plugin (not a Service Worker):

npm install -D vite-plugin-mock
import { viteMockServe } from 'vite-plugin-mock'

plugins: [
  viteMockServe({
    mockPath: 'mock',     // folder with mock files
    enable: true,
  }),
]

Writing a Custom Vitest Plugin

Vitest plugins are Vite plugins with optional configureVitest / vitestConfigSchema extensions.

// my-vitest-plugin.ts
import type { Plugin } from 'vite'

export function myVitestPlugin(): Plugin {
  return {
    name: 'my-vitest-plugin',

    // Standard Vite hooks — run during test transform
    transform(code, id) {
      if (id.endsWith('.test.ts')) {
        // transform test files
        return code
      }
    },

    // Vitest-specific hook (Vite plugin context)
    configureServer(server) {
      // access the Vite dev server
    },
  }
}

Vitest-Specific Reporter Plugin

import type { Reporter } from 'vitest'

export class MyReporter implements Reporter {
  onInit(ctx: Vitest) {
    console.log('Tests starting...')
  }

  onTaskUpdate(packs) {
    for (const [id, result] of packs) {
      if (result?.state === 'fail') {
        console.error(`FAILED: ${id}`)
      }
    }
  }

  onFinished(files, errors) {
    console.log(`Done. Files: ${files.length}`)
  }
}
// vitest.config.ts
import { MyReporter } from './my-reporter'

export default defineConfig({
  test: {
    reporters: [new MyReporter()],
  },
})

Plugin Execution Order

Plugins execute in order. Use enforce: 'pre' or enforce: 'post' to control position:

{
  name: 'run-first',
  enforce: 'pre',
  transform(code) { /* ... */ }
}

Environment Plugin (Custom Environment)

// my-env.ts
import type { Environment } from 'vitest'

export default <Environment>{
  name: 'my-env',
  transformMode: 'ssr',
  async setup() {
    // setup global APIs
    return {
      teardown() {
        // cleanup
      },
    }
  },
}
// vitest.config.ts
export default defineConfig({
  test: {
    environment: './my-env.ts',
  },
})