@vitest/expect 3.2.4 → 4.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021-Present Vitest Team
3
+ Copyright (c) 2021-Present VoidZero Inc. and Vitest contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/dist/index.d.ts CHANGED
@@ -3,14 +3,14 @@ import { stringify, Constructable } from '@vitest/utils';
3
3
  import { Formatter } from 'tinyrainbow';
4
4
  import { diff, printDiffOrStringify } from '@vitest/utils/diff';
5
5
  export { DiffOptions } from '@vitest/utils/diff';
6
+ import * as chai from 'chai';
7
+ export { chai };
6
8
 
7
9
  declare const MATCHERS_OBJECT: unique symbol;
8
10
  declare const JEST_MATCHERS_OBJECT: unique symbol;
9
11
  declare const GLOBAL_EXPECT: unique symbol;
10
12
  declare const ASYMMETRIC_MATCHERS_OBJECT: unique symbol;
11
13
 
12
- /* eslint-disable unicorn/no-instanceof-builtins -- we check both */
13
-
14
14
  interface AsymmetricMatcherInterface {
15
15
  asymmetricMatch: (other: unknown) => boolean;
16
16
  toString: () => string;
@@ -23,7 +23,6 @@ declare abstract class AsymmetricMatcher<
23
23
  > implements AsymmetricMatcherInterface {
24
24
  protected sample: T;
25
25
  protected inverse: boolean;
26
- // should have "jest" to be compatible with its ecosystem
27
26
  $$typeof: symbol;
28
27
  constructor(sample: T, inverse?: boolean);
29
28
  protected getMatcherContext(expect?: Chai.ExpectStatic): State;
@@ -43,10 +42,11 @@ declare class Anything extends AsymmetricMatcher<void> {
43
42
  toString(): string;
44
43
  toAsymmetricMatcher(): string;
45
44
  }
46
- declare class ObjectContaining extends AsymmetricMatcher<Record<string, unknown>> {
45
+ declare class ObjectContaining extends AsymmetricMatcher<Record<string | symbol | number, unknown>> {
47
46
  constructor(sample: Record<string, unknown>, inverse?: boolean);
48
47
  getPrototype(obj: object): any;
49
- hasProperty(obj: object | null, property: string): boolean;
48
+ hasProperty(obj: object | null, property: string | symbol): boolean;
49
+ getProperties(obj: object): (string | symbol)[];
50
50
  asymmetricMatch(other: any): boolean;
51
51
  toString(): string;
52
52
  getExpectedType(): string;
@@ -77,17 +77,17 @@ declare function matcherHint(matcherName: string, received?: string, expected?:
77
77
  declare function printReceived(object: unknown): string;
78
78
  declare function printExpected(value: unknown): string;
79
79
  declare function getMatcherUtils(): {
80
- EXPECTED_COLOR: Formatter
81
- RECEIVED_COLOR: Formatter
82
- INVERTED_COLOR: Formatter
83
- BOLD_WEIGHT: Formatter
84
- DIM_COLOR: Formatter
85
- diff: typeof diff
86
- matcherHint: typeof matcherHint
87
- printReceived: typeof printReceived
88
- printExpected: typeof printExpected
89
- printDiffOrStringify: typeof printDiffOrStringify
90
- printWithType: typeof printWithType
80
+ EXPECTED_COLOR: Formatter;
81
+ RECEIVED_COLOR: Formatter;
82
+ INVERTED_COLOR: Formatter;
83
+ BOLD_WEIGHT: Formatter;
84
+ DIM_COLOR: Formatter;
85
+ diff: typeof diff;
86
+ matcherHint: typeof matcherHint;
87
+ printReceived: typeof printReceived;
88
+ printExpected: typeof printExpected;
89
+ printDiffOrStringify: typeof printDiffOrStringify;
90
+ printWithType: typeof printWithType;
91
91
  };
92
92
  declare function printWithType<T>(name: string, value: T, print: (value: T) => string): string;
93
93
  declare function addCustomEqualityTesters(newTesters: Array<Tester>): void;
@@ -129,16 +129,14 @@ interface MatcherState {
129
129
  isExpectingAssertions?: boolean;
130
130
  isExpectingAssertionsError?: Error | null;
131
131
  isNot: boolean;
132
- // environment: VitestEnvironment
133
132
  promise: string;
134
- // snapshotState: SnapshotState
135
133
  suppressedErrors: Array<Error>;
136
134
  testPath?: string;
137
135
  utils: ReturnType<typeof getMatcherUtils> & {
138
- diff: typeof diff
139
- stringify: typeof stringify
140
- iterableEquality: Tester
141
- subsetEquality: Tester
136
+ diff: typeof diff;
137
+ stringify: typeof stringify;
138
+ iterableEquality: Tester;
139
+ subsetEquality: Tester;
142
140
  };
143
141
  soft?: boolean;
144
142
  poll?: boolean;
@@ -157,9 +155,6 @@ interface RawMatcherFn<
157
155
  > {
158
156
  (this: T, received: any, ...expected: E): ExpectationResult;
159
157
  }
160
- // Allow unused `T` to preserve its name for extensions.
161
- // Type parameter names must be identical when extending those types.
162
- // eslint-disable-next-line
163
158
  interface Matchers<T = any> {}
164
159
  type MatchersObject<T extends MatcherState = MatcherState> = Record<string, RawMatcherFn<T>> & ThisType<T> & { [K in keyof Matchers<T>]? : RawMatcherFn<T, Parameters<Matchers<T>[K]>> };
165
160
  interface ExpectStatic extends Chai.ExpectStatic, Matchers, AsymmetricMatchersContaining {
@@ -366,6 +361,13 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
366
361
  */
367
362
  toBeNull: () => void;
368
363
  /**
364
+ * Used to check that a variable is nullable (null or undefined).
365
+ *
366
+ * @example
367
+ * expect(value).toBeNullable();
368
+ */
369
+ toBeNullable: () => void;
370
+ /**
369
371
  * Ensure that a variable is not undefined.
370
372
  *
371
373
  * @example
@@ -736,50 +738,20 @@ interface Assertion<T = any> extends VitestAssertion<Chai.Assertion, T>, JestAss
736
738
  rejects: PromisifyAssertion<T>;
737
739
  }
738
740
  declare global {
739
- // support augmenting jest.Matchers by other libraries
740
- // eslint-disable-next-line ts/no-namespace
741
741
  namespace jest {
742
- // eslint-disable-next-line unused-imports/no-unused-vars, ts/no-empty-object-type
743
- interface Matchers<
742
+ interface Matchers<
744
743
  R,
745
744
  T = {}
746
745
  > {}
747
746
  }
748
747
  }
749
748
 
750
- // selectively ported from https://github.com/jest-community/jest-extended
751
749
  declare const customMatchers: MatchersObject;
752
750
 
753
- // Jest Expect Compact
754
751
  declare const JestChaiExpect: ChaiPlugin;
755
752
 
756
753
  declare const JestExtend: ChaiPlugin;
757
754
 
758
- /*
759
- Copyright (c) 2008-2016 Pivotal Labs
760
-
761
- Permission is hereby granted, free of charge, to any person obtaining
762
- a copy of this software and associated documentation files (the
763
- "Software"), to deal in the Software without restriction, including
764
- without limitation the rights to use, copy, modify, merge, publish,
765
- distribute, sublicense, and/or sell copies of the Software, and to
766
- permit persons to whom the Software is furnished to do so, subject to
767
- the following conditions:
768
-
769
- The above copyright notice and this permission notice shall be
770
- included in all copies or substantial portions of the Software.
771
-
772
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
773
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
774
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
775
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
776
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
777
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
778
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
779
-
780
- */
781
-
782
- // Extracted out of jasmine 2.5.2
783
755
  declare function equals(a: unknown, b: unknown, customTesters?: Array<Tester>, strictCheck?: boolean): boolean;
784
756
  declare function isAsymmetric(obj: any): boolean;
785
757
  declare function hasAsymmetric(obj: any, seen?: Set<any>): boolean;
@@ -797,8 +769,8 @@ declare function generateToBeMessage(deepEqualityName: string, expected?: string
797
769
  declare function pluralize(word: string, count: number): string;
798
770
  declare function getObjectKeys(object: object): Array<string | symbol>;
799
771
  declare function getObjectSubset(object: any, subset: any, customTesters: Array<Tester>): {
800
- subset: any
801
- stripped: number
772
+ subset: any;
773
+ stripped: number;
802
774
  };
803
775
 
804
776
  declare function getState<State extends MatcherState = MatcherState>(expect: ExpectStatic): State;
package/dist/index.js CHANGED
@@ -4,6 +4,8 @@ import c from 'tinyrainbow';
4
4
  import { isMockFunction } from '@vitest/spy';
5
5
  import { processError } from '@vitest/utils/error';
6
6
  import { use, util } from 'chai';
7
+ import * as chai from 'chai';
8
+ export { chai };
7
9
 
8
10
  const MATCHERS_OBJECT = Symbol.for("matchers-object");
9
11
  const JEST_MATCHERS_OBJECT = Symbol.for("$$jest-matchers-object");
@@ -339,7 +341,7 @@ function hasDefinedKey(obj, key) {
339
341
  return hasKey(obj, key) && obj[key] !== undefined;
340
342
  }
341
343
  function hasKey(obj, key) {
342
- return Object.prototype.hasOwnProperty.call(obj, key);
344
+ return Object.hasOwn(obj, key);
343
345
  }
344
346
  function isA(typeName, value) {
345
347
  return Object.prototype.toString.apply(value) === `[object ${typeName}]`;
@@ -367,7 +369,7 @@ function hasProperty(obj, property) {
367
369
  if (!obj) {
368
370
  return false;
369
371
  }
370
- if (Object.prototype.hasOwnProperty.call(obj, property)) {
372
+ if (Object.hasOwn(obj, property)) {
371
373
  return true;
372
374
  }
373
375
  return hasProperty(getPrototype(obj), property);
@@ -514,7 +516,7 @@ function hasPropertyInObject(object, key) {
514
516
  if (shouldTerminate) {
515
517
  return false;
516
518
  }
517
- return Object.prototype.hasOwnProperty.call(object, key) || hasPropertyInObject(Object.getPrototypeOf(object), key);
519
+ return Object.hasOwn(object, key) || hasPropertyInObject(Object.getPrototypeOf(object), key);
518
520
  }
519
521
  function isObjectWithKeys(a) {
520
522
  return isObject(a) && !(a instanceof Error) && !Array.isArray(a) && !(a instanceof Date);
@@ -658,7 +660,7 @@ function getObjectSubset(object, subset, customTesters) {
658
660
  };
659
661
  }
660
662
 
661
- if (!Object.prototype.hasOwnProperty.call(globalThis, MATCHERS_OBJECT)) {
663
+ if (!Object.hasOwn(globalThis, MATCHERS_OBJECT)) {
662
664
  const globalState = new WeakMap();
663
665
  const matchers = Object.create(null);
664
666
  const customEqualityTesters = [];
@@ -769,19 +771,33 @@ class ObjectContaining extends AsymmetricMatcher {
769
771
  if (!obj) {
770
772
  return false;
771
773
  }
772
- if (Object.prototype.hasOwnProperty.call(obj, property)) {
774
+ if (Object.hasOwn(obj, property)) {
773
775
  return true;
774
776
  }
775
777
  return this.hasProperty(this.getPrototype(obj), property);
776
778
  }
779
+ getProperties(obj) {
780
+ return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj).filter((s) => {
781
+ var _Object$getOwnPropert;
782
+ return (_Object$getOwnPropert = Object.getOwnPropertyDescriptor(obj, s)) === null || _Object$getOwnPropert === void 0 ? void 0 : _Object$getOwnPropert.enumerable;
783
+ })];
784
+ }
777
785
  asymmetricMatch(other) {
778
786
  if (typeof this.sample !== "object") {
779
787
  throw new TypeError(`You must provide an object to ${this.toString()}, not '${typeof this.sample}'.`);
780
788
  }
781
789
  let result = true;
782
790
  const matcherContext = this.getMatcherContext();
783
- for (const property in this.sample) {
784
- if (!this.hasProperty(other, property) || !equals(this.sample[property], other[property], matcherContext.customTesters)) {
791
+ const properties = this.getProperties(this.sample);
792
+ for (const property of properties) {
793
+ var _Object$getOwnPropert2, _Object$getOwnPropert3;
794
+ if (!this.hasProperty(other, property)) {
795
+ result = false;
796
+ break;
797
+ }
798
+ const value = ((_Object$getOwnPropert2 = Object.getOwnPropertyDescriptor(this.sample, property)) === null || _Object$getOwnPropert2 === void 0 ? void 0 : _Object$getOwnPropert2.value) ?? this.sample[property];
799
+ const otherValue = ((_Object$getOwnPropert3 = Object.getOwnPropertyDescriptor(other, property)) === null || _Object$getOwnPropert3 === void 0 ? void 0 : _Object$getOwnPropert3.value) ?? other[property];
800
+ if (!equals(value, otherValue, matcherContext.customTesters)) {
785
801
  result = false;
786
802
  break;
787
803
  }
@@ -1241,6 +1257,10 @@ const JestChaiExpect = (chai, utils) => {
1241
1257
  const obj = utils.flag(this, "object");
1242
1258
  this.assert(obj === null, "expected #{this} to be null", "expected #{this} not to be null", null, obj);
1243
1259
  });
1260
+ def("toBeNullable", function() {
1261
+ const obj = utils.flag(this, "object");
1262
+ this.assert(obj == null, "expected #{this} to be nullish", "expected #{this} not to be nullish", null, obj);
1263
+ });
1244
1264
  def("toBeDefined", function() {
1245
1265
  const obj = utils.flag(this, "object");
1246
1266
  this.assert(typeof obj !== "undefined", "expected #{this} to be defined", "expected #{this} to be undefined", obj);
@@ -1264,7 +1284,7 @@ const JestChaiExpect = (chai, utils) => {
1264
1284
  const actual = this._obj;
1265
1285
  const [propertyName, expected] = args;
1266
1286
  const getValue = () => {
1267
- const hasOwn = Object.prototype.hasOwnProperty.call(actual, propertyName);
1287
+ const hasOwn = Object.hasOwn(actual, propertyName);
1268
1288
  if (hasOwn) {
1269
1289
  return {
1270
1290
  value: actual[propertyName],
@@ -1383,7 +1403,7 @@ const JestChaiExpect = (chai, utils) => {
1383
1403
  def(["toHaveBeenLastCalledWith", "lastCalledWith"], function(...args) {
1384
1404
  const spy = getSpy(this);
1385
1405
  const spyName = spy.getMockName();
1386
- const lastCall = spy.mock.calls[spy.mock.calls.length - 1];
1406
+ const lastCall = spy.mock.calls.at(-1);
1387
1407
  this.assert(lastCall && equalsArgumentArray(lastCall, args), `expected last "${spyName}" call to have been called with #{exp}`, `expected last "${spyName}" call to not have been called with #{exp}`, args, lastCall);
1388
1408
  });
1389
1409
  /**
@@ -1522,22 +1542,22 @@ const JestChaiExpect = (chai, utils) => {
1522
1542
  [{
1523
1543
  name: "toHaveLastResolvedWith",
1524
1544
  condition: (spy, value) => {
1525
- const result = spy.mock.settledResults[spy.mock.settledResults.length - 1];
1526
- return result && result.type === "fulfilled" && equals(result.value, value);
1545
+ const result = spy.mock.settledResults.at(-1);
1546
+ return Boolean(result && result.type === "fulfilled" && equals(result.value, value));
1527
1547
  },
1528
1548
  action: "resolve"
1529
1549
  }, {
1530
1550
  name: ["toHaveLastReturnedWith", "lastReturnedWith"],
1531
1551
  condition: (spy, value) => {
1532
- const result = spy.mock.results[spy.mock.results.length - 1];
1533
- return result && result.type === "return" && equals(result.value, value);
1552
+ const result = spy.mock.results.at(-1);
1553
+ return Boolean(result && result.type === "return" && equals(result.value, value));
1534
1554
  },
1535
1555
  action: "return"
1536
1556
  }].forEach(({ name, condition, action }) => {
1537
1557
  def(name, function(value) {
1538
1558
  const spy = getSpy(this);
1539
1559
  const results = action === "return" ? spy.mock.results : spy.mock.settledResults;
1540
- const result = results[results.length - 1];
1560
+ const result = results.at(-1);
1541
1561
  const spyName = spy.getMockName();
1542
1562
  this.assert(condition(spy, value), `expected last "${spyName}" call to ${action} #{exp}`, `expected last "${spyName}" call to not ${action} #{exp}`, value, result === null || result === void 0 ? void 0 : result.value);
1543
1563
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/expect",
3
3
  "type": "module",
4
- "version": "3.2.4",
4
+ "version": "4.0.0-beta.10",
5
5
  "description": "Jest's expect matchers as a Chai plugin",
6
6
  "license": "MIT",
7
7
  "funding": "https://opencollective.com/vitest",
@@ -30,14 +30,13 @@
30
30
  ],
31
31
  "dependencies": {
32
32
  "@types/chai": "^5.2.2",
33
- "chai": "^5.2.0",
33
+ "chai": "^6.0.1",
34
34
  "tinyrainbow": "^2.0.0",
35
- "@vitest/spy": "3.2.4",
36
- "@vitest/utils": "3.2.4"
35
+ "@vitest/spy": "4.0.0-beta.10",
36
+ "@vitest/utils": "4.0.0-beta.10"
37
37
  },
38
38
  "devDependencies": {
39
- "rollup-plugin-copy": "^3.5.0",
40
- "@vitest/runner": "3.2.4"
39
+ "@vitest/runner": "4.0.0-beta.10"
41
40
  },
42
41
  "scripts": {
43
42
  "build": "rimraf dist && rollup -c",