Vitest Skill
sickn33/agentic-awesome-skills
Generates Vitest tests in JavaScript/TypeScript with Vite-native speed.
Set up Vitest testing in any project — detects type (Cloudflare Workers, React, Node, library), generates vitest.config.ts, test setup, utilities, and a sample test.
$ npx skills add jezweb/claude-skills --skill vitest -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install jezweb/claude-skills vitest --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/jezweb/claude-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/dev-tools/skills/vitest .claude/skills/vitest && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "vitest" agent skill from https://github.com/jezweb/claude-skills/tree/main/plugins/dev-tools/skills/vitest into .claude/skills/vitest/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "vitest", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/jezweb/claude-skills/tree/main/plugins/dev-tools/skills/vitestType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add jezweb/claude-skills --skill vitest -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install jezweb/claude-skills vitest --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jezweb/claude-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/dev-tools/skills/vitest .agents/skills/vitest && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "vitest" agent skill from https://github.com/jezweb/claude-skills/tree/main/plugins/dev-tools/skills/vitest into .agents/skills/vitest/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "vitest", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add jezweb/claude-skills --skill vitest -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install jezweb/claude-skills vitest --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jezweb/claude-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/dev-tools/skills/vitest .cursor/skills/vitest && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "vitest" agent skill from https://github.com/jezweb/claude-skills/tree/main/plugins/dev-tools/skills/vitest into .cursor/skills/vitest/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "vitest", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/jezweb/claude-skills.git --path plugins/dev-tools/skills/vitest--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add jezweb/claude-skills --skill vitest -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install jezweb/claude-skills vitest --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jezweb/claude-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/dev-tools/skills/vitest .gemini/skills/vitest && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "vitest" agent skill from https://github.com/jezweb/claude-skills/tree/main/plugins/dev-tools/skills/vitest into .gemini/skills/vitest/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "vitest", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install jezweb/claude-skills vitestInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add jezweb/claude-skills --skill vitest -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/jezweb/claude-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/dev-tools/skills/vitest .github/skills/vitest && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "vitest" agent skill from https://github.com/jezweb/claude-skills/tree/main/plugins/dev-tools/skills/vitest into .github/skills/vitest/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "vitest", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add jezweb/claude-skills --skill vitest -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install jezweb/claude-skills vitest --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jezweb/claude-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/dev-tools/skills/vitest .opencode/skills/vitest && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "vitest" agent skill from https://github.com/jezweb/claude-skills/tree/main/plugins/dev-tools/skills/vitest into .opencode/skills/vitest/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "vitest", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
vitestSet up Vitest testing in any project — detects type (Cloudflare Workers, React, Node, library), generates vitest.config.ts, test setup, utilities, and a sample test.
Vitest is an agent skill from jezweb/claude-skills. Set up Vitest testing in any project — detects type (Cloudflare Workers, React, Node, library), generates vitest.config.ts, test setup, utilities, and a sample test. Covers mocking patterns, coverage config, workspace setup, Jest migration. Use whenever the user mentions adding tests, setting up Vitest, configuring tests, migrating from Jest, fixing testing infrastructure, or asks 'how do I test this'.
Its SKILL.md is about 3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Testing & QA, covering Unit testing. It works with Vitest, React, Cloudflare Workers and Jest. The repository describes itself as: Skills for Claude Code CLI such as full stack dev Cloudflare, React, Tailwind v4, and AI integrations. The licence is MIT.
8 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 64965d9. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
pnpmFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use pnpm, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Vitest loads about 3k tokens when it runs. Until then it costs about 103 tokens; SKILL.md has 645 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from jezweb/claude-skills at commit 64965d9, republished under its MIT licence (© jezweb). 645 words, ~3,001 tokens.
.claude/skills/vitest/SKILL.md (or your agent's skills folder).Detect the project type, generate the right Vitest configuration, and produce working test infrastructure. Not a reference card — this skill creates files.
Read these files to determine the project:
package.json → dependencies, scripts, type field
tsconfig.json → paths, compiler options
wrangler.toml → Cloudflare Workers project
vite.config.ts → existing Vite setup (extend, don't replace)
vitest.config.ts → already configured? just fill gaps
jest.config.* → migration candidate
src/ → source structureClassify as one of:
| Type | Signals | Environment |
|---|---|---|
| Cloudflare Workers | wrangler.toml, @cloudflare/workers-types, cloudflare vite plugin | node with Workers-specific setup |
| React (Vite) | @vitejs/plugin-react, react-dom | jsdom or happy-dom |
| React (SSR/TanStack Start) | @tanstack/start, vinxi | Split: node for server, jsdom for client |
| Node/Hono API | hono, express, no react-dom | node |
| Library | exports field, no framework deps | node |
If a vite.config.ts already exists, extend it rather than creating a separate vitest.config.ts — Vitest reads Vite config natively.
Generate the install command based on detected type:
# Base (always)
pnpm add -D vitest
# React projects — add jsdom and Testing Library
pnpm add -D @vitest/coverage-v8 jsdom @testing-library/react @testing-library/jest-dom @testing-library/user-event
# Workers projects — add Cloudflare test utilities
pnpm add -D @vitest/coverage-v8 @cloudflare/vitest-pool-workers
# Node/Hono projects
pnpm add -D @vitest/coverage-v8
# If migrating from Jest, also remove:
pnpm remove jest ts-jest @types/jest jest-environment-jsdom babel-jestUse the project's package manager (check for pnpm-lock.yaml, yarn.lock, bun.lockb, or package-lock.json).
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
export default defineWorkersConfig({
test: {
globals: true,
poolOptions: {
workers: {
wrangler: { configPath: "./wrangler.toml" },
},
},
},
});If the project uses the Cloudflare Vite plugin (@cloudflare/vite-plugin), integrate into the existing vite.config.ts instead:
/// <reference types="vitest/config" />
import { defineConfig } from "vite";
import { cloudflare } from "@cloudflare/vite-plugin";
export default defineConfig({
plugins: [cloudflare()],
test: {
globals: true,
},
});/// <reference types="vitest/config" />
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: "jsdom",
setupFiles: ["./src/test/setup.ts"],
css: true,
},
});If a vite.config.ts already exists, add the test block to it rather than creating a new file.
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
globals: true,
environment: "node",
},
}); test: {
// ... existing config
coverage: {
provider: "v8",
reporter: ["text", "html", "lcov"],
exclude: [
"node_modules/",
"**/*.config.*",
"**/*.d.ts",
"**/test/**",
],
},
},Create src/test/setup.ts (React projects only):
import "@testing-library/jest-dom/vitest";That single import adds all the custom matchers (toBeInTheDocument, toHaveTextContent, etc.) and registers the Vitest expect.extend automatically.
Add to tsconfig.json compilerOptions:
{
"compilerOptions": {
"types": ["vitest/globals"]
}
}For projects with multiple tsconfig files (e.g. tsconfig.app.json + tsconfig.node.json), add to the one that covers test files — usually the root tsconfig.json or create a tsconfig.test.json that extends it.
{
"scripts": {
"test": "vitest",
"test:run": "vitest run",
"test:coverage": "vitest run --coverage",
"test:ui": "vitest --ui"
}
}Don't overwrite existing scripts — merge with what's there.
Write one test file that demonstrates the right patterns for this specific project. Place it next to real source code, not in a separate __tests__ directory.
src/routes/health.ts):import { describe, it, expect } from "vitest";
import { app } from "../index";
describe("GET /health", () => {
it("returns 200 with status ok", async () => {
const res = await app.request("/health");
expect(res.status).toBe(200);
const body = await res.json();
expect(body).toEqual({ status: "ok" });
});
});src/components/Button.tsx):import { describe, it, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Button } from "./Button";
describe("Button", () => {
it("renders with label", () => {
render(<Button>Click me</Button>);
expect(screen.getByRole("button", { name: /click me/i })).toBeInTheDocument();
});
it("calls onClick when clicked", async () => {
const user = userEvent.setup();
const handleClick = vi.fn();
render(<Button onClick={handleClick}>Click me</Button>);
await user.click(screen.getByRole("button"));
expect(handleClick).toHaveBeenCalledOnce();
});
});src/utils/format.ts):import { describe, it, expect } from "vitest";
import { formatCurrency } from "./format";
describe("formatCurrency", () => {
it("formats whole numbers", () => {
expect(formatCurrency(1000)).toBe("$1,000.00");
});
it("formats decimals", () => {
expect(formatCurrency(49.9)).toBe("$49.90");
});
it("handles zero", () => {
expect(formatCurrency(0)).toBe("$0.00");
});
});Pick a real file from the project to test. Don't invent a fake module — the sample test should run immediately after setup.
Run the tests to confirm everything works:
pnpm test:runIf it fails, diagnose and fix. Common issues:
| Error | Fix |
|---|---|
Cannot find module 'vitest' | Check install completed, check node_modules/.vitest exists |
ReferenceError: describe is not defined | Add globals: true to config, or add types: ["vitest/globals"] to tsconfig |
document is not defined | Wrong environment — set environment: "jsdom" for React tests |
Cannot use import.meta | Ensure vitest.config uses .ts extension and project has "type": "module" or Vite handles transforms |
| Workers bindings undefined | Use @cloudflare/vitest-pool-workers instead of plain vitest, check wrangler.toml path |
These patterns are for writing tests after setup is complete. Include them in the sample test or a src/test/examples.test.ts if the user asks for mocking examples.
import { vi, describe, it, expect } from "vitest";
import { getUser } from "./api";
vi.mock("./api", () => ({
getUser: vi.fn(),
}));
it("mocks a module function", async () => {
vi.mocked(getUser).mockResolvedValue({ id: 1, name: "Test" });
const user = await getUser(1);
expect(user.name).toBe("Test");
expect(getUser).toHaveBeenCalledWith(1);
});it("spies on console.warn", () => {
const spy = vi.spyOn(console, "warn").mockImplementation(() => {});
doSomethingThatWarns();
expect(spy).toHaveBeenCalledOnce();
spy.mockRestore();
});import { vi, beforeEach, afterEach, it, expect } from "vitest";
beforeEach(() => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2026-01-15T10:00:00Z"));
});
afterEach(() => {
vi.useRealTimers();
});
it("uses controlled time", () => {
expect(new Date().toISOString()).toBe("2026-01-15T10:00:00.000Z");
});it("stubs fetch", async () => {
const mockFetch = vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({ data: "test" }),
});
vi.stubGlobal("fetch", mockFetch);
const res = await fetch("/api/data");
expect(mockFetch).toHaveBeenCalledWith("/api/data");
vi.unstubAllGlobals();
});it("matches snapshot", () => {
const result = generateConfig({ debug: true });
expect(result).toMatchSnapshot();
});
it("matches inline snapshot", () => {
expect({ status: "ok", count: 3 }).toMatchInlineSnapshot(`
{
"count": 3,
"status": "ok",
}
`);
});describe.each([
{ input: "hello", expected: "HELLO" },
{ input: "world", expected: "WORLD" },
{ input: "", expected: "" },
])("toUpperCase($input)", ({ input, expected }) => {
it(`returns ${expected}`, () => {
expect(input.toUpperCase()).toBe(expected);
});
});When the detected project has Jest (jest.config.*, @types/jest, ts-jest in dependencies):
// Before
import { jest } from "@jest/globals";
jest.mock("./api");
jest.fn();
jest.spyOn(obj, "method");
// After
import { vi } from "vitest";
vi.mock("./api");
vi.fn();
vi.spyOn(obj, "method");pnpm remove jest ts-jest @types/jest jest-environment-jsdom babel-jest @jest/globalsUpdate tsconfig — replace "types": ["jest"] with "types": ["vitest/globals"]
Run tests and fix any remaining issues
Key replacements:
| Jest | Vitest |
|---|---|
jest.fn() | vi.fn() |
jest.mock() | vi.mock() |
jest.spyOn() | vi.spyOn() |
jest.useFakeTimers() | vi.useFakeTimers() |
jest.clearAllMocks() | vi.clearAllMocks() |
jest.requireActual() | vi.importActual() |
@jest/globals | vitest |
jest.config.js | vitest.config.ts |
For monorepo projects with multiple packages:
// vitest.workspace.ts
import { defineWorkspace } from "vitest/config";
export default defineWorkspace([
"packages/*/vitest.config.ts",
]);Each package gets its own config. The workspace file just points to them.
After running, the project should have:
vitest.config.ts (or test block added to existing vite.config.ts)src/test/setup.ts (React projects)tsconfig.json with vitest/globals typepackage.json with test scriptsThe tests should pass on first run. If they don't, fix them before finishing.
© jezweb, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in plugins/dev-tools/skills/vitest of jezweb/claude-skills.
Open the folder on GitHubat commit 64965d9
Vitest next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Vitest this skilljezweb/claude-skills | 1.1k | — | ~3k | Automated safety check: Pass | MIT | |
| Vitest Skillsickn33/agentic-awesome-skills | 47k | 1 repos | ~1.2k | Automated safety check: Pass | MIT | |
| Tooling SetupMadAppGang/claude-code | 284 | — | ~1.2k | Automated safety check: Notes | MIT | |
| Vitestsupabase/supabase | 111k | 12 repos | ~1.1k | Automated safety check: Pass | Apache-2.0 | |
| Effect TStellahq/opensession | 392 | — | ~3.7k | Automated safety check: Pass | MIT | |
| React Testinggetsentry/sentry | 46k | — | ~2.2k | Automated safety check: Pass | Custom licence |
sickn33/agentic-awesome-skills
Generates Vitest tests in JavaScript/TypeScript with Vite-native speed.
MadAppGang/claude-code
A skill your agent uses when setting up new projects or updating tool configurations.
supabase/supabase
Vitest API and config reference (Jest-compatible) — mocking with vi., spies, fake timers, coverage configuration, fixtures, snapshots, and test filtering.
tellahq/opensession
Write idiomatic Effect v4 TypeScript verified against the pinned effect@4.0.0-rc.112 source.
getsentry/sentry
Write and review React/TypeScript tests for Sentry's frontend using Jest and React Testing Library.
nrwl/nx
Migrate an Nx repo package's unit tests from Jest to Vitest, reusing the shared setup that packages/workspace established.
jezweb/claude-skills
Build conversational AI voice agents on the ElevenLabs platform.
jezweb/claude-skills
Generate custom favicons from logos, text, or brand colours.
jezweb/claude-skills
Set up Tailwind v4 + shadcn/ui themed UI with dark mode. An agent skill from jezweb/claude-skills.
jezweb/claude-skills
All-in-one project configuration and health management. An agent skill from jezweb/claude-skills.
jezweb/claude-skills
Test website responsiveness across viewport widths using browser automation.
jezweb/claude-skills
Build MCP servers in Python with FastMCP. An agent skill from jezweb/claude-skills.
Categories
Set up Vitest testing in any project — detects type (Cloudflare Workers, React, Node, library), generates vitest.config.ts, test setup, utilities, and a sample test. Vitest is an agent skill from jezweb/claude-skills.ts, test setup, utilities, and a sample test.
Vitest fits situations like: the user mentions adding tests; setting up Vitest; configuring tests; migrating from Jest.
Run `npx skills add jezweb/claude-skills --skill vitest -a claude-code`. Or copy the skill folder (plugins/dev-tools/skills/vitest in jezweb/claude-skills) into .claude/skills/vitest in your project. Claude Code loads it when a task matches its description.
Run `npx skills add jezweb/claude-skills --skill vitest -a codex`. Or copy the skill folder (plugins/dev-tools/skills/vitest in jezweb/claude-skills) into .agents/skills/vitest in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add jezweb/claude-skills --skill vitest -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/vitest, .gemini/skills/vitest, .github/skills/vitest and .opencode/skills/vitest in your project.
Going by SKILL.md and its folder, Vitest needs the command-line tools its instructions call (pnpm).
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Vitest is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 3k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Vitest: Vitest Skill (sickn33/agentic-awesome-skills, 47k stars), Tooling Setup (MadAppGang/claude-code, 284 stars), Vitest (supabase/supabase, 111k stars) and Effect TS (tellahq/opensession, 392 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
jezweb (a GitHub user) maintains it in jezweb/claude-skills, which has 1,051 GitHub stars. The repository holds 52 skills in this directory. The repository was last updated on October 5, 2026.
Source: jezweb/claude-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.