All skills
antfu avatar

/vitest

@d02c484 official
by Anthony Fuantfu/skills5.9k stars
335

Vitest fast unit testing framework powered by Vite with Jest-compatible API. Use when writing tests, mocking, configuring coverage, or working with test filtering and fixtures.

Use this Skill: https://skilld.dev/gh/antfu/skills/vitest

This session only. Nothing lands on disk.

referencesadvanced-projects.md

≈1.9k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Projects

Run different test configurations in the same Vitest process.

v5 Config Inheritance & Nested Projects

  • Inline projects inherit the root config by default — extends now defaults to true, so root Vite options (plugins, resolve.alias) and test options are inherited. Arrays like setupFiles are appended, not replaced. Opt out with extends: false, or inherit from another file with extends: './vitest.shared.ts'. Projects referenced as config files/directories still don't inherit the root.
  • Referenced config files can declare their own projects — such a config acts as a container providing nested projects named app (unit), app (e2e), etc. In v4 a referenced config's projects field was silently ignored, so audit merged configs that pull one in.
  • Inline projects share the declaring config's Vite server by default (sharedViteServer) — the declaring config runs once, so plugin config hooks no longer run per project. A project gets its own server only when it changes the Vite config (plugins, alias, css, deps.optimizer, root, browser, mode). Set sharedViteServer: false if a plugin must be re-instantiated per project.
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()], // inherited by every inline project (v4 needed extends: true)
  test: {
    projects: [
      { test: { name: 'unit', include: ['**/*.unit.test.ts'] } },
      // a package that declares its own projects becomes a nested container:
      './packages/app/vitest.config.ts', // -> "app (unit)", "app (e2e)", ...
    ],
  },
})

Basic Projects Setup

// vitest.config.ts
defineConfig({
  test: {
    projects: [
      // Glob patterns for config files
      'packages/*',
      
      // Inline config
      {
        test: {
          name: 'unit',
          include: ['tests/unit/**/*.test.ts'],
          environment: 'node',
        },
      },
      {
        test: {
          name: 'integration',
          include: ['tests/integration/**/*.test.ts'],
          environment: 'jsdom',
        },
      },
    ],
  },
})

Monorepo Pattern

defineConfig({
  test: {
    projects: [
      // Each package has its own vitest.config.ts
      'packages/core',
      'packages/cli',
      'packages/utils',
    ],
  },
})

Package config:

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

export default defineConfig({
  test: {
    name: 'core',
    include: ['src/**/*.test.ts'],
    environment: 'node',
  },
})

Different Environments

Run same tests in different environments:

defineConfig({
  test: {
    projects: [
      {
        test: {
          name: 'happy-dom',
          root: './shared-tests',
          environment: 'happy-dom',
          setupFiles: ['./setup.happy-dom.ts'],
        },
      },
      {
        test: {
          name: 'node',
          root: './shared-tests',
          environment: 'node',
          setupFiles: ['./setup.node.ts'],
        },
      },
    ],
  },
})

Browser + Node Projects

defineConfig({
  test: {
    projects: [
      {
        test: {
          name: 'unit',
          include: ['tests/unit/**/*.test.ts'],
          environment: 'node',
        },
      },
      {
        test: {
          name: 'browser',
          include: ['tests/browser/**/*.test.ts'],
          browser: {
            enabled: true,
            name: 'chromium',
            provider: 'playwright',
          },
        },
      },
    ],
  },
})

Shared Configuration

// vitest.shared.ts
export const sharedConfig = {
  testTimeout: 10000,
  setupFiles: ['./tests/setup.ts'],
}

// vitest.config.ts
import { sharedConfig } from './vitest.shared'

defineConfig({
  test: {
    projects: [
      {
        test: {
          ...sharedConfig,
          name: 'unit',
          include: ['tests/unit/**/*.test.ts'],
        },
      },
      {
        test: {
          ...sharedConfig,
          name: 'e2e',
          include: ['tests/e2e/**/*.test.ts'],
        },
      },
    ],
  },
})

Project-Specific Dependencies

Each project can have different dependencies inlined:

defineConfig({
  test: {
    projects: [
      {
        test: {
          name: 'project-a',
          server: {
            deps: {
              inline: ['package-a'],
            },
          },
        },
      },
    ],
  },
})

Running Specific Projects

