agentleFS
revealui-studiorevealui-studio/revskills/skills/vitest-testing/SKILL.md

vitest-testing

Skill2 starsChanged 40 days agoMITView on GitHub

Vitest testing patterns for production TypeScript projects. Use when writing tests, fixing test failures, configuring coverage, mocking modules, debugging flaky tests, or setting up Vitest in a monorepo. Covers Vitest 3+, vi.mock, vi.fn, React Testing Library, PGlite in-memory PostgreSQL, pool forks, maxWorkers, and hookTimeout.

We split this skill into the rules it gives an agent

16 rules. 0 are common, 4 are distinctive, and 12 are very specific to this project.

  • 0

    Common

    Most of the 3 edited versions we read keep these.

  • 4

    Distinctive

    This author's own choices. Worth a look.

  • 12

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Test directories: __tests__/ for grouped tests

    line 17
  2. Very specific:

    Test utilities: shared test package or test/helpers.ts

    line 19
  3. Very specific:

    Important: When using Biome, always mock classes with class syntax inside vi.mock() factories.

    line 58
  4. Very specific:

    Use pool: 'forks' for process isolation (prevents shared state leaks)

    line 114
  5. Very specific:

    Don't use jest.fn() — use vi.fn() (Vitest, not Jest)

    line 141
  6. Distinctive:

    Don't mock everything — prefer real implementations, mock only external services

    line 142
  7. Very specific:

    Don't use function() in vi.mock() factories — Biome converts to arrows, breaking new

    line 143
  8. Very specific:

    Don't share state between tests — use beforeEach to reset

    line 144
  9. Very specific:

    Don't use threads pool with native modules — use forks

    line 145
  10. Very specific:

    Don't set hookTimeout too low when using PGlite

    line 146
  11. Distinctive:

    Check for shared mutable state between tests

    line 150
  12. Very specific:

    Check for timing issues (setTimeout, setInterval)

    line 151
  13. Distinctive:

    Check for port conflicts (parallel workers binding same port)

    line 152
  14. Distinctive:

    Check for PGlite startup timeout under load

    line 153
  15. Very specific:

    Run with --reporter=verbose to see individual test timings

    line 154
  16. Very specific:

    Run single test: vitest run src/path/to/file.test.ts

    line 155

“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Vitest Testing Patterns

Test File Conventions

  • Unit/integration tests: *.test.ts or *.test.tsx (co-located with source)
  • Test directories: __tests__/ for grouped tests
  • Fixtures: __fixtures__/ or test/fixtures/
  • Test utilities: shared test package or test/helpers.ts

Writing Tests

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';

describe('MyFunction', () => {
  it('should handle the happy path', () => {
    const result = myFunction('valid-input');
    expect(result).toEqual({ status: 'ok' });
  });

  it('should throw on invalid input', () => {
    expect(() => myFunction('')).toThrow('Input required');
  });
});

Mocking

// Mock a module
vi.mock('./database', () => ({
  query: vi.fn().mockResolvedValue([{ id: 1 }]),
}));

// Mock a class (Biome-safe — use class syntax, not function)
vi.mock('./service', () => ({
  MyService: class {
    async getData() { return []; }
  },
}));

// Spy on a method
const spy = vi.spyOn(object, 'method');
spy.mockReturnValue('mocked');

Important: When using Biome, always mock classes with class syntax inside vi.mock() factories. Biome converts function() to arrow functions, which breaks new.

Async Testing

it('should fetch data', async () => {
  const result = await fetchData();
  expect(result).toHaveLength(3);
});

it('should reject on error', async () => {
  await expect(fetchBadData()).rejects.toThrow('Not found');
});

PGlite (In-Memory PostgreSQL)

import { PGlite } from '@electric-sql/pglite';

let db: PGlite;

beforeEach(async () => {
  db = new PGlite(); // in-memory, fresh each test
  await db.exec(schema);
});

afterEach(async () => {
  await db.close();
});

Config for PGlite: PGlite startup can take 3-5s under load. Set hookTimeout: 30000 in vitest.config.ts:

export default defineConfig({
  test: {
    hookTimeout: 30000,
  },
});

Monorepo Testing

// vitest.config.ts — per-package config
export default defineConfig({
  test: {
    pool: 'forks',       // process isolation (not threads)
    maxWorkers: 2,       // prevent OOM in CI
    hookTimeout: 30000,  // PGlite startup time
    include: ['src/**/*.test.{ts,tsx}'],
  },
});
  • Use pool: 'forks' for process isolation (prevents shared state leaks)
  • Cap maxWorkers to prevent fork explosion (turbo concurrency x workers = total processes)
  • Disable test caching in turbo ("cache": false in turbo.json test task) to prevent stale results

Coverage

// vitest.config.ts
export default defineConfig({
  test: {
    coverage: {
      provider: 'v8',
      reporter: ['text', 'lcov'],
      exclude: ['**/*.test.ts', '**/__fixtures__/**'],
      thresholds: {
        statements: 80,
        branches: 75,
        functions: 80,
        lines: 80,
      },
    },
  },
});

Common Mistakes to Avoid

  1. Don't use jest.fn() — use vi.fn() (Vitest, not Jest)
  2. Don't mock everything — prefer real implementations, mock only external services
  3. Don't use function() in vi.mock() factories — Biome converts to arrows, breaking new
  4. Don't share state between tests — use beforeEach to reset
  5. Don't use threads pool with native modules — use forks
  6. Don't set hookTimeout too low when using PGlite

Debugging Flaky Tests

  1. Check for shared mutable state between tests
  2. Check for timing issues (setTimeout, setInterval)
  3. Check for port conflicts (parallel workers binding same port)
  4. Check for PGlite startup timeout under load
  5. Run with --reporter=verbose to see individual test timings
  6. Run single test: vitest run src/path/to/file.test.ts

Skill by RevealUI Studio — the agentic business runtime.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.