@vitest/utils 2.0.4 → 2.0.5

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/diff.d.ts CHANGED
@@ -88,6 +88,13 @@ declare function diffStringsRaw(a: string, b: string, cleanup: boolean, options?
88
88
  * @param options Diff options
89
89
  * @returns {string | null} a string diff
90
90
  */
91
- declare function diff(a: any, b: any, options?: DiffOptions): string | null;
91
+ declare function diff(a: any, b: any, options?: DiffOptions): string | undefined;
92
+ declare function printDiffOrStringify(expected: unknown, received: unknown, options?: DiffOptions): string | undefined;
93
+ declare function replaceAsymmetricMatcher(actual: any, expected: any, actualReplaced?: WeakSet<WeakKey>, expectedReplaced?: WeakSet<WeakKey>): {
94
+ replacedActual: any;
95
+ replacedExpected: any;
96
+ };
97
+ type PrintLabel = (string: string) => string;
98
+ declare function getLabelPrinter(...strings: Array<string>): PrintLabel;
92
99
 
93
- export { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff, DiffOptions, diff, diffLinesRaw, diffLinesUnified, diffLinesUnified2, diffStringsRaw, diffStringsUnified };
100
+ export { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff, DiffOptions, diff, diffLinesRaw, diffLinesUnified, diffLinesUnified2, diffStringsRaw, diffStringsUnified, getLabelPrinter, printDiffOrStringify, replaceAsymmetricMatcher };
package/dist/diff.js CHANGED
@@ -1,5 +1,8 @@
1
1
  import { format, plugins } from '@vitest/pretty-format';
2
2
  import c from 'tinyrainbow';
3
+ import { s as stringify } from './chunk-display.js';
4
+ import { deepClone, getOwnProperties, getType as getType$1 } from './helpers.js';
5
+ import 'loupe';
3
6
 
4
7
  function getType(value) {
5
8
  if (value === void 0) {
@@ -1851,10 +1854,10 @@ function diff(a, b, options) {
1851
1854
  let omitDifference = false;
1852
1855
  if (aType === "object" && typeof a.asymmetricMatch === "function") {
1853
1856
  if (a.$$typeof !== Symbol.for("jest.asymmetricMatcher")) {
1854
- return null;
1857
+ return void 0;
1855
1858
  }
1856
1859
  if (typeof a.getExpectedType !== "function") {
1857
- return null;
1860
+ return void 0;
1858
1861
  }
1859
1862
  expectedType = a.getExpectedType();
1860
1863
  omitDifference = expectedType === "string";
@@ -1873,7 +1876,7 @@ ${bDisplay}`;
1873
1876
  ${bDiff}`;
1874
1877
  }
1875
1878
  if (omitDifference) {
1876
- return null;
1879
+ return void 0;
1877
1880
  }
1878
1881
  switch (aType) {
1879
1882
  case "string":
@@ -1949,5 +1952,98 @@ function getObjectsDifference(a, b, formatOptions, options) {
1949
1952
  );
1950
1953
  }
1951
1954
  }
1955
+ const MAX_DIFF_STRING_LENGTH = 2e4;
1956
+ function isAsymmetricMatcher(data) {
1957
+ const type = getType$1(data);
1958
+ return type === "Object" && typeof data.asymmetricMatch === "function";
1959
+ }
1960
+ function isReplaceable(obj1, obj2) {
1961
+ const obj1Type = getType$1(obj1);
1962
+ const obj2Type = getType$1(obj2);
1963
+ return obj1Type === obj2Type && (obj1Type === "Object" || obj1Type === "Array");
1964
+ }
1965
+ function printDiffOrStringify(expected, received, options) {
1966
+ const { aAnnotation, bAnnotation } = normalizeDiffOptions(options);
1967
+ if (typeof expected === "string" && typeof received === "string" && expected.length > 0 && received.length > 0 && expected.length <= MAX_DIFF_STRING_LENGTH && received.length <= MAX_DIFF_STRING_LENGTH && expected !== received) {
1968
+ if (expected.includes("\n") || received.includes("\n")) {
1969
+ return diffStringsUnified(received, expected, options);
1970
+ }
1971
+ const [diffs] = diffStringsRaw(received, expected, true);
1972
+ const hasCommonDiff = diffs.some((diff2) => diff2[0] === DIFF_EQUAL);
1973
+ const printLabel = getLabelPrinter(aAnnotation, bAnnotation);
1974
+ const expectedLine = printLabel(aAnnotation) + printExpected(
1975
+ getCommonAndChangedSubstrings(diffs, DIFF_DELETE, hasCommonDiff)
1976
+ );
1977
+ const receivedLine = printLabel(bAnnotation) + printReceived(
1978
+ getCommonAndChangedSubstrings(diffs, DIFF_INSERT, hasCommonDiff)
1979
+ );
1980
+ return `${expectedLine}
1981
+ ${receivedLine}`;
1982
+ }
1983
+ const clonedExpected = deepClone(expected, { forceWritable: true });
1984
+ const clonedReceived = deepClone(received, { forceWritable: true });
1985
+ const { replacedExpected, replacedActual } = replaceAsymmetricMatcher(clonedExpected, clonedReceived);
1986
+ const difference = diff(replacedExpected, replacedActual, options);
1987
+ return difference;
1988
+ }
1989
+ function replaceAsymmetricMatcher(actual, expected, actualReplaced = /* @__PURE__ */ new WeakSet(), expectedReplaced = /* @__PURE__ */ new WeakSet()) {
1990
+ if (!isReplaceable(actual, expected)) {
1991
+ return { replacedActual: actual, replacedExpected: expected };
1992
+ }
1993
+ if (actualReplaced.has(actual) || expectedReplaced.has(expected)) {
1994
+ return { replacedActual: actual, replacedExpected: expected };
1995
+ }
1996
+ actualReplaced.add(actual);
1997
+ expectedReplaced.add(expected);
1998
+ getOwnProperties(expected).forEach((key) => {
1999
+ const expectedValue = expected[key];
2000
+ const actualValue = actual[key];
2001
+ if (isAsymmetricMatcher(expectedValue)) {
2002
+ if (expectedValue.asymmetricMatch(actualValue)) {
2003
+ actual[key] = expectedValue;
2004
+ }
2005
+ } else if (isAsymmetricMatcher(actualValue)) {
2006
+ if (actualValue.asymmetricMatch(expectedValue)) {
2007
+ expected[key] = actualValue;
2008
+ }
2009
+ } else if (isReplaceable(actualValue, expectedValue)) {
2010
+ const replaced = replaceAsymmetricMatcher(
2011
+ actualValue,
2012
+ expectedValue,
2013
+ actualReplaced,
2014
+ expectedReplaced
2015
+ );
2016
+ actual[key] = replaced.replacedActual;
2017
+ expected[key] = replaced.replacedExpected;
2018
+ }
2019
+ });
2020
+ return {
2021
+ replacedActual: actual,
2022
+ replacedExpected: expected
2023
+ };
2024
+ }
2025
+ function getLabelPrinter(...strings) {
2026
+ const maxLength = strings.reduce(
2027
+ (max, string) => string.length > max ? string.length : max,
2028
+ 0
2029
+ );
2030
+ return (string) => `${string}: ${" ".repeat(maxLength - string.length)}`;
2031
+ }
2032
+ const SPACE_SYMBOL = "\xB7";
2033
+ function replaceTrailingSpaces(text) {
2034
+ return text.replace(/\s+$/gm, (spaces) => SPACE_SYMBOL.repeat(spaces.length));
2035
+ }
2036
+ function printReceived(object) {
2037
+ return c.red(replaceTrailingSpaces(stringify(object)));
2038
+ }
2039
+ function printExpected(value) {
2040
+ return c.green(replaceTrailingSpaces(stringify(value)));
2041
+ }
2042
+ function getCommonAndChangedSubstrings(diffs, op, hasCommonDiff) {
2043
+ return diffs.reduce(
2044
+ (reduced, diff2) => reduced + (diff2[0] === DIFF_EQUAL ? diff2[1] : diff2[0] === op ? hasCommonDiff ? c.inverse(diff2[1]) : diff2[1] : ""),
2045
+ ""
2046
+ );
2047
+ }
1952
2048
 
1953
- export { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff, diff, diffLinesRaw, diffLinesUnified, diffLinesUnified2, diffStringsRaw, diffStringsUnified };
2049
+ export { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff, diff, diffLinesRaw, diffLinesUnified, diffLinesUnified2, diffStringsRaw, diffStringsUnified, getLabelPrinter, printDiffOrStringify, replaceAsymmetricMatcher };
package/dist/error.d.ts CHANGED
@@ -1,11 +1,8 @@
1
1
  import { D as DiffOptions } from './types-Bxe-2Udy.js';
2
2
  import '@vitest/pretty-format';
3
3
 
4
- declare function serializeError(val: any, seen?: WeakMap<WeakKey, any>): any;
5
- declare function processError(err: any, diffOptions?: DiffOptions, seen?: WeakSet<WeakKey>): any;
6
- declare function replaceAsymmetricMatcher(actual: any, expected: any, actualReplaced?: WeakSet<WeakKey>, expectedReplaced?: WeakSet<WeakKey>): {
7
- replacedActual: any;
8
- replacedExpected: any;
9
- };
4
+ declare function serializeValue(val: any, seen?: WeakMap<WeakKey, any>): any;
10
5
 
11
- export { processError, replaceAsymmetricMatcher, serializeError };
6
+ declare function processError(_err: any, diffOptions?: DiffOptions, seen?: WeakSet<WeakKey>): any;
7
+
8
+ export { processError, serializeValue as serializeError, serializeValue };
package/dist/error.js CHANGED
@@ -1,8 +1,8 @@
1
- import { diff } from './diff.js';
1
+ import { printDiffOrStringify } from './diff.js';
2
2
  import { f as format, s as stringify } from './chunk-display.js';
3
- import { deepClone, getOwnProperties, getType } from './helpers.js';
4
3
  import '@vitest/pretty-format';
5
4
  import 'tinyrainbow';
5
+ import './helpers.js';
6
6
  import 'loupe';
7
7
 
8
8
  const IS_RECORD_SYMBOL = "@@__IMMUTABLE_RECORD__@@";
@@ -20,7 +20,7 @@ function getUnserializableMessage(err) {
20
20
  }
21
21
  return "<unserializable>";
22
22
  }
23
- function serializeError(val, seen = /* @__PURE__ */ new WeakMap()) {
23
+ function serializeValue(val, seen = /* @__PURE__ */ new WeakMap()) {
24
24
  if (!val || typeof val === "string") {
25
25
  return val;
26
26
  }
@@ -34,7 +34,7 @@ function serializeError(val, seen = /* @__PURE__ */ new WeakMap()) {
34
34
  return val;
35
35
  }
36
36
  if (isImmutable(val)) {
37
- return serializeError(val.toJSON(), seen);
37
+ return serializeValue(val.toJSON(), seen);
38
38
  }
39
39
  if (val instanceof Promise || val.constructor && val.constructor.prototype === "AsyncFunction") {
40
40
  return "Promise";
@@ -46,7 +46,7 @@ function serializeError(val, seen = /* @__PURE__ */ new WeakMap()) {
46
46
  return `${val.toString()} ${format(val.sample)}`;
47
47
  }
48
48
  if (typeof val.toJSON === "function") {
49
- return serializeError(val.toJSON(), seen);
49
+ return serializeValue(val.toJSON(), seen);
50
50
  }
51
51
  if (seen.has(val)) {
52
52
  return seen.get(val);
@@ -56,7 +56,7 @@ function serializeError(val, seen = /* @__PURE__ */ new WeakMap()) {
56
56
  seen.set(val, clone);
57
57
  val.forEach((e, i) => {
58
58
  try {
59
- clone[i] = serializeError(e, seen);
59
+ clone[i] = serializeValue(e, seen);
60
60
  } catch (err) {
61
61
  clone[i] = getUnserializableMessage(err);
62
62
  }
@@ -72,7 +72,7 @@ function serializeError(val, seen = /* @__PURE__ */ new WeakMap()) {
72
72
  return;
73
73
  }
74
74
  try {
75
- clone[key] = serializeError(val[key], seen);
75
+ clone[key] = serializeValue(val[key], seen);
76
76
  } catch (err) {
77
77
  delete clone[key];
78
78
  clone[key] = getUnserializableMessage(err);
@@ -86,10 +86,11 @@ function serializeError(val, seen = /* @__PURE__ */ new WeakMap()) {
86
86
  function normalizeErrorMessage(message) {
87
87
  return message.replace(/__(vite_ssr_import|vi_import)_\d+__\./g, "");
88
88
  }
89
- function processError(err, diffOptions, seen = /* @__PURE__ */ new WeakSet()) {
90
- if (!err || typeof err !== "object") {
91
- return { message: err };
89
+ function processError(_err, diffOptions, seen = /* @__PURE__ */ new WeakSet()) {
90
+ if (!_err || typeof _err !== "object") {
91
+ return { message: String(_err) };
92
92
  }
93
+ const err = _err;
93
94
  if (err.stack) {
94
95
  err.stackStr = String(err.stack);
95
96
  }
@@ -97,13 +98,7 @@ function processError(err, diffOptions, seen = /* @__PURE__ */ new WeakSet()) {
97
98
  err.nameStr = String(err.name);
98
99
  }
99
100
  if (err.showDiff || err.showDiff === void 0 && err.expected !== void 0 && err.actual !== void 0) {
100
- const clonedActual = deepClone(err.actual, { forceWritable: true });
101
- const clonedExpected = deepClone(err.expected, { forceWritable: true });
102
- const { replacedActual, replacedExpected } = replaceAsymmetricMatcher(
103
- clonedActual,
104
- clonedExpected
105
- );
106
- err.diff = diff(replacedExpected, replacedActual, {
101
+ err.diff = printDiffOrStringify(err.actual, err.expected, {
107
102
  ...diffOptions,
108
103
  ...err.diffOptions
109
104
  });
@@ -128,9 +123,9 @@ function processError(err, diffOptions, seen = /* @__PURE__ */ new WeakSet()) {
128
123
  } catch {
129
124
  }
130
125
  try {
131
- return serializeError(err);
126
+ return serializeValue(err);
132
127
  } catch (e) {
133
- return serializeError(
128
+ return serializeValue(
134
129
  new Error(
135
130
  `Failed to fully serialize error: ${e == null ? void 0 : e.message}
136
131
  Inner error message: ${err == null ? void 0 : err.message}`
@@ -138,50 +133,5 @@ Inner error message: ${err == null ? void 0 : err.message}`
138
133
  );
139
134
  }
140
135
  }
141
- function isAsymmetricMatcher(data) {
142
- const type = getType(data);
143
- return type === "Object" && typeof data.asymmetricMatch === "function";
144
- }
145
- function isReplaceable(obj1, obj2) {
146
- const obj1Type = getType(obj1);
147
- const obj2Type = getType(obj2);
148
- return obj1Type === obj2Type && (obj1Type === "Object" || obj1Type === "Array");
149
- }
150
- function replaceAsymmetricMatcher(actual, expected, actualReplaced = /* @__PURE__ */ new WeakSet(), expectedReplaced = /* @__PURE__ */ new WeakSet()) {
151
- if (!isReplaceable(actual, expected)) {
152
- return { replacedActual: actual, replacedExpected: expected };
153
- }
154
- if (actualReplaced.has(actual) || expectedReplaced.has(expected)) {
155
- return { replacedActual: actual, replacedExpected: expected };
156
- }
157
- actualReplaced.add(actual);
158
- expectedReplaced.add(expected);
159
- getOwnProperties(expected).forEach((key) => {
160
- const expectedValue = expected[key];
161
- const actualValue = actual[key];
162
- if (isAsymmetricMatcher(expectedValue)) {
163
- if (expectedValue.asymmetricMatch(actualValue)) {
164
- actual[key] = expectedValue;
165
- }
166
- } else if (isAsymmetricMatcher(actualValue)) {
167
- if (actualValue.asymmetricMatch(expectedValue)) {
168
- expected[key] = actualValue;
169
- }
170
- } else if (isReplaceable(actualValue, expectedValue)) {
171
- const replaced = replaceAsymmetricMatcher(
172
- actualValue,
173
- expectedValue,
174
- actualReplaced,
175
- expectedReplaced
176
- );
177
- actual[key] = replaced.replacedActual;
178
- expected[key] = replaced.replacedExpected;
179
- }
180
- });
181
- return {
182
- replacedActual: actual,
183
- replacedExpected: expected
184
- };
185
- }
186
136
 
187
- export { processError, replaceAsymmetricMatcher, serializeError };
137
+ export { processError, serializeValue as serializeError, serializeValue };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { DeferPromise, assertTypes, clone, createDefer, createSimpleStackTrace, deepClone, getCallLastIndex, getOwnProperties, getType, isNegativeNaN, isObject, isPrimitive, noop, notNullish, objectAttr, parseRegexp, slash, toArray } from './helpers.js';
2
2
  import { PrettyFormatOptions } from '@vitest/pretty-format';
3
3
  import { Colors } from 'tinyrainbow';
4
- export { ArgumentsType, Arrayable, Awaitable, Constructable, DeepMerge, ErrorWithDiff, MergeInsertions, MutableArray, Nullable, ParsedStack } from './types.js';
4
+ export { ArgumentsType, Arrayable, Awaitable, Constructable, DeepMerge, ErrorWithDiff, MergeInsertions, MutableArray, Nullable, ParsedStack, SerializedError, TestError } from './types.js';
5
5
 
6
6
  interface SafeTimers {
7
7
  nextTick: (cb: () => void) => void;
@@ -1,4 +1,4 @@
1
- import { ParsedStack, ErrorWithDiff } from './types.js';
1
+ import { ErrorWithDiff, ParsedStack } from './types.js';
2
2
 
3
3
  type GeneratedColumn = number;
4
4
  type SourcesIndex = number;
@@ -105,7 +105,7 @@ interface StackTraceParserOptions {
105
105
  ignoreStackEntries?: (RegExp | string)[];
106
106
  getSourceMap?: (file: string) => unknown;
107
107
  getFileName?: (id: string) => string;
108
- frameFilter?: (error: Error, frame: ParsedStack) => boolean | void;
108
+ frameFilter?: (error: ErrorWithDiff, frame: ParsedStack) => boolean | void;
109
109
  }
110
110
  declare function parseSingleFFOrSafariStack(raw: string): ParsedStack | null;
111
111
  declare function parseSingleStack(raw: string): ParsedStack | null;
package/dist/types.d.ts CHANGED
@@ -20,8 +20,27 @@ interface ParsedStack {
20
20
  line: number;
21
21
  column: number;
22
22
  }
23
- interface ErrorWithDiff extends Error {
24
- name: string;
23
+ interface SerializedError {
24
+ message: string;
25
+ stack?: string;
26
+ name?: string;
27
+ stacks?: ParsedStack[];
28
+ cause?: SerializedError;
29
+ [key: string]: unknown;
30
+ }
31
+ interface TestError extends SerializedError {
32
+ cause?: TestError;
33
+ diff?: string;
34
+ actual?: string;
35
+ expected?: string;
36
+ }
37
+ /**
38
+ * @deprecated Use `TestError` instead
39
+ */
40
+ interface ErrorWithDiff {
41
+ message: string;
42
+ name?: string;
43
+ cause?: unknown;
25
44
  nameStr?: string;
26
45
  stack?: string;
27
46
  stackStr?: string;
@@ -36,4 +55,4 @@ interface ErrorWithDiff extends Error {
36
55
  codeFrame?: string;
37
56
  }
38
57
 
39
- export type { ArgumentsType, Arrayable, Awaitable, Constructable, DeepMerge, ErrorWithDiff, MergeInsertions, MutableArray, Nullable, ParsedStack };
58
+ export type { ArgumentsType, Arrayable, Awaitable, Constructable, DeepMerge, ErrorWithDiff, MergeInsertions, MutableArray, Nullable, ParsedStack, SerializedError, TestError };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/utils",
3
3
  "type": "module",
4
- "version": "2.0.4",
4
+ "version": "2.0.5",
5
5
  "description": "Shared Vitest utility functions",
6
6
  "license": "MIT",
7
7
  "funding": "https://opencollective.com/vitest",
@@ -63,7 +63,7 @@
63
63
  "estree-walker": "^3.0.3",
64
64
  "loupe": "^3.1.1",
65
65
  "tinyrainbow": "^1.2.0",
66
- "@vitest/pretty-format": "2.0.4"
66
+ "@vitest/pretty-format": "2.0.5"
67
67
  },
68
68
  "devDependencies": {
69
69
  "@jridgewell/trace-mapping": "^0.3.25",