Files
vitest/test/browser/specs/aria-snapshot.test.ts
2026-07-14 17:34:20 +09:00

206 lines
6.4 KiB
TypeScript

import fs, { readFileSync } from 'node:fs'
import { join } from 'node:path'
import { expect, test } from 'vitest'
import { editFile } from '../../test-utils'
import { instances, runBrowserTests } from './utils'
const dir = join(import.meta.dirname, '../fixtures/aria-snapshot')
function extractInlineSnaphsots(code: string) {
const matches = Array.from(
code.matchAll(/\.toMatchAriaInlineSnapshot\(\s*`[\s\S]*?`\s*\)/g),
)
const snapshots = matches.map((match) => {
const end = match.index! + match[0].length
const start = code.lastIndexOf('expect', match.index)
if (start === -1) {
throw new Error(`Failed to extract inline snapshot: no expect found for match ${match[0]}`)
}
return code.slice(start, end)
})
return `\n${snapshots.join('\n\n')}\n`
}
test.for(instances.map(i => i.browser))('aria snapshot %s', async (browser) => {
const testFile = join(dir, 'basic.test.ts')
const snapshotFile = join(dir, '__snapshots__/basic.test.ts.snap')
// clean slate — remove file snapshots and clear inline snapshots
fs.rmSync(join(dir, '__snapshots__'), { recursive: true, force: true })
editFile(testFile, s =>
s.replace(/toMatchAriaInlineSnapshot\(`[^`]*`\)/g, 'toMatchAriaInlineSnapshot()'))
// run with update: new — creates snapshots from scratch
let result = await runBrowserTests({
root: './fixtures/aria-snapshot',
project: [browser],
update: 'new',
})
expect(result.stderr).toMatchInlineSnapshot(`""`)
expect(result.errorTree()).toMatchInlineSnapshot(`
{
"basic.test.ts": {
"expect.element aria once": "passed",
"expect.element aria retry": "passed",
"poll aria once": "passed",
"toMatchAriaInlineSnapshot simple": "passed",
"toMatchAriaSnapshot simple": "passed",
},
}
`)
expect(readFileSync(snapshotFile, 'utf-8')).toMatchInlineSnapshot(`
"// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[\`toMatchAriaSnapshot simple 1\`] = \`
- main:
- heading "Dashboard" [level=1]
- navigation "Actions":
- button "Save"
- button "Cancel"
\`;
"
`)
expect(extractInlineSnaphsots(readFileSync(testFile, 'utf-8'))).toMatchInlineSnapshot(`
"
expect(document.body).toMatchAriaInlineSnapshot(\`
- paragraph: Original
- button "1234": Pattern
\`)
expect.poll(async () => {
document.body.innerHTML = \`<p>poll once</p>\`
return document.body
}).toMatchAriaInlineSnapshot(\`- paragraph: poll once\`)
expect.element(page.getByTestId('body')).toMatchAriaInlineSnapshot(\`
- heading "Hello" [level=1]
- paragraph: World
\`)
expect.element(page.getByTestId('body'), { interval: 20 })
.toMatchAriaInlineSnapshot(\`
- heading "Hello" [level=1]
- paragraph: World
\`)
"
`)
// run with update: none — all should pass
const result2 = await runBrowserTests({
root: './fixtures/aria-snapshot',
project: [browser],
update: 'none',
})
expect(result2.stderr).toEqual(result.stderr)
expect(result2.errorTree()).toEqual(result.errorTree())
// edit snapshots to add regex patterns, run with none — should still pass
editFile(snapshotFile, s => s.replace(`navigation "Actions"`, 'navigation /A\\\\w+/'))
editFile(testFile, s => s.replace(`- button "1234"`, '- button /\\\\d+/'))
const result3 = await runBrowserTests({
root: './fixtures/aria-snapshot',
project: [browser],
update: 'none',
})
expect(result3.stderr).toEqual(result.stderr)
expect(result3.errorTree()).toEqual(result.errorTree())
// edit test HTML to break a literal match, run with none — should fail
editFile(testFile, s => s.replace(`aria-label="Actions"`, `aria-label="EDITED"`))
editFile(testFile, s => s.replace('<p>Original</p>', '<p>Changed</p>'))
result = await runBrowserTests({
root: './fixtures/aria-snapshot',
project: [browser],
update: 'none',
})
expect(result.errorTree({ stackTrace: true, diff: true })).toMatchInlineSnapshot(`
{
"basic.test.ts": {
"expect.element aria once": "passed",
"expect.element aria retry": "passed",
"poll aria once": "passed",
"toMatchAriaInlineSnapshot simple": [
"Snapshot \`toMatchAriaInlineSnapshot simple 1\` mismatched
- Expected
+ Received
- - paragraph: Original
+ - paragraph: Changed
- button /\\d+/: Pattern
at basic.test.ts:22:25",
],
"toMatchAriaSnapshot simple": [
"Snapshot \`toMatchAriaSnapshot simple 1\` mismatched
- Expected
+ Received
- main:
- heading "Dashboard" [level=1]
- - navigation /A\\w+/:
+ - navigation "EDITED":
- button "Save"
- button "Cancel"
at basic.test.ts:14:25",
],
},
}
`)
// run with update: all — should pass, preserve regex, update mismatched literal
result = await runBrowserTests({
root: './fixtures/aria-snapshot',
project: [browser],
update: 'all',
})
expect(result.stderr).toMatchInlineSnapshot(`""`)
expect(result.errorTree()).toMatchInlineSnapshot(`
{
"basic.test.ts": {
"expect.element aria once": "passed",
"expect.element aria retry": "passed",
"poll aria once": "passed",
"toMatchAriaInlineSnapshot simple": "passed",
"toMatchAriaSnapshot simple": "passed",
},
}
`)
expect(readFileSync(snapshotFile, 'utf-8')).toMatchInlineSnapshot(`
"// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[\`toMatchAriaSnapshot simple 1\`] = \`
- main:
- heading "Dashboard" [level=1]
- navigation "EDITED":
- button "Save"
- button "Cancel"
\`;
"
`)
expect(extractInlineSnaphsots(readFileSync(testFile, 'utf-8'))).toMatchInlineSnapshot(`
"
expect(document.body).toMatchAriaInlineSnapshot(\`
- paragraph: Changed
- button /\\\\d+/: Pattern
\`)
expect.poll(async () => {
document.body.innerHTML = \`<p>poll once</p>\`
return document.body
}).toMatchAriaInlineSnapshot(\`- paragraph: poll once\`)
expect.element(page.getByTestId('body')).toMatchAriaInlineSnapshot(\`
- heading "Hello" [level=1]
- paragraph: World
\`)
expect.element(page.getByTestId('body'), { interval: 20 })
.toMatchAriaInlineSnapshot(\`
- heading "Hello" [level=1]
- paragraph: World
\`)
"
`)
})