From f91eba21934f972c7628b6e7386c0b9f78e464cc Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Tue, 13 Aug 2024 14:38:23 +0900 Subject: [PATCH 1/4] fix(snapshot): reject toMatchInlineSnapshot in loop --- packages/snapshot/src/port/state.ts | 7 +++++ .../fails/inline-snapshop-inside-loop.test.ts | 31 +++++++++++++++++++ .../cli/test/__snapshots__/fails.test.ts.snap | 6 ++++ 3 files changed, 44 insertions(+) create mode 100644 test/cli/fixtures/fails/inline-snapshop-inside-loop.test.ts diff --git a/packages/snapshot/src/port/state.ts b/packages/snapshot/src/port/state.ts index eab28e81e005..78c9bbf62b45 100644 --- a/packages/snapshot/src/port/state.ts +++ b/packages/snapshot/src/port/state.ts @@ -158,6 +158,13 @@ export default class SnapshotState { // location for js files, but `column-1` points to the same in both js/ts // https://github.com/vitejs/vite/issues/8657 stack.column-- + // reject multiple inline snapshots at the same location + const duplicateIndex = this._inlineSnapshots.findIndex(s => s.file === stack.file && s.line === stack.line && s.column === stack.column); + if (duplicateIndex >= 0) { + // remove the first one to avoid updating an inline snapshot + this._inlineSnapshots.splice(duplicateIndex, 1); + throw new Error("toMatchInlineSnapshot cannot be called multiple times at the same location."); + } this._inlineSnapshots.push({ snapshot: receivedSerialized, ...stack, diff --git a/test/cli/fixtures/fails/inline-snapshop-inside-loop.test.ts b/test/cli/fixtures/fails/inline-snapshop-inside-loop.test.ts new file mode 100644 index 000000000000..a016b0b8047f --- /dev/null +++ b/test/cli/fixtures/fails/inline-snapshop-inside-loop.test.ts @@ -0,0 +1,31 @@ +import {test, expect} from "vitest"; + +test("ok", () => { + expect("ok").toMatchInlineSnapshot(`"ok"`); +}); + +test("fail 1", () => { + for (const str of ["foo", "bar"]) { + expect(str).toMatchInlineSnapshot(); + } +}); + +// this test causes infinite re-run when --watch and --update +// since snapshot update switches between "foo" and "bar" forever. +test("fail 2", () => { + for (const str of ["foo", "bar"]) { + expect(str).toMatchInlineSnapshot(`"bar"`); + } +}); + +test("fail 3", () => { + for (const str of ["ok", "ok"]) { + expect(str).toMatchInlineSnapshot(); + } +}); + +test("somehow ok", () => { + for (const str of ["ok", "ok"]) { + expect(str).toMatchInlineSnapshot(`"ok"`); + } +}); diff --git a/test/cli/test/__snapshots__/fails.test.ts.snap b/test/cli/test/__snapshots__/fails.test.ts.snap index 5ee6a3c42c5a..896cfad4c49e 100644 --- a/test/cli/test/__snapshots__/fails.test.ts.snap +++ b/test/cli/test/__snapshots__/fails.test.ts.snap @@ -31,6 +31,12 @@ Error: InlineSnapshot cannot be used inside of test.each or describe.each Error: InlineSnapshot cannot be used inside of test.each or describe.each" `; +exports[`should fail inline-snapshop-inside-loop.test.ts > inline-snapshop-inside-loop.test.ts 1`] = ` +"Error: toMatchInlineSnapshot cannot be called multiple times at the same location. +Error: Snapshot \`fail 2 1\` mismatched +Error: toMatchInlineSnapshot cannot be called multiple times at the same location." +`; + exports[`should fail mock-import-proxy-module.test.ts > mock-import-proxy-module.test.ts 1`] = `"Error: There are some problems in resolving the mocks API."`; exports[`should fail nested-suite.test.ts > nested-suite.test.ts 1`] = `"AssertionError: expected true to be false // Object.is equality"`; From 83ff40d41ca56d6d26d02d8a51e9b80c7eef05b3 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Tue, 13 Aug 2024 14:55:48 +0900 Subject: [PATCH 2/4] chore: lint --- packages/snapshot/src/port/state.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/snapshot/src/port/state.ts b/packages/snapshot/src/port/state.ts index 78c9bbf62b45..a08fae338a7d 100644 --- a/packages/snapshot/src/port/state.ts +++ b/packages/snapshot/src/port/state.ts @@ -159,11 +159,11 @@ export default class SnapshotState { // https://github.com/vitejs/vite/issues/8657 stack.column-- // reject multiple inline snapshots at the same location - const duplicateIndex = this._inlineSnapshots.findIndex(s => s.file === stack.file && s.line === stack.line && s.column === stack.column); + const duplicateIndex = this._inlineSnapshots.findIndex(s => s.file === stack.file && s.line === stack.line && s.column === stack.column) if (duplicateIndex >= 0) { // remove the first one to avoid updating an inline snapshot - this._inlineSnapshots.splice(duplicateIndex, 1); - throw new Error("toMatchInlineSnapshot cannot be called multiple times at the same location."); + this._inlineSnapshots.splice(duplicateIndex, 1) + throw new Error('toMatchInlineSnapshot cannot be called multiple times at the same location.') } this._inlineSnapshots.push({ snapshot: receivedSerialized, From 09d9cf0096269820c008ed30496524c1b38f81bb Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Tue, 13 Aug 2024 15:01:37 +0900 Subject: [PATCH 3/4] test: force update --- .../fixtures/fails/inline-snapshop-inside-loop.test.ts | 10 +++++----- test/cli/test/__snapshots__/fails.test.ts.snap | 1 - test/cli/test/fails.test.ts | 5 ++++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/test/cli/fixtures/fails/inline-snapshop-inside-loop.test.ts b/test/cli/fixtures/fails/inline-snapshop-inside-loop.test.ts index a016b0b8047f..ead153701ba0 100644 --- a/test/cli/fixtures/fails/inline-snapshop-inside-loop.test.ts +++ b/test/cli/fixtures/fails/inline-snapshop-inside-loop.test.ts @@ -12,11 +12,11 @@ test("fail 1", () => { // this test causes infinite re-run when --watch and --update // since snapshot update switches between "foo" and "bar" forever. -test("fail 2", () => { - for (const str of ["foo", "bar"]) { - expect(str).toMatchInlineSnapshot(`"bar"`); - } -}); +// test("fail 2", () => { +// for (const str of ["foo", "bar"]) { +// expect(str).toMatchInlineSnapshot(`"bar"`); +// } +// }); test("fail 3", () => { for (const str of ["ok", "ok"]) { diff --git a/test/cli/test/__snapshots__/fails.test.ts.snap b/test/cli/test/__snapshots__/fails.test.ts.snap index 896cfad4c49e..843fa879f922 100644 --- a/test/cli/test/__snapshots__/fails.test.ts.snap +++ b/test/cli/test/__snapshots__/fails.test.ts.snap @@ -33,7 +33,6 @@ Error: InlineSnapshot cannot be used inside of test.each or describe.each" exports[`should fail inline-snapshop-inside-loop.test.ts > inline-snapshop-inside-loop.test.ts 1`] = ` "Error: toMatchInlineSnapshot cannot be called multiple times at the same location. -Error: Snapshot \`fail 2 1\` mismatched Error: toMatchInlineSnapshot cannot be called multiple times at the same location." `; diff --git a/test/cli/test/fails.test.ts b/test/cli/test/fails.test.ts index 04ef933d2e75..aee55dd286e8 100644 --- a/test/cli/test/fails.test.ts +++ b/test/cli/test/fails.test.ts @@ -8,7 +8,10 @@ const root = resolve(__dirname, '../fixtures/fails') const files = await fg('**/*.test.ts', { cwd: root, dot: true }) it.each(files)('should fail %s', async (file) => { - const { stderr } = await runVitest({ root }, [file]) + const { stderr } = await runVitest({ + root, + update: file === 'inline-snapshop-inside-loop.test.ts' ? true : undefined, + }, [file]) expect(stderr).toBeTruthy() const msg = String(stderr) From 7267b4a99cc2d241688c907322966cfa2c159fad Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Tue, 13 Aug 2024 15:42:30 +0900 Subject: [PATCH 4/4] test: tweak --- ...ts => inline-snapshop-inside-loop-update-all.test.ts} | 8 -------- .../inline-snapshop-inside-loop-update-none.test.ts | 9 +++++++++ test/cli/test/__snapshots__/fails.test.ts.snap | 4 +++- test/cli/test/fails.test.ts | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) rename test/cli/fixtures/fails/{inline-snapshop-inside-loop.test.ts => inline-snapshop-inside-loop-update-all.test.ts} (62%) create mode 100644 test/cli/fixtures/fails/inline-snapshop-inside-loop-update-none.test.ts diff --git a/test/cli/fixtures/fails/inline-snapshop-inside-loop.test.ts b/test/cli/fixtures/fails/inline-snapshop-inside-loop-update-all.test.ts similarity index 62% rename from test/cli/fixtures/fails/inline-snapshop-inside-loop.test.ts rename to test/cli/fixtures/fails/inline-snapshop-inside-loop-update-all.test.ts index ead153701ba0..ffad4925d808 100644 --- a/test/cli/fixtures/fails/inline-snapshop-inside-loop.test.ts +++ b/test/cli/fixtures/fails/inline-snapshop-inside-loop-update-all.test.ts @@ -10,14 +10,6 @@ test("fail 1", () => { } }); -// this test causes infinite re-run when --watch and --update -// since snapshot update switches between "foo" and "bar" forever. -// test("fail 2", () => { -// for (const str of ["foo", "bar"]) { -// expect(str).toMatchInlineSnapshot(`"bar"`); -// } -// }); - test("fail 3", () => { for (const str of ["ok", "ok"]) { expect(str).toMatchInlineSnapshot(); diff --git a/test/cli/fixtures/fails/inline-snapshop-inside-loop-update-none.test.ts b/test/cli/fixtures/fails/inline-snapshop-inside-loop-update-none.test.ts new file mode 100644 index 000000000000..ae2ccbff44d9 --- /dev/null +++ b/test/cli/fixtures/fails/inline-snapshop-inside-loop-update-none.test.ts @@ -0,0 +1,9 @@ +import {test, expect} from "vitest"; + +// this test causes infinite re-run when --watch and --update +// since snapshot update switches between "foo" and "bar" forever. +test("fail 2", () => { + for (const str of ["foo", "bar"]) { + expect(str).toMatchInlineSnapshot(`"bar"`); + } +}); diff --git a/test/cli/test/__snapshots__/fails.test.ts.snap b/test/cli/test/__snapshots__/fails.test.ts.snap index 843fa879f922..6572cb5552da 100644 --- a/test/cli/test/__snapshots__/fails.test.ts.snap +++ b/test/cli/test/__snapshots__/fails.test.ts.snap @@ -31,11 +31,13 @@ Error: InlineSnapshot cannot be used inside of test.each or describe.each Error: InlineSnapshot cannot be used inside of test.each or describe.each" `; -exports[`should fail inline-snapshop-inside-loop.test.ts > inline-snapshop-inside-loop.test.ts 1`] = ` +exports[`should fail inline-snapshop-inside-loop-update-all.test.ts > inline-snapshop-inside-loop-update-all.test.ts 1`] = ` "Error: toMatchInlineSnapshot cannot be called multiple times at the same location. Error: toMatchInlineSnapshot cannot be called multiple times at the same location." `; +exports[`should fail inline-snapshop-inside-loop-update-none.test.ts > inline-snapshop-inside-loop-update-none.test.ts 1`] = `"Error: Snapshot \`fail 2 1\` mismatched"`; + exports[`should fail mock-import-proxy-module.test.ts > mock-import-proxy-module.test.ts 1`] = `"Error: There are some problems in resolving the mocks API."`; exports[`should fail nested-suite.test.ts > nested-suite.test.ts 1`] = `"AssertionError: expected true to be false // Object.is equality"`; diff --git a/test/cli/test/fails.test.ts b/test/cli/test/fails.test.ts index aee55dd286e8..0bb19ad73288 100644 --- a/test/cli/test/fails.test.ts +++ b/test/cli/test/fails.test.ts @@ -10,7 +10,7 @@ const files = await fg('**/*.test.ts', { cwd: root, dot: true }) it.each(files)('should fail %s', async (file) => { const { stderr } = await runVitest({ root, - update: file === 'inline-snapshop-inside-loop.test.ts' ? true : undefined, + update: file === 'inline-snapshop-inside-loop-update-all.test.ts' ? true : undefined, }, [file]) expect(stderr).toBeTruthy()