skills/unit-test-best-practices/SKILL.md
Vitest unit test authoring for this repo — setup, mocking, API handler testing, and common pitfalls for non-hook code. Use when the user asks to add, update, fix, or review unit tests for utilities, components, API handlers, or scripts. Do NOT use for React hook tests — load unit-test-hook-best-practices instead.
npx skillsauth add bkinsey808/songshare-effect unit-test-best-practicesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Requires: file-read, terminal (test runner). No network access needed.
Depends on: unit-test-hook-best-practices/SKILL.md
— load when the target under test is a React hook (use*.ts / use*.tsx).
docs/unit-test-best-practices.md — load on demand for deep dives into mocking patterns, API handler setup, or advanced tradeoffs.
Preconditions:
docs/ai/rules.md for repo-wide constraints before proceeding.Clarifying questions:
// Arrange,
// Act, // Assert) and only omit a section when the linked docs
explicitly allow it; follow the mocking order below.foo.test.ts — let
me know if a different file is intended."Output format:
Error handling:
npm run test:unit fails, report the error output verbatim, diagnose
the root cause, and fix before declaring success.path/to/file.test.ts).describe/it rules, named constants, toStrictEqual, lint rulesvi.mock + vi.mocked, vi.spyOn escape hatch, vi.doMock
exception flow, Supabase stubs, ESM/Effect patterns, shared helpers, vi.hoisted, forceCastmakeCtx, makeSupabaseClient, MockRow<T>, Effect.runPromiseas any, act, async races, lint hygiene, toSorted()vi.mock("path") + vi.mocked(...) by default.
(docs)
Prefer this non-factory vi.mock pattern over vi.spyOn when possible —
vi.spyOn is intended as an escape hatch for one-off partial overrides on
stable references. Mocking the module surface with vi.mock keeps tests
simpler and easier to statically analyze.vi.spyOn(...) only for one-off partial overrides on stable references.
(docs)vi.doMock(...) only when runtime-dependent per-test mocking is required before
importing the SUT. (docs)vi.importActual / vi.hoisted only for explicit advanced cases
that cannot be expressed with the default pattern.
(docs)docs/ai/rules.md.docs/testing/unit-test-best-practices.md for full patterns.effect at module level. Mock your own boundary module and return real
Effect values.vi.hoisted() or vi.importActual() as baseline patterns; they are
exception paths.When writing tests aim to pass the repo lint on the first run. Quick rules for agents:
beforeEach / afterEach hooks; prefer per-test setup or extracted *.test-util.ts helpers.vi.spyOn(await import('...'), 'default')) or vi.mocked(...) inside the test.const NONE = 0, const ONE = 1).toStrictEqual() and toHaveLength() for array length assertions.any — prefer unknown or forceCast<T>(value) from test-utils.import * as mod) in tests; use named imports or dynamic import.import * as mod) in tests; prefer named or default static imports at the top of the file.import() in tests unless absolutely required. Prefer static imports combined with top-level vi.mock("path") and vi.mocked(...) implementations to keep test imports predictable and lint-friendly.init-declarations.npm run lint locally before finishing a test change.npm run test:unit -- path/to/file.test.ts # targeted (fastest)
npm run test:unit # all tests (before PR)
Input: "Add unit tests for shared/src/utils/safe.ts"
Expected: Agent reads safe.ts and any existing safe.test.ts, writes
tests using explicit AAA sections by default, runs targeted test command,
reports which cases were added and the full test output.
Input: "How should I mock a Supabase query in this repo?"
Expected: Agent answers in prose with inline code referencing the Supabase
mocking section of docs/testing/unit-test-best-practices.md. No test file modified.
Input: "Write tests for my hook useEventList.ts"
Expected: Agent loads unit-test-hook-best-practices skill and proceeds per that
skill's guidance rather than this one.
Input: "Add tests" (no file specified) Expected: Agent asks which file to test before proceeding.
tools
Zustand state management patterns for this project — store creation, selectors, Immer middleware, async actions with loading states, devtools, persist, and testing. Use when authoring or editing Zustand stores (use*Store files) or components that subscribe to stores. Do NOT use for React component structure or TypeScript-only utilities.
testing
How to write, update, or split skill files in this repo. Use when creating a new SKILL.md, updating an existing one, or deciding whether to put content in a skill vs. docs/.
development
Complete guide for testing React hooks — renderHook, Documentation by Harness, installStore, fixtures, subscription patterns, lint/compiler traps, and pre-completion checklist. Read docs/testing/unit-test-hook-best-practices.md for the full reference.
development
TypeScript conventions for this repo (no `any`, explicit return types, JSDoc, exactOptionalPropertyTypes, ambient types, import style). Use when authoring or editing any `.ts` or `.tsx` file, resolving TypeScript strictness errors, or fixing type-related lint failures. Do NOT use for React-specific typing patterns (see react-best-practices skill) or JSDoc-only changes (see code-comment-best-practices skill).