Files
stack/packages/mosaic/framework/skills/vitest/references/advanced-projects.md
T
fargo 1a822493ba format: apply repo prettier (3.8.1) to the folded skills tree
963 markdown files reformatted with the repository's pinned prettier so
pnpm format:check covers the folded tree like every other repo file.

The formatter's embedded-language pass also normalized code fences
(TS semicolons, closed HTML tags in examples, lowercased CSS hex colors,
one renumbered list that skipped an index). Alphanumeric token deltas vs
the fold commit were audited file-by-file; all are formatter-equivalent
markup normalizations plus the four sanitized skills.
2026-08-19 14:37:17 -05:00

4.9 KiB

name, description
name description
projects-workspaces Multi-project configuration for monorepos and different test types

Projects

Run different test configurations in the same Vitest process.

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
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:

// 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
});

Project Isolation

Each project runs in its own thread pool by default:

defineConfig({
  test: {
    projects: [
      {
        test: {
          name: 'isolated',
          isolate: true, // Full isolation
          pool: 'forks',
        },
      },
    ],
  },
});

Global Setup per Project

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