Skip to content

Commit 4d84f0a

Browse files
authored
fix(snapshot)!: fail test with obsolete snapshot on CI (#7963)
1 parent be11d37 commit 4d84f0a

File tree

8 files changed

+93
-2
lines changed

8 files changed

+93
-2
lines changed

packages/runner/src/run.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,9 +576,9 @@ export async function runSuite(suite: Suite, runner: VitestRunner): Promise<void
576576

577577
suite.result.duration = now() - start
578578

579-
updateTask('suite-finished', suite, runner)
580-
581579
await runner.onAfterRunSuite?.(suite)
580+
581+
updateTask('suite-finished', suite, runner)
582582
}
583583
}
584584

packages/vitest/src/runtime/runners/test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type { SerializedConfig } from '../config'
1414
// import type { VitestExecutor } from '../execute'
1515
import { getState, GLOBAL_EXPECT, setState } from '@vitest/expect'
1616
import { getNames, getTestName, getTests } from '@vitest/runner/utils'
17+
import { processError } from '@vitest/utils/error'
1718
import { normalize } from 'pathe'
1819
import { createExpect } from '../../integrations/chai/index'
1920
import { inject } from '../../integrations/inject'
@@ -76,6 +77,18 @@ export class VitestTestRunner implements VitestRunner {
7677
}
7778

7879
const result = await this.snapshotClient.finish(suite.file.filepath)
80+
if (
81+
this.workerState.config.snapshotOptions.updateSnapshot === 'none'
82+
&& result.unchecked
83+
) {
84+
let message = `Obsolete snapshots found when no snapshot update is expected.\n`
85+
for (const key of result.uncheckedKeys) {
86+
message += ${key}\n`
87+
}
88+
suite.result!.errors ??= []
89+
suite.result!.errors.push(processError(new Error(message)))
90+
suite.result!.state = 'fail'
91+
}
7992
await rpc().snapshotSaved(result)
8093
}
8194

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`bar 1`] = `"bar"`;
4+
5+
exports[`foo 1`] = `"foo"`;
6+
7+
exports[`fuu 1`] = `"fuu"`;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`bar 1`] = `"bar"`;
4+
5+
exports[`foo 1`] = `"foo"`;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { expect, it } from 'vitest'
2+
3+
it('foo', () => {
4+
if (process.env.TEST_OBSOLETE) return
5+
expect("foo").toMatchSnapshot();
6+
})
7+
8+
it('fuu', () => {
9+
if (process.env.TEST_OBSOLETE) return
10+
expect("fuu").toMatchSnapshot();
11+
})
12+
13+
it('bar', () => {
14+
expect("bar").toMatchSnapshot();
15+
})
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { expect, it } from 'vitest'
2+
3+
it('foo', () => {
4+
expect("foo").toMatchSnapshot();
5+
})
6+
7+
it('bar', () => {
8+
expect("bar").toMatchSnapshot();
9+
})
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { defineConfig } from 'vitest/config'
2+
3+
export default defineConfig({})

test/snapshots/test/obsolete.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import fs from 'node:fs'
2+
import path from 'node:path'
3+
import { expect, test } from 'vitest'
4+
import { runVitestCli } from '../../test-utils'
5+
6+
test('obsolete snapshot fails CI', async () => {
7+
// cleanup snapshot
8+
const root = path.join(import.meta.dirname, 'fixtures/obsolete')
9+
fs.rmSync(path.join(root, 'src/__snapshots__'), { recursive: true, force: true })
10+
11+
// initial run to write snapshot
12+
let vitest = await runVitestCli('--root', root, '--update')
13+
expect(vitest.stdout).toContain('Snapshots 5 written')
14+
expect(vitest.stderr).toBe('')
15+
16+
// test fails with obsolete snapshots
17+
// (use cli to test `updateSnapshot: 'none'`)
18+
vitest = await runVitestCli(
19+
{
20+
nodeOptions: {
21+
env: {
22+
CI: 'true',
23+
TEST_OBSOLETE: 'true',
24+
},
25+
},
26+
},
27+
'--root',
28+
root,
29+
)
30+
expect(vitest.stdout).toContain('2 obsolete')
31+
expect(vitest.stdout).toContain('Test Files 1 failed | 1 passed')
32+
expect(vitest.stdout).toContain('Tests 5 passed')
33+
expect(vitest.stderr).toContain(`
34+
Error: Obsolete snapshots found when no snapshot update is expected.
35+
· foo 1
36+
· fuu 1
37+
`)
38+
expect(vitest.exitCode).toBe(1)
39+
})

0 commit comments

Comments
 (0)