mirror of https://github.com/facebook/jest.git
Add type tests for all `expect` matchers (#11949)
This commit is contained in:
parent
46c9c13811
commit
ae1f04bf0a
|
@ -4,7 +4,8 @@
|
|||
|
||||
### Fixes
|
||||
|
||||
- `[jest-runtime]` Ensure absolute paths can be resolved within test modules ([11943](https://github.com/facebook/jest/pull/11943))
|
||||
- `[expect]` Tweak and improve types ([#11949](https://github.com/facebook/jest/pull/11949))
|
||||
- `[jest-runtime]` Ensure absolute paths can be resolved within test modules ([#11943](https://github.com/facebook/jest/pull/11943))
|
||||
- `[jest-runtime]` Fix `instanceof` for `ModernFakeTimers` and `LegacyFakeTimers` methods ([#11946](https://github.com/facebook/jest/pull/11946))
|
||||
|
||||
### Chore & Maintenance
|
||||
|
|
|
@ -37,6 +37,7 @@ describe('.hasAssertions()', () => {
|
|||
|
||||
it('throws if expected is not undefined', () => {
|
||||
jestExpect(() => {
|
||||
// @ts-expect-error
|
||||
jestExpect.hasAssertions(2);
|
||||
}).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
|
|
|
@ -431,7 +431,7 @@ const expectExport = expect as Expect;
|
|||
|
||||
declare namespace expectExport {
|
||||
export type MatcherState = JestMatcherState;
|
||||
export interface Matchers<R> extends MatcherInterface<R> {}
|
||||
export interface Matchers<R, T> extends MatcherInterface<R, T> {}
|
||||
}
|
||||
|
||||
export = expectExport;
|
||||
|
|
|
@ -98,15 +98,14 @@ export const setMatchers = <State extends MatcherState = MatcherState>(
|
|||
}
|
||||
}
|
||||
|
||||
expect[key] = (...sample: [unknown, ...Array<unknown>]) =>
|
||||
new CustomMatcher(false, ...sample);
|
||||
if (!expect.not) {
|
||||
throw new Error(
|
||||
'`expect.not` is not defined - please report this bug to https://github.com/facebook/jest',
|
||||
);
|
||||
}
|
||||
expect.not[key] = (...sample: [unknown, ...Array<unknown>]) =>
|
||||
new CustomMatcher(true, ...sample);
|
||||
Object.defineProperty(expect, key, {
|
||||
value: (...sample: [unknown, ...Array<unknown>]) =>
|
||||
new CustomMatcher(false, ...sample),
|
||||
});
|
||||
Object.defineProperty(expect.not, key, {
|
||||
value: (...sample: [unknown, ...Array<unknown>]) =>
|
||||
new CustomMatcher(true, ...sample),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/* eslint-disable local/ban-types-eventually */
|
||||
|
||||
import type {Config} from '@jest/types';
|
||||
import type * as jestMatcherUtils from 'jest-matcher-utils';
|
||||
import {INTERNAL_MATCHER_FLAG} from './jestMatchersObject';
|
||||
|
@ -72,26 +70,17 @@ export type ExpectedAssertionsErrors = Array<{
|
|||
expected: string;
|
||||
}>;
|
||||
|
||||
interface InverseAsymmetricMatchers {
|
||||
interface AsymmetricMatchers {
|
||||
any(sample: unknown): AsymmetricMatcher;
|
||||
anything(): AsymmetricMatcher;
|
||||
arrayContaining(sample: Array<unknown>): AsymmetricMatcher;
|
||||
objectContaining(sample: Record<string, unknown>): AsymmetricMatcher;
|
||||
stringContaining(expected: string): AsymmetricMatcher;
|
||||
stringMatching(expected: string | RegExp): AsymmetricMatcher;
|
||||
}
|
||||
|
||||
interface AsymmetricMatchers extends InverseAsymmetricMatchers {
|
||||
any(expectedObject: unknown): AsymmetricMatcher;
|
||||
anything(): AsymmetricMatcher;
|
||||
}
|
||||
|
||||
// Should use interface merging somehow
|
||||
interface ExtraAsymmetricMatchers {
|
||||
// at least one argument is needed - that's probably wrong. Should allow `expect.toBeDivisibleBy2()` like `expect.anything()`
|
||||
[id: string]: (...sample: [unknown, ...Array<unknown>]) => AsymmetricMatcher;
|
||||
stringContaining(sample: string): AsymmetricMatcher;
|
||||
stringMatching(sample: string | RegExp): AsymmetricMatcher;
|
||||
}
|
||||
|
||||
export type Expect<State extends MatcherState = MatcherState> = {
|
||||
<T = unknown>(actual: T): Matchers<void>;
|
||||
<T = unknown>(actual: T): Matchers<void, T>;
|
||||
// TODO: this is added by test runners, not `expect` itself
|
||||
addSnapshotSerializer(serializer: unknown): void;
|
||||
assertions(numberOfAssertions: number): void;
|
||||
|
@ -101,43 +90,42 @@ export type Expect<State extends MatcherState = MatcherState> = {
|
|||
getState(): State;
|
||||
hasAssertions(): void;
|
||||
setState(state: Partial<State>): void;
|
||||
} & AsymmetricMatchers &
|
||||
ExtraAsymmetricMatchers & {
|
||||
not: InverseAsymmetricMatchers & ExtraAsymmetricMatchers;
|
||||
} & AsymmetricMatchers & {
|
||||
not: Omit<AsymmetricMatchers, 'any' | 'anything'>;
|
||||
};
|
||||
|
||||
// This is a copy from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/de6730f4463cba69904698035fafd906a72b9664/types/jest/index.d.ts#L570-L817
|
||||
export interface Matchers<R> {
|
||||
export interface Matchers<R, T = unknown> {
|
||||
/**
|
||||
* Ensures the last call to a mock function was provided specific args.
|
||||
*/
|
||||
lastCalledWith(...args: Array<unknown>): R;
|
||||
lastCalledWith(...expected: [unknown, ...Array<unknown>]): R;
|
||||
/**
|
||||
* Ensure that the last call to a mock function has returned a specified value.
|
||||
*/
|
||||
lastReturnedWith(value: unknown): R;
|
||||
lastReturnedWith(expected: unknown): R;
|
||||
/**
|
||||
* If you know how to test something, `.not` lets you test its opposite.
|
||||
*/
|
||||
not: Matchers<R>;
|
||||
not: Matchers<R, T>;
|
||||
/**
|
||||
* Ensure that a mock function is called with specific arguments on an Nth call.
|
||||
*/
|
||||
nthCalledWith(nthCall: number, ...args: Array<unknown>): R;
|
||||
nthCalledWith(nth: number, ...expected: [unknown, ...Array<unknown>]): R;
|
||||
/**
|
||||
* Ensure that the nth call to a mock function has returned a specified value.
|
||||
*/
|
||||
nthReturnedWith(n: number, value: unknown): R;
|
||||
nthReturnedWith(nth: number, expected: unknown): R;
|
||||
/**
|
||||
* Use resolves to unwrap the value of a fulfilled promise so any other
|
||||
* matcher can be chained. If the promise is rejected the assertion fails.
|
||||
*/
|
||||
resolves: Matchers<Promise<R>>;
|
||||
resolves: Matchers<Promise<R>, T>;
|
||||
/**
|
||||
* Unwraps the reason of a rejected promise so any other matcher can be chained.
|
||||
* If the promise is fulfilled the assertion fails.
|
||||
*/
|
||||
rejects: Matchers<Promise<R>>;
|
||||
rejects: Matchers<Promise<R>, T>;
|
||||
/**
|
||||
* Checks that a value is what you expect. It uses `===` to check strict equality.
|
||||
* Don't use `toBe` with floating-point numbers.
|
||||
|
@ -154,13 +142,13 @@ export interface Matchers<R> {
|
|||
/**
|
||||
* Ensure that a mock function is called with specific arguments.
|
||||
*/
|
||||
toBeCalledWith(...args: Array<unknown>): R;
|
||||
toBeCalledWith(...expected: [unknown, ...Array<unknown>]): R;
|
||||
/**
|
||||
* Using exact equality with floating point numbers is a bad idea.
|
||||
* Rounding means that intuitive things fail.
|
||||
* The default for numDigits is 2.
|
||||
* The default for `precision` is 2.
|
||||
*/
|
||||
toBeCloseTo(expected: number, numDigits?: number): R;
|
||||
toBeCloseTo(expected: number, precision?: number): R;
|
||||
/**
|
||||
* Ensure that a variable is not undefined.
|
||||
*/
|
||||
|
@ -182,7 +170,7 @@ export interface Matchers<R> {
|
|||
* Ensure that an object is an instance of a class.
|
||||
* This matcher uses `instanceof` underneath.
|
||||
*/
|
||||
toBeInstanceOf(expected: Function): R;
|
||||
toBeInstanceOf(expected: unknown): R;
|
||||
/**
|
||||
* For comparing floating point numbers.
|
||||
*/
|
||||
|
@ -237,16 +225,19 @@ export interface Matchers<R> {
|
|||
/**
|
||||
* Ensure that a mock function is called with specific arguments.
|
||||
*/
|
||||
toHaveBeenCalledWith(...args: Array<unknown>): R;
|
||||
toHaveBeenCalledWith(...expected: [unknown, ...Array<unknown>]): R;
|
||||
/**
|
||||
* Ensure that a mock function is called with specific arguments on an Nth call.
|
||||
*/
|
||||
toHaveBeenNthCalledWith(nthCall: number, ...args: Array<unknown>): R;
|
||||
toHaveBeenNthCalledWith(
|
||||
nth: number,
|
||||
...expected: [unknown, ...Array<unknown>]
|
||||
): R;
|
||||
/**
|
||||
* If you have a mock function, you can use `.toHaveBeenLastCalledWith`
|
||||
* to test what arguments it was last called with.
|
||||
*/
|
||||
toHaveBeenLastCalledWith(...args: Array<unknown>): R;
|
||||
toHaveBeenLastCalledWith(...expected: [unknown, ...Array<unknown>]): R;
|
||||
/**
|
||||
* 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
|
||||
|
@ -263,7 +254,7 @@ export interface Matchers<R> {
|
|||
* 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.
|
||||
*/
|
||||
toHaveNthReturnedWith(nthCall: number, expected: unknown): R;
|
||||
toHaveNthReturnedWith(nth: number, expected: unknown): R;
|
||||
/**
|
||||
* Use to check if property at provided reference keyPath exists for an object.
|
||||
* For checking deeply nested properties in an object you may use dot notation or an array containing
|
||||
|
@ -277,7 +268,10 @@ export interface Matchers<R> {
|
|||
*
|
||||
* expect(houseForSale).toHaveProperty('kitchen.area', 20);
|
||||
*/
|
||||
toHaveProperty(keyPath: string | Array<string>, value?: unknown): R;
|
||||
toHaveProperty(
|
||||
expectedPath: string | Array<string>,
|
||||
expectedValue?: unknown,
|
||||
): R;
|
||||
/**
|
||||
* Use to test that the mock function successfully returned (i.e., did not throw an error) at least one time
|
||||
*/
|
||||
|
@ -298,7 +292,9 @@ export interface Matchers<R> {
|
|||
/**
|
||||
* Used to check that a JavaScript object matches a subset of the properties of an object
|
||||
*/
|
||||
toMatchObject(expected: Record<string, unknown> | Array<unknown>): R;
|
||||
toMatchObject(
|
||||
expected: Record<string, unknown> | Array<Record<string, unknown>>,
|
||||
): R;
|
||||
/**
|
||||
* Ensure that a mock function has returned (as opposed to thrown) at least once.
|
||||
*/
|
||||
|
@ -306,11 +302,11 @@ export interface Matchers<R> {
|
|||
/**
|
||||
* Ensure that a mock function has returned (as opposed to thrown) a specified number of times.
|
||||
*/
|
||||
toReturnTimes(count: number): R;
|
||||
toReturnTimes(expected: number): R;
|
||||
/**
|
||||
* Ensure that a mock function has returned a specified value at least once.
|
||||
*/
|
||||
toReturnWith(value: unknown): R;
|
||||
toReturnWith(expected: unknown): R;
|
||||
/**
|
||||
* Use to test that objects have the same types as well as structure.
|
||||
*/
|
||||
|
@ -318,34 +314,25 @@ export interface Matchers<R> {
|
|||
/**
|
||||
* Used to test that a function throws when it is called.
|
||||
*/
|
||||
toThrow(error?: unknown): R;
|
||||
toThrow(expected?: unknown): R;
|
||||
/**
|
||||
* If you want to test that a specific error is thrown inside a function.
|
||||
*/
|
||||
toThrowError(error?: unknown): R;
|
||||
toThrowError(expected?: unknown): R;
|
||||
|
||||
/* TODO: START snapshot matchers are not from `expect`, the types should not be here */
|
||||
/**
|
||||
* This ensures that a value matches the most recent snapshot with property matchers.
|
||||
* Check out [the Snapshot Testing guide](https://jestjs.io/docs/snapshot-testing) for more information.
|
||||
*/
|
||||
toMatchSnapshot<T extends {[P in keyof R]: unknown}>(
|
||||
propertyMatchers: Partial<T>,
|
||||
snapshotName?: string,
|
||||
): R;
|
||||
toMatchSnapshot(hint?: string): R;
|
||||
/**
|
||||
* This ensures that a value matches the most recent snapshot.
|
||||
* Check out [the Snapshot Testing guide](https://jestjs.io/docs/snapshot-testing) for more information.
|
||||
*/
|
||||
toMatchSnapshot(snapshotName?: string): R;
|
||||
/**
|
||||
* This ensures that a value matches the most recent snapshot with property matchers.
|
||||
* Instead of writing the snapshot value to a .snap file, it will be written into the source code automatically.
|
||||
* Check out [the Snapshot Testing guide](https://jestjs.io/docs/snapshot-testing) for more information.
|
||||
*/
|
||||
toMatchInlineSnapshot<T extends {[P in keyof R]: unknown}>(
|
||||
propertyMatchers: Partial<T>,
|
||||
snapshot?: string,
|
||||
toMatchSnapshot<U extends Record<keyof T, unknown>>(
|
||||
propertyMatchers: Partial<U>,
|
||||
hint?: string,
|
||||
): R;
|
||||
/**
|
||||
* This ensures that a value matches the most recent snapshot with property matchers.
|
||||
|
@ -353,10 +340,19 @@ export interface Matchers<R> {
|
|||
* Check out [the Snapshot Testing guide](https://jestjs.io/docs/snapshot-testing) for more information.
|
||||
*/
|
||||
toMatchInlineSnapshot(snapshot?: string): R;
|
||||
/**
|
||||
* This ensures that a value matches the most recent snapshot with property matchers.
|
||||
* Instead of writing the snapshot value to a .snap file, it will be written into the source code automatically.
|
||||
* Check out [the Snapshot Testing guide](https://jestjs.io/docs/snapshot-testing) for more information.
|
||||
*/
|
||||
toMatchInlineSnapshot<U extends Record<keyof T, unknown>>(
|
||||
propertyMatchers: Partial<U>,
|
||||
snapshot?: string,
|
||||
): R;
|
||||
/**
|
||||
* Used to test that a function throws a error matching the most recent snapshot when it is called.
|
||||
*/
|
||||
toThrowErrorMatchingSnapshot(): R;
|
||||
toThrowErrorMatchingSnapshot(hint?: string): R;
|
||||
/**
|
||||
* Used to test that a function throws a error matching the most recent snapshot when it is called.
|
||||
* Instead of writing the snapshot value to a .snap file, it will be written into the source code automatically.
|
||||
|
|
|
@ -0,0 +1,348 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @type ./empty.d.ts
|
||||
*/
|
||||
|
||||
import {expectError, expectType} from 'mlh-tsd';
|
||||
import {expect} from '@jest/globals';
|
||||
|
||||
// asymmetric matchers
|
||||
|
||||
expectType<void>(expect('value').toEqual(expect.any(String)));
|
||||
expectError(expect(123).toEqual(expect.any()));
|
||||
expectError(expect('value').toEqual(expect.not.any(Number)));
|
||||
|
||||
expectType<void>(expect(jest.fn()).toBeCalledWith(expect.anything()));
|
||||
expectError(expect(jest.fn()).toBeCalledWith(expect.anything(true)));
|
||||
expectError(expect(jest.fn()).toBeCalledWith(expect.not.anything()));
|
||||
|
||||
expectType<void>(expect(['A', 'B']).toEqual(expect.arrayContaining(['A'])));
|
||||
expectError(expect(['A']).toEqual(expect.arrayContaining('A')));
|
||||
expectError(expect(['A']).toEqual(expect.arrayContaining()));
|
||||
expectType<void>(expect(['B']).toEqual(expect.not.arrayContaining(['A'])));
|
||||
expectError(expect(['A']).toEqual(expect.not.arrayContaining('A')));
|
||||
expectError(expect(['A']).toEqual(expect.not.arrayContaining()));
|
||||
|
||||
expectType<void>(expect({a: 1}).toEqual(expect.objectContaining({a: 1})));
|
||||
expectError(expect({a: 1}).toEqual(expect.objectContaining(1)));
|
||||
expectError(expect({a: 1}).toEqual(expect.objectContaining()));
|
||||
expectType<void>(expect({b: 2}).toEqual(expect.not.objectContaining({a: 1})));
|
||||
expectError(expect({a: 1}).toEqual(expect.not.objectContaining(1)));
|
||||
expectError(expect({a: 1}).toEqual(expect.not.objectContaining()));
|
||||
|
||||
expectType<void>(expect('one').toEqual(expect.stringContaining('n')));
|
||||
expectError(expect('two').toEqual(expect.stringContaining(2)));
|
||||
expectError(expect('three').toEqual(expect.stringContaining()));
|
||||
expectType<void>(expect('one').toEqual(expect.not.stringContaining('m')));
|
||||
expectError(expect('two').toEqual(expect.not.stringContaining(2)));
|
||||
expectError(expect('three').toEqual(expect.not.stringContaining()));
|
||||
|
||||
expectType<void>(expect('one').toEqual(expect.stringMatching(/^[No]ne/)));
|
||||
expectError(expect('one').toEqual(expect.stringMatching(2)));
|
||||
expectError(expect('one').toEqual(expect.stringMatching()));
|
||||
expectType<void>(expect('two').toEqual(expect.not.stringMatching(/^[No]ne/)));
|
||||
expectError(expect('two').toEqual(expect.not.stringMatching(1)));
|
||||
expectError(expect('two').toEqual(expect.not.stringMatching()));
|
||||
|
||||
// chainers and utilities
|
||||
|
||||
expectType<void>(expect.assertions(2));
|
||||
expectError(expect.assertions());
|
||||
|
||||
expectType<void>(expect.hasAssertions());
|
||||
expectError(expect.hasAssertions(true));
|
||||
|
||||
expectType<Promise<void>>(
|
||||
expect(Promise.resolve('lemon')).resolves.toBe('lemon'),
|
||||
);
|
||||
|
||||
expectType<Promise<void>>(
|
||||
expect(Promise.reject(new Error('octopus'))).rejects.toThrow('octopus'),
|
||||
);
|
||||
|
||||
// equality and relational matchers
|
||||
|
||||
expectType<void>(expect(2).toBe(2));
|
||||
expectType<void>(expect('three').not.toBe('four'));
|
||||
expectError(expect(false).toBe());
|
||||
|
||||
expectType<void>(expect(0.2 + 0.1).toBeCloseTo(0.3));
|
||||
expectType<void>(expect(0.2 + 0.1).toBeCloseTo(0.3, 5));
|
||||
expectError(expect(0.2 + 0.1).toBeCloseTo());
|
||||
expectError(expect(0.2 + 0.1).toBeCloseTo('three'));
|
||||
expectError(expect(BigInt(0.2 + 0.1)).toBeCloseTo(BigInt(0.3)));
|
||||
expectError(expect(0.2 + 0.1).toBeCloseTo(0.3, false));
|
||||
|
||||
expectType<void>(expect('value').toBeDefined());
|
||||
expectError(expect(true).not.toBeDefined(false));
|
||||
|
||||
expectType<void>(expect(0).toBeFalsy());
|
||||
expectError(expect(true).not.toBeFalsy(true));
|
||||
|
||||
expectType<void>(expect(10).toBeGreaterThan(5));
|
||||
expectType<void>(expect(BigInt(5.65)).toBeGreaterThan(BigInt(5.61)));
|
||||
expectError(expect(10).toBeGreaterThan());
|
||||
expectError(expect(10).toBeGreaterThan('1'));
|
||||
|
||||
expectType<void>(expect(10).toBeGreaterThanOrEqual(5));
|
||||
expectType<void>(expect(BigInt(5.65)).toBeGreaterThanOrEqual(BigInt(5.61)));
|
||||
expectError(expect(10).toBeGreaterThanOrEqual());
|
||||
expectError(expect(10).toBeGreaterThanOrEqual('1'));
|
||||
|
||||
expectType<void>(expect(5).toBeLessThan(10));
|
||||
expectType<void>(expect(BigInt(5.61)).toBeLessThan(BigInt(5.65)));
|
||||
expectError(expect(1).toBeLessThan());
|
||||
expectError(expect(1).toBeLessThan('10'));
|
||||
|
||||
expectType<void>(expect(5).toBeLessThanOrEqual(10));
|
||||
expectType<void>(expect(BigInt(5.61)).toBeLessThanOrEqual(BigInt(5.65)));
|
||||
expectError(expect(1).toBeLessThanOrEqual());
|
||||
expectError(expect(1).toBeLessThanOrEqual('10'));
|
||||
|
||||
expectType<void>(expect(() => {}).toBeInstanceOf(Function));
|
||||
expectError(expect(() => {}).toBeInstanceOf());
|
||||
|
||||
expectType<void>(expect(Number('ten')).toBeNaN());
|
||||
expectError(expect(Number('10')).not.toBeNaN(true));
|
||||
|
||||
expectType<void>(expect(null).toBeNull());
|
||||
expectError(expect('not null').not.toBeNull(true));
|
||||
|
||||
expectType<void>(expect('true').toBeTruthy());
|
||||
expectError(expect(false).not.toBeTruthy(true));
|
||||
|
||||
expectType<void>(expect(undefined).toBeUndefined());
|
||||
expectError(expect('value').not.toBeUndefined(false));
|
||||
|
||||
expectType<void>(expect(['lemon', 'lime']).not.toContain('orange'));
|
||||
expectType<void>(expect('citrus fruits').toContain('fruit'));
|
||||
|
||||
const a = {key1: true, key2: false};
|
||||
expectType<void>(expect([{key1: true, key2: false}]).toContainEqual(a));
|
||||
|
||||
expectType<void>(expect({a: 1, b: undefined}).toEqual({a: 1}));
|
||||
expectError(expect({a: 1}).toEqual());
|
||||
|
||||
expectType<void>(expect({a: 1, b: 2}).toStrictEqual({a: 1, b: 2}));
|
||||
expectError(expect({a: 1}).toStrictEqual());
|
||||
|
||||
expectType<void>(expect([1, 2, 3]).toHaveLength(3));
|
||||
expectType<void>(expect('abc').not.toHaveLength(5));
|
||||
expectError(expect('abc').toHaveLength());
|
||||
|
||||
expectType<void>(
|
||||
expect({kitchen: {area: 20}}).toHaveProperty('kitchen.area', 20),
|
||||
);
|
||||
expectType<void>(
|
||||
expect({kitchen: {area: 20}}).not.toHaveProperty(['kitchen', 'color']),
|
||||
);
|
||||
expectError(expect({kitchen: {area: 20}}).toHaveProperty());
|
||||
expectError(expect({kitchen: {area: 20}}).toHaveProperty(true));
|
||||
|
||||
expectType<void>(expect('grapefruits').toMatch(/fruit/));
|
||||
expectType<void>(expect('grapefruits').toMatch('fruit'));
|
||||
expectError(expect('grapefruits').toMatch(true));
|
||||
|
||||
expectType<void>(expect({a: 1, b: 2}).toMatchObject({b: 2}));
|
||||
expectType<void>(
|
||||
expect([{a: 1}, {b: 2, c: true}]).toMatchObject([{a: 1}, {b: 2}]),
|
||||
);
|
||||
expectError(expect({c: true}).toMatchObject(true));
|
||||
expectError(expect({c: true}).toMatchObject());
|
||||
|
||||
// error matchers
|
||||
|
||||
expectType<void>(expect(() => {}).toThrow());
|
||||
expectType<void>(expect(() => {}).toThrow(/error/));
|
||||
expectType<void>(expect(() => {}).toThrow('error'));
|
||||
expectType<void>(expect(() => {}).toThrow(Error));
|
||||
expectType<void>(expect(() => {}).toThrow(new Error('error')));
|
||||
|
||||
expectType<void>(expect(() => {}).toThrowError());
|
||||
expectType<void>(expect(() => {}).toThrowError(/error/));
|
||||
expectType<void>(expect(() => {}).toThrowError('error'));
|
||||
expectType<void>(expect(() => {}).toThrowError(Error));
|
||||
expectType<void>(expect(() => {}).toThrowError(new Error('error')));
|
||||
|
||||
// mock matchers
|
||||
|
||||
expectType<void>(expect(jest.fn()).toBeCalled());
|
||||
expectError(expect(jest.fn()).toBeCalled('value'));
|
||||
expectType<void>(expect(jest.fn()).toHaveBeenCalled());
|
||||
expectError(expect(jest.fn()).toHaveBeenCalled(false));
|
||||
|
||||
expectType<void>(expect(jest.fn()).toBeCalledTimes(1));
|
||||
expectError(expect(jest.fn()).toBeCalledTimes('twice'));
|
||||
expectError(expect(jest.fn()).toBeCalledTimes());
|
||||
expectType<void>(expect(jest.fn()).toHaveBeenCalledTimes(3));
|
||||
expectError(expect(jest.fn()).toHaveBeenCalledTimes(true));
|
||||
expectError(expect(jest.fn()).toHaveBeenCalledTimes());
|
||||
|
||||
expectType<void>(expect(jest.fn()).toBeCalledWith('value'));
|
||||
expectType<void>(expect(jest.fn()).toBeCalledWith('value', 123));
|
||||
// expectError(expect(jest.fn()).toBeCalledWith());
|
||||
expectType<void>(expect(jest.fn()).toHaveBeenCalledWith(123));
|
||||
expectType<void>(expect(jest.fn()).toHaveBeenCalledWith(123, 'value'));
|
||||
// expectError(expect(jest.fn()).toHaveBeenCalledWith());
|
||||
|
||||
expectType<void>(expect(jest.fn()).lastCalledWith('value'));
|
||||
expectType<void>(expect(jest.fn()).lastCalledWith('value', 123));
|
||||
// expectError(expect(jest.fn()).lastCalledWith());
|
||||
expectType<void>(expect(jest.fn()).toHaveBeenLastCalledWith(123));
|
||||
expectType<void>(expect(jest.fn()).toHaveBeenLastCalledWith(123, 'value'));
|
||||
// expectError(expect(jest.fn()).toHaveBeenLastCalledWith());
|
||||
|
||||
expectType<void>(expect(jest.fn()).nthCalledWith(1, 'value'));
|
||||
expectType<void>(expect(jest.fn()).nthCalledWith(1, 'value', 123));
|
||||
// expectError(expect(jest.fn()).nthCalledWith());
|
||||
// expectError(expect(jest.fn()).nthCalledWith(2));
|
||||
expectType<void>(expect(jest.fn()).toHaveBeenNthCalledWith(1, 'value'));
|
||||
expectType<void>(expect(jest.fn()).toHaveBeenNthCalledWith(1, 'value', 123));
|
||||
// expectError(expect(jest.fn()).toHaveBeenNthCalledWith());
|
||||
// expectError(expect(jest.fn()).toHaveBeenNthCalledWith(2));
|
||||
|
||||
expectType<void>(expect(jest.fn()).toReturn());
|
||||
expectError(expect(jest.fn()).toReturn('value'));
|
||||
expectType<void>(expect(jest.fn()).toHaveReturned());
|
||||
expectError(expect(jest.fn()).toHaveReturned(false));
|
||||
|
||||
expectType<void>(expect(jest.fn()).toReturnTimes(1));
|
||||
expectError(expect(jest.fn()).toReturnTimes('twice'));
|
||||
expectError(expect(jest.fn()).toReturnTimes());
|
||||
expectType<void>(expect(jest.fn()).toHaveReturnedTimes(3));
|
||||
expectError(expect(jest.fn()).toHaveReturnedTimes(true));
|
||||
expectError(expect(jest.fn()).toHaveReturnedTimes());
|
||||
|
||||
expectType<void>(expect(jest.fn()).toReturnWith('value'));
|
||||
expectError(expect(jest.fn()).toReturnWith());
|
||||
expectType<void>(expect(jest.fn()).toHaveReturnedWith(123));
|
||||
expectError(expect(jest.fn()).toHaveReturnedWith());
|
||||
|
||||
expectType<void>(expect(jest.fn()).lastReturnedWith('value'));
|
||||
expectError(expect(jest.fn()).lastReturnedWith());
|
||||
expectType<void>(expect(jest.fn()).toHaveLastReturnedWith(123));
|
||||
expectError(expect(jest.fn()).toHaveLastReturnedWith());
|
||||
|
||||
expectType<void>(expect(jest.fn()).nthReturnedWith(1, 'value'));
|
||||
expectError(expect(jest.fn()).nthReturnedWith());
|
||||
expectError(expect(jest.fn()).nthReturnedWith(2));
|
||||
expectType<void>(expect(jest.fn()).toHaveNthReturnedWith(1, 'value'));
|
||||
expectError(expect(jest.fn()).toHaveNthReturnedWith());
|
||||
expectError(expect(jest.fn()).toHaveNthReturnedWith(2));
|
||||
|
||||
// snapshot matchers
|
||||
|
||||
expectType<void>(expect({a: 1}).toMatchSnapshot());
|
||||
expectType<void>(expect({a: 1}).toMatchSnapshot('hint'));
|
||||
expectError(expect({a: 1}).toMatchSnapshot(true));
|
||||
|
||||
expectType<void>(
|
||||
expect({
|
||||
date: new Date(),
|
||||
name: 'John Doe',
|
||||
}).toMatchSnapshot({
|
||||
date: expect.any(Date),
|
||||
name: expect.any(String),
|
||||
}),
|
||||
);
|
||||
|
||||
expectType<void>(
|
||||
expect({
|
||||
date: new Date(),
|
||||
name: 'John Doe',
|
||||
}).toMatchSnapshot(
|
||||
{
|
||||
date: expect.any(Date),
|
||||
name: expect.any(String),
|
||||
},
|
||||
'hint',
|
||||
),
|
||||
);
|
||||
|
||||
expectError(
|
||||
expect({
|
||||
date: new Date(),
|
||||
name: 'John Doe',
|
||||
}).toMatchSnapshot({
|
||||
date: expect.any(Date),
|
||||
time: expect.any(Date),
|
||||
}),
|
||||
);
|
||||
|
||||
expectType<void>(expect('abc').toMatchInlineSnapshot());
|
||||
expectType<void>(expect('abc').toMatchInlineSnapshot('inline snapshot here'));
|
||||
expectError(expect('abc').toMatchInlineSnapshot(true));
|
||||
|
||||
expectType<void>(
|
||||
expect({
|
||||
date: new Date(),
|
||||
name: 'John Doe',
|
||||
}).toMatchInlineSnapshot({
|
||||
date: expect.any(Date),
|
||||
name: expect.any(String),
|
||||
}),
|
||||
);
|
||||
|
||||
expectType<void>(
|
||||
expect({
|
||||
date: new Date(),
|
||||
name: 'John Doe',
|
||||
}).toMatchInlineSnapshot(
|
||||
{
|
||||
date: expect.any(Date),
|
||||
name: expect.any(String),
|
||||
},
|
||||
'inline snapshot here',
|
||||
),
|
||||
);
|
||||
|
||||
expectError(
|
||||
expect({
|
||||
date: new Date(),
|
||||
name: 'John Doe',
|
||||
}).toMatchInlineSnapshot({
|
||||
date: expect.any(Date),
|
||||
time: expect.any(Date),
|
||||
}),
|
||||
);
|
||||
|
||||
expectType<void>(expect(jest.fn()).toThrowErrorMatchingSnapshot());
|
||||
expectType<void>(expect(jest.fn()).toThrowErrorMatchingSnapshot('hint'));
|
||||
expectError(expect(jest.fn()).toThrowErrorMatchingSnapshot(true));
|
||||
|
||||
expectType<void>(expect(jest.fn()).toThrowErrorMatchingInlineSnapshot());
|
||||
expectType<void>(
|
||||
expect(jest.fn()).toThrowErrorMatchingInlineSnapshot('inline snapshot here'),
|
||||
);
|
||||
expectError(expect(jest.fn()).toThrowErrorMatchingInlineSnapshot(true));
|
||||
|
||||
// extend
|
||||
|
||||
expectType<void>(
|
||||
expect.extend({
|
||||
toBeDivisibleBy(actual: number, expected: number) {
|
||||
expectType<boolean>(this.isNot);
|
||||
|
||||
const pass = actual % expected === 0;
|
||||
const message = pass
|
||||
? () =>
|
||||
`expected ${this.utils.printReceived(
|
||||
actual,
|
||||
)} not to be divisible by ${expected}`
|
||||
: () =>
|
||||
`expected ${this.utils.printReceived(
|
||||
actual,
|
||||
)} to be divisible by ${expected}`;
|
||||
|
||||
return {message, pass};
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// TODO
|
||||
// expect(4).toBeDivisibleBy(2);
|
||||
// expect.toBeDivisibleBy(2);
|
|
@ -14,7 +14,6 @@ import {
|
|||
beforeAll,
|
||||
beforeEach,
|
||||
describe,
|
||||
expect,
|
||||
test,
|
||||
} from '@jest/globals';
|
||||
import type {Global} from '@jest/types';
|
||||
|
@ -109,42 +108,3 @@ expectType<void>(describe.only.each(testTable)(testName, fn));
|
|||
expectType<void>(describe.only.each(testTable)(testName, fn, timeout));
|
||||
expectType<void>(describe.skip.each(testTable)(testName, fn));
|
||||
expectType<void>(describe.skip.each(testTable)(testName, fn, timeout));
|
||||
|
||||
/// expect
|
||||
|
||||
expectType<void>(expect(2).toBe(2));
|
||||
expectType<Promise<void>>(expect(2).resolves.toBe(2));
|
||||
|
||||
expectType<void>(expect(() => {}).toThrow());
|
||||
expectType<void>(expect(() => {}).toThrow(/error/));
|
||||
expectType<void>(expect(() => {}).toThrow('error'));
|
||||
expectType<void>(expect(() => {}).toThrow(Error));
|
||||
expectType<void>(expect(() => {}).toThrow(new Error('error')));
|
||||
|
||||
expectType<void>(expect('Hello').toEqual(expect.any(String)));
|
||||
|
||||
// this currently does not error due to `[id: string]` in ExtraAsymmetricMatchers - we should have nothing there and force people to use interface merging
|
||||
// expectError(expect('Hello').toEqual(expect.not.any(Number)));
|
||||
|
||||
expectType<void>(
|
||||
expect.extend({
|
||||
toBeDivisibleBy(actual: number, expected: number) {
|
||||
expectType<boolean>(this.isNot);
|
||||
|
||||
const pass = actual % expected === 0;
|
||||
const message = pass
|
||||
? () =>
|
||||
`expected ${this.utils.printReceived(
|
||||
actual,
|
||||
)} not to be divisible by ${expected}`
|
||||
: () =>
|
||||
`expected ${this.utils.printReceived(
|
||||
actual,
|
||||
)} to be divisible by ${expected}`;
|
||||
|
||||
return {message, pass};
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// TODO: some way of calling `expect(4).toBeDivisbleBy(2)` and `expect.toBeDivisbleBy(2)`
|
||||
|
|
Loading…
Reference in New Issue