# Run specific project (v5 adds the -p shorthand)
vitest --project unit
vitest -p integration

# Multiple projects / wildcards
vitest --project unit --project e2e
vitest --project="packages*"

# Exclude a project
vitest --project="!browser"

# Nested projects: --project matches the prefix
vitest -p app                 # every project of the "app" config
vitest -p "app (unit)"        # just one nested project

Providing Values to Projects

Share values from config to tests:

// vitest.config.ts
defineConfig({
  test: {
    projects: [
      {
        test: {
          name: 'staging',
          provide: {
            apiUrl: 'https://staging.api.com',
            debug: true,
          },
        },
      },
      {
        test: {
          name: 'production',
          provide: {
            apiUrl: 'https://api.com',
            debug: false,
          },
        },
      },
    ],
  },
})

// In tests, use inject
import { inject } from 'vitest'

test('uses correct api', () => {
  const url = inject('apiUrl')
  expect(url).toContain('api.com')
})

With Fixtures

const test = base.extend({
  apiUrl: ['/default', { injected: true }],
})

test('uses injected url', ({ apiUrl }) => {
  // apiUrl comes from project's provide config
})

Per-Project Pool & Isolation (v4)

Since the v4 pool rework, isolation, parallelism, and Node CLI options can be set per project:

defineConfig({
  test: {
    projects: [
      {
        test: {
          name: 'unit',
          isolate: false,                 // fast, non-isolated unit tests
          exclude: ['**/*.integration.test.ts'],
        },
      },
      {
        test: {
          name: 'sequential',
          include: ['**/*.sequential.test.ts'],
          fileParallelism: false,         // run these files one at a time
        },
      },
      {
        test: {
          name: 'staging',
          execArgv: ['--env-file=.env.staging'], // per-project Node flags
        },
      },
    ],
  },
})

Global Setup per Project

defineConfig({
  test: {
    projects: [
      {
        test: {
          name: 'with-db',
          globalSetup: ['./tests/db-setup.ts'],
        },
      },
    ],
  },
})

Key Points

  • Projects run in same Vitest process (replaces the removed workspace option)
  • Each project can have different environment, pool, isolation, and config
  • Use glob patterns for monorepo packages
  • Run specific projects with --project (supports wildcards and ! exclusion)
  • Use provide to inject config values into tests
  • Inline projects inherit root config by default (v5 extends: true); set extends: false to opt out
  • Referenced configs that declare projects provide nested projects (name (child))
<!-- Source references: - https://vitest.dev/guide/projects.html -->

Source: SKILL.md on GitHub

No alerts3d5 checks · Risk SAFE
  • Gen Agent Trust Hub3d

    The skill provides comprehensive documentation and reference material for the Vitest testing framework. It covers configuration, CLI usage, mocking, coverage, and advanced features like type testing and benchmarking. No security issues were detected; the instructions follow standard development and testing practices.

  • Socket3d

    No alerts

  • Snyk3d

    Risk: LOW · No issues

  • Runlayer7mo

    1/18 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at d02c484. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 4 days ago
Other metadata
metadata
{
  "author": "Anthony Fu",
  "version": "2026.9.25",
  "source": "Generated from https://github.com/vitest-dev/vitest, scripts located at https://github.com/antfu/skills"
}

README badge

README badge for antfu/skills/vitest

Vitest is a Jest-compatible unit testing framework powered by Vite, with native ESM, TypeScript, and JSX support. Use it for writing tests with smart watch mode, mocking, fixtures, coverage reporting, and snapshot testing in projects already using Vite.

Generated from the current SKILL.md.

Is Vitest a drop-in replacement for Jest?
Mostly. Vitest provides a Jest-compatible API and can run most Jest test suites without modification, but it uses Vite's transformation pipeline instead of Jest's, so some edge cases may differ.
Does Vitest require configuration?
No. It natively supports ESM, TypeScript, and JSX out of the box and shares Vite's config, transformers, and resolvers, so many projects need minimal or no additional setup.
What coverage providers does Vitest support?
Vitest includes built-in coverage via V8 or Istanbul providers.
Can I run tests in parallel?
Yes. Vitest uses multi-threaded workers for parallel test execution and supports sharding across multiple processes.
What test environments are available?
Vitest supports node, jsdom, happy-dom, and custom environments.

Generated from the current SKILL.md. These answers refresh after source changes.