Generate Jest unit and integration tests for JavaScript
A skill for generating Jest tests - matchers, mocking, async testing, snapshots, and React component testing.
Why it matters
Automate the creation of comprehensive Jest test suites for JavaScript and TypeScript projects, covering unit tests, integration tests, mocking strategies, async patterns, and React component testing to ensure code quality and catch regressions.
Outcomes
What it gets done
Write describe/it/expect test blocks with matchers for functions and classes
Mock modules, functions, and timers using jest.fn(), jest.mock(), and spies
Test async code with promises, resolves/rejects matchers, and waitFor patterns
Generate React component tests with Testing Library and snapshot assertions
Install
Add it to your toolbox
Run in your project directory:
curl -fsSL https://spark.entire.vc/get/ag-jest-skill | bash Overview
Jest Testing Skill
This skill generates Jest tests in JavaScript/TypeScript: matchers, mocking (functions, modules, spies, timers), async testing, snapshot testing, and React component testing with Testing Library. Use it when writing Jest unit or integration tests, including mocking, async testing, snapshots, or React component tests.
What it does
A skill for generating Jest unit and integration tests in JavaScript or TypeScript, covering mocking, snapshots, async testing, and React component testing. Core patterns cover basic describe/beforeEach/test structure with common matchers (toBe for strict equality, toEqual for deep equality, toBeTruthy, toBeGreaterThan, toBeCloseTo, toMatch, toContain, toHaveLength, toHaveProperty, toMatchObject, toThrow). Mocking covers jest.fn() with mockReturnValue/mockResolvedValue plus toHaveBeenCalledWith/toHaveBeenCalledTimes assertions, module mocking via jest.mock() (both auto-mocked and with an explicit factory implementation), jest.spyOn for spying on existing methods (with mockRestore to undo it), and fake timers via jest.useFakeTimers/advanceTimersByTime/useRealTimers. Async testing covers async/await tests, and the resolves/rejects matcher forms for asserting a promise's resolution or rejection directly. React component testing uses Testing Library (render, screen, fireEvent, waitFor) with a worked login-form example simulating field changes and a button click, then waiting for the onSubmit callback to be called with the expected payload. Snapshot testing uses toMatchSnapshot with jest --updateSnapshot to refresh snapshots. A documented anti-pattern table contrasts bad vs. good: expect(x === y).toBe(true) versus expect(x).toBe(y) for better failure messages, missing await on async assertions (silently swallows failures), and snapshotting everything versus snapshotting UI while asserting logic directly (avoiding snapshot fatigue). A quick-reference table covers running all tests, watch mode, coverage, updating snapshots, running a single file, and test.only for a single test. A deeper reference/playbook.md is pointed to for production-grade patterns across twelve sections: production config (Node/React configs, path aliases, coverage thresholds), a mocking deep dive (module/partial/manual mocks, spies, timers, env vars), async patterns (promises, rejections, event emitters, streams), table-driven testing with test.each/describe.each, custom matchers with TypeScript declarations, deeper React Testing Library patterns (userEvent, hooks, context providers), deeper snapshot testing (component/inline/property matchers), API service testing (mocked axios, CRUD, error handling), global setup for multi-project configs and DB setup/teardown, CI/CD with GitHub Actions and coverage gates, a debugging table of ten common problems with fixes, and a fifteen-item production best-practices checklist.
When to use - and when NOT to
Use it when the user mentions Jest, describe/it/expect, jest.mock, or toMatchSnapshot, or needs unit/integration tests written for JavaScript or TypeScript code including React components.
Inputs and outputs
Given code to test, it produces Jest test files using the appropriate matchers, mocks, async patterns, or React Testing Library queries for the code under test, following the documented anti-pattern avoidance and quick-reference commands.
Integrations
npx jest --coverage
Uses Jest as the test runner and matcher library, @testing-library/react and @testing-library/jest-dom for React component testing, and jest.mock/jest.spyOn/fake timers for isolating dependencies.
Who it's for
Developers writing Jest tests - unit tests, mocked integration tests, async code, or React components - who want correct matcher choice, proper mocking patterns, and awareness of common anti-patterns like missing awaits or over-snapshotting.
Source README
Jest Testing Skill
When to Use
Use this skill when you need generates Jest unit and integration tests in JavaScript or TypeScript. Covers mocking, snapshots, async testing, and React component testing. Use when user mentions "Jest", "describe/it/expect", "jest.mock", "toMatchSnapshot". Triggers on: "Jest", "expect().toBe()", "jest.mock",...
Core Patterns
Basic Test
describe('Calculator', () => {
let calc;
beforeEach(() => { calc = new Calculator(); });
test('adds two numbers', () => {
expect(calc.add(2, 3)).toBe(5);
});
test('throws on division by zero', () => {
expect(() => calc.divide(10, 0)).toThrow('Division by zero');
});
});
Matchers
expect(value).toBe(exact); // === strict
expect(value).toEqual(object); // deep equality
expect(value).toBeTruthy();
expect(value).toBeNull();
expect(value).toBeGreaterThan(3);
expect(value).toBeCloseTo(0.3, 5);
expect(str).toMatch(/regex/);
expect(arr).toContain(item);
expect(arr).toHaveLength(3);
expect(obj).toHaveProperty('name');
expect(obj).toMatchObject({ name: 'Alice' });
expect(() => fn()).toThrow(CustomError);
Mocking
// Mock function
const mockFn = jest.fn();
mockFn.mockReturnValue(42);
mockFn.mockResolvedValue({ data: 'test' });
expect(mockFn).toHaveBeenCalledWith('arg1');
expect(mockFn).toHaveBeenCalledTimes(1);
// Mock module
jest.mock('./database');
const db = require('./database');
db.getUser.mockResolvedValue({ name: 'Alice' });
// Mock with implementation
jest.mock('./api', () => ({
fetchUsers: jest.fn().mockResolvedValue([{ name: 'Alice' }]),
}));
// Spy
const spy = jest.spyOn(console, 'log').mockImplementation();
expect(spy).toHaveBeenCalledWith('expected');
spy.mockRestore();
// Fake timers
jest.useFakeTimers();
jest.advanceTimersByTime(1000);
jest.useRealTimers();
Async Testing
test('fetches users', async () => {
const users = await fetchUsers();
expect(users).toHaveLength(3);
});
test('resolves with data', () => {
return expect(fetchData()).resolves.toEqual({ data: 'value' });
});
test('rejects with error', () => {
return expect(fetchBadData()).rejects.toThrow('not found');
});
React Component Testing (Testing Library)
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import LoginForm from './LoginForm';
test('submits login form', async () => {
const onSubmit = jest.fn();
render(<LoginForm onSubmit={onSubmit} />);
fireEvent.change(screen.getByLabelText('Email'), {
target: { value: 'user@test.com' },
});
fireEvent.change(screen.getByLabelText('Password'), {
target: { value: 'password123' },
});
fireEvent.click(screen.getByRole('button', { name: /login/i }));
await waitFor(() => {
expect(onSubmit).toHaveBeenCalledWith({
email: 'user@test.com', [REDACTED],
});
});
});
Snapshot Testing
test('renders correctly', () => {
const tree = renderer.create(<Button label="Click" />).toJSON();
expect(tree).toMatchSnapshot();
});
// Update: jest --updateSnapshot
Anti-Patterns
| Bad | Good | Why |
|---|---|---|
expect(x === y).toBe(true) |
expect(x).toBe(y) |
Better errors |
No await on async |
Always await |
Swallows failures |
| Snapshot everything | Snapshot UI, assert logic | Snapshot fatigue |
Quick Reference
| Task | Command |
|---|---|
| Run all | npx jest |
| Watch | npx jest --watch |
| Coverage | npx jest --coverage |
| Update snapshots | npx jest --updateSnapshot |
| Run file | npx jest tests/calc.test.js |
| Single test | test.only('name', () => {}) |
Deep Patterns
For production-grade patterns, see reference/playbook.md:
| Section | What's Inside |
|---|---|
| §1 Production Config | Node + React configs, path aliases, coverage thresholds |
| §2 Mocking Deep Dive | Module/partial/manual mocks, spies, timers, env vars |
| §3 Async Patterns | Promises, rejections, event emitters, streams |
| §4 test.each | Array, tagged template, describe.each for table-driven tests |
| §5 Custom Matchers | toBeWithinRange, toBeValidEmail, TypeScript declarations |
| §6 React Testing Library | userEvent, hooks, context providers |
| §7 Snapshot Testing | Component, inline, property matchers |
| §8 API Service Testing | Mocked axios, CRUD patterns, error handling |
| §9 Global Setup | Multi-project config, DB setup/teardown |
| §10 CI/CD | GitHub Actions with coverage gates |
| §11 Debugging Table | 10 common problems with fixes |
| §12 Best Practices | 15-item production checklist |
Limitations
- Use this skill only when the task clearly matches its upstream source and local project context.
- Verify commands, generated code, dependencies, credentials, and external service behavior before applying changes.
- Do not treat examples as a substitute for environment-specific tests, security review, or user approval for destructive or costly actions.
FAQ
Common questions
Discussion
Questions & comments · 0
Sign In Sign in to leave a comment.