Next generation testing framework powered by Vite
npx @tessl/cli install tessl/npm-vitest@4.0.00
# Vitest
1
2
Vitest is a blazing fast unit test framework powered by Vite with native ES modules support, TypeScript integration, and Jest-compatible APIs.
3
4
## Package Information
5
6
- **Package**: `vitest` (npm)
7
- **Install**: `npm install -D vitest`
8
- **Docs**: https://vitest.dev
9
10
## Quick Start
11
12
```typescript
13
import { test, describe, expect, vi, beforeEach, afterEach } from 'vitest';
14
15
// Basic test
16
test('adds numbers', () => {
17
expect(1 + 2).toBe(3);
18
});
19
20
// Suite with lifecycle
21
describe('Math', () => {
22
beforeEach(() => { /* setup */ });
23
afterEach(() => { /* cleanup */ });
24
25
test('multiply', () => expect(2 * 3).toBe(6));
26
});
27
28
// Async test
29
test('async operation', async () => {
30
await expect(Promise.resolve(42)).resolves.toBe(42);
31
});
32
33
// Mock function
34
test('with mock', () => {
35
const fn = vi.fn(() => 'result');
36
expect(fn()).toBe('result');
37
expect(fn).toHaveBeenCalledTimes(1);
38
});
39
```
40
41
## Entry Points
42
43
| Import | Use Case |
44
|--------|----------|
45
| `vitest` | Test APIs (test, expect, vi, etc.) |
46
| `vitest/config` | Configuration (defineConfig, defineProject) |
47
| `vitest/node` | Programmatic APIs (createVitest, reporters) |
48
| `vitest/reporters` | Reporter classes |
49
| `vitest/browser` | Browser testing utilities |
50
51
## Core Imports
52
53
```typescript
54
// ESM
55
import { test, describe, expect, vi, beforeEach, afterEach } from 'vitest';
56
57
// Globals (with globals: true in config)
58
test('no import needed', () => expect(true).toBe(true));
59
```
60
61
## API Quick Reference
62
63
### Test Definition → [Details](./test-definition.md)
64
65
```typescript { .api }
66
function test(name: string, fn: TestFunction, options?: TestOptions): void;
67
function describe(name: string, fn: () => void, options?: TestOptions): void;
68
69
// Modifiers
70
test.only | test.skip | test.todo | test.skipIf(cond) | test.runIf(cond)
71
test.concurrent | test.sequential | test.fails | test.each(cases)
72
73
// Lifecycle
74
function beforeEach(fn: () => void | Promise<void>, timeout?: number): void;
75
function afterEach(fn: () => void | Promise<void>, timeout?: number): void;
76
function beforeAll(fn: () => void | Promise<void>, timeout?: number): void;
77
function afterAll(fn: () => void | Promise<void>, timeout?: number): void;
78
```
79
80
### Assertions → [Details](./assertions.md)
81
82
```typescript { .api }
83
function expect<T>(actual: T): Assertion<T>;
84
function createExpect(test?: TaskPopulated): ExpectStatic;
85
86
// Key methods
87
.toBe() | .toEqual() | .toStrictEqual()
88
.toBeTruthy() | .toBeFalsy() | .toBeDefined() | .toBeUndefined()
89
.toBeGreaterThan() | .toBeLessThan() | .toBeCloseTo()
90
.toMatch() | .toContain() | .toHaveLength() | .toHaveProperty()
91
.toThrow() | .toMatchObject()
92
.resolves | .rejects | .not
93
94
// Snapshots
95
.toMatchSnapshot() | .toMatchInlineSnapshot() | .toMatchFileSnapshot()
96
97
// Async
98
expect.poll(fn, options) | expect.soft(value)
99
```
100
101
### Mocking → [Details](./mocking.md)
102
103
```typescript { .api }
104
vi.fn(impl?) // Create mock function
105
vi.spyOn(obj, method, accessType?) // Spy on method
106
vi.mock(path, factory?) // Mock module (hoisted)
107
vi.doMock(path, factory?) // Mock module (not hoisted)
108
vi.importActual(path) | vi.importMock(path)
109
vi.mocked(item, deep?) | vi.mockObject(obj, options?)
110
111
// Cleanup
112
vi.clearAllMocks() | vi.resetAllMocks() | vi.restoreAllMocks()
113
114
// Globals
115
vi.stubGlobal(name, value) | vi.stubEnv(name, value)
116
vi.unstubAllGlobals() | vi.unstubAllEnvs()
117
118
// Wait utilities
119
vi.waitFor(callback, options?) | vi.waitUntil(callback, options?)
120
```
121
122
### Timers → [Details](./timers.md)
123
124
```typescript { .api }
125
vi.useFakeTimers(config?) | vi.useRealTimers()
126
vi.advanceTimersByTime(ms) | vi.advanceTimersToNextTimer()
127
vi.runOnlyPendingTimers() | vi.runAllTimers() | vi.runAllTicks()
128
vi.setSystemTime(time) | vi.getMockedSystemTime() | vi.getRealSystemTime()
129
vi.getTimerCount() | vi.clearAllTimers()
130
```
131
132
### Configuration → [Details](./configuration.md)
133
134
```typescript { .api }
135
import { defineConfig, defineProject } from 'vitest/config';
136
137
export default defineConfig({
138
test: {
139
globals: boolean;
140
environment: 'node' | 'jsdom' | 'happy-dom' | 'edge-runtime';
141
include: string[];
142
exclude: string[];
143
testTimeout: number;
144
hookTimeout: number;
145
setupFiles: string | string[];
146
coverage: CoverageOptions;
147
reporters: Array<Reporter>;
148
}
149
});
150
```
151
152
## Common Patterns
153
154
### Test Organization
155
156
| Pattern | Code | Use When |
157
|---------|------|----------|
158
| Single test | `test('name', () => {...})` | Simple, isolated test |
159
| Test suite | `describe('name', () => {...})` | Grouping related tests |
160
| Nested suites | `describe('A', () => describe('B', ...))` | Hierarchical organization |
161
| Shared setup | `beforeEach(() => {...})` | Common test setup |
162
163
### Assertion Patterns
164
165
| Goal | Matcher | Example |
166
|------|---------|---------|
167
| Exact equality | `.toBe()` | `expect(x).toBe(5)` |
168
| Deep equality | `.toEqual()` | `expect(obj).toEqual({a: 1})` |
169
| Truthiness | `.toBeTruthy()` | `expect(value).toBeTruthy()` |
170
| Array contains | `.toContain()` | `expect([1,2]).toContain(1)` |
171
| Object has prop | `.toHaveProperty()` | `expect(obj).toHaveProperty('key')` |
172
| Throws error | `.toThrow()` | `expect(() => fn()).toThrow()` |
173
| Async success | `.resolves` | `expect(promise).resolves.toBe(x)` |
174
| Async failure | `.rejects` | `expect(promise).rejects.toThrow()` |
175
176
### Mocking Strategies
177
178
| Scenario | Approach | Code |
179
|----------|----------|------|
180
| Track calls | Mock function | `const fn = vi.fn()` |
181
| Keep original | Spy | `vi.spyOn(obj, 'method')` |
182
| Replace module | Module mock | `vi.mock('./module')` |
183
| Partial mock | Import actual + mock | `await vi.importActual()` |
184
| Global APIs | Stub global | `vi.stubGlobal('fetch', mockFetch)` |
185
186
### Time Control
187
188
| Need | Method | Use Case |
189
|------|--------|----------|
190
| Control time | `vi.useFakeTimers()` | Deterministic testing |
191
| Jump forward | `vi.advanceTimersByTime(ms)` | Skip delays |
192
| Next timer | `vi.advanceTimersToNextTimer()` | Step through |
193
| Run all | `vi.runAllTimers()` | Complete all async |
194
| Set date | `vi.setSystemTime(date)` | Mock Date.now() |
195
196
## Advanced Features
197
198
### Benchmarking → [Details](./benchmarking.md)
199
200
```typescript
201
import { bench } from 'vitest';
202
203
bench('operation', () => {
204
// Code to benchmark
205
}, { time: 5000, iterations: 100 });
206
```
207
208
### Type Testing → [Details](./type-testing.md)
209
210
```typescript
211
import { expectTypeOf, assertType } from 'vitest';
212
213
expectTypeOf<string>().toBeString();
214
expectTypeOf(fn).returns.toBeNumber();
215
assertType<number>(value);
216
```
217
218
### Browser Testing → [Details](./browser-testing.md)
219
220
```typescript
221
import { readFile, writeFile } from 'vitest/browser';
222
223
test('browser APIs', async () => {
224
await writeFile('./test.txt', 'content');
225
expect(await readFile('./test.txt')).toBe('content');
226
});
227
```
228
229
### Reporters → [Details](./reporters.md)
230
231
Built-in: `default`, `verbose`, `dot`, `tree`, `json`, `junit`, `tap`, `github-actions`
232
233
```typescript
234
export default defineConfig({
235
test: {
236
reporters: ['default', 'json'],
237
outputFile: './results.json'
238
}
239
});
240
```
241
242
### Node APIs → [Details](./node-apis.md)
243
244
```typescript
245
import { createVitest } from 'vitest/node';
246
247
const vitest = await createVitest('test', { watch: false });
248
await vitest.start();
249
await vitest.close();
250
```
251
252
## Configuration Defaults
253
254
```typescript
255
configDefaults.include // ['**/*.{test,spec}.?(c|m)[jt]s?(x)']
256
configDefaults.exclude // ['**/node_modules/**', '**/dist/**', ...]
257
defaultBrowserPort // 63315
258
```
259
260
## Decision Guides
261
262
### When to Use
263
264
| Feature | Choose When |
265
|---------|-------------|
266
| `test.only` | Debugging specific test |
267
| `test.skip` | Temporarily disable test |
268
| `test.concurrent` | Independent tests that can run in parallel |
269
| `test.sequential` | Tests with shared state |
270
| `describe.skip` | Disable entire suite |
271
| `beforeEach` | Setup needed for every test |
272
| `beforeAll` | Expensive setup once per suite |
273
274
### Mocking Decision Tree
275
276
```
277
Need to track calls?
278
├─ Yes, keep original behavior?
279
│ └─ Yes: vi.spyOn(obj, 'method')
280
│ └─ No: vi.fn(newImpl)
281
└─ No, replace entire module?
282
└─ Yes: vi.mock('./module')
283
└─ No: Use real implementation
284
```
285
286
### Environment Selection
287
288
| Environment | Use Case | APIs Available |
289
|-------------|----------|----------------|
290
| `node` | Server code, CLI tools | Node.js APIs |
291
| `jsdom` | Browser simulation | DOM, window, document |
292
| `happy-dom` | Faster browser simulation | DOM (lighter) |
293
| `edge-runtime` | Edge functions | Subset of Web APIs |
294
| Browser mode | Real browser testing | Full browser APIs |
295
296
## Common Gotchas
297
298
1. **Module mocks are hoisted** - `vi.mock()` runs before imports
299
2. **Use `vi.hoisted()` for shared mock values**
300
3. **`vi.mock()` is hoisted, `vi.doMock()` is not**
301
4. **Restore mocks** - Use `afterEach(() => vi.restoreAllMocks())`
302
5. **Async timers** - Use `*Async()` versions with async code
303
6. **Globals require config** - Set `globals: true` in config
304
305
## Additional Exports
306
307
```typescript
308
inject<T>(key: string | symbol): T // Dependency injection
309
chai, assert, should // Chai assertion library
310
```
311