.claude/skills/jest/SKILL.md
Jest unit testing and test configuration for Express + TypeScript backend services. Use when: Writing unit tests, mocking services, testing business logic, setting up test infrastructure, or validating service layer functions.
npx skillsauth add kaxuna1/ecomsite jestInstall 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.
Writes unit tests and mocks for Express + TypeScript backend services. This codebase uses a service layer pattern with object literal exports and direct PostgreSQL pool.query() calls requiring manual mocking.
cd backend
npm install -D jest @types/jest ts-jest @faker-js/faker
npx ts-jest config:init
// backend/src/services/__tests__/authService.test.ts
import { authService } from '../authService';
import { pool } from '../../db/client';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
jest.mock('../../db/client');
jest.mock('bcryptjs');
jest.mock('jsonwebtoken');
describe('authService', () => {
beforeEach(() => jest.clearAllMocks());
describe('validateCredentials', () => {
it('returns token for valid credentials', async () => {
const mockUser = { id: 1, email: '[email protected]', password_hash: 'hash', name: 'Admin', role: 'admin', is_active: true };
(pool.query as jest.Mock).mockResolvedValueOnce({ rows: [mockUser] });
(bcrypt.compare as jest.Mock).mockResolvedValue(true);
(jwt.sign as jest.Mock).mockReturnValue('mock-token');
const result = await authService.validateCredentials('[email protected]', 'password');
expect(result).toEqual({ token: 'mock-token', user: expect.objectContaining({ email: '[email protected]' }) });
});
it('returns null for invalid password', async () => {
(pool.query as jest.Mock).mockResolvedValueOnce({ rows: [{ is_active: true, password_hash: 'hash' }] });
(bcrypt.compare as jest.Mock).mockResolvedValue(false);
expect(await authService.validateCredentials('[email protected]', 'wrong')).toBeNull();
});
});
});
| Concept | Usage | Example |
|---------|-------|---------|
| Mock pool.query | Replace database calls | jest.mock('../../db/client') |
| Test transactions | Mock client.connect() | See integration reference |
| JWT token factory | Generate test tokens | jwt.sign({ userId: 1 }, secret) |
| Type factories | Create typed test data | createProduct({ name: 'Test' }) |
export default {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/src'],
testMatch: ['**/__tests__/**/*.test.ts'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
setupFilesAfterEnv: ['<rootDir>/src/test/setup.ts'],
clearMocks: true,
collectCoverageFrom: ['src/services/**/*.ts', '!src/**/*.d.ts']
};
// backend/src/test/setup.ts
jest.mock('../db/client', () => ({
pool: {
query: jest.fn(),
connect: jest.fn()
}
}));
// Reset env for tests
process.env.JWT_SECRET = 'test-secret';
process.env.NODE_ENV = 'test';
When: Testing exported object literal services
// Services export object literals - mock at module level
jest.mock('../../db/client');
describe('orderService.create', () => {
const mockClient = {
query: jest.fn(),
release: jest.fn()
};
beforeEach(() => {
(pool.connect as jest.Mock).mockResolvedValue(mockClient);
});
it('creates order with transaction', async () => {
mockClient.query
.mockResolvedValueOnce({}) // BEGIN
.mockResolvedValueOnce({ rows: [{ id: 1 }] }) // INSERT order
.mockResolvedValueOnce({ rows: [{ id: 1, inventory: 10 }] }) // SELECT product
.mockResolvedValueOnce({}) // INSERT order_item
.mockResolvedValueOnce({}) // UPDATE inventory
.mockResolvedValueOnce({}); // COMMIT
const order = await orderService.create(mockOrderPayload);
expect(mockClient.query).toHaveBeenCalledWith('BEGIN');
});
});
tools
Zustand lightweight state management with persistence and middleware. Use when: managing client-side state (cart, auth, UI preferences), replacing React Context with simpler API, accessing state outside React components, implementing localStorage persistence
development
Zod schema validation and TypeScript integration for runtime type safety. Use when: Validating API payloads, form inputs, environment variables, or any external data boundaries where TypeScript types alone cannot guarantee safety.
tools
Configures Vite 5.x build tool, dev server, and frontend asset optimization for the Luxia e-commerce platform. Use when: configuring builds, adding environment variables, optimizing bundle size, setting up testing, debugging HMR issues, or adding Vite plugins.
development
Enforces strict TypeScript types across frontend and backend codebases. Use when: Writing new services, DTOs, interfaces, type guards, debugging type errors, or ensuring type safety at API boundaries.