@dfosco/storyboard-core 3.2.0 → 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 -18
- 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/lib/components/ui/trigger-button/trigger-button.svelte +8 -4
- 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,238 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test-context-fixtures
|
|
3
|
+
description: Test context, custom fixtures with test.extend
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Test Context & Fixtures
|
|
7
|
+
|
|
8
|
+
## Built-in Context
|
|
9
|
+
|
|
10
|
+
Every test receives context as first argument:
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
test('context', ({ task, expect, skip }) => {
|
|
14
|
+
console.log(task.name) // Test name
|
|
15
|
+
expect(1).toBe(1) // Context-bound expect
|
|
16
|
+
skip() // Skip test dynamically
|
|
17
|
+
})
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Context Properties
|
|
21
|
+
|
|
22
|
+
- `task` - Test metadata (name, file, etc.)
|
|
23
|
+
- `expect` - Expect bound to this test (important for concurrent tests)
|
|
24
|
+
- `skip(condition?, message?)` - Skip the test
|
|
25
|
+
- `onTestFinished(fn)` - Cleanup after test
|
|
26
|
+
- `onTestFailed(fn)` - Run on failure only
|
|
27
|
+
|
|
28
|
+
## Custom Fixtures with test.extend
|
|
29
|
+
|
|
30
|
+
Create reusable test utilities:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { test as base } from 'vitest'
|
|
34
|
+
|
|
35
|
+
// Define fixture types
|
|
36
|
+
interface Fixtures {
|
|
37
|
+
db: Database
|
|
38
|
+
user: User
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Create extended test
|
|
42
|
+
export const test = base.extend<Fixtures>({
|
|
43
|
+
// Fixture with setup/teardown
|
|
44
|
+
db: async ({}, use) => {
|
|
45
|
+
const db = await createDatabase()
|
|
46
|
+
await use(db) // Provide to test
|
|
47
|
+
await db.close() // Cleanup
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
// Fixture depending on another fixture
|
|
51
|
+
user: async ({ db }, use) => {
|
|
52
|
+
const user = await db.createUser({ name: 'Test' })
|
|
53
|
+
await use(user)
|
|
54
|
+
await db.deleteUser(user.id)
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Using fixtures:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
test('query user', async ({ db, user }) => {
|
|
63
|
+
const found = await db.findUser(user.id)
|
|
64
|
+
expect(found).toEqual(user)
|
|
65
|
+
})
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Fixture Initialization
|
|
69
|
+
|
|
70
|
+
Fixtures only initialize when accessed:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
const test = base.extend({
|
|
74
|
+
expensive: async ({}, use) => {
|
|
75
|
+
console.log('initializing') // Only runs if test uses it
|
|
76
|
+
await use('value')
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
test('no fixture', () => {}) // expensive not called
|
|
81
|
+
test('uses fixture', ({ expensive }) => {}) // expensive called
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Auto Fixtures
|
|
85
|
+
|
|
86
|
+
Run fixture for every test:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
const test = base.extend({
|
|
90
|
+
setup: [
|
|
91
|
+
async ({}, use) => {
|
|
92
|
+
await globalSetup()
|
|
93
|
+
await use()
|
|
94
|
+
await globalTeardown()
|
|
95
|
+
},
|
|
96
|
+
{ auto: true } // Always run
|
|
97
|
+
],
|
|
98
|
+
})
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Scoped Fixtures
|
|
102
|
+
|
|
103
|
+
### File Scope
|
|
104
|
+
|
|
105
|
+
Initialize once per file:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
const test = base.extend({
|
|
109
|
+
connection: [
|
|
110
|
+
async ({}, use) => {
|
|
111
|
+
const conn = await connect()
|
|
112
|
+
await use(conn)
|
|
113
|
+
await conn.close()
|
|
114
|
+
},
|
|
115
|
+
{ scope: 'file' }
|
|
116
|
+
],
|
|
117
|
+
})
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Worker Scope
|
|
121
|
+
|
|
122
|
+
Initialize once per worker:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
const test = base.extend({
|
|
126
|
+
sharedResource: [
|
|
127
|
+
async ({}, use) => {
|
|
128
|
+
await use(globalResource)
|
|
129
|
+
},
|
|
130
|
+
{ scope: 'worker' }
|
|
131
|
+
],
|
|
132
|
+
})
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Injected Fixtures (from Config)
|
|
136
|
+
|
|
137
|
+
Override fixtures per project:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
// test file
|
|
141
|
+
const test = base.extend({
|
|
142
|
+
apiUrl: ['/default', { injected: true }],
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
// vitest.config.ts
|
|
146
|
+
defineConfig({
|
|
147
|
+
test: {
|
|
148
|
+
projects: [
|
|
149
|
+
{
|
|
150
|
+
test: {
|
|
151
|
+
name: 'prod',
|
|
152
|
+
provide: { apiUrl: 'https://api.prod.com' },
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
})
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Scoped Values per Suite
|
|
161
|
+
|
|
162
|
+
Override fixture for specific suite:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
const test = base.extend({
|
|
166
|
+
environment: 'development',
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
describe('production tests', () => {
|
|
170
|
+
test.scoped({ environment: 'production' })
|
|
171
|
+
|
|
172
|
+
test('uses production', ({ environment }) => {
|
|
173
|
+
expect(environment).toBe('production')
|
|
174
|
+
})
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
test('uses default', ({ environment }) => {
|
|
178
|
+
expect(environment).toBe('development')
|
|
179
|
+
})
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Extended Test Hooks
|
|
183
|
+
|
|
184
|
+
Type-aware hooks with fixtures:
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
const test = base.extend<{ db: Database }>({
|
|
188
|
+
db: async ({}, use) => {
|
|
189
|
+
const db = await createDb()
|
|
190
|
+
await use(db)
|
|
191
|
+
await db.close()
|
|
192
|
+
},
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
// Hooks know about fixtures
|
|
196
|
+
test.beforeEach(({ db }) => {
|
|
197
|
+
db.seed()
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
test.afterEach(({ db }) => {
|
|
201
|
+
db.clear()
|
|
202
|
+
})
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Composing Fixtures
|
|
206
|
+
|
|
207
|
+
Extend from another extended test:
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
// base-test.ts
|
|
211
|
+
export const test = base.extend<{ db: Database }>({
|
|
212
|
+
db: async ({}, use) => { /* ... */ },
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
// admin-test.ts
|
|
216
|
+
import { test as dbTest } from './base-test'
|
|
217
|
+
|
|
218
|
+
export const test = dbTest.extend<{ admin: User }>({
|
|
219
|
+
admin: async ({ db }, use) => {
|
|
220
|
+
const admin = await db.createAdmin()
|
|
221
|
+
await use(admin)
|
|
222
|
+
},
|
|
223
|
+
})
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Key Points
|
|
227
|
+
|
|
228
|
+
- Use `{ }` destructuring to access fixtures
|
|
229
|
+
- Fixtures are lazy - only initialize when accessed
|
|
230
|
+
- Return cleanup function from fixtures
|
|
231
|
+
- Use `{ auto: true }` for setup fixtures
|
|
232
|
+
- Use `{ scope: 'file' }` for expensive shared resources
|
|
233
|
+
- Fixtures compose - extend from extended tests
|
|
234
|
+
|
|
235
|
+
<!--
|
|
236
|
+
Source references:
|
|
237
|
+
- https://vitest.dev/guide/test-context.html
|
|
238
|
+
-->
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-coverage
|
|
3
|
+
description: Code coverage with V8 or Istanbul providers
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Code Coverage
|
|
7
|
+
|
|
8
|
+
## Setup
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
# Run tests with coverage
|
|
12
|
+
vitest run --coverage
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
// vitest.config.ts
|
|
19
|
+
defineConfig({
|
|
20
|
+
test: {
|
|
21
|
+
coverage: {
|
|
22
|
+
// Provider: 'v8' (default, faster) or 'istanbul' (more compatible)
|
|
23
|
+
provider: 'v8',
|
|
24
|
+
|
|
25
|
+
// Enable coverage
|
|
26
|
+
enabled: true,
|
|
27
|
+
|
|
28
|
+
// Reporters
|
|
29
|
+
reporter: ['text', 'json', 'html'],
|
|
30
|
+
|
|
31
|
+
// Files to include
|
|
32
|
+
include: ['src/**/*.{ts,tsx}'],
|
|
33
|
+
|
|
34
|
+
// Files to exclude
|
|
35
|
+
exclude: [
|
|
36
|
+
'node_modules/',
|
|
37
|
+
'tests/',
|
|
38
|
+
'**/*.d.ts',
|
|
39
|
+
'**/*.test.ts',
|
|
40
|
+
],
|
|
41
|
+
|
|
42
|
+
// Report uncovered files
|
|
43
|
+
all: true,
|
|
44
|
+
|
|
45
|
+
// Thresholds
|
|
46
|
+
thresholds: {
|
|
47
|
+
lines: 80,
|
|
48
|
+
functions: 80,
|
|
49
|
+
branches: 80,
|
|
50
|
+
statements: 80,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Providers
|
|
58
|
+
|
|
59
|
+
### V8 (Default)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm i -D @vitest/coverage-v8
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
- Faster, no pre-instrumentation
|
|
66
|
+
- Uses V8's native coverage
|
|
67
|
+
- Recommended for most projects
|
|
68
|
+
|
|
69
|
+
### Istanbul
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npm i -D @vitest/coverage-istanbul
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
- Pre-instruments code
|
|
76
|
+
- Works in any JS runtime
|
|
77
|
+
- More overhead but widely compatible
|
|
78
|
+
|
|
79
|
+
## Reporters
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
coverage: {
|
|
83
|
+
reporter: [
|
|
84
|
+
'text', // Terminal output
|
|
85
|
+
'text-summary', // Summary only
|
|
86
|
+
'json', // JSON file
|
|
87
|
+
'html', // HTML report
|
|
88
|
+
'lcov', // For CI tools
|
|
89
|
+
'cobertura', // XML format
|
|
90
|
+
],
|
|
91
|
+
reportsDirectory: './coverage',
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Thresholds
|
|
96
|
+
|
|
97
|
+
Fail tests if coverage is below threshold:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
coverage: {
|
|
101
|
+
thresholds: {
|
|
102
|
+
// Global thresholds
|
|
103
|
+
lines: 80,
|
|
104
|
+
functions: 75,
|
|
105
|
+
branches: 70,
|
|
106
|
+
statements: 80,
|
|
107
|
+
|
|
108
|
+
// Per-file thresholds
|
|
109
|
+
perFile: true,
|
|
110
|
+
|
|
111
|
+
// Auto-update thresholds (for gradual improvement)
|
|
112
|
+
autoUpdate: true,
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Ignoring Code
|
|
118
|
+
|
|
119
|
+
### V8
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
/* v8 ignore next -- @preserve */
|
|
123
|
+
function ignored() {
|
|
124
|
+
return 'not covered'
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* v8 ignore start -- @preserve */
|
|
128
|
+
// All code here ignored
|
|
129
|
+
/* v8 ignore stop -- @preserve */
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Istanbul
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
/* istanbul ignore next -- @preserve */
|
|
136
|
+
function ignored() {}
|
|
137
|
+
|
|
138
|
+
/* istanbul ignore if -- @preserve */
|
|
139
|
+
if (condition) {
|
|
140
|
+
// ignored
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Note: `@preserve` keeps comments through esbuild.
|
|
145
|
+
|
|
146
|
+
## Package.json Scripts
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"scripts": {
|
|
151
|
+
"test": "vitest",
|
|
152
|
+
"test:coverage": "vitest run --coverage",
|
|
153
|
+
"test:coverage:watch": "vitest --coverage"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Vitest UI Coverage
|
|
159
|
+
|
|
160
|
+
Enable HTML coverage in Vitest UI:
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
coverage: {
|
|
164
|
+
enabled: true,
|
|
165
|
+
reporter: ['text', 'html'],
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Run with `vitest --ui` to view coverage visually.
|
|
170
|
+
|
|
171
|
+
## CI Integration
|
|
172
|
+
|
|
173
|
+
```yaml
|
|
174
|
+
# GitHub Actions
|
|
175
|
+
- name: Run tests with coverage
|
|
176
|
+
run: npm run test:coverage
|
|
177
|
+
|
|
178
|
+
- name: Upload coverage to Codecov
|
|
179
|
+
uses: codecov/codecov-action@v3
|
|
180
|
+
with:
|
|
181
|
+
files: ./coverage/lcov.info
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Coverage with Sharding
|
|
185
|
+
|
|
186
|
+
Merge coverage from sharded runs:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
vitest run --shard=1/3 --coverage --reporter=blob
|
|
190
|
+
vitest run --shard=2/3 --coverage --reporter=blob
|
|
191
|
+
vitest run --shard=3/3 --coverage --reporter=blob
|
|
192
|
+
|
|
193
|
+
vitest --merge-reports --coverage --reporter=json
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Key Points
|
|
197
|
+
|
|
198
|
+
- V8 is faster, Istanbul is more compatible
|
|
199
|
+
- Use `--coverage` flag or `coverage.enabled: true`
|
|
200
|
+
- Include `all: true` to see uncovered files
|
|
201
|
+
- Set thresholds to enforce minimum coverage
|
|
202
|
+
- Use `@preserve` comment to keep ignore hints
|
|
203
|
+
|
|
204
|
+
<!--
|
|
205
|
+
Source references:
|
|
206
|
+
- https://vitest.dev/guide/coverage.html
|
|
207
|
+
-->
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test-filtering
|
|
3
|
+
description: Filter tests by name, file patterns, and tags
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Test Filtering
|
|
7
|
+
|
|
8
|
+
## CLI Filtering
|
|
9
|
+
|
|
10
|
+
### By File Path
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# Run files containing "user"
|
|
14
|
+
vitest user
|
|
15
|
+
|
|
16
|
+
# Multiple patterns
|
|
17
|
+
vitest user auth
|
|
18
|
+
|
|
19
|
+
# Specific file
|
|
20
|
+
vitest src/user.test.ts
|
|
21
|
+
|
|
22
|
+
# By line number
|
|
23
|
+
vitest src/user.test.ts:25
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### By Test Name
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Tests matching pattern
|
|
30
|
+
vitest -t "login"
|
|
31
|
+
vitest --testNamePattern "should.*work"
|
|
32
|
+
|
|
33
|
+
# Regex patterns
|
|
34
|
+
vitest -t "/user|auth/"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Changed Files
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Uncommitted changes
|
|
41
|
+
vitest --changed
|
|
42
|
+
|
|
43
|
+
# Since specific commit
|
|
44
|
+
vitest --changed HEAD~1
|
|
45
|
+
vitest --changed abc123
|
|
46
|
+
|
|
47
|
+
# Since branch
|
|
48
|
+
vitest --changed origin/main
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Related Files
|
|
52
|
+
|
|
53
|
+
Run tests that import specific files:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
vitest related src/utils.ts src/api.ts --run
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Useful with lint-staged:
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
// .lintstagedrc.js
|
|
63
|
+
export default {
|
|
64
|
+
'*.{ts,tsx}': 'vitest related --run',
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Focus Tests (.only)
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
test.only('only this runs', () => {})
|
|
72
|
+
|
|
73
|
+
describe.only('only this suite', () => {
|
|
74
|
+
test('runs', () => {})
|
|
75
|
+
})
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
In CI, `.only` throws error unless configured:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
defineConfig({
|
|
82
|
+
test: {
|
|
83
|
+
allowOnly: true, // Allow .only in CI
|
|
84
|
+
},
|
|
85
|
+
})
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Skip Tests
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
test.skip('skipped', () => {})
|
|
92
|
+
|
|
93
|
+
// Conditional
|
|
94
|
+
test.skipIf(process.env.CI)('not in CI', () => {})
|
|
95
|
+
test.runIf(!process.env.CI)('local only', () => {})
|
|
96
|
+
|
|
97
|
+
// Dynamic skip
|
|
98
|
+
test('dynamic', ({ skip }) => {
|
|
99
|
+
skip(someCondition, 'reason')
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Tags
|
|
104
|
+
|
|
105
|
+
Filter by custom tags:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
test('database test', { tags: ['db'] }, () => {})
|
|
109
|
+
test('slow test', { tags: ['slow', 'integration'] }, () => {})
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Run tagged tests:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
vitest --tags db
|
|
116
|
+
vitest --tags "db,slow" # OR
|
|
117
|
+
vitest --tags db --tags slow # OR
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Configure allowed tags:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
defineConfig({
|
|
124
|
+
test: {
|
|
125
|
+
tags: ['db', 'slow', 'integration'],
|
|
126
|
+
strictTags: true, // Fail on unknown tags
|
|
127
|
+
},
|
|
128
|
+
})
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Include/Exclude Patterns
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
defineConfig({
|
|
135
|
+
test: {
|
|
136
|
+
// Test file patterns
|
|
137
|
+
include: ['**/*.{test,spec}.{ts,tsx}'],
|
|
138
|
+
|
|
139
|
+
// Exclude patterns
|
|
140
|
+
exclude: [
|
|
141
|
+
'**/node_modules/**',
|
|
142
|
+
'**/e2e/**',
|
|
143
|
+
'**/*.skip.test.ts',
|
|
144
|
+
],
|
|
145
|
+
|
|
146
|
+
// Include source for in-source testing
|
|
147
|
+
includeSource: ['src/**/*.ts'],
|
|
148
|
+
},
|
|
149
|
+
})
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Watch Mode Filtering
|
|
153
|
+
|
|
154
|
+
In watch mode, press:
|
|
155
|
+
- `p` - Filter by filename pattern
|
|
156
|
+
- `t` - Filter by test name pattern
|
|
157
|
+
- `a` - Run all tests
|
|
158
|
+
- `f` - Run only failed tests
|
|
159
|
+
|
|
160
|
+
## Projects Filtering
|
|
161
|
+
|
|
162
|
+
Run specific project:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
vitest --project unit
|
|
166
|
+
vitest --project integration --project e2e
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Environment-based Filtering
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
const isDev = process.env.NODE_ENV === 'development'
|
|
173
|
+
const isCI = process.env.CI
|
|
174
|
+
|
|
175
|
+
describe.skipIf(isCI)('local only tests', () => {})
|
|
176
|
+
describe.runIf(isDev)('dev tests', () => {})
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Combining Filters
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# File pattern + test name + changed
|
|
183
|
+
vitest user -t "login" --changed
|
|
184
|
+
|
|
185
|
+
# Related files + run mode
|
|
186
|
+
vitest related src/auth.ts --run
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## List Tests Without Running
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
vitest list # Show all test names
|
|
193
|
+
vitest list -t "user" # Filter by name
|
|
194
|
+
vitest list --filesOnly # Show only file paths
|
|
195
|
+
vitest list --json # JSON output
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Key Points
|
|
199
|
+
|
|
200
|
+
- Use `-t` for test name pattern filtering
|
|
201
|
+
- `--changed` runs only tests affected by changes
|
|
202
|
+
- `--related` runs tests importing specific files
|
|
203
|
+
- Tags provide semantic test grouping
|
|
204
|
+
- Use `.only` for debugging, but configure CI to reject it
|
|
205
|
+
- Watch mode has interactive filtering
|
|
206
|
+
|
|
207
|
+
<!--
|
|
208
|
+
Source references:
|
|
209
|
+
- https://vitest.dev/guide/filtering.html
|
|
210
|
+
- https://vitest.dev/guide/cli.html
|
|
211
|
+
-->
|