vitest-plugin-vis 3.1.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/esm/client-api.d.ts +1 -0
- package/esm/client-api.d.ts.map +1 -1
- package/esm/client-api.js +1 -0
- package/esm/config/types.d.ts +4 -2
- package/esm/config/types.d.ts.map +1 -1
- package/esm/config/vis.js +1 -1
- package/esm/server/snapshot_path.d.ts +9 -0
- package/esm/server/snapshot_path.d.ts.map +1 -1
- package/esm/server/snapshot_path.js +9 -1
- package/esm/server-utils.d.ts +1 -0
- package/esm/server-utils.d.ts.map +1 -1
- package/esm/server-utils.js +1 -0
- package/esm/setup.d.ts.map +1 -1
- package/esm/setup.js +1 -2
- package/package.json +16 -6
- package/src/changelog.mdx +6 -0
- package/src/client/auto_snapshot_options.mdx +255 -0
- package/src/client/expect/to_match_image_snapshot.mdx +298 -0
- package/src/client/page/has_image_snapshot.mdx +328 -0
- package/src/client/page/to_match_image_snapshot.mdx +471 -0
- package/src/client-api.ts +1 -0
- package/src/config/types.ts +4 -2
- package/src/config/vis.ts +1 -1
- package/src/config.vis.mdx +76 -0
- package/src/overview.mdx +92 -0
- package/src/server/snapshot_path.ts +9 -1
- package/src/server-utils.ts +1 -0
- package/src/setup.create_vis.mdx +12 -0
- package/src/setup.ts +1 -2
- package/src/setup.vis.mdx +122 -0
- package/src/shared/trim_common_folder.mdx +153 -0
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
import { Meta } from "@storybook/addon-docs/blocks";
|
|
2
|
+
|
|
3
|
+
<Meta title="page/toMatchImageSnapshot" />
|
|
4
|
+
|
|
5
|
+
# page.toMatchImageSnapshot
|
|
6
|
+
|
|
7
|
+
`page.toMatchImageSnapshot()` is a method that captures and compares full page or viewport screenshots against baseline images.
|
|
8
|
+
|
|
9
|
+
Unlike `expect().toMatchImageSnapshot()` which targets specific elements, `page.toMatchImageSnapshot()` is designed for capturing entire pages or viewports, making it ideal for full-page visual regression testing.
|
|
10
|
+
|
|
11
|
+
## Basic Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { page } from '@vitest/browser/context'
|
|
15
|
+
|
|
16
|
+
it('should take a page snapshot', async () => {
|
|
17
|
+
// Your test setup here
|
|
18
|
+
render(<MyApp />)
|
|
19
|
+
|
|
20
|
+
// Take a viewport snapshot
|
|
21
|
+
await page.toMatchImageSnapshot()
|
|
22
|
+
})
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Options
|
|
26
|
+
|
|
27
|
+
The `page.toMatchImageSnapshot()` method accepts an optional options object with the following properties:
|
|
28
|
+
|
|
29
|
+
### Page Capture Options
|
|
30
|
+
|
|
31
|
+
#### `fullPage`
|
|
32
|
+
|
|
33
|
+
Capture the entire page including content below the fold, not just the visible viewport.
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
it('should capture full page', async () => {
|
|
37
|
+
render(<LongPageContent />)
|
|
38
|
+
|
|
39
|
+
// Capture the entire scrollable page
|
|
40
|
+
await page.toMatchImageSnapshot({
|
|
41
|
+
fullPage: true
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('should capture viewport only', async () => {
|
|
46
|
+
render(<LongPageContent />)
|
|
47
|
+
|
|
48
|
+
// Capture only the visible viewport (default)
|
|
49
|
+
await page.toMatchImageSnapshot({
|
|
50
|
+
fullPage: false // default
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Snapshot Identification
|
|
56
|
+
|
|
57
|
+
#### `snapshotKey`
|
|
58
|
+
|
|
59
|
+
Customize the snapshot key/name for the snapshot file.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
it('should use custom snapshot key', async () => {
|
|
63
|
+
render(<MyApp />)
|
|
64
|
+
|
|
65
|
+
await page.toMatchImageSnapshot({
|
|
66
|
+
snapshotKey: 'homepage_layout'
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Failure Threshold
|
|
72
|
+
|
|
73
|
+
#### `failureThreshold` and `failureThresholdType`
|
|
74
|
+
|
|
75
|
+
Control how much difference is allowed before the test fails.
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
// Allow up to 100 pixels to be different
|
|
79
|
+
it('should allow pixel differences', async () => {
|
|
80
|
+
render(<MyApp />)
|
|
81
|
+
|
|
82
|
+
await page.toMatchImageSnapshot({
|
|
83
|
+
failureThreshold: 100,
|
|
84
|
+
failureThresholdType: 'pixel' // default
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
// Allow up to 0.5% difference
|
|
89
|
+
it('should allow percentage differences', async () => {
|
|
90
|
+
render(<MyApp />)
|
|
91
|
+
|
|
92
|
+
await page.toMatchImageSnapshot({
|
|
93
|
+
failureThreshold: 0.005,
|
|
94
|
+
failureThresholdType: 'percent'
|
|
95
|
+
})
|
|
96
|
+
})
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Comparison Methods
|
|
100
|
+
|
|
101
|
+
#### `comparisonMethod`
|
|
102
|
+
|
|
103
|
+
Choose between pixel-by-pixel comparison or structural similarity comparison.
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
// Default pixel comparison
|
|
107
|
+
it('should use pixel comparison', async () => {
|
|
108
|
+
render(<MyApp />)
|
|
109
|
+
|
|
110
|
+
await page.toMatchImageSnapshot({
|
|
111
|
+
comparisonMethod: 'pixel' // default
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
// SSIM (Structural Similarity) comparison
|
|
116
|
+
it('should use SSIM comparison', async () => {
|
|
117
|
+
render(<MyApp />)
|
|
118
|
+
|
|
119
|
+
await page.toMatchImageSnapshot({
|
|
120
|
+
comparisonMethod: 'ssim'
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Diff Options
|
|
126
|
+
|
|
127
|
+
#### `diffOptions` for Pixel Comparison
|
|
128
|
+
|
|
129
|
+
When using `comparisonMethod: 'pixel'` (default), you can customize pixelmatch options:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
it('should use custom pixel diff options', async () => {
|
|
133
|
+
render(<MyApp />)
|
|
134
|
+
|
|
135
|
+
await page.toMatchImageSnapshot({
|
|
136
|
+
comparisonMethod: 'pixel',
|
|
137
|
+
diffOptions: {
|
|
138
|
+
threshold: 0.1, // Matching threshold (0-1, default: 0.1)
|
|
139
|
+
includeAA: false, // Include anti-aliased pixels (default: false)
|
|
140
|
+
alpha: 0.1, // Blending factor for unchanged pixels (default: 0.1)
|
|
141
|
+
aaColor: [255, 255, 0], // Color for anti-aliased pixels [R, G, B]
|
|
142
|
+
diffColor: [255, 0, 0], // Color for different pixels [R, G, B]
|
|
143
|
+
diffColorAlt: null, // Alternative color for dark-on-light differences
|
|
144
|
+
diffMask: false // Draw diff over transparent background (default: false)
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
})
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### `diffOptions` for SSIM Comparison
|
|
151
|
+
|
|
152
|
+
When using `comparisonMethod: 'ssim'`, you can customize SSIM options:
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
it('should use custom SSIM diff options', async () => {
|
|
156
|
+
render(<MyApp />)
|
|
157
|
+
|
|
158
|
+
await page.toMatchImageSnapshot({
|
|
159
|
+
comparisonMethod: 'ssim',
|
|
160
|
+
diffOptions: {
|
|
161
|
+
ssim: 'bezkrovny', // 'bezkrovny' (fast, default) | 'fast' (accurate) | 'weber' | 'original'
|
|
162
|
+
windowSize: 11, // Window size for SSIM calculation (default: 11)
|
|
163
|
+
k1: 0.01, // First stability constant (default: 0.01)
|
|
164
|
+
k2: 0.03, // Second stability constant (default: 0.03)
|
|
165
|
+
bitDepth: 8, // Bits per channel (default: 8)
|
|
166
|
+
downsample: 'original' // 'original' | 'fast' | false
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
})
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Timeout
|
|
173
|
+
|
|
174
|
+
#### `timeout`
|
|
175
|
+
|
|
176
|
+
Set a timeout for taking the snapshot.
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
it('should use custom timeout', async () => {
|
|
180
|
+
render(<MyApp />)
|
|
181
|
+
|
|
182
|
+
await page.toMatchImageSnapshot({
|
|
183
|
+
timeout: 60000 // 60 seconds (default: 30000ms)
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Testing Utilities
|
|
189
|
+
|
|
190
|
+
#### `expectToFail`
|
|
191
|
+
|
|
192
|
+
Expect the matcher to fail - useful for testing that changes are detected.
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
it('should detect page differences', async () => {
|
|
196
|
+
render(<MyApp />)
|
|
197
|
+
|
|
198
|
+
// First, create the baseline
|
|
199
|
+
if (!(await page.hasImageSnapshot({ snapshotKey: 'page_changes' }))) {
|
|
200
|
+
await page.toMatchImageSnapshot({
|
|
201
|
+
snapshotKey: 'page_changes'
|
|
202
|
+
})
|
|
203
|
+
return
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Modify the page
|
|
207
|
+
document.body.style.backgroundColor = 'red'
|
|
208
|
+
|
|
209
|
+
// Expect the test to fail due to changes
|
|
210
|
+
await page.toMatchImageSnapshot({
|
|
211
|
+
snapshotKey: 'page_changes',
|
|
212
|
+
expectToFail: true
|
|
213
|
+
})
|
|
214
|
+
.then(
|
|
215
|
+
() => {
|
|
216
|
+
throw new Error('Should not reach - expected failure')
|
|
217
|
+
},
|
|
218
|
+
(error) => {
|
|
219
|
+
expect(error.message).toMatch(/Expected image to match but was differ by \d+ pixels/)
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
})
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Complete Example
|
|
226
|
+
|
|
227
|
+
Here's a comprehensive example showing multiple options:
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
it('should demonstrate all page snapshot options', async () => {
|
|
231
|
+
render(<MyComplexApp />)
|
|
232
|
+
|
|
233
|
+
await page.toMatchImageSnapshot({
|
|
234
|
+
// Page capture
|
|
235
|
+
fullPage: true,
|
|
236
|
+
|
|
237
|
+
// Snapshot identification
|
|
238
|
+
snapshotKey: 'full_app_layout',
|
|
239
|
+
|
|
240
|
+
// Failure threshold
|
|
241
|
+
failureThreshold: 0.01,
|
|
242
|
+
failureThresholdType: 'percent',
|
|
243
|
+
|
|
244
|
+
// Comparison method
|
|
245
|
+
comparisonMethod: 'ssim',
|
|
246
|
+
|
|
247
|
+
// SSIM-specific options
|
|
248
|
+
diffOptions: {
|
|
249
|
+
ssim: 'bezkrovny',
|
|
250
|
+
windowSize: 11,
|
|
251
|
+
k1: 0.01,
|
|
252
|
+
k2: 0.03
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
// Timeout
|
|
256
|
+
timeout: 45000,
|
|
257
|
+
|
|
258
|
+
// Testing utility
|
|
259
|
+
expectToFail: false
|
|
260
|
+
})
|
|
261
|
+
})
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Use Cases
|
|
265
|
+
|
|
266
|
+
### Full Page Layout Testing
|
|
267
|
+
|
|
268
|
+
Perfect for testing complete page layouts, including content below the fold:
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
it('should capture entire homepage layout', async () => {
|
|
272
|
+
render(<Homepage />)
|
|
273
|
+
|
|
274
|
+
await page.toMatchImageSnapshot({
|
|
275
|
+
fullPage: true,
|
|
276
|
+
snapshotKey: 'homepage_complete',
|
|
277
|
+
failureThreshold: 0.01,
|
|
278
|
+
failureThresholdType: 'percent'
|
|
279
|
+
})
|
|
280
|
+
})
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Viewport Testing
|
|
284
|
+
|
|
285
|
+
Test how your application appears in the current viewport:
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
it('should capture above-the-fold content', async () => {
|
|
289
|
+
render(<LandingPage />)
|
|
290
|
+
|
|
291
|
+
await page.toMatchImageSnapshot({
|
|
292
|
+
fullPage: false, // default - viewport only
|
|
293
|
+
snapshotKey: 'landing_viewport'
|
|
294
|
+
})
|
|
295
|
+
})
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Responsive Design Testing
|
|
299
|
+
|
|
300
|
+
Test different viewport sizes by combining with browser configuration:
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
it('should test mobile layout', async () => {
|
|
304
|
+
// Assuming viewport is configured for mobile in test setup
|
|
305
|
+
render(<ResponsiveApp />)
|
|
306
|
+
|
|
307
|
+
await page.toMatchImageSnapshot({
|
|
308
|
+
snapshotKey: 'mobile_layout',
|
|
309
|
+
fullPage: true
|
|
310
|
+
})
|
|
311
|
+
})
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Cross-Browser Consistency
|
|
315
|
+
|
|
316
|
+
Ensure consistent rendering across different browsers:
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
it('should render consistently across browsers', async () => {
|
|
320
|
+
render(<CrossBrowserApp />)
|
|
321
|
+
|
|
322
|
+
await page.toMatchImageSnapshot({
|
|
323
|
+
snapshotKey: 'cross_browser_test',
|
|
324
|
+
comparisonMethod: 'ssim', // More forgiving for browser differences
|
|
325
|
+
failureThreshold: 0.02,
|
|
326
|
+
failureThresholdType: 'percent'
|
|
327
|
+
})
|
|
328
|
+
})
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Comparison Method Recommendations
|
|
332
|
+
|
|
333
|
+
### When to use Pixel Comparison (`comparisonMethod: 'pixel'`)
|
|
334
|
+
|
|
335
|
+
- **Default choice** for most page-level visual regression tests
|
|
336
|
+
- **Precise detection** of layout shifts, color changes, and text modifications
|
|
337
|
+
- **Good for** detecting critical visual regressions
|
|
338
|
+
- **Fast execution** for most page sizes
|
|
339
|
+
|
|
340
|
+
### When to use SSIM Comparison (`comparisonMethod: 'ssim'`)
|
|
341
|
+
|
|
342
|
+
- **Structural similarity** comparison that's more forgiving of minor rendering differences
|
|
343
|
+
- **Reduced false positives** from browser-specific rendering variations
|
|
344
|
+
- **Better for** pages with complex graphics, gradients, or anti-aliased content
|
|
345
|
+
- **Recommended for** cross-browser testing where minor pixel differences are expected
|
|
346
|
+
|
|
347
|
+
```ts
|
|
348
|
+
// Recommended SSIM configuration for page testing
|
|
349
|
+
it('should use recommended SSIM settings for pages', async () => {
|
|
350
|
+
render(<MyApp />)
|
|
351
|
+
|
|
352
|
+
await page.toMatchImageSnapshot({
|
|
353
|
+
comparisonMethod: 'ssim',
|
|
354
|
+
failureThreshold: 0.01,
|
|
355
|
+
failureThresholdType: 'percent',
|
|
356
|
+
diffOptions: {
|
|
357
|
+
ssim: 'bezkrovny' // Fast and accurate for most cases
|
|
358
|
+
}
|
|
359
|
+
})
|
|
360
|
+
})
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
## Best Practices
|
|
364
|
+
|
|
365
|
+
### 1. Use Descriptive Snapshot Keys
|
|
366
|
+
|
|
367
|
+
```ts
|
|
368
|
+
// Good
|
|
369
|
+
await page.toMatchImageSnapshot({
|
|
370
|
+
snapshotKey: 'dashboard_with_data_loaded'
|
|
371
|
+
})
|
|
372
|
+
|
|
373
|
+
// Better
|
|
374
|
+
await page.toMatchImageSnapshot({
|
|
375
|
+
snapshotKey: 'user_dashboard_logged_in_state'
|
|
376
|
+
})
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### 2. Consider Page Loading States
|
|
380
|
+
|
|
381
|
+
```ts
|
|
382
|
+
it('should wait for page to be fully loaded', async () => {
|
|
383
|
+
render(<AsyncApp />)
|
|
384
|
+
|
|
385
|
+
// Wait for async content to load
|
|
386
|
+
await page.waitForSelector('[data-testid="content-loaded"]')
|
|
387
|
+
|
|
388
|
+
await page.toMatchImageSnapshot({
|
|
389
|
+
snapshotKey: 'fully_loaded_page'
|
|
390
|
+
})
|
|
391
|
+
})
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### 3. Use Appropriate Failure Thresholds
|
|
395
|
+
|
|
396
|
+
```ts
|
|
397
|
+
// For critical UI elements - strict comparison
|
|
398
|
+
await page.toMatchImageSnapshot({
|
|
399
|
+
snapshotKey: 'critical_layout',
|
|
400
|
+
failureThreshold: 0 // No differences allowed
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
// For pages with dynamic content - more lenient
|
|
404
|
+
await page.toMatchImageSnapshot({
|
|
405
|
+
snapshotKey: 'dynamic_content_page',
|
|
406
|
+
failureThreshold: 0.5,
|
|
407
|
+
failureThresholdType: 'percent'
|
|
408
|
+
})
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### 4. Choose Full Page vs Viewport Strategically
|
|
412
|
+
|
|
413
|
+
```ts
|
|
414
|
+
// Use fullPage for complete layout testing
|
|
415
|
+
await page.toMatchImageSnapshot({
|
|
416
|
+
fullPage: true,
|
|
417
|
+
snapshotKey: 'complete_article_layout'
|
|
418
|
+
})
|
|
419
|
+
|
|
420
|
+
// Use viewport for above-the-fold testing
|
|
421
|
+
await page.toMatchImageSnapshot({
|
|
422
|
+
fullPage: false,
|
|
423
|
+
snapshotKey: 'hero_section'
|
|
424
|
+
})
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## Limitations
|
|
428
|
+
|
|
429
|
+
### Concurrent Tests
|
|
430
|
+
|
|
431
|
+
`page.toMatchImageSnapshot()` cannot be used in concurrent tests as they share the same browser environment:
|
|
432
|
+
|
|
433
|
+
```ts
|
|
434
|
+
// ❌ This will throw an error
|
|
435
|
+
it.concurrent('concurrent test', async () => {
|
|
436
|
+
await page.toMatchImageSnapshot() // Error: cannot be called in concurrent test
|
|
437
|
+
})
|
|
438
|
+
|
|
439
|
+
// ✅ Use regular tests instead
|
|
440
|
+
it('sequential test', async () => {
|
|
441
|
+
await page.toMatchImageSnapshot() // Works fine
|
|
442
|
+
})
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### WebDriverIO Considerations
|
|
446
|
+
|
|
447
|
+
When using WebDriverIO as the browser provider:
|
|
448
|
+
|
|
449
|
+
- `fullPage` option may not work correctly in headless mode
|
|
450
|
+
- Consider setting explicit window size in configuration
|
|
451
|
+
- Playwright is recommended for more reliable visual testing
|
|
452
|
+
|
|
453
|
+
```ts
|
|
454
|
+
// vitest.config.ts - WebDriverIO workaround
|
|
455
|
+
export default {
|
|
456
|
+
test: {
|
|
457
|
+
browser: {
|
|
458
|
+
instances: [
|
|
459
|
+
{
|
|
460
|
+
browser: 'chrome',
|
|
461
|
+
capabilities: {
|
|
462
|
+
'goog:chromeOptions': {
|
|
463
|
+
args: ['--window-size=1280,720']
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
]
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
```
|
package/src/client-api.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from './client/actions/match_page_image_snapshot_action.ts'
|
|
|
7
7
|
export { setAutoSnapshotOptions, type MetaTask } from './client/auto_snapshot_options.ts'
|
|
8
8
|
export * from './client/expect/expectation_result.ts'
|
|
9
9
|
export type * from './client/expect/to_match_image_snapshot.types.ts'
|
|
10
|
+
export * from './client/setup/create_vis.ts'
|
|
10
11
|
export * from './client/task_id.ts'
|
|
11
12
|
export * from './shared/constants.ts'
|
|
12
13
|
export type * from './shared/types.ts'
|
package/src/config/types.ts
CHANGED
|
@@ -34,12 +34,14 @@ export type VisOptions<M extends ComparisonMethod = 'pixel'> = (M extends 'ssim'
|
|
|
34
34
|
/**
|
|
35
35
|
* Loads the `test.setupFiles` of the specified preset.
|
|
36
36
|
*
|
|
37
|
-
* Note:
|
|
37
|
+
* Note:
|
|
38
|
+
* - 'enable` is deprecated. Use `manual` for the same effect.
|
|
39
|
+
* - 'none` is deprecated. Use `custom` for the same effect.
|
|
38
40
|
*
|
|
39
41
|
* @default 'auto'
|
|
40
42
|
*
|
|
41
43
|
*/
|
|
42
|
-
preset?: 'enable' | 'manual' | 'auto' | 'none' | undefined
|
|
44
|
+
preset?: 'enable' | 'manual' | 'auto' | 'custom' | 'none' | undefined
|
|
43
45
|
/**
|
|
44
46
|
* The snapshot folder relative to the root of the project.
|
|
45
47
|
*
|
package/src/config/vis.ts
CHANGED
|
@@ -23,7 +23,7 @@ export function vis<M extends ComparisonMethod = 'pixel'>(options: VisOptions<M>
|
|
|
23
23
|
name: undefined as unknown as string,
|
|
24
24
|
commands,
|
|
25
25
|
},
|
|
26
|
-
setupFiles: preset && preset !== 'none' ? [`vitest-plugin-vis/presets/${preset}`] : [],
|
|
26
|
+
setupFiles: preset && preset !== 'none' && preset !== 'custom' ? [`vitest-plugin-vis/presets/${preset}`] : [],
|
|
27
27
|
},
|
|
28
28
|
}
|
|
29
29
|
},
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Meta, Source } from "@storybook/addon-docs/blocks";
|
|
2
|
+
|
|
3
|
+
<Meta title="vitest-plugin-vis/config/vis" />
|
|
4
|
+
|
|
5
|
+
`vis` from `vitest-plugin-vis/config` is the Vitest plugin of `vitest-plugin-vis`.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
// vitest.config.ts
|
|
9
|
+
import { vis } from 'vitest-plugin-vis/config'
|
|
10
|
+
|
|
11
|
+
export default defineConfig({
|
|
12
|
+
plugins: [vis()],
|
|
13
|
+
})
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
It provides a lot of options to customize the behavior of the plugin.
|
|
17
|
+
(You can learn more about the default configuration [here](/docs/overview--docs#basic-configuration).)
|
|
18
|
+
|
|
19
|
+
## Preset
|
|
20
|
+
|
|
21
|
+
The `preset` option set up typical visual testing strategies.
|
|
22
|
+
|
|
23
|
+
### `auto`
|
|
24
|
+
|
|
25
|
+
The `auto` preset is the default preset.
|
|
26
|
+
It will take a snapshot of the page at the end of each rendering test.
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
// vitest.config.ts
|
|
30
|
+
import { vis } from 'vitest-plugin-vis/config'
|
|
31
|
+
|
|
32
|
+
export default defineConfig({
|
|
33
|
+
plugins: [vis({ preset: 'auto' })],
|
|
34
|
+
})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### `manual`
|
|
38
|
+
|
|
39
|
+
The `manual` preset is for manual testing.
|
|
40
|
+
It will not take any snapshot automatically.
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
// vitest.config.ts
|
|
44
|
+
import { vis } from 'vitest-plugin-vis/config'
|
|
45
|
+
|
|
46
|
+
export default defineConfig({
|
|
47
|
+
plugins: [vis({ preset: 'manual' })],
|
|
48
|
+
})
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
See [Manual Snapshot](/docs/expect-tomatchimagesnapshot--docs) section on how to take an image snapshot manually.
|
|
52
|
+
|
|
53
|
+
### `custom`
|
|
54
|
+
|
|
55
|
+
The `custom` preset is for advanced users.
|
|
56
|
+
It will not take any snapshot automatically.
|
|
57
|
+
You need to set up your own visual testing strategy in `vitest.setup.ts`.
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
// vitest.config.ts
|
|
61
|
+
import { vis } from 'vitest-plugin-vis/config'
|
|
62
|
+
|
|
63
|
+
export default defineConfig({
|
|
64
|
+
plugins: [vis({ preset: 'custom' })],
|
|
65
|
+
test: {
|
|
66
|
+
// Set up your own visual testing strategy in `vitest.setup.ts`.
|
|
67
|
+
setupFiles: ['./vitest.setup.ts'],
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
When using the `custom` preset, you can set up your own visual testing strategy in `vitest.setup.ts` using the [vis](/docs/vitest-plugin-vis-setup-vis--docs) object from `vitest-plugin-vis/setup`.
|
|
73
|
+
|
|
74
|
+
[vitest-plugin-vis]: https://npmjs.org/package/vitest-plugin-vis
|
|
75
|
+
|
|
76
|
+
|
package/src/overview.mdx
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Meta, Markdown } from "@storybook/addon-docs/blocks";
|
|
2
|
+
|
|
3
|
+
<Meta title="Overview" />
|
|
4
|
+
|
|
5
|
+
# Vitest Visual Testing Plugin
|
|
6
|
+
|
|
7
|
+
[vitest-plugin-vis] provides visual testing for [Vitest] when running in [Browser Mode][browser-mode].
|
|
8
|
+
|
|
9
|
+
It offers a new unique features:
|
|
10
|
+
|
|
11
|
+
- You can capture and compare image snapshot both automatically and manually.
|
|
12
|
+
- You can take a snapshot of the whole page or a specific component.
|
|
13
|
+
- You can take snapshots in different environments, platform, browser, screen size and themes.
|
|
14
|
+
- The snapshots are stored locally in the `__vis__` directory.
|
|
15
|
+
- You can enable, disable, and customize how the snapshots are taken and compared.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
[vitest-plugin-vis] works with Vitest 2.0.0 or later.
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npm install --save-dev vitest-plugin-vis
|
|
23
|
+
|
|
24
|
+
pnpm add --save-dev vitest-plugin-vis
|
|
25
|
+
|
|
26
|
+
yarn add --save-dev vitest-plugin-vis
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Basic Configuration
|
|
30
|
+
|
|
31
|
+
To use [vitest-plugin-vis], you need to add it to your Vitest configuration.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
// vitest.config.ts
|
|
35
|
+
import { defineConfig } from 'vitest/config'
|
|
36
|
+
import { vis } from 'vitest-plugin-vis/config'
|
|
37
|
+
|
|
38
|
+
export default defineConfig({
|
|
39
|
+
plugins: [vis()],
|
|
40
|
+
test: {
|
|
41
|
+
// vitest v2
|
|
42
|
+
browser: {
|
|
43
|
+
enabled: true,
|
|
44
|
+
provider: 'playwright',
|
|
45
|
+
name: 'chromium',
|
|
46
|
+
},
|
|
47
|
+
// vitest v3
|
|
48
|
+
browser: {
|
|
49
|
+
enabled: true,
|
|
50
|
+
provider: 'playwright',
|
|
51
|
+
instances: [
|
|
52
|
+
{ browser: 'chromium' }
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This default configuration will:
|
|
60
|
+
|
|
61
|
+
- Use the `auto` preset, taking image snapshot at the end on each rendering test.
|
|
62
|
+
- Use `pixelmatch` as the image comparison method.
|
|
63
|
+
- Set config to compare image snapshot with a failure threshold of `0 pixels`.
|
|
64
|
+
- Timeout for image comparison is set to `30000 ms`.
|
|
65
|
+
- Save image snapshots in the `<project-root>/__vis__` directory.
|
|
66
|
+
|
|
67
|
+
## Update .gitignore
|
|
68
|
+
|
|
69
|
+
By default, [vitest-plugin-vis] will save image snapshots in the `<project-root>/__vis__` directory.
|
|
70
|
+
|
|
71
|
+
Under this directory, you will find different set of snapshots for different environments:
|
|
72
|
+
|
|
73
|
+
- `local`: For snapshots taken locally.
|
|
74
|
+
- `<platform: ubuntu | darwin | win32>`: Fom snapshots taken in respective CI.
|
|
75
|
+
|
|
76
|
+
In each platform directory, there are 3 directories:
|
|
77
|
+
|
|
78
|
+
- `__baselines__`: The directory for the baseline snapshots. This should be committed to the repository (except for `local`).
|
|
79
|
+
- `__results__`: The directory for the current snapshots created when Vitest runs.
|
|
80
|
+
- `__diffs__`: The directory for the diffs between the current snapshot and the baseline snapshot.
|
|
81
|
+
|
|
82
|
+
Because of that, you should add the following lines to your `.gitignore` file:
|
|
83
|
+
|
|
84
|
+
```gitignore
|
|
85
|
+
**/__vis__/local
|
|
86
|
+
**/__vis__/**/__diffs__
|
|
87
|
+
**/__vis__/**/__results__
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
[browser-mode]: https://vitest.dev/guide/browser
|
|
91
|
+
[vitest]: https://vitest.dev
|
|
92
|
+
[vitest-plugin-vis]: https://npmjs.org/package/vitest-plugin-vis
|
|
@@ -19,7 +19,15 @@ export function resolveSnapshotRootDir(browserCommandContext: PartialBrowserComm
|
|
|
19
19
|
})
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Gets the root directory for storing snapshots.
|
|
24
|
+
*
|
|
25
|
+
* @param snapshotRootDir - Base directory for snapshots. Defaults to `__vis__`.
|
|
26
|
+
* @returns The full snapshot root directory path, which includes a platform-specific subdirectory:
|
|
27
|
+
* - When running in CI: `<snapshotRootDir>/<platform>` (e.g. `__vis__/linux`)
|
|
28
|
+
* - When running locally: `<snapshotRootDir>/local`
|
|
29
|
+
*/
|
|
30
|
+
export function getSnapshotRootDir(snapshotRootDir = SNAPSHOT_ROOT_DIR) {
|
|
23
31
|
return `${snapshotRootDir}/${ci ? platform : 'local'}`
|
|
24
32
|
}
|
|
25
33
|
|
package/src/server-utils.ts
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Meta, Markdown ,Canvas} from "@storybook/addon-docs/blocks";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
tags={['deprecated']}
|
|
5
|
+
title="vitest-plugin-vis/setup/createVis"
|
|
6
|
+
/>
|
|
7
|
+
|
|
8
|
+
🪦 Deprecated
|
|
9
|
+
|
|
10
|
+
`createVis` in `vitest-plugin-vis/setup` is deprecated.
|
|
11
|
+
|
|
12
|
+
It is moved to `/client-api`.
|