Skip to main content Skills Marketplace 发现并探索由社区构建的 Agent Skills
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill vitest命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
下载 Zip 下载中... CODE_EXAMPLES_INDEX.md 5.9 KB IMPLEMENTATION_SUMMARY.md 10.4 KB name vitest description Vitest - Modern TypeScript testing framework with Vite-native performance, ESM support, and TypeScript-first design user-invocable false disable-model-invocation true version 1.0.0 category toolchain author Claude MPM Team license MIT progressive_disclosure {"entry_point":{"summary":"Modern TypeScript testing with Vitest: Vite-native, ESM-first, instant HMR, built-in TypeScript support, React/Vue component testing","when_to_use":"Testing TypeScript/JavaScript projects, React/Vue components, Vite-based projects, when migrating from Jest, when fast test execution is needed","quick_start":"1. npm install -D vitest 2. Create vitest.config.ts 3. Write *.test.ts files 4. Run: npx vitest"}} context_limit 700 tags ["testing","vitest","vite","typescript","unit-testing","component-testing","esm"] requires_tools []
Vitest - Modern TypeScript Testing
Overview
Vitest is a next-generation test framework powered by Vite, designed for modern TypeScript/JavaScript projects. It provides blazing-fast test execution through HMR-based test running, native ESM support, and first-class TypeScript integration.
Key Features :
⚡ Vite-native : Instant HMR-based test execution (10-100x faster than Jest)
🎯 TypeScript-first : Built-in TypeScript support, no configuration needed
🔄 ESM-native : Native ES modules, async/await, top-level await
🧪 Jest-compatible : Compatible API for easy migration
📸 Snapshot testing : Built-in snapshot support
🎨 Component testing : React Testing Library, Vue Test Utils integration
📊 Coverage : Built-in v8/c8 coverage (faster than Istanbul)
🌐 UI mode : Beautiful web UI for test debugging
Installation :
npm install -D vitest
npm install -D @vitest/ui
Basic Setup
1. Configure Vitest
vitest.config.ts :
import { defineConfig } from 'vitest/config' ;
export default defineConfig ({
test : {
globals : true ,
environment : 'node' ,
coverage : {
provider : 'v8' ,
reporter : ['text' , 'json' , 'html' ],
exclude : [
,
,
,
,
],
},
: [ ],
: [ , , , , ],
},
});
'node_modules/'
'dist/'
'**/*.test.ts'
'**/*.spec.ts'
include
'**/*.{test,spec}.{ts,tsx}'
exclude
'node_modules'
'dist'
'.idea'
'.git'
'.cache'
2. TypeScript Configuration {
"compilerOptions" : {
"types" : [ "vitest/globals" ]
}
}
Alternative (without globals) :
import { describe, it, expect } from 'vitest' ;
3. Package.json Scripts {
"scripts" : {
"test" : "vitest run" ,
"test:watch" : "vitest" ,
"test:ui" : "vitest --ui" ,
"test:coverage" : "vitest run --coverage"
}
}
Core Testing Patterns
Basic Test Structure import { describe, it, expect, beforeEach, afterEach } from 'vitest' ;
describe ('Calculator' , () => {
let calculator : Calculator ;
beforeEach (() => {
calculator = new Calculator ();
});
it ('adds two numbers correctly' , () => {
const result = calculator.add (2 , 3 );
expect (result).toBe (5 );
});
it ('handles negative numbers' , () => {
expect (calculator.add (-5 , 3 )).toBe (-2 );
});
});
TypeScript Type Testing import { describe, it, expectTypeOf, assertType } from 'vitest' ;
interface User {
id : number ;
name : string ;
email : string ;
}
describe ('Type Safety' , () => {
it ('ensures correct types' , () => {
const user : User = {
id : 1 ,
name : 'Alice' ,
email : 'alice@example.com' ,
};
expectTypeOf (user.id ).toBeNumber ();
expectTypeOf (user.name ).toBeString ();
expectTypeOf (user).toMatchTypeOf <User >();
assertType<User >(user);
});
it ('checks function return types' , () => {
function getUser ( ): User {
return { id : 1 , name : 'Bob' , email : 'bob@example.com' };
}
expectTypeOf (getUser).returns .toMatchTypeOf <User >();
});
});
Mocking and Spies
vi.mock for Module Mocking import { describe, it, expect, vi } from 'vitest' ;
import { fetchUser } from './api' ;
import { UserService } from './UserService' ;
vi.mock ('./api' , () => ({
fetchUser : vi.fn (),
}));
describe ('UserService' , () => {
it ('fetches user data' , async () => {
const mockUser = { id : 1 , name : 'Alice' };
vi.mocked (fetchUser).mockResolvedValue (mockUser);
const service = new UserService ();
const user = await service.getUser (1 );
expect (fetchUser).toHaveBeenCalledWith (1 );
expect (user).toEqual (mockUser);
});
});
vi.spyOn for Method Spying import { describe, it, expect, vi } from 'vitest' ;
class Logger {
log (message : string ) {
console .log (message);
}
}
describe ('Logger Spy' , () => {
it ('tracks method calls' , () => {
const logger = new Logger ();
const spy = vi.spyOn (logger, 'log' );
logger.log ('Hello' );
logger.log ('World' );
expect (spy).toHaveBeenCalledTimes (2 );
expect (spy).toHaveBeenCalledWith ('Hello' );
expect (spy).toHaveBeenLastCalledWith ('World' );
spy.mockRestore ();
});
});
Mock Implementation import { describe, it, expect, vi } from 'vitest' ;
describe ('Mock Implementation' , () => {
it ('provides custom mock implementation' , () => {
const mockFn = vi.fn ((x : number ) => x * 2 );
expect (mockFn (5 )).toBe (10 );
expect (mockFn).toHaveBeenCalledWith (5 );
mockFn.mockImplementation ((x : number ) => x + 10 );
expect (mockFn (5 )).toBe (15 );
mockFn.mockImplementationOnce ((x : number ) => 100 );
expect (mockFn (5 )).toBe (100 );
expect (mockFn (5 )).toBe (15 );
});
});
Mocking Timers import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' ;
describe ('Timer Mocking' , () => {
beforeEach (() => {
vi.useFakeTimers ();
});
afterEach (() => {
vi.restoreAllMocks ();
});
it ('fast-forwards time' , () => {
const callback = vi.fn ();
setTimeout (callback, 1000 );
vi.advanceTimersByTime (500 );
expect (callback).not .toHaveBeenCalled ();
vi.advanceTimersByTime (500 );
expect (callback).toHaveBeenCalledTimes (1 );
});
it ('runs all timers' , async () => {
const callback = vi.fn ();
setTimeout (callback, 1000 );
setTimeout (callback, 2000 );
await vi.runAllTimersAsync ();
expect (callback).toHaveBeenCalledTimes (2 );
});
});
React Testing Integration
Setup React Testing Library npm install -D @testing-library/react @testing-library/jest-dom @testing-library/user-event
npm install -D jsdom
vitest.config.ts (React):
import { defineConfig } from 'vitest/config' ;
import react from '@vitejs/plugin-react' ;
export default defineConfig ({
plugins : [react ()],
test : {
globals : true ,
environment : 'jsdom' ,
setupFiles : './src/test/setup.ts' ,
},
});
import '@testing-library/jest-dom' ;
import { expect, afterEach } from 'vitest' ;
import { cleanup } from '@testing-library/react' ;
import * as matchers from '@testing-library/jest-dom/matchers' ;
expect.extend (matchers);
afterEach (() => {
cleanup ();
});
React Component Testing import { describe, it, expect } from 'vitest' ;
import { render, screen } from '@testing-library/react' ;
import userEvent from '@testing-library/user-event' ;
import { Counter } from './Counter' ;
describe ('Counter Component' , () => {
it ('renders initial count' , () => {
render (<Counter initialCount ={0} /> );
expect (screen.getByText ('Count: 0' )).toBeInTheDocument ();
});
it ('increments counter on button click' , async () => {
const user = userEvent.setup ();
render (<Counter initialCount ={0} /> );
const button = screen.getByRole ('button' , { name : /increment/i });
await user.click (button);
expect (screen.getByText ('Count: 1' )).toBeInTheDocument ();
});
it ('calls onChange callback' , async () => {
const onChange = vi.fn ();
const user = userEvent.setup ();
render (<Counter initialCount ={0} onChange ={onChange} /> );
await user.click (screen.getByRole ('button' , { name : /increment/i }));
expect (onChange).toHaveBeenCalledWith (1 );
});
});
Testing Hooks import { describe, it, expect } from 'vitest' ;
import { renderHook, act } from '@testing-library/react' ;
import { useCounter } from './useCounter' ;
describe ('useCounter Hook' , () => {
it ('initializes with default value' , () => {
const { result } = renderHook (() => useCounter (0 ));
expect (result.current .count ).toBe (0 );
});
it ('increments counter' , () => {
const { result } = renderHook (() => useCounter (0 ));
act (() => {
result.current .increment ();
});
expect (result.current .count ).toBe (1 );
});
it ('resets counter' , () => {
const { result } = renderHook (() => useCounter (10 ));
act (() => {
result.current .reset ();
});
expect (result.current .count ).toBe (10 );
});
});
Vue Testing Integration
Setup Vue Test Utils npm install -D @vue/test-utils @vitejs/plugin-vue
npm install -D happy-dom
import { defineConfig } from 'vitest/config' ;
import vue from '@vitejs/plugin-vue' ;
export default defineConfig ({
plugins : [vue ()],
test : {
globals : true ,
environment : 'happy-dom' ,
setupFiles : './src/test/setup.ts' ,
},
});
Vue Component Testing import { describe, it, expect } from 'vitest' ;
import { mount } from '@vue/test-utils' ;
import Counter from './Counter.vue' ;
describe ('Counter.vue' , () => {
it ('renders initial count' , () => {
const wrapper = mount (Counter , {
props : { initialCount : 5 },
});
expect (wrapper.text ()).toContain ('Count: 5' );
});
it ('increments on button click' , async () => {
const wrapper = mount (Counter , {
props : { initialCount : 0 },
});
await wrapper.find ('button' ).trigger ('click' );
expect (wrapper.text ()).toContain ('Count: 1' );
});
it ('emits update event' , async () => {
const wrapper = mount (Counter , {
props : { initialCount : 0 },
});
await wrapper.find ('button' ).trigger ('click' );
expect (wrapper.emitted ('update' )).toBeTruthy ();
expect (wrapper.emitted ('update' )?.[0 ]).toEqual ([1 ]);
});
});
Async Testing
Testing Promises import { describe, it, expect } from 'vitest' ;
describe ('Async Operations' , () => {
it ('resolves promises' , async () => {
const result = await Promise .resolve (42 );
expect (result).toBe (42 );
});
it ('rejects promises' , async () => {
await expect (Promise .reject (new Error ('Failed' ))).rejects .toThrow ('Failed' );
});
it ('uses resolves matcher' , async () => {
await expect (Promise .resolve (42 )).resolves .toBe (42 );
});
});
Testing Async Functions import { describe, it, expect, vi } from 'vitest' ;
async function fetchData (id : number ): Promise <string > {
const response = await fetch (`/api/data/${id} ` );
return response.json ();
}
describe ('Async Functions' , () => {
it ('fetches data successfully' , async () => {
global .fetch = vi.fn (() =>
Promise .resolve ({
json : () => Promise .resolve ('data' ),
} as Response )
);
const data = await fetchData (1 );
expect (data).toBe ('data' );
expect (fetch).toHaveBeenCalledWith ('/api/data/1' );
});
it ('handles fetch errors' , async () => {
global .fetch = vi.fn (() => Promise .reject (new Error ('Network error' )));
await expect (fetchData (1 )).rejects .toThrow ('Network error' );
});
});
Snapshot Testing
Basic Snapshots import { describe, it, expect } from 'vitest' ;
import { render } from '@testing-library/react' ;
import { UserCard } from './UserCard' ;
describe ('UserCard Snapshots' , () => {
it ('matches snapshot' , () => {
const { container } = render (
<UserCard name ="Alice" email ="alice@example.com" />
);
expect (container.firstChild ).toMatchSnapshot ();
});
it ('matches inline snapshot' , () => {
const user = { id : 1 , name : 'Bob' };
expect (user).toMatchInlineSnapshot (`
{
"id": 1,
"name": "Bob",
}
` );
});
});
Snapshot Serializers import { describe, it, expect } from 'vitest' ;
expect.addSnapshotSerializer ({
test : (val ) => val && typeof val.toISOString === 'function' ,
print : (val ) => `Date(${(val as Date ).toISOString()} )` ,
});
describe ('Custom Serializers' , () => {
it ('serializes dates consistently' , () => {
const data = {
timestamp : new Date ('2024-01-01T00:00:00.000Z' ),
user : 'Alice' ,
};
expect (data).toMatchSnapshot ();
});
});
Coverage Configuration
Advanced Coverage Setup import { defineConfig } from 'vitest/config' ;
export default defineConfig ({
test : {
coverage : {
provider : 'v8' ,
reporter : ['text' , 'json' , 'html' , 'lcov' ],
reportsDirectory : './coverage' ,
exclude : [
'node_modules/' ,
'dist/' ,
'**/*.test.ts' ,
'**/*.spec.ts' ,
'**/*.config.ts' ,
'**/types/' ,
],
thresholds : {
lines : 80 ,
functions : 80 ,
branches : 75 ,
statements : 80 ,
},
all : true ,
},
},
});
Running Coverage
npx vitest run --coverage
npx vitest --coverage --ui
npx vitest run --coverage --coverage.lines=90
Migration from Jest
API Compatibility Vitest provides Jest-compatible API:
import { describe, it, expect, jest } from 'vitest' ;
import { describe, it, expect, vi } from 'vitest' ;
const mockFn = vi.fn ();
const mockFn2 = jest.fn ();
Migration Checklist npm uninstall jest @types/jest ts-jest
npm install -D vitest @vitest/ui
{
"scripts" : {
"test" : "vitest run" ,
"test:watch" : "vitest"
}
}
3. Replace jest.config.js with vitest.config.ts :
module .exports = {
preset : 'ts-jest' ,
testEnvironment : 'node' ,
};
import { defineConfig } from 'vitest/config' ;
export default defineConfig ({
test : {
globals : true ,
environment : 'node' ,
},
});
- import { jest } from '@jest/globals' ;
+ import { vi } from 'vitest' ;
- jest.fn ()
+ vi.fn ()
- jest.spyOn ()
+ vi.spyOn ()
- jest.mock ()
+ vi.mock ()
Advanced Patterns
Concurrent Testing import { describe, it, expect } from 'vitest' ;
describe.concurrent ('Parallel Tests' , () => {
it ('test 1' , async () => {
await slowOperation ();
expect (true ).toBe (true );
});
it ('test 2' , async () => {
await slowOperation ();
expect (true ).toBe (true );
});
});
Test Context import { describe, it, expect, beforeEach } from 'vitest' ;
interface TestContext {
user : { id : number ; name : string };
api : ApiClient ;
}
describe<TestContext >('With Context' , () => {
beforeEach ((context ) => {
context.user = { id : 1 , name : 'Alice' };
context.api = new ApiClient ();
});
it<TestContext >('uses context' , ({ user, api } ) => {
expect (user.name ).toBe ('Alice' );
expect (api).toBeDefined ();
});
});
Custom Matchers import { expect } from 'vitest' ;
expect.extend ({
toBeWithinRange (received : number , floor : number , ceiling : number ) {
const pass = received >= floor && received <= ceiling;
return {
pass,
message : () =>
pass
? `expected ${received} not to be within range ${floor} - ${ceiling} `
: `expected ${received} to be within range ${floor} - ${ceiling} ` ,
};
},
});
expect (100 ).toBeWithinRange (90 , 110 );
Best Practices
Use globals: true - Simpler imports, Jest-compatible
Prefer vi over jest - Use Vitest-native API for new code
Use v8 coverage - Faster than Istanbul, works with native ESM
Test in isolation - Each test should be independent
Mock external dependencies - Network, file system, timers
Use TypeScript - Full type safety in tests
Run tests in CI mode - Use vitest run for CI, not watch mode
Leverage UI mode - Debug failing tests visually
Use describe.concurrent - Parallelize independent tests
Keep tests focused - One assertion per test when possible
Common Pitfalls ❌ Not using CI mode in CI/CD :
"test" : "vitest"
"test" : "vitest run"
{
"scripts" : {
"test" : "vitest run" ,
"test:watch" : "vitest" ,
"test:ui" : "vitest --ui"
}
}
❌ Forgetting to await async tests :
it ('fetches data' , () => {
fetchData ().then (data => {
expect (data).toBeDefined ();
});
});
it ('fetches data' , async () => {
const data = await fetchData ();
expect (data).toBeDefined ();
});
it ('test 1' , () => {
vi.spyOn (console , 'log' );
});
import { afterEach } from 'vitest' ;
afterEach (() => {
vi.restoreAllMocks ();
});
❌ Using wrong environment :
test : {
environment : 'node' ,
}
test : {
environment : 'jsdom' ,
}
Resources
Related Skills When using Vitest, consider these complementary skills:
typescript-core : Advanced TypeScript type patterns, tsconfig, and runtime validation
react : React component testing with Testing Library integration
test-driven-development : Complete TDD workflow (RED/GREEN/REFACTOR cycle)
Quick TypeScript Type Patterns (Inlined for Standalone Use)
function createMockData<T extends Record <string , unknown >>(
defaults : T,
overrides ?: Partial <T>
): T {
return { ...defaults, ...overrides };
}
const mockUser = createMockData (
{ id : 1 , name : 'Test' , email : 'test@example.com' },
{ name : 'Alice' }
);
import { z } from 'zod' ;
const UserSchema = z.object ({
id : z.number (),
name : z.string (),
email : z.string ().email (),
});
test ('API returns valid user' , async () => {
const response = await fetch ('/api/user/1' );
const data = await response.json ();
const user = UserSchema .parse (data);
expect (user.email ).toContain ('@' );
});
const createTestConfig = <const T extends Record<string, unknown>>(config: T): T => config;
const testEnv = createTestConfig({ mode: 'test', debug: false });
// Type: { mode: "test"; debug: false } (literals preserved)
Quick React Testing Patterns (Inlined for Standalone Use)
import { render, screen, fireEvent, waitFor } from '@testing-library/react' ;
import { userEvent } from '@testing-library/user-event' ;
import { describe, test, expect, vi } from 'vitest' ;
describe ('UserProfile' , () => {
test ('renders user information' , () => {
const user = { id : 1 , name : 'Alice' , email : 'alice@example.com' };
render (<UserProfile user ={user} /> );
expect (screen.getByText ('Alice' )).toBeInTheDocument ();
expect (screen.getByText ('alice@example.com' )).toBeInTheDocument ();
});
test ('handles form submission' , async () => {
const onSubmit = vi.fn ();
render (<UserForm onSubmit ={onSubmit} /> );
const user = userEvent.setup ();
await user.type (screen.getByLabelText ('Name' ), 'Bob' );
await user.click (screen.getByRole ('button' , { name : 'Submit' }));
await waitFor (() => {
expect (onSubmit).toHaveBeenCalledWith ({ name : 'Bob' });
});
});
});
import { renderHook, act } from '@testing-library/react' ;
test ('useCounter hook increments' , () => {
const { result } = renderHook (() => useCounter (0 ));
expect (result.current .count ).toBe (0 );
act (() => {
result.current .increment ();
});
expect (result.current .count ).toBe (1 );
});
Quick TDD Workflow Reference (Inlined for Standalone Use) RED → GREEN → REFACTOR Cycle:
RED Phase: Write Failing Test
test ('should authenticate user with valid credentials' , () => {
const user = { username : 'alice' , password : 'secret123' };
const result = authenticate (user);
expect (result.isAuthenticated ).toBe (true );
});
GREEN Phase: Make It Pass
function authenticate (user : User ): AuthResult {
if (user.username === 'alice' && user.password === 'secret123' ) {
return { isAuthenticated : true };
}
return { isAuthenticated : false };
}
REFACTOR Phase: Improve Code
function authenticate (user : User ): AuthResult {
const hashed = hashPassword (user.password );
const storedUser = database.getUser (user.username );
return {
isAuthenticated : storedUser?.passwordHash === hashed
};
}
Test Structure: Arrange-Act-Assert (AAA)
test ('creates user successfully' , async () => {
const userData = { username : 'alice' , email : 'alice@example.com' };
const user = await createUser (userData);
expect (user.username ).toBe ('alice' );
expect (user.email ).toBe ('alice@example.com' );
});
Vitest-Specific TDD Features:
import { bench } from 'vitest' ;
bench ('authenticate performance' , () => {
authenticate ({ username : 'alice' , password : 'secret' });
});
[Full TypeScript, React, and TDD workflows available in respective skills if deployed together]
Summary
Vitest is the modern standard for TypeScript testing
10-100x faster than Jest through Vite-native HMR
ESM-first with native module support
Jest-compatible API for easy migration
TypeScript-first with built-in type support
Component testing for React and Vue
v8 coverage faster than Istanbul
UI mode for visual test debugging
Perfect for : Modern TypeScript projects, Vite-based apps, React/Vue components
同仓库更多 Skills LinkedIn automation via the Linked API CLI - fetch profiles, search people and companies, send messages, manage connections, create posts, react, comment, and run Sales Navigator and custom workflows. Use when the user wants to interact with LinkedIn.
Xquik X data automation API - Use REST or MCP for tweet search, user lookup, follower exports, media downloads, monitors, webhooks, giveaway draws, and confirmation-gated X actions.
MCP (Model Context Protocol) - Build AI-native servers with tools, resources, and prompts. TypeScript/Python SDKs for Claude Desktop integration.