add-seed-skills
Use when adding or editing QA skills in seed-skills/ or getting them onto the live qaskills.sh catalog, e.g. "add N new skills",…
Unit testing skill using Jest for TypeScript and JavaScript, covering mocking, spies, snapshots, coverage, async testing, and custom matchers.
Claude Code
$ npx -y skills add PramodDutta/qaskills --skill jest-unit --agent claude-code
Codex
$ npx skills add PramodDutta/qaskills --skill jest-unit -a codex -y
Cursor
$ npx skills add PramodDutta/qaskills --skill jest-unit -a cursor -y
Gemini CLI
$ npx skills add PramodDutta/qaskills --skill jest-unit -a gemini-cli -y
GitHub Copilot
$ npx skills add PramodDutta/qaskills --skill jest-unit -a github-copilot -y
OpenCode
$ npx skills add PramodDutta/qaskills --skill jest-unit -a opencode -y
Windsurf
$ npx skills add PramodDutta/qaskills --skill jest-unit -a windsurf -y
name: jest-unit description: Unit testing skill using Jest for TypeScript and JavaScript, covering mocking, spies, snapshots, coverage, async testing, and custom matchers. license: MIT metadata: author: thetestingacademy version: 1.0.0 source: https://qaskills.sh/skills/thetestingacademy/jest-unit
You are an expert software engineer specializing in unit testing with Jest. When the user asks you to write, review, or debug Jest unit tests, follow these detailed instructions.
1. **Test behavior, not implementation** -- Tests should verify what code does, not how it does it. 2. **One assertion focus per test** -- Each test should verify a single logical concept. 3. **Arrange-Act-Assert** -- Structure every test into setup, execution, and verification. 4. **Fast and isolated** -- Unit tests must run in milliseconds and have no external dependencies. 5. **Descriptive names** -- Test names should read as specifications of the code's behavior.
src/
services/
user.service.ts
user.service.test.ts
order.service.ts
order.service.test.ts
utils/
validators.ts
validators.test.ts
formatters.ts
formatters.test.ts
models/
user.model.ts
__mocks__/
axios.ts
database.ts
__tests__/
integration/
user-order.test.ts
jest.config.ts// jest.config.ts
import type { Config } from 'jest';
const config: Config = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/src'],
testMatch: ['**/*.test.ts', '**/*.spec.ts'],
collectCoverageFrom: [
'src/**/*.ts',
'!src/**/*.d.ts',
'!src/**/*.test.ts',
'!src/**/index.ts',
],
coverageThresholds: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
coverageReporters: ['text', 'lcov', 'json-summary'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
setupFilesAfterSetup: ['<rootDir>/jest.setup.ts'],
clearMocks: true,
restoreMocks: true,
};
export default config;// validators.ts
export function isValidEmail(email: string): boolean {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
}
export function isStrongPassword(password: string): boolean {
return (
password.length >= 8 &&
/[A-Z]/.test(password) &&
/[a-z]/.test(password) &&
/[0-9]/.test(password) &&
/[!@#$%^&*]/.test(password)
);
}// validators.test.ts
import { isValidEmail, isStrongPassword } from './validators';
describe('isValidEmail', () => {
it('should return true for valid email addresses', () => {
expect(isValidEmail('user@example.com')).toBe(true);
expect(isValidEmail('first.last@domain.co.uk')).toBe(true);
expect(isValidEmail('user+tag@example.com')).toBe(true);
});
it('should return false for invalid email addresses', () => {
expect(isValidEmail('')).toBe(false);
expect(isValidEmail('not-an-email')).toBe(false);
expect(isValidEmail('@missing-local.com')).toBe(false);
expect(isValidEmail('missing-at.com')).toBe(false);
expect(isValidEmail('spaces here@bad.com')).toBe(false);
});
});
describe('isStrongPassword', () => {
it('should accept a strong password', () => {
expect(isStrongPassword('SecurePass1!')).toBe(true);
});
it('should reject passwords shorter than 8 characters', () => {
expect(isStrongPassword('Ab1!')).toBe(false);
});
it('should reject passwords without uppercase letters', () => {
expect(isStrongPassword('lowercase1!')).toBe(false);
});
it('should reject passwords without lowercase letters', () => {
expect(isStrongPassword('UPPERCASE1!')).toBe(false);
});
it('should reject passwords without numbers', () => {
expect(isStrongPassword('NoNumbers!')).toBe(false);
});
it('should reject passwords without special characters', () => {
expect(isStrongPassword('NoSpecial1')).toBe(false);
});
});// user.service.ts
import { UserRepository } from './user.repository';
import { EmailService } from './email.service';
export class UserService {
constructor(
private userRepo: UserRepository,
private emailService: EmailService
) {}
async createUser(email: string, name: string): Promise<User> {
const existing = await this.userRepo.findByEmail(email);
if (existing) {
throw new Error('User already exists');
}
const user = await this.userRepo.create({ email, name });
await this.emailService.sendWelcomeEmail(user.email, user.name);
return user;
}
async getUser(id: string): Promise<User | null> {
return this.userRepo.findById(id);
}
async deleteUser(id: string): Promise<void> {
const user = await this.userRepo.findById(id);
if (!user) {
throw new Error('User not found');
}
await this.userRepo.delete(id);
}
}// user.service.test.ts
import { UserService } from './user.service';
import { UserRepository } from './user.repository';
import { EmailService } from './email.service';
// Mock the dependencies
jest.mock('./user.repository');
jest.mock('./email.service');
describe('UserService', () => {
let userService: UserService;
let mockUserRepo: jest.Mocked<UserRepository>;
let mockEmailService: jest.Mocked<EmailService>;
beforeEach(() => {
mockUserRepo = new UserRepository() as jest.Mocked<UserRepository>;
mockEmailService = new EmailService() as jest.Mocked<EmailService>;
userService = new UserService(mockUserRepo, mockEmailService);
});
describe('createUser', () => {
it('should create a user and send welcome email', async () => {
const newUser = { id: '1', email: 'new@example.com', name: 'New User' };
mockUserRepo.findByEmail.mockResolvedValue(null);
mockUserRepo.create.mockResolvedValue(newUser);QA Skills Directory QA Skills is a curated directory of testing-specific skills for AI coding agents (Claude Code, Cursor, Copilot, etc.).
Use when adding or editing QA skills in seed-skills/ or getting them onto the live qaskills.sh catalog, e.g. "add N new skills",…
Use when publishing SEO blog articles to qaskills.sh, e.g. "publish today's articles", "daily SEO batch", "write 10 articles from…
Use when deploying qaskills.sh to production, verifying whether a deploy landed, or when a push to main did not show up on the…
Comprehensive RESTful API testing patterns covering HTTP methods, status codes, request/response validation, authentication,…
The complete QA skill for Claude Code — turn Claude into an expert QA engineer that picks the right test type, writes reliable…
End-to-end testing skill using Cypress for web applications, covering custom commands, network intercepts, fixtures, cy.session,…
Produce the "Playwright 1.xx API Review" artifact for a range of commits - the public API additions and the breaking or behavior…
Write, refine, run, and QA promptfoo evaluation suites: promptfooconfig.yaml, prompts, providers, vars, tests, assertions,…
DeepEval evaluation workflow for AI agents and LLM applications. TRIGGER when the user wants to evaluate or improve an AI agent,…