@vitest/expect 1.4.0 → 1.5.1

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.d.ts CHANGED
@@ -237,6 +237,11 @@ declare function arrayBufferEquality(a: unknown, b: unknown): boolean | undefine
237
237
  declare function sparseArrayEquality(a: unknown, b: unknown, customTesters?: Array<Tester>): boolean | undefined;
238
238
  declare function generateToBeMessage(deepEqualityName: string, expected?: string, actual?: string): string;
239
239
  declare function pluralize(word: string, count: number): string;
240
+ declare function getObjectKeys(object: object): Array<string | symbol>;
241
+ declare function getObjectSubset(object: any, subset: any, customTesters?: Array<Tester>): {
242
+ subset: any;
243
+ stripped: number;
244
+ };
240
245
 
241
246
  declare const MATCHERS_OBJECT: unique symbol;
242
247
  declare const JEST_MATCHERS_OBJECT: unique symbol;
@@ -250,4 +255,4 @@ declare const JestChaiExpect: ChaiPlugin;
250
255
 
251
256
  declare const JestExtend: ChaiPlugin;
252
257
 
253
- export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, type Assertion, AsymmetricMatcher, type AsymmetricMatcherInterface, type AsymmetricMatchersContaining, type AsyncExpectationResult, type ChaiPlugin, type ExpectStatic, type ExpectationResult, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, type JestAssertion, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, type MatcherHintOptions, type MatcherState, type MatchersObject, ObjectContaining, type RawMatcherFn, StringContaining, StringMatching, type SyncExpectationResult, type Tester, type TesterContext, addCustomEqualityTesters, arrayBufferEquality, equals, fnNameFor, generateToBeMessage, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, iterableEquality, pluralize, setState, sparseArrayEquality, subsetEquality, typeEquality };
258
+ export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, type Assertion, AsymmetricMatcher, type AsymmetricMatcherInterface, type AsymmetricMatchersContaining, type AsyncExpectationResult, type ChaiPlugin, type ExpectStatic, type ExpectationResult, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, type JestAssertion, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, type MatcherHintOptions, type MatcherState, type MatchersObject, ObjectContaining, type RawMatcherFn, StringContaining, StringMatching, type SyncExpectationResult, type Tester, type TesterContext, addCustomEqualityTesters, arrayBufferEquality, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, iterableEquality, pluralize, setState, sparseArrayEquality, subsetEquality, typeEquality };
package/dist/index.js CHANGED
@@ -304,7 +304,7 @@ function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
304
304
  return iterableEquality(
305
305
  a2,
306
306
  b2,
307
- [...filteredCustomTesters],
307
+ [...customTesters],
308
308
  [...aStack],
309
309
  [...bStack]
310
310
  );
@@ -382,7 +382,7 @@ function subsetEquality(object, subset, customTesters = []) {
382
382
  if (!isObjectWithKeys(subset2))
383
383
  return void 0;
384
384
  return Object.keys(subset2).every((key) => {
385
- if (isObjectWithKeys(subset2[key])) {
385
+ if (typeof subset2[key] === "object") {
386
386
  if (seenReferences.has(subset2[key]))
387
387
  return equals(object2[key], subset2[key], filteredCustomTesters);
388
388
  seenReferences.set(subset2[key], true);
@@ -446,6 +446,57 @@ Received: serializes to the same string
446
446
  function pluralize(word, count) {
447
447
  return `${count} ${word}${count === 1 ? "" : "s"}`;
448
448
  }
449
+ function getObjectKeys(object) {
450
+ return [
451
+ ...Object.keys(object),
452
+ ...Object.getOwnPropertySymbols(object).filter(
453
+ (s) => {
454
+ var _a;
455
+ return (_a = Object.getOwnPropertyDescriptor(object, s)) == null ? void 0 : _a.enumerable;
456
+ }
457
+ )
458
+ ];
459
+ }
460
+ function getObjectSubset(object, subset, customTesters = []) {
461
+ let stripped = 0;
462
+ const getObjectSubsetWithContext = (seenReferences = /* @__PURE__ */ new WeakMap()) => (object2, subset2) => {
463
+ if (Array.isArray(object2)) {
464
+ if (Array.isArray(subset2) && subset2.length === object2.length) {
465
+ return subset2.map(
466
+ (sub, i) => getObjectSubsetWithContext(seenReferences)(object2[i], sub)
467
+ );
468
+ }
469
+ } else if (object2 instanceof Date) {
470
+ return object2;
471
+ } else if (isObject(object2) && isObject(subset2)) {
472
+ if (equals(object2, subset2, [
473
+ ...customTesters,
474
+ iterableEquality,
475
+ subsetEquality
476
+ ])) {
477
+ return subset2;
478
+ }
479
+ const trimmed = {};
480
+ seenReferences.set(object2, trimmed);
481
+ for (const key of getObjectKeys(object2)) {
482
+ if (hasPropertyInObject(subset2, key)) {
483
+ trimmed[key] = seenReferences.has(object2[key]) ? seenReferences.get(object2[key]) : getObjectSubsetWithContext(seenReferences)(object2[key], subset2[key]);
484
+ } else {
485
+ if (!seenReferences.has(object2[key])) {
486
+ stripped += 1;
487
+ if (isObject(object2[key]))
488
+ stripped += getObjectKeys(object2[key]).length;
489
+ getObjectSubsetWithContext(seenReferences)(object2[key], subset2[key]);
490
+ }
491
+ }
492
+ }
493
+ if (getObjectKeys(trimmed).length > 0)
494
+ return trimmed;
495
+ }
496
+ return object2;
497
+ };
498
+ return { subset: getObjectSubsetWithContext()(object, subset), stripped };
499
+ }
449
500
 
450
501
  class AsymmetricMatcher {
451
502
  constructor(sample, inverse = false) {
@@ -876,16 +927,30 @@ const JestChaiExpect = (chai, utils) => {
876
927
  });
877
928
  def("toMatchObject", function(expected) {
878
929
  const actual = this._obj;
879
- return this.assert(
880
- equals(actual, expected, [...customTesters, iterableEquality, subsetEquality]),
881
- "expected #{this} to match object #{exp}",
882
- "expected #{this} to not match object #{exp}",
883
- expected,
884
- actual
885
- );
930
+ const pass = equals(actual, expected, [...customTesters, iterableEquality, subsetEquality]);
931
+ const isNot = utils.flag(this, "negate");
932
+ const { subset: actualSubset, stripped } = getObjectSubset(actual, expected);
933
+ if (pass && isNot || !pass && !isNot) {
934
+ const msg = utils.getMessage(
935
+ this,
936
+ [
937
+ pass,
938
+ "expected #{this} to match object #{exp}",
939
+ "expected #{this} to not match object #{exp}",
940
+ expected,
941
+ actualSubset,
942
+ false
943
+ ]
944
+ );
945
+ const message = stripped === 0 ? msg : `${msg}
946
+ (${stripped} matching ${stripped === 1 ? "property" : "properties"} omitted from actual)`;
947
+ throw new AssertionError(message, { showDiff: true, expected, actual: actualSubset });
948
+ }
886
949
  });
887
950
  def("toMatch", function(expected) {
888
951
  const actual = this._obj;
952
+ if (typeof actual !== "string")
953
+ throw new TypeError(`.toMatch() expects to receive a string, but got ${typeof actual}`);
889
954
  return this.assert(
890
955
  typeof expected === "string" ? actual.includes(expected) : actual.match(expected),
891
956
  `expected #{this} to match #{exp}`,
@@ -1227,12 +1292,15 @@ Number of calls: ${c().bold(spy.mock.calls.length)}
1227
1292
  const spy = getSpy(this);
1228
1293
  const spyName = spy.getMockName();
1229
1294
  const nthCall = spy.mock.calls[times - 1];
1295
+ const callCount = spy.mock.calls.length;
1296
+ const isCalled = times <= callCount;
1230
1297
  this.assert(
1231
1298
  equals(nthCall, args, [...customTesters, iterableEquality]),
1232
- `expected ${ordinalOf(times)} "${spyName}" call to have been called with #{exp}`,
1299
+ `expected ${ordinalOf(times)} "${spyName}" call to have been called with #{exp}${isCalled ? `` : `, but called only ${callCount} times`}`,
1233
1300
  `expected ${ordinalOf(times)} "${spyName}" call to not have been called with #{exp}`,
1234
1301
  args,
1235
- nthCall
1302
+ nthCall,
1303
+ isCalled
1236
1304
  );
1237
1305
  });
1238
1306
  def(["toHaveBeenLastCalledWith", "lastCalledWith"], function(...args) {
@@ -1564,4 +1632,4 @@ const JestExtend = (chai, utils) => {
1564
1632
  });
1565
1633
  };
1566
1634
 
1567
- export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, AsymmetricMatcher, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, ObjectContaining, StringContaining, StringMatching, addCustomEqualityTesters, arrayBufferEquality, equals, fnNameFor, generateToBeMessage, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, iterableEquality, pluralize, setState, sparseArrayEquality, subsetEquality, typeEquality };
1635
+ export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, AsymmetricMatcher, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, ObjectContaining, StringContaining, StringMatching, addCustomEqualityTesters, arrayBufferEquality, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, iterableEquality, pluralize, setState, sparseArrayEquality, subsetEquality, typeEquality };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/expect",
3
3
  "type": "module",
4
- "version": "1.4.0",
4
+ "version": "1.5.1",
5
5
  "description": "Jest's expect matchers as a Chai plugin",
6
6
  "license": "MIT",
7
7
  "funding": "https://opencollective.com/vitest",
@@ -31,14 +31,14 @@
31
31
  ],
32
32
  "dependencies": {
33
33
  "chai": "^4.3.10",
34
- "@vitest/spy": "1.4.0",
35
- "@vitest/utils": "1.4.0"
34
+ "@vitest/spy": "1.5.1",
35
+ "@vitest/utils": "1.5.1"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/chai": "4.3.6",
39
39
  "picocolors": "^1.0.0",
40
40
  "rollup-plugin-copy": "^3.5.0",
41
- "@vitest/runner": "1.4.0"
41
+ "@vitest/runner": "1.5.1"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "rimraf dist && rollup -c",