diff --git a/packages/snapshot/src/port/inlineSnapshot.ts b/packages/snapshot/src/port/inlineSnapshot.ts index c7e9f91298e7..3e98dea188c5 100644 --- a/packages/snapshot/src/port/inlineSnapshot.ts +++ b/packages/snapshot/src/port/inlineSnapshot.ts @@ -34,21 +34,47 @@ export async function saveInlineSnapshots( const startObjectRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\S\s]*\*\/\s*|\/\/.*\s+)*\s*({)/m function replaceObjectSnap(code: string, s: MagicString, index: number, newSnap: string) { - code = code.slice(index) - const startMatch = startObjectRegex.exec(code) + let _code = code.slice(index) + const startMatch = startObjectRegex.exec(_code) if (!startMatch) return false - code = code.slice(startMatch.index) - const charIndex = getCallLastIndex(code) - if (charIndex === null) + _code = _code.slice(startMatch.index) + + let callEnd = getCallLastIndex(_code) + if (callEnd === null) return false + callEnd += index + startMatch.index + + const shapeStart = index + startMatch.index + startMatch[0].length + const shapeEnd = getObjectShapeEndIndex(code, shapeStart) + const snap = `, ${prepareSnapString(newSnap, code, index)}` - s.appendLeft(index + startMatch.index + charIndex, `, ${prepareSnapString(newSnap, code, index)}`) + if (shapeEnd === callEnd) { + // toMatchInlineSnapshot({ foo: expect.any(String) }) + s.appendLeft(callEnd, snap) + } + else { + // toMatchInlineSnapshot({ foo: expect.any(String) }, ``) + s.overwrite(shapeEnd, callEnd, snap) + } return true } +function getObjectShapeEndIndex(code: string, index: number) { + let startBraces = 1 + let endBraces = 0 + while (startBraces !== endBraces && index < code.length) { + const s = code[index++] + if (s === '{') + startBraces++ + else if (s === '}') + endBraces++ + } + return index +} + function prepareSnapString(snap: string, source: string, index: number) { const lineNumber = offsetToLineNumber(source, index) const line = source.split(lineSplitRE)[lineNumber - 1] diff --git a/test/core/test/inline-snap.test.ts b/test/core/test/inline-snap.test.ts index eb41a39a2da7..26d4547828d9 100644 --- a/test/core/test/inline-snap.test.ts +++ b/test/core/test/inline-snap.test.ts @@ -146,4 +146,44 @@ ${indent}}\`) " `) }) + + describe('replaceObjectSnap()', () => { + it('without snapshot', async () => { + const code = 'expect({ foo: \'bar\' }).toMatchInlineSnapshot({ foo: expect.any(String) })' + + const s = new MagicString(code) + replaceInlineSnap(code, s, 23, ` + { + "foo": Any, + } + `) + + expect(s.toString()).toMatchInlineSnapshot(` + "expect({ foo: 'bar' }).toMatchInlineSnapshot({ foo: expect.any(String) }, \` + { + \\"foo\\": Any, + } + \`)" + `) + }) + + it('with snapshot', async () => { + const code = 'expect({ foo: \'bar\' }).toMatchInlineSnapshot({ foo: expect.any(String) }, `{ }`)' + + const s = new MagicString(code) + replaceInlineSnap(code, s, 23, ` + { + "foo": Any, + } + `) + + expect(s.toString()).toMatchInlineSnapshot(` + "expect({ foo: 'bar' }).toMatchInlineSnapshot({ foo: expect.any(String) }, \` + { + \\"foo\\": Any, + } + \`)" + `) + }) + }) }) diff --git a/test/snapshots/test-update/snapshots-inline-js.test.js b/test/snapshots/test-update/snapshots-inline-js.test.js index dbfd8799863a..806e740dc692 100644 --- a/test/snapshots/test-update/snapshots-inline-js.test.js +++ b/test/snapshots/test-update/snapshots-inline-js.test.js @@ -23,3 +23,21 @@ describe('snapshots are generated in correct order', async () => { `) }) }) + +describe('snapshots with properties', () => { + test('without snapshot', () => { + expect({ foo: 'bar' }).toMatchInlineSnapshot({ foo: expect.any(String) }, ` + Object { + "foo": Any, + } + `) + }) + + test('with snapshot', () => { + expect({ foo: 'bar' }).toMatchInlineSnapshot({ foo: expect.any(String) }, ` + Object { + "foo": Any, + } + `) + }) +}) diff --git a/test/snapshots/test/__snapshots__/shapshots.test.ts.snap b/test/snapshots/test/__snapshots__/shapshots.test.ts.snap index 736d9307ddaf..e5485a6b62a3 100644 --- a/test/snapshots/test/__snapshots__/shapshots.test.ts.snap +++ b/test/snapshots/test/__snapshots__/shapshots.test.ts.snap @@ -26,6 +26,24 @@ describe('snapshots are generated in correct order', async () => { \`) }) }) + +describe('snapshots with properties', () => { + test('without snapshot', () => { + expect({ foo: 'bar' }).toMatchInlineSnapshot({ foo: expect.any(String) }, \` + Object { + \\"foo\\": Any, + } + \`) + }) + + test('with snapshot', () => { + expect({ foo: 'bar' }).toMatchInlineSnapshot({ foo: expect.any(String) }, \` + Object { + \\"foo\\": Any, + } + \`) + }) +}) " `; diff --git a/test/snapshots/tools/inline-test-template.js b/test/snapshots/tools/inline-test-template.js index 0f3547cf6f68..f80e7918f3d8 100644 --- a/test/snapshots/tools/inline-test-template.js +++ b/test/snapshots/tools/inline-test-template.js @@ -11,3 +11,13 @@ describe('snapshots are generated in correct order', async () => { expect({ foo: ['zed'] }).toMatchInlineSnapshot() }) }) + +describe('snapshots with properties', () => { + test('without snapshot', () => { + expect({ foo: 'bar' }).toMatchInlineSnapshot({ foo: expect.any(String) }) + }) + + test('with snapshot', () => { + expect({ foo: 'bar' }).toMatchInlineSnapshot({ foo: expect.any(String) }, '') + }) +})