Automated summary
Runs and writes Jest tests for JavaScript/TypeScript projects, with examples for mocking, async tests, and React component testing.
Strengths
- Provides concrete commands to run all tests, target a file or test name, enable watch mode, or collect coverage.
- Shows reusable patterns for module mocks, spies, fake timers, and async assertions.
- Also covers React component tests with Testing Library and userEvent.
- The path triggers focus on Jest config files and test files, which limits off-topic activation.
Limitations
- Only covers Jest: there is no migration guide or initial setup for projects not already using this runner.
- The React component test example is truncated at the end of the document.
- E2E support is mentioned but no specific examples or guidance are provided.
Use it when a JavaScript/TypeScript project already uses Jest and you need to run, write, or debug tests.
Avoid it when the project uses another runner (pytest, RSpec, ExUnit, xUnit) or when the runner has not been identified yet; run test-detector first.
Security analysis
CautionThe skill is a straightforward Jest test-runner reference: it runs standard npm/npx test commands and shows idiomatic test, mocking, and configuration patterns. There are no destructive shell commands, no network exfiltration, no obfuscated payloads, and no attempts to alter agent behavior. The only risk surface is the inherent one of executing project test code via Bash and the snapshot-update flag that mutates files, so it lands at caution rather than safe.
- •Uses Bash to run `npm test` / `npx jest`, which executes arbitrary project test code and any npm lifecycle scripts — expected for a test runner but still arbitrary code execution from the repo.
- •Includes `npx jest --updateSnapshot`, which rewrites snapshot files on disk; agents should be cautious about auto-accepting snapshot changes.
- •`npx jest --watch` is an interactive/watching command that will hang a non-interactive agent session.
Examples
Add Jest tests for src/services/user.ts covering the success and not-found cases. Mock the repository with jest.fn(), then run the new test file.Run only the Jest tests whose name matches "should create user" with verbose output and show me the failures.Update the Jest snapshots and run the suite with coverage, then summarize which files have uncovered lines.name: jest description: Run and write Jest tests for JavaScript/TypeScript projects — the JS/TS test runner. when_to_use: Reach for this when the project tests JavaScript or TypeScript with Jest (jest.config.js, jest in package.json). Per-language test runner — use pytest for Python, rspec for Ruby, exunit for Elixir, xunit for C#/.NET. If you don't yet know which runner the project uses, run test-detector first. allowed-tools: Read, Write, Edit, Bash, Grep, Glob paths:
- "jest.config.*"
- "**/*.test.{ts,js,tsx,jsx}"
- "**/*.spec.{ts,js,tsx,jsx}"
- "package.json"
Jest Testing Skill
Execute and generate Jest tests for JavaScript/TypeScript projects with support for unit, integration, and E2E testing.
Test Execution
Run All Tests
npm test
# or
npx jest
Run Specific Tests
# Run tests matching a pattern
npx jest --testNamePattern="should create user"
# Run tests in a specific file
npx jest src/services/user.test.ts
# Run tests in watch mode
npx jest --watch
# Run with coverage
npx jest --coverage
Common Options
# Verbose output
npx jest --verbose
# Run only changed files
npx jest --onlyChanged
# Update snapshots
npx jest --updateSnapshot
# Run in CI mode
npx jest --ci --coverage --reporters=default --reporters=jest-junit
Test Patterns
Basic Test Structure
describe('UserService', () => {
let service: UserService;
let mockRepo: jest.Mocked<UserRepository>;
beforeEach(() => {
mockRepo = {
findById: jest.fn(),
create: jest.fn(),
update: jest.fn(),
delete: jest.fn(),
};
service = new UserService(mockRepo);
});
afterEach(() => {
jest.clearAllMocks();
});
describe('getUser', () => {
it('should return user when found', async () => {
const user = { id: '1', name: 'John' };
mockRepo.findById.mockResolvedValue(user);
const result = await service.getUser('1');
expect(result).toEqual(user);
expect(mockRepo.findById).toHaveBeenCalledWith('1');
});
it('should throw when user not found', async () => {
mockRepo.findById.mockResolvedValue(null);
await expect(service.getUser('999')).rejects.toThrow('User not found');
});
});
});
Mocking
// Mock a module
jest.mock('./api', () => ({
fetchUser: jest.fn(),
}));
// Mock implementation
import { fetchUser } from './api';
const mockFetchUser = fetchUser as jest.MockedFunction<typeof fetchUser>;
beforeEach(() => {
mockFetchUser.mockResolvedValue({ id: '1', name: 'Test' });
});
// Spy on methods
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
// Mock timers
jest.useFakeTimers();
jest.advanceTimersByTime(1000);
jest.useRealTimers();
Async Testing
// Using async/await
it('fetches data asynchronously', async () => {
const data = await fetchData();
expect(data).toEqual({ id: 1 });
});
// Testing rejected promises
it('handles errors', async () => {
await expect(fetchData()).rejects.toThrow('Network error');
});
// Waiting for side effects
it('updates state after fetch', async () => {
render(<Component />);
await waitFor(() => {
expect(screen.getByText('Loaded')).toBeInTheDocument();
});
});
React Component Testing
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
describe('LoginForm', () => {
it('submits with valid credentials', async () => {
const onSubmit = jest.fn();
render(<LoginForm onSubmit={onSubmit} />);
await userEvent.type(screen.getByLabelText('Email'), 'test@example.com');
await userEvent.type(screen.getByLabelText('Password'), 'password123');
await userEvent.click(screen.getByRole('button', { name: /submit/i }));
expect(onSubmit).toHaveBeenCalledWith({
email: 'test@example.com',
password: 'password123',
});
});
it('shows validation errors', async () => {
render(<LoginForm onSubmit={jest.fn()} />);
await userEvent.click(screen.getByRole('button', { name: /submit/i }));
expect(screen.getByText('Email is required')).toBeInTheDocument();
});
});
Configuration
jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/src'],
testMatch: ['**/*.test.ts', '**/*.spec.ts'],
collectCoverageFrom: [
'src/**/*.ts',
'!src/**/*.d.ts',
'!src/**/*.test.ts',
],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
};
jest.setup.ts
import '@testing-library/jest-dom';
// Global mocks
global.fetch = jest.fn();
// Extend expect
expect.extend({
toBeWithinRange(received: number, floor: number, ceiling: number) {
const pass = received >= floor && received <= ceiling;
return {
message: () =>
`expected ${received} ${pass ? 'not ' : ''}to be within range ${floor} - ${ceiling}`,
pass,
};
},
});
Troubleshooting
Common Issues
- Tests hanging: Check for unresolved promises or missing
done()callbacks - Mock not working: Ensure mock is defined before importing the module
- Timeout errors: Increase timeout with
jest.setTimeout(30000) - Memory issues: Run with
--maxWorkers=2or--runInBand
UI/UX Design Audit
Testing
Audit the interface and user experience of your digital products.
Web Accessibility Audit
Testing
Performs a comprehensive web accessibility audit following WCAG standards.
UAT Test Case Generator
Testing
Generates structured and comprehensive user acceptance test cases.