skills/jest-vitest/SKILL.md
JavaScript/TypeScript testing with Jest and Vitest. Use when user asks to "write JS tests", "add unit tests", "test React component", "mock a module", "snapshot testing", "test async code", "set up Jest", "migrate to Vitest", or any JS/TS testing tasks.
npx skillsauth add 1mangesh1/dev-skills-collection jest-vitestInstall 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.
JavaScript/TypeScript testing with Jest and Vitest.
# Jest
npx jest
npx jest --watch
npx jest --coverage
npx jest path/to/test.ts
npx jest -t "test name pattern"
# Vitest
npx vitest
npx vitest run # Single run (no watch)
npx vitest --coverage
npx vitest path/to/test.ts
// Jest and Vitest share the same API
describe("Calculator", () => {
let calc: Calculator;
beforeEach(() => {
calc = new Calculator();
});
afterEach(() => {
calc.reset();
});
it("should add two numbers", () => {
expect(calc.add(2, 3)).toBe(5);
});
it("should throw on division by zero", () => {
expect(() => calc.divide(1, 0)).toThrow("Division by zero");
});
describe("negative numbers", () => {
it("should handle negative addition", () => {
expect(calc.add(-1, -2)).toBe(-3);
});
});
});
// Equality
expect(value).toBe(exact); // === strict
expect(value).toEqual(deepEqual); // Deep equality
expect(value).toStrictEqual(strict); // Deep + type
// Truthiness
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeNull();
expect(value).toBeUndefined();
expect(value).toBeDefined();
// Numbers
expect(value).toBeGreaterThan(3);
expect(value).toBeLessThanOrEqual(10);
expect(value).toBeCloseTo(0.3, 5);
// Strings
expect(str).toMatch(/regex/);
expect(str).toContain("substring");
// Arrays/Objects
expect(arr).toContain(item);
expect(arr).toHaveLength(3);
expect(obj).toHaveProperty("key", "value");
expect(obj).toMatchObject({ name: "Alice" });
// Exceptions
expect(() => fn()).toThrow();
expect(() => fn()).toThrow("message");
expect(() => fn()).toThrow(ErrorClass);
// Mock function
const mockFn = jest.fn(); // Jest
const mockFn = vi.fn(); // Vitest
mockFn.mockReturnValue(42);
mockFn.mockReturnValueOnce(1);
mockFn.mockResolvedValue({ data: [] });
mockFn.mockImplementation((x) => x * 2);
// Assertions
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(2);
expect(mockFn).toHaveBeenCalledWith("arg1", "arg2");
// Mock module
jest.mock("./database"); // Jest
vi.mock("./database"); // Vitest
// Mock with implementation
jest.mock("./api", () => ({
fetchUser: jest.fn().mockResolvedValue({ name: "Alice" }),
}));
// Vitest equivalent
vi.mock("./api", () => ({
fetchUser: vi.fn().mockResolvedValue({ name: "Alice" }),
}));
// Spy on existing method
const spy = jest.spyOn(object, "method"); // Jest
const spy = vi.spyOn(object, "method"); // Vitest
// Mock timers
jest.useFakeTimers(); // Jest
vi.useFakeTimers(); // Vitest
jest.advanceTimersByTime(1000); // Jest
vi.advanceTimersByTime(1000); // Vitest
// Async/await
it("fetches users", async () => {
const users = await fetchUsers();
expect(users).toHaveLength(3);
});
// Resolved/rejected
it("resolves with data", async () => {
await expect(fetchData()).resolves.toEqual({ ok: true });
});
it("rejects with error", async () => {
await expect(fetchBad()).rejects.toThrow("Network error");
});
// Create/update snapshot
it("renders correctly", () => {
const tree = render(<Button label="Click" />);
expect(tree).toMatchSnapshot();
});
// Inline snapshot
it("serializes", () => {
expect(serialize(data)).toMatchInlineSnapshot(`"expected output"`);
});
// Update snapshots: jest --updateSnapshot / vitest --update
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
it("renders and interacts", async () => {
render(<LoginForm onSubmit={mockSubmit} />);
// Query elements
const input = screen.getByRole("textbox", { name: /email/i });
const button = screen.getByRole("button", { name: /submit/i });
// Interact
fireEvent.change(input, { target: { value: "[email protected]" } });
fireEvent.click(button);
// Assert
await waitFor(() => {
expect(mockSubmit).toHaveBeenCalledWith("[email protected]");
});
expect(screen.getByText("Success")).toBeInTheDocument();
});
// userEvent (more realistic)
import userEvent from "@testing-library/user-event";
it("types and submits", async () => {
const user = userEvent.setup();
render(<Form />);
await user.type(screen.getByRole("textbox"), "hello");
await user.click(screen.getByRole("button"));
});
# Jest
npx jest --coverage --coverageThreshold='{"global":{"branches":80,"functions":80,"lines":80}}'
# Vitest (vitest.config.ts)
# coverage: { provider: "v8", thresholds: { lines: 80 } }
// vitest.config.ts
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
globals: true,
environment: "jsdom",
setupFiles: ["./tests/setup.ts"],
coverage: {
provider: "v8",
reporter: ["text", "html"],
exclude: ["node_modules/", "tests/"],
},
},
});
// jest.config.js
module.exports = {
preset: "ts-jest",
testEnvironment: "jsdom",
setupFilesAfterSetup: ["./tests/setup.ts"],
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1",
},
coverageThreshold: {
global: { branches: 80, functions: 80, lines: 80, statements: 80 },
},
};
For advanced patterns, React testing recipes, and migration guides: references/patterns.md
tools
Parallel execution with xargs, GNU parallel, and batch processing patterns. Use when user mentions "xargs", "parallel", "batch processing", "run in parallel", "parallel execution", "process list of files", "bulk operations", "concurrent commands", "map over files", or running commands on multiple inputs.
development
WebSocket implementation for real-time bidirectional communication. Use when user mentions "websocket", "ws://", "wss://", "real-time", "live updates", "chat application", "socket.io", "Server-Sent Events", "SSE", "push notifications", "live data", "streaming data", "bidirectional communication", "websocket server", "reconnection", or building real-time features.
tools
Frontend bundler configuration for Webpack and Vite. Use when user mentions "webpack", "vite", "bundler", "vite config", "webpack config", "code splitting", "tree shaking", "hot module replacement", "HMR", "build optimization", "bundle size", "chunk splitting", "loader", "plugin", "esbuild", "rollup", "dev server", or configuring JavaScript build tools.
tools
VS Code configuration, extensions, keybindings, and workspace optimization. Use when user mentions "vscode", "vs code", "vscode settings", "vscode extensions", "keybindings", "code editor", "workspace settings", "settings.json", "launch.json", "tasks.json", "vscode snippets", "devcontainer", "remote development", or customizing their VS Code setup.