Skip to content

page.hasImageSnapshot()

page.hasImageSnapshot() checks whether an image snapshot exists for the current test.

Use it to run code conditionally on whether a snapshot was created before, for example for negative tests, or to handle a first run differently from later runs.

import { page } from 'vitest/browser'
it('should check if snapshot exists', async ({ expect }) => {
const hasSnapshot = await page.hasImageSnapshot()
if (!hasSnapshot) {
// First run - create the baseline snapshot
await expect(page.getByTestId('component')).toMatchImageSnapshot()
}
})

It returns a Promise<boolean>, so use await or .then().

The key that identifies the snapshot. If omitted, the default snapshot key of the test is used.

// A snapshot that does not exist
expect(await page.hasImageSnapshot({ snapshotKey: 'non_existing_snapshot' })).toBe(false)

The snapshotKey cannot contain a dash, because dashes are reserved for internal path separation:

// Throws: Snapshot key cannot contain dash
page.hasImageSnapshot({ snapshotKey: 'invalid-key' })
// Use underscores or camelCase instead
await page.hasImageSnapshot({ snapshotKey: 'valid_key' })
await page.hasImageSnapshot({ snapshotKey: 'validKey' })

Unlike the async result, the dash check throws synchronously.

it('returns true when the snapshot exists', async ({ expect }) => {
await render(<div data-testid="subject">hello</div>)
const subject = page.getByTestId('subject')
await expect(subject).toMatchImageSnapshot({ snapshotKey: 'existing_snapshot' })
expect(await page.hasImageSnapshot({ snapshotKey: 'existing_snapshot' })).toBe(true)
})

Create the baseline on the first run, compare on later runs

Section titled “Create the baseline on the first run, compare on later runs”

This pattern is used by the specs of expect().toMatchImageSnapshot() to test failures:

it('fails when the image is different', async ({ expect }) => {
const hasImageSnapshot = await page.hasImageSnapshot()
await render(<div data-testid="subject">{hasImageSnapshot ? 'Hello' : 'World'}</div>)
const subject = page.getByTestId('subject')
if (!hasImageSnapshot) {
await expect(subject).toMatchImageSnapshot()
return
}
await expect(subject).toMatchImageSnapshot({ expectToFail: true }).then(
() => {
throw new Error('Should not reach')
},
(error) => {
expect(error.message).toMatch(/Expected image to match but was differ by \d+ pixels./)
},
)
})

With vis.setup({ auto: false }), a test that renders content takes no auto snapshot:

expect(await page.hasImageSnapshot()).toBe(false)

Outside a test, it throws:

`hasImageSnapshot()` must be called in a test.

Concurrent tests share the same iframe, so page.hasImageSnapshot() throws in it.concurrent():

`hasImageSnapshot()` cannot be called in a concurrent test because concurrent tests run at the same time in the same iframe and affect each other's environment.

Use a regular it() instead.