--- name: projects-workspaces description: Multi-project configuration for monorepos and different test types --- # Projects Run different test configurations in the same Vitest process. ## Basic Projects Setup ```ts // 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 ```ts defineConfig({ test: { projects: [ // Each package has its own vitest.config.ts 'packages/core', 'packages/cli', 'packages/utils', ], }, }) ``` Package config: ```ts // 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: ```ts 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 ```ts 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 ```ts // 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: ```ts defineConfig({ test: { projects: [ { test: { name: 'project-a', server: { deps: { inline: ['package-a'], }, }, }, }, ], }, }) ``` ## Running Specific Projects ```bash # Run specific project vitest --project unit vitest --project integration # Multiple projects vitest --project unit --project e2e # Exclude project vitest --project.ignore browser ``` ## Providing Values to Projects Share values from config to tests: ```ts // 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 ```ts const test = base.extend({ apiUrl: ['/default', { injected: true }], }) test('uses injected url', ({ apiUrl }) => { // apiUrl comes from project's provide config }) ``` ## Project Isolation Each project runs in its own thread pool by default: ```ts defineConfig({ test: { projects: [ { test: { name: 'isolated', isolate: true, // Full isolation pool: 'forks', }, }, ], }, }) ``` ## Global Setup per Project ```ts defineConfig({ test: { projects: [ { test: { name: 'with-db', globalSetup: ['./tests/db-setup.ts'], }, }, ], }, }) ``` ## Key Points - Projects run in same Vitest process - Each project can have different environment, config - Use glob patterns for monorepo packages - Run specific projects with `--project` flag - Use `provide` to inject config values into tests - Projects inherit from root config unless overridden