Skip to content

vis (config)

vis from vitest-plugin-vis/config is the Vitest plugin of vitest-plugin-vis. This is not the same vis as the setup object exported from vitest-plugin-vis/setup.

vitest.config.ts
import { vis } from 'vitest-plugin-vis/config'
export default defineConfig({
plugins: [vis()],
})

vis() works with zero config. The options below customize its behavior. See also the config overview for how the snapshot path is built.

The preset option sets up a typical visual testing strategy.

auto is the default preset. It takes a snapshot of the page at the end of each rendering test. It adds vitest-plugin-vis/presets/auto to test.setupFiles.

vitest.config.ts
import { vis } from 'vitest-plugin-vis/config'
export default defineConfig({
plugins: [vis({ preset: 'auto' })],
})

When you pass an options object without preset (for example vis({})), no preset is applied and test.setupFiles stays empty.

The manual preset does not take any snapshot automatically. It adds vitest-plugin-vis/presets/manual to test.setupFiles.

vitest.config.ts
import { vis } from 'vitest-plugin-vis/config'
export default defineConfig({
plugins: [vis({ preset: 'manual' })],
})

See expect().toMatchImageSnapshot() on how to take an image snapshot manually.

The custom preset is for advanced users. It adds no setup file and takes no snapshot automatically. You set up your own visual testing strategy in vitest.setup.ts.

vitest.config.ts
import { vis } from 'vitest-plugin-vis/config'
export default defineConfig({
plugins: [vis({ preset: 'custom' })],
test: {
// Set up your own visual testing strategy in `vitest.setup.ts`.
setupFiles: ['./vitest.setup.ts'],
},
})

Use vis.setup() from vitest-plugin-vis/setup in vitest.setup.ts.

By default, the snapshot is taken from the document.body element.

If you establish a common pattern in your tests, set subject to a selector. For example, if you enforce a data-testid attribute on the element you want to snapshot:

vitest.config.ts
import { vis } from 'vitest-plugin-vis/config'
export default defineConfig({
plugins: [vis({ subject: '[data-testid="subject"]' })],
})

By default, snapshots are saved in the __vis__ folder relative to the project root. To save them elsewhere, set snapshotRootDir:

vitest.config.ts
import { vis } from 'vitest-plugin-vis/config'
export default defineConfig({
plugins: [
vis({
// save the snapshot in the `<projectRoot>/custom` folder
snapshotRootDir: 'custom',
}),
],
})

Besides a static path, you can provide a function that receives this context:

  • ci: whether the code is running in a CI environment.
  • platform: the platform string (for example linux, darwin, win32).
  • browserName: the name of the browser (for example chromium, firefox).
  • providerName: the name of the provider (for example playwright, webdriverio).
  • screenshotFailures: whether screenshot failures are enabled.
  • screenshotDirectory: the directory to save the screenshot.

The default function is:

({ ci, platform }) => `__vis__/${ci ? platform : 'local'}`

Customize the snapshot sub-path. The default is ({ subpath }) => trimCommonFolder(subpath). To keep the folder structure, return the sub-path as is:

vis({ snapshotSubpath: ({ subpath }) => subpath })

trimCommonFolder is exported if you want to use it in your own function.

snapshotKey specifies the key of the auto snapshot. The default is auto.

vis({ snapshotKey: 'custom' })

A key that contains a dash is rejected when the plugin loads, with the error Snapshot key cannot contain dash. Use alphanumeric characters and underscores.

comparisonMethod specifies the comparison method: 'pixel' (the default) or 'ssim'.

vitest.config.ts
import { vis } from 'vitest-plugin-vis/config'
export default defineConfig({
plugins: [vis({ comparisonMethod: 'ssim' })],
})

diffOptions specifies the options of the comparison. What it accepts depends on comparisonMethod.

For pixel comparison, it accepts the options of pixelmatch:

vitest.config.ts
import { vis } from 'vitest-plugin-vis/config'
export default defineConfig({
plugins: [
vis({
comparisonMethod: 'pixel',
diffOptions: {
threshold: 0.1, // Matching threshold (0-1), default: 0.1
includeAA: false, // Include anti-aliased pixels in comparison
alpha: 0.1, // Blending factor of unchanged pixels
aaColor: [255, 255, 0], // Color of anti-aliased pixels in diff
diffColor: [255, 0, 255], // Color of different pixels in diff
},
}),
],
})

For option details, see the pixelmatch documentation.

If your images have gradients, shadows, or anti-aliasing, SSIM (Structural Similarity Index) might be a better fit. It is designed to match how humans perceive image differences, which means fewer false positives when minor rendering differences do not matter.

vitest.config.ts
import { vis } from 'vitest-plugin-vis/config'
export default defineConfig({
plugins: [
vis({
comparisonMethod: 'ssim',
diffOptions: {
ssim: 'bezkrovny', // 'bezkrovny' (fast, default) | 'fast' (accurate) | 'weber' | 'original'
windowSize: 11, // Window size for SSIM calculation (default: 11)
k1: 0.01, // First stability constant (default: 0.01)
k2: 0.03, // Second stability constant (default: 0.03)
bitDepth: 8, // Bits per channel (default: 8)
downsample: 'original', // 'original' | 'fast' | false
},
}),
],
})

For option details, see the ssim documentation. The ssim.js repository is archived, so an issue with ssim comparison may not be fixed.

A failure threshold sets how much difference is acceptable before a test fails. failureThresholdType is 'pixel' (the default) or 'percent'.

vis({
failureThreshold: 100, // Allow 100 pixels to differ
failureThresholdType: 'pixel', // Default: 'pixel'
})

Percentages scale better across image sizes.

vis({
failureThreshold: 0.05, // Allow 5% of pixels to differ
failureThresholdType: 'percent',
})

This is the default behavior: any pixel difference fails.

vis({
failureThreshold: 0,
failureThresholdType: 'pixel',
})

When a snapshot mismatches, vitest-plugin-vis writes a review image (<name>.review.png) next to the diff image. It places the baseline, result, and diff crops of each changed region side by side, so you or a coding agent can see what changed without opening the full images. The changed regions are also written to <name>.regions.json. See expect().toMatchImageSnapshot() for details.

To not write the review image:

vis({ reviewImage: false })

The timeout option sets the default timeout of a snapshot, in milliseconds. The default is 30 seconds.

vis({ timeout: 60000 }) // 60 seconds
vis({ timeout: 5000 }) // 5 seconds

When true, paths that would exceed Windows-safe limits are shortened. The default is false. The final path segment is replaced with {firstToken}-{hash12}{ext} when the full path length reaches 250 or a segment is longer than 255. snapshotRootDir itself is not rewritten.

vis({ shortenLongSnapshotPaths: true })

The spec checks only that the option is accepted. The description comes from the doc comment of the option in the source.