Open milahu opened 1 year ago
You can disable this in the pretty format options with escapeString
// vitest.config.ts
test: {
snapshotFormat: {
escapeString: false,
},
},
no, i still get
❯ test/basic.test.ts (3)
❯ suite name (3)
✓ snapshot
✓ string snapshot actual
× string snapshot expected
expected:
i tried both vite.config.ts
and vitest.config.ts
Describe the bug
snapshot strings have double indent in line 2 and following
i want "string snapshots" like in #856 but this bug-feature produces ugly snapshots
Reproduction
https://stackblitz.com/edit/vitest-dev-vitest-kfybto?file=test/basic.test.ts
demo.test.js
Workaround
add a prefix to the string
Fix
blame: stripSnapshotIndentation, prepareSnapString @ inlineSnapshot.ts
the "wrong first line" is caused by
snap.trim()
the "double indent" is caused by
lines.map((i) => i ? indentNext + i : "")
the serialized snapshot is also modified by
addExtraLineBreaks(serialize(received
andprepareExpected(
andexpect(actual.trim()).equals(expected ? expected.trim() : "");
which is not desired in my casethese could be made optional
or add a new method
toMatchStringSnapshot
patches/vitest+0.25.2.patch
```diff diff --git a/node_modules/vitest/dist/chunk-runtime-chain.a0b441dc.js b/node_modules/vitest/dist/chunk-runtime-chain.a0b441dc.js index 4323980..07ba202 100644 --- a/node_modules/vitest/dist/chunk-runtime-chain.a0b441dc.js +++ b/node_modules/vitest/dist/chunk-runtime-chain.a0b441dc.js @@ -1,3 +1,5 @@ +const debugSnaps = false; + import util$1 from 'util'; import { i as isObject, b as getCallLastIndex, s as slash, g as getWorkerState, c as getNames, d as assertTypes, e as getFullName, n as noop, f as isRunningInTest, h as isRunningInBenchmark } from './chunk-typecheck-constants.4891f22f.js'; import * as chai$2 from 'chai'; @@ -502,10 +504,18 @@ const removeExtraLineBreaks = (string) => string.length > 2 && string.startsWith const escapeRegex = true; const printFunctionName = false; function serialize(val, indent = 2, formatOverrides = {}) { + + debugSnaps && console.dir({ + f: "serialize", + val, + plugins: getSerializers(), + }) + return normalizeNewlines( format_1(val, { escapeRegex, indent, + // expect.addSnapshotSerializer plugins: getSerializers(), printFunctionName, ...formatOverrides @@ -547,6 +557,8 @@ ${snapshots.join("\n\n")} )); } function prepareExpected(expected) { + // dont prepare + return expected function findStartIndent() { var _a, _b; const matchObject = /^( +)}\s+$/m.exec(expected || ""); @@ -607,6 +619,12 @@ async function saveInlineSnapshots(snapshots) { const code = await promises.readFile(file, "utf8"); const s = new MagicString(code); for (const snap of snaps) { + + debugSnaps && console.dir({ + f: "saveInlineSnapshots", + snap, + }) + const index = posToNumber(code, snap); replaceInlineSnap(code, s, index, snap.snapshot); } @@ -629,22 +647,52 @@ function replaceObjectSnap(code, s, index, newSnap) { return true; } function prepareSnapString(snap, source, index) { + const lineIndex = numberToPos(source, index).line; const line = source.split(lineSplitRE)[lineIndex - 1]; const indent = line.match(/^\s*/)[0] || ""; const indentNext = indent.includes(" ") ? `${indent} ` : `${indent} `; - const lines = snap.trim().replace(/\\/g, "\\\\").split(/\n/g); + //const lines = snap.trim().replace(/\\/g, "\\\\").split(/\n/g); + // dont trim + const lines = snap.replace(/\\/g, "\\\\").split(/\n/g); const isOneline = lines.length <= 1; const quote = isOneline ? "'" : "`"; + + debugSnaps && console.dir({ + f: "prepareSnapString", + snap, + line, + indent, + indentNext, + isOneline, + lines, + //source, index // test file source + }) + +// add indentNext +//${lines.map((i) => i ? indentNext + i : "").join("\n").replace(/`/g, "\\`").replace(/\${/g, "\\${")} +// dont add indentNext + +// dont wrap +return `${quote}${snap.replace(/`/g, "\\`").replace(/\${/g, "\\${")}${quote}` + + if (isOneline) return `'${lines.join("\n").replace(/'/g, "\\'")}'`; else return `${quote} -${lines.map((i) => i ? indentNext + i : "").join("\n").replace(/`/g, "\\`").replace(/\${/g, "\\${")} +${lines.join("\n").replace(/`/g, "\\`").replace(/\${/g, "\\${")} ${indent}${quote}`; } + const startRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\S\s]*\*\/\s*|\/\/.*\s+)*\s*[\w_$]*(['"`\)])/m; function replaceInlineSnap(code, s, index, newSnap) { + + debugSnaps && console.dir({ + f: "replaceInlineSnap", + newSnap, + }) + const startMatch = startRegex.exec(code.slice(index)); if (!startMatch) return replaceObjectSnap(code, s, index, newSnap); @@ -742,6 +790,12 @@ ${JSON.stringify(stacks)}` ); } stack.column--; + + debugSnaps && console.dir({ + f: "SnapshotState._addSnapshot", + receivedSerialized, + }) + this._inlineSnapshots.push({ snapshot: receivedSerialized, ...stack @@ -770,8 +824,15 @@ ${JSON.stringify(stacks)}` if ((this._dirty || this._uncheckedKeys.size) && !isEmpty) { if (hasExternalSnapshots) await saveSnapshotFile(this._snapshotData, this.snapshotPath); - if (hasInlineSnapshots) + if (hasInlineSnapshots) { + + debugSnaps && console.dir({ + f: "SnapshotState.save", + _inlineSnapshots: this._inlineSnapshots, + }) + await saveInlineSnapshots(this._inlineSnapshots); + } status.saved = true; } else if (!hasExternalSnapshots && fs.existsSync(this.snapshotPath)) { if (this._updateSnapshot === "all") @@ -807,7 +868,36 @@ ${JSON.stringify(stacks)}` key = testNameToKey(testName, count); if (!(isInline && this._snapshotData[key] !== void 0)) this._uncheckedKeys.delete(key); - const receivedSerialized = addExtraLineBreaks(serialize(received, void 0, this._snapshotFormat)); + + debugSnaps && console.dir({ + f: "sstate.match", + received, + }) + + /* + const serializer = getSerializers().find(s => s.test(received)) + //const receivedSerialized = addExtraLineBreaks(serialize(received, void 0, this._snapshotFormat)); + const receivedSerialized = serialize(received, void 0, this._snapshotFormat); + if (serializer?.addExtraLineBreaks != false) { + receivedSerialized = addExtraLineBreaks(receivedSerialized); + } + const expected = isInline ? inlineSnapshot : this._snapshotData[key]; + //const expectedTrimmed = prepareExpected(expected); + let expectedTrimmed = expected; + if (serializer?.prepareExpected != false) { + expectedTrimmed = prepareExpected(expectedTrimmed); + } + //const pass = expectedTrimmed === prepareExpected(receivedSerialized); + let receivedSerializedTrimmed = receivedSerialized; + if (serializer?.prepareExpected != false) { + receivedSerializedTrimmed = prepareExpected(receivedSerializedTrimmed); + } + const pass = expectedTrimmed === receivedSerializedTrimmed; + */ + + //const receivedSerialized = addExtraLineBreaks(serialize(received, void 0, this._snapshotFormat)); + const receivedSerialized = (serialize(received, void 0, this._snapshotFormat)); + const expected = isInline ? inlineSnapshot : this._snapshotData[key]; const expectedTrimmed = prepareExpected(expected); const pass = expectedTrimmed === prepareExpected(receivedSerialized); @@ -931,6 +1021,13 @@ class SnapshotClient { errorMessage } = options; let { received } = options; + + debugSnaps && console.dir({ + f: "SnapshotClient.assert", + received, + inlineSnapshot, + }) + if (!test) throw new Error("Snapshot cannot be used outside of test"); if (typeof properties === "object") { @@ -960,13 +1057,19 @@ class SnapshotClient { inlineSnapshot }); if (!pass) { + debugSnaps && console.log(`SnapshotClient.assert: pass == false`) try { - expect(actual.trim()).equals(expected ? expected.trim() : ""); + //expect(actual.trim()).equals(expected ? expected.trim() : ""); + // dont trim + expect(actual).equals(expected ? expected : ""); } catch (error2) { error2.message = errorMessage || `Snapshot \`${key || "unknown"}\` mismatched`; throw error2; } } + else { + debugSnaps && console.log(`SnapshotClient.assert: pass == true`) + } } async saveCurrent() { if (!this.snapshotState) @@ -1040,8 +1143,16 @@ const SnapshotPlugin = (chai, utils) => { inlineSnapshot = properties; properties = void 0; } + /* if (inlineSnapshot) inlineSnapshot = stripSnapshotIndentation(inlineSnapshot); + */ + debugSnaps && console.dir({ + f: "toMatchInlineSnapshot", + expected, + inlineSnapshot, + }) + const errorMessage = utils.flag(this, "message"); getSnapshotClient().assert({ received: expected, ```System Info
Used Package Manager
pnpm
Validations