Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vitest 3.x reference skill covering configuration, test/describe APIs, mocking, coverage, snapshots, and concurrency.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/features-context.md
1---2name: test-context-fixtures3description: Test context, custom fixtures with test.extend4---56# Test Context & Fixtures78## Built-in Context910Every test receives context as first argument:1112```ts13test('context', ({ task, expect, skip }) => {14console.log(task.name) // Test name15expect(1).toBe(1) // Context-bound expect16skip() // Skip test dynamically17})18```1920### Context Properties2122- `task` - Test metadata (name, file, etc.)23- `expect` - Expect bound to this test (important for concurrent tests)24- `skip(condition?, message?)` - Skip the test25- `onTestFinished(fn)` - Cleanup after test26- `onTestFailed(fn)` - Run on failure only2728## Custom Fixtures with test.extend2930Create reusable test utilities:3132```ts33import { test as base } from 'vitest'3435// Define fixture types36interface Fixtures {37db: Database38user: User39}4041// Create extended test42export const test = base.extend<Fixtures>({43// Fixture with setup/teardown44db: async ({}, use) => {45const db = await createDatabase()46await use(db) // Provide to test47await db.close() // Cleanup48},4950// Fixture depending on another fixture51user: async ({ db }, use) => {52const user = await db.createUser({ name: 'Test' })53await use(user)54await db.deleteUser(user.id)55},56})57```5859Using fixtures:6061```ts62test('query user', async ({ db, user }) => {63const found = await db.findUser(user.id)64expect(found).toEqual(user)65})66```6768## Fixture Initialization6970Fixtures only initialize when accessed:7172```ts73const test = base.extend({74expensive: async ({}, use) => {75console.log('initializing') // Only runs if test uses it76await use('value')77},78})7980test('no fixture', () => {}) // expensive not called81test('uses fixture', ({ expensive }) => {}) // expensive called82```8384## Auto Fixtures8586Run fixture for every test:8788```ts89const test = base.extend({90setup: [91async ({}, use) => {92await globalSetup()93await use()94await globalTeardown()95},96{ auto: true } // Always run97],98})99```100101## Scoped Fixtures102103### File Scope104105Initialize once per file:106107```ts108const test = base.extend({109connection: [110async ({}, use) => {111const conn = await connect()112await use(conn)113await conn.close()114},115{ scope: 'file' }116],117})118```119120### Worker Scope121122Initialize once per worker:123124```ts125const test = base.extend({126sharedResource: [127async ({}, use) => {128await use(globalResource)129},130{ scope: 'worker' }131],132})133```134135## Injected Fixtures (from Config)136137Override fixtures per project:138139```ts140// test file141const test = base.extend({142apiUrl: ['/default', { injected: true }],143})144145// vitest.config.ts146defineConfig({147test: {148projects: [149{150test: {151name: 'prod',152provide: { apiUrl: 'https://api.prod.com' },153},154},155],156},157})158```159160## Scoped Values per Suite161162Override fixture for specific suite:163164```ts165const test = base.extend({166environment: 'development',167})168169describe('production tests', () => {170test.scoped({ environment: 'production' })171172test('uses production', ({ environment }) => {173expect(environment).toBe('production')174})175})176177test('uses default', ({ environment }) => {178expect(environment).toBe('development')179})180```181182## Extended Test Hooks183184Type-aware hooks with fixtures:185186```ts187const test = base.extend<{ db: Database }>({188db: async ({}, use) => {189const db = await createDb()190await use(db)191await db.close()192},193})194195// Hooks know about fixtures196test.beforeEach(({ db }) => {197db.seed()198})199200test.afterEach(({ db }) => {201db.clear()202})203```204205## Composing Fixtures206207Extend from another extended test:208209```ts210// base-test.ts211export const test = base.extend<{ db: Database }>({212db: async ({}, use) => { /* ... */ },213})214215// admin-test.ts216import { test as dbTest } from './base-test'217218export const test = dbTest.extend<{ admin: User }>({219admin: async ({ db }, use) => {220const admin = await db.createAdmin()221await use(admin)222},223})224```225226## Key Points227228- Use `{ }` destructuring to access fixtures229- Fixtures are lazy - only initialize when accessed230- Return cleanup function from fixtures231- Use `{ auto: true }` for setup fixtures232- Use `{ scope: 'file' }` for expensive shared resources233- Fixtures compose - extend from extended tests234235<!--236Source references:237- https://vitest.dev/guide/test-context.html238-->239