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.

referencesfeatures-context.md

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

Test Context & Fixtures

Built-in Context

Every test receives context as its first argument:

test('context', ({ task, expect, skip, signal, annotate }) => {
  console.log(task.name)        // Test metadata (readonly)
  expect(1).toBe(1)             // Expect bound to this test
  skip(condition, 'reason')     // Skip dynamically
})

Properties:

  • task — test metadata (name, file, etc.)
  • expect — expect bound to this test (required for concurrent snapshot tests)
  • skip(condition?, message?) — skip the test
  • signal (3.2+) — AbortSignal aborted on timeout/cancel/bail
  • annotate(message, type?, attachment?) (3.2+) — attach reporter annotations
  • onTestFinished(fn) / onTestFailed(fn) — per-test cleanup/handlers
  • bench (v5) — benchmark fixture (only in *.bench.ts files)

Custom Fixtures — Builder Pattern (4.1+, recommended)

.extend(name, options?, fixture) infers types automatically. Use onCleanup for teardown:

import { test as baseTest } from 'vitest'

export const test = baseTest
  // Plain value — type inferred as { port: number; host: string }
  .extend('config', { port: 3000, host: 'localhost' })
  // Function fixture — can read previously defined fixtures
  .extend('server', async ({ config }, { onCleanup }) => {
    const server = await startServer(config)
    onCleanup(() => server.close()) // runs after test/scope ends
    return server
  })

test('uses server', ({ config, server }) => {
  expect(server.url).toContain(String(config.port))
})

onCleanup can be called once per fixture. For multiple resources, split into separate fixtures.

Fixture Options

const test = baseTest
  .extend('metrics', { auto: true }, () => new Metrics())       // runs for every test
  .extend('config', { scope: 'worker' }, () => loadConfig())    // once per worker
  .extend('db', { scope: 'file' }, async ({ config }, { onCleanup }) => {
    const db = await createDatabase(config)
    onCleanup(() => db.close())
    return db
  })
  .extend('baseUrl', { injected: true }, () => 'http://localhost:3000') // overridable via config

Object Syntax (Playwright-compatible)

Uses the use() callback; types must be declared manually:

const test = baseTest.extend<{ page: Page; baseUrl: string }>({
  page: async ({}, use) => {
    const page = await browser.newPage()
    await use(page)        // test runs here
    await page.close()     // cleanup after
  },
  baseUrl: 'http://localhost:3000',
})

Tuple form sets options: fixture: [async ({}, use) => {…}, { scope: 'file' }].

Fixture Scopes (3.2+)

Scope Lifetime Can access
test (default) each test worker + file + test fixtures + built-in context
file once per file worker + file fixtures
worker once per worker process only worker fixtures

Only test-scoped fixtures can access the built-in context (task, expect, …). In file/worker fixtures use expect.getState().testPath for the file path. By default every file is its own worker, so file and worker behave the same unless isolation is disabled.

Injected Fixtures (per-project values)

// fixtures.ts
const test = baseTest.extend('url', { injected: true }, '/default')

// vitest.config.ts — provide per project
defineConfig({
  test: {
    projects: [
      { test: { name: 'prod', provide: { url: 'https://prod' } } },
    ],
  },
})

Read raw provided values without fixtures via import { inject } from 'vitest'.

Overriding Fixtures — test.override (4.1+)

test.override replaces fixture values for a suite and its children (replaces the deprecated test.scoped):

describe('production', () => {
  test
    .override('config', { port: 8080, host: 'api.example.com' })
    .override('debug', false)        // chainable

  test('uses prod config', ({ server }) => {
    expect(server.url).toBe('http://api.example.com:8080')
  })
})

// Function override (reads other fixtures) with cleanup
test.override('db', async ({ config }, { onCleanup }) => {
  const db = await createTestDatabase(config)
  onCleanup(() => db.drop())
  return db
})

You cannot introduce new fixtures or change scope/auto via override; use test.extend for new fixtures.

Composing & Hooks

Extend an already-extended test, and use type-aware hooks on the extended test:

import { test as dbTest } from './db-test'

export const test = dbTest.extend('user', ({ db }) => db.createUser())

test.beforeEach(({ db }) => db.seed())            // sees fixtures
test.beforeAll(({ db }) => db.migrate())          // file/worker fixtures only (4.1+)
test.aroundAll(async (run, { db }) => db.tx(run))

Key Points

  • Prefer the builder pattern — types are inferred, cleanup via onCleanup
  • Fixtures are lazy — only initialized when destructured
  • Always destructure { db } (not context.db)
  • Use { scope: 'file' | 'worker' } for expensive shared resources
  • Use test.override (not test.scoped) to vary fixture values per suite
  • Use { injected: true } + project provide for per-project values
<!-- Source references: - https://vitest.dev/guide/test-context.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.