@vitest/snapshot 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +75 -0
- package/dist/environment-8fbbf71b.d.ts +12 -0
- package/dist/environment.d.ts +14 -0
- package/dist/environment.js +40 -0
- package/dist/index-2c775746.d.ts +59 -0
- package/dist/index.d.ts +112 -0
- package/dist/index.js +940 -0
- package/dist/manager.d.ts +18 -0
- package/dist/manager.js +74 -0
- package/package.json +49 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,940 @@
|
|
|
1
|
+
import { join, dirname } from 'pathe';
|
|
2
|
+
import { plugins, format } from 'pretty-format';
|
|
3
|
+
import 'util';
|
|
4
|
+
|
|
5
|
+
var naturalCompare$1 = {exports: {}};
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* @version 1.4.0
|
|
9
|
+
* @date 2015-10-26
|
|
10
|
+
* @stability 3 - Stable
|
|
11
|
+
* @author Lauri Rooden (https://github.com/litejs/natural-compare-lite)
|
|
12
|
+
* @license MIT License
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
var naturalCompare = function(a, b) {
|
|
17
|
+
var i, codeA
|
|
18
|
+
, codeB = 1
|
|
19
|
+
, posA = 0
|
|
20
|
+
, posB = 0
|
|
21
|
+
, alphabet = String.alphabet;
|
|
22
|
+
|
|
23
|
+
function getCode(str, pos, code) {
|
|
24
|
+
if (code) {
|
|
25
|
+
for (i = pos; code = getCode(str, i), code < 76 && code > 65;) ++i;
|
|
26
|
+
return +str.slice(pos - 1, i)
|
|
27
|
+
}
|
|
28
|
+
code = alphabet && alphabet.indexOf(str.charAt(pos));
|
|
29
|
+
return code > -1 ? code + 76 : ((code = str.charCodeAt(pos) || 0), code < 45 || code > 127) ? code
|
|
30
|
+
: code < 46 ? 65 // -
|
|
31
|
+
: code < 48 ? code - 1
|
|
32
|
+
: code < 58 ? code + 18 // 0-9
|
|
33
|
+
: code < 65 ? code - 11
|
|
34
|
+
: code < 91 ? code + 11 // A-Z
|
|
35
|
+
: code < 97 ? code - 37
|
|
36
|
+
: code < 123 ? code + 5 // a-z
|
|
37
|
+
: code - 63
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
if ((a+="") != (b+="")) for (;codeB;) {
|
|
42
|
+
codeA = getCode(a, posA++);
|
|
43
|
+
codeB = getCode(b, posB++);
|
|
44
|
+
|
|
45
|
+
if (codeA < 76 && codeB < 76 && codeA > 66 && codeB > 66) {
|
|
46
|
+
codeA = getCode(a, posA, posA);
|
|
47
|
+
codeB = getCode(b, posB, posA = i);
|
|
48
|
+
posB = i;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (codeA != codeB) return (codeA < codeB) ? -1 : 1
|
|
52
|
+
}
|
|
53
|
+
return 0
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
naturalCompare$1.exports = naturalCompare;
|
|
58
|
+
} catch (e) {
|
|
59
|
+
String.naturalCompare = naturalCompare;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function notNullish(v) {
|
|
63
|
+
return v != null;
|
|
64
|
+
}
|
|
65
|
+
function isPrimitive(value) {
|
|
66
|
+
return value === null || typeof value !== "function" && typeof value !== "object";
|
|
67
|
+
}
|
|
68
|
+
function isObject(item) {
|
|
69
|
+
return item != null && typeof item === "object" && !Array.isArray(item);
|
|
70
|
+
}
|
|
71
|
+
function getCallLastIndex(code) {
|
|
72
|
+
let charIndex = -1;
|
|
73
|
+
let inString = null;
|
|
74
|
+
let startedBracers = 0;
|
|
75
|
+
let endedBracers = 0;
|
|
76
|
+
let beforeChar = null;
|
|
77
|
+
while (charIndex <= code.length) {
|
|
78
|
+
beforeChar = code[charIndex];
|
|
79
|
+
charIndex++;
|
|
80
|
+
const char = code[charIndex];
|
|
81
|
+
const isCharString = char === '"' || char === "'" || char === "`";
|
|
82
|
+
if (isCharString && beforeChar !== "\\") {
|
|
83
|
+
if (inString === char)
|
|
84
|
+
inString = null;
|
|
85
|
+
else if (!inString)
|
|
86
|
+
inString = char;
|
|
87
|
+
}
|
|
88
|
+
if (!inString) {
|
|
89
|
+
if (char === "(")
|
|
90
|
+
startedBracers++;
|
|
91
|
+
if (char === ")")
|
|
92
|
+
endedBracers++;
|
|
93
|
+
}
|
|
94
|
+
if (startedBracers && endedBracers && startedBracers === endedBracers)
|
|
95
|
+
return charIndex;
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let getPromiseValue = () => 'Promise{…}';
|
|
101
|
+
try {
|
|
102
|
+
const { getPromiseDetails, kPending, kRejected } = process.binding('util');
|
|
103
|
+
if (Array.isArray(getPromiseDetails(Promise.resolve()))) {
|
|
104
|
+
getPromiseValue = (value, options) => {
|
|
105
|
+
const [state, innerValue] = getPromiseDetails(value);
|
|
106
|
+
if (state === kPending) {
|
|
107
|
+
return 'Promise{<pending>}'
|
|
108
|
+
}
|
|
109
|
+
return `Promise${state === kRejected ? '!' : ''}{${options.inspect(innerValue, options)}}`
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
} catch (notNode) {
|
|
113
|
+
/* ignore */
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* !
|
|
117
|
+
* loupe
|
|
118
|
+
* Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com>
|
|
119
|
+
* MIT Licensed
|
|
120
|
+
*/
|
|
121
|
+
let nodeInspect = false;
|
|
122
|
+
try {
|
|
123
|
+
// eslint-disable-next-line global-require
|
|
124
|
+
const nodeUtil = require('util');
|
|
125
|
+
nodeInspect = nodeUtil.inspect ? nodeUtil.inspect.custom : false;
|
|
126
|
+
} catch (noNodeInspect) {
|
|
127
|
+
nodeInspect = false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function normalizeWindowsPath(input = "") {
|
|
131
|
+
if (!input || !input.includes("\\")) {
|
|
132
|
+
return input;
|
|
133
|
+
}
|
|
134
|
+
return input.replace(/\\/g, "/");
|
|
135
|
+
}
|
|
136
|
+
const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
137
|
+
function cwd() {
|
|
138
|
+
if (typeof process !== "undefined") {
|
|
139
|
+
return process.cwd().replace(/\\/g, "/");
|
|
140
|
+
}
|
|
141
|
+
return "/";
|
|
142
|
+
}
|
|
143
|
+
const resolve = function(...arguments_) {
|
|
144
|
+
arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
|
|
145
|
+
let resolvedPath = "";
|
|
146
|
+
let resolvedAbsolute = false;
|
|
147
|
+
for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
|
|
148
|
+
const path = index >= 0 ? arguments_[index] : cwd();
|
|
149
|
+
if (!path || path.length === 0) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
resolvedPath = `${path}/${resolvedPath}`;
|
|
153
|
+
resolvedAbsolute = isAbsolute(path);
|
|
154
|
+
}
|
|
155
|
+
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
|
156
|
+
if (resolvedAbsolute && !isAbsolute(resolvedPath)) {
|
|
157
|
+
return `/${resolvedPath}`;
|
|
158
|
+
}
|
|
159
|
+
return resolvedPath.length > 0 ? resolvedPath : ".";
|
|
160
|
+
};
|
|
161
|
+
function normalizeString(path, allowAboveRoot) {
|
|
162
|
+
let res = "";
|
|
163
|
+
let lastSegmentLength = 0;
|
|
164
|
+
let lastSlash = -1;
|
|
165
|
+
let dots = 0;
|
|
166
|
+
let char = null;
|
|
167
|
+
for (let index = 0; index <= path.length; ++index) {
|
|
168
|
+
if (index < path.length) {
|
|
169
|
+
char = path[index];
|
|
170
|
+
} else if (char === "/") {
|
|
171
|
+
break;
|
|
172
|
+
} else {
|
|
173
|
+
char = "/";
|
|
174
|
+
}
|
|
175
|
+
if (char === "/") {
|
|
176
|
+
if (lastSlash === index - 1 || dots === 1)
|
|
177
|
+
;
|
|
178
|
+
else if (dots === 2) {
|
|
179
|
+
if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
|
|
180
|
+
if (res.length > 2) {
|
|
181
|
+
const lastSlashIndex = res.lastIndexOf("/");
|
|
182
|
+
if (lastSlashIndex === -1) {
|
|
183
|
+
res = "";
|
|
184
|
+
lastSegmentLength = 0;
|
|
185
|
+
} else {
|
|
186
|
+
res = res.slice(0, lastSlashIndex);
|
|
187
|
+
lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
|
|
188
|
+
}
|
|
189
|
+
lastSlash = index;
|
|
190
|
+
dots = 0;
|
|
191
|
+
continue;
|
|
192
|
+
} else if (res.length > 0) {
|
|
193
|
+
res = "";
|
|
194
|
+
lastSegmentLength = 0;
|
|
195
|
+
lastSlash = index;
|
|
196
|
+
dots = 0;
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (allowAboveRoot) {
|
|
201
|
+
res += res.length > 0 ? "/.." : "..";
|
|
202
|
+
lastSegmentLength = 2;
|
|
203
|
+
}
|
|
204
|
+
} else {
|
|
205
|
+
if (res.length > 0) {
|
|
206
|
+
res += `/${path.slice(lastSlash + 1, index)}`;
|
|
207
|
+
} else {
|
|
208
|
+
res = path.slice(lastSlash + 1, index);
|
|
209
|
+
}
|
|
210
|
+
lastSegmentLength = index - lastSlash - 1;
|
|
211
|
+
}
|
|
212
|
+
lastSlash = index;
|
|
213
|
+
dots = 0;
|
|
214
|
+
} else if (char === "." && dots !== -1) {
|
|
215
|
+
++dots;
|
|
216
|
+
} else {
|
|
217
|
+
dots = -1;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return res;
|
|
221
|
+
}
|
|
222
|
+
const isAbsolute = function(p) {
|
|
223
|
+
return _IS_ABSOLUTE_RE.test(p);
|
|
224
|
+
};
|
|
225
|
+
const lineSplitRE = /\r?\n/;
|
|
226
|
+
const stackIgnorePatterns = [
|
|
227
|
+
"node:internal",
|
|
228
|
+
/\/packages\/\w+\/dist\//,
|
|
229
|
+
/\/@vitest\/\w+\/dist\//,
|
|
230
|
+
"/vitest/dist/",
|
|
231
|
+
"/vitest/src/",
|
|
232
|
+
"/vite-node/dist/",
|
|
233
|
+
"/vite-node/src/",
|
|
234
|
+
"/node_modules/chai/",
|
|
235
|
+
"/node_modules/tinypool/",
|
|
236
|
+
"/node_modules/tinyspy/"
|
|
237
|
+
];
|
|
238
|
+
function extractLocation(urlLike) {
|
|
239
|
+
if (!urlLike.includes(":"))
|
|
240
|
+
return [urlLike];
|
|
241
|
+
const regExp = /(.+?)(?::(\d+))?(?::(\d+))?$/;
|
|
242
|
+
const parts = regExp.exec(urlLike.replace(/[()]/g, ""));
|
|
243
|
+
if (!parts)
|
|
244
|
+
return [urlLike];
|
|
245
|
+
return [parts[1], parts[2] || void 0, parts[3] || void 0];
|
|
246
|
+
}
|
|
247
|
+
function parseSingleStack(raw) {
|
|
248
|
+
let line = raw.trim();
|
|
249
|
+
if (line.includes("(eval "))
|
|
250
|
+
line = line.replace(/eval code/g, "eval").replace(/(\(eval at [^()]*)|(,.*$)/g, "");
|
|
251
|
+
let sanitizedLine = line.replace(/^\s+/, "").replace(/\(eval code/g, "(").replace(/^.*?\s+/, "");
|
|
252
|
+
const location = sanitizedLine.match(/ (\(.+\)$)/);
|
|
253
|
+
sanitizedLine = location ? sanitizedLine.replace(location[0], "") : sanitizedLine;
|
|
254
|
+
const [url, lineNumber, columnNumber] = extractLocation(location ? location[1] : sanitizedLine);
|
|
255
|
+
let method = location && sanitizedLine || "";
|
|
256
|
+
let file = url && ["eval", "<anonymous>"].includes(url) ? void 0 : url;
|
|
257
|
+
if (!file || !lineNumber || !columnNumber)
|
|
258
|
+
return null;
|
|
259
|
+
if (method.startsWith("async "))
|
|
260
|
+
method = method.slice(6);
|
|
261
|
+
if (file.startsWith("file://"))
|
|
262
|
+
file = file.slice(7);
|
|
263
|
+
file = resolve(file);
|
|
264
|
+
return {
|
|
265
|
+
method,
|
|
266
|
+
file,
|
|
267
|
+
line: parseInt(lineNumber),
|
|
268
|
+
column: parseInt(columnNumber)
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function parseStacktrace(stack, ignore = stackIgnorePatterns) {
|
|
272
|
+
const stackFrames = stack.split("\n").map((raw) => {
|
|
273
|
+
const stack2 = parseSingleStack(raw);
|
|
274
|
+
if (!stack2 || ignore.length && ignore.some((p) => stack2.file.match(p)))
|
|
275
|
+
return null;
|
|
276
|
+
return stack2;
|
|
277
|
+
}).filter(notNullish);
|
|
278
|
+
return stackFrames;
|
|
279
|
+
}
|
|
280
|
+
function parseErrorStacktrace(e, ignore = stackIgnorePatterns) {
|
|
281
|
+
if (!e || isPrimitive(e))
|
|
282
|
+
return [];
|
|
283
|
+
if (e.stacks)
|
|
284
|
+
return e.stacks;
|
|
285
|
+
const stackStr = e.stack || e.stackStr || "";
|
|
286
|
+
const stackFrames = parseStacktrace(stackStr, ignore);
|
|
287
|
+
e.stacks = stackFrames;
|
|
288
|
+
return stackFrames;
|
|
289
|
+
}
|
|
290
|
+
function positionToOffset(source, lineNumber, columnNumber) {
|
|
291
|
+
const lines = source.split(lineSplitRE);
|
|
292
|
+
const nl = /\r\n/.test(source) ? 2 : 1;
|
|
293
|
+
let start = 0;
|
|
294
|
+
if (lineNumber > lines.length)
|
|
295
|
+
return source.length;
|
|
296
|
+
for (let i = 0; i < lineNumber - 1; i++)
|
|
297
|
+
start += lines[i].length + nl;
|
|
298
|
+
return start + columnNumber;
|
|
299
|
+
}
|
|
300
|
+
function offsetToLineNumber(source, offset) {
|
|
301
|
+
if (offset > source.length) {
|
|
302
|
+
throw new Error(
|
|
303
|
+
`offset is longer than source length! offset ${offset} > length ${source.length}`
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
const lines = source.split(lineSplitRE);
|
|
307
|
+
const nl = /\r\n/.test(source) ? 2 : 1;
|
|
308
|
+
let counted = 0;
|
|
309
|
+
let line = 0;
|
|
310
|
+
for (; line < lines.length; line++) {
|
|
311
|
+
const lineLength = lines[line].length + nl;
|
|
312
|
+
if (counted + lineLength >= offset)
|
|
313
|
+
break;
|
|
314
|
+
counted += lineLength;
|
|
315
|
+
}
|
|
316
|
+
return line + 1;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const serialize$1 = (val, config, indentation, depth, refs, printer) => {
|
|
320
|
+
const name = val.getMockName();
|
|
321
|
+
const nameString = name === "vi.fn()" ? "" : ` ${name}`;
|
|
322
|
+
let callsString = "";
|
|
323
|
+
if (val.mock.calls.length !== 0) {
|
|
324
|
+
const indentationNext = indentation + config.indent;
|
|
325
|
+
callsString = ` {${config.spacingOuter}${indentationNext}"calls": ${printer(val.mock.calls, config, indentationNext, depth, refs)}${config.min ? ", " : ","}${config.spacingOuter}${indentationNext}"results": ${printer(val.mock.results, config, indentationNext, depth, refs)}${config.min ? "" : ","}${config.spacingOuter}${indentation}}`;
|
|
326
|
+
}
|
|
327
|
+
return `[MockFunction${nameString}]${callsString}`;
|
|
328
|
+
};
|
|
329
|
+
const test = (val) => val && !!val._isMockFunction;
|
|
330
|
+
const plugin = { serialize: serialize$1, test };
|
|
331
|
+
|
|
332
|
+
const {
|
|
333
|
+
DOMCollection,
|
|
334
|
+
DOMElement,
|
|
335
|
+
Immutable,
|
|
336
|
+
ReactElement,
|
|
337
|
+
ReactTestComponent,
|
|
338
|
+
AsymmetricMatcher
|
|
339
|
+
} = plugins;
|
|
340
|
+
let PLUGINS = [
|
|
341
|
+
ReactTestComponent,
|
|
342
|
+
ReactElement,
|
|
343
|
+
DOMElement,
|
|
344
|
+
DOMCollection,
|
|
345
|
+
Immutable,
|
|
346
|
+
AsymmetricMatcher,
|
|
347
|
+
plugin
|
|
348
|
+
];
|
|
349
|
+
function addSerializer(plugin) {
|
|
350
|
+
PLUGINS = [plugin].concat(PLUGINS);
|
|
351
|
+
}
|
|
352
|
+
function getSerializers() {
|
|
353
|
+
return PLUGINS;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function testNameToKey(testName, count) {
|
|
357
|
+
return `${testName} ${count}`;
|
|
358
|
+
}
|
|
359
|
+
function keyToTestName(key) {
|
|
360
|
+
if (!/ \d+$/.test(key))
|
|
361
|
+
throw new Error("Snapshot keys must end with a number.");
|
|
362
|
+
return key.replace(/ \d+$/, "");
|
|
363
|
+
}
|
|
364
|
+
function getSnapshotData(content, options) {
|
|
365
|
+
const update = options.updateSnapshot;
|
|
366
|
+
const data = /* @__PURE__ */ Object.create(null);
|
|
367
|
+
let snapshotContents = "";
|
|
368
|
+
let dirty = false;
|
|
369
|
+
if (content != null) {
|
|
370
|
+
try {
|
|
371
|
+
snapshotContents = content;
|
|
372
|
+
const populate = new Function("exports", snapshotContents);
|
|
373
|
+
populate(data);
|
|
374
|
+
} catch {
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
const isInvalid = snapshotContents;
|
|
378
|
+
if ((update === "all" || update === "new") && isInvalid)
|
|
379
|
+
dirty = true;
|
|
380
|
+
return { data, dirty };
|
|
381
|
+
}
|
|
382
|
+
function addExtraLineBreaks(string) {
|
|
383
|
+
return string.includes("\n") ? `
|
|
384
|
+
${string}
|
|
385
|
+
` : string;
|
|
386
|
+
}
|
|
387
|
+
function removeExtraLineBreaks(string) {
|
|
388
|
+
return string.length > 2 && string.startsWith("\n") && string.endsWith("\n") ? string.slice(1, -1) : string;
|
|
389
|
+
}
|
|
390
|
+
const escapeRegex = true;
|
|
391
|
+
const printFunctionName = false;
|
|
392
|
+
function serialize(val, indent = 2, formatOverrides = {}) {
|
|
393
|
+
return normalizeNewlines(
|
|
394
|
+
format(val, {
|
|
395
|
+
escapeRegex,
|
|
396
|
+
indent,
|
|
397
|
+
plugins: getSerializers(),
|
|
398
|
+
printFunctionName,
|
|
399
|
+
...formatOverrides
|
|
400
|
+
})
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
function escapeBacktickString(str) {
|
|
404
|
+
return str.replace(/`|\\|\${/g, "\\$&");
|
|
405
|
+
}
|
|
406
|
+
function printBacktickString(str) {
|
|
407
|
+
return `\`${escapeBacktickString(str)}\``;
|
|
408
|
+
}
|
|
409
|
+
async function ensureDirectoryExists(environment, filePath) {
|
|
410
|
+
try {
|
|
411
|
+
await environment.prepareDirectory(join(dirname(filePath)));
|
|
412
|
+
} catch {
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
function normalizeNewlines(string) {
|
|
416
|
+
return string.replace(/\r\n|\r/g, "\n");
|
|
417
|
+
}
|
|
418
|
+
async function saveSnapshotFile(environment, snapshotData, snapshotPath) {
|
|
419
|
+
const snapshots = Object.keys(snapshotData).sort(naturalCompare$1.exports).map(
|
|
420
|
+
(key) => `exports[${printBacktickString(key)}] = ${printBacktickString(normalizeNewlines(snapshotData[key]))};`
|
|
421
|
+
);
|
|
422
|
+
const content = `${environment.getHeader()}
|
|
423
|
+
|
|
424
|
+
${snapshots.join("\n\n")}
|
|
425
|
+
`;
|
|
426
|
+
const oldContent = await environment.readSnapshotFile(snapshotPath);
|
|
427
|
+
const skipWriting = oldContent && oldContent === content;
|
|
428
|
+
if (skipWriting)
|
|
429
|
+
return;
|
|
430
|
+
await ensureDirectoryExists(environment, snapshotPath);
|
|
431
|
+
await environment.saveSnapshotFile(
|
|
432
|
+
snapshotPath,
|
|
433
|
+
content
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
function prepareExpected(expected) {
|
|
437
|
+
function findStartIndent() {
|
|
438
|
+
var _a, _b;
|
|
439
|
+
const matchObject = /^( +)}\s+$/m.exec(expected || "");
|
|
440
|
+
const objectIndent = (_a = matchObject == null ? void 0 : matchObject[1]) == null ? void 0 : _a.length;
|
|
441
|
+
if (objectIndent)
|
|
442
|
+
return objectIndent;
|
|
443
|
+
const matchText = /^\n( +)"/.exec(expected || "");
|
|
444
|
+
return ((_b = matchText == null ? void 0 : matchText[1]) == null ? void 0 : _b.length) || 0;
|
|
445
|
+
}
|
|
446
|
+
const startIndent = findStartIndent();
|
|
447
|
+
let expectedTrimmed = expected == null ? void 0 : expected.trim();
|
|
448
|
+
if (startIndent) {
|
|
449
|
+
expectedTrimmed = expectedTrimmed == null ? void 0 : expectedTrimmed.replace(new RegExp(`^${" ".repeat(startIndent)}`, "gm"), "").replace(/ +}$/, "}");
|
|
450
|
+
}
|
|
451
|
+
return expectedTrimmed;
|
|
452
|
+
}
|
|
453
|
+
function deepMergeArray(target = [], source = []) {
|
|
454
|
+
const mergedOutput = Array.from(target);
|
|
455
|
+
source.forEach((sourceElement, index) => {
|
|
456
|
+
const targetElement = mergedOutput[index];
|
|
457
|
+
if (Array.isArray(target[index])) {
|
|
458
|
+
mergedOutput[index] = deepMergeArray(target[index], sourceElement);
|
|
459
|
+
} else if (isObject(targetElement)) {
|
|
460
|
+
mergedOutput[index] = deepMergeSnapshot(target[index], sourceElement);
|
|
461
|
+
} else {
|
|
462
|
+
mergedOutput[index] = sourceElement;
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
return mergedOutput;
|
|
466
|
+
}
|
|
467
|
+
function deepMergeSnapshot(target, source) {
|
|
468
|
+
if (isObject(target) && isObject(source)) {
|
|
469
|
+
const mergedOutput = { ...target };
|
|
470
|
+
Object.keys(source).forEach((key) => {
|
|
471
|
+
if (isObject(source[key]) && !source[key].$$typeof) {
|
|
472
|
+
if (!(key in target))
|
|
473
|
+
Object.assign(mergedOutput, { [key]: source[key] });
|
|
474
|
+
else
|
|
475
|
+
mergedOutput[key] = deepMergeSnapshot(target[key], source[key]);
|
|
476
|
+
} else if (Array.isArray(source[key])) {
|
|
477
|
+
mergedOutput[key] = deepMergeArray(target[key], source[key]);
|
|
478
|
+
} else {
|
|
479
|
+
Object.assign(mergedOutput, { [key]: source[key] });
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
return mergedOutput;
|
|
483
|
+
} else if (Array.isArray(target) && Array.isArray(source)) {
|
|
484
|
+
return deepMergeArray(target, source);
|
|
485
|
+
}
|
|
486
|
+
return target;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
async function saveInlineSnapshots(environment, snapshots) {
|
|
490
|
+
const MagicString = (await import('magic-string')).default;
|
|
491
|
+
const files = new Set(snapshots.map((i) => i.file));
|
|
492
|
+
await Promise.all(Array.from(files).map(async (file) => {
|
|
493
|
+
const snaps = snapshots.filter((i) => i.file === file);
|
|
494
|
+
const code = await environment.readSnapshotFile(file);
|
|
495
|
+
const s = new MagicString(code);
|
|
496
|
+
for (const snap of snaps) {
|
|
497
|
+
const index = positionToOffset(code, snap.line, snap.column);
|
|
498
|
+
replaceInlineSnap(code, s, index, snap.snapshot);
|
|
499
|
+
}
|
|
500
|
+
const transformed = s.toString();
|
|
501
|
+
if (transformed !== code)
|
|
502
|
+
await environment.saveSnapshotFile(file, transformed);
|
|
503
|
+
}));
|
|
504
|
+
}
|
|
505
|
+
const startObjectRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\S\s]*\*\/\s*|\/\/.*\s+)*\s*({)/m;
|
|
506
|
+
function replaceObjectSnap(code, s, index, newSnap) {
|
|
507
|
+
code = code.slice(index);
|
|
508
|
+
const startMatch = startObjectRegex.exec(code);
|
|
509
|
+
if (!startMatch)
|
|
510
|
+
return false;
|
|
511
|
+
code = code.slice(startMatch.index);
|
|
512
|
+
const charIndex = getCallLastIndex(code);
|
|
513
|
+
if (charIndex === null)
|
|
514
|
+
return false;
|
|
515
|
+
s.appendLeft(index + startMatch.index + charIndex, `, ${prepareSnapString(newSnap, code, index)}`);
|
|
516
|
+
return true;
|
|
517
|
+
}
|
|
518
|
+
function prepareSnapString(snap, source, index) {
|
|
519
|
+
const lineNumber = offsetToLineNumber(source, index);
|
|
520
|
+
const line = source.split(lineSplitRE)[lineNumber - 1];
|
|
521
|
+
const indent = line.match(/^\s*/)[0] || "";
|
|
522
|
+
const indentNext = indent.includes(" ") ? `${indent} ` : `${indent} `;
|
|
523
|
+
const lines = snap.trim().replace(/\\/g, "\\\\").split(/\n/g);
|
|
524
|
+
const isOneline = lines.length <= 1;
|
|
525
|
+
const quote = isOneline ? "'" : "`";
|
|
526
|
+
if (isOneline)
|
|
527
|
+
return `'${lines.join("\n").replace(/'/g, "\\'")}'`;
|
|
528
|
+
else
|
|
529
|
+
return `${quote}
|
|
530
|
+
${lines.map((i) => i ? indentNext + i : "").join("\n").replace(/`/g, "\\`").replace(/\${/g, "\\${")}
|
|
531
|
+
${indent}${quote}`;
|
|
532
|
+
}
|
|
533
|
+
const startRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\S\s]*\*\/\s*|\/\/.*\s+)*\s*[\w_$]*(['"`\)])/m;
|
|
534
|
+
function replaceInlineSnap(code, s, index, newSnap) {
|
|
535
|
+
const startMatch = startRegex.exec(code.slice(index));
|
|
536
|
+
if (!startMatch)
|
|
537
|
+
return replaceObjectSnap(code, s, index, newSnap);
|
|
538
|
+
const quote = startMatch[1];
|
|
539
|
+
const startIndex = index + startMatch.index + startMatch[0].length;
|
|
540
|
+
const snapString = prepareSnapString(newSnap, code, index);
|
|
541
|
+
if (quote === ")") {
|
|
542
|
+
s.appendRight(startIndex - 1, snapString);
|
|
543
|
+
return true;
|
|
544
|
+
}
|
|
545
|
+
const quoteEndRE = new RegExp(`(?:^|[^\\\\])${quote}`);
|
|
546
|
+
const endMatch = quoteEndRE.exec(code.slice(startIndex));
|
|
547
|
+
if (!endMatch)
|
|
548
|
+
return false;
|
|
549
|
+
const endIndex = startIndex + endMatch.index + endMatch[0].length;
|
|
550
|
+
s.overwrite(startIndex - 1, endIndex, snapString);
|
|
551
|
+
return true;
|
|
552
|
+
}
|
|
553
|
+
const INDENTATION_REGEX = /^([^\S\n]*)\S/m;
|
|
554
|
+
function stripSnapshotIndentation(inlineSnapshot) {
|
|
555
|
+
const match = inlineSnapshot.match(INDENTATION_REGEX);
|
|
556
|
+
if (!match || !match[1]) {
|
|
557
|
+
return inlineSnapshot;
|
|
558
|
+
}
|
|
559
|
+
const indentation = match[1];
|
|
560
|
+
const lines = inlineSnapshot.split(/\n/g);
|
|
561
|
+
if (lines.length <= 2) {
|
|
562
|
+
return inlineSnapshot;
|
|
563
|
+
}
|
|
564
|
+
if (lines[0].trim() !== "" || lines[lines.length - 1].trim() !== "") {
|
|
565
|
+
return inlineSnapshot;
|
|
566
|
+
}
|
|
567
|
+
for (let i = 1; i < lines.length - 1; i++) {
|
|
568
|
+
if (lines[i] !== "") {
|
|
569
|
+
if (lines[i].indexOf(indentation) !== 0) {
|
|
570
|
+
return inlineSnapshot;
|
|
571
|
+
}
|
|
572
|
+
lines[i] = lines[i].substring(indentation.length);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
lines[lines.length - 1] = "";
|
|
576
|
+
inlineSnapshot = lines.join("\n");
|
|
577
|
+
return inlineSnapshot;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
async function saveRawSnapshots(environment, snapshots) {
|
|
581
|
+
await Promise.all(snapshots.map(async (snap) => {
|
|
582
|
+
if (!snap.readonly)
|
|
583
|
+
await environment.saveSnapshotFile(snap.file, snap.snapshot);
|
|
584
|
+
}));
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
class SnapshotState {
|
|
588
|
+
constructor(testFilePath, snapshotPath, snapshotContent, options) {
|
|
589
|
+
this.testFilePath = testFilePath;
|
|
590
|
+
this.snapshotPath = snapshotPath;
|
|
591
|
+
const { data, dirty } = getSnapshotData(
|
|
592
|
+
snapshotContent,
|
|
593
|
+
options
|
|
594
|
+
);
|
|
595
|
+
this._fileExists = snapshotContent != null;
|
|
596
|
+
this._initialData = data;
|
|
597
|
+
this._snapshotData = data;
|
|
598
|
+
this._dirty = dirty;
|
|
599
|
+
this._inlineSnapshots = [];
|
|
600
|
+
this._rawSnapshots = [];
|
|
601
|
+
this._uncheckedKeys = new Set(Object.keys(this._snapshotData));
|
|
602
|
+
this._counters = /* @__PURE__ */ new Map();
|
|
603
|
+
this.expand = options.expand || false;
|
|
604
|
+
this.added = 0;
|
|
605
|
+
this.matched = 0;
|
|
606
|
+
this.unmatched = 0;
|
|
607
|
+
this._updateSnapshot = options.updateSnapshot;
|
|
608
|
+
this.updated = 0;
|
|
609
|
+
this._snapshotFormat = {
|
|
610
|
+
printBasicPrototype: false,
|
|
611
|
+
...options.snapshotFormat
|
|
612
|
+
};
|
|
613
|
+
this._environment = options.snapshotEnvironment;
|
|
614
|
+
}
|
|
615
|
+
static async create(testFilePath, options) {
|
|
616
|
+
const snapshotPath = await options.snapshotEnvironment.resolvePath(testFilePath);
|
|
617
|
+
const content = await options.snapshotEnvironment.readSnapshotFile(snapshotPath);
|
|
618
|
+
return new SnapshotState(testFilePath, snapshotPath, content, options);
|
|
619
|
+
}
|
|
620
|
+
get environment() {
|
|
621
|
+
return this._environment;
|
|
622
|
+
}
|
|
623
|
+
markSnapshotsAsCheckedForTest(testName) {
|
|
624
|
+
this._uncheckedKeys.forEach((uncheckedKey) => {
|
|
625
|
+
if (keyToTestName(uncheckedKey) === testName)
|
|
626
|
+
this._uncheckedKeys.delete(uncheckedKey);
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
_inferInlineSnapshotStack(stacks) {
|
|
630
|
+
const promiseIndex = stacks.findIndex((i) => i.method.match(/__VITEST_(RESOLVES|REJECTS)__/));
|
|
631
|
+
if (promiseIndex !== -1)
|
|
632
|
+
return stacks[promiseIndex + 3];
|
|
633
|
+
const stackIndex = stacks.findIndex((i) => i.method.includes("__INLINE_SNAPSHOT__"));
|
|
634
|
+
return stackIndex !== -1 ? stacks[stackIndex + 2] : null;
|
|
635
|
+
}
|
|
636
|
+
_addSnapshot(key, receivedSerialized, options) {
|
|
637
|
+
this._dirty = true;
|
|
638
|
+
if (options.isInline) {
|
|
639
|
+
const stacks = parseErrorStacktrace(options.error || new Error("snapshot"), []);
|
|
640
|
+
const stack = this._inferInlineSnapshotStack(stacks);
|
|
641
|
+
if (!stack) {
|
|
642
|
+
throw new Error(
|
|
643
|
+
`@vitest/snapshot: Couldn't infer stack frame for inline snapshot.
|
|
644
|
+
${JSON.stringify(stacks)}`
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
stack.column--;
|
|
648
|
+
this._inlineSnapshots.push({
|
|
649
|
+
snapshot: receivedSerialized,
|
|
650
|
+
...stack
|
|
651
|
+
});
|
|
652
|
+
} else if (options.rawSnapshot) {
|
|
653
|
+
this._rawSnapshots.push({
|
|
654
|
+
...options.rawSnapshot,
|
|
655
|
+
snapshot: receivedSerialized
|
|
656
|
+
});
|
|
657
|
+
} else {
|
|
658
|
+
this._snapshotData[key] = receivedSerialized;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
clear() {
|
|
662
|
+
this._snapshotData = this._initialData;
|
|
663
|
+
this._counters = /* @__PURE__ */ new Map();
|
|
664
|
+
this.added = 0;
|
|
665
|
+
this.matched = 0;
|
|
666
|
+
this.unmatched = 0;
|
|
667
|
+
this.updated = 0;
|
|
668
|
+
this._dirty = false;
|
|
669
|
+
}
|
|
670
|
+
async save() {
|
|
671
|
+
const hasExternalSnapshots = Object.keys(this._snapshotData).length;
|
|
672
|
+
const hasInlineSnapshots = this._inlineSnapshots.length;
|
|
673
|
+
const hasRawSnapshots = this._rawSnapshots.length;
|
|
674
|
+
const isEmpty = !hasExternalSnapshots && !hasInlineSnapshots && !hasRawSnapshots;
|
|
675
|
+
const status = {
|
|
676
|
+
deleted: false,
|
|
677
|
+
saved: false
|
|
678
|
+
};
|
|
679
|
+
if ((this._dirty || this._uncheckedKeys.size) && !isEmpty) {
|
|
680
|
+
if (hasExternalSnapshots) {
|
|
681
|
+
await saveSnapshotFile(this._environment, this._snapshotData, this.snapshotPath);
|
|
682
|
+
this._fileExists = true;
|
|
683
|
+
}
|
|
684
|
+
if (hasInlineSnapshots)
|
|
685
|
+
await saveInlineSnapshots(this._environment, this._inlineSnapshots);
|
|
686
|
+
if (hasRawSnapshots)
|
|
687
|
+
await saveRawSnapshots(this._environment, this._rawSnapshots);
|
|
688
|
+
status.saved = true;
|
|
689
|
+
} else if (!hasExternalSnapshots && this._fileExists) {
|
|
690
|
+
if (this._updateSnapshot === "all") {
|
|
691
|
+
await this._environment.removeSnapshotFile(this.snapshotPath);
|
|
692
|
+
this._fileExists = false;
|
|
693
|
+
}
|
|
694
|
+
status.deleted = true;
|
|
695
|
+
}
|
|
696
|
+
return status;
|
|
697
|
+
}
|
|
698
|
+
getUncheckedCount() {
|
|
699
|
+
return this._uncheckedKeys.size || 0;
|
|
700
|
+
}
|
|
701
|
+
getUncheckedKeys() {
|
|
702
|
+
return Array.from(this._uncheckedKeys);
|
|
703
|
+
}
|
|
704
|
+
removeUncheckedKeys() {
|
|
705
|
+
if (this._updateSnapshot === "all" && this._uncheckedKeys.size) {
|
|
706
|
+
this._dirty = true;
|
|
707
|
+
this._uncheckedKeys.forEach((key) => delete this._snapshotData[key]);
|
|
708
|
+
this._uncheckedKeys.clear();
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
match({
|
|
712
|
+
testName,
|
|
713
|
+
received,
|
|
714
|
+
key,
|
|
715
|
+
inlineSnapshot,
|
|
716
|
+
isInline,
|
|
717
|
+
error,
|
|
718
|
+
rawSnapshot
|
|
719
|
+
}) {
|
|
720
|
+
this._counters.set(testName, (this._counters.get(testName) || 0) + 1);
|
|
721
|
+
const count = Number(this._counters.get(testName));
|
|
722
|
+
if (!key)
|
|
723
|
+
key = testNameToKey(testName, count);
|
|
724
|
+
if (!(isInline && this._snapshotData[key] !== void 0))
|
|
725
|
+
this._uncheckedKeys.delete(key);
|
|
726
|
+
let receivedSerialized = rawSnapshot && typeof received === "string" ? received : serialize(received, void 0, this._snapshotFormat);
|
|
727
|
+
if (!rawSnapshot)
|
|
728
|
+
receivedSerialized = addExtraLineBreaks(receivedSerialized);
|
|
729
|
+
const expected = isInline ? inlineSnapshot : rawSnapshot ? rawSnapshot.content : this._snapshotData[key];
|
|
730
|
+
const expectedTrimmed = prepareExpected(expected);
|
|
731
|
+
const pass = expectedTrimmed === prepareExpected(receivedSerialized);
|
|
732
|
+
const hasSnapshot = expected !== void 0;
|
|
733
|
+
const snapshotIsPersisted = isInline || this._fileExists || rawSnapshot && rawSnapshot.content != null;
|
|
734
|
+
if (pass && !isInline && !rawSnapshot) {
|
|
735
|
+
this._snapshotData[key] = receivedSerialized;
|
|
736
|
+
}
|
|
737
|
+
if (hasSnapshot && this._updateSnapshot === "all" || (!hasSnapshot || !snapshotIsPersisted) && (this._updateSnapshot === "new" || this._updateSnapshot === "all")) {
|
|
738
|
+
if (this._updateSnapshot === "all") {
|
|
739
|
+
if (!pass) {
|
|
740
|
+
if (hasSnapshot)
|
|
741
|
+
this.updated++;
|
|
742
|
+
else
|
|
743
|
+
this.added++;
|
|
744
|
+
this._addSnapshot(key, receivedSerialized, { error, isInline, rawSnapshot });
|
|
745
|
+
} else {
|
|
746
|
+
this.matched++;
|
|
747
|
+
}
|
|
748
|
+
} else {
|
|
749
|
+
this._addSnapshot(key, receivedSerialized, { error, isInline, rawSnapshot });
|
|
750
|
+
this.added++;
|
|
751
|
+
}
|
|
752
|
+
return {
|
|
753
|
+
actual: "",
|
|
754
|
+
count,
|
|
755
|
+
expected: "",
|
|
756
|
+
key,
|
|
757
|
+
pass: true
|
|
758
|
+
};
|
|
759
|
+
} else {
|
|
760
|
+
if (!pass) {
|
|
761
|
+
this.unmatched++;
|
|
762
|
+
return {
|
|
763
|
+
actual: removeExtraLineBreaks(receivedSerialized),
|
|
764
|
+
count,
|
|
765
|
+
expected: expectedTrimmed !== void 0 ? removeExtraLineBreaks(expectedTrimmed) : void 0,
|
|
766
|
+
key,
|
|
767
|
+
pass: false
|
|
768
|
+
};
|
|
769
|
+
} else {
|
|
770
|
+
this.matched++;
|
|
771
|
+
return {
|
|
772
|
+
actual: "",
|
|
773
|
+
count,
|
|
774
|
+
expected: "",
|
|
775
|
+
key,
|
|
776
|
+
pass: true
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
async pack() {
|
|
782
|
+
const snapshot = {
|
|
783
|
+
filepath: this.testFilePath,
|
|
784
|
+
added: 0,
|
|
785
|
+
fileDeleted: false,
|
|
786
|
+
matched: 0,
|
|
787
|
+
unchecked: 0,
|
|
788
|
+
uncheckedKeys: [],
|
|
789
|
+
unmatched: 0,
|
|
790
|
+
updated: 0
|
|
791
|
+
};
|
|
792
|
+
const uncheckedCount = this.getUncheckedCount();
|
|
793
|
+
const uncheckedKeys = this.getUncheckedKeys();
|
|
794
|
+
if (uncheckedCount)
|
|
795
|
+
this.removeUncheckedKeys();
|
|
796
|
+
const status = await this.save();
|
|
797
|
+
snapshot.fileDeleted = status.deleted;
|
|
798
|
+
snapshot.added = this.added;
|
|
799
|
+
snapshot.matched = this.matched;
|
|
800
|
+
snapshot.unmatched = this.unmatched;
|
|
801
|
+
snapshot.updated = this.updated;
|
|
802
|
+
snapshot.unchecked = !status.deleted ? uncheckedCount : 0;
|
|
803
|
+
snapshot.uncheckedKeys = Array.from(uncheckedKeys);
|
|
804
|
+
return snapshot;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
function createMismatchError(message, actual, expected) {
|
|
809
|
+
const error = new Error(message);
|
|
810
|
+
Object.defineProperty(error, "actual", {
|
|
811
|
+
value: actual,
|
|
812
|
+
enumerable: true,
|
|
813
|
+
configurable: true,
|
|
814
|
+
writable: true
|
|
815
|
+
});
|
|
816
|
+
Object.defineProperty(error, "expected", {
|
|
817
|
+
value: expected,
|
|
818
|
+
enumerable: true,
|
|
819
|
+
configurable: true,
|
|
820
|
+
writable: true
|
|
821
|
+
});
|
|
822
|
+
return error;
|
|
823
|
+
}
|
|
824
|
+
class SnapshotClient {
|
|
825
|
+
constructor(Service = SnapshotState) {
|
|
826
|
+
this.Service = Service;
|
|
827
|
+
this.snapshotStateMap = /* @__PURE__ */ new Map();
|
|
828
|
+
}
|
|
829
|
+
async setTest(filepath, name, options) {
|
|
830
|
+
var _a;
|
|
831
|
+
this.filepath = filepath;
|
|
832
|
+
this.name = name;
|
|
833
|
+
if (((_a = this.snapshotState) == null ? void 0 : _a.testFilePath) !== filepath) {
|
|
834
|
+
this.resetCurrent();
|
|
835
|
+
if (!this.getSnapshotState(filepath)) {
|
|
836
|
+
this.snapshotStateMap.set(
|
|
837
|
+
filepath,
|
|
838
|
+
await this.Service.create(
|
|
839
|
+
filepath,
|
|
840
|
+
options
|
|
841
|
+
)
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
this.snapshotState = this.getSnapshotState(filepath);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
getSnapshotState(filepath) {
|
|
848
|
+
return this.snapshotStateMap.get(filepath);
|
|
849
|
+
}
|
|
850
|
+
clearTest() {
|
|
851
|
+
this.filepath = void 0;
|
|
852
|
+
this.name = void 0;
|
|
853
|
+
}
|
|
854
|
+
skipTestSnapshots(name) {
|
|
855
|
+
var _a;
|
|
856
|
+
(_a = this.snapshotState) == null ? void 0 : _a.markSnapshotsAsCheckedForTest(name);
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Should be overridden by the consumer.
|
|
860
|
+
*
|
|
861
|
+
* Vitest checks equality with @vitest/expect.
|
|
862
|
+
*/
|
|
863
|
+
equalityCheck(received, expected) {
|
|
864
|
+
return received === expected;
|
|
865
|
+
}
|
|
866
|
+
assert(options) {
|
|
867
|
+
const {
|
|
868
|
+
filepath = this.filepath,
|
|
869
|
+
name = this.name,
|
|
870
|
+
message,
|
|
871
|
+
isInline = false,
|
|
872
|
+
properties,
|
|
873
|
+
inlineSnapshot,
|
|
874
|
+
error,
|
|
875
|
+
errorMessage,
|
|
876
|
+
rawSnapshot
|
|
877
|
+
} = options;
|
|
878
|
+
let { received } = options;
|
|
879
|
+
if (!filepath)
|
|
880
|
+
throw new Error("Snapshot cannot be used outside of test");
|
|
881
|
+
if (typeof properties === "object") {
|
|
882
|
+
if (typeof received !== "object" || !received)
|
|
883
|
+
throw new Error("Received value must be an object when the matcher has properties");
|
|
884
|
+
try {
|
|
885
|
+
const pass2 = this.equalityCheck(received, properties);
|
|
886
|
+
if (!pass2)
|
|
887
|
+
throw createMismatchError("Snapshot properties mismatched", received, properties);
|
|
888
|
+
else
|
|
889
|
+
received = deepMergeSnapshot(received, properties);
|
|
890
|
+
} catch (err) {
|
|
891
|
+
err.message = errorMessage || "Snapshot mismatched";
|
|
892
|
+
throw err;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
const testName = [
|
|
896
|
+
name,
|
|
897
|
+
...message ? [message] : []
|
|
898
|
+
].join(" > ");
|
|
899
|
+
const snapshotState = this.getSnapshotState(filepath);
|
|
900
|
+
const { actual, expected, key, pass } = snapshotState.match({
|
|
901
|
+
testName,
|
|
902
|
+
received,
|
|
903
|
+
isInline,
|
|
904
|
+
error,
|
|
905
|
+
inlineSnapshot,
|
|
906
|
+
rawSnapshot
|
|
907
|
+
});
|
|
908
|
+
if (!pass)
|
|
909
|
+
throw createMismatchError(`Snapshot \`${key || "unknown"}\` mismatched`, actual == null ? void 0 : actual.trim(), expected == null ? void 0 : expected.trim());
|
|
910
|
+
}
|
|
911
|
+
async assertRaw(options) {
|
|
912
|
+
if (!options.rawSnapshot)
|
|
913
|
+
throw new Error("Raw snapshot is required");
|
|
914
|
+
const {
|
|
915
|
+
filepath = this.filepath,
|
|
916
|
+
rawSnapshot
|
|
917
|
+
} = options;
|
|
918
|
+
if (rawSnapshot.content == null) {
|
|
919
|
+
if (!filepath)
|
|
920
|
+
throw new Error("Snapshot cannot be used outside of test");
|
|
921
|
+
const snapshotState = this.getSnapshotState(filepath);
|
|
922
|
+
options.filepath || (options.filepath = filepath);
|
|
923
|
+
rawSnapshot.file = await snapshotState.environment.resolveRawPath(filepath, rawSnapshot.file);
|
|
924
|
+
rawSnapshot.content = await snapshotState.environment.readSnapshotFile(rawSnapshot.file) || void 0;
|
|
925
|
+
}
|
|
926
|
+
return this.assert(options);
|
|
927
|
+
}
|
|
928
|
+
async resetCurrent() {
|
|
929
|
+
if (!this.snapshotState)
|
|
930
|
+
return null;
|
|
931
|
+
const result = await this.snapshotState.pack();
|
|
932
|
+
this.snapshotState = void 0;
|
|
933
|
+
return result;
|
|
934
|
+
}
|
|
935
|
+
clear() {
|
|
936
|
+
this.snapshotStateMap.clear();
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
export { SnapshotClient, SnapshotState, addSerializer, getSerializers, stripSnapshotIndentation };
|