@martinffx/atelier 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +94 -253
- package/package.json +1 -1
- package/skills/{spec-orchestrator → atelier-orchestrator}/SKILL.md +3 -3
- package/skills/atelier-setup/SKILL.md +80 -0
- package/skills/code-review/references/reviewers.md +3 -3
- package/skills/code-review/references/rq.md +6 -6
- package/skills/spec-brainstorm/SKILL.md +5 -5
- package/skills/spec-implement/SKILL.md +2 -3
- package/skills/spec-plan/SKILL.md +21 -29
- package/skills/spec-plan/references/plan_template.md +77 -0
- package/skills/python-architecture/SKILL.md +0 -148
- package/skills/python-architecture/references/data-modeling.md +0 -558
- package/skills/python-architecture/references/ddd.md +0 -569
- package/skills/python-architecture/references/functional-core.md +0 -337
- package/skills/python-build-tools/SKILL.md +0 -153
- package/skills/python-build-tools/references/basedpyright.md +0 -321
- package/skills/python-build-tools/references/ruff.md +0 -225
- package/skills/python-build-tools/references/uv.md +0 -257
- package/skills/python-fastapi/SKILL.md +0 -184
- package/skills/python-fastapi/references/api-design.md +0 -563
- package/skills/python-fastapi/references/dependencies.md +0 -479
- package/skills/python-fastapi/references/middleware.md +0 -475
- package/skills/python-fastapi/references/validation.md +0 -497
- package/skills/python-modern-python/SKILL.md +0 -201
- package/skills/python-modern-python/references/async.md +0 -76
- package/skills/python-modern-python/references/pattern-matching.md +0 -89
- package/skills/python-modern-python/references/typing.md +0 -96
- package/skills/python-monorepo/SKILL.md +0 -146
- package/skills/python-monorepo/references/docker.md +0 -515
- package/skills/python-monorepo/references/namespace-packages.md +0 -426
- package/skills/python-monorepo/references/workspace-config.md +0 -341
- package/skills/python-sqlalchemy/SKILL.md +0 -119
- package/skills/python-sqlalchemy/references/async.md +0 -51
- package/skills/python-sqlalchemy/references/models.md +0 -67
- package/skills/python-sqlalchemy/references/queries.md +0 -57
- package/skills/python-temporal/SKILL.md +0 -128
- package/skills/python-temporal/references/patterns.md +0 -87
- package/skills/python-temporal/references/testing.md +0 -54
- package/skills/python-testing/SKILL.md +0 -161
- package/skills/python-testing/references/boundaries.md +0 -449
- package/skills/python-testing/references/mocking.md +0 -449
- package/skills/python-testing/references/pytest.md +0 -524
- package/skills/typescript-api-design/SKILL.md +0 -396
- package/skills/typescript-api-design/references/error-responses.md +0 -469
- package/skills/typescript-build-tools/SKILL.md +0 -447
- package/skills/typescript-build-tools/references/biome.md +0 -436
- package/skills/typescript-build-tools/references/bun.md +0 -432
- package/skills/typescript-build-tools/references/turborepo.md +0 -426
- package/skills/typescript-build-tools/references/vitest.md +0 -518
- package/skills/typescript-drizzle-orm/SKILL.md +0 -398
- package/skills/typescript-drizzle-orm/references/cloudflare.md +0 -392
- package/skills/typescript-drizzle-orm/references/entity-pattern.md +0 -412
- package/skills/typescript-drizzle-orm/references/postgresql.md +0 -191
- package/skills/typescript-drizzle-orm/references/repository-pattern.md +0 -479
- package/skills/typescript-drizzle-orm/references/sqlite.md +0 -291
- package/skills/typescript-dynamodb-toolbox/SKILL.md +0 -370
- package/skills/typescript-dynamodb-toolbox/references/entity-layer.md +0 -574
- package/skills/typescript-dynamodb-toolbox/references/error-handling.md +0 -495
- package/skills/typescript-dynamodb-toolbox/references/modeling.md +0 -332
- package/skills/typescript-dynamodb-toolbox/references/repository-layer.md +0 -631
- package/skills/typescript-dynamodb-toolbox/references/testing.md +0 -718
- package/skills/typescript-dynamodb-toolbox/references/transactions.md +0 -423
- package/skills/typescript-effect-ts/SKILL.md +0 -341
- package/skills/typescript-effect-ts/references/core.md +0 -412
- package/skills/typescript-effect-ts/references/error-handling.md +0 -468
- package/skills/typescript-effect-ts/references/resources.md +0 -476
- package/skills/typescript-effect-ts/references/schema.md +0 -536
- package/skills/typescript-effect-ts/references/services.md +0 -461
- package/skills/typescript-fastify/SKILL.md +0 -405
- package/skills/typescript-fastify/references/plugins.md +0 -329
- package/skills/typescript-fastify/references/typeid.md +0 -315
- package/skills/typescript-functional-patterns/SKILL.md +0 -402
- package/skills/typescript-functional-patterns/references/adts.md +0 -497
- package/skills/typescript-functional-patterns/references/branded-types.md +0 -542
- package/skills/typescript-functional-patterns/references/migration-guide.md +0 -695
- package/skills/typescript-functional-patterns/references/option-result.md +0 -585
- package/skills/typescript-testing/SKILL.md +0 -353
- package/skills/typescript-testing/references/mocking.md +0 -675
- package/skills/typescript-testing/references/msw.md +0 -852
- package/skills/typescript-testing/references/snapshot-testing.md +0 -774
|
@@ -1,518 +0,0 @@
|
|
|
1
|
-
# Advanced Vitest Patterns
|
|
2
|
-
|
|
3
|
-
Detailed Vitest configuration patterns for complex setups including workspaces, benchmarks, and database testing.
|
|
4
|
-
|
|
5
|
-
## Workspace Configuration
|
|
6
|
-
|
|
7
|
-
Use workspaces when you need different test configurations (e.g., unit tests vs integration tests with different parallelism).
|
|
8
|
-
|
|
9
|
-
### vitest.workspace.ts
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
import { defineWorkspace } from 'vitest/config'
|
|
13
|
-
|
|
14
|
-
export default defineWorkspace([
|
|
15
|
-
{
|
|
16
|
-
extends: './vitest.config.ts',
|
|
17
|
-
test: {
|
|
18
|
-
name: 'unit',
|
|
19
|
-
include: ['src/**/*.test.ts'],
|
|
20
|
-
exclude: ['src/**/*.repo.test.ts'],
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
extends: './vitest.config.ts',
|
|
25
|
-
test: {
|
|
26
|
-
name: 'repo',
|
|
27
|
-
include: ['src/**/*.repo.test.ts'],
|
|
28
|
-
fileParallelism: false, // Sequential for DB tests
|
|
29
|
-
testTimeout: 30000,
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
])
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Running Specific Workspaces
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
# Run all workspaces
|
|
39
|
-
vitest run
|
|
40
|
-
|
|
41
|
-
# Run specific workspace
|
|
42
|
-
vitest run --project unit
|
|
43
|
-
vitest run --project repo
|
|
44
|
-
|
|
45
|
-
# Run in watch mode
|
|
46
|
-
vitest --project unit
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Benchmark Configuration
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
// vitest.config.benchmark.ts
|
|
53
|
-
import { defineConfig } from 'vitest/config'
|
|
54
|
-
import tsconfigPaths from 'vite-tsconfig-paths'
|
|
55
|
-
|
|
56
|
-
export default defineConfig({
|
|
57
|
-
plugins: [tsconfigPaths()],
|
|
58
|
-
test: {
|
|
59
|
-
benchmark: {
|
|
60
|
-
include: ['src/**/*.bench.ts'],
|
|
61
|
-
reporters: ['default'],
|
|
62
|
-
},
|
|
63
|
-
testTimeout: 120000, // 2 minutes for benchmarks
|
|
64
|
-
},
|
|
65
|
-
})
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### Benchmark Example
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
// src/utils/hash.bench.ts
|
|
72
|
-
import { bench, describe } from 'vitest'
|
|
73
|
-
import { hashPassword, verifyPassword } from './hash'
|
|
74
|
-
|
|
75
|
-
describe('password hashing', () => {
|
|
76
|
-
bench('hashPassword', async () => {
|
|
77
|
-
await hashPassword('test-password-123')
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
bench('verifyPassword', async () => {
|
|
81
|
-
const hash = await hashPassword('test-password-123')
|
|
82
|
-
await verifyPassword('test-password-123', hash)
|
|
83
|
-
})
|
|
84
|
-
})
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Running Benchmarks
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
# Run benchmarks
|
|
91
|
-
vitest bench
|
|
92
|
-
|
|
93
|
-
# Run with specific config
|
|
94
|
-
vitest bench --config vitest.config.benchmark.ts
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Database Test Setup
|
|
98
|
-
|
|
99
|
-
### Global Setup for Migrations
|
|
100
|
-
|
|
101
|
-
```typescript
|
|
102
|
-
// test/global-setup.ts
|
|
103
|
-
import { drizzle } from 'drizzle-orm/bun-sqlite'
|
|
104
|
-
import { migrate } from 'drizzle-orm/bun-sqlite/migrator'
|
|
105
|
-
import { Database } from 'bun:sqlite'
|
|
106
|
-
|
|
107
|
-
export async function setup() {
|
|
108
|
-
const sqlite = new Database(':memory:')
|
|
109
|
-
const db = drizzle(sqlite)
|
|
110
|
-
|
|
111
|
-
console.log('Running migrations...')
|
|
112
|
-
migrate(db, { migrationsFolder: './drizzle' })
|
|
113
|
-
|
|
114
|
-
// Store for use in tests
|
|
115
|
-
globalThis.__TEST_DB__ = db
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export async function teardown() {
|
|
119
|
-
globalThis.__TEST_DB__?.close()
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### Per-Test Setup
|
|
124
|
-
|
|
125
|
-
```typescript
|
|
126
|
-
// test/setup.ts
|
|
127
|
-
import { beforeEach, afterEach } from 'vitest'
|
|
128
|
-
import { users } from '../src/schema'
|
|
129
|
-
|
|
130
|
-
beforeEach(async () => {
|
|
131
|
-
// Reset database state before each test
|
|
132
|
-
await globalThis.__TEST_DB__.delete(users)
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
afterEach(async () => {
|
|
136
|
-
// Cleanup after each test
|
|
137
|
-
})
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### Using in Tests
|
|
141
|
-
|
|
142
|
-
```typescript
|
|
143
|
-
// src/users.test.ts
|
|
144
|
-
import { describe, it, expect } from 'vitest'
|
|
145
|
-
import { UserRepo } from './UserRepo'
|
|
146
|
-
|
|
147
|
-
describe('UserRepo', () => {
|
|
148
|
-
it('creates a user', async () => {
|
|
149
|
-
const db = globalThis.__TEST_DB__
|
|
150
|
-
const repo = new UserRepo(db)
|
|
151
|
-
|
|
152
|
-
const user = await repo.create({
|
|
153
|
-
name: 'Alice',
|
|
154
|
-
email: 'alice@example.com',
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
expect(user.id).toBeDefined()
|
|
158
|
-
expect(user.name).toBe('Alice')
|
|
159
|
-
})
|
|
160
|
-
})
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
## Coverage Configuration
|
|
164
|
-
|
|
165
|
-
```typescript
|
|
166
|
-
// vitest.config.ts
|
|
167
|
-
import { defineConfig } from 'vitest/config'
|
|
168
|
-
|
|
169
|
-
export default defineConfig({
|
|
170
|
-
test: {
|
|
171
|
-
coverage: {
|
|
172
|
-
provider: 'v8',
|
|
173
|
-
reporter: ['text', 'json', 'html', 'lcov'],
|
|
174
|
-
include: ['src/**/*.ts'],
|
|
175
|
-
exclude: [
|
|
176
|
-
'src/**/*.test.ts',
|
|
177
|
-
'src/**/*.bench.ts',
|
|
178
|
-
'src/types/**',
|
|
179
|
-
'src/**/*.d.ts',
|
|
180
|
-
],
|
|
181
|
-
thresholds: {
|
|
182
|
-
lines: 80,
|
|
183
|
-
functions: 80,
|
|
184
|
-
branches: 80,
|
|
185
|
-
statements: 80,
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
},
|
|
189
|
-
})
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### Running Coverage
|
|
193
|
-
|
|
194
|
-
```bash
|
|
195
|
-
# Run tests with coverage
|
|
196
|
-
vitest run --coverage
|
|
197
|
-
|
|
198
|
-
# Generate coverage report
|
|
199
|
-
vitest run --coverage --reporter=html
|
|
200
|
-
|
|
201
|
-
# Fail if coverage below threshold
|
|
202
|
-
vitest run --coverage --coverage.thresholds.lines=80
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
## Cloudflare Workers Pool
|
|
206
|
-
|
|
207
|
-
For testing Cloudflare Workers and Durable Objects:
|
|
208
|
-
|
|
209
|
-
```typescript
|
|
210
|
-
// vitest.config.ts
|
|
211
|
-
import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config'
|
|
212
|
-
|
|
213
|
-
export default defineWorkersConfig({
|
|
214
|
-
test: {
|
|
215
|
-
globals: true,
|
|
216
|
-
pool: '@cloudflare/vitest-pool-workers',
|
|
217
|
-
poolOptions: {
|
|
218
|
-
workers: {
|
|
219
|
-
wrangler: { configPath: './wrangler.jsonc' },
|
|
220
|
-
miniflare: {
|
|
221
|
-
compatibilityDate: '2024-11-01',
|
|
222
|
-
compatibilityFlags: ['nodejs_compat'],
|
|
223
|
-
},
|
|
224
|
-
},
|
|
225
|
-
},
|
|
226
|
-
},
|
|
227
|
-
})
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
### Test Helper for Durable Objects
|
|
231
|
-
|
|
232
|
-
```typescript
|
|
233
|
-
// test/helpers.ts
|
|
234
|
-
import { env, runInDurableObject } from 'cloudflare:test'
|
|
235
|
-
import { drizzle } from 'drizzle-orm/durable-sqlite'
|
|
236
|
-
import * as schema from '../src/schema'
|
|
237
|
-
|
|
238
|
-
export async function withTestDB<T>(
|
|
239
|
-
fn: (db: ReturnType<typeof drizzle>) => Promise<T>
|
|
240
|
-
): Promise<T> {
|
|
241
|
-
const id = env.USER_LEDGER.newUniqueId()
|
|
242
|
-
const stub = env.USER_LEDGER.get(id)
|
|
243
|
-
|
|
244
|
-
return runInDurableObject(stub, async (_instance, state) => {
|
|
245
|
-
const db = drizzle(state.storage, { schema })
|
|
246
|
-
return fn(db)
|
|
247
|
-
})
|
|
248
|
-
}
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
### Using in Tests
|
|
252
|
-
|
|
253
|
-
```typescript
|
|
254
|
-
// src/ledger.test.ts
|
|
255
|
-
import { describe, it, expect } from 'vitest'
|
|
256
|
-
import { withTestDB } from '../test/helpers'
|
|
257
|
-
import { LedgerRepo } from './LedgerRepo'
|
|
258
|
-
|
|
259
|
-
describe('LedgerRepo', () => {
|
|
260
|
-
it('creates a ledger', async () => {
|
|
261
|
-
await withTestDB(async (db) => {
|
|
262
|
-
const repo = new LedgerRepo(db)
|
|
263
|
-
const ledger = await repo.create({ name: 'Test Ledger' })
|
|
264
|
-
|
|
265
|
-
expect(ledger.id).toBeDefined()
|
|
266
|
-
expect(ledger.name).toBe('Test Ledger')
|
|
267
|
-
})
|
|
268
|
-
})
|
|
269
|
-
})
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
## Snapshot Testing
|
|
273
|
-
|
|
274
|
-
```typescript
|
|
275
|
-
// user.test.ts
|
|
276
|
-
import { test, expect } from 'vitest'
|
|
277
|
-
import { UserEntity } from './UserEntity'
|
|
278
|
-
|
|
279
|
-
test('user response matches snapshot', () => {
|
|
280
|
-
const user = UserEntity.fromRequest({
|
|
281
|
-
name: 'Alice',
|
|
282
|
-
email: 'alice@example.com',
|
|
283
|
-
})
|
|
284
|
-
|
|
285
|
-
expect(user.toResponse()).toMatchSnapshot()
|
|
286
|
-
})
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
### Updating Snapshots
|
|
290
|
-
|
|
291
|
-
```bash
|
|
292
|
-
# Update all snapshots
|
|
293
|
-
vitest run -u
|
|
294
|
-
|
|
295
|
-
# Update snapshots for specific file
|
|
296
|
-
vitest run -u src/users.test.ts
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
## Mock Patterns
|
|
300
|
-
|
|
301
|
-
### Module Mocking
|
|
302
|
-
|
|
303
|
-
```typescript
|
|
304
|
-
import { vi, test, expect, beforeEach } from 'vitest'
|
|
305
|
-
import { sendEmail } from './email'
|
|
306
|
-
import { createUser } from './users'
|
|
307
|
-
|
|
308
|
-
vi.mock('./email', () => ({
|
|
309
|
-
sendEmail: vi.fn().mockResolvedValue({ success: true }),
|
|
310
|
-
}))
|
|
311
|
-
|
|
312
|
-
beforeEach(() => {
|
|
313
|
-
vi.clearAllMocks()
|
|
314
|
-
})
|
|
315
|
-
|
|
316
|
-
test('sends welcome email', async () => {
|
|
317
|
-
await createUser({ name: 'Alice', email: 'alice@example.com' })
|
|
318
|
-
|
|
319
|
-
expect(sendEmail).toHaveBeenCalledWith({
|
|
320
|
-
to: 'alice@example.com',
|
|
321
|
-
subject: 'Welcome!',
|
|
322
|
-
})
|
|
323
|
-
})
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
### Spy on Functions
|
|
327
|
-
|
|
328
|
-
```typescript
|
|
329
|
-
import { vi, test, expect } from 'vitest'
|
|
330
|
-
|
|
331
|
-
test('logs errors', async () => {
|
|
332
|
-
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
333
|
-
|
|
334
|
-
await processItem(invalidItem)
|
|
335
|
-
|
|
336
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
337
|
-
expect.stringContaining('Invalid item')
|
|
338
|
-
)
|
|
339
|
-
|
|
340
|
-
consoleSpy.mockRestore()
|
|
341
|
-
})
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
### Mock Timers
|
|
345
|
-
|
|
346
|
-
```typescript
|
|
347
|
-
import { vi, test, expect } from 'vitest'
|
|
348
|
-
|
|
349
|
-
test('delays execution', async () => {
|
|
350
|
-
vi.useFakeTimers()
|
|
351
|
-
|
|
352
|
-
const callback = vi.fn()
|
|
353
|
-
setTimeout(callback, 1000)
|
|
354
|
-
|
|
355
|
-
// Fast-forward time
|
|
356
|
-
vi.advanceTimersByTime(1000)
|
|
357
|
-
|
|
358
|
-
expect(callback).toHaveBeenCalled()
|
|
359
|
-
|
|
360
|
-
vi.useRealTimers()
|
|
361
|
-
})
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
## Filtering Tests
|
|
365
|
-
|
|
366
|
-
### Run Specific Tests
|
|
367
|
-
|
|
368
|
-
```bash
|
|
369
|
-
# Run specific test file
|
|
370
|
-
vitest src/users.test.ts
|
|
371
|
-
|
|
372
|
-
# Run tests matching pattern
|
|
373
|
-
vitest --grep "UserRepo"
|
|
374
|
-
|
|
375
|
-
# Skip tests matching pattern
|
|
376
|
-
vitest --grep -v "integration"
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
### Test-Only and Skip
|
|
380
|
-
|
|
381
|
-
```typescript
|
|
382
|
-
import { describe, it, test } from 'vitest'
|
|
383
|
-
|
|
384
|
-
describe('UserRepo', () => {
|
|
385
|
-
// Only run this test
|
|
386
|
-
it.only('creates a user', async () => {
|
|
387
|
-
// ...
|
|
388
|
-
})
|
|
389
|
-
|
|
390
|
-
// Skip this test
|
|
391
|
-
it.skip('updates a user', async () => {
|
|
392
|
-
// ...
|
|
393
|
-
})
|
|
394
|
-
|
|
395
|
-
// Run if condition is true
|
|
396
|
-
it.runIf(process.env.CI)('runs in CI', async () => {
|
|
397
|
-
// ...
|
|
398
|
-
})
|
|
399
|
-
|
|
400
|
-
// Skip if condition is true
|
|
401
|
-
it.skipIf(process.platform === 'win32')('runs on Unix', async () => {
|
|
402
|
-
// ...
|
|
403
|
-
})
|
|
404
|
-
})
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
## Parallelism Control
|
|
408
|
-
|
|
409
|
-
### Disable File Parallelism
|
|
410
|
-
|
|
411
|
-
```typescript
|
|
412
|
-
// vitest.config.ts
|
|
413
|
-
import { defineConfig } from 'vitest/config'
|
|
414
|
-
|
|
415
|
-
export default defineConfig({
|
|
416
|
-
test: {
|
|
417
|
-
fileParallelism: false, // Run test files sequentially
|
|
418
|
-
},
|
|
419
|
-
})
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
### Configure Max Threads
|
|
423
|
-
|
|
424
|
-
```typescript
|
|
425
|
-
// vitest.config.ts
|
|
426
|
-
import { defineConfig } from 'vitest/config'
|
|
427
|
-
|
|
428
|
-
export default defineConfig({
|
|
429
|
-
test: {
|
|
430
|
-
pool: 'threads',
|
|
431
|
-
poolOptions: {
|
|
432
|
-
threads: {
|
|
433
|
-
maxThreads: 4,
|
|
434
|
-
minThreads: 1,
|
|
435
|
-
},
|
|
436
|
-
},
|
|
437
|
-
},
|
|
438
|
-
})
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
## Test Retries
|
|
442
|
-
|
|
443
|
-
```typescript
|
|
444
|
-
// vitest.config.ts
|
|
445
|
-
import { defineConfig } from 'vitest/config'
|
|
446
|
-
|
|
447
|
-
export default defineConfig({
|
|
448
|
-
test: {
|
|
449
|
-
retry: 2, // Retry failed tests up to 2 times
|
|
450
|
-
},
|
|
451
|
-
})
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
### Per-Test Retries
|
|
455
|
-
|
|
456
|
-
```typescript
|
|
457
|
-
import { it } from 'vitest'
|
|
458
|
-
|
|
459
|
-
it('flaky test', { retry: 3 }, async () => {
|
|
460
|
-
// Test that might fail occasionally
|
|
461
|
-
})
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
## Debugging Tests
|
|
465
|
-
|
|
466
|
-
### VSCode Launch Config
|
|
467
|
-
|
|
468
|
-
```json
|
|
469
|
-
{
|
|
470
|
-
"version": "0.2.0",
|
|
471
|
-
"configurations": [
|
|
472
|
-
{
|
|
473
|
-
"type": "node",
|
|
474
|
-
"request": "launch",
|
|
475
|
-
"name": "Debug Vitest Tests",
|
|
476
|
-
"runtimeExecutable": "bun",
|
|
477
|
-
"runtimeArgs": ["run", "vitest", "run"],
|
|
478
|
-
"console": "integratedTerminal",
|
|
479
|
-
"internalConsoleOptions": "neverOpen"
|
|
480
|
-
}
|
|
481
|
-
]
|
|
482
|
-
}
|
|
483
|
-
```
|
|
484
|
-
|
|
485
|
-
### Run with Debugging
|
|
486
|
-
|
|
487
|
-
```bash
|
|
488
|
-
# Run tests with debugger
|
|
489
|
-
vitest --inspect-brk
|
|
490
|
-
|
|
491
|
-
# Run specific test with debugger
|
|
492
|
-
vitest --inspect-brk src/users.test.ts
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
## UI Mode
|
|
496
|
-
|
|
497
|
-
```bash
|
|
498
|
-
# Run tests in UI mode
|
|
499
|
-
vitest --ui
|
|
500
|
-
|
|
501
|
-
# Run with specific port
|
|
502
|
-
vitest --ui --port 5173
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
## Best Practices
|
|
506
|
-
|
|
507
|
-
1. **Separate unit and integration tests** with workspace configs
|
|
508
|
-
2. **Disable file parallelism** for database tests (`fileParallelism: false`)
|
|
509
|
-
3. **Use global setup** for one-time migrations
|
|
510
|
-
4. **Use setup files** for per-test reset
|
|
511
|
-
5. **Set appropriate timeouts** - 30s for DB tests, 2min for benchmarks
|
|
512
|
-
6. **Use V8 provider** for coverage - more accurate than Istanbul
|
|
513
|
-
7. **Configure coverage thresholds** to prevent regression
|
|
514
|
-
8. **Use snapshots sparingly** - only for complex output structures
|
|
515
|
-
9. **Mock external services** - email, third-party APIs
|
|
516
|
-
10. **Clean up after tests** - delete created records, restore mocks
|
|
517
|
-
11. **Use workspace separation** for tests that need different environments
|
|
518
|
-
12. **Name test files descriptively** - `*.test.ts` for unit, `*.repo.test.ts` for DB
|