diff --git a/packages/expect/src/types.ts b/packages/expect/src/types.ts index 7a64137e60b5..c1f033437980 100644 --- a/packages/expect/src/types.ts +++ b/packages/expect/src/types.ts @@ -106,60 +106,484 @@ export interface ExpectStatic } export interface AsymmetricMatchersContaining { + /** + * Matches if the received string contains the expected substring. + * + * @example + * expect('I have an apple').toEqual(expect.stringContaining('apple')); + * expect({ a: 'test string' }).toEqual({ a: expect.stringContaining('test') }); + */ stringContaining: (expected: string) => any + + /** + * Matches if the received object contains all properties of the expected object. + * + * @example + * expect({ a: '1', b: 2 }).toEqual(expect.objectContaining({ a: '1' })) + */ objectContaining: (expected: T) => any + + /** + * Matches if the received array contains all elements in the expected array. + * + * @example + * expect(['a', 'b', 'c']).toEqual(expect.arrayContaining(['b', 'a'])); + */ arrayContaining: (expected: Array) => any + + /** + * Matches if the received string or regex matches the expected pattern. + * + * @example + * expect('hello world').toEqual(expect.stringMatching(/^hello/)); + * expect('hello world').toEqual(expect.stringMatching('hello')); + */ stringMatching: (expected: string | RegExp) => any + + /** + * Matches if the received number is within a certain precision of the expected number. + * + * @param precision - Optional decimal precision for comparison. Default is 2. + * + * @example + * expect(10.45).toEqual(expect.closeTo(10.5, 1)); + * expect(5.11).toEqual(expect.closeTo(5.12)); // with default precision + */ closeTo: (expected: number, precision?: number) => any } export interface JestAssertion extends jest.Matchers { - // Jest compact + /** + * Used when you want to check that two objects have the same value. + * This matcher recursively checks the equality of all fields, rather than checking for object identity. + * + * @example + * expect(user).toEqual({ name: 'Alice', age: 30 }); + */ toEqual: (expected: E) => void + + /** + * Use to test that objects have the same types as well as structure. + * + * @example + * expect(user).toStrictEqual({ name: 'Alice', age: 30 }); + */ toStrictEqual: (expected: E) => void + + /** + * Checks that a value is what you expect. It calls `Object.is` to compare values. + * Don't use `toBe` with floating-point numbers. + * + * @example + * expect(result).toBe(42); + * expect(status).toBe(true); + */ toBe: (expected: E) => void + + /** + * Check that a string matches a regular expression. + * + * @example + * expect(message).toMatch(/hello/); + * expect(greeting).toMatch('world'); + */ toMatch: (expected: string | RegExp) => void + + /** + * Used to check that a JavaScript object matches a subset of the properties of an object + * + * @example + * expect(user).toMatchObject({ + * name: 'Alice', + * address: { city: 'Wonderland' } + * }); + */ toMatchObject: (expected: E) => void + + /** + * Used when you want to check that an item is in a list. + * For testing the items in the list, this uses `===`, a strict equality check. + * + * @example + * expect(items).toContain('apple'); + * expect(numbers).toContain(5); + */ toContain: (item: E) => void + + /** + * Used when you want to check that an item is in a list. + * For testing the items in the list, this matcher recursively checks the + * equality of all fields, rather than checking for object identity. + * + * @example + * expect(items).toContainEqual({ name: 'apple', quantity: 1 }); + */ toContainEqual: (item: E) => void + + /** + * Use when you don't care what a value is, you just want to ensure a value + * is true in a boolean context. In JavaScript, there are six falsy values: + * `false`, `0`, `''`, `null`, `undefined`, and `NaN`. Everything else is truthy. + * + * @example + * expect(user.isActive).toBeTruthy(); + */ toBeTruthy: () => void + + /** + * When you don't care what a value is, you just want to + * ensure a value is false in a boolean context. + * + * @example + * expect(user.isActive).toBeFalsy(); + */ toBeFalsy: () => void + + /** + * For comparing floating point numbers. + * + * @example + * expect(score).toBeGreaterThan(10); + */ toBeGreaterThan: (num: number | bigint) => void + + /** + * For comparing floating point numbers. + * + * @example + * expect(score).toBeGreaterThanOrEqual(10); + */ toBeGreaterThanOrEqual: (num: number | bigint) => void + + /** + * For comparing floating point numbers. + * + * @example + * expect(score).toBeLessThan(10); + */ toBeLessThan: (num: number | bigint) => void + + /** + * For comparing floating point numbers. + * + * @example + * expect(score).toBeLessThanOrEqual(10); + */ toBeLessThanOrEqual: (num: number | bigint) => void + + /** + * Used to check that a variable is NaN. + * + * @example + * expect(value).toBeNaN(); + */ toBeNaN: () => void + + /** + * Used to check that a variable is undefined. + * + * @example + * expect(value).toBeUndefined(); + */ toBeUndefined: () => void + + /** + * This is the same as `.toBe(null)` but the error messages are a bit nicer. + * So use `.toBeNull()` when you want to check that something is null. + * + * @example + * expect(value).toBeNull(); + */ toBeNull: () => void + + /** + * Ensure that a variable is not undefined. + * + * @example + * expect(value).toBeDefined(); + */ toBeDefined: () => void + + /** + * Ensure that an object is an instance of a class. + * This matcher uses `instanceof` underneath. + * + * @example + * expect(new Date()).toBeInstanceOf(Date); + */ toBeInstanceOf: (expected: E) => void - toBeCalledTimes: (times: number) => void + + /** + * Used to check that an object has a `.length` property + * and it is set to a certain numeric value. + * + * @example + * expect([1, 2, 3]).toHaveLength(3); + * expect('hello').toHaveLength(5); + */ toHaveLength: (length: number) => void + + /** + * Use to check if a property at the specified path exists on an object. + * For checking deeply nested properties, you may use dot notation or an array containing + * the path segments for deep references. + * + * Optionally, you can provide a value to check if it matches the value present at the path + * on the target object. This matcher uses 'deep equality' (like `toEqual()`) and recursively checks + * the equality of all fields. + * + * @example + * expect(user).toHaveProperty('address.city', 'New York'); + * expect(config).toHaveProperty(['settings', 'theme'], 'dark'); + */ toHaveProperty: ( property: string | (string | number)[], value?: E ) => void + + /** + * Using exact equality with floating point numbers is a bad idea. + * Rounding means that intuitive things fail. + * The default for `precision` is 2. + * + * @example + * expect(price).toBeCloseTo(9.99, 2); + */ toBeCloseTo: (number: number, numDigits?: number) => void + + /** + * Ensures that a mock function is called an exact number of times. + * + * Also under the alias `expect.toBeCalledTimes`. + * + * @example + * expect(mockFunc).toHaveBeenCalledTimes(2); + */ toHaveBeenCalledTimes: (times: number) => void + + /** + * Ensures that a mock function is called an exact number of times. + * + * Alias for `expect.toHaveBeenCalledTimes`. + * + * @example + * expect(mockFunc).toBeCalledTimes(2); + */ + toBeCalledTimes: (times: number) => void + + /** + * Ensures that a mock function is called. + * + * Also under the alias `expect.toBeCalled`. + * + * @example + * expect(mockFunc).toHaveBeenCalled(); + */ + toHaveBeenCalled: () => void + + /** + * Ensures that a mock function is called. + * + * Alias for `expect.toHaveBeenCalled`. + * + * @example + * expect(mockFunc).toBeCalled(); + */ toBeCalled: () => void + + /** + * Ensure that a mock function is called with specific arguments. + * + * Also under the alias `expect.toBeCalledWith`. + * + * @example + * expect(mockFunc).toHaveBeenCalledWith('arg1', 42); + */ toHaveBeenCalledWith: (...args: E) => void + + /** + * Ensure that a mock function is called with specific arguments. + * + * Alias for `expect.toHaveBeenCalledWith`. + * + * @example + * expect(mockFunc).toBeCalledWith('arg1', 42); + */ toBeCalledWith: (...args: E) => void + + /** + * Ensure that a mock function is called with specific arguments on an Nth call. + * + * Also under the alias `expect.nthCalledWith`. + * + * @example + * expect(mockFunc).toHaveBeenNthCalledWith(2, 'secondArg'); + */ toHaveBeenNthCalledWith: (n: number, ...args: E) => void + + /** + * Ensure that a mock function is called with specific arguments on an Nth call. + * + * Alias for `expect.toHaveBeenNthCalledWith`. + * + * @example + * expect(mockFunc).nthCalledWith(2, 'secondArg'); + */ nthCalledWith: (nthCall: number, ...args: E) => void + + /** + * If you have a mock function, you can use `.toHaveBeenLastCalledWith` + * to test what arguments it was last called with. + * + * Also under the alias `expect.lastCalledWith`. + * + * @example + * expect(mockFunc).toHaveBeenLastCalledWith('lastArg'); + */ toHaveBeenLastCalledWith: (...args: E) => void + + /** + * If you have a mock function, you can use `.lastCalledWith` + * to test what arguments it was last called with. + * + * Alias for `expect.toHaveBeenLastCalledWith`. + * + * @example + * expect(mockFunc).lastCalledWith('lastArg'); + */ lastCalledWith: (...args: E) => void + + /** + * Used to test that a function throws when it is called. + * + * Also under the alias `expect.toThrowError`. + * + * @example + * expect(() => functionWithError()).toThrow('Error message'); + * expect(() => parseJSON('invalid')).toThrow(SyntaxError); + */ toThrow: (expected?: string | Constructable | RegExp | Error) => void + + /** + * Used to test that a function throws when it is called. + * + * Alias for `expect.toThrow`. + * + * @example + * expect(() => functionWithError()).toThrowError('Error message'); + * expect(() => parseJSON('invalid')).toThrowError(SyntaxError); + */ toThrowError: (expected?: string | Constructable | RegExp | Error) => void + + /** + * Use to test that the mock function successfully returned (i.e., did not throw an error) at least one time + * + * Alias for `expect.toHaveReturned`. + * + * @example + * expect(mockFunc).toReturn(); + */ toReturn: () => void + + /** + * Use to test that the mock function successfully returned (i.e., did not throw an error) at least one time + * + * Also under the alias `expect.toReturn`. + * + * @example + * expect(mockFunc).toHaveReturned(); + */ toHaveReturned: () => void + + /** + * Use to ensure that a mock function returned successfully (i.e., did not throw an error) an exact number of times. + * Any calls to the mock function that throw an error are not counted toward the number of times the function returned. + * + * Alias for `expect.toHaveReturnedTimes`. + * + * @example + * expect(mockFunc).toReturnTimes(3); + */ toReturnTimes: (times: number) => void + + /** + * Use to ensure that a mock function returned successfully (i.e., did not throw an error) an exact number of times. + * Any calls to the mock function that throw an error are not counted toward the number of times the function returned. + * + * Also under the alias `expect.toReturnTimes`. + * + * @example + * expect(mockFunc).toHaveReturnedTimes(3); + */ toHaveReturnedTimes: (times: number) => void + + /** + * Use to ensure that a mock function returned a specific value. + * + * Alias for `expect.toHaveReturnedWith`. + * + * @example + * expect(mockFunc).toReturnWith('returnValue'); + */ toReturnWith: (value: E) => void + + /** + * Use to ensure that a mock function returned a specific value. + * + * Also under the alias `expect.toReturnWith`. + * + * @example + * expect(mockFunc).toHaveReturnedWith('returnValue'); + */ toHaveReturnedWith: (value: E) => void + + /** + * Use to test the specific value that a mock function last returned. + * If the last call to the mock function threw an error, then this matcher will fail + * no matter what value you provided as the expected return value. + * + * Also under the alias `expect.lastReturnedWith`. + * + * @example + * expect(mockFunc).toHaveLastReturnedWith('lastValue'); + */ toHaveLastReturnedWith: (value: E) => void + + /** + * Use to test the specific value that a mock function last returned. + * If the last call to the mock function threw an error, then this matcher will fail + * no matter what value you provided as the expected return value. + * + * Alias for `expect.toHaveLastReturnedWith`. + * + * @example + * expect(mockFunc).lastReturnedWith('lastValue'); + */ lastReturnedWith: (value: E) => void + + /** + * Use to test the specific value that a mock function returned for the nth call. + * If the nth call to the mock function threw an error, then this matcher will fail + * no matter what value you provided as the expected return value. + * + * Also under the alias `expect.nthReturnedWith`. + * + * @example + * expect(mockFunc).toHaveNthReturnedWith(2, 'nthValue'); + */ toHaveNthReturnedWith: (nthCall: number, value: E) => void + + /** + * Use to test the specific value that a mock function returned for the nth call. + * If the nth call to the mock function threw an error, then this matcher will fail + * no matter what value you provided as the expected return value. + * + * Alias for `expect.toHaveNthReturnedWith`. + * + * @example + * expect(mockFunc).nthReturnedWith(2, 'nthValue'); + */ nthReturnedWith: (nthCall: number, value: E) => void } @@ -184,6 +608,13 @@ export type PromisifyAssertion = Promisify> export interface Assertion extends VitestAssertion, JestAssertion { + /** + * Ensures a value is of a specific type. + * + * @example + * expect(value).toBeTypeOf('string'); + * expect(number).toBeTypeOf('number'); + */ toBeTypeOf: ( expected: | 'bigint' @@ -195,16 +626,80 @@ export interface Assertion | 'symbol' | 'undefined' ) => void + + /** + * Asserts that a mock function was called exactly once. + * + * @example + * expect(mockFunc).toHaveBeenCalledOnce(); + */ toHaveBeenCalledOnce: () => void + + /** + * Checks that a value satisfies a custom matcher function. + * + * @param matcher - A function returning a boolean based on the custom condition + * @param message - Optional custom error message on failure + * + * @example + * expect(age).toSatisfy(val => val >= 18, 'Age must be at least 18'); + */ toSatisfy: (matcher: (value: E) => boolean, message?: string) => void + /** + * Checks that a promise resolves successfully at least once. + * + * @example + * await expect(promise).toHaveResolved(); + */ toHaveResolved: () => void + + /** + * Checks that a promise resolves to a specific value. + * + * @example + * await expect(promise).toHaveResolvedWith('success'); + */ toHaveResolvedWith: (value: E) => void + + /** + * Ensures a promise resolves a specific number of times. + * + * @example + * expect(mockAsyncFunc).toHaveResolvedTimes(3); + */ toHaveResolvedTimes: (times: number) => void + + /** + * Asserts that the last resolved value of a promise matches an expected value. + * + * @example + * await expect(mockAsyncFunc).toHaveLastResolvedWith('finalResult'); + */ toHaveLastResolvedWith: (value: E) => void + + /** + * Ensures a specific value was returned by a promise on the nth resolution. + * + * @example + * await expect(mockAsyncFunc).toHaveNthResolvedWith(2, 'secondResult'); + */ toHaveNthResolvedWith: (nthCall: number, value: E) => void + /** + * Verifies that a promise resolves. + * + * @example + * await expect(someAsyncFunc).resolves.toBe(42); + */ resolves: PromisifyAssertion + + /** + * Verifies that a promise rejects. + * + * @example + * await expect(someAsyncFunc).rejects.toThrow('error'); + */ rejects: PromisifyAssertion } diff --git a/packages/vitest/src/types/global.ts b/packages/vitest/src/types/global.ts index ee157a28d9ad..c9ba65420ac3 100644 --- a/packages/vitest/src/types/global.ts +++ b/packages/vitest/src/types/global.ts @@ -64,11 +64,43 @@ declare module '@vitest/expect' { matchSnapshot: SnapshotMatcher toMatchSnapshot: SnapshotMatcher toMatchInlineSnapshot: InlineSnapshotMatcher + + /** + * Checks that an error thrown by a function matches a previously recorded snapshot. + * + * @param message - Optional custom error message. + * + * @example + * expect(functionWithError).toThrowErrorMatchingSnapshot(); + */ toThrowErrorMatchingSnapshot: (message?: string) => void + + /** + * Checks that an error thrown by a function matches an inline snapshot within the test file. + * Useful for keeping snapshots close to the test code. + * + * @param snapshot - Optional inline snapshot string to match. + * @param message - Optional custom error message. + * + * @example + * const throwError = () => { throw new Error('Error occurred') }; + * expect(throwError).toThrowErrorMatchingInlineSnapshot(`"Error occurred"`); + */ toThrowErrorMatchingInlineSnapshot: ( snapshot?: string, message?: string ) => void + + /** + * Compares the received value to a snapshot saved in a specified file. + * Useful for cases where snapshot content is large or needs to be shared across tests. + * + * @param filepath - Path to the snapshot file. + * @param message - Optional custom error message. + * + * @example + * await expect(largeData).toMatchFileSnapshot('path/to/snapshot.json'); + */ toMatchFileSnapshot: (filepath: string, message?: string) => Promise } }