К основному содержанию
скилл CX Codex

vitest · jezweb — скилл для Claude Code: настройка тестов в проекте

Определяет тип проекта и создаёт рабочую конфигурацию Vitest: конфиг, setup-файл, утилиты и пример теста. Пригодится, когда тестов в проекте ещё нет.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add jezweb/claude-skills --skill vitest -a claude-code
Открыть на GitHub

Что делает vitest

Скилл сканирует package.json, tsconfig.json, wrangler.toml, vite.config.ts и jest.config.*, чтобы понять, что за проект перед ним. Дальше классифицирует его: Cloudflare Workers, React на Vite, React с SSR, Node/Hono API или библиотека. От типа зависит окружение тестов — jsdom для компонентов, node для серверного кода.

Дальше скилл генерирует файлы, а не просто рассказывает. Он пишет vitest.config.ts, setup-файл src/test/setup.ts для React, добавляет vitest/globals в tsconfig.json и скрипты test, test:run, test:coverage, test:ui в package.json. Существующие скрипты не перезаписываются, а если в проекте уже есть vite.config.ts, блок test встраивается туда — Vitest читает конфиг Vite напрямую.

Пакеты скилл ставит через тот менеджер, который найдёт по lock-файлу. Для React это jsdom и Testing Library, для Workers — @cloudflare/vitest-pool-workers. Если проект переезжает с Jest, старые пакеты вроде ts-jest и babel-jest скилл предлагает удалить. Учтите: пример теста он кладёт рядом с исходником, а не в отдельную папку __tests__ — если у вас принят другой порядок, файл придётся перенести.

Какие задачи решает

  • поднять тесты в проекте, где их никогда не было
  • подобрать окружение под React, Workers или Node API
  • переехать с Jest и вычистить старые пакеты
  • включить покрытие кода без ручной правки конфига
  • получить первый рабочий тест как образец для остальных

Примеры запросов агенту

  • настрой Vitest в этом проекте
  • добавь тесты для API-роутов на Hono
  • перенеси тесты с Jest на Vitest

Как установить vitest

1Через Skills CLI (Vercel)

npx skills add jezweb/claude-skills --skill vitest -a claude-code

2Вручную: положить файлы

~/.claude/skills/vitest/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/vitest/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о vitest

Как установить vitest в Claude?

Выполните npx skills add jezweb/claude-skills --skill vitest -a claude-code. После этого файл скилла окажется в ~/.claude/skills/vitest/SKILL.md.

Что делает скилл vitest?

Определяет тип проекта, генерирует vitest.config.ts, setup-файл, утилиты и один пример теста, а также прописывает скрипты и типы для TypeScript.

Он заменит мой существующий конфиг Vite?

Нет. Если vite.config.ts уже есть, скилл добавляет в него блок test, а не создаёт отдельный файл. Скрипты в package.json тоже дополняются, а не перезаписываются.

Исходный текст

SKILL.md · MIT
---
name: vitest
description: "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'."
license: MIT
---

# Vitest Setup

Detect the project type, generate the right Vitest configuration, and produce working test infrastructure. Not a reference card — this skill creates files.

## Workflow

1. **Detect** — scan the project to determine type and existing setup
2. **Configure** — generate vitest.config.ts tailored to the environment
3. **Scaffold** — create test setup, utilities, and a sample test
4. **Wire up** — add package.json scripts and TypeScript config

## Step 1: Detect Project Type

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 structure
```

Classify 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.

## Step 2: Install Dependencies

Generate the install command based on detected type:

```bash
# 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-jest
```

Use the project's package manager (check for pnpm-lock.yaml, yarn.lock, bun.lockb, or package-lock.json).

## Step 3: Generate vitest.config.ts

### Cloudflare Workers

```typescript
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:

```typescript
/// <reference types="vitest/config" />
import { defineConfig } from "vite";
import { cloudflare } from "@cloudflare/vite-plugin";

export default defineConfig({
  plugins: [cloudflare()],
  test: {
    globals: true,
  },
});
```

### React (Vite)

```typescript
/// <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.

### Node / Hono API

```typescript
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    globals: true,
    environment: "node",
  },
});
```

### With Coverage (add to any config)

```typescript
  test: {
    // ... existing config
    coverage: {
      provider: "v8",
      reporter: ["text", "html", "lcov"],
      exclude: [
        "node_modules/",
        "**/*.config.*",
        "**/*.d.ts",
        "**/test/**",
      ],
    },
  },
```

## Step 4: Generate Test Setup File

Create `src/test/setup.ts` (React projects only):

```typescript
import "@testing-library/jest-dom/vitest";
```

That single import adds all the custom matchers (toBeInTheDocument, toHaveTextContent, etc.) and registers the Vitest `expect.extend` automatically.

## Step 5: Add TypeScript Config

Add to `tsconfig.json` compilerOptions:

```json
{
  "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.

## Step 6: Add Package.json Scripts

```json
{
  "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.

## Step 7: Generate Sample Test

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.

### For a Hono API route (e.g. `src/routes/health.ts`):

```typescript
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" });
  });
});
```

### For a React component (e.g. `src/components/Button.tsx`):

```typescript
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();
  });
});
```

### For a utility function (e.g. `src/utils/format.ts`):

```typescript
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.

## Step 8: Verify

Run the tests to confirm everything works:

```bash
pnpm test:run
```

If 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 |

---

## Mocking Reference

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.

### Module mocking (vi.mock)

```typescript
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);
});
```

### Spy on methods (vi.spyOn)

```typescript
it("spies on console.warn", () => {
  const spy = vi.spyOn(console, "warn").mockImplementation(() => {});
  doSomethingThatWarns();
  expect(spy).toHaveBeenCalledOnce();
  spy.mockRestore();
});
```

### Fake timers

```typescript
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");
});
```

### Global stubs

```typescript
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();
});
```

### Snapshot testing

```typescript
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",
    }
  `);
});
```

### Parameterized tests

```typescript
describe.each([
  { input: "hello", expected: "HELLO" },
  { input: "world", expected: "WORLD" },
  { input: "", expected: "" },
])("toUpperCase($input)", ({ input, expected }) => {
  it(`returns ${expected}`, () => {
    expect(input.toUpperCase()).toBe(expected);
  });
});
```

---

## Jest Migration

When the detected project has Jest (`jest.config.*`, `@types/jest`, `ts-jest` in dependencies):

1. **Generate the vitest.config.ts** using the steps above
2. **Update imports** in existing test files:

```typescript
// 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");
```

3. **Remove Jest packages:**
```bash
pnpm remove jest ts-jest @types/jest jest-environment-jsdom babel-jest @jest/globals
```

4. **Update tsconfig** — replace `"types": ["jest"]` with `"types": ["vitest/globals"]`

5. **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` |

---

## Workspace Setup (Monorepos)

For monorepo projects with multiple packages:

```typescript
// 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.

---

## What This Skill Produces

After running, the project should have:
- `vitest.config.ts` (or test block added to existing vite.config.ts)
- `src/test/setup.ts` (React projects)
- Updated `tsconfig.json` with vitest/globals type
- Updated `package.json` with test scripts
- At least one passing sample test against real source code
- Dependencies installed

The tests should pass on first run. If they don't, fix them before finishing.

© jezweb · MIT · jezweb/claude-skills

Похожие скиллы

Всё по теме «Тесты и QA» →

Сначала — vitest от других авторов.

vitest Anthony Fu Скилл помогает писать тесты на Vitest, настраивать моки и покрытие. Пригодится, когда нужно разобраться с фильтрацией тестов или фикстурами. CX Codex +1 43 800установок vitest pproenca Скилл даёт ИИ-агенту 44 правила для написания, отладки и ускорения тестов на Vitest. Помогает настроить моки, изолировать окружение и разобрать нестабильные проверки. CX Codex +1 6 100установок vitest-skill TestMu AI Генерирует юнит-тесты на Vitest для JavaScript и TypeScript проектов. Помогает настроить моки через vi и протестировать компоненты React. CX Codex +1 448установок vitest-testing existential-birds Скилл для ИИ-агента: подсказывает, как писать тесты на Vitest — ассерты, моки, асинхронность, конфиг. Пригодится, когда в проекте уже стоит Vitest. CX Codex +1 467установок cloudflare-workers-testing secondsky Скилл для написания тестов Cloudflare Workers на Vitest с реальными биндингами D1, KV, R2 и Durable Objects. Пригодится, когда тесты падают на моках или не видят окружение. CX Codex +1 325установок vitest-midscene-e2e web-infra-dev Скилл объединяет Vitest и Midscene для создания E2E-тестов на естественном языке под Web, Android и iOS. Помогает быстро развернуть бойлерплейт или наладить автотесты без селекторов. CX Codex +1 2 100установок vitest-unit-testing-cursorrules-prompt-file PatrickJS Правило задаёт Cursor поведение эксперта по Vitest и TypeScript: пишет юнит-тесты на бизнес-логику и утилиты, мокает зависимости через vi.mock. ★ 41 011звёзд репо react-testing affaan-m Скилл для написания тестов React-компонентов, хуков и страниц: React Testing Library, Vitest или Jest, MSW для моков сети и проверки доступности через axe. CX Codex +1 4 800установок

Из того же набора54

seo-local-business Генерирует метатеги <head>, микроразметку JSON-LD LocalBusiness, robots.txt и sitemap.xml для сайтов локальных компаний с привязкой к регионам и пригородам. CX Codex +1 1 800установок elevenlabs-agents Собирает голосовых ИИ-агентов на ElevenLabs: настраивает агента, инструменты, базу знаний и подключение SDK. CX Codex +1 1 700установок wordpress-content Создаёт и правит посты, страницы, медиа, рубрики, метки и меню WordPress через WP-CLI или REST API. Пригодится, когда контент надо заливать пачкой, а не руками в админке. CX Codex +1 1 700установок d1-drizzle-schema Генерирует схемы Drizzle ORM с учётом ограничений Cloudflare D1. Помогает описать таблицы, настроить миграции и задокументировать структуру базы данных. CX Codex +1 1 700установок hono-api-scaffolder Создаёт маршруты Hono для Cloudflare Workers с проверкой Zod, обработкой ошибок и документацией API. Нужен после подготовки каркаса проекта. CX Codex +1 1 600установок project-health Проверяет конфигурацию Claude в проекте: права, файлы контекста, утёкшие секреты. Запускается и на старте, и в середине работы. CX Codex +1 1 600установок landing-page Собирает готовый одностраничный сайт в один файл HTML с Tailwind CSS по вашему брифу. CX Codex +1 1 500установок wordpress-setup Скилл проверяет WP-CLI, тестирует SSH или REST API, настраивает авторизацию и сохраняет конфиг подключения к WordPress. CX Codex +1 1 500установок

Спонсоры проекта

Компании, которые помогают держать аналитику открытой