Use this skill when the user asks to add tests to existing code, improve test coverage, or write tests for a specific file or module.
-
Detect the test setup — check what's already configured:
cat package.json | grep -E "jest|vitest|mocha|playwright|cypress"
Look for config files: vitest.config.ts, jest.config.ts, playwright.config.ts, .mocharc.*. Check for existing test files to understand the project's test patterns and conventions.
-
If no test runner exists — set one up:
npm install -D vitest @testing-library/react @testing-library/jest-dom
Add a test script to package.json:
{ "test": "vitest run", "test:watch": "vitest" }
-
Analyze the target code — read the file(s) to test and identify:
- Public API: exported functions, classes, components, hooks
- Code paths: conditionals, error handling, edge cases
- Dependencies: external services, databases, APIs that need mocking
- Side effects: file I/O, network calls, DOM mutations
-
Create the test file — place it next to the source file or in a __tests__/ directory, matching the project's convention:
src/utils/format.ts → src/utils/format.test.ts
src/components/Button.tsx → src/components/Button.test.tsx
-
Write tests following this structure:
import { describe, it, expect, vi } from "vitest";
describe("functionName", () => {
it("returns formatted output for valid input", () => { ... });
it("handles empty string", () => { ... });
it("handles null/undefined input", () => { ... });
it("throws on invalid argument", () => { ... });
it("handles maximum length input", () => { ... });
});
-
Mock external dependencies — don't make real API calls or database queries in unit tests:
vi.mock("@/lib/db", () => ({
query: vi.fn().mockResolvedValue([{ id: 1, name: "test" }]),
}));
For React components, mock hooks that fetch data:
vi.mock("@/hooks/useUser", () => ({
useUser: () => ({ user: { name: "Test" }, isLoading: false }),
}));
-
Test React components with Testing Library:
import { render, screen, fireEvent } from "@testing-library/react";
it("renders the button and handles click", () => {
const onClick = vi.fn();
render(<Button onClick={onClick}>Click me</Button>);
fireEvent.click(screen.getByRole("button", { name: "Click me" }));
expect(onClick).toHaveBeenCalledOnce();
});
-
Run the tests and verify they pass:
npm test
If any fail, fix the test or the code (depending on whether the test expectation or the implementation is wrong).