@vitest/snapshot 3.0.9 → 3.1.0-beta.2

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/dist/index.js CHANGED
@@ -577,221 +577,229 @@ function traceSegmentInternal(segments, memo, line, column, bias) {
577
577
  return index;
578
578
  }
579
579
 
580
+ /**
581
+ * Get original stacktrace without source map support the most performant way.
582
+ * - Create only 1 stack frame.
583
+ * - Rewrite prepareStackTrace to bypass "support-stack-trace" (usually takes ~250ms).
584
+ */
580
585
  function notNullish(v) {
581
- return v != null;
586
+ return v != null;
582
587
  }
583
588
  function isPrimitive(value) {
584
- return value === null || typeof value !== "function" && typeof value !== "object";
589
+ return value === null || typeof value !== "function" && typeof value !== "object";
585
590
  }
586
591
  function isObject(item) {
587
- return item != null && typeof item === "object" && !Array.isArray(item);
592
+ return item != null && typeof item === "object" && !Array.isArray(item);
588
593
  }
594
+ /**
595
+ * If code starts with a function call, will return its last index, respecting arguments.
596
+ * This will return 25 - last ending character of toMatch ")"
597
+ * Also works with callbacks
598
+ * ```
599
+ * toMatch({ test: '123' });
600
+ * toBeAliased('123')
601
+ * ```
602
+ */
589
603
  function getCallLastIndex(code) {
590
- let charIndex = -1;
591
- let inString = null;
592
- let startedBracers = 0;
593
- let endedBracers = 0;
594
- let beforeChar = null;
595
- while (charIndex <= code.length) {
596
- beforeChar = code[charIndex];
597
- charIndex++;
598
- const char = code[charIndex];
599
- const isCharString = char === '"' || char === "'" || char === "`";
600
- if (isCharString && beforeChar !== "\\") {
601
- if (inString === char) {
602
- inString = null;
603
- } else if (!inString) {
604
- inString = char;
605
- }
606
- }
607
- if (!inString) {
608
- if (char === "(") {
609
- startedBracers++;
610
- }
611
- if (char === ")") {
612
- endedBracers++;
613
- }
614
- }
615
- if (startedBracers && endedBracers && startedBracers === endedBracers) {
616
- return charIndex;
617
- }
618
- }
619
- return null;
604
+ let charIndex = -1;
605
+ let inString = null;
606
+ let startedBracers = 0;
607
+ let endedBracers = 0;
608
+ let beforeChar = null;
609
+ while (charIndex <= code.length) {
610
+ beforeChar = code[charIndex];
611
+ charIndex++;
612
+ const char = code[charIndex];
613
+ const isCharString = char === "\"" || char === "'" || char === "`";
614
+ if (isCharString && beforeChar !== "\\") {
615
+ if (inString === char) {
616
+ inString = null;
617
+ } else if (!inString) {
618
+ inString = char;
619
+ }
620
+ }
621
+ if (!inString) {
622
+ if (char === "(") {
623
+ startedBracers++;
624
+ }
625
+ if (char === ")") {
626
+ endedBracers++;
627
+ }
628
+ }
629
+ if (startedBracers && endedBracers && startedBracers === endedBracers) {
630
+ return charIndex;
631
+ }
632
+ }
633
+ return null;
620
634
  }
621
635
 
622
636
  const CHROME_IE_STACK_REGEXP = /^\s*at .*(?:\S:\d+|\(native\))/m;
623
637
  const SAFARI_NATIVE_CODE_REGEXP = /^(?:eval@)?(?:\[native code\])?$/;
624
638
  const stackIgnorePatterns = [
625
- "node:internal",
626
- /\/packages\/\w+\/dist\//,
627
- /\/@vitest\/\w+\/dist\//,
628
- "/vitest/dist/",
629
- "/vitest/src/",
630
- "/vite-node/dist/",
631
- "/vite-node/src/",
632
- "/node_modules/chai/",
633
- "/node_modules/tinypool/",
634
- "/node_modules/tinyspy/",
635
- // browser related deps
636
- "/deps/chunk-",
637
- "/deps/@vitest",
638
- "/deps/loupe",
639
- "/deps/chai",
640
- /node:\w+/,
641
- /__vitest_test__/,
642
- /__vitest_browser__/,
643
- /\/deps\/vitest_/
639
+ "node:internal",
640
+ /\/packages\/\w+\/dist\//,
641
+ /\/@vitest\/\w+\/dist\//,
642
+ "/vitest/dist/",
643
+ "/vitest/src/",
644
+ "/vite-node/dist/",
645
+ "/vite-node/src/",
646
+ "/node_modules/chai/",
647
+ "/node_modules/tinypool/",
648
+ "/node_modules/tinyspy/",
649
+ "/deps/chunk-",
650
+ "/deps/@vitest",
651
+ "/deps/loupe",
652
+ "/deps/chai",
653
+ /node:\w+/,
654
+ /__vitest_test__/,
655
+ /__vitest_browser__/,
656
+ /\/deps\/vitest_/
644
657
  ];
645
658
  function extractLocation(urlLike) {
646
- if (!urlLike.includes(":")) {
647
- return [urlLike];
648
- }
649
- const regExp = /(.+?)(?::(\d+))?(?::(\d+))?$/;
650
- const parts = regExp.exec(urlLike.replace(/^\(|\)$/g, ""));
651
- if (!parts) {
652
- return [urlLike];
653
- }
654
- let url = parts[1];
655
- if (url.startsWith("async ")) {
656
- url = url.slice(6);
657
- }
658
- if (url.startsWith("http:") || url.startsWith("https:")) {
659
- const urlObj = new URL(url);
660
- urlObj.searchParams.delete("import");
661
- urlObj.searchParams.delete("browserv");
662
- url = urlObj.pathname + urlObj.hash + urlObj.search;
663
- }
664
- if (url.startsWith("/@fs/")) {
665
- const isWindows = /^\/@fs\/[a-zA-Z]:\//.test(url);
666
- url = url.slice(isWindows ? 5 : 4);
667
- }
668
- return [url, parts[2] || void 0, parts[3] || void 0];
659
+ if (!urlLike.includes(":")) {
660
+ return [urlLike];
661
+ }
662
+ const regExp = /(.+?)(?::(\d+))?(?::(\d+))?$/;
663
+ const parts = regExp.exec(urlLike.replace(/^\(|\)$/g, ""));
664
+ if (!parts) {
665
+ return [urlLike];
666
+ }
667
+ let url = parts[1];
668
+ if (url.startsWith("async ")) {
669
+ url = url.slice(6);
670
+ }
671
+ if (url.startsWith("http:") || url.startsWith("https:")) {
672
+ const urlObj = new URL(url);
673
+ urlObj.searchParams.delete("import");
674
+ urlObj.searchParams.delete("browserv");
675
+ url = urlObj.pathname + urlObj.hash + urlObj.search;
676
+ }
677
+ if (url.startsWith("/@fs/")) {
678
+ const isWindows = /^\/@fs\/[a-zA-Z]:\//.test(url);
679
+ url = url.slice(isWindows ? 5 : 4);
680
+ }
681
+ return [
682
+ url,
683
+ parts[2] || undefined,
684
+ parts[3] || undefined
685
+ ];
669
686
  }
670
687
  function parseSingleFFOrSafariStack(raw) {
671
- let line = raw.trim();
672
- if (SAFARI_NATIVE_CODE_REGEXP.test(line)) {
673
- return null;
674
- }
675
- if (line.includes(" > eval")) {
676
- line = line.replace(
677
- / line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,
678
- ":$1"
679
- );
680
- }
681
- if (!line.includes("@") && !line.includes(":")) {
682
- return null;
683
- }
684
- const functionNameRegex = /((.*".+"[^@]*)?[^@]*)(@)/;
685
- const matches = line.match(functionNameRegex);
686
- const functionName = matches && matches[1] ? matches[1] : void 0;
687
- const [url, lineNumber, columnNumber] = extractLocation(
688
- line.replace(functionNameRegex, "")
689
- );
690
- if (!url || !lineNumber || !columnNumber) {
691
- return null;
692
- }
693
- return {
694
- file: url,
695
- method: functionName || "",
696
- line: Number.parseInt(lineNumber),
697
- column: Number.parseInt(columnNumber)
698
- };
688
+ let line = raw.trim();
689
+ if (SAFARI_NATIVE_CODE_REGEXP.test(line)) {
690
+ return null;
691
+ }
692
+ if (line.includes(" > eval")) {
693
+ line = line.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g, ":$1");
694
+ }
695
+ if (!line.includes("@") && !line.includes(":")) {
696
+ return null;
697
+ }
698
+ const functionNameRegex = /((.*".+"[^@]*)?[^@]*)(@)/;
699
+ const matches = line.match(functionNameRegex);
700
+ const functionName = matches && matches[1] ? matches[1] : undefined;
701
+ const [url, lineNumber, columnNumber] = extractLocation(line.replace(functionNameRegex, ""));
702
+ if (!url || !lineNumber || !columnNumber) {
703
+ return null;
704
+ }
705
+ return {
706
+ file: url,
707
+ method: functionName || "",
708
+ line: Number.parseInt(lineNumber),
709
+ column: Number.parseInt(columnNumber)
710
+ };
699
711
  }
700
712
  function parseSingleV8Stack(raw) {
701
- let line = raw.trim();
702
- if (!CHROME_IE_STACK_REGEXP.test(line)) {
703
- return null;
704
- }
705
- if (line.includes("(eval ")) {
706
- line = line.replace(/eval code/g, "eval").replace(/(\(eval at [^()]*)|(,.*$)/g, "");
707
- }
708
- let sanitizedLine = line.replace(/^\s+/, "").replace(/\(eval code/g, "(").replace(/^.*?\s+/, "");
709
- const location = sanitizedLine.match(/ (\(.+\)$)/);
710
- sanitizedLine = location ? sanitizedLine.replace(location[0], "") : sanitizedLine;
711
- const [url, lineNumber, columnNumber] = extractLocation(
712
- location ? location[1] : sanitizedLine
713
- );
714
- let method = location && sanitizedLine || "";
715
- let file = url && ["eval", "<anonymous>"].includes(url) ? void 0 : url;
716
- if (!file || !lineNumber || !columnNumber) {
717
- return null;
718
- }
719
- if (method.startsWith("async ")) {
720
- method = method.slice(6);
721
- }
722
- if (file.startsWith("file://")) {
723
- file = file.slice(7);
724
- }
725
- file = file.startsWith("node:") || file.startsWith("internal:") ? file : resolve$2(file);
726
- if (method) {
727
- method = method.replace(/__vite_ssr_import_\d+__\./g, "");
728
- }
729
- return {
730
- method,
731
- file,
732
- line: Number.parseInt(lineNumber),
733
- column: Number.parseInt(columnNumber)
734
- };
713
+ let line = raw.trim();
714
+ if (!CHROME_IE_STACK_REGEXP.test(line)) {
715
+ return null;
716
+ }
717
+ if (line.includes("(eval ")) {
718
+ line = line.replace(/eval code/g, "eval").replace(/(\(eval at [^()]*)|(,.*$)/g, "");
719
+ }
720
+ let sanitizedLine = line.replace(/^\s+/, "").replace(/\(eval code/g, "(").replace(/^.*?\s+/, "");
721
+ const location = sanitizedLine.match(/ (\(.+\)$)/);
722
+ sanitizedLine = location ? sanitizedLine.replace(location[0], "") : sanitizedLine;
723
+ const [url, lineNumber, columnNumber] = extractLocation(location ? location[1] : sanitizedLine);
724
+ let method = location && sanitizedLine || "";
725
+ let file = url && ["eval", "<anonymous>"].includes(url) ? undefined : url;
726
+ if (!file || !lineNumber || !columnNumber) {
727
+ return null;
728
+ }
729
+ if (method.startsWith("async ")) {
730
+ method = method.slice(6);
731
+ }
732
+ if (file.startsWith("file://")) {
733
+ file = file.slice(7);
734
+ }
735
+ file = file.startsWith("node:") || file.startsWith("internal:") ? file : resolve$2(file);
736
+ if (method) {
737
+ method = method.replace(/__vite_ssr_import_\d+__\./g, "");
738
+ }
739
+ return {
740
+ method,
741
+ file,
742
+ line: Number.parseInt(lineNumber),
743
+ column: Number.parseInt(columnNumber)
744
+ };
735
745
  }
736
746
  function parseStacktrace(stack, options = {}) {
737
- const { ignoreStackEntries = stackIgnorePatterns } = options;
738
- const stacks = !CHROME_IE_STACK_REGEXP.test(stack) ? parseFFOrSafariStackTrace(stack) : parseV8Stacktrace(stack);
739
- return stacks.map((stack2) => {
740
- var _a;
741
- if (options.getUrlId) {
742
- stack2.file = options.getUrlId(stack2.file);
743
- }
744
- const map = (_a = options.getSourceMap) == null ? void 0 : _a.call(options, stack2.file);
745
- if (!map || typeof map !== "object" || !map.version) {
746
- return shouldFilter(ignoreStackEntries, stack2.file) ? null : stack2;
747
- }
748
- const traceMap = new TraceMap(map);
749
- const { line, column, source, name } = originalPositionFor(traceMap, stack2);
750
- let file = stack2.file;
751
- if (source) {
752
- const fileUrl = stack2.file.startsWith("file://") ? stack2.file : `file://${stack2.file}`;
753
- const sourceRootUrl = map.sourceRoot ? new URL(map.sourceRoot, fileUrl) : fileUrl;
754
- file = new URL(source, sourceRootUrl).pathname;
755
- }
756
- if (shouldFilter(ignoreStackEntries, file)) {
757
- return null;
758
- }
759
- if (line != null && column != null) {
760
- return {
761
- line,
762
- column,
763
- file,
764
- method: name || stack2.method
765
- };
766
- }
767
- return stack2;
768
- }).filter((s) => s != null);
747
+ const { ignoreStackEntries = stackIgnorePatterns } = options;
748
+ const stacks = !CHROME_IE_STACK_REGEXP.test(stack) ? parseFFOrSafariStackTrace(stack) : parseV8Stacktrace(stack);
749
+ return stacks.map((stack) => {
750
+ var _options$getSourceMap;
751
+ if (options.getUrlId) {
752
+ stack.file = options.getUrlId(stack.file);
753
+ }
754
+ const map = (_options$getSourceMap = options.getSourceMap) === null || _options$getSourceMap === void 0 ? void 0 : _options$getSourceMap.call(options, stack.file);
755
+ if (!map || typeof map !== "object" || !map.version) {
756
+ return shouldFilter(ignoreStackEntries, stack.file) ? null : stack;
757
+ }
758
+ const traceMap = new TraceMap(map);
759
+ const { line, column, source, name } = originalPositionFor(traceMap, stack);
760
+ let file = stack.file;
761
+ if (source) {
762
+ const fileUrl = stack.file.startsWith("file://") ? stack.file : `file://${stack.file}`;
763
+ const sourceRootUrl = map.sourceRoot ? new URL(map.sourceRoot, fileUrl) : fileUrl;
764
+ file = new URL(source, sourceRootUrl).pathname;
765
+ }
766
+ if (shouldFilter(ignoreStackEntries, file)) {
767
+ return null;
768
+ }
769
+ if (line != null && column != null) {
770
+ return {
771
+ line,
772
+ column,
773
+ file,
774
+ method: name || stack.method
775
+ };
776
+ }
777
+ return stack;
778
+ }).filter((s) => s != null);
769
779
  }
770
780
  function shouldFilter(ignoreStackEntries, file) {
771
- return ignoreStackEntries.some((p) => file.match(p));
781
+ return ignoreStackEntries.some((p) => file.match(p));
772
782
  }
773
783
  function parseFFOrSafariStackTrace(stack) {
774
- return stack.split("\n").map((line) => parseSingleFFOrSafariStack(line)).filter(notNullish);
784
+ return stack.split("\n").map((line) => parseSingleFFOrSafariStack(line)).filter(notNullish);
775
785
  }
776
786
  function parseV8Stacktrace(stack) {
777
- return stack.split("\n").map((line) => parseSingleV8Stack(line)).filter(notNullish);
787
+ return stack.split("\n").map((line) => parseSingleV8Stack(line)).filter(notNullish);
778
788
  }
779
789
  function parseErrorStacktrace(e, options = {}) {
780
- if (!e || isPrimitive(e)) {
781
- return [];
782
- }
783
- if (e.stacks) {
784
- return e.stacks;
785
- }
786
- const stackStr = e.stack || e.stackStr || "";
787
- let stackFrames = parseStacktrace(stackStr, options);
788
- if (options.frameFilter) {
789
- stackFrames = stackFrames.filter(
790
- (f) => options.frameFilter(e, f) !== false
791
- );
792
- }
793
- e.stacks = stackFrames;
794
- return stackFrames;
790
+ if (!e || isPrimitive(e)) {
791
+ return [];
792
+ }
793
+ if (e.stacks) {
794
+ return e.stacks;
795
+ }
796
+ const stackStr = e.stack || e.stackStr || "";
797
+ let stackFrames = parseStacktrace(stackStr, options);
798
+ if (options.frameFilter) {
799
+ stackFrames = stackFrames.filter((f) => options.frameFilter(e, f) !== false);
800
+ }
801
+ e.stacks = stackFrames;
802
+ return stackFrames;
795
803
  }
796
804
 
797
805
  let getPromiseValue = () => 'Promise{…}';
@@ -828,14 +836,7 @@ catch (noNodeInspect) {
828
836
  nodeInspect = false;
829
837
  }
830
838
 
831
- const {
832
- AsymmetricMatcher: AsymmetricMatcher$1,
833
- DOMCollection: DOMCollection$1,
834
- DOMElement: DOMElement$1,
835
- Immutable: Immutable$1,
836
- ReactElement: ReactElement$1,
837
- ReactTestComponent: ReactTestComponent$1
838
- } = plugins;
839
+ const { AsymmetricMatcher: AsymmetricMatcher$1, DOMCollection: DOMCollection$1, DOMElement: DOMElement$1, Immutable: Immutable$1, ReactElement: ReactElement$1, ReactTestComponent: ReactTestComponent$1 } = plugins;
839
840
 
840
841
  function getDefaultExportFromCjs (x) {
841
842
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
@@ -1374,190 +1375,180 @@ p();
1374
1375
 
1375
1376
  const lineSplitRE = /\r?\n/;
1376
1377
  function positionToOffset(source, lineNumber, columnNumber) {
1377
- const lines = source.split(lineSplitRE);
1378
- const nl = /\r\n/.test(source) ? 2 : 1;
1379
- let start = 0;
1380
- if (lineNumber > lines.length) {
1381
- return source.length;
1382
- }
1383
- for (let i = 0; i < lineNumber - 1; i++) {
1384
- start += lines[i].length + nl;
1385
- }
1386
- return start + columnNumber;
1378
+ const lines = source.split(lineSplitRE);
1379
+ const nl = /\r\n/.test(source) ? 2 : 1;
1380
+ let start = 0;
1381
+ if (lineNumber > lines.length) {
1382
+ return source.length;
1383
+ }
1384
+ for (let i = 0; i < lineNumber - 1; i++) {
1385
+ start += lines[i].length + nl;
1386
+ }
1387
+ return start + columnNumber;
1387
1388
  }
1388
1389
  function offsetToLineNumber(source, offset) {
1389
- if (offset > source.length) {
1390
- throw new Error(
1391
- `offset is longer than source length! offset ${offset} > length ${source.length}`
1392
- );
1393
- }
1394
- const lines = source.split(lineSplitRE);
1395
- const nl = /\r\n/.test(source) ? 2 : 1;
1396
- let counted = 0;
1397
- let line = 0;
1398
- for (; line < lines.length; line++) {
1399
- const lineLength = lines[line].length + nl;
1400
- if (counted + lineLength >= offset) {
1401
- break;
1402
- }
1403
- counted += lineLength;
1404
- }
1405
- return line + 1;
1390
+ if (offset > source.length) {
1391
+ throw new Error(`offset is longer than source length! offset ${offset} > length ${source.length}`);
1392
+ }
1393
+ const lines = source.split(lineSplitRE);
1394
+ const nl = /\r\n/.test(source) ? 2 : 1;
1395
+ let counted = 0;
1396
+ let line = 0;
1397
+ for (; line < lines.length; line++) {
1398
+ const lineLength = lines[line].length + nl;
1399
+ if (counted + lineLength >= offset) {
1400
+ break;
1401
+ }
1402
+ counted += lineLength;
1403
+ }
1404
+ return line + 1;
1406
1405
  }
1407
1406
 
1408
1407
  async function saveInlineSnapshots(environment, snapshots) {
1409
- const MagicString = (await import('magic-string')).default;
1410
- const files = new Set(snapshots.map((i) => i.file));
1411
- await Promise.all(
1412
- Array.from(files).map(async (file) => {
1413
- const snaps = snapshots.filter((i) => i.file === file);
1414
- const code = await environment.readSnapshotFile(file);
1415
- const s = new MagicString(code);
1416
- for (const snap of snaps) {
1417
- const index = positionToOffset(code, snap.line, snap.column);
1418
- replaceInlineSnap(code, s, index, snap.snapshot);
1419
- }
1420
- const transformed = s.toString();
1421
- if (transformed !== code) {
1422
- await environment.saveSnapshotFile(file, transformed);
1423
- }
1424
- })
1425
- );
1408
+ const MagicString = (await import('magic-string')).default;
1409
+ const files = new Set(snapshots.map((i) => i.file));
1410
+ await Promise.all(Array.from(files).map(async (file) => {
1411
+ const snaps = snapshots.filter((i) => i.file === file);
1412
+ const code = await environment.readSnapshotFile(file);
1413
+ const s = new MagicString(code);
1414
+ for (const snap of snaps) {
1415
+ const index = positionToOffset(code, snap.line, snap.column);
1416
+ replaceInlineSnap(code, s, index, snap.snapshot);
1417
+ }
1418
+ const transformed = s.toString();
1419
+ if (transformed !== code) {
1420
+ await environment.saveSnapshotFile(file, transformed);
1421
+ }
1422
+ }));
1426
1423
  }
1427
1424
  const startObjectRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\s\S]*\*\/\s*|\/\/.*(?:[\n\r\u2028\u2029]\s*|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF]))*\{/;
1428
1425
  function replaceObjectSnap(code, s, index, newSnap) {
1429
- let _code = code.slice(index);
1430
- const startMatch = startObjectRegex.exec(_code);
1431
- if (!startMatch) {
1432
- return false;
1433
- }
1434
- _code = _code.slice(startMatch.index);
1435
- let callEnd = getCallLastIndex(_code);
1436
- if (callEnd === null) {
1437
- return false;
1438
- }
1439
- callEnd += index + startMatch.index;
1440
- const shapeStart = index + startMatch.index + startMatch[0].length;
1441
- const shapeEnd = getObjectShapeEndIndex(code, shapeStart);
1442
- const snap = `, ${prepareSnapString(newSnap, code, index)}`;
1443
- if (shapeEnd === callEnd) {
1444
- s.appendLeft(callEnd, snap);
1445
- } else {
1446
- s.overwrite(shapeEnd, callEnd, snap);
1447
- }
1448
- return true;
1426
+ let _code = code.slice(index);
1427
+ const startMatch = startObjectRegex.exec(_code);
1428
+ if (!startMatch) {
1429
+ return false;
1430
+ }
1431
+ _code = _code.slice(startMatch.index);
1432
+ let callEnd = getCallLastIndex(_code);
1433
+ if (callEnd === null) {
1434
+ return false;
1435
+ }
1436
+ callEnd += index + startMatch.index;
1437
+ const shapeStart = index + startMatch.index + startMatch[0].length;
1438
+ const shapeEnd = getObjectShapeEndIndex(code, shapeStart);
1439
+ const snap = `, ${prepareSnapString(newSnap, code, index)}`;
1440
+ if (shapeEnd === callEnd) {
1441
+ s.appendLeft(callEnd, snap);
1442
+ } else {
1443
+ s.overwrite(shapeEnd, callEnd, snap);
1444
+ }
1445
+ return true;
1449
1446
  }
1450
1447
  function getObjectShapeEndIndex(code, index) {
1451
- let startBraces = 1;
1452
- let endBraces = 0;
1453
- while (startBraces !== endBraces && index < code.length) {
1454
- const s = code[index++];
1455
- if (s === "{") {
1456
- startBraces++;
1457
- } else if (s === "}") {
1458
- endBraces++;
1459
- }
1460
- }
1461
- return index;
1448
+ let startBraces = 1;
1449
+ let endBraces = 0;
1450
+ while (startBraces !== endBraces && index < code.length) {
1451
+ const s = code[index++];
1452
+ if (s === "{") {
1453
+ startBraces++;
1454
+ } else if (s === "}") {
1455
+ endBraces++;
1456
+ }
1457
+ }
1458
+ return index;
1462
1459
  }
1463
1460
  function prepareSnapString(snap, source, index) {
1464
- const lineNumber = offsetToLineNumber(source, index);
1465
- const line = source.split(lineSplitRE)[lineNumber - 1];
1466
- const indent = line.match(/^\s*/)[0] || "";
1467
- const indentNext = indent.includes(" ") ? `${indent} ` : `${indent} `;
1468
- const lines = snap.trim().replace(/\\/g, "\\\\").split(/\n/g);
1469
- const isOneline = lines.length <= 1;
1470
- const quote = "`";
1471
- if (isOneline) {
1472
- return `${quote}${lines.join("\n").replace(/`/g, "\\`").replace(/\$\{/g, "\\${")}${quote}`;
1473
- }
1474
- return `${quote}
1475
- ${lines.map((i) => i ? indentNext + i : "").join("\n").replace(/`/g, "\\`").replace(/\$\{/g, "\\${")}
1476
- ${indent}${quote}`;
1461
+ const lineNumber = offsetToLineNumber(source, index);
1462
+ const line = source.split(lineSplitRE)[lineNumber - 1];
1463
+ const indent = line.match(/^\s*/)[0] || "";
1464
+ const indentNext = indent.includes(" ") ? `${indent}\t` : `${indent} `;
1465
+ const lines = snap.trim().replace(/\\/g, "\\\\").split(/\n/g);
1466
+ const isOneline = lines.length <= 1;
1467
+ const quote = "`";
1468
+ if (isOneline) {
1469
+ return `${quote}${lines.join("\n").replace(/`/g, "\\`").replace(/\$\{/g, "\\\${")}${quote}`;
1470
+ }
1471
+ return `${quote}\n${lines.map((i) => i ? indentNext + i : "").join("\n").replace(/`/g, "\\`").replace(/\$\{/g, "\\\${")}\n${indent}${quote}`;
1477
1472
  }
1478
1473
  const toMatchInlineName = "toMatchInlineSnapshot";
1479
1474
  const toThrowErrorMatchingInlineName = "toThrowErrorMatchingInlineSnapshot";
1480
1475
  function getCodeStartingAtIndex(code, index) {
1481
- const indexInline = index - toMatchInlineName.length;
1482
- if (code.slice(indexInline, index) === toMatchInlineName) {
1483
- return {
1484
- code: code.slice(indexInline),
1485
- index: indexInline
1486
- };
1487
- }
1488
- const indexThrowInline = index - toThrowErrorMatchingInlineName.length;
1489
- if (code.slice(index - indexThrowInline, index) === toThrowErrorMatchingInlineName) {
1490
- return {
1491
- code: code.slice(index - indexThrowInline),
1492
- index: index - indexThrowInline
1493
- };
1494
- }
1495
- return {
1496
- code: code.slice(index),
1497
- index
1498
- };
1476
+ const indexInline = index - toMatchInlineName.length;
1477
+ if (code.slice(indexInline, index) === toMatchInlineName) {
1478
+ return {
1479
+ code: code.slice(indexInline),
1480
+ index: indexInline
1481
+ };
1482
+ }
1483
+ const indexThrowInline = index - toThrowErrorMatchingInlineName.length;
1484
+ if (code.slice(index - indexThrowInline, index) === toThrowErrorMatchingInlineName) {
1485
+ return {
1486
+ code: code.slice(index - indexThrowInline),
1487
+ index: index - indexThrowInline
1488
+ };
1489
+ }
1490
+ return {
1491
+ code: code.slice(index),
1492
+ index
1493
+ };
1499
1494
  }
1500
1495
  const startRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\s\S]*\*\/\s*|\/\/.*(?:[\n\r\u2028\u2029]\s*|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF]))*[\w$]*(['"`)])/;
1501
1496
  function replaceInlineSnap(code, s, currentIndex, newSnap) {
1502
- const { code: codeStartingAtIndex, index } = getCodeStartingAtIndex(code, currentIndex);
1503
- const startMatch = startRegex.exec(codeStartingAtIndex);
1504
- const firstKeywordMatch = /toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot/.exec(
1505
- codeStartingAtIndex
1506
- );
1507
- if (!startMatch || startMatch.index !== (firstKeywordMatch == null ? void 0 : firstKeywordMatch.index)) {
1508
- return replaceObjectSnap(code, s, index, newSnap);
1509
- }
1510
- const quote = startMatch[1];
1511
- const startIndex = index + startMatch.index + startMatch[0].length;
1512
- const snapString = prepareSnapString(newSnap, code, index);
1513
- if (quote === ")") {
1514
- s.appendRight(startIndex - 1, snapString);
1515
- return true;
1516
- }
1517
- const quoteEndRE = new RegExp(`(?:^|[^\\\\])${quote}`);
1518
- const endMatch = quoteEndRE.exec(code.slice(startIndex));
1519
- if (!endMatch) {
1520
- return false;
1521
- }
1522
- const endIndex = startIndex + endMatch.index + endMatch[0].length;
1523
- s.overwrite(startIndex - 1, endIndex, snapString);
1524
- return true;
1497
+ const { code: codeStartingAtIndex, index } = getCodeStartingAtIndex(code, currentIndex);
1498
+ const startMatch = startRegex.exec(codeStartingAtIndex);
1499
+ const firstKeywordMatch = /toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot/.exec(codeStartingAtIndex);
1500
+ if (!startMatch || startMatch.index !== (firstKeywordMatch === null || firstKeywordMatch === void 0 ? void 0 : firstKeywordMatch.index)) {
1501
+ return replaceObjectSnap(code, s, index, newSnap);
1502
+ }
1503
+ const quote = startMatch[1];
1504
+ const startIndex = index + startMatch.index + startMatch[0].length;
1505
+ const snapString = prepareSnapString(newSnap, code, index);
1506
+ if (quote === ")") {
1507
+ s.appendRight(startIndex - 1, snapString);
1508
+ return true;
1509
+ }
1510
+ const quoteEndRE = new RegExp(`(?:^|[^\\\\])${quote}`);
1511
+ const endMatch = quoteEndRE.exec(code.slice(startIndex));
1512
+ if (!endMatch) {
1513
+ return false;
1514
+ }
1515
+ const endIndex = startIndex + endMatch.index + endMatch[0].length;
1516
+ s.overwrite(startIndex - 1, endIndex, snapString);
1517
+ return true;
1525
1518
  }
1526
1519
  const INDENTATION_REGEX = /^([^\S\n]*)\S/m;
1527
1520
  function stripSnapshotIndentation(inlineSnapshot) {
1528
- const match = inlineSnapshot.match(INDENTATION_REGEX);
1529
- if (!match || !match[1]) {
1530
- return inlineSnapshot;
1531
- }
1532
- const indentation = match[1];
1533
- const lines = inlineSnapshot.split(/\n/g);
1534
- if (lines.length <= 2) {
1535
- return inlineSnapshot;
1536
- }
1537
- if (lines[0].trim() !== "" || lines[lines.length - 1].trim() !== "") {
1538
- return inlineSnapshot;
1539
- }
1540
- for (let i = 1; i < lines.length - 1; i++) {
1541
- if (lines[i] !== "") {
1542
- if (lines[i].indexOf(indentation) !== 0) {
1543
- return inlineSnapshot;
1544
- }
1545
- lines[i] = lines[i].substring(indentation.length);
1546
- }
1547
- }
1548
- lines[lines.length - 1] = "";
1549
- inlineSnapshot = lines.join("\n");
1550
- return inlineSnapshot;
1521
+ const match = inlineSnapshot.match(INDENTATION_REGEX);
1522
+ if (!match || !match[1]) {
1523
+ return inlineSnapshot;
1524
+ }
1525
+ const indentation = match[1];
1526
+ const lines = inlineSnapshot.split(/\n/g);
1527
+ if (lines.length <= 2) {
1528
+ return inlineSnapshot;
1529
+ }
1530
+ if (lines[0].trim() !== "" || lines[lines.length - 1].trim() !== "") {
1531
+ return inlineSnapshot;
1532
+ }
1533
+ for (let i = 1; i < lines.length - 1; i++) {
1534
+ if (lines[i] !== "") {
1535
+ if (lines[i].indexOf(indentation) !== 0) {
1536
+ return inlineSnapshot;
1537
+ }
1538
+ lines[i] = lines[i].substring(indentation.length);
1539
+ }
1540
+ }
1541
+ lines[lines.length - 1] = "";
1542
+ inlineSnapshot = lines.join("\n");
1543
+ return inlineSnapshot;
1551
1544
  }
1552
1545
 
1553
1546
  async function saveRawSnapshots(environment, snapshots) {
1554
- await Promise.all(
1555
- snapshots.map(async (snap) => {
1556
- if (!snap.readonly) {
1557
- await environment.saveSnapshotFile(snap.file, snap.snapshot);
1558
- }
1559
- })
1560
- );
1547
+ await Promise.all(snapshots.map(async (snap) => {
1548
+ if (!snap.readonly) {
1549
+ await environment.saveSnapshotFile(snap.file, snap.snapshot);
1550
+ }
1551
+ }));
1561
1552
  }
1562
1553
 
1563
1554
  var naturalCompare$1 = {exports: {}};
@@ -1628,699 +1619,618 @@ var naturalCompareExports = requireNaturalCompare();
1628
1619
  var naturalCompare = /*@__PURE__*/getDefaultExportFromCjs(naturalCompareExports);
1629
1620
 
1630
1621
  const serialize$1 = (val, config, indentation, depth, refs, printer) => {
1631
- const name = val.getMockName();
1632
- const nameString = name === "vi.fn()" ? "" : ` ${name}`;
1633
- let callsString = "";
1634
- if (val.mock.calls.length !== 0) {
1635
- const indentationNext = indentation + config.indent;
1636
- callsString = ` {${config.spacingOuter}${indentationNext}"calls": ${printer(
1637
- val.mock.calls,
1638
- config,
1639
- indentationNext,
1640
- depth,
1641
- refs
1642
- )}${config.min ? ", " : ","}${config.spacingOuter}${indentationNext}"results": ${printer(
1643
- val.mock.results,
1644
- config,
1645
- indentationNext,
1646
- depth,
1647
- refs
1648
- )}${config.min ? "" : ","}${config.spacingOuter}${indentation}}`;
1649
- }
1650
- return `[MockFunction${nameString}]${callsString}`;
1622
+ const name = val.getMockName();
1623
+ const nameString = name === "vi.fn()" ? "" : ` ${name}`;
1624
+ let callsString = "";
1625
+ if (val.mock.calls.length !== 0) {
1626
+ const indentationNext = indentation + config.indent;
1627
+ 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}}`;
1628
+ }
1629
+ return `[MockFunction${nameString}]${callsString}`;
1651
1630
  };
1652
1631
  const test = (val) => val && !!val._isMockFunction;
1653
- const plugin = { serialize: serialize$1, test };
1632
+ const plugin = {
1633
+ serialize: serialize$1,
1634
+ test
1635
+ };
1654
1636
 
1655
- const {
1656
- DOMCollection,
1657
- DOMElement,
1658
- Immutable,
1659
- ReactElement,
1660
- ReactTestComponent,
1661
- AsymmetricMatcher
1662
- } = plugins;
1637
+ const { DOMCollection, DOMElement, Immutable, ReactElement, ReactTestComponent, AsymmetricMatcher } = plugins;
1663
1638
  let PLUGINS = [
1664
- ReactTestComponent,
1665
- ReactElement,
1666
- DOMElement,
1667
- DOMCollection,
1668
- Immutable,
1669
- AsymmetricMatcher,
1670
- plugin
1639
+ ReactTestComponent,
1640
+ ReactElement,
1641
+ DOMElement,
1642
+ DOMCollection,
1643
+ Immutable,
1644
+ AsymmetricMatcher,
1645
+ plugin
1671
1646
  ];
1672
1647
  function addSerializer(plugin) {
1673
- PLUGINS = [plugin].concat(PLUGINS);
1648
+ PLUGINS = [plugin].concat(PLUGINS);
1674
1649
  }
1675
1650
  function getSerializers() {
1676
- return PLUGINS;
1651
+ return PLUGINS;
1677
1652
  }
1678
1653
 
1679
1654
  function testNameToKey(testName, count) {
1680
- return `${testName} ${count}`;
1655
+ return `${testName} ${count}`;
1681
1656
  }
1682
1657
  function keyToTestName(key) {
1683
- if (!/ \d+$/.test(key)) {
1684
- throw new Error("Snapshot keys must end with a number.");
1685
- }
1686
- return key.replace(/ \d+$/, "");
1658
+ if (!/ \d+$/.test(key)) {
1659
+ throw new Error("Snapshot keys must end with a number.");
1660
+ }
1661
+ return key.replace(/ \d+$/, "");
1687
1662
  }
1688
1663
  function getSnapshotData(content, options) {
1689
- const update = options.updateSnapshot;
1690
- const data = /* @__PURE__ */ Object.create(null);
1691
- let snapshotContents = "";
1692
- let dirty = false;
1693
- if (content != null) {
1694
- try {
1695
- snapshotContents = content;
1696
- const populate = new Function("exports", snapshotContents);
1697
- populate(data);
1698
- } catch {
1699
- }
1700
- }
1701
- const isInvalid = snapshotContents;
1702
- if ((update === "all" || update === "new") && isInvalid) {
1703
- dirty = true;
1704
- }
1705
- return { data, dirty };
1664
+ const update = options.updateSnapshot;
1665
+ const data = Object.create(null);
1666
+ let snapshotContents = "";
1667
+ let dirty = false;
1668
+ if (content != null) {
1669
+ try {
1670
+ snapshotContents = content;
1671
+ const populate = new Function("exports", snapshotContents);
1672
+ populate(data);
1673
+ } catch {}
1674
+ }
1675
+ const isInvalid = snapshotContents;
1676
+ if ((update === "all" || update === "new") && isInvalid) {
1677
+ dirty = true;
1678
+ }
1679
+ return {
1680
+ data,
1681
+ dirty
1682
+ };
1706
1683
  }
1707
1684
  function addExtraLineBreaks(string) {
1708
- return string.includes("\n") ? `
1709
- ${string}
1710
- ` : string;
1685
+ return string.includes("\n") ? `\n${string}\n` : string;
1711
1686
  }
1712
1687
  function removeExtraLineBreaks(string) {
1713
- return string.length > 2 && string.startsWith("\n") && string.endsWith("\n") ? string.slice(1, -1) : string;
1688
+ return string.length > 2 && string.startsWith("\n") && string.endsWith("\n") ? string.slice(1, -1) : string;
1714
1689
  }
1715
1690
  const escapeRegex = true;
1716
1691
  const printFunctionName = false;
1717
1692
  function serialize(val, indent = 2, formatOverrides = {}) {
1718
- return normalizeNewlines(
1719
- format(val, {
1720
- escapeRegex,
1721
- indent,
1722
- plugins: getSerializers(),
1723
- printFunctionName,
1724
- ...formatOverrides
1725
- })
1726
- );
1693
+ return normalizeNewlines(format(val, {
1694
+ escapeRegex,
1695
+ indent,
1696
+ plugins: getSerializers(),
1697
+ printFunctionName,
1698
+ ...formatOverrides
1699
+ }));
1727
1700
  }
1728
1701
  function escapeBacktickString(str) {
1729
- return str.replace(/`|\\|\$\{/g, "\\$&");
1702
+ return str.replace(/`|\\|\$\{/g, "\\$&");
1730
1703
  }
1731
1704
  function printBacktickString(str) {
1732
- return `\`${escapeBacktickString(str)}\``;
1705
+ return `\`${escapeBacktickString(str)}\``;
1733
1706
  }
1734
1707
  function normalizeNewlines(string) {
1735
- return string.replace(/\r\n|\r/g, "\n");
1708
+ return string.replace(/\r\n|\r/g, "\n");
1736
1709
  }
1737
1710
  async function saveSnapshotFile(environment, snapshotData, snapshotPath) {
1738
- const snapshots = Object.keys(snapshotData).sort(naturalCompare).map(
1739
- (key) => `exports[${printBacktickString(key)}] = ${printBacktickString(
1740
- normalizeNewlines(snapshotData[key])
1741
- )};`
1742
- );
1743
- const content = `${environment.getHeader()}
1744
-
1745
- ${snapshots.join("\n\n")}
1746
- `;
1747
- const oldContent = await environment.readSnapshotFile(snapshotPath);
1748
- const skipWriting = oldContent != null && oldContent === content;
1749
- if (skipWriting) {
1750
- return;
1751
- }
1752
- await environment.saveSnapshotFile(snapshotPath, content);
1711
+ const snapshots = Object.keys(snapshotData).sort(naturalCompare).map((key) => `exports[${printBacktickString(key)}] = ${printBacktickString(normalizeNewlines(snapshotData[key]))};`);
1712
+ const content = `${environment.getHeader()}\n\n${snapshots.join("\n\n")}\n`;
1713
+ const oldContent = await environment.readSnapshotFile(snapshotPath);
1714
+ const skipWriting = oldContent != null && oldContent === content;
1715
+ if (skipWriting) {
1716
+ return;
1717
+ }
1718
+ await environment.saveSnapshotFile(snapshotPath, content);
1753
1719
  }
1754
1720
  function prepareExpected(expected) {
1755
- function findStartIndent() {
1756
- var _a, _b;
1757
- const matchObject = /^( +)\}\s+$/m.exec(expected || "");
1758
- const objectIndent = (_a = matchObject == null ? void 0 : matchObject[1]) == null ? void 0 : _a.length;
1759
- if (objectIndent) {
1760
- return objectIndent;
1761
- }
1762
- const matchText = /^\n( +)"/.exec(expected || "");
1763
- return ((_b = matchText == null ? void 0 : matchText[1]) == null ? void 0 : _b.length) || 0;
1764
- }
1765
- const startIndent = findStartIndent();
1766
- let expectedTrimmed = expected == null ? void 0 : expected.trim();
1767
- if (startIndent) {
1768
- expectedTrimmed = expectedTrimmed == null ? void 0 : expectedTrimmed.replace(new RegExp(`^${" ".repeat(startIndent)}`, "gm"), "").replace(/ +\}$/, "}");
1769
- }
1770
- return expectedTrimmed;
1721
+ function findStartIndent() {
1722
+ var _matchObject$, _matchText$;
1723
+ const matchObject = /^( +)\}\s+$/m.exec(expected || "");
1724
+ const objectIndent = matchObject === null || matchObject === void 0 || (_matchObject$ = matchObject[1]) === null || _matchObject$ === void 0 ? void 0 : _matchObject$.length;
1725
+ if (objectIndent) {
1726
+ return objectIndent;
1727
+ }
1728
+ const matchText = /^\n( +)"/.exec(expected || "");
1729
+ return (matchText === null || matchText === void 0 || (_matchText$ = matchText[1]) === null || _matchText$ === void 0 ? void 0 : _matchText$.length) || 0;
1730
+ }
1731
+ const startIndent = findStartIndent();
1732
+ let expectedTrimmed = expected === null || expected === void 0 ? void 0 : expected.trim();
1733
+ if (startIndent) {
1734
+ expectedTrimmed = expectedTrimmed === null || expectedTrimmed === void 0 ? void 0 : expectedTrimmed.replace(new RegExp(`^${" ".repeat(startIndent)}`, "gm"), "").replace(/ +\}$/, "}");
1735
+ }
1736
+ return expectedTrimmed;
1771
1737
  }
1772
1738
  function deepMergeArray(target = [], source = []) {
1773
- const mergedOutput = Array.from(target);
1774
- source.forEach((sourceElement, index) => {
1775
- const targetElement = mergedOutput[index];
1776
- if (Array.isArray(target[index])) {
1777
- mergedOutput[index] = deepMergeArray(target[index], sourceElement);
1778
- } else if (isObject(targetElement)) {
1779
- mergedOutput[index] = deepMergeSnapshot(target[index], sourceElement);
1780
- } else {
1781
- mergedOutput[index] = sourceElement;
1782
- }
1783
- });
1784
- return mergedOutput;
1739
+ const mergedOutput = Array.from(target);
1740
+ source.forEach((sourceElement, index) => {
1741
+ const targetElement = mergedOutput[index];
1742
+ if (Array.isArray(target[index])) {
1743
+ mergedOutput[index] = deepMergeArray(target[index], sourceElement);
1744
+ } else if (isObject(targetElement)) {
1745
+ mergedOutput[index] = deepMergeSnapshot(target[index], sourceElement);
1746
+ } else {
1747
+ mergedOutput[index] = sourceElement;
1748
+ }
1749
+ });
1750
+ return mergedOutput;
1785
1751
  }
1752
+ /**
1753
+ * Deep merge, but considers asymmetric matchers. Unlike base util's deep merge,
1754
+ * will merge any object-like instance.
1755
+ * Compatible with Jest's snapshot matcher. Should not be used outside of snapshot.
1756
+ *
1757
+ * @example
1758
+ * ```ts
1759
+ * toMatchSnapshot({
1760
+ * name: expect.stringContaining('text')
1761
+ * })
1762
+ * ```
1763
+ */
1786
1764
  function deepMergeSnapshot(target, source) {
1787
- if (isObject(target) && isObject(source)) {
1788
- const mergedOutput = { ...target };
1789
- Object.keys(source).forEach((key) => {
1790
- if (isObject(source[key]) && !source[key].$$typeof) {
1791
- if (!(key in target)) {
1792
- Object.assign(mergedOutput, { [key]: source[key] });
1793
- } else {
1794
- mergedOutput[key] = deepMergeSnapshot(target[key], source[key]);
1795
- }
1796
- } else if (Array.isArray(source[key])) {
1797
- mergedOutput[key] = deepMergeArray(target[key], source[key]);
1798
- } else {
1799
- Object.assign(mergedOutput, { [key]: source[key] });
1800
- }
1801
- });
1802
- return mergedOutput;
1803
- } else if (Array.isArray(target) && Array.isArray(source)) {
1804
- return deepMergeArray(target, source);
1805
- }
1806
- return target;
1765
+ if (isObject(target) && isObject(source)) {
1766
+ const mergedOutput = { ...target };
1767
+ Object.keys(source).forEach((key) => {
1768
+ if (isObject(source[key]) && !source[key].$$typeof) {
1769
+ if (!(key in target)) {
1770
+ Object.assign(mergedOutput, { [key]: source[key] });
1771
+ } else {
1772
+ mergedOutput[key] = deepMergeSnapshot(target[key], source[key]);
1773
+ }
1774
+ } else if (Array.isArray(source[key])) {
1775
+ mergedOutput[key] = deepMergeArray(target[key], source[key]);
1776
+ } else {
1777
+ Object.assign(mergedOutput, { [key]: source[key] });
1778
+ }
1779
+ });
1780
+ return mergedOutput;
1781
+ } else if (Array.isArray(target) && Array.isArray(source)) {
1782
+ return deepMergeArray(target, source);
1783
+ }
1784
+ return target;
1807
1785
  }
1808
1786
  class DefaultMap extends Map {
1809
- constructor(defaultFn, entries) {
1810
- super(entries);
1811
- this.defaultFn = defaultFn;
1812
- }
1813
- get(key) {
1814
- if (!this.has(key)) {
1815
- this.set(key, this.defaultFn(key));
1816
- }
1817
- return super.get(key);
1818
- }
1787
+ constructor(defaultFn, entries) {
1788
+ super(entries);
1789
+ this.defaultFn = defaultFn;
1790
+ }
1791
+ get(key) {
1792
+ if (!this.has(key)) {
1793
+ this.set(key, this.defaultFn(key));
1794
+ }
1795
+ return super.get(key);
1796
+ }
1819
1797
  }
1820
1798
  class CounterMap extends DefaultMap {
1821
- constructor() {
1822
- super(() => 0);
1823
- }
1824
- // compat for jest-image-snapshot https://github.com/vitest-dev/vitest/issues/7322
1825
- // `valueOf` and `Snapshot.added` setter allows
1826
- // snapshotState.added = snapshotState.added + 1
1827
- // to function as
1828
- // snapshotState.added.total_ = snapshotState.added.total() + 1
1829
- _total;
1830
- valueOf() {
1831
- return this._total = this.total();
1832
- }
1833
- increment(key) {
1834
- if (typeof this._total !== "undefined") {
1835
- this._total++;
1836
- }
1837
- this.set(key, this.get(key) + 1);
1838
- }
1839
- total() {
1840
- if (typeof this._total !== "undefined") {
1841
- return this._total;
1842
- }
1843
- let total = 0;
1844
- for (const x of this.values()) {
1845
- total += x;
1846
- }
1847
- return total;
1848
- }
1799
+ constructor() {
1800
+ super(() => 0);
1801
+ }
1802
+ _total;
1803
+ valueOf() {
1804
+ return this._total = this.total();
1805
+ }
1806
+ increment(key) {
1807
+ if (typeof this._total !== "undefined") {
1808
+ this._total++;
1809
+ }
1810
+ this.set(key, this.get(key) + 1);
1811
+ }
1812
+ total() {
1813
+ if (typeof this._total !== "undefined") {
1814
+ return this._total;
1815
+ }
1816
+ let total = 0;
1817
+ for (const x of this.values()) {
1818
+ total += x;
1819
+ }
1820
+ return total;
1821
+ }
1849
1822
  }
1850
1823
 
1851
1824
  function isSameStackPosition(x, y) {
1852
- return x.file === y.file && x.column === y.column && x.line === y.line;
1825
+ return x.file === y.file && x.column === y.column && x.line === y.line;
1853
1826
  }
1854
1827
  class SnapshotState {
1855
- constructor(testFilePath, snapshotPath, snapshotContent, options) {
1856
- this.testFilePath = testFilePath;
1857
- this.snapshotPath = snapshotPath;
1858
- const { data, dirty } = getSnapshotData(snapshotContent, options);
1859
- this._fileExists = snapshotContent != null;
1860
- this._initialData = { ...data };
1861
- this._snapshotData = { ...data };
1862
- this._dirty = dirty;
1863
- this._inlineSnapshots = [];
1864
- this._inlineSnapshotStacks = [];
1865
- this._rawSnapshots = [];
1866
- this._uncheckedKeys = new Set(Object.keys(this._snapshotData));
1867
- this.expand = options.expand || false;
1868
- this._updateSnapshot = options.updateSnapshot;
1869
- this._snapshotFormat = {
1870
- printBasicPrototype: false,
1871
- escapeString: false,
1872
- ...options.snapshotFormat
1873
- };
1874
- this._environment = options.snapshotEnvironment;
1875
- }
1876
- _counters = new CounterMap();
1877
- _dirty;
1878
- _updateSnapshot;
1879
- _snapshotData;
1880
- _initialData;
1881
- _inlineSnapshots;
1882
- _inlineSnapshotStacks;
1883
- _testIdToKeys = new DefaultMap(() => []);
1884
- _rawSnapshots;
1885
- _uncheckedKeys;
1886
- _snapshotFormat;
1887
- _environment;
1888
- _fileExists;
1889
- expand;
1890
- // getter/setter for jest-image-snapshot compat
1891
- // https://github.com/vitest-dev/vitest/issues/7322
1892
- _added = new CounterMap();
1893
- _matched = new CounterMap();
1894
- _unmatched = new CounterMap();
1895
- _updated = new CounterMap();
1896
- get added() {
1897
- return this._added;
1898
- }
1899
- set added(value) {
1900
- this._added._total = value;
1901
- }
1902
- get matched() {
1903
- return this._matched;
1904
- }
1905
- set matched(value) {
1906
- this._matched._total = value;
1907
- }
1908
- get unmatched() {
1909
- return this._unmatched;
1910
- }
1911
- set unmatched(value) {
1912
- this._unmatched._total = value;
1913
- }
1914
- get updated() {
1915
- return this._updated;
1916
- }
1917
- set updated(value) {
1918
- this._updated._total = value;
1919
- }
1920
- static async create(testFilePath, options) {
1921
- const snapshotPath = await options.snapshotEnvironment.resolvePath(
1922
- testFilePath
1923
- );
1924
- const content = await options.snapshotEnvironment.readSnapshotFile(
1925
- snapshotPath
1926
- );
1927
- return new SnapshotState(testFilePath, snapshotPath, content, options);
1928
- }
1929
- get environment() {
1930
- return this._environment;
1931
- }
1932
- markSnapshotsAsCheckedForTest(testName) {
1933
- this._uncheckedKeys.forEach((uncheckedKey) => {
1934
- if (/ \d+$| > /.test(uncheckedKey.slice(testName.length))) {
1935
- this._uncheckedKeys.delete(uncheckedKey);
1936
- }
1937
- });
1938
- }
1939
- clearTest(testId) {
1940
- this._inlineSnapshots = this._inlineSnapshots.filter((s) => s.testId !== testId);
1941
- this._inlineSnapshotStacks = this._inlineSnapshotStacks.filter((s) => s.testId !== testId);
1942
- for (const key of this._testIdToKeys.get(testId)) {
1943
- const name = keyToTestName(key);
1944
- const count = this._counters.get(name);
1945
- if (count > 0) {
1946
- if (key in this._snapshotData || key in this._initialData) {
1947
- this._snapshotData[key] = this._initialData[key];
1948
- }
1949
- this._counters.set(name, count - 1);
1950
- }
1951
- }
1952
- this._testIdToKeys.delete(testId);
1953
- this.added.delete(testId);
1954
- this.updated.delete(testId);
1955
- this.matched.delete(testId);
1956
- this.unmatched.delete(testId);
1957
- }
1958
- _inferInlineSnapshotStack(stacks) {
1959
- const promiseIndex = stacks.findIndex(
1960
- (i) => i.method.match(/__VITEST_(RESOLVES|REJECTS)__/)
1961
- );
1962
- if (promiseIndex !== -1) {
1963
- return stacks[promiseIndex + 3];
1964
- }
1965
- const stackIndex = stacks.findIndex(
1966
- (i) => i.method.includes("__INLINE_SNAPSHOT__")
1967
- );
1968
- return stackIndex !== -1 ? stacks[stackIndex + 2] : null;
1969
- }
1970
- _addSnapshot(key, receivedSerialized, options) {
1971
- this._dirty = true;
1972
- if (options.stack) {
1973
- this._inlineSnapshots.push({
1974
- snapshot: receivedSerialized,
1975
- testId: options.testId,
1976
- ...options.stack
1977
- });
1978
- } else if (options.rawSnapshot) {
1979
- this._rawSnapshots.push({
1980
- ...options.rawSnapshot,
1981
- snapshot: receivedSerialized
1982
- });
1983
- } else {
1984
- this._snapshotData[key] = receivedSerialized;
1985
- }
1986
- }
1987
- async save() {
1988
- const hasExternalSnapshots = Object.keys(this._snapshotData).length;
1989
- const hasInlineSnapshots = this._inlineSnapshots.length;
1990
- const hasRawSnapshots = this._rawSnapshots.length;
1991
- const isEmpty = !hasExternalSnapshots && !hasInlineSnapshots && !hasRawSnapshots;
1992
- const status = {
1993
- deleted: false,
1994
- saved: false
1995
- };
1996
- if ((this._dirty || this._uncheckedKeys.size) && !isEmpty) {
1997
- if (hasExternalSnapshots) {
1998
- await saveSnapshotFile(
1999
- this._environment,
2000
- this._snapshotData,
2001
- this.snapshotPath
2002
- );
2003
- this._fileExists = true;
2004
- }
2005
- if (hasInlineSnapshots) {
2006
- await saveInlineSnapshots(this._environment, this._inlineSnapshots);
2007
- }
2008
- if (hasRawSnapshots) {
2009
- await saveRawSnapshots(this._environment, this._rawSnapshots);
2010
- }
2011
- status.saved = true;
2012
- } else if (!hasExternalSnapshots && this._fileExists) {
2013
- if (this._updateSnapshot === "all") {
2014
- await this._environment.removeSnapshotFile(this.snapshotPath);
2015
- this._fileExists = false;
2016
- }
2017
- status.deleted = true;
2018
- }
2019
- return status;
2020
- }
2021
- getUncheckedCount() {
2022
- return this._uncheckedKeys.size || 0;
2023
- }
2024
- getUncheckedKeys() {
2025
- return Array.from(this._uncheckedKeys);
2026
- }
2027
- removeUncheckedKeys() {
2028
- if (this._updateSnapshot === "all" && this._uncheckedKeys.size) {
2029
- this._dirty = true;
2030
- this._uncheckedKeys.forEach((key) => delete this._snapshotData[key]);
2031
- this._uncheckedKeys.clear();
2032
- }
2033
- }
2034
- match({
2035
- testId,
2036
- testName,
2037
- received,
2038
- key,
2039
- inlineSnapshot,
2040
- isInline,
2041
- error,
2042
- rawSnapshot
2043
- }) {
2044
- var _a, _b;
2045
- this._counters.increment(testName);
2046
- const count = this._counters.get(testName);
2047
- if (!key) {
2048
- key = testNameToKey(testName, count);
2049
- }
2050
- this._testIdToKeys.get(testId).push(key);
2051
- if (!(isInline && this._snapshotData[key] !== void 0)) {
2052
- this._uncheckedKeys.delete(key);
2053
- }
2054
- let receivedSerialized = rawSnapshot && typeof received === "string" ? received : serialize(received, void 0, this._snapshotFormat);
2055
- if (!rawSnapshot) {
2056
- receivedSerialized = addExtraLineBreaks(receivedSerialized);
2057
- }
2058
- if (rawSnapshot) {
2059
- if (rawSnapshot.content && rawSnapshot.content.match(/\r\n/) && !receivedSerialized.match(/\r\n/)) {
2060
- rawSnapshot.content = normalizeNewlines(rawSnapshot.content);
2061
- }
2062
- }
2063
- const expected = isInline ? inlineSnapshot : rawSnapshot ? rawSnapshot.content : this._snapshotData[key];
2064
- const expectedTrimmed = rawSnapshot ? expected : prepareExpected(expected);
2065
- const pass = expectedTrimmed === (rawSnapshot ? receivedSerialized : prepareExpected(receivedSerialized));
2066
- const hasSnapshot = expected !== void 0;
2067
- const snapshotIsPersisted = isInline || this._fileExists || rawSnapshot && rawSnapshot.content != null;
2068
- if (pass && !isInline && !rawSnapshot) {
2069
- this._snapshotData[key] = receivedSerialized;
2070
- }
2071
- let stack;
2072
- if (isInline) {
2073
- const stacks = parseErrorStacktrace(
2074
- error || new Error("snapshot"),
2075
- { ignoreStackEntries: [] }
2076
- );
2077
- const _stack = this._inferInlineSnapshotStack(stacks);
2078
- if (!_stack) {
2079
- throw new Error(
2080
- `@vitest/snapshot: Couldn't infer stack frame for inline snapshot.
2081
- ${JSON.stringify(
2082
- stacks
2083
- )}`
2084
- );
2085
- }
2086
- stack = ((_b = (_a = this.environment).processStackTrace) == null ? void 0 : _b.call(_a, _stack)) || _stack;
2087
- stack.column--;
2088
- const snapshotsWithSameStack = this._inlineSnapshotStacks.filter((s) => isSameStackPosition(s, stack));
2089
- if (snapshotsWithSameStack.length > 0) {
2090
- this._inlineSnapshots = this._inlineSnapshots.filter((s) => !isSameStackPosition(s, stack));
2091
- const differentSnapshot = snapshotsWithSameStack.find((s) => s.snapshot !== receivedSerialized);
2092
- if (differentSnapshot) {
2093
- throw Object.assign(
2094
- new Error(
2095
- "toMatchInlineSnapshot with different snapshots cannot be called at the same location"
2096
- ),
2097
- {
2098
- actual: receivedSerialized,
2099
- expected: differentSnapshot.snapshot
2100
- }
2101
- );
2102
- }
2103
- }
2104
- this._inlineSnapshotStacks.push({ ...stack, testId, snapshot: receivedSerialized });
2105
- }
2106
- if (hasSnapshot && this._updateSnapshot === "all" || (!hasSnapshot || !snapshotIsPersisted) && (this._updateSnapshot === "new" || this._updateSnapshot === "all")) {
2107
- if (this._updateSnapshot === "all") {
2108
- if (!pass) {
2109
- if (hasSnapshot) {
2110
- this.updated.increment(testId);
2111
- } else {
2112
- this.added.increment(testId);
2113
- }
2114
- this._addSnapshot(key, receivedSerialized, {
2115
- stack,
2116
- testId,
2117
- rawSnapshot
2118
- });
2119
- } else {
2120
- this.matched.increment(testId);
2121
- }
2122
- } else {
2123
- this._addSnapshot(key, receivedSerialized, {
2124
- stack,
2125
- testId,
2126
- rawSnapshot
2127
- });
2128
- this.added.increment(testId);
2129
- }
2130
- return {
2131
- actual: "",
2132
- count,
2133
- expected: "",
2134
- key,
2135
- pass: true
2136
- };
2137
- } else {
2138
- if (!pass) {
2139
- this.unmatched.increment(testId);
2140
- return {
2141
- actual: rawSnapshot ? receivedSerialized : removeExtraLineBreaks(receivedSerialized),
2142
- count,
2143
- expected: expectedTrimmed !== void 0 ? rawSnapshot ? expectedTrimmed : removeExtraLineBreaks(expectedTrimmed) : void 0,
2144
- key,
2145
- pass: false
2146
- };
2147
- } else {
2148
- this.matched.increment(testId);
2149
- return {
2150
- actual: "",
2151
- count,
2152
- expected: "",
2153
- key,
2154
- pass: true
2155
- };
2156
- }
2157
- }
2158
- }
2159
- async pack() {
2160
- const snapshot = {
2161
- filepath: this.testFilePath,
2162
- added: 0,
2163
- fileDeleted: false,
2164
- matched: 0,
2165
- unchecked: 0,
2166
- uncheckedKeys: [],
2167
- unmatched: 0,
2168
- updated: 0
2169
- };
2170
- const uncheckedCount = this.getUncheckedCount();
2171
- const uncheckedKeys = this.getUncheckedKeys();
2172
- if (uncheckedCount) {
2173
- this.removeUncheckedKeys();
2174
- }
2175
- const status = await this.save();
2176
- snapshot.fileDeleted = status.deleted;
2177
- snapshot.added = this.added.total();
2178
- snapshot.matched = this.matched.total();
2179
- snapshot.unmatched = this.unmatched.total();
2180
- snapshot.updated = this.updated.total();
2181
- snapshot.unchecked = !status.deleted ? uncheckedCount : 0;
2182
- snapshot.uncheckedKeys = Array.from(uncheckedKeys);
2183
- return snapshot;
2184
- }
1828
+ _counters = new CounterMap();
1829
+ _dirty;
1830
+ _updateSnapshot;
1831
+ _snapshotData;
1832
+ _initialData;
1833
+ _inlineSnapshots;
1834
+ _inlineSnapshotStacks;
1835
+ _testIdToKeys = new DefaultMap(() => []);
1836
+ _rawSnapshots;
1837
+ _uncheckedKeys;
1838
+ _snapshotFormat;
1839
+ _environment;
1840
+ _fileExists;
1841
+ expand;
1842
+ _added = new CounterMap();
1843
+ _matched = new CounterMap();
1844
+ _unmatched = new CounterMap();
1845
+ _updated = new CounterMap();
1846
+ get added() {
1847
+ return this._added;
1848
+ }
1849
+ set added(value) {
1850
+ this._added._total = value;
1851
+ }
1852
+ get matched() {
1853
+ return this._matched;
1854
+ }
1855
+ set matched(value) {
1856
+ this._matched._total = value;
1857
+ }
1858
+ get unmatched() {
1859
+ return this._unmatched;
1860
+ }
1861
+ set unmatched(value) {
1862
+ this._unmatched._total = value;
1863
+ }
1864
+ get updated() {
1865
+ return this._updated;
1866
+ }
1867
+ set updated(value) {
1868
+ this._updated._total = value;
1869
+ }
1870
+ constructor(testFilePath, snapshotPath, snapshotContent, options) {
1871
+ this.testFilePath = testFilePath;
1872
+ this.snapshotPath = snapshotPath;
1873
+ const { data, dirty } = getSnapshotData(snapshotContent, options);
1874
+ this._fileExists = snapshotContent != null;
1875
+ this._initialData = { ...data };
1876
+ this._snapshotData = { ...data };
1877
+ this._dirty = dirty;
1878
+ this._inlineSnapshots = [];
1879
+ this._inlineSnapshotStacks = [];
1880
+ this._rawSnapshots = [];
1881
+ this._uncheckedKeys = new Set(Object.keys(this._snapshotData));
1882
+ this.expand = options.expand || false;
1883
+ this._updateSnapshot = options.updateSnapshot;
1884
+ this._snapshotFormat = {
1885
+ printBasicPrototype: false,
1886
+ escapeString: false,
1887
+ ...options.snapshotFormat
1888
+ };
1889
+ this._environment = options.snapshotEnvironment;
1890
+ }
1891
+ static async create(testFilePath, options) {
1892
+ const snapshotPath = await options.snapshotEnvironment.resolvePath(testFilePath);
1893
+ const content = await options.snapshotEnvironment.readSnapshotFile(snapshotPath);
1894
+ return new SnapshotState(testFilePath, snapshotPath, content, options);
1895
+ }
1896
+ get environment() {
1897
+ return this._environment;
1898
+ }
1899
+ markSnapshotsAsCheckedForTest(testName) {
1900
+ this._uncheckedKeys.forEach((uncheckedKey) => {
1901
+ if (/ \d+$| > /.test(uncheckedKey.slice(testName.length))) {
1902
+ this._uncheckedKeys.delete(uncheckedKey);
1903
+ }
1904
+ });
1905
+ }
1906
+ clearTest(testId) {
1907
+ this._inlineSnapshots = this._inlineSnapshots.filter((s) => s.testId !== testId);
1908
+ this._inlineSnapshotStacks = this._inlineSnapshotStacks.filter((s) => s.testId !== testId);
1909
+ for (const key of this._testIdToKeys.get(testId)) {
1910
+ const name = keyToTestName(key);
1911
+ const count = this._counters.get(name);
1912
+ if (count > 0) {
1913
+ if (key in this._snapshotData || key in this._initialData) {
1914
+ this._snapshotData[key] = this._initialData[key];
1915
+ }
1916
+ this._counters.set(name, count - 1);
1917
+ }
1918
+ }
1919
+ this._testIdToKeys.delete(testId);
1920
+ this.added.delete(testId);
1921
+ this.updated.delete(testId);
1922
+ this.matched.delete(testId);
1923
+ this.unmatched.delete(testId);
1924
+ }
1925
+ _inferInlineSnapshotStack(stacks) {
1926
+ const promiseIndex = stacks.findIndex((i) => i.method.match(/__VITEST_(RESOLVES|REJECTS)__/));
1927
+ if (promiseIndex !== -1) {
1928
+ return stacks[promiseIndex + 3];
1929
+ }
1930
+ const stackIndex = stacks.findIndex((i) => i.method.includes("__INLINE_SNAPSHOT__"));
1931
+ return stackIndex !== -1 ? stacks[stackIndex + 2] : null;
1932
+ }
1933
+ _addSnapshot(key, receivedSerialized, options) {
1934
+ this._dirty = true;
1935
+ if (options.stack) {
1936
+ this._inlineSnapshots.push({
1937
+ snapshot: receivedSerialized,
1938
+ testId: options.testId,
1939
+ ...options.stack
1940
+ });
1941
+ } else if (options.rawSnapshot) {
1942
+ this._rawSnapshots.push({
1943
+ ...options.rawSnapshot,
1944
+ snapshot: receivedSerialized
1945
+ });
1946
+ } else {
1947
+ this._snapshotData[key] = receivedSerialized;
1948
+ }
1949
+ }
1950
+ async save() {
1951
+ const hasExternalSnapshots = Object.keys(this._snapshotData).length;
1952
+ const hasInlineSnapshots = this._inlineSnapshots.length;
1953
+ const hasRawSnapshots = this._rawSnapshots.length;
1954
+ const isEmpty = !hasExternalSnapshots && !hasInlineSnapshots && !hasRawSnapshots;
1955
+ const status = {
1956
+ deleted: false,
1957
+ saved: false
1958
+ };
1959
+ if ((this._dirty || this._uncheckedKeys.size) && !isEmpty) {
1960
+ if (hasExternalSnapshots) {
1961
+ await saveSnapshotFile(this._environment, this._snapshotData, this.snapshotPath);
1962
+ this._fileExists = true;
1963
+ }
1964
+ if (hasInlineSnapshots) {
1965
+ await saveInlineSnapshots(this._environment, this._inlineSnapshots);
1966
+ }
1967
+ if (hasRawSnapshots) {
1968
+ await saveRawSnapshots(this._environment, this._rawSnapshots);
1969
+ }
1970
+ status.saved = true;
1971
+ } else if (!hasExternalSnapshots && this._fileExists) {
1972
+ if (this._updateSnapshot === "all") {
1973
+ await this._environment.removeSnapshotFile(this.snapshotPath);
1974
+ this._fileExists = false;
1975
+ }
1976
+ status.deleted = true;
1977
+ }
1978
+ return status;
1979
+ }
1980
+ getUncheckedCount() {
1981
+ return this._uncheckedKeys.size || 0;
1982
+ }
1983
+ getUncheckedKeys() {
1984
+ return Array.from(this._uncheckedKeys);
1985
+ }
1986
+ removeUncheckedKeys() {
1987
+ if (this._updateSnapshot === "all" && this._uncheckedKeys.size) {
1988
+ this._dirty = true;
1989
+ this._uncheckedKeys.forEach((key) => delete this._snapshotData[key]);
1990
+ this._uncheckedKeys.clear();
1991
+ }
1992
+ }
1993
+ match({ testId, testName, received, key, inlineSnapshot, isInline, error, rawSnapshot }) {
1994
+ this._counters.increment(testName);
1995
+ const count = this._counters.get(testName);
1996
+ if (!key) {
1997
+ key = testNameToKey(testName, count);
1998
+ }
1999
+ this._testIdToKeys.get(testId).push(key);
2000
+ if (!(isInline && this._snapshotData[key] !== undefined)) {
2001
+ this._uncheckedKeys.delete(key);
2002
+ }
2003
+ let receivedSerialized = rawSnapshot && typeof received === "string" ? received : serialize(received, undefined, this._snapshotFormat);
2004
+ if (!rawSnapshot) {
2005
+ receivedSerialized = addExtraLineBreaks(receivedSerialized);
2006
+ }
2007
+ if (rawSnapshot) {
2008
+ if (rawSnapshot.content && rawSnapshot.content.match(/\r\n/) && !receivedSerialized.match(/\r\n/)) {
2009
+ rawSnapshot.content = normalizeNewlines(rawSnapshot.content);
2010
+ }
2011
+ }
2012
+ const expected = isInline ? inlineSnapshot : rawSnapshot ? rawSnapshot.content : this._snapshotData[key];
2013
+ const expectedTrimmed = rawSnapshot ? expected : prepareExpected(expected);
2014
+ const pass = expectedTrimmed === (rawSnapshot ? receivedSerialized : prepareExpected(receivedSerialized));
2015
+ const hasSnapshot = expected !== undefined;
2016
+ const snapshotIsPersisted = isInline || this._fileExists || rawSnapshot && rawSnapshot.content != null;
2017
+ if (pass && !isInline && !rawSnapshot) {
2018
+ this._snapshotData[key] = receivedSerialized;
2019
+ }
2020
+ let stack;
2021
+ if (isInline) {
2022
+ var _this$environment$pro, _this$environment;
2023
+ const stacks = parseErrorStacktrace(error || new Error("snapshot"), { ignoreStackEntries: [] });
2024
+ const _stack = this._inferInlineSnapshotStack(stacks);
2025
+ if (!_stack) {
2026
+ throw new Error(`@vitest/snapshot: Couldn't infer stack frame for inline snapshot.\n${JSON.stringify(stacks)}`);
2027
+ }
2028
+ stack = ((_this$environment$pro = (_this$environment = this.environment).processStackTrace) === null || _this$environment$pro === void 0 ? void 0 : _this$environment$pro.call(_this$environment, _stack)) || _stack;
2029
+ stack.column--;
2030
+ const snapshotsWithSameStack = this._inlineSnapshotStacks.filter((s) => isSameStackPosition(s, stack));
2031
+ if (snapshotsWithSameStack.length > 0) {
2032
+ this._inlineSnapshots = this._inlineSnapshots.filter((s) => !isSameStackPosition(s, stack));
2033
+ const differentSnapshot = snapshotsWithSameStack.find((s) => s.snapshot !== receivedSerialized);
2034
+ if (differentSnapshot) {
2035
+ throw Object.assign(new Error("toMatchInlineSnapshot with different snapshots cannot be called at the same location"), {
2036
+ actual: receivedSerialized,
2037
+ expected: differentSnapshot.snapshot
2038
+ });
2039
+ }
2040
+ }
2041
+ this._inlineSnapshotStacks.push({
2042
+ ...stack,
2043
+ testId,
2044
+ snapshot: receivedSerialized
2045
+ });
2046
+ }
2047
+ if (hasSnapshot && this._updateSnapshot === "all" || (!hasSnapshot || !snapshotIsPersisted) && (this._updateSnapshot === "new" || this._updateSnapshot === "all")) {
2048
+ if (this._updateSnapshot === "all") {
2049
+ if (!pass) {
2050
+ if (hasSnapshot) {
2051
+ this.updated.increment(testId);
2052
+ } else {
2053
+ this.added.increment(testId);
2054
+ }
2055
+ this._addSnapshot(key, receivedSerialized, {
2056
+ stack,
2057
+ testId,
2058
+ rawSnapshot
2059
+ });
2060
+ } else {
2061
+ this.matched.increment(testId);
2062
+ }
2063
+ } else {
2064
+ this._addSnapshot(key, receivedSerialized, {
2065
+ stack,
2066
+ testId,
2067
+ rawSnapshot
2068
+ });
2069
+ this.added.increment(testId);
2070
+ }
2071
+ return {
2072
+ actual: "",
2073
+ count,
2074
+ expected: "",
2075
+ key,
2076
+ pass: true
2077
+ };
2078
+ } else {
2079
+ if (!pass) {
2080
+ this.unmatched.increment(testId);
2081
+ return {
2082
+ actual: rawSnapshot ? receivedSerialized : removeExtraLineBreaks(receivedSerialized),
2083
+ count,
2084
+ expected: expectedTrimmed !== undefined ? rawSnapshot ? expectedTrimmed : removeExtraLineBreaks(expectedTrimmed) : undefined,
2085
+ key,
2086
+ pass: false
2087
+ };
2088
+ } else {
2089
+ this.matched.increment(testId);
2090
+ return {
2091
+ actual: "",
2092
+ count,
2093
+ expected: "",
2094
+ key,
2095
+ pass: true
2096
+ };
2097
+ }
2098
+ }
2099
+ }
2100
+ async pack() {
2101
+ const snapshot = {
2102
+ filepath: this.testFilePath,
2103
+ added: 0,
2104
+ fileDeleted: false,
2105
+ matched: 0,
2106
+ unchecked: 0,
2107
+ uncheckedKeys: [],
2108
+ unmatched: 0,
2109
+ updated: 0
2110
+ };
2111
+ const uncheckedCount = this.getUncheckedCount();
2112
+ const uncheckedKeys = this.getUncheckedKeys();
2113
+ if (uncheckedCount) {
2114
+ this.removeUncheckedKeys();
2115
+ }
2116
+ const status = await this.save();
2117
+ snapshot.fileDeleted = status.deleted;
2118
+ snapshot.added = this.added.total();
2119
+ snapshot.matched = this.matched.total();
2120
+ snapshot.unmatched = this.unmatched.total();
2121
+ snapshot.updated = this.updated.total();
2122
+ snapshot.unchecked = !status.deleted ? uncheckedCount : 0;
2123
+ snapshot.uncheckedKeys = Array.from(uncheckedKeys);
2124
+ return snapshot;
2125
+ }
2185
2126
  }
2186
2127
 
2187
2128
  function createMismatchError(message, expand, actual, expected) {
2188
- const error = new Error(message);
2189
- Object.defineProperty(error, "actual", {
2190
- value: actual,
2191
- enumerable: true,
2192
- configurable: true,
2193
- writable: true
2194
- });
2195
- Object.defineProperty(error, "expected", {
2196
- value: expected,
2197
- enumerable: true,
2198
- configurable: true,
2199
- writable: true
2200
- });
2201
- Object.defineProperty(error, "diffOptions", { value: { expand } });
2202
- return error;
2129
+ const error = new Error(message);
2130
+ Object.defineProperty(error, "actual", {
2131
+ value: actual,
2132
+ enumerable: true,
2133
+ configurable: true,
2134
+ writable: true
2135
+ });
2136
+ Object.defineProperty(error, "expected", {
2137
+ value: expected,
2138
+ enumerable: true,
2139
+ configurable: true,
2140
+ writable: true
2141
+ });
2142
+ Object.defineProperty(error, "diffOptions", { value: { expand } });
2143
+ return error;
2203
2144
  }
2204
2145
  class SnapshotClient {
2205
- constructor(options = {}) {
2206
- this.options = options;
2207
- }
2208
- snapshotStateMap = /* @__PURE__ */ new Map();
2209
- async setup(filepath, options) {
2210
- if (this.snapshotStateMap.has(filepath)) {
2211
- return;
2212
- }
2213
- this.snapshotStateMap.set(
2214
- filepath,
2215
- await SnapshotState.create(filepath, options)
2216
- );
2217
- }
2218
- async finish(filepath) {
2219
- const state = this.getSnapshotState(filepath);
2220
- const result = await state.pack();
2221
- this.snapshotStateMap.delete(filepath);
2222
- return result;
2223
- }
2224
- skipTest(filepath, testName) {
2225
- const state = this.getSnapshotState(filepath);
2226
- state.markSnapshotsAsCheckedForTest(testName);
2227
- }
2228
- clearTest(filepath, testId) {
2229
- const state = this.getSnapshotState(filepath);
2230
- state.clearTest(testId);
2231
- }
2232
- getSnapshotState(filepath) {
2233
- const state = this.snapshotStateMap.get(filepath);
2234
- if (!state) {
2235
- throw new Error(
2236
- `The snapshot state for '${filepath}' is not found. Did you call 'SnapshotClient.setup()'?`
2237
- );
2238
- }
2239
- return state;
2240
- }
2241
- assert(options) {
2242
- var _a, _b;
2243
- const {
2244
- filepath,
2245
- name,
2246
- testId = name,
2247
- message,
2248
- isInline = false,
2249
- properties,
2250
- inlineSnapshot,
2251
- error,
2252
- errorMessage,
2253
- rawSnapshot
2254
- } = options;
2255
- let { received } = options;
2256
- if (!filepath) {
2257
- throw new Error("Snapshot cannot be used outside of test");
2258
- }
2259
- const snapshotState = this.getSnapshotState(filepath);
2260
- if (typeof properties === "object") {
2261
- if (typeof received !== "object" || !received) {
2262
- throw new Error(
2263
- "Received value must be an object when the matcher has properties"
2264
- );
2265
- }
2266
- try {
2267
- const pass2 = ((_b = (_a = this.options).isEqual) == null ? void 0 : _b.call(_a, received, properties)) ?? false;
2268
- if (!pass2) {
2269
- throw createMismatchError(
2270
- "Snapshot properties mismatched",
2271
- snapshotState.expand,
2272
- received,
2273
- properties
2274
- );
2275
- } else {
2276
- received = deepMergeSnapshot(received, properties);
2277
- }
2278
- } catch (err) {
2279
- err.message = errorMessage || "Snapshot mismatched";
2280
- throw err;
2281
- }
2282
- }
2283
- const testName = [name, ...message ? [message] : []].join(" > ");
2284
- const { actual, expected, key, pass } = snapshotState.match({
2285
- testId,
2286
- testName,
2287
- received,
2288
- isInline,
2289
- error,
2290
- inlineSnapshot,
2291
- rawSnapshot
2292
- });
2293
- if (!pass) {
2294
- throw createMismatchError(
2295
- `Snapshot \`${key || "unknown"}\` mismatched`,
2296
- snapshotState.expand,
2297
- rawSnapshot ? actual : actual == null ? void 0 : actual.trim(),
2298
- rawSnapshot ? expected : expected == null ? void 0 : expected.trim()
2299
- );
2300
- }
2301
- }
2302
- async assertRaw(options) {
2303
- if (!options.rawSnapshot) {
2304
- throw new Error("Raw snapshot is required");
2305
- }
2306
- const { filepath, rawSnapshot } = options;
2307
- if (rawSnapshot.content == null) {
2308
- if (!filepath) {
2309
- throw new Error("Snapshot cannot be used outside of test");
2310
- }
2311
- const snapshotState = this.getSnapshotState(filepath);
2312
- options.filepath || (options.filepath = filepath);
2313
- rawSnapshot.file = await snapshotState.environment.resolveRawPath(
2314
- filepath,
2315
- rawSnapshot.file
2316
- );
2317
- rawSnapshot.content = await snapshotState.environment.readSnapshotFile(rawSnapshot.file) ?? void 0;
2318
- }
2319
- return this.assert(options);
2320
- }
2321
- clear() {
2322
- this.snapshotStateMap.clear();
2323
- }
2146
+ snapshotStateMap = new Map();
2147
+ constructor(options = {}) {
2148
+ this.options = options;
2149
+ }
2150
+ async setup(filepath, options) {
2151
+ if (this.snapshotStateMap.has(filepath)) {
2152
+ return;
2153
+ }
2154
+ this.snapshotStateMap.set(filepath, await SnapshotState.create(filepath, options));
2155
+ }
2156
+ async finish(filepath) {
2157
+ const state = this.getSnapshotState(filepath);
2158
+ const result = await state.pack();
2159
+ this.snapshotStateMap.delete(filepath);
2160
+ return result;
2161
+ }
2162
+ skipTest(filepath, testName) {
2163
+ const state = this.getSnapshotState(filepath);
2164
+ state.markSnapshotsAsCheckedForTest(testName);
2165
+ }
2166
+ clearTest(filepath, testId) {
2167
+ const state = this.getSnapshotState(filepath);
2168
+ state.clearTest(testId);
2169
+ }
2170
+ getSnapshotState(filepath) {
2171
+ const state = this.snapshotStateMap.get(filepath);
2172
+ if (!state) {
2173
+ throw new Error(`The snapshot state for '${filepath}' is not found. Did you call 'SnapshotClient.setup()'?`);
2174
+ }
2175
+ return state;
2176
+ }
2177
+ assert(options) {
2178
+ const { filepath, name, testId = name, message, isInline = false, properties, inlineSnapshot, error, errorMessage, rawSnapshot } = options;
2179
+ let { received } = options;
2180
+ if (!filepath) {
2181
+ throw new Error("Snapshot cannot be used outside of test");
2182
+ }
2183
+ const snapshotState = this.getSnapshotState(filepath);
2184
+ if (typeof properties === "object") {
2185
+ if (typeof received !== "object" || !received) {
2186
+ throw new Error("Received value must be an object when the matcher has properties");
2187
+ }
2188
+ try {
2189
+ var _this$options$isEqual, _this$options;
2190
+ const pass = ((_this$options$isEqual = (_this$options = this.options).isEqual) === null || _this$options$isEqual === void 0 ? void 0 : _this$options$isEqual.call(_this$options, received, properties)) ?? false;
2191
+ if (!pass) {
2192
+ throw createMismatchError("Snapshot properties mismatched", snapshotState.expand, received, properties);
2193
+ } else {
2194
+ received = deepMergeSnapshot(received, properties);
2195
+ }
2196
+ } catch (err) {
2197
+ err.message = errorMessage || "Snapshot mismatched";
2198
+ throw err;
2199
+ }
2200
+ }
2201
+ const testName = [name, ...message ? [message] : []].join(" > ");
2202
+ const { actual, expected, key, pass } = snapshotState.match({
2203
+ testId,
2204
+ testName,
2205
+ received,
2206
+ isInline,
2207
+ error,
2208
+ inlineSnapshot,
2209
+ rawSnapshot
2210
+ });
2211
+ if (!pass) {
2212
+ throw createMismatchError(`Snapshot \`${key || "unknown"}\` mismatched`, snapshotState.expand, rawSnapshot ? actual : actual === null || actual === void 0 ? void 0 : actual.trim(), rawSnapshot ? expected : expected === null || expected === void 0 ? void 0 : expected.trim());
2213
+ }
2214
+ }
2215
+ async assertRaw(options) {
2216
+ if (!options.rawSnapshot) {
2217
+ throw new Error("Raw snapshot is required");
2218
+ }
2219
+ const { filepath, rawSnapshot } = options;
2220
+ if (rawSnapshot.content == null) {
2221
+ if (!filepath) {
2222
+ throw new Error("Snapshot cannot be used outside of test");
2223
+ }
2224
+ const snapshotState = this.getSnapshotState(filepath);
2225
+ options.filepath || (options.filepath = filepath);
2226
+ rawSnapshot.file = await snapshotState.environment.resolveRawPath(filepath, rawSnapshot.file);
2227
+ rawSnapshot.content = await snapshotState.environment.readSnapshotFile(rawSnapshot.file) ?? undefined;
2228
+ }
2229
+ return this.assert(options);
2230
+ }
2231
+ clear() {
2232
+ this.snapshotStateMap.clear();
2233
+ }
2324
2234
  }
2325
2235
 
2326
2236
  export { SnapshotClient, SnapshotState, addSerializer, getSerializers, stripSnapshotIndentation };