Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.3 KiB
4.3 KiB
name, description
| name | description |
|---|---|
| test-context-fixtures | Test context, custom fixtures with test.extend |
Test Context & Fixtures
Built-in Context
Every test receives context as first argument:
test('context', ({ task, expect, skip }) => {
console.log(task.name) // Test name
expect(1).toBe(1) // Context-bound expect
skip() // Skip test dynamically
})
Context Properties
task- Test metadata (name, file, etc.)expect- Expect bound to this test (important for concurrent tests)skip(condition?, message?)- Skip the testonTestFinished(fn)- Cleanup after testonTestFailed(fn)- Run on failure only
Custom Fixtures with test.extend
Create reusable test utilities:
import { test as base } from 'vitest'
// Define fixture types
interface Fixtures {
db: Database
user: User
}
// Create extended test
export const test = base.extend<Fixtures>({
// Fixture with setup/teardown
db: async ({}, use) => {
const db = await createDatabase()
await use(db) // Provide to test
await db.close() // Cleanup
},
// Fixture depending on another fixture
user: async ({ db }, use) => {
const user = await db.createUser({ name: 'Test' })
await use(user)
await db.deleteUser(user.id)
},
})
Using fixtures:
test('query user', async ({ db, user }) => {
const found = await db.findUser(user.id)
expect(found).toEqual(user)
})
Fixture Initialization
Fixtures only initialize when accessed:
const test = base.extend({
expensive: async ({}, use) => {
console.log('initializing') // Only runs if test uses it
await use('value')
},
})
test('no fixture', () => {}) // expensive not called
test('uses fixture', ({ expensive }) => {}) // expensive called
Auto Fixtures
Run fixture for every test:
const test = base.extend({
setup: [
async ({}, use) => {
await globalSetup()
await use()
await globalTeardown()
},
{ auto: true } // Always run
],
})
Scoped Fixtures
File Scope
Initialize once per file:
const test = base.extend({
connection: [
async ({}, use) => {
const conn = await connect()
await use(conn)
await conn.close()
},
{ scope: 'file' }
],
})
Worker Scope
Initialize once per worker:
const test = base.extend({
sharedResource: [
async ({}, use) => {
await use(globalResource)
},
{ scope: 'worker' }
],
})
Injected Fixtures (from Config)
Override fixtures per project:
// test file
const test = base.extend({
apiUrl: ['/default', { injected: true }],
})
// vitest.config.ts
defineConfig({
test: {
projects: [
{
test: {
name: 'prod',
provide: { apiUrl: 'https://api.prod.com' },
},
},
],
},
})
Scoped Values per Suite
Override fixture for specific suite:
const test = base.extend({
environment: 'development',
})
describe('production tests', () => {
test.scoped({ environment: 'production' })
test('uses production', ({ environment }) => {
expect(environment).toBe('production')
})
})
test('uses default', ({ environment }) => {
expect(environment).toBe('development')
})
Extended Test Hooks
Type-aware hooks with fixtures:
const test = base.extend<{ db: Database }>({
db: async ({}, use) => {
const db = await createDb()
await use(db)
await db.close()
},
})
// Hooks know about fixtures
test.beforeEach(({ db }) => {
db.seed()
})
test.afterEach(({ db }) => {
db.clear()
})
Composing Fixtures
Extend from another extended test:
// base-test.ts
export const test = base.extend<{ db: Database }>({
db: async ({}, use) => { /* ... */ },
})
// admin-test.ts
import { test as dbTest } from './base-test'
export const test = dbTest.extend<{ admin: User }>({
admin: async ({ db }, use) => {
const admin = await db.createAdmin()
await use(admin)
},
})
Key Points
- Use
{ }destructuring to access fixtures - Fixtures are lazy - only initialize when accessed
- Return cleanup function from fixtures
- Use
{ auto: true }for setup fixtures - Use
{ scope: 'file' }for expensive shared resources - Fixtures compose - extend from extended tests