| name | jest-testing |
| description | Write, run, debug, and stabilize Jest tests for JavaScript, TypeScript, Node, and React projects. |
| allowed-tools | Bash(npm:*) Bash(npx:*) Bash(node:*) |
Jest Testing
When to use
Use this skill when writing, running, debugging, or stabilizing Jest tests for JavaScript, TypeScript, Node, and React projects.
For Vite-first projects, consider Vitest unless the project already uses Jest.
Quick start commands
npm test
npm test -- --watch
npx jest path/to/file.test.ts
npx jest -t "test name"
npx jest --findRelatedTests src/foo.ts
npx jest --coverage
npx jest --ci --coverage
node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand path/to/test
Test writing rules
- Use arrange/act/assert structure with descriptive test names.
- Prefer behavior over implementation details.
- Isolate state between tests and clean up side effects.
- For React Testing Library, query by role, label, or visible text; use
user-event for interactions and avoid component internals.
- For Node tests, mock I/O, network, and time; clean up open handles.
- For TypeScript, import from
@jest/globals when needed; run tsc --noEmit if Babel only transpiles and does not type-check.
Async rules
await expect(loadUser()).resolves.toEqual({ id: '1' });
await expect(loadUser()).rejects.toThrow('not found');
- Return or await promises so Jest can observe failures.
- Use
resolves and rejects for promise expectations.
- Use
expect.assertions(...) for rejection and callback paths that must assert.
- Do not mix
done callbacks with promises or async functions.
Mocking
const load = jest.fn().mockResolvedValue({ id: '1' });
const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
jest.mock('../api', () => ({
...jest.requireActual('../api'),
fetchUser: jest.fn().mockRejectedValue(new Error('offline')),
}));
spy.mockRestore();
- Use
jest.fn, jest.spyOn, and jest.mock for collaborators and boundaries.
- Use
mockResolvedValue and mockRejectedValue for async dependencies.
- Use
jest.requireActual for partial mocks.
- Clear or restore mocks with
jest.clearAllMocks(), jest.restoreAllMocks(), or per-mock restore calls.
Timers
jest.useFakeTimers();
jest.advanceTimersByTime(1000);
jest.runOnlyPendingTimers();
jest.useRealTimers();
- Use
useFakeTimers, runAllTimers, runOnlyPendingTimers, and advanceTimersByTime for deterministic time-based tests.
- Restore real timers after timer tests.
- Flush pending timers before switching back when code schedules delayed cleanup.
Debugging workflow
npx jest path/to/file.test.ts --runInBand --detectOpenHandles
npx jest -t "test name" --runInBand
node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand path/to/test
- Reproduce with the smallest file or test name filter.
- Run serially with
--runInBand when debugging shared state, timers, or open handles.
- Check Jest config, transform settings, module aliases, test environment (
node vs jsdom), and setup files.
- Remove
test.only and describe.only before final validation.
CI and coverage
npx jest --ci --coverage
npx jest --runInBand --detectOpenHandles
- Use
--ci for non-interactive runs.
- Use coverage to find meaningful gaps, not to force brittle implementation assertions.
- Stabilize CI by mocking network, controlling time, avoiding shared mutable state, and cleaning up handles.
Anti-patterns
- Testing private implementation details instead of observable behavior.
- Leaving
test.only, describe.only, broad snapshots, or skipped tests in committed code.
- Not awaiting promises or expecting async failures outside the awaited path.
- Mixing
done with promises or async tests.
- Mocking the unit under test instead of its dependencies.
- Depending on real network, wall-clock time, filesystem state, or process globals without cleanup.
Specific tasks
Official references