@dfosco/storyboard-core 3.1.2 → 3.3.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/dist/storyboard-ui.css +1 -0
- package/dist/storyboard-ui.js +26298 -0
- package/dist/storyboard-ui.js.map +1 -0
- package/dist/tailwind.css +1 -1
- package/package.json +24 -19
- package/scaffold/manifest.json +35 -0
- package/scaffold/scripts/link.sh +26 -0
- package/scaffold/scripts/unlink.sh +10 -0
- package/scaffold/skills/create/SKILL.md +501 -0
- package/scaffold/skills/storyboard/SKILL.md +360 -0
- package/scaffold/skills/update-storyboard/SKILL.md +16 -0
- package/scaffold/skills/update-storyboard/update-storyboard-packages.sh +26 -0
- package/scaffold/skills/vitest/GENERATION.md +5 -0
- package/scaffold/skills/vitest/SKILL.md +52 -0
- package/scaffold/skills/vitest/references/advanced-environments.md +264 -0
- package/scaffold/skills/vitest/references/advanced-projects.md +300 -0
- package/scaffold/skills/vitest/references/advanced-type-testing.md +237 -0
- package/scaffold/skills/vitest/references/advanced-vi.md +249 -0
- package/scaffold/skills/vitest/references/core-cli.md +166 -0
- package/scaffold/skills/vitest/references/core-config.md +174 -0
- package/scaffold/skills/vitest/references/core-describe.md +193 -0
- package/scaffold/skills/vitest/references/core-expect.md +219 -0
- package/scaffold/skills/vitest/references/core-hooks.md +244 -0
- package/scaffold/skills/vitest/references/core-test-api.md +233 -0
- package/scaffold/skills/vitest/references/features-concurrency.md +250 -0
- package/scaffold/skills/vitest/references/features-context.md +238 -0
- package/scaffold/skills/vitest/references/features-coverage.md +207 -0
- package/scaffold/skills/vitest/references/features-filtering.md +211 -0
- package/scaffold/skills/vitest/references/features-mocking.md +265 -0
- package/scaffold/skills/vitest/references/features-snapshots.md +207 -0
- package/scaffold/skills/worktree/SKILL.md +51 -0
- package/scaffold/storyboard.config.json +26 -0
- package/scaffold/svelte.config.js +1 -0
- package/scaffold/toolbar.config.json +4 -0
- package/src/ActionMenuButton.svelte +1 -1
- package/src/CanvasCreateMenu.svelte +1 -1
- package/src/CoreUIBar.svelte +20 -9
- package/src/CreateMenuButton.svelte +1 -1
- package/src/InspectorPanel.svelte +144 -49
- package/src/SidePanel.svelte +10 -10
- package/src/commandActions.js +1 -1
- package/src/comments/index.js +0 -3
- package/src/devtools.js +4 -1
- package/src/index.js +5 -2
- package/src/inspector/highlighter.js +3 -4
- package/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte +1 -1
- package/src/mountStoryboardCore.js +223 -0
- package/src/scaffold.js +100 -0
- package/src/stores/themeStore.ts +29 -8
- package/src/styles/tailwind.css +16 -0
- package/src/svelte-plugin-ui/components/Viewfinder.svelte +18 -0
- package/src/ui-entry.js +30 -0
- package/src/vite/server-plugin.js +8 -24
- package/src/workshop/features/createCanvas/CreateCanvasForm.svelte +24 -6
- package/src/workshop/features/createFlow/CreateFlowForm.svelte +1 -1
- package/src/workshop/features/createFlow/index.js +0 -1
- package/src/workshop/features/createPrototype/CreatePrototypeForm.svelte +1 -1
- package/src/workshop/features/createPrototype/index.js +0 -1
- /package/{core-ui.config.json → toolbar.config.json} +0 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: type-testing
|
|
3
|
+
description: Test TypeScript types with expectTypeOf and assertType
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Type Testing
|
|
7
|
+
|
|
8
|
+
Test TypeScript types without runtime execution.
|
|
9
|
+
|
|
10
|
+
## Setup
|
|
11
|
+
|
|
12
|
+
Type tests use `.test-d.ts` extension:
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
// math.test-d.ts
|
|
16
|
+
import { expectTypeOf } from 'vitest'
|
|
17
|
+
import { add } from './math'
|
|
18
|
+
|
|
19
|
+
test('add returns number', () => {
|
|
20
|
+
expectTypeOf(add).returns.toBeNumber()
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Configuration
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
defineConfig({
|
|
28
|
+
test: {
|
|
29
|
+
typecheck: {
|
|
30
|
+
enabled: true,
|
|
31
|
+
|
|
32
|
+
// Only type check
|
|
33
|
+
only: false,
|
|
34
|
+
|
|
35
|
+
// Checker: 'tsc' or 'vue-tsc'
|
|
36
|
+
checker: 'tsc',
|
|
37
|
+
|
|
38
|
+
// Include patterns
|
|
39
|
+
include: ['**/*.test-d.ts'],
|
|
40
|
+
|
|
41
|
+
// tsconfig to use
|
|
42
|
+
tsconfig: './tsconfig.json',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## expectTypeOf API
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { expectTypeOf } from 'vitest'
|
|
52
|
+
|
|
53
|
+
// Basic type checks
|
|
54
|
+
expectTypeOf<string>().toBeString()
|
|
55
|
+
expectTypeOf<number>().toBeNumber()
|
|
56
|
+
expectTypeOf<boolean>().toBeBoolean()
|
|
57
|
+
expectTypeOf<null>().toBeNull()
|
|
58
|
+
expectTypeOf<undefined>().toBeUndefined()
|
|
59
|
+
expectTypeOf<void>().toBeVoid()
|
|
60
|
+
expectTypeOf<never>().toBeNever()
|
|
61
|
+
expectTypeOf<any>().toBeAny()
|
|
62
|
+
expectTypeOf<unknown>().toBeUnknown()
|
|
63
|
+
expectTypeOf<object>().toBeObject()
|
|
64
|
+
expectTypeOf<Function>().toBeFunction()
|
|
65
|
+
expectTypeOf<[]>().toBeArray()
|
|
66
|
+
expectTypeOf<symbol>().toBeSymbol()
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Value Type Checking
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
const value = 'hello'
|
|
73
|
+
expectTypeOf(value).toBeString()
|
|
74
|
+
|
|
75
|
+
const obj = { name: 'test', count: 42 }
|
|
76
|
+
expectTypeOf(obj).toMatchTypeOf<{ name: string }>()
|
|
77
|
+
expectTypeOf(obj).toHaveProperty('name')
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Function Types
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
function greet(name: string): string {
|
|
84
|
+
return `Hello, ${name}`
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
expectTypeOf(greet).toBeFunction()
|
|
88
|
+
expectTypeOf(greet).parameters.toEqualTypeOf<[string]>()
|
|
89
|
+
expectTypeOf(greet).returns.toBeString()
|
|
90
|
+
|
|
91
|
+
// Parameter checking
|
|
92
|
+
expectTypeOf(greet).parameter(0).toBeString()
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Object Types
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
interface User {
|
|
99
|
+
id: number
|
|
100
|
+
name: string
|
|
101
|
+
email?: string
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
expectTypeOf<User>().toHaveProperty('id')
|
|
105
|
+
expectTypeOf<User>().toHaveProperty('name').toBeString()
|
|
106
|
+
|
|
107
|
+
// Check shape
|
|
108
|
+
expectTypeOf({ id: 1, name: 'test' }).toMatchTypeOf<User>()
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Equality vs Matching
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
interface A { x: number }
|
|
115
|
+
interface B { x: number; y: string }
|
|
116
|
+
|
|
117
|
+
// toMatchTypeOf - subset matching
|
|
118
|
+
expectTypeOf<B>().toMatchTypeOf<A>() // B extends A
|
|
119
|
+
|
|
120
|
+
// toEqualTypeOf - exact match
|
|
121
|
+
expectTypeOf<A>().not.toEqualTypeOf<B>() // Not exact match
|
|
122
|
+
expectTypeOf<A>().toEqualTypeOf<{ x: number }>() // Exact match
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Branded Types
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
type UserId = number & { __brand: 'UserId' }
|
|
129
|
+
type PostId = number & { __brand: 'PostId' }
|
|
130
|
+
|
|
131
|
+
expectTypeOf<UserId>().not.toEqualTypeOf<PostId>()
|
|
132
|
+
expectTypeOf<UserId>().not.toEqualTypeOf<number>()
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Generic Types
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
function identity<T>(value: T): T {
|
|
139
|
+
return value
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
expectTypeOf(identity<string>).returns.toBeString()
|
|
143
|
+
expectTypeOf(identity<number>).returns.toBeNumber()
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Nullable Types
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
type MaybeString = string | null | undefined
|
|
150
|
+
|
|
151
|
+
expectTypeOf<MaybeString>().toBeNullable()
|
|
152
|
+
expectTypeOf<string>().not.toBeNullable()
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## assertType
|
|
156
|
+
|
|
157
|
+
Assert a value matches a type (no assertion at runtime):
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import { assertType } from 'vitest'
|
|
161
|
+
|
|
162
|
+
function getUser(): User | null {
|
|
163
|
+
return { id: 1, name: 'test' }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
test('returns user', () => {
|
|
167
|
+
const result = getUser()
|
|
168
|
+
|
|
169
|
+
// @ts-expect-error - should fail type check
|
|
170
|
+
assertType<string>(result)
|
|
171
|
+
|
|
172
|
+
// Correct type
|
|
173
|
+
assertType<User | null>(result)
|
|
174
|
+
})
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Using @ts-expect-error
|
|
178
|
+
|
|
179
|
+
Test that code produces type error:
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
test('rejects wrong types', () => {
|
|
183
|
+
function requireString(s: string) {}
|
|
184
|
+
|
|
185
|
+
// @ts-expect-error - number not assignable to string
|
|
186
|
+
requireString(123)
|
|
187
|
+
})
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Running Type Tests
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# Run type tests
|
|
194
|
+
vitest typecheck
|
|
195
|
+
|
|
196
|
+
# Run alongside unit tests
|
|
197
|
+
vitest --typecheck
|
|
198
|
+
|
|
199
|
+
# Type tests only
|
|
200
|
+
vitest --typecheck.only
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Mixed Test Files
|
|
204
|
+
|
|
205
|
+
Combine runtime and type tests:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
// user.test.ts
|
|
209
|
+
import { describe, expect, expectTypeOf, test } from 'vitest'
|
|
210
|
+
import { createUser } from './user'
|
|
211
|
+
|
|
212
|
+
describe('createUser', () => {
|
|
213
|
+
test('runtime: creates user', () => {
|
|
214
|
+
const user = createUser('John')
|
|
215
|
+
expect(user.name).toBe('John')
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
test('types: returns User type', () => {
|
|
219
|
+
expectTypeOf(createUser).returns.toMatchTypeOf<{ name: string }>()
|
|
220
|
+
})
|
|
221
|
+
})
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Key Points
|
|
225
|
+
|
|
226
|
+
- Use `.test-d.ts` for type-only tests
|
|
227
|
+
- `expectTypeOf` for type assertions
|
|
228
|
+
- `toMatchTypeOf` for subset matching
|
|
229
|
+
- `toEqualTypeOf` for exact type matching
|
|
230
|
+
- Use `@ts-expect-error` to test type errors
|
|
231
|
+
- Run with `vitest typecheck` or `--typecheck`
|
|
232
|
+
|
|
233
|
+
<!--
|
|
234
|
+
Source references:
|
|
235
|
+
- https://vitest.dev/guide/testing-types.html
|
|
236
|
+
- https://vitest.dev/api/expect-typeof.html
|
|
237
|
+
-->
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vi-utilities
|
|
3
|
+
description: vi helper for mocking, timers, utilities
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Vi Utilities
|
|
7
|
+
|
|
8
|
+
The `vi` helper provides mocking and utility functions.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { vi } from 'vitest'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Mock Functions
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
// Create mock
|
|
18
|
+
const fn = vi.fn()
|
|
19
|
+
const fnWithImpl = vi.fn((x) => x * 2)
|
|
20
|
+
|
|
21
|
+
// Check if mock
|
|
22
|
+
vi.isMockFunction(fn) // true
|
|
23
|
+
|
|
24
|
+
// Mock methods
|
|
25
|
+
fn.mockReturnValue(42)
|
|
26
|
+
fn.mockReturnValueOnce(1)
|
|
27
|
+
fn.mockResolvedValue(data)
|
|
28
|
+
fn.mockRejectedValue(error)
|
|
29
|
+
fn.mockImplementation(() => 'result')
|
|
30
|
+
fn.mockImplementationOnce(() => 'once')
|
|
31
|
+
|
|
32
|
+
// Clear/reset
|
|
33
|
+
fn.mockClear() // Clear call history
|
|
34
|
+
fn.mockReset() // Clear history + implementation
|
|
35
|
+
fn.mockRestore() // Restore original (for spies)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Spying
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
const obj = { method: () => 'original' }
|
|
42
|
+
|
|
43
|
+
const spy = vi.spyOn(obj, 'method')
|
|
44
|
+
obj.method()
|
|
45
|
+
|
|
46
|
+
expect(spy).toHaveBeenCalled()
|
|
47
|
+
|
|
48
|
+
// Mock implementation
|
|
49
|
+
spy.mockReturnValue('mocked')
|
|
50
|
+
|
|
51
|
+
// Spy on getter/setter
|
|
52
|
+
vi.spyOn(obj, 'prop', 'get').mockReturnValue('value')
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Module Mocking
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
// Hoisted to top of file
|
|
59
|
+
vi.mock('./module', () => ({
|
|
60
|
+
fn: vi.fn(),
|
|
61
|
+
}))
|
|
62
|
+
|
|
63
|
+
// Partial mock
|
|
64
|
+
vi.mock('./module', async (importOriginal) => ({
|
|
65
|
+
...(await importOriginal()),
|
|
66
|
+
specificFn: vi.fn(),
|
|
67
|
+
}))
|
|
68
|
+
|
|
69
|
+
// Spy mode - keep implementation
|
|
70
|
+
vi.mock('./module', { spy: true })
|
|
71
|
+
|
|
72
|
+
// Import actual module inside mock
|
|
73
|
+
const actual = await vi.importActual('./module')
|
|
74
|
+
|
|
75
|
+
// Import as mock
|
|
76
|
+
const mocked = await vi.importMock('./module')
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Dynamic Mocking
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
// Not hoisted - use with dynamic imports
|
|
83
|
+
vi.doMock('./config', () => ({ key: 'value' }))
|
|
84
|
+
const config = await import('./config')
|
|
85
|
+
|
|
86
|
+
// Unmock
|
|
87
|
+
vi.doUnmock('./config')
|
|
88
|
+
vi.unmock('./module') // Hoisted
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Reset Modules
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
// Clear module cache
|
|
95
|
+
vi.resetModules()
|
|
96
|
+
|
|
97
|
+
// Wait for dynamic imports
|
|
98
|
+
await vi.dynamicImportSettled()
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Fake Timers
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
vi.useFakeTimers()
|
|
105
|
+
|
|
106
|
+
setTimeout(() => console.log('done'), 1000)
|
|
107
|
+
|
|
108
|
+
// Advance time
|
|
109
|
+
vi.advanceTimersByTime(1000)
|
|
110
|
+
vi.advanceTimersByTimeAsync(1000) // For async callbacks
|
|
111
|
+
vi.advanceTimersToNextTimer()
|
|
112
|
+
vi.advanceTimersToNextFrame() // requestAnimationFrame
|
|
113
|
+
|
|
114
|
+
// Run all timers
|
|
115
|
+
vi.runAllTimers()
|
|
116
|
+
vi.runAllTimersAsync()
|
|
117
|
+
vi.runOnlyPendingTimers()
|
|
118
|
+
|
|
119
|
+
// Clear timers
|
|
120
|
+
vi.clearAllTimers()
|
|
121
|
+
|
|
122
|
+
// Check state
|
|
123
|
+
vi.getTimerCount()
|
|
124
|
+
vi.isFakeTimers()
|
|
125
|
+
|
|
126
|
+
// Restore
|
|
127
|
+
vi.useRealTimers()
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Mock Date/Time
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
vi.setSystemTime(new Date('2024-01-01'))
|
|
134
|
+
expect(new Date().getFullYear()).toBe(2024)
|
|
135
|
+
|
|
136
|
+
vi.getMockedSystemTime() // Get mocked date
|
|
137
|
+
vi.getRealSystemTime() // Get real time (ms)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Global/Env Mocking
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
// Stub global
|
|
144
|
+
vi.stubGlobal('fetch', vi.fn())
|
|
145
|
+
vi.unstubAllGlobals()
|
|
146
|
+
|
|
147
|
+
// Stub environment
|
|
148
|
+
vi.stubEnv('API_KEY', 'test')
|
|
149
|
+
vi.stubEnv('NODE_ENV', 'test')
|
|
150
|
+
vi.unstubAllEnvs()
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Hoisted Code
|
|
154
|
+
|
|
155
|
+
Run code before imports:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
const mock = vi.hoisted(() => vi.fn())
|
|
159
|
+
|
|
160
|
+
vi.mock('./module', () => ({
|
|
161
|
+
fn: mock, // Can reference hoisted variable
|
|
162
|
+
}))
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Waiting Utilities
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
// Wait for callback to succeed
|
|
169
|
+
await vi.waitFor(async () => {
|
|
170
|
+
const el = document.querySelector('.loaded')
|
|
171
|
+
expect(el).toBeTruthy()
|
|
172
|
+
}, { timeout: 5000, interval: 100 })
|
|
173
|
+
|
|
174
|
+
// Wait for truthy value
|
|
175
|
+
const element = await vi.waitUntil(
|
|
176
|
+
() => document.querySelector('.loaded'),
|
|
177
|
+
{ timeout: 5000 }
|
|
178
|
+
)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Mock Object
|
|
182
|
+
|
|
183
|
+
Mock all methods of an object:
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
const original = {
|
|
187
|
+
method: () => 'real',
|
|
188
|
+
nested: { fn: () => 'nested' },
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const mocked = vi.mockObject(original)
|
|
192
|
+
mocked.method() // undefined (mocked)
|
|
193
|
+
mocked.method.mockReturnValue('mocked')
|
|
194
|
+
|
|
195
|
+
// Spy mode
|
|
196
|
+
const spied = vi.mockObject(original, { spy: true })
|
|
197
|
+
spied.method() // 'real'
|
|
198
|
+
expect(spied.method).toHaveBeenCalled()
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Test Configuration
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
vi.setConfig({
|
|
205
|
+
testTimeout: 10_000,
|
|
206
|
+
hookTimeout: 10_000,
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
vi.resetConfig()
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Global Mock Management
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
vi.clearAllMocks() // Clear all mock call history
|
|
216
|
+
vi.resetAllMocks() // Reset + clear implementation
|
|
217
|
+
vi.restoreAllMocks() // Restore originals (spies)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## vi.mocked Type Helper
|
|
221
|
+
|
|
222
|
+
TypeScript helper for mocked values:
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
import { myFn } from './module'
|
|
226
|
+
vi.mock('./module')
|
|
227
|
+
|
|
228
|
+
// Type as mock
|
|
229
|
+
vi.mocked(myFn).mockReturnValue('typed')
|
|
230
|
+
|
|
231
|
+
// Deep mocking
|
|
232
|
+
vi.mocked(myModule, { deep: true })
|
|
233
|
+
|
|
234
|
+
// Partial mock typing
|
|
235
|
+
vi.mocked(fn, { partial: true }).mockResolvedValue({ ok: true })
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Key Points
|
|
239
|
+
|
|
240
|
+
- `vi.mock` is hoisted - use `vi.doMock` for dynamic mocking
|
|
241
|
+
- `vi.hoisted` lets you reference variables in mock factories
|
|
242
|
+
- Use `vi.spyOn` to spy on existing methods
|
|
243
|
+
- Fake timers require explicit setup and teardown
|
|
244
|
+
- `vi.waitFor` retries until assertion passes
|
|
245
|
+
|
|
246
|
+
<!--
|
|
247
|
+
Source references:
|
|
248
|
+
- https://vitest.dev/api/vi.html
|
|
249
|
+
-->
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vitest-cli
|
|
3
|
+
description: Command line interface commands and options
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Command Line Interface
|
|
7
|
+
|
|
8
|
+
## Commands
|
|
9
|
+
|
|
10
|
+
### `vitest`
|
|
11
|
+
|
|
12
|
+
Start Vitest in watch mode (dev) or run mode (CI):
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
vitest # Watch mode in dev, run mode in CI
|
|
16
|
+
vitest foobar # Run tests containing "foobar" in path
|
|
17
|
+
vitest basic/foo.test.ts:10 # Run specific test by file and line number
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### `vitest run`
|
|
21
|
+
|
|
22
|
+
Run tests once without watch mode:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
vitest run
|
|
26
|
+
vitest run --coverage
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### `vitest watch`
|
|
30
|
+
|
|
31
|
+
Explicitly start watch mode:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
vitest watch
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### `vitest related`
|
|
38
|
+
|
|
39
|
+
Run tests that import specific files (useful with lint-staged):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
vitest related src/index.ts src/utils.ts --run
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### `vitest bench`
|
|
46
|
+
|
|
47
|
+
Run only benchmark tests:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
vitest bench
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### `vitest list`
|
|
54
|
+
|
|
55
|
+
List all matching tests without running them:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
vitest list # List test names
|
|
59
|
+
vitest list --json # Output as JSON
|
|
60
|
+
vitest list --filesOnly # List only test files
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### `vitest init`
|
|
64
|
+
|
|
65
|
+
Initialize project setup:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
vitest init browser # Set up browser testing
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Common Options
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Configuration
|
|
75
|
+
--config <path> # Path to config file
|
|
76
|
+
--project <name> # Run specific project
|
|
77
|
+
|
|
78
|
+
# Filtering
|
|
79
|
+
--testNamePattern, -t # Run tests matching pattern
|
|
80
|
+
--changed # Run tests for changed files
|
|
81
|
+
--changed HEAD~1 # Tests for last commit changes
|
|
82
|
+
|
|
83
|
+
# Reporters
|
|
84
|
+
--reporter <name> # default, verbose, dot, json, html
|
|
85
|
+
--reporter=html --outputFile=report.html
|
|
86
|
+
|
|
87
|
+
# Coverage
|
|
88
|
+
--coverage # Enable coverage
|
|
89
|
+
--coverage.provider v8 # Use v8 provider
|
|
90
|
+
--coverage.reporter text,html
|
|
91
|
+
|
|
92
|
+
# Execution
|
|
93
|
+
--shard <index>/<count> # Split tests across machines
|
|
94
|
+
--bail <n> # Stop after n failures
|
|
95
|
+
--retry <n> # Retry failed tests n times
|
|
96
|
+
--sequence.shuffle # Randomize test order
|
|
97
|
+
|
|
98
|
+
# Watch mode
|
|
99
|
+
--no-watch # Disable watch mode
|
|
100
|
+
--standalone # Start without running tests
|
|
101
|
+
|
|
102
|
+
# Environment
|
|
103
|
+
--environment <env> # jsdom, happy-dom, node
|
|
104
|
+
--globals # Enable global APIs
|
|
105
|
+
|
|
106
|
+
# Debugging
|
|
107
|
+
--inspect # Enable Node inspector
|
|
108
|
+
--inspect-brk # Break on start
|
|
109
|
+
|
|
110
|
+
# Output
|
|
111
|
+
--silent # Suppress console output
|
|
112
|
+
--no-color # Disable colors
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Package.json Scripts
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"scripts": {
|
|
120
|
+
"test": "vitest",
|
|
121
|
+
"test:run": "vitest run",
|
|
122
|
+
"test:ui": "vitest --ui",
|
|
123
|
+
"coverage": "vitest run --coverage"
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Sharding for CI
|
|
129
|
+
|
|
130
|
+
Split tests across multiple machines:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Machine 1
|
|
134
|
+
vitest run --shard=1/3 --reporter=blob
|
|
135
|
+
|
|
136
|
+
# Machine 2
|
|
137
|
+
vitest run --shard=2/3 --reporter=blob
|
|
138
|
+
|
|
139
|
+
# Machine 3
|
|
140
|
+
vitest run --shard=3/3 --reporter=blob
|
|
141
|
+
|
|
142
|
+
# Merge reports
|
|
143
|
+
vitest --merge-reports --reporter=junit
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Watch Mode Keyboard Shortcuts
|
|
147
|
+
|
|
148
|
+
In watch mode, press:
|
|
149
|
+
- `a` - Run all tests
|
|
150
|
+
- `f` - Run only failed tests
|
|
151
|
+
- `u` - Update snapshots
|
|
152
|
+
- `p` - Filter by filename pattern
|
|
153
|
+
- `t` - Filter by test name pattern
|
|
154
|
+
- `q` - Quit
|
|
155
|
+
|
|
156
|
+
## Key Points
|
|
157
|
+
|
|
158
|
+
- Watch mode is default in dev, run mode in CI (when `process.env.CI` is set)
|
|
159
|
+
- Use `--run` flag to ensure single run (important for lint-staged)
|
|
160
|
+
- Both camelCase (`--testTimeout`) and kebab-case (`--test-timeout`) work
|
|
161
|
+
- Boolean options can be negated with `--no-` prefix
|
|
162
|
+
|
|
163
|
+
<!--
|
|
164
|
+
Source references:
|
|
165
|
+
- https://vitest.dev/guide/cli.html
|
|
166
|
+
-->
|