Skip to content

Manual snapshots

Besides automatic snapshot, you can capture image snapshot manually.

import { expect } from '@storybook/test'
// `page` and the like are proxies of `@vitest/browser/context` to work within storybook
import { page } from 'storybook-addon-vis'
export const PageSnapshot = {
// typically you want to disable automatic snapshot when using manual snapshot
// but you can use both at the same time.
tags: ['!snapshot'],
async play({ canvasElement }) {
await expect(canvasElement).toMatchImageSnapshot(/* options */)
}
}
export const ElementSnapshot = {
// typically you want to disable automatic snapshot when using manual snapshot
// but you can use both at the same time.
tags: ['!snapshot'],
async play({ canvas }) {
const element = await canvas.getByTestid('subject')
await expect(element).toMatchImageSnapshot(/* options */)
}
}

While less common, you can also check if a snapshot exists:

import { hasImageSnapshot } from 'storybook-addon-vis'
export const HasImageSnapshot = {
tags: ['!snapshot'],
loaders: [async () => ({ hasImageSnapshot: await hasImageSnapshot(/* options */) })],
render(_, { loaded: { hasImageSnapshot } }) {
return <div data-testid="subject">Has snapshot: {String(hasImageSnapshot)}</div>
},
async play({ canvas, loaded: { hasImageSnapshot } }) {
const subject = canvas.getByTestId('subject')
if (!hasImageSnapshot) {
await expect(subject).toMatchImageSnapshot()
return
}
// This will only execute in Vitest
await expect(subject)
.toMatchImageSnapshot()
.then(
() => {
throw new Error('Should not reach')
},
(error) => {
expect(error.message).toMatch(/Expected image to match but was differ by \d+ pixels./)
},
)
},
}

This is useful when you are performing some negative test. In a plain Storybook preview hasImageSnapshot() always returns false, because the preview cannot read snapshot files.

To use the Chrome DevTools Protocol from a story, see Chrome DevTools Protocol.