import type { ViteUserConfig } from 'vitest/config'
import type { TestFsStructure } from '../../test-utils'
import { platform } from 'node:os'
import { resolve } from 'node:path'
import { describe, expect, test } from 'vitest'
import { runVitestCli, useFS } from '../../test-utils'
import { extractToMatchScreenshotPaths } from '../fixtures/expect-dom/utils'
import utilsContent from '../fixtures/expect-dom/utils?raw'
const testFilename = 'basic.test.ts'
const testName = 'screenshot-snapshot'
const bgColor = '#fff'
const testContent = /* ts */`
import { page, server } from 'vitest/browser'
import { describe, test } from 'vitest'
import { render } from './utils'
const dataTestId = 'inline-test'
test('${testName}', async ({ expect }) => {
render('
Inline Test
')
await expect(page.getByTestId(dataTestId)).toMatchScreenshot()
})
`
const browser = 'chromium'
export async function runInlineTests(
structure: TestFsStructure,
config: ViteUserConfig['test'] = {},
) {
const root = resolve(process.cwd(), `vitest-test-${crypto.randomUUID()}`)
const fs = useFS(root, {
...structure,
'vitest.config.ts': `
import { playwright } from '@vitest/browser-playwright'
export default {
test: {
browser: {
enabled: true,
screenshotFailures: false,
provider: playwright(),
headless: true,
instances: [{ browser: ${JSON.stringify(browser)} }],
},
reporters: ['verbose'],
...${JSON.stringify(config)},
},
}`,
})
const vitest = await runVitestCli({
nodeOptions: {
env: {
CI: 'false',
GITHUB_ACTIONS: undefined,
NO_COLOR: 'true',
},
},
}, '--root', root, '--watch')
return {
fs,
root,
...vitest,
}
}
describe('--watch', () => {
test(
'fails when creating a snapshot for the first time and does NOT update it afterwards',
async () => {
const { fs, stderr, vitest } = await runInlineTests(
{
[testFilename]: testContent,
'utils.ts': utilsContent,
},
)
const [referencePath] = extractToMatchScreenshotPaths(stderr, testName)
expect(stderr).toContain(`No existing reference screenshot found; a new one was created. Review it before running tests again.\n\nReference screenshot:\n ${referencePath}`)
const { atime: _1, atimeMs: _2, ...referenceStat } = fs.statFile(referencePath)
fs.editFile(testFilename, content => `${content}\n`)
vitest.resetOutput()
await vitest.waitForStdout('Test Files 1 passed')
expect(vitest.stdout).toContain('✓ |chromium| basic.test.ts > screenshot-snapshot')
const { atime: _3, atimeMs: _4, ...newReferenceStat } = fs.statFile(referencePath)
expect(referenceStat).toEqual(newReferenceStat)
},
)
test(
'with --update creates snapshots and updates them on change',
async () => {
const { fs, stderr, vitest } = await runInlineTests(
{
[testFilename]: testContent,
'utils.ts': utilsContent,
},
{
update: true,
},
)
expect(stderr).toMatchInlineSnapshot(`""`)
const referencePath = `__screenshots__/${testFilename}/${testName}-1-${browser}-${platform()}.png`
const referenceStat = fs.statFile(referencePath)
fs.editFile(testFilename, content => `${content}\n`)
vitest.resetOutput()
await vitest.waitForStdout('Test Files 1 passed')
expect(vitest.stdout).toContain('✓ |chromium| basic.test.ts > screenshot-snapshot')
const {
atime,
atimeMs,
ctime,
ctimeMs,
mtime,
mtimeMs,
...diffs
} = fs.statFile(referencePath)
expect(referenceStat).toEqual(expect.objectContaining(diffs))
expect(atime.getTime()).toBeGreaterThan(referenceStat.atime.getTime())
expect(ctime.getTime()).toBeGreaterThan(referenceStat.ctime.getTime())
expect(mtime.getTime()).toBeGreaterThan(referenceStat.mtime.getTime())
expect(atimeMs).toBeGreaterThan(referenceStat.atimeMs)
expect(ctimeMs).toBeGreaterThan(referenceStat.ctimeMs)
expect(mtimeMs).toBeGreaterThan(referenceStat.mtimeMs)
},
)
test(
'creates a reference and fails when changing the DOM content',
async () => {
const { fs, stderr, vitest } = await runInlineTests(
{
[testFilename]: testContent,
'utils.ts': utilsContent,
},
)
expect(stderr).toContain(`No existing reference screenshot found; a new one was created. Review it before running tests again.\n\nReference screenshot:`)
fs.editFile(testFilename, content => content.replace(bgColor, '#0ff'))
vitest.resetOutput()
await vitest.waitForStdout('Test Files 1 failed')
expect(vitest.stdout).toContain('× |chromium| basic.test.ts > screenshot-snapshot')
expect(vitest.stdout).toContain('Screenshot does not match the stored reference.')
expect(vitest.stdout).toMatch(/\d+ pixels \(ratio 0.\d{2}\) differ\./)
},
)
})