vitest-dev
Scannednpx machina-cli add skill BjornMelin/dev-skills/vitest-dev --openclawvitest-dev
A Claude Code skill for producing high-signal, low-flake, fast Vitest suites (TypeScript + Next.js 16) and for shaping Vitest configuration for optimal local DX and CI throughput.
Core outcomes
- Correctness first: tests encode business behavior (not implementation details).
- Deterministic: no network, no clocks, no global leakage, no order dependencies.
- Fast:
- fast feedback locally (watch mode + smart filtering)
- scalable CI (parallel workers + sharding + cache + machine-readable reports)
- Actionable failures: failures localize root cause quickly.
Default operating procedure
When asked to add or improve tests:
- Map the unit under test
- Identify public API / observable behavior
- Identify boundaries: I/O, time, randomness, network, database, filesystem, env, global state
- Choose the lightest test that gives confidence
- Pure unit test (no framework/runtime) → preferred
- Component test in
jsdom(React) when DOM behavior is essential - Integration test in Node when multiple modules must cooperate
- Browser Mode (real browser) only when DOM fidelity matters (layout/visuals, real events)
- Design a minimal test matrix
- happy path(s)
- boundary conditions
- error paths
- key invariants (idempotency, caching semantics, auth gates, etc.)
- Implement tests
- arrange/act/assert clarity
- isolate side effects and restore mocks
- prefer stable assertions (
toHaveTextContent, role-based queries, etc.)
- Run locally and fix
- run smallest scope first (single file / name filtering)
- Harden
- remove flakiness vectors (timers, concurrency, random, hidden network)
- ensure tests pass in “run mode” (CI-like)
- Optimize
- reduce expensive setup per test file
- tune Vitest config: pool, isolate, workers, cache, deps optimization, sharding
- Deliver
- include config + scripts changes needed for local + CI
- include README notes if non-obvious
Naming and structure conventions
- Place tests next to code for discoverability:
src/foo.ts→src/foo.test.tssrc/components/Button.tsx→src/components/Button.test.tsx
- Use
__tests__for framework-driven routes when colocation is awkward (Next example uses this convention). - Prefer
describe('<unit>')with focusedit('does X when Y').
Vitest execution modes and what to target
- Local development:
vitest(watch mode by default when TTY is detected). - CI:
vitest run(forces a single run and is non-interactive).
From the Vitest CLI guide, Vitest defaults to watch mode when process.stdout.isTTY is true and falls back to run mode otherwise, while vitest run always runs once. (See: https://vitest.dev/guide/cli)
Configuration baseline
Recommended “default” config goals
- Use TypeScript path aliases (monorepos and Next apps frequently need this).
- Choose an environment per project:
nodefor backend/unit testsjsdom(orhappy-dom) for React component tests
- Keep setup lightweight.
Pool choice (speed vs compatibility)
Vitest runs test files using a pool (forks, threads, vmThreads, vmForks). By default (Vitest v4 docs) it uses forks. threads can be faster but may break libraries that use native bindings; forks uses child_process and supports process APIs like process.chdir(). (See: https://vitest.dev/config/pool)
Rule of thumb:
- Prefer
threadsfor “pure JS/TS” unit tests. - Use
forksif you use:- native addons (e.g. Prisma, bcrypt, canvas)
process.*APIs that are not available in threads
- Avoid VM pools unless you have measured wins and understand the tradeoffs.
Isolation (speed vs global leakage)
test.isolate defaults to true. Disabling can improve performance when tests don’t rely on side effects (often true for Node-only units). (See: https://vitest.dev/config/isolate)
Rule of thumb:
- Keep
isolate: truefor frontend/component tests (jsdom) and any suite that touches global state. - Consider
isolate: falsefor Node-only pure units after you have strong isolation discipline.
File-level and test-level parallelism
test.fileParallelismdefault istrue. Setting it tofalseforces single-worker execution by overridingmaxWorkersto 1. (See: https://vitest.dev/config/fileparallelism)test.maxWorkersdefaults to:- all available parallelism when watch is disabled
- half when watch is enabled
It also accepts a percentage string like
"50%". (See: https://vitest.dev/config/maxworkers)
test.maxConcurrencycontrols how manytest.concurrenttests can run simultaneously, default5. (See: https://vitest.dev/config/maxconcurrency)
Cache (CI win)
Vitest caching is enabled by default and uses node_modules/.vite/vitest. (See: https://vitest.dev/config/cache)
For CI, persist this directory between runs (per branch key) for significant speedups.
Next.js 16 integration defaults
Use Next’s recommended baseline:
- Install (TypeScript):
vitest,@vitejs/plugin-react,jsdom,@testing-library/react,@testing-library/dom,vite-tsconfig-paths. - Configure
test.environment = 'jsdom'with the React + tsconfigPaths plugins.
(See: https://nextjs.org/docs/app/guides/testing/vitest)
Important limitation noted by Next.js: Vitest currently does not support async Server Components; for async components, use E2E tests instead. (See the same Next.js guide above.)
Mocking & test doubles discipline
Preferred hierarchy (from most realistic to most isolated)
- Real pure functions (no mocking)
- In-memory fakes (e.g., fake repo with a Map)
- Contract-driven stubs (minimal, stable)
- Spies (
vi.spyOn) for verifying interactions - Module mocks (
vi.mock) only when necessary
Mock reset policy
- Default: clean up per test file:
afterEach(() => vi.restoreAllMocks())
- If you use global stubs (env/globals), clean them up in
afterEachtoo.
Timers
Use fake timers to avoid slow sleeps. Vitest’s docs show using vi.useFakeTimers() with vi.runAllTimers() / vi.advanceTimersByTime() to speed time-based code. (See: https://vitest.dev/guide/mocking/timers)
Advanced note: if you configure fakeTimers.toFake to include nextTick, it is not supported with --pool=forks because Node’s child_process uses process.nextTick internally and can hang; it is supported with --pool=threads. (See: https://vitest.dev/config/faketimers)
CI reporting and sharding
Reporters
- Use
junitto export JUnit XML (for most CI systems). (See: https://vitest.dev/guide/reporters) - In GitHub Actions, Vitest automatically adds
github-actionsreporter whenGITHUB_ACTIONS === 'true'if default reporters are used; if you override reporters, add it explicitly. (See: https://vitest.dev/guide/reporters)
Sharding (multi-machine parallel CI)
Use --shard with the blob reporter and merge at the end. Vitest recommends the blob reporter for sharded runs and provides --merge-reports. (See: https://vitest.dev/guide/reporters)
Using test projects for multi-environment suites
Use test.projects to run multiple configurations in one process (monorepos or mixed environments). Vitest notes the older “workspace” name is deprecated in favor of projects. (See: https://vitest.dev/guide/projects)
Patterns:
- project A:
environment: 'node',pool: 'threads',isolate: false - project B:
environment: 'jsdom',isolate: true
Deliverables this skill produces
When invoked, this skill can generate or update:
- Vitest config(s):
vitest.config.ts, multi-project configs, CI overrides - Test setup:
setupTests.ts, test utils, mocks - Tests: unit, integration, React component tests, type tests
- CI scripts: sharding + merging reports, coverage, flake detection
- Performance tuning recommendations with measurable steps
Output quality gates
Before finalizing, ensure:
- No test uses real timers (
setTimeoutwaits), real network, or real clock time without explicit control. - All mocks/stubs are restored.
- Tests pass with:
vitestvitest run
- On CI, tests emit machine-readable artifacts (JUnit, JSON, blob merge) if requested.
- Coverage settings match team goals and don’t create “coverage theater”.
Where to look for authoritative details (official docs)
- Config reference: https://vitest.dev/config
- CLI: https://vitest.dev/guide/cli
- Improving performance: https://vitest.dev/guide/improving-performance
- Profiling performance: https://vitest.dev/guide/profiling-test-performance
- Parallelism: https://vitest.dev/guide/parallelism
- Mocking: https://vitest.dev/guide/mocking
- Reporters: https://vitest.dev/guide/reporters
- Coverage: https://vitest.dev/guide/coverage
- Next.js 16 + Vitest: https://nextjs.org/docs/app/guides/testing/vitest
Source
git clone https://github.com/BjornMelin/dev-skills/blob/main/skills/vitest-dev/SKILL.mdView on GitHub Overview
A Claude Code skill that builds high-signal, low-flake Vitest suites for TypeScript + Next.js 16, optimized for fast local feedback and scalable CI. It emphasizes correctness, determinism, and actionable failures to drive confident code changes.
How This Skill Works
Start by mapping the unit under test and identifying boundaries (I/O, time, randomness, network, env). Choose the lightest test type that provides confidence (pure unit, jsdom React component tests, or Node integration tests), then implement with clear arrange/act/assert and isolated side effects. Tune Vitest config for speed and reliability (pool/worker settings, caching, and optional sharding) and ensure tests run in both local watch mode and CI run mode; rely on test.isolate defaults and only disable if you’ve proven no global leakage.
When to Use It
- You need fast, deterministic test feedback for a TypeScript + Next.js project in local development.
- Setting up or refining Vitest configuration for a monorepo to accelerate CI throughput with parallel workers and caching.
- You want to minimize flakiness vectors like timers, concurrency, hidden network calls, or global state leakage.
- Testing React components where DOM behavior matters (jsdom/happy-dom) or performing focused integration tests in Node.
- You want to align test structure with conventions ( colocated tests, describe/it patterns) and optimize for maintainability.
Quick Start
- Step 1: Map the unit under test and place tests alongside code (e.g., src/foo.ts → src/foo.test.ts).
- Step 2: Start with a minimal test (pure unit) and add a component or integration test only if needed.
- Step 3: Run locally (vitest in watch mode) and in CI (vitest run); adjust pool and cache settings for speed and reliability.
Best Practices
- Map the unit under test by public API and observable behavior first.
- Prefer the lightest valid test type (pure unit > component > integration) before browser-mode tests.
- Design a minimal test matrix: happy paths, boundaries, error paths, and invariants.
- Write arrange/act/assert tests with isolated side effects and stable assertions.
- Harden tests by removing flakiness vectors and aligning CI-like run mode with local run.
Example Use Cases
- Test a pure TS utility function with deterministic outputs and no external dependencies.
- Test a React component in jsdom to validate toHaveTextContent and role-based queries.
- Create a Node integration test to ensure multiple modules cooperate without network I/O.
- Configure browser-mode testing only when real DOM fidelity affects layout or events.
- Configure vitest.config.ts to enable proper path aliases, environment, and caching for fast CI runs.