testing
/testing
Apply when writing .test.ts or .test-d.ts files. Esposter's Vitest conventions and the decision of what earns a test at all. The values a test writes are the test-values skill's.
- Author
- Esposter ↗
- Repository
- Esposter ↗
- Licence
- Apache-2.0
- Last repository change
- 26.10.2026
Assessment and security
- Files in this package
- 28
- Scripts
- 0
- HTML comments
- 0
- URLs in SKILL.md
- 0
No signals detected. Repository changed on 26.10.2026, without references to retired models or APIs.
Apache-2.0, otwarta: można używać i zmieniać, z zachowaniem licencji i informacji o zmianach.
What it does and when to use it
Apply when writing .test.ts or .test-d.ts files. Esposter's Vitest conventions and the decision of what earns a test at all. The values a test writes are the test-values skill's.
Original author description
Apply when writing .test.ts or .test-d.ts files. Esposter's Vitest conventions and the decision of what earns a test at all. The values a test writes are the test-values skill's.
How it works
- Settled — do not re-propose
- Deep dives
- Structure
- Test data — the test-values skill
- Assertions
- Mocking
- Reactive Effects and Timers
- Running Tests
- What to Test
SKILL.md preview
---
name: testing
description: Apply when writing .test.ts or .test-d.ts files. Esposter's Vitest conventions and the decision of what earns a test at all. The values a test writes are the test-values skill's.
---
# Testing Conventions (Vitest)
## Settled — do not re-propose
- **A lint rule for constant scope** — an AST selector cannot ask the two whole-Program questions the exceptions turn on (a helper file, a binding read from a hoisted `vi.mock` factory or an awaited initialiser); `scripts/src/workspace/constantScope.test.ts` is the enforcer and asks both.
- **`isolate: false`, per project or globally.** The packages that survive it come out level, and the apparent gain belongs to the ones that fail under it for the reason isolation exists (`references/running-the-suite.md`).
- **A count target for tests** — a cap or quota per package measures how many tests exist, not whether a regression is caught. The keep test in `references/what-earns-a-test.md` is the only gate on a test.
## Deep dives
Structure and helpers:
- `references/what-earns-a-test.md` — when deciding whether a subject earns a test at all, and which one.
- `references/test-placement.md` — when deciding which file a test goes in, or whether two checks over one directory are one suite.
- `references/suite-titles.md` — when a `describe`'s subject has no function reference, or its export is not camelCase.
- `references/module-scope.md` — when a test declares anything outside its `describe`, or `constantScope.test.ts` reports one.
- `references/case-tables.md` — when a test runs over a table of cases.
- `references/test-helper-files.md` — when a helper, fixture or hook block is shared between suites: one function per file, `constants.test.ts`, `setup*` fixtures.
- `references/wrapper-suites.md` — when two suites match modulo constants, or a suite tests a thin wrapper.
- `references/type-tests.md` — when writing a `.test-d.ts`, or asserting a `void` return.
- `references/router-test-setup.md` — when writing a tRPC router test: callers, mock sessions, seeded rows, naming.
Assertions and waiting:
- `references/assertions.md` — when writing a test's `expect` calls: the matcher, how much of the value, a void return, a call's arguments.
- `references/error-assertions.md` — when filling in the inline snapshot a thrown or rejected error is asserted with.
- `references/polling.md` — when a test waits for something to happen.
- `references/timers-and-hand-resolved-promises.md` — when a test fakes timers, pins the clock, or holds a call in flight.
- `references/awaiting-a-double.md` — when a test proves a caller awaits its side effect, orders two overlapping calls, or reads what a tRPC call caused.
Doubles:
- `references/module-mocks.md` — when reaching for `vi.mock` or a spy: whether the behaviour needs a double, and which seam.
- `references/colocated-mocks.md` — when a module is mocked in several suites, writing a `vi.mock` factory, or mocking `db` or a `Proxy` export.
- `references/client-trpc-calls.md` — when code under test calls tRPC from the client: `setupMswTrpc` and `trpcMsw`, never a mocked client.
- `references/mock-cleanup.md` — when choosing a mock's cleanup hook, queuing once-values, or stubbing a global or env var.
- `references/fabricated-ids.md` — when a mock returns a persisted entity, or a new foreign key turns a suite red.
Environment and running:
- `references/test-environment.md` — when a test needs a DOM, a layout engine or the nuxt runtime, or tests a composable with lifecycle hooks.
- `references/nuxt-environment-and-mounting.md` — when a test mounts a component: a routed link, a mount attached to the body, a dispatched event.
- `references/mounted-stores.md` — when a test seeds a store a mounted component reads, room-scoped stores included, or a suite reaches for its own Pinia.
- `references/platform-and-bundle-tests.md` — when a suite is skipped on some hosts, or its output depends on the host.
- `references/bundle-size.md` — when a size snapshot fails or moves, or a new library package needs one.
- `references/running-the-suite.md` — when narrowing a run with `-t` or `-u`, or reading a failure only the full parallel run produces.
- `references/timeouts.md` — when a test, suite or config sets a timeout, or a test fails with `Test timed out`: the measurement and the ladder that decide whether a timeout is earned at all.
- `references/regression-proof.md` — when a regression test is about to be kept, and its fix is reverted for the end-of-work run.
## Structure
- **`test` not `it`** — always `test(...)`.
- **A test lives beside what it tests** — `Foo.ts` → `Foo.test.ts`, never folded into a nearby suite or moved to the module it scans (`references/test-placement.md`).
- **A file snapshot lives beside what it holds, as `<name>.snapshot.<extension>`** — a component's rendered HTML beside the component, a parsed map beside the map — never in a `__snapshots__` folder. The suffix is what the formatter and the JSON lint skip, so the file stays as its test wrote it.
- **`describe(functionRef, …)`**, flat — a string only when no reference exists, naming the file's export; `describe.each` over a matrix is not a group (`references/suite-titles.md`).
- **Nothing but imports, pure helpers and hoisted mocks lives at module scope** — every constant is a `const` inside the `describe` (`references/module-scope.md`).
- **`test.each` for a table of cases, never a loop around `test`** (`vitest/prefer-each`), titled with `%s` (`references/case-tables.md`).
- **`expect.hasAssertions()`** — top of every test body.
- **Assertions after all assignments** — `expect` calls follow that phase's operations and locals, after a blank line.
- **A `void` return is never assigned or asserted at runtime** — `await fn();` bare, or `resolves.toBeUndefined()` (`references/assertions.md`).
- **Reuse utilities, and prefix factories `create*`** — look for an existing helper beside the code under test first; builders are `createRow`, never `make*`.
## Test data — the `test-values` skill
Every literal, id, date, path and fixture a test writes is that skill's: the canonical values, dates computed from the epoch, the three checks a string literal passes, and the shared-data shapes. This page assumes them.
## Assertions
- **`toStrictEqual` always**, exact counts, and `arrayContaining` never for an argv or an ordered sequence (`references/assertions.md`).
- **Never fragment-match a deterministic output** — the whole value with `.toBe(...)` or an inline snapshot, a runtime value the test holds interpolated in, never an element sampled from a knowable sequence (`references/assertions.md`).
- **Once + args → `toHaveBeenCalledExactlyOnceWith(...)`**, never the jest-extended once-with matcher (`references/assertions.md`).
- **`takeOne(arr, index)`** for `arr[index]` under `noUncheckedIndexedAccess` — not universal, prefer `find` when more idiomatic. **`assert.exists(value)`** narrows nullables and fails fast instead of `?? []`. Cloning: the `typescript` skill (`references/cloning.md`).
- **No unnecessary destructure** — for plain objects, read a property directly when used once. Stores and composables keep the destructure ordering of the `pinia` skill's `references/consuming-a-store.md`, unchanged in tests.
- **`toThrowErrorMatchingInlineSnapshot(...)` is the only accepted error assertion**, sync and async (`vitest/no-restricted-matchers`); `not.toThrow()` is not an error assertion and stays, as how a best-effort function proves it swallows what it should (`references/error-assertions.md`).
## Mocking
- **Mock the smallest seam that makes the behaviour reachable**, never re-declare a mock another file owns, and drive real state before faking it (`references/module-mocks.md`).
- **The cleanup hook follows how the mock was created**, never habit — the wrong one leaks an implementation or a queued once-value into the next test (`references/mock-cleanup.md`).
- **`vi.fn()` always takes its signature** — `vi.fn<(input: CreateEmojiInput) => Promise<void>>()`, the production input and return types imported rather than restated. A bare `vi.fn()` infers `unknown` parameters, so destructuring a recorded call is an implicit-`any` lint error and `mockResolvedValue` accepts anything.
## Reactive Effects and Timers
- **A `watch` callback and a re-render run on Vue's scheduler, never synchronously** — `await nextTick()` flushes them after the write that queued them; `flushPromises()` from `@vue/test-utils` when the callback itself awaits. With nothing queued, neither is written.
- **Fake timers, and any promise the test resolves by hand, follow `references/timers-and-hand-resolved-promises.md`** — one `vi.useFakeTimers({ now: 0 })` in `beforeEach` with an unconditional restore in `afterEach`, `toFake` narrowed rather than widened, and `Promise.withResolvers` instead of a `let` closed over by an executor.
- **Await the real completion signal, never a poll** — the repo-wide ban is `openspec/specs/architecture/no-polling/design.md`, and the test forms are `references/polling.md`.
## Running Tests
- **The touched tests are a session's one check, run in the background once at the end** — the rest are CI's (the `running-checks` skill).
- **Never run the full suite locally** — `pnpm test <paths> --run` over what the change touched (`references/running-the-suite.md`).
- **`-t "name"` is not a scope, and `-u` gets the narrowest path list** — read the snapshot diff before committing (`references/running-the-suite.md`).
## What to Test
**Every test earns its line or it is deleted** — the keep test in `references/what-earns-a-test.md` decides it.
- **A regression test is proven to fail before it is kept** — the end-of-work run that shows it is `references/regression-proof.md`.
- What never earns a line, and the subjects already decided: `references/what-earns-a-test.md`.
Files in this package (28)
- SKILL.md 10 KB
- references/assertions.md 4 KB
- references/awaiting-a-double.md 4 KB
- references/bundle-size.md 4 KB
- references/case-tables.md 1 KB
- references/client-trpc-calls.md 4 KB
- references/colocated-mocks.md 7 KB
- references/error-assertions.md 3 KB
- references/fabricated-ids.md 2 KB
- references/mock-cleanup.md 3 KB
- references/module-mocks.md 1 KB
- references/module-scope.md 2 KB
- references/mounted-stores.md 3 KB
- references/nuxt-environment-and-mounting.md 4 KB
- references/platform-and-bundle-tests.md 3 KB
- references/polling.md 1 KB
- references/regression-proof.md 1 KB
- references/router-test-setup.md 5 KB
- references/running-the-suite.md 6 KB
- references/suite-titles.md 2 KB
- references/test-environment.md 4 KB
- references/test-helper-files.md 4 KB
- references/test-placement.md 1 KB
- references/timeouts.md 3 KB
- references/timers-and-hand-resolved-promises.md 5 KB
- references/type-tests.md 1 KB
- references/what-earns-a-test.md 7 KB
- references/wrapper-suites.md 2 KB
Versions
| Repository | Score | Licence |
|---|---|---|
| This page · Esposter/Esposter | 90 | Apache-2.0 |
| iuliandita/skills | 100 | MIT |
| wrongstack/wrongstack | 100 | MIT |
| langwatch/langwatch | 100 | Apache-2.0 |
| mcouthon/agents | 100 | MIT |
| nteract/nteract | 100 | BSD-3-Clause |
| kettleofketchup/DraftForge | 100 | GPL-3.0 |
| skillberry-ai/cap-evolve | 100 | Apache-2.0 |
| TheBeardedBearSAS/claude-craft | 100 | MIT |
Database snapshot: 13.11.2026 · package version 0f6d494a4356 (SHA-256 digest of the entire package)
Downloads in the last 30 days: 0 · ranking
Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.
Similar skills
- 90typescript
Apply when writing any TypeScript in this project. Esposter's TypeScript conventions. - 90test-values
Apply when writing or reviewing any literal, fixture, id, date, path or helper argument in a .test.ts, .test-d.ts or .bench.ts file. Esposter's test values — the literals, ids, dates, paths and fixtures a test writes, and the shared data they are drawn from. - 92conventions-testing
Apply when writing or reviewing tests. - 100vitest
Vitest conventions for assertions, snapshots, and fixtures. Use when writing, reviewing, or fixing Vitest tests. - 100vitest-test-creator
Create vitest test creator operations. Auto-activating skill for Test Automation. Triggers on: vitest test creator, vitest test creator Part of the Test Automation skill category. Use when writing or running tests. Trigger with phrases like "vitest test creator", "vitest creator", "vitest". - 100react-testing
Test React components with RTL and Jest/Vitest. Use when writing React component tests with React Testing Library, Jest, or Vitest.