@vitest/expect 4.0.16 → 4.1.0-beta.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
@@ -9,11 +9,6 @@ import { stringify } from '@vitest/utils/display';
9
9
  import * as chai from 'chai';
10
10
  export { chai };
11
11
 
12
- declare const MATCHERS_OBJECT: unique symbol;
13
- declare const JEST_MATCHERS_OBJECT: unique symbol;
14
- declare const GLOBAL_EXPECT: unique symbol;
15
- declare const ASYMMETRIC_MATCHERS_OBJECT: unique symbol;
16
-
17
12
  interface AsymmetricMatcherInterface {
18
13
  asymmetricMatch: (other: unknown, customTesters?: Array<Tester>) => boolean;
19
14
  toString: () => string;
@@ -655,7 +650,7 @@ type VitestAssertion<
655
650
  > = { [K in keyof A] : A[K] extends Chai.Assertion ? Assertion<T> : A[K] extends (...args: any[]) => any ? A[K] : VitestAssertion<A[K], T> } & ((type: string, message?: string) => Assertion);
656
651
  type Promisify<O> = { [K in keyof O] : O[K] extends (...args: infer A) => infer R ? Promisify<O[K]> & ((...args: A) => Promise<R>) : O[K] };
657
652
  type PromisifyAssertion<T> = Promisify<Assertion<T>>;
658
- interface Assertion<T = any> extends VitestAssertion<Chai.Assertion, T>, JestAssertion<T>, Matchers<T> {
653
+ interface Assertion<T = any> extends VitestAssertion<Chai.Assertion, T>, JestAssertion<T>, ChaiMockAssertion, Matchers<T> {
659
654
  /**
660
655
  * Ensures a value is of a specific type.
661
656
  *
@@ -759,6 +754,140 @@ interface Assertion<T = any> extends VitestAssertion<Chai.Assertion, T>, JestAss
759
754
  */
760
755
  rejects: PromisifyAssertion<T>;
761
756
  }
757
+ /**
758
+ * Chai-style assertions for spy/mock testing.
759
+ * These provide sinon-chai compatible assertion names that delegate to Jest-style implementations.
760
+ */
761
+ interface ChaiMockAssertion {
762
+ /**
763
+ * Checks that a spy was called at least once.
764
+ * Chai-style equivalent of `toHaveBeenCalled`.
765
+ *
766
+ * @example
767
+ * expect(spy).to.have.been.called
768
+ */
769
+ readonly called: Assertion;
770
+ /**
771
+ * Checks that a spy was called a specific number of times.
772
+ * Chai-style equivalent of `toHaveBeenCalledTimes`.
773
+ *
774
+ * @example
775
+ * expect(spy).to.have.callCount(3)
776
+ */
777
+ callCount: (count: number) => void;
778
+ /**
779
+ * Checks that a spy was called with specific arguments at least once.
780
+ * Chai-style equivalent of `toHaveBeenCalledWith`.
781
+ *
782
+ * @example
783
+ * expect(spy).to.have.been.calledWith('arg1', 'arg2')
784
+ */
785
+ calledWith: <E extends any[]>(...args: E) => void;
786
+ /**
787
+ * Checks that a spy was called exactly once.
788
+ * Chai-style equivalent of `toHaveBeenCalledOnce`.
789
+ *
790
+ * @example
791
+ * expect(spy).to.have.been.calledOnce
792
+ */
793
+ readonly calledOnce: Assertion;
794
+ /**
795
+ * Checks that a spy was called exactly once with specific arguments.
796
+ * Chai-style equivalent of `toHaveBeenCalledExactlyOnceWith`.
797
+ *
798
+ * @example
799
+ * expect(spy).to.have.been.calledOnceWith('arg1', 'arg2')
800
+ */
801
+ calledOnceWith: <E extends any[]>(...args: E) => void;
802
+ /**
803
+ * Checks that the last call to a spy was made with specific arguments.
804
+ * Chai-style equivalent of `toHaveBeenLastCalledWith`.
805
+ *
806
+ * @example
807
+ * expect(spy).to.have.been.lastCalledWith('arg1', 'arg2')
808
+ */
809
+ lastCalledWith: <E extends any[]>(...args: E) => void;
810
+ /**
811
+ * Checks that the nth call to a spy was made with specific arguments.
812
+ * Chai-style equivalent of `toHaveBeenNthCalledWith`.
813
+ *
814
+ * @example
815
+ * expect(spy).to.have.been.nthCalledWith(2, 'arg1', 'arg2')
816
+ */
817
+ nthCalledWith: <E extends any[]>(n: number, ...args: E) => void;
818
+ /**
819
+ * Checks that a spy returned successfully at least once.
820
+ * Chai-style equivalent of `toHaveReturned`.
821
+ *
822
+ * @example
823
+ * expect(spy).to.have.returned
824
+ */
825
+ readonly returned: Assertion;
826
+ /**
827
+ * Checks that a spy returned a specific value at least once.
828
+ * Chai-style equivalent of `toHaveReturnedWith`.
829
+ *
830
+ * @example
831
+ * expect(spy).to.have.returnedWith('value')
832
+ */
833
+ returnedWith: <E>(value: E) => void;
834
+ /**
835
+ * Checks that a spy returned successfully a specific number of times.
836
+ * Chai-style equivalent of `toHaveReturnedTimes`.
837
+ *
838
+ * @example
839
+ * expect(spy).to.have.returnedTimes(3)
840
+ */
841
+ returnedTimes: (count: number) => void;
842
+ /**
843
+ * Checks that the last return value of a spy matches the expected value.
844
+ * Chai-style equivalent of `toHaveLastReturnedWith`.
845
+ *
846
+ * @example
847
+ * expect(spy).to.have.lastReturnedWith('value')
848
+ */
849
+ lastReturnedWith: <E>(value: E) => void;
850
+ /**
851
+ * Checks that the nth return value of a spy matches the expected value.
852
+ * Chai-style equivalent of `toHaveNthReturnedWith`.
853
+ *
854
+ * @example
855
+ * expect(spy).to.have.nthReturnedWith(2, 'value')
856
+ */
857
+ nthReturnedWith: <E>(n: number, value: E) => void;
858
+ /**
859
+ * Checks that a spy was called before another spy.
860
+ * Chai-style equivalent of `toHaveBeenCalledBefore`.
861
+ *
862
+ * @example
863
+ * expect(spy1).to.have.been.calledBefore(spy2)
864
+ */
865
+ calledBefore: (mock: MockInstance, failIfNoFirstInvocation?: boolean) => void;
866
+ /**
867
+ * Checks that a spy was called after another spy.
868
+ * Chai-style equivalent of `toHaveBeenCalledAfter`.
869
+ *
870
+ * @example
871
+ * expect(spy1).to.have.been.calledAfter(spy2)
872
+ */
873
+ calledAfter: (mock: MockInstance, failIfNoFirstInvocation?: boolean) => void;
874
+ /**
875
+ * Checks that a spy was called exactly twice.
876
+ * Chai-style equivalent of `toHaveBeenCalledTimes(2)`.
877
+ *
878
+ * @example
879
+ * expect(spy).to.have.been.calledTwice
880
+ */
881
+ readonly calledTwice: Assertion;
882
+ /**
883
+ * Checks that a spy was called exactly three times.
884
+ * Chai-style equivalent of `toHaveBeenCalledTimes(3)`.
885
+ *
886
+ * @example
887
+ * expect(spy).to.have.been.calledThrice
888
+ */
889
+ readonly calledThrice: Assertion;
890
+ }
762
891
  declare global {
763
892
  namespace jest {
764
893
  interface Matchers<
@@ -768,6 +897,13 @@ declare global {
768
897
  }
769
898
  }
770
899
 
900
+ declare const ChaiStyleAssertions: ChaiPlugin;
901
+
902
+ declare const MATCHERS_OBJECT: unique symbol;
903
+ declare const JEST_MATCHERS_OBJECT: unique symbol;
904
+ declare const GLOBAL_EXPECT: unique symbol;
905
+ declare const ASYMMETRIC_MATCHERS_OBJECT: unique symbol;
906
+
771
907
  declare const customMatchers: MatchersObject;
772
908
 
773
909
  declare const JestChaiExpect: ChaiPlugin;
@@ -802,5 +938,5 @@ declare function isStandardSchema(obj: any): obj is StandardSchemaV1;
802
938
  declare function getState<State extends MatcherState = MatcherState>(expect: ExpectStatic): State;
803
939
  declare function setState<State extends MatcherState = MatcherState>(state: Partial<State>, expect: ExpectStatic): void;
804
940
 
805
- export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, AsymmetricMatcher, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, ObjectContaining, SchemaMatching, StringContaining, StringMatching, addCustomEqualityTesters, arrayBufferEquality, customMatchers, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, isStandardSchema, iterableEquality, pluralize, setState, sparseArrayEquality, subsetEquality, typeEquality };
806
- export type { Assertion, AsymmetricMatcherInterface, AsymmetricMatchersContaining, AsyncExpectationResult, ChaiPlugin, DeeplyAllowMatchers, ExpectStatic, ExpectationResult, JestAssertion, MatcherHintOptions, MatcherState, Matchers, MatchersObject, PromisifyAssertion, RawMatcherFn, SyncExpectationResult, Tester, TesterContext };
941
+ export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, AsymmetricMatcher, ChaiStyleAssertions, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, ObjectContaining, SchemaMatching, StringContaining, StringMatching, addCustomEqualityTesters, arrayBufferEquality, customMatchers, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, isStandardSchema, iterableEquality, pluralize, setState, sparseArrayEquality, subsetEquality, typeEquality };
942
+ export type { Assertion, AsymmetricMatcherInterface, AsymmetricMatchersContaining, AsyncExpectationResult, ChaiMockAssertion, ChaiPlugin, DeeplyAllowMatchers, ExpectStatic, ExpectationResult, JestAssertion, MatcherHintOptions, MatcherState, Matchers, MatchersObject, PromisifyAssertion, RawMatcherFn, SyncExpectationResult, Tester, TesterContext };
package/dist/index.js CHANGED
@@ -8,6 +8,52 @@ import { use, util } from 'chai';
8
8
  import * as chai from 'chai';
9
9
  export { chai };
10
10
 
11
+ const ChaiStyleAssertions = (chai, utils) => {
12
+ function defProperty(name, delegateTo) {
13
+ utils.addProperty(chai.Assertion.prototype, name, function() {
14
+ const jestMethod = chai.Assertion.prototype[delegateTo];
15
+ if (!jestMethod) {
16
+ throw new Error(`Cannot delegate to ${String(delegateTo)}: method not found. Ensure JestChaiExpect plugin is loaded first.`);
17
+ }
18
+ return jestMethod.call(this);
19
+ });
20
+ }
21
+ function defPropertyWithArgs(name, delegateTo, ...args) {
22
+ utils.addProperty(chai.Assertion.prototype, name, function() {
23
+ const jestMethod = chai.Assertion.prototype[delegateTo];
24
+ if (!jestMethod) {
25
+ throw new Error(`Cannot delegate to ${String(delegateTo)}: method not found. Ensure JestChaiExpect plugin is loaded first.`);
26
+ }
27
+ return jestMethod.call(this, ...args);
28
+ });
29
+ }
30
+ function defMethod(name, delegateTo) {
31
+ utils.addChainableMethod(chai.Assertion.prototype, name, function(...args) {
32
+ const jestMethod = chai.Assertion.prototype[delegateTo];
33
+ if (!jestMethod) {
34
+ throw new Error(`Cannot delegate to ${String(delegateTo)}: method not found. Ensure JestChaiExpect plugin is loaded first.`);
35
+ }
36
+ return jestMethod.call(this, ...args);
37
+ }, () => {});
38
+ }
39
+ defProperty("called", "toHaveBeenCalled");
40
+ defProperty("calledOnce", "toHaveBeenCalledOnce");
41
+ defProperty("returned", "toHaveReturned");
42
+ defPropertyWithArgs("calledTwice", "toHaveBeenCalledTimes", 2);
43
+ defPropertyWithArgs("calledThrice", "toHaveBeenCalledTimes", 3);
44
+ defMethod("callCount", "toHaveBeenCalledTimes");
45
+ defMethod("calledWith", "toHaveBeenCalledWith");
46
+ defMethod("calledOnceWith", "toHaveBeenCalledExactlyOnceWith");
47
+ defMethod("lastCalledWith", "toHaveBeenLastCalledWith");
48
+ defMethod("nthCalledWith", "toHaveBeenNthCalledWith");
49
+ defMethod("returnedWith", "toHaveReturnedWith");
50
+ defMethod("returnedTimes", "toHaveReturnedTimes");
51
+ defMethod("lastReturnedWith", "toHaveLastReturnedWith");
52
+ defMethod("nthReturnedWith", "toHaveNthReturnedWith");
53
+ defMethod("calledBefore", "toHaveBeenCalledBefore");
54
+ defMethod("calledAfter", "toHaveBeenCalledAfter");
55
+ };
56
+
11
57
  const MATCHERS_OBJECT = Symbol.for("matchers-object");
12
58
  const JEST_MATCHERS_OBJECT = Symbol.for("$$jest-matchers-object");
13
59
  const GLOBAL_EXPECT = Symbol.for("expect-global");
@@ -1872,4 +1918,4 @@ const JestExtend = (chai, utils) => {
1872
1918
  });
1873
1919
  };
1874
1920
 
1875
- export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, AsymmetricMatcher, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, ObjectContaining, SchemaMatching, StringContaining, StringMatching, addCustomEqualityTesters, arrayBufferEquality, customMatchers, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, isStandardSchema, iterableEquality, pluralize, setState, sparseArrayEquality, subsetEquality, typeEquality };
1921
+ export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, AsymmetricMatcher, ChaiStyleAssertions, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, ObjectContaining, SchemaMatching, StringContaining, StringMatching, addCustomEqualityTesters, arrayBufferEquality, customMatchers, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, isStandardSchema, 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": "4.0.16",
4
+ "version": "4.1.0-beta.1",
5
5
  "description": "Jest's expect matchers as a Chai plugin",
6
6
  "license": "MIT",
7
7
  "funding": "https://opencollective.com/vitest",
@@ -29,15 +29,15 @@
29
29
  "dist"
30
30
  ],
31
31
  "dependencies": {
32
- "@standard-schema/spec": "^1.0.0",
32
+ "@standard-schema/spec": "^1.1.0",
33
33
  "@types/chai": "^5.2.2",
34
- "chai": "^6.2.1",
34
+ "chai": "^6.2.2",
35
35
  "tinyrainbow": "^3.0.3",
36
- "@vitest/spy": "4.0.16",
37
- "@vitest/utils": "4.0.16"
36
+ "@vitest/utils": "4.1.0-beta.1",
37
+ "@vitest/spy": "4.1.0-beta.1"
38
38
  },
39
39
  "devDependencies": {
40
- "@vitest/runner": "4.0.16"
40
+ "@vitest/runner": "4.1.0-beta.1"
41
41
  },
42
42
  "scripts": {
43
43
  "build": "premove dist && rollup -c",