Vitest in Core
Use the repository harness as the source of truth. Core currently resolves
Vitest 4.1.x from bun.lock; verify the exact version before relying on a newly
introduced API.
Authority and test surface
Read these before changing tests or configuration:
vitest.config.ts — include globs, aliases, Node default environment,
timeouts, mock clearing, setup, and the custom coverage provider.
tests/setup/unit-env.ts — safe env defaults and browser shims.
scripts/verify/unit-tests.mjs — the full unit gate and platform behavior.
docs/ai/rules/testing.md — repository-wide test and CI policy.
.next-docs/01-app/02-guides/testing/vitest.mdx when testing Next.js code.
Do not use bun test; that selects Bun's test runner. Use Vitest through the
committed scripts or bunx vitest.
Commands
# Full CI-equivalent unit suite with Core's coverage provider
bun run test:unit
# Focused file or directory while iterating
bunx vitest run tests/unit/path/to/example.test.ts
# Focused test name
bunx vitest run tests/unit/path/to/example.test.ts -t "expected behavior"
# Watch a focused surface
bunx vitest tests/unit/path/to/example.test.ts
# Structured failure report and targeted reruns
bun run test:unit:feedback
Workflow
- Choose the boundary. Test observable behavior at the smallest stable
public boundary. Prefer pure logic/unit coverage; use Playwright when the
claim depends on a real browser, routing, hydration, or an async Server
Component.
- Place the test in an included path. Match the existing
tests/unit,
packages/api/tests/unit, or packages/auth conventions from
vitest.config.ts; do not invent a disconnected test root.
- Control the environment. The default is
node. Add
// @vitest-environment jsdom only to files that need DOM APIs, and clean up
rendered components and mutated globals.
- Mock boundaries, not the unit's internals. Remember that
vi.mock is
hoisted. Use vi.hoisted for shared mock state, dynamic imports when a module
must load after mocks, and vi.importActual for intentional partial mocks.
- Reset all changed state.
clearMocks: true clears call history but does
not restore globals, timers, dates, env values, or spy implementations. Undo
those changes in hooks.
- Run focused, then full. Iterate on the smallest file/name filter and run
bun run test:unit before handoff.
Core-specific guardrails
- Unit tests must not call live Supabase, Stripe, Resend, Payload, or network
services. Use deterministic fakes at repository boundaries.
- Keep real credentials out of tests. The committed env defaults are
placeholders and intentionally clear the Supabase service-role key.
- Assert behavior and durable contracts, not incidental class strings or
implementation order unless that order is itself the contract.
- Prefer explicit test data builders/helpers over large untyped fixture blobs.
- Avoid
.only; use .skip/.todo only with a documented reason and no hidden
loss of required coverage.
- Core's custom coverage output is useful evidence, but its current
totalScripts: 0 summary is not a line/branch quality signal. Do not claim a
threshold the provider does not measure.
Checklist
Provenance
See references/upstream.md for the reviewed upstream
source, version mismatch decision, license, and refresh workflow.
1---2name: vitest3description: Write, review, filter, mock, and debug Core unit tests with the repository's installed Vitest 4 configuration. Use for tests under Core's Vitest include paths, `vi.mock`/spies/timers, jsdom component tests, coverage output, focused reruns, or unit-test failures. Do not use for browser E2E flows or async Next.js Server Components.4---56# Vitest in Core78Use the repository harness as the source of truth. Core currently resolves9Vitest 4.1.x from `bun.lock`; verify the exact version before relying on a newly10introduced API.1112## Authority and test surface1314Read these before changing tests or configuration:1516- `vitest.config.ts` — include globs, aliases, Node default environment,17 timeouts, mock clearing, setup, and the custom coverage provider.18- `tests/setup/unit-env.ts` — safe env defaults and browser shims.19- `scripts/verify/unit-tests.mjs` — the full unit gate and platform behavior.20- `docs/ai/rules/testing.md` — repository-wide test and CI policy.21- `.next-docs/01-app/02-guides/testing/vitest.mdx` when testing Next.js code.2223Do not use `bun test`; that selects Bun's test runner. Use Vitest through the24committed scripts or `bunx vitest`.2526## Commands2728```bash29# Full CI-equivalent unit suite with Core's coverage provider30bun run test:unit3132# Focused file or directory while iterating33bunx vitest run tests/unit/path/to/example.test.ts3435# Focused test name36bunx vitest run tests/unit/path/to/example.test.ts -t "expected behavior"3738# Watch a focused surface39bunx vitest tests/unit/path/to/example.test.ts4041# Structured failure report and targeted reruns42bun run test:unit:feedback43```4445## Workflow46471. **Choose the boundary.** Test observable behavior at the smallest stable48 public boundary. Prefer pure logic/unit coverage; use Playwright when the49 claim depends on a real browser, routing, hydration, or an async Server50 Component.512. **Place the test in an included path.** Match the existing `tests/unit`,52 `packages/api/tests/unit`, or `packages/auth` conventions from53 `vitest.config.ts`; do not invent a disconnected test root.543. **Control the environment.** The default is `node`. Add55 `// @vitest-environment jsdom` only to files that need DOM APIs, and clean up56 rendered components and mutated globals.574. **Mock boundaries, not the unit's internals.** Remember that `vi.mock` is58 hoisted. Use `vi.hoisted` for shared mock state, dynamic imports when a module59 must load after mocks, and `vi.importActual` for intentional partial mocks.605. **Reset all changed state.** `clearMocks: true` clears call history but does61 not restore globals, timers, dates, env values, or spy implementations. Undo62 those changes in hooks.636. **Run focused, then full.** Iterate on the smallest file/name filter and run64 `bun run test:unit` before handoff.6566## Core-specific guardrails6768- Unit tests must not call live Supabase, Stripe, Resend, Payload, or network69 services. Use deterministic fakes at repository boundaries.70- Keep real credentials out of tests. The committed env defaults are71 placeholders and intentionally clear the Supabase service-role key.72- Assert behavior and durable contracts, not incidental class strings or73 implementation order unless that order is itself the contract.74- Prefer explicit test data builders/helpers over large untyped fixture blobs.75- Avoid `.only`; use `.skip`/`.todo` only with a documented reason and no hidden76 loss of required coverage.77- Core's custom coverage output is useful evidence, but its current78 `totalScripts: 0` summary is not a line/branch quality signal. Do not claim a79 threshold the provider does not measure.8081## Checklist8283- [ ] The test exercises an observable contract at the right test layer.84- [ ] The file is inside a configured include path and uses the correct env.85- [ ] Mocks intercept external boundaries and respect Vitest hoisting.86- [ ] Globals, env, timers, dates, spies, DOM, and module state are isolated.87- [ ] Assertions are deterministic and do not depend on network or test order.88- [ ] Focused tests pass, then `bun run test:unit` passes.89- [ ] Coverage output is described without overstating its current signal.9091## Provenance9293See [references/upstream.md](references/upstream.md) for the reviewed upstream94source, version mismatch decision, license, and refresh workflow.