vitest-skill — Claude Code skill: what it does, how to install
Generates Vitest unit tests for JavaScript and TypeScript projects. Provides patterns for vi mocking and React component testing.
npx skills add LambdaTest/agent-skills --skill vitest-skill -a claude-codeWhat vitest-skill does
This skill guides the agent in writing Vitest test suites for JavaScript and TypeScript codebases. It enforces native ESM patterns and Vitest's own vi namespace, covering function stubs and fake timers. Tests targeting Jest patterns like jest.fn() are treated as anti-patterns and replaced with vi.fn().
The guidelines include test templates for React components via @testing-library/react and in-source testing using import.meta.vitest. It also provides a ready-to-use vitest.config.ts setup configured for jsdom and V8 code coverage.
What it helps with
- migrate test suites from Jest mocks to
vi.mockandvi.fn - set up
vitest.config.tswith jsdom and V8 coverage - test React components using
@testing-library/react - implement in-source testing with
import.meta.vitest
Example prompts for the agent
- Write Vitest unit tests for Calculator covering normal execution and errors
- Mock the database module using vi.mock and vi.fn
- Create a vitest.config.ts file with jsdom environment and v8 coverage provider
How to install vitest-skill
1Skills CLI (Vercel)
npx skills add LambdaTest/agent-skills --skill vitest-skill -a claude-code2Manually: put the files in place
~/.claude/skills/vitest-skill/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/vitest-skill/
1Skills CLI (Vercel)
npx skills add LambdaTest/agent-skills --skill vitest-skill -a codex2Manually: put the files in place
.agents/skills/vitest-skill/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add LambdaTest/agent-skills --skill vitest-skill -a cursor2Manually: put the files in place
.cursor/skills/vitest-skill/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install LambdaTest/agent-skills vitest-skill2Manually: put the files in place
.github/skills/vitest-skill/SKILL.md1Skills CLI (Vercel)
npx skills add LambdaTest/agent-skills --skill vitest-skill -a gemini-cli2Platform CLI
gemini skills install https://github.com/LambdaTest/agent-skills --path vitest-skillManually: put the files in place
.devin/skills/vitest-skill/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add LambdaTest/agent-skills --skill vitest-skill -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about vitest-skill
How do I install vitest-skill in Claude Code?
Run npx skills add LambdaTest/agent-skills --skill vitest-skill -a claude-code in your terminal.
What does vitest-skill do?
It provides prompt instructions and code templates for writing Vitest tests, configuring mocks with vi, and setting up test runners.
How does it handle Jest compatibility?
While Vitest has a Jest-compatible API, the skill enforces using vi.fn() and vi.mock() instead of jest globals to avoid namespace errors.
Source text
SKILL.md · MIT
---
name: vitest-skill
description: >
Generates Vitest tests in JavaScript/TypeScript with Vite-native speed.
Jest-compatible API with ESM support and HMR. Use when user mentions "Vitest",
"vi.mock", "vitest.config". Triggers on: "Vitest", "vi.mock", "vi.fn",
"Vite test", "vitest config".
languages:
- JavaScript
- TypeScript
category: unit-testing
license: MIT
metadata:
author: TestMu AI
version: "1.0"
---
# Vitest Testing Skill
## Core Patterns
### Basic Test
```typescript
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { Calculator } from './calculator';
describe('Calculator', () => {
let calc: Calculator;
beforeEach(() => { calc = new Calculator(); });
it('adds two numbers', () => {
expect(calc.add(2, 3)).toBe(5);
});
it('throws on divide by zero', () => {
expect(() => calc.divide(10, 0)).toThrow();
});
});
```
### Mocking (vi instead of jest)
```typescript
import { vi } from 'vitest';
// Mock module
vi.mock('./database', () => ({
getUser: vi.fn().mockResolvedValue({ name: 'Alice' }),
saveUser: vi.fn().mockResolvedValue(true),
}));
// Mock function
const mockFn = vi.fn();
mockFn.mockReturnValue(42);
mockFn.mockResolvedValue({ data: 'test' });
// Spy
const spy = vi.spyOn(console, 'log').mockImplementation(() => {});
expect(spy).toHaveBeenCalledWith('message');
spy.mockRestore();
// Timers
vi.useFakeTimers();
vi.advanceTimersByTime(1000);
vi.runAllTimers();
vi.useRealTimers();
```
### In-Source Testing
```typescript
// src/math.ts — tests alongside code!
export function add(a: number, b: number) { return a + b; }
export function multiply(a: number, b: number) { return a * b; }
if (import.meta.vitest) {
const { it, expect } = import.meta.vitest;
it('adds', () => { expect(add(2, 3)).toBe(5); });
it('multiplies', () => { expect(multiply(3, 4)).toBe(12); });
}
```
### Snapshot Testing
```typescript
it('serializes user', () => {
expect(serializeUser(user)).toMatchSnapshot();
});
it('inline snapshot', () => {
expect(serializeUser(user)).toMatchInlineSnapshot(`
{ "name": "Alice", "email": "[email protected]" }
`);
});
```
### React Component Testing
```typescript
import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import Button from './Button';
describe('Button', () => {
it('renders with label', () => {
render(<Button label="Click me" />);
expect(screen.getByText('Click me')).toBeDefined();
});
});
```
### Anti-Patterns
| Bad | Good | Why |
|-----|------|-----|
| `jest.fn()` | `vi.fn()` | Vitest uses `vi` |
| `jest.mock()` | `vi.mock()` | Different namespace |
| No type safety | TypeScript + strict | Vitest is TS-first |
## Quick Reference
| Task | Command |
|------|---------|
| Run once | `npx vitest run` |
| Watch | `npx vitest` (default) |
| UI | `npx vitest --ui` |
| Coverage | `npx vitest --coverage` |
| Specific file | `npx vitest run src/math.test.ts` |
| Filter | `npx vitest run -t "adds"` |
## vitest.config.ts
```typescript
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
environment: 'jsdom',
coverage: { provider: 'v8', reporter: ['text', 'html'] },
include: ['src/**/*.{test,spec}.{js,ts,tsx}'],
includeSource: ['src/**/*.{js,ts}'],
},
});
```
## Deep Patterns → `reference/playbook.md`
| § | Section | Lines |
|---|---------|-------|
| 1 | Production Configuration | Config, workspace, setup file |
| 2 | Mocking Patterns | vi.mock, spies, timers, fetch |
| 3 | React Testing Library | Components, hooks, providers |
| 4 | Snapshot & Inline Snapshots | File, inline, serializers |
| 5 | Table-Driven Tests | test.each, describe.each |
| 6 | In-Source Testing | Co-located tests in source |
| 7 | API / Integration Testing | Server tests with fetch |
| 8 | CI/CD Integration | GitHub Actions, scripts |
| 9 | Debugging Quick-Reference | 10 common problems |
| 10 | Best Practices Checklist | 13 items |
© TestMu AI · MIT · LambdaTest/agent-skills