From 7ff1b1dc6fc250948bbbeb49c1700c33fd1d9ede Mon Sep 17 00:00:00 2001 From: Franck Royer Date: Thu, 30 Apr 2020 10:31:25 +1000 Subject: [PATCH] Update comparison methods to support BigInt As per https://github.com/facebook/jest/pull/8382 TypeScript 3.2+ supports BigInt with esnext target. TypeScript 3.8+ supports it with es2020 target. dtslint is very particular on how the `typesVersions` should be handled, hence the code duplication. --- types/jest/package.json | 5 + types/jest/ts3.2/index.d.ts | 1466 ++++++++++++++++++++++++++++++++ types/jest/ts3.2/jest-tests.ts | 1448 +++++++++++++++++++++++++++++++ types/jest/ts3.2/tsconfig.json | 20 + types/jest/ts3.2/tslint.json | 6 + types/jest/ts3.8/index.d.ts | 1466 ++++++++++++++++++++++++++++++++ types/jest/ts3.8/jest-tests.ts | 1448 +++++++++++++++++++++++++++++++ types/jest/ts3.8/tsconfig.json | 20 + types/jest/ts3.8/tslint.json | 6 + 9 files changed, 5885 insertions(+) create mode 100644 types/jest/ts3.2/index.d.ts create mode 100644 types/jest/ts3.2/jest-tests.ts create mode 100644 types/jest/ts3.2/tsconfig.json create mode 100644 types/jest/ts3.2/tslint.json create mode 100644 types/jest/ts3.8/index.d.ts create mode 100644 types/jest/ts3.8/jest-tests.ts create mode 100644 types/jest/ts3.8/tsconfig.json create mode 100644 types/jest/ts3.8/tslint.json diff --git a/types/jest/package.json b/types/jest/package.json index d2dd38a8831b4ed..45bcfcc4d4e2a56 100644 --- a/types/jest/package.json +++ b/types/jest/package.json @@ -3,5 +3,10 @@ "dependencies": { "jest-diff": "^25.2.1", "pretty-format": "^25.2.1" + }, + "types": "index", + "typesVersions": { + ">=3.8.0-0": { "*": ["ts3.8/*"] }, + ">=3.2.0-0": { "*": ["ts3.2/*"] } } } diff --git a/types/jest/ts3.2/index.d.ts b/types/jest/ts3.2/index.d.ts new file mode 100644 index 000000000000000..59c85752f824720 --- /dev/null +++ b/types/jest/ts3.2/index.d.ts @@ -0,0 +1,1466 @@ +declare var beforeAll: jest.Lifecycle; +declare var beforeEach: jest.Lifecycle; +declare var afterAll: jest.Lifecycle; +declare var afterEach: jest.Lifecycle; +declare var describe: jest.Describe; +declare var fdescribe: jest.Describe; +declare var xdescribe: jest.Describe; +declare var it: jest.It; +declare var fit: jest.It; +declare var xit: jest.It; +declare var test: jest.It; +declare var xtest: jest.It; + +declare const expect: jest.Expect; + +type ExtractEachCallbackArgs> = { + 1: [T[0]], + 2: [T[0], T[1]], + 3: [T[0], T[1], T[2]], + 4: [T[0], T[1], T[2], T[3]], + 5: [T[0], T[1], T[2], T[3], T[4]], + 6: [T[0], T[1], T[2], T[3], T[4], T[5]], + 7: [T[0], T[1], T[2], T[3], T[4], T[5], T[6]], + 8: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7]], + 9: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8]], + 10: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9]], + 'fallback': Array<(T extends ReadonlyArray? U: any)> +}[ + T extends Readonly<[any]> ? 1 + : T extends Readonly<[any, any]> ? 2 + : T extends Readonly<[any, any, any]> ? 3 + : T extends Readonly<[any, any, any, any]> ? 4 + : T extends Readonly<[any, any, any, any, any]> ? 5 + : T extends Readonly<[any, any, any, any, any, any]> ? 6 + : T extends Readonly<[any, any, any, any, any, any, any]> ? 7 + : T extends Readonly<[any, any, any, any, any, any, any, any]> ? 8 + : T extends Readonly<[any, any, any, any, any, any, any, any, any]> ? 9 + : T extends Readonly<[any, any, any, any, any, any, any, any, any, any]> ? 10 + : 'fallback' +]; + +interface NodeRequire { + /** + * Returns the actual module instead of a mock, bypassing all checks on + * whether the module should receive a mock implementation or not. + * + * @deprecated Use `jest.requireActual` instead. + */ + requireActual(moduleName: string): any; + /** + * Returns a mock module instead of the actual module, bypassing all checks + * on whether the module should be required normally or not. + * + * @deprecated Use `jest.requireMock`instead. + */ + requireMock(moduleName: string): any; +} + +declare namespace jest { + /** + * Provides a way to add Jasmine-compatible matchers into your Jest context. + */ + function addMatchers(matchers: jasmine.CustomMatcherFactories): typeof jest; + /** + * Disables automatic mocking in the module loader. + */ + function autoMockOff(): typeof jest; + /** + * Enables automatic mocking in the module loader. + */ + function autoMockOn(): typeof jest; + /** + * Clears the mock.calls and mock.instances properties of all mocks. + * Equivalent to calling .mockClear() on every mocked function. + */ + function clearAllMocks(): typeof jest; + /** + * Resets the state of all mocks. + * Equivalent to calling .mockReset() on every mocked function. + */ + function resetAllMocks(): typeof jest; + /** + * available since Jest 21.1.0 + * Restores all mocks back to their original value. + * Equivalent to calling .mockRestore on every mocked function. + * Beware that jest.restoreAllMocks() only works when mock was created with + * jest.spyOn; other mocks will require you to manually restore them. + */ + function restoreAllMocks(): typeof jest; + /** + * Removes any pending timers from the timer system. If any timers have + * been scheduled, they will be cleared and will never have the opportunity + * to execute in the future. + */ + function clearAllTimers(): typeof jest; + /** + * Returns the number of fake timers still left to run. + */ + function getTimerCount(): number; + /** + * Indicates that the module system should never return a mocked version + * of the specified module, including all of the specificied module's dependencies. + */ + function deepUnmock(moduleName: string): typeof jest; + /** + * Disables automatic mocking in the module loader. + */ + function disableAutomock(): typeof jest; + /** + * Mocks a module with an auto-mocked version when it is being required. + */ + function doMock(moduleName: string, factory?: () => unknown, options?: MockOptions): typeof jest; + /** + * Indicates that the module system should never return a mocked version + * of the specified module from require() (e.g. that it should always return the real module). + */ + function dontMock(moduleName: string): typeof jest; + /** + * Enables automatic mocking in the module loader. + */ + function enableAutomock(): typeof jest; + /** + * Creates a mock function. Optionally takes a mock implementation. + */ + function fn(): Mock; + /** + * Creates a mock function. Optionally takes a mock implementation. + */ + function fn(implementation?: (...args: Y) => T): Mock; + /** + * Use the automatic mocking system to generate a mocked version of the given module. + */ + function genMockFromModule(moduleName: string): T; + /** + * Returns whether the given function is a mock function. + */ + function isMockFunction(fn: any): fn is Mock; + /** + * Mocks a module with an auto-mocked version when it is being required. + */ + function mock(moduleName: string, factory?: () => unknown, options?: MockOptions): typeof jest; + /** + * Returns the actual module instead of a mock, bypassing all checks on + * whether the module should receive a mock implementation or not. + */ + function requireActual(moduleName: string): any; + /** + * Returns a mock module instead of the actual module, bypassing all checks + * on whether the module should be required normally or not. + */ + function requireMock(moduleName: string): any; + /** + * Resets the module registry - the cache of all required modules. This is + * useful to isolate modules where local state might conflict between tests. + */ + function resetModuleRegistry(): typeof jest; + /** + * Resets the module registry - the cache of all required modules. This is + * useful to isolate modules where local state might conflict between tests. + */ + function resetModules(): typeof jest; + /** + * Creates a sandbox registry for the modules that are loaded inside the callback function.. + * This is useful to isolate specific modules for every test so that local module state doesn't conflict between tests. + */ + function isolateModules(fn: () => void): typeof jest; + /** + * Runs failed tests n-times until they pass or until the max number of retries is exhausted. + * This only works with jest-circus! + */ + function retryTimes(numRetries: number): typeof jest; + /** + * Exhausts tasks queued by setImmediate(). + */ + function runAllImmediates(): typeof jest; + /** + * Exhausts the micro-task queue (usually interfaced in node via process.nextTick). + */ + function runAllTicks(): typeof jest; + /** + * Exhausts the macro-task queue (i.e., all tasks queued by setTimeout() and setInterval()). + */ + function runAllTimers(): typeof jest; + /** + * Executes only the macro-tasks that are currently pending (i.e., only the + * tasks that have been queued by setTimeout() or setInterval() up to this point). + * If any of the currently pending macro-tasks schedule new macro-tasks, + * those new tasks will not be executed by this call. + */ + function runOnlyPendingTimers(): typeof jest; + /** + * (renamed to `advanceTimersByTime` in Jest 21.3.0+) Executes only the macro + * task queue (i.e. all tasks queued by setTimeout() or setInterval() and setImmediate()). + */ + function runTimersToTime(msToRun: number): typeof jest; + /** + * Advances all timers by msToRun milliseconds. All pending "macro-tasks" that have been + * queued via setTimeout() or setInterval(), and would be executed within this timeframe + * will be executed. + */ + function advanceTimersByTime(msToRun: number): typeof jest; + /** + * Advances all timers by the needed milliseconds so that only the next + * timeouts/intervals will run. Optionally, you can provide steps, so it + * will run steps amount of next timeouts/intervals. + */ + function advanceTimersToNextTimer(step?: number): void; + /** + * Explicitly supplies the mock object that the module system should return + * for the specified module. + */ + function setMock(moduleName: string, moduleExports: T): typeof jest; + /** + * Set the default timeout interval for tests and before/after hooks in milliseconds. + * Note: The default timeout interval is 5 seconds if this method is not called. + */ + function setTimeout(timeout: number): typeof jest; + /** + * Creates a mock function similar to jest.fn but also tracks calls to `object[methodName]` + * + * Note: By default, jest.spyOn also calls the spied method. This is different behavior from most + * other test libraries. + * + * @example + * + * const video = require('./video'); + * + * test('plays video', () => { + * const spy = jest.spyOn(video, 'play'); + * const isPlaying = video.play(); + * + * expect(spy).toHaveBeenCalled(); + * expect(isPlaying).toBe(true); + * + * spy.mockReset(); + * spy.mockRestore(); + * }); + */ + function spyOn>>( + object: T, + method: M, + accessType: 'get' + ): SpyInstance[M], []>; + function spyOn>>( + object: T, + method: M, + accessType: 'set' + ): SpyInstance[M]]>; + function spyOn>>( + object: T, + method: M + ): Required[M] extends (...args: any[]) => any + ? SpyInstance[M]>, ArgsType[M]>> + : never; + function spyOn>>( + object: T, + method: M + ): Required[M] extends new (...args: any[]) => any + ? SpyInstance[M]>, ConstructorArgsType[M]>> + : never; + /** + * Indicates that the module system should never return a mocked version of + * the specified module from require() (e.g. that it should always return the real module). + */ + function unmock(moduleName: string): typeof jest; + /** + * Instructs Jest to use fake versions of the standard timer functions. + */ + function useFakeTimers(): typeof jest; + /** + * Instructs Jest to use the real versions of the standard timer functions. + */ + function useRealTimers(): typeof jest; + + interface MockOptions { + virtual?: boolean; + } + + type EmptyFunction = () => void; + type ArgsType = T extends (...args: infer A) => any ? A : never; + type ConstructorArgsType = T extends new (...args: infer A) => any ? A : never; + type RejectedValue = T extends PromiseLike ? any : never; + type ResolvedValue = T extends PromiseLike ? U | T : never; + // see https://github.com/Microsoft/TypeScript/issues/25215 + type NonFunctionPropertyNames = { [K in keyof T]: T[K] extends (...args: any[]) => any ? never : K }[keyof T] & + string; + type FunctionPropertyNames = { [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never }[keyof T] & + string; + type ConstructorPropertyNames = { [K in keyof T]: T[K] extends new (...args: any[]) => any ? K : never }[keyof T] & + string; + + interface DoneCallback { + (...args: any[]): any; + fail(error?: string | { message: string }): any; + } + + type ProvidesCallback = (cb: DoneCallback) => any; + + type Lifecycle = (fn: ProvidesCallback, timeout?: number) => any; + + interface FunctionLike { + readonly name: string; + } + + interface Each { + // Exclusively arrays. + (cases: ReadonlyArray): (name: string, fn: (...args: T) => any, timeout?: number) => void; + >(cases: ReadonlyArray): (name: string, fn: (...args: ExtractEachCallbackArgs) => any, timeout?: number) => void; + // Not arrays. + (cases: ReadonlyArray): (name: string, fn: (...args: T[]) => any, timeout?: number) => void; + (cases: ReadonlyArray>): ( + name: string, + fn: (...args: any[]) => any, + timeout?: number + ) => void; + (strings: TemplateStringsArray, ...placeholders: any[]): ( + name: string, + fn: (arg: any) => any, + timeout?: number + ) => void; + } + + /** + * Creates a test closure + */ + interface It { + /** + * Creates a test closure. + * + * @param name The name of your test + * @param fn The function for your test + * @param timeout The timeout for an async function test + */ + (name: string, fn?: ProvidesCallback, timeout?: number): void; + /** + * Only runs this test in the current file. + */ + only: It; + /** + * Skips running this test in the current file. + */ + skip: It; + /** + * Sketch out which tests to write in the future. + */ + todo: It; + /** + * Experimental and should be avoided. + */ + concurrent: It; + /** + * Use if you keep duplicating the same test with different data. `.each` allows you to write the + * test once and pass data in. + * + * `.each` is available with two APIs: + * + * #### 1 `test.each(table)(name, fn)` + * + * - `table`: Array of Arrays with the arguments that are passed into the test fn for each row. + * - `name`: String the title of the test block. + * - `fn`: Function the test to be ran, this is the function that will receive the parameters in each row as function arguments. + * + * + * #### 2 `test.each table(name, fn)` + * + * - `table`: Tagged Template Literal + * - `name`: String the title of the test, use `$variable` to inject test data into the test title from the tagged template expressions. + * - `fn`: Function the test to be ran, this is the function that will receive the test data object.. + * + * @example + * + * // API 1 + * test.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])( + * '.add(%i, %i)', + * (a, b, expected) => { + * expect(a + b).toBe(expected); + * }, + * ); + * + * // API 2 + * test.each` + * a | b | expected + * ${1} | ${1} | ${2} + * ${1} | ${2} | ${3} + * ${2} | ${1} | ${3} + * `('returns $expected when $a is added $b', ({a, b, expected}) => { + * expect(a + b).toBe(expected); + * }); + * + */ + each: Each; + } + + interface Describe { + // tslint:disable-next-line ban-types + (name: number | string | Function | FunctionLike, fn: EmptyFunction): void; + /** Only runs the tests inside this `describe` for the current file */ + only: Describe; + /** Skips running the tests inside this `describe` for the current file */ + skip: Describe; + each: Each; + } + + type PrintLabel = (string: string) => string; + + type MatcherHintColor = (arg: string) => string; + + interface MatcherHintOptions { + comment?: string; + expectedColor?: MatcherHintColor; + isDirectExpectCall?: boolean; + isNot?: boolean; + promise?: string; + receivedColor?: MatcherHintColor; + secondArgument?: string; + secondArgumentColor?: MatcherHintColor; + } + + interface ChalkFunction { + (text: TemplateStringsArray, ...placeholders: any[]): string; + (...text: any[]): string; + } + + interface ChalkColorSupport { + level: 0 | 1 | 2 | 3; + hasBasic: boolean; + has256: boolean; + has16m: boolean; + } + + type MatcherColorFn = ChalkFunction & { supportsColor: ChalkColorSupport }; + + type EqualityTester = (a: any, b: any) => boolean | undefined; + + interface MatcherUtils { + readonly isNot: boolean; + readonly dontThrow: () => void; + readonly promise: string; + readonly assertionCalls: number; + readonly expectedAssertionsNumber: number | null; + readonly isExpectingAssertions: boolean; + readonly suppressedErrors: any[]; + readonly expand: boolean; + readonly testPath: string; + readonly currentTestName: string; + utils: { + readonly EXPECTED_COLOR: MatcherColorFn; + readonly RECEIVED_COLOR: MatcherColorFn; + readonly INVERTED_COLOR: MatcherColorFn; + readonly BOLD_WEIGHT: MatcherColorFn; + readonly DIM_COLOR: MatcherColorFn; + readonly SUGGEST_TO_CONTAIN_EQUAL: string; + diff(a: any, b: any, options?: import("jest-diff").DiffOptions): string | null; + ensureActualIsNumber(actual: any, matcherName: string, options?: MatcherHintOptions): void; + ensureExpectedIsNumber(actual: any, matcherName: string, options?: MatcherHintOptions): void; + ensureNoExpected(actual: any, matcherName: string, options?: MatcherHintOptions): void; + ensureNumbers(actual: any, expected: any, matcherName: string, options?: MatcherHintOptions): void; + ensureExpectedIsNonNegativeInteger(expected: any, matcherName: string, options?: MatcherHintOptions): void; + matcherHint( + matcherName: string, + received?: string, + expected?: string, + options?: MatcherHintOptions + ): string; + matcherErrorMessage( + hint: string, + generic: string, + specific: string + ): string; + pluralize(word: string, count: number): string; + printReceived(object: any): string; + printExpected(value: any): string; + printWithType(name: string, value: any, print: (value: any) => string): string; + stringify(object: {}, maxDepth?: number): string; + highlightTrailingWhitespace(text: string): string; + + printDiffOrStringify(expected: any, received: any, expectedLabel: string, receivedLabel: string, expand: boolean): string; + + getLabelPrinter(...strings: string[]): PrintLabel; + + iterableEquality: EqualityTester; + subsetEquality: EqualityTester; + }; + /** + * This is a deep-equality function that will return true if two objects have the same values (recursively). + */ + equals(a: any, b: any, customTesters?: EqualityTester[], strictCheck?: boolean): boolean; + [other: string]: any; + } + + interface ExpectExtendMap { + [key: string]: CustomMatcher; + } + + type MatcherContext = MatcherUtils & Readonly; + type CustomMatcher = ( + this: MatcherContext, + received: any, + ...actual: any[] + ) => CustomMatcherResult | Promise; + + interface CustomMatcherResult { + pass: boolean; + message: () => string; + } + + type SnapshotSerializerPlugin = import('pretty-format').Plugin; + + interface InverseAsymmetricMatchers { + /** + * `expect.not.arrayContaining(array)` matches a received array which + * does not contain all of the elements in the expected array. That is, + * the expected array is not a subset of the received array. It is the + * inverse of `expect.arrayContaining`. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: E[]): any; + /** + * `expect.not.objectContaining(object)` matches any received object + * that does not recursively match the expected properties. That is, the + * expected object is not a subset of the received object. Therefore, + * it matches a received object which contains properties that are not + * in the expected object. It is the inverse of `expect.objectContaining`. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: E): any; + /** + * `expect.not.stringMatching(string | regexp)` matches the received + * string that does not match the expected regexp. It is the inverse of + * `expect.stringMatching`. + */ + stringMatching(str: string | RegExp): any; + /** + * `expect.not.stringContaining(string)` matches the received string + * that does not contain the exact expected string. It is the inverse of + * `expect.stringContaining`. + */ + stringContaining(str: string): any; + } + interface MatcherState { + assertionCalls: number; + currentTestName: string; + expand: boolean; + expectedAssertionsNumber: number; + isExpectingAssertions?: boolean; + suppressedErrors: Error[]; + testPath: string; + } + /** + * The `expect` function is used every time you want to test a value. + * You will rarely call `expect` by itself. + */ + interface Expect { + /** + * The `expect` function is used every time you want to test a value. + * You will rarely call `expect` by itself. + * + * @param actual The value to apply matchers against. + */ + (actual: T): JestMatchers; + /** + * Matches anything but null or undefined. You can use it inside `toEqual` or `toBeCalledWith` instead + * of a literal value. For example, if you want to check that a mock function is called with a + * non-null argument: + * + * @example + * + * test('map calls its argument with a non-null argument', () => { + * const mock = jest.fn(); + * [1].map(x => mock(x)); + * expect(mock).toBeCalledWith(expect.anything()); + * }); + * + */ + anything(): any; + /** + * Matches anything that was created with the given constructor. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * @example + * + * function randocall(fn) { + * return fn(Math.floor(Math.random() * 6 + 1)); + * } + * + * test('randocall calls its callback with a number', () => { + * const mock = jest.fn(); + * randocall(mock); + * expect(mock).toBeCalledWith(expect.any(Number)); + * }); + */ + any(classType: any): any; + /** + * Matches any array made up entirely of elements in the provided array. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: E[]): any; + /** + * Verifies that a certain number of assertions are called during a test. + * This is often useful when testing asynchronous code, in order to + * make sure that assertions in a callback actually got called. + */ + assertions(num: number): void; + /** + * Verifies that at least one assertion is called during a test. + * This is often useful when testing asynchronous code, in order to + * make sure that assertions in a callback actually got called. + */ + hasAssertions(): void; + /** + * You can use `expect.extend` to add your own matchers to Jest. + */ + extend(obj: ExpectExtendMap): void; + /** + * Adds a module to format application-specific data structures for serialization. + */ + addSnapshotSerializer(serializer: SnapshotSerializerPlugin): void; + /** + * Matches any object that recursively matches the provided keys. + * This is often handy in conjunction with other asymmetric matchers. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: E): any; + /** + * Matches any string that contains the exact provided string + */ + stringMatching(str: string | RegExp): any; + /** + * Matches any received string that contains the exact expected string + */ + stringContaining(str: string): any; + + not: InverseAsymmetricMatchers; + + setState(state: object): void; + getState(): MatcherState & Record; + } + + type JestMatchers = JestMatchersShape, Matchers, T>>; + + type JestMatchersShape = { + /** + * 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: AndNot, + /** + * Unwraps the reason of a rejected promise so any other matcher can be chained. + * If the promise is fulfilled the assertion fails. + */ + rejects: AndNot + } & AndNot; + type AndNot = T & { + not: T + }; + // should be R extends void|Promise but getting dtslint error + interface Matchers { + /** + * Ensures the last call to a mock function was provided specific args. + * + * Optionally, you can provide a type for the expected arguments via a generic. + * Note that the type must be either an array or a tuple. + */ + lastCalledWith(...args: E): R; + /** + * Ensure that the last call to a mock function has returned a specified value. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + lastReturnedWith(value: E): R; + /** + * Ensure that a mock function is called with specific arguments on an Nth call. + * + * Optionally, you can provide a type for the expected arguments via a generic. + * Note that the type must be either an array or a tuple. + */ + nthCalledWith(nthCall: number, ...params: E): R; + /** + * Ensure that the nth call to a mock function has returned a specified value. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + nthReturnedWith(n: number, value: E): R; + /** + * Checks that a value is what you expect. It uses `Object.is` to check strict equality. + * Don't use `toBe` with floating-point numbers. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toBe(expected: E): R; + /** + * Ensures that a mock function is called. + */ + toBeCalled(): R; + /** + * Ensures that a mock function is called an exact number of times. + */ + toBeCalledTimes(expected: number): R; + /** + * Ensure that a mock function is called with specific arguments. + * + * Optionally, you can provide a type for the expected arguments via a generic. + * Note that the type must be either an array or a tuple. + */ + toBeCalledWith(...args: E): R; + /** + * Using exact equality with floating point numbers is a bad idea. + * Rounding means that intuitive things fail. + * The default for numDigits is 2. + */ + toBeCloseTo(expected: number, numDigits?: number): R; + /** + * Ensure that a variable is not undefined. + */ + toBeDefined(): R; + /** + * When you don't care what a value is, you just want to + * ensure a value is false in a boolean context. + */ + toBeFalsy(): R; + /** + * For comparing numbers or big integer values. + */ + toBeGreaterThan(expected: number | bigint): R; + /** + * For comparing numbers or big integer values. + */ + toBeGreaterThanOrEqual(expected: number | bigint): R; + /** + * Ensure that an object is an instance of a class. + * This matcher uses `instanceof` underneath. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toBeInstanceOf(expected: E): R; + /** + * For comparing numbers or big integer values. + */ + toBeLessThan(expected: number | bigint): R; + /** + * For comparing numbers or big integer values. + */ + toBeLessThanOrEqual(expected: number | bigint): R; + /** + * 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. + */ + toBeNull(): R; + /** + * 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. + */ + toBeTruthy(): R; + /** + * Used to check that a variable is undefined. + */ + toBeUndefined(): R; + /** + * Used to check that a variable is NaN. + */ + toBeNaN(): R; + /** + * 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. + * It can also check whether a string is a substring of another string. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toContain(expected: E): R; + /** + * 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. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toContainEqual(expected: E): R; + /** + * 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. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toEqual(expected: E): R; + /** + * Ensures that a mock function is called. + */ + toHaveBeenCalled(): R; + /** + * Ensures that a mock function is called an exact number of times. + */ + toHaveBeenCalledTimes(expected: number): R; + /** + * Ensure that a mock function is called with specific arguments. + * + * Optionally, you can provide a type for the expected arguments via a generic. + * Note that the type must be either an array or a tuple. + */ + toHaveBeenCalledWith(...params: E): R; + /** + * Ensure that a mock function is called with specific arguments on an Nth call. + * + * Optionally, you can provide a type for the expected arguments via a generic. + * Note that the type must be either an array or a tuple. + */ + toHaveBeenNthCalledWith(nthCall: number, ...params: E): R; + /** + * If you have a mock function, you can use `.toHaveBeenLastCalledWith` + * to test what arguments it was last called with. + * + * Optionally, you can provide a type for the expected arguments via a generic. + * Note that the type must be either an array or a tuple. + */ + toHaveBeenLastCalledWith(...params: E): 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 + * no matter what value you provided as the expected return value. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toHaveLastReturnedWith(expected: E): R; + /** + * Used to check that an object has a `.length` property + * and it is set to a certain numeric value. + */ + toHaveLength(expected: number): R; + /** + * 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. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toHaveNthReturnedWith(nthCall: number, expected: E): 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 + * the keyPath for deep references. + * + * Optionally, you can provide a value to check if it's equal to the value present at keyPath + * on the target object. This matcher uses 'deep equality' (like `toEqual()`) and recursively checks + * the equality of all fields. + * + * @example + * + * expect(houseForSale).toHaveProperty('kitchen.area', 20); + */ + toHaveProperty(propertyPath: string | any[], value?: E): R; + /** + * Use to test that the mock function successfully returned (i.e., did not throw an error) at least one time + */ + toHaveReturned(): R; + /** + * 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. + */ + toHaveReturnedTimes(expected: number): R; + /** + * Use to ensure that a mock function returned a specific value. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toHaveReturnedWith(expected: E): R; + /** + * Check that a string matches a regular expression. + */ + toMatch(expected: string | RegExp): R; + /** + * Used to check that a JavaScript object matches a subset of the properties of an object + * + * Optionally, you can provide an object to use as Generic type for the expected value. + * This ensures that the matching object matches the structure of the provided object-like type. + * + * @example + * + * type House = { + * bath: boolean; + * bedrooms: number; + * kitchen: { + * amenities: string[]; + * area: number; + * wallColor: string; + * } + * }; + * + * expect(desiredHouse).toMatchObject(...standardHouse, kitchen: {area: 20}) // wherein standardHouse is some base object of type House + */ + toMatchObject(expected: E): R; + /** + * This ensures that a value matches the most recent snapshot with property matchers. + * Check out [the Snapshot Testing guide](http://facebook.github.io/jest/docs/snapshot-testing.html) for more information. + */ + toMatchSnapshot(propertyMatchers: Partial, snapshotName?: string): R; + /** + * This ensures that a value matches the most recent snapshot. + * Check out [the Snapshot Testing guide](http://facebook.github.io/jest/docs/snapshot-testing.html) 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](http://facebook.github.io/jest/docs/snapshot-testing.html) for more information. + */ + toMatchInlineSnapshot(propertyMatchers: Partial, 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](http://facebook.github.io/jest/docs/snapshot-testing.html) for more information. + */ + toMatchInlineSnapshot(snapshot?: string): R; + /** + * Ensure that a mock function has returned (as opposed to thrown) at least once. + */ + toReturn(): R; + /** + * Ensure that a mock function has returned (as opposed to thrown) a specified number of times. + */ + toReturnTimes(count: number): R; + /** + * Ensure that a mock function has returned a specified value at least once. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toReturnWith(value: E): R; + /** + * Use to test that objects have the same types as well as structure. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toStrictEqual(expected: E): R; + /** + * Used to test that a function throws when it is called. + */ + toThrow(error?: string | Constructable | RegExp | Error): R; + /** + * If you want to test that a specific error is thrown inside a function. + */ + toThrowError(error?: string | Constructable | RegExp | Error): R; + /** + * Used to test that a function throws a error matching the most recent snapshot when it is called. + */ + toThrowErrorMatchingSnapshot(): 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. + */ + toThrowErrorMatchingInlineSnapshot(snapshot?: string): R; + } + + type RemoveFirstFromTuple = + T['length'] extends 0 ? [] : + (((...b: T) => void) extends (a: any, ...b: infer I) => void ? I : []); + + type Parameters any> = T extends (...args: infer P) => any ? P : never; + + interface AsymmetricMatcher { + asymmetricMatch(other: unknown): boolean; + } + type NonAsyncMatchers = { + [K in keyof TMatchers]: ReturnType extends Promise? never: K + }[keyof TMatchers]; + type CustomAsyncMatchers = {[K in NonAsyncMatchers]: CustomAsymmetricMatcher}; + type CustomAsymmetricMatcher any> = (...args: RemoveFirstFromTuple>) => AsymmetricMatcher; + + // should be TMatcherReturn extends void|Promise but getting dtslint error + type CustomJestMatcher any, TMatcherReturn> = (...args: RemoveFirstFromTuple>) => TMatcherReturn; + + type ExpectProperties= { + [K in keyof Expect]: Expect[K] + }; + // should be TMatcherReturn extends void|Promise but getting dtslint error + // Use the `void` type for return types only. Otherwise, use `undefined`. See: https://github.com/Microsoft/dtslint/blob/master/docs/void-return.md + // have added issue https://github.com/microsoft/dtslint/issues/256 - Cannot have type union containing void ( to be used as return type only + type ExtendedMatchers = Matchers & {[K in keyof TMatchers]: CustomJestMatcher}; + type JestExtendedMatchers = JestMatchersShape, ExtendedMatchers, TActual>>; + + // when have called expect.extend + type ExtendedExpectFunction = (actual: TActual) => JestExtendedMatchers; + + type ExtendedExpect= + ExpectProperties & + AndNot> & + ExtendedExpectFunction; + /** + * Construct a type with the properties of T except for those in type K. + */ + type Omit = Pick>; + type NonPromiseMatchers = Omit; + type PromiseMatchers = Omit; + + interface Constructable { + new (...args: any[]): any; + } + + interface Mock extends Function, MockInstance { + new (...args: Y): T; + (...args: Y): T; + } + + interface SpyInstance extends MockInstance {} + + /** + * Represents a function that has been spied on. + */ + type SpiedFunction any> = SpyInstance, ArgsType>; + + /** + * Wrap a function with mock definitions + * + * @example + * + * import { myFunction } from "./library"; + * jest.mock("./library"); + * + * const mockMyFunction = myFunction as jest.MockedFunction; + * expect(mockMyFunction.mock.calls[0][0]).toBe(42); + */ + type MockedFunction any> = MockInstance, ArgsType> & T; + + /** + * Wrap a class with mock definitions + * + * @example + * + * import { MyClass } from "./libary"; + * jest.mock("./library"); + * + * const mockedMyClass = MyClass as jest.MockedClass; + * + * expect(mockedMyClass.mock.calls[0][0]).toBe(42); // Constructor calls + * expect(mockedMyClass.prototype.myMethod.mock.calls[0][0]).toBe(42); // Method calls + */ + + type MockedClass = MockInstance< + InstanceType, + T extends new (...args: infer P) => any ? P : never + > & { + prototype: T extends { prototype: any } ? Mocked : never; + } & T; + + /** + * Wrap an object or a module with mock definitions + * + * @example + * + * jest.mock("../api"); + * import * as api from "../api"; + * + * const mockApi = api as jest.Mocked; + * api.MyApi.prototype.myApiMethod.mockImplementation(() => "test"); + */ + type Mocked = { + [P in keyof T]: T[P] extends (...args: any[]) => any + ? MockInstance, ArgsType> + : T[P] extends Constructable + ? MockedClass + : T[P] + } & + T; + + interface MockInstance { + /** Returns the mock name string set by calling `mockFn.mockName(value)`. */ + getMockName(): string; + /** Provides access to the mock's metadata */ + mock: MockContext; + /** + * Resets all information stored in the mockFn.mock.calls and mockFn.mock.instances arrays. + * + * Often this is useful when you want to clean up a mock's usage data between two assertions. + * + * Beware that `mockClear` will replace `mockFn.mock`, not just `mockFn.mock.calls` and `mockFn.mock.instances`. + * You should therefore avoid assigning mockFn.mock to other variables, temporary or not, to make sure you + * don't access stale data. + */ + mockClear(): this; + /** + * Resets all information stored in the mock, including any initial implementation and mock name given. + * + * This is useful when you want to completely restore a mock back to its initial state. + * + * Beware that `mockReset` will replace `mockFn.mock`, not just `mockFn.mock.calls` and `mockFn.mock.instances`. + * You should therefore avoid assigning mockFn.mock to other variables, temporary or not, to make sure you + * don't access stale data. + */ + mockReset(): this; + /** + * Does everything that `mockFn.mockReset()` does, and also restores the original (non-mocked) implementation. + * + * This is useful when you want to mock functions in certain test cases and restore the original implementation in others. + * + * Beware that `mockFn.mockRestore` only works when mock was created with `jest.spyOn`. Thus you have to take care of restoration + * yourself when manually assigning `jest.fn()`. + * + * The [`restoreMocks`](https://jestjs.io/docs/en/configuration.html#restoremocks-boolean) configuration option is available + * to restore mocks automatically between tests. + */ + mockRestore(): void; + /** + * Returns the function that was set as the implementation of the mock (using mockImplementation). + */ + getMockImplementation(): (...args: Y) => T | undefined; + /** + * Accepts a function that should be used as the implementation of the mock. The mock itself will still record + * all calls that go into and instances that come from itself – the only difference is that the implementation + * will also be executed when the mock is called. + * + * Note: `jest.fn(implementation)` is a shorthand for `jest.fn().mockImplementation(implementation)`. + */ + mockImplementation(fn?: (...args: Y) => T): this; + /** + * Accepts a function that will be used as an implementation of the mock for one call to the mocked function. + * Can be chained so that multiple function calls produce different results. + * + * @example + * + * const myMockFn = jest + * .fn() + * .mockImplementationOnce(cb => cb(null, true)) + * .mockImplementationOnce(cb => cb(null, false)); + * + * myMockFn((err, val) => console.log(val)); // true + * + * myMockFn((err, val) => console.log(val)); // false + */ + mockImplementationOnce(fn: (...args: Y) => T): this; + /** Sets the name of the mock`. */ + mockName(name: string): this; + /** + * Just a simple sugar function for: + * + * @example + * + * jest.fn(function() { + * return this; + * }); + */ + mockReturnThis(): this; + /** + * Accepts a value that will be returned whenever the mock function is called. + * + * @example + * + * const mock = jest.fn(); + * mock.mockReturnValue(42); + * mock(); // 42 + * mock.mockReturnValue(43); + * mock(); // 43 + */ + mockReturnValue(value: T): this; + /** + * Accepts a value that will be returned for one call to the mock function. Can be chained so that + * successive calls to the mock function return different values. When there are no more + * `mockReturnValueOnce` values to use, calls will return a value specified by `mockReturnValue`. + * + * @example + * + * const myMockFn = jest.fn() + * .mockReturnValue('default') + * .mockReturnValueOnce('first call') + * .mockReturnValueOnce('second call'); + * + * // 'first call', 'second call', 'default', 'default' + * console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn()); + * + */ + mockReturnValueOnce(value: T): this; + /** + * Simple sugar function for: `jest.fn().mockImplementation(() => Promise.resolve(value));` + */ + mockResolvedValue(value: ResolvedValue): this; + /** + * Simple sugar function for: `jest.fn().mockImplementationOnce(() => Promise.resolve(value));` + * + * @example + * + * test('async test', async () => { + * const asyncMock = jest + * .fn() + * .mockResolvedValue('default') + * .mockResolvedValueOnce('first call') + * .mockResolvedValueOnce('second call'); + * + * await asyncMock(); // first call + * await asyncMock(); // second call + * await asyncMock(); // default + * await asyncMock(); // default + * }); + * + */ + mockResolvedValueOnce(value: ResolvedValue): this; + /** + * Simple sugar function for: `jest.fn().mockImplementation(() => Promise.reject(value));` + * + * @example + * + * test('async test', async () => { + * const asyncMock = jest.fn().mockRejectedValue(new Error('Async error')); + * + * await asyncMock(); // throws "Async error" + * }); + */ + mockRejectedValue(value: RejectedValue): this; + + /** + * Simple sugar function for: `jest.fn().mockImplementationOnce(() => Promise.reject(value));` + * + * @example + * + * test('async test', async () => { + * const asyncMock = jest + * .fn() + * .mockResolvedValueOnce('first call') + * .mockRejectedValueOnce(new Error('Async error')); + * + * await asyncMock(); // first call + * await asyncMock(); // throws "Async error" + * }); + * + */ + mockRejectedValueOnce(value: RejectedValue): this; + } + + /** + * Represents the result of a single call to a mock function with a return value. + */ + interface MockResultReturn { + type: 'return'; + value: T; + } + /** + * Represents the result of a single incomplete call to a mock function. + */ + interface MockResultIncomplete { + type: 'incomplete'; + value: undefined; + } + /** + * Represents the result of a single call to a mock function with a thrown error. + */ + interface MockResultThrow { + type: 'throw'; + value: any; + } + + type MockResult = MockResultReturn | MockResultThrow | MockResultIncomplete; + + interface MockContext { + calls: Y[]; + instances: T[]; + invocationCallOrder: number[]; + /** + * List of results of calls to the mock function. + */ + results: Array>; + } +} + +// Jest ships with a copy of Jasmine. They monkey-patch its APIs and divergence/deprecation are expected. +// Relevant parts of Jasmine's API are below so they can be changed and removed over time. +// This file can't reference jasmine.d.ts since the globals aren't compatible. + +declare function spyOn(object: T, method: keyof T): jasmine.Spy; +/** + * If you call the function pending anywhere in the spec body, + * no matter the expectations, the spec will be marked pending. + */ +declare function pending(reason?: string): void; +/** + * Fails a test when called within one. + */ +declare function fail(error?: any): never; +declare namespace jasmine { + let DEFAULT_TIMEOUT_INTERVAL: number; + function clock(): Clock; + function any(aclass: any): Any; + function anything(): Any; + function arrayContaining(sample: any[]): ArrayContaining; + function objectContaining(sample: any): ObjectContaining; + function createSpy(name?: string, originalFn?: (...args: any[]) => any): Spy; + function createSpyObj(baseName: string, methodNames: any[]): any; + function createSpyObj(baseName: string, methodNames: any[]): T; + function pp(value: any): string; + function addCustomEqualityTester(equalityTester: CustomEqualityTester): void; + function addMatchers(matchers: CustomMatcherFactories): void; + function stringMatching(value: string | RegExp): Any; + + interface Clock { + install(): void; + uninstall(): void; + /** + * Calls to any registered callback are triggered when the clock isticked forward + * via the jasmine.clock().tick function, which takes a number of milliseconds. + */ + tick(ms: number): void; + mockDate(date?: Date): void; + } + + interface Any { + new (expectedClass: any): any; + jasmineMatches(other: any): boolean; + jasmineToString(): string; + } + + interface ArrayContaining { + new (sample: any[]): any; + asymmetricMatch(other: any): boolean; + jasmineToString(): string; + } + + interface ObjectContaining { + new (sample: any): any; + jasmineMatches(other: any, mismatchKeys: any[], mismatchValues: any[]): boolean; + jasmineToString(): string; + } + + interface Spy { + (...params: any[]): any; + identity: string; + and: SpyAnd; + calls: Calls; + mostRecentCall: { args: any[] }; + argsForCall: any[]; + wasCalled: boolean; + } + + interface SpyAnd { + /** + * By chaining the spy with and.callThrough, the spy will still track all + * calls to it but in addition it will delegate to the actual implementation. + */ + callThrough(): Spy; + /** + * By chaining the spy with and.returnValue, all calls to the function + * will return a specific value. + */ + returnValue(val: any): Spy; + /** + * By chaining the spy with and.returnValues, all calls to the function + * will return specific values in order until it reaches the end of the return values list. + */ + returnValues(...values: any[]): Spy; + /** + * By chaining the spy with and.callFake, all calls to the spy + * will delegate to the supplied function. + */ + callFake(fn: (...args: any[]) => any): Spy; + /** + * By chaining the spy with and.throwError, all calls to the spy + * will throw the specified value. + */ + throwError(msg: string): Spy; + /** + * When a calling strategy is used for a spy, the original stubbing + * behavior can be returned at any time with and.stub. + */ + stub(): Spy; + } + + interface Calls { + /** + * By chaining the spy with calls.any(), + * will return false if the spy has not been called at all, + * and then true once at least one call happens. + */ + any(): boolean; + /** + * By chaining the spy with calls.count(), + * will return the number of times the spy was called + */ + count(): number; + /** + * By chaining the spy with calls.argsFor(), + * will return the arguments passed to call number index + */ + argsFor(index: number): any[]; + /** + * By chaining the spy with calls.allArgs(), + * will return the arguments to all calls + */ + allArgs(): any[]; + /** + * By chaining the spy with calls.all(), will return the + * context (the this) and arguments passed all calls + */ + all(): CallInfo[]; + /** + * By chaining the spy with calls.mostRecent(), will return the + * context (the this) and arguments for the most recent call + */ + mostRecent(): CallInfo; + /** + * By chaining the spy with calls.first(), will return the + * context (the this) and arguments for the first call + */ + first(): CallInfo; + /** + * By chaining the spy with calls.reset(), will clears all tracking for a spy + */ + reset(): void; + } + + interface CallInfo { + /** + * The context (the this) for the call + */ + object: any; + /** + * All arguments passed to the call + */ + args: any[]; + /** + * The return value of the call + */ + returnValue: any; + } + + interface CustomMatcherFactories { + [index: string]: CustomMatcherFactory; + } + + type CustomMatcherFactory = (util: MatchersUtil, customEqualityTesters: CustomEqualityTester[]) => CustomMatcher; + + interface MatchersUtil { + equals(a: any, b: any, customTesters?: CustomEqualityTester[]): boolean; + contains(haystack: ArrayLike | string, needle: any, customTesters?: CustomEqualityTester[]): boolean; + buildFailureMessage(matcherName: string, isNot: boolean, actual: any, ...expected: any[]): string; + } + + type CustomEqualityTester = (first: any, second: any) => boolean; + + interface CustomMatcher { + compare(actual: T, expected: T, ...args: any[]): CustomMatcherResult; + compare(actual: any, ...expected: any[]): CustomMatcherResult; + } + + interface CustomMatcherResult { + pass: boolean; + message: string | (() => string); + } + + interface ArrayLike { + length: number; + [n: number]: T; + } +} diff --git a/types/jest/ts3.2/jest-tests.ts b/types/jest/ts3.2/jest-tests.ts new file mode 100644 index 000000000000000..499c303e55add1d --- /dev/null +++ b/types/jest/ts3.2/jest-tests.ts @@ -0,0 +1,1448 @@ +/* Lifecycle events */ + +beforeAll(() => {}); +beforeAll((done: jest.DoneCallback) => {}); +beforeAll((done: jest.DoneCallback) => done.fail(), 9001); + +beforeEach(() => {}); +beforeEach((done: jest.DoneCallback) => {}); +beforeEach((done: jest.DoneCallback) => done.fail(), 9001); + +afterAll(() => {}); +afterAll((done: jest.DoneCallback) => {}); +afterAll((done: jest.DoneCallback) => done.fail(), 9001); + +afterEach(() => {}); +afterEach((done: jest.DoneCallback) => {}); +afterEach((done: jest.DoneCallback) => done.fail(), 9001); + +/* describe */ + +describe(0, () => {}); +describe('name', () => {}); +describe(() => {}, () => {}); +describe({ name: 'name' }, () => {}); + +describe.only(0, () => {}); +describe.only('name', () => {}); +describe.only(() => {}, () => {}); +describe.only({ name: 'name' }, () => {}); + +describe.skip(0, () => {}); +describe.skip('name', () => {}); +describe.skip(() => {}, () => {}); +describe.skip({ name: 'name' }, () => {}); + +fdescribe(0, () => {}); +fdescribe('name', () => {}); +fdescribe(() => {}, () => {}); +fdescribe({ name: 'name' }, () => {}); + +fdescribe.only(0, () => {}); +fdescribe.only('name', () => {}); +fdescribe.only(() => {}, () => {}); +fdescribe.only({ name: 'name' }, () => {}); + +fdescribe.skip(0, () => {}); +fdescribe.skip('name', () => {}); +fdescribe.skip(() => {}, () => {}); +fdescribe.skip({ name: 'name' }, () => {}); + +xdescribe(0, () => {}); +xdescribe('name', () => {}); +xdescribe(() => {}, () => {}); +xdescribe({ name: 'name' }, () => {}); + +xdescribe.only(0, () => {}); +xdescribe.only('name', () => {}); +xdescribe.only(() => {}, () => {}); +xdescribe.only({ name: 'name' }, () => {}); + +xdescribe.skip(0, () => {}); +xdescribe.skip('name', () => {}); +xdescribe.skip(() => {}, () => {}); +xdescribe.skip({ name: 'name' }, () => {}); + +/* it */ + +it('name', () => {}); +it('name', async () => {}); +it('name', () => {}, 9001); +it('name', async () => {}, 9001); +it('name', (callback: jest.DoneCallback) => {}, 9001); + +it.only('name', () => {}); +it.only('name', async () => {}); +it.only('name', () => {}, 9001); +it.only('name', async () => {}, 9001); +it.only('name', (callback: jest.DoneCallback) => {}, 9001); + +it.skip('name', () => {}); +it.skip('name', async () => {}); +it.skip('name', () => {}, 9001); +it.skip('name', async () => {}, 9001); +it.skip('name', (callback: jest.DoneCallback) => {}, 9001); + +it.todo('name', () => {}); +it.todo('name', async () => {}); +it.todo('name', () => {}, 9001); +it.todo('name', async () => {}, 9001); +it.todo('name', (callback: jest.DoneCallback) => {}, 9001); + +it.concurrent('name', () => {}); +it.concurrent('name', async () => {}); +it.concurrent('name', () => {}, 9001); +it.concurrent('name', async () => {}, 9001); +it.concurrent('name', (callback: jest.DoneCallback) => {}, 9001); + +fit('name', () => {}); +fit('name', async () => {}); +fit('name', () => {}, 9001); +fit('name', async () => {}, 9001); +fit('name', (callback: jest.DoneCallback) => {}, 9001); + +fit.only('name', () => {}); +fit.only('name', async () => {}); +fit.only('name', () => {}, 9001); +fit.only('name', async () => {}, 9001); +fit.only('name', (callback: jest.DoneCallback) => {}, 9001); + +fit.skip('name', () => {}); +fit.skip('name', async () => {}); +fit.skip('name', () => {}, 9001); +fit.skip('name', async () => {}, 9001); +fit.skip('name', (callback: jest.DoneCallback) => {}, 9001); + +fit.todo('name', () => {}); +fit.todo('name', async () => {}); +fit.todo('name', () => {}, 9001); +fit.todo('name', async () => {}, 9001); +fit.todo('name', (callback: jest.DoneCallback) => {}, 9001); + +fit.concurrent('name', () => {}); +fit.concurrent('name', async () => {}); +fit.concurrent('name', () => {}, 9001); +fit.concurrent('name', async () => {}, 9001); +fit.concurrent('name', (callback: jest.DoneCallback) => {}, 9001); + +xit('name', () => {}); +xit('name', async () => {}); +xit('name', () => {}, 9001); +xit('name', async () => {}, 9001); +xit('name', (callback: jest.DoneCallback) => {}, 9001); + +xit.only('name', () => {}); +xit.only('name', async () => {}); +xit.only('name', () => {}, 9001); +xit.only('name', async () => {}, 9001); +xit.only('name', (callback: jest.DoneCallback) => {}, 9001); + +xit.skip('name', () => {}); +xit.skip('name', async () => {}); +xit.skip('name', () => {}, 9001); +xit.skip('name', async () => {}, 9001); +xit.skip('name', (callback: jest.DoneCallback) => {}, 9001); + +xit.todo('name', () => {}); +xit.todo('name', async () => {}); +xit.todo('name', () => {}, 9001); +xit.todo('name', async () => {}, 9001); +xit.todo('name', (callback: jest.DoneCallback) => {}, 9001); + +xit.concurrent('name', () => {}); +xit.concurrent('name', async () => {}); +xit.concurrent('name', () => {}, 9001); +xit.concurrent('name', async () => {}, 9001); +xit.concurrent('name', (callback: jest.DoneCallback) => {}, 9001); + +test('name', () => {}); +test('name', async () => {}); +test('name', () => {}, 9001); +test('name', async () => {}, 9001); +test('name', (callback: jest.DoneCallback) => {}, 9001); + +test.only('name', () => {}); +test.only('name', async () => {}); +test.only('name', () => {}, 9001); +test.only('name', async () => {}, 9001); +test.only('name', (callback: jest.DoneCallback) => {}, 9001); + +test.skip('name', () => {}); +test.skip('name', async () => {}); +test.skip('name', () => {}, 9001); +test.skip('name', async () => {}, 9001); +test.skip('name', (callback: jest.DoneCallback) => {}, 9001); + +test.todo('name', () => {}); +test.todo('name', async () => {}); +test.todo('name', () => {}, 9001); +test.todo('name', async () => {}, 9001); +test.todo('name', (callback: jest.DoneCallback) => {}, 9001); + +test.concurrent('name', () => {}); +test.concurrent('name', async () => {}); +test.concurrent('name', () => {}, 9001); +test.concurrent('name', async () => {}, 9001); +test.concurrent('name', (callback: jest.DoneCallback) => {}, 9001); + +xtest('name', () => {}); +xtest('name', async () => {}); +xtest('name', () => {}, 9001); +xtest('name', async () => {}, 9001); +xtest('name', (callback: jest.DoneCallback) => {}, 9001); + +xtest.only('name', () => {}); +xtest.only('name', async () => {}); +xtest.only('name', () => {}, 9001); +xtest.only('name', async () => {}, 9001); +xtest.only('name', (callback: jest.DoneCallback) => {}, 9001); + +xtest.skip('name', () => {}); +xtest.skip('name', async () => {}); +xtest.skip('name', () => {}, 9001); +xtest.skip('name', async () => {}, 9001); +xtest.skip('name', (callback: jest.DoneCallback) => {}, 9001); + +xtest.todo('name', () => {}); +xtest.todo('name', async () => {}); +xtest.todo('name', () => {}, 9001); +xtest.todo('name', async () => {}, 9001); +xtest.todo('name', (callback: jest.DoneCallback) => {}, 9001); + +xtest.concurrent('name', () => {}); +xtest.concurrent('name', async () => {}); +xtest.concurrent('name', () => {}, 9001); +xtest.concurrent('name', async () => {}, 9001); +xtest.concurrent('name', (callback: jest.DoneCallback) => {}, 9001); + +/* Done callbacks */ + +describe('', () => { + it('', (callback: jest.DoneCallback): void => { + callback(); + callback(''); + callback('', 3); + callback.fail(); + callback.fail('error'); + callback.fail({ message: 'message' }); + }); +}); + +/* NodeRequire interface (require extensions) */ + +declare const nodeRequire: NodeRequire; + +// $ExpectType any +nodeRequire.requireActual('moduleName'); + +// $ExpectType any +nodeRequire.requireMock('moduleName'); + +/* Top-level jest namespace functions */ + +const customMatcherFactories: jasmine.CustomMatcherFactories = {}; + +jest.addMatchers(customMatcherFactories) + .addMatchers({}) + .addMatchers(customMatcherFactories) + .autoMockOff() + .autoMockOn() + .clearAllMocks() + .clearAllTimers() + .resetAllMocks() + .restoreAllMocks() + .clearAllTimers() + .deepUnmock('moduleName') + .disableAutomock() + .doMock('moduleName') + .doMock('moduleName', jest.fn()) + .doMock('moduleName', jest.fn(), {}) + .doMock('moduleName', jest.fn(), { virtual: true }) + .dontMock('moduleName') + .enableAutomock() + .mock('moduleName') + .mock('moduleName', jest.fn()) + .mock('moduleName', jest.fn(), {}) + .mock('moduleName', jest.fn(), { virtual: true }) + .resetModuleRegistry() + .resetModules() + .isolateModules(() => {}) + .retryTimes(3) + .runAllImmediates() + .runAllTicks() + .runAllTimers() + .runOnlyPendingTimers() + .runTimersToTime(9001) + .advanceTimersByTime(9001) + .setMock('moduleName', {}) + .setMock<{}>('moduleName', {}) + .setMock<{ a: 'b' }>('moduleName', { a: 'b' }) + .setTimeout(9001) + .unmock('moduleName') + .useFakeTimers() + .useRealTimers(); + +jest.advanceTimersToNextTimer(); +jest.advanceTimersToNextTimer(2); + +// https://jestjs.io/docs/en/jest-object#jestrequireactualmodulename +jest.requireActual('./thisReturnsTheActualModule'); + +// https://jestjs.io/docs/en/jest-object#jestrequiremockmodulename +jest.requireMock('./thisAlwaysReturnsTheMock'); + +/* Mocks and spies */ + +// $ExpectType Mock +const mock1: jest.Mock = jest.fn(); +// $ExpectType Mock +const mock2 = jest.fn(() => undefined); +// $ExpectType Mock +const mock3 = jest.fn(() => 'abc'); +// $ExpectType Mock<"abc", []> +const mock4 = jest.fn((): 'abc' => 'abc'); +// $ExpectType Mock +const mock5 = jest.fn((...args: string[]) => args.join('')); +// $ExpectType Mock<{}, [{}]> +const mock6 = jest.fn((arg: {}) => arg); +// $ExpectType Mock +const mock7 = jest.fn((arg: number) => arg); +// $ExpectType Mock +const mock8: jest.Mock = jest.fn((arg: number) => arg); +// $ExpectType Mock, [number, string, {}, [], boolean]> +const mock9 = jest.fn((a: number, _b: string, _c: {}, _iReallyDontCare: [], _makeItStop: boolean) => + Promise.resolve(_makeItStop) +); +// $ExpectType Mock +const mock10 = jest.fn(() => { + throw new Error(); +}); +// $ExpectType Mock +const mock11 = jest.fn((arg: unknown) => arg); +interface TestApi { + test(x: number): string; +} +// $ExpectType Mock +const mock12 = jest.fn, jest.ArgsType>(); + +// $ExpectType number +mock1('test'); + +// $ExpectError +mock7('abc'); +// $ExpectError +mock7.mockImplementation((arg: string) => 1); + +// compiles because mock8 is declared as jest.Mock<{}, any> +mock8('abc'); +mock8.mockImplementation((arg: string) => 1); + +// mockImplementation not required to declare all arguments +mock9.mockImplementation((a: number) => Promise.resolve(a === 0)); + +const genMockModule1: {} = jest.genMockFromModule('moduleName'); +const genMockModule2: { a: 'b' } = jest.genMockFromModule<{ a: 'b' }>('moduleName'); + +const isStringMock: boolean = jest.isMockFunction('foo'); +const isMockMock: boolean = jest.isMockFunction(mock1); + +const maybeMock = () => {}; +if (jest.isMockFunction(maybeMock)) { + maybeMock.getMockName(); +} + +const mockName: string = jest.fn().getMockName(); +const mockContextVoid = jest.fn().mock; +const mockContextString = jest.fn(() => '').mock; + +jest.fn().mockClear(); +jest.fn().mockReset(); +jest.fn().mockRestore(); +jest.fn().mockImplementation((test: number) => test); +jest.fn().mockResolvedValue(1); + +interface SpyInterface { + prop?: number; + method?: (arg1: boolean) => void; +} +const spiedTarget = { + returnsVoid(): void {}, + setValue(value: string): void { + this.value = value; + }, + returnsString(): string { + return ''; + }, +}; +class SpiedTargetClass { + private _value = 3; + private _value2 = ''; + get value() { + return this._value; + } + set value(value) { + this._value = value; + } + get value2() { + return this._value2; + } + set value2(value2) { + this._value2 = value2; + } +} + +const spiedTarget2 = new SpiedTargetClass(); + +// $ExpectError +jest.spyOn(spiedTarget, 'setValue', 'get'); +// $ExpectError +jest.spyOn(spiedTarget2, 'value'); + +const spy1 = jest.spyOn(spiedTarget, 'returnsVoid'); +const spy3 = jest.spyOn(spiedTarget, 'returnsString'); +const spy1Name: string = spy1.getMockName(); + +const spy1Calls: Array<[]> = spy1.mock.calls; + +spy1.mockClear(); +spy1.mockReset(); + +const spy3Mock = spy3 + .mockImplementation(() => '') + .mockImplementation() + // $ExpectError + .mockImplementation((arg: {}) => arg) + .mockImplementation((...args: string[]) => args.join('')) + .mockImplementationOnce(() => '') + .mockName('name') + .mockReturnThis() + .mockReturnValue('value') + .mockReturnValueOnce('value'); + +const spiedPromiseTarget = { + resolvesString() { + return Promise.resolve('string'); + } +}; +jest.spyOn(spiedPromiseTarget, 'resolvesString') + .mockResolvedValue('value') + .mockResolvedValueOnce('value') + .mockRejectedValue('value') + .mockRejectedValueOnce('value'); + +let spy4: jest.SpyInstance; +// $ExpectType SpyInstance +spy4 = jest.spyOn(spiedTarget, 'returnsString'); +// compiles because spy4 is declared as jest.SpyInstance +spy4.mockImplementation(() => 1); +spy4.mockRestore(); + +let spy5: jest.SpiedFunction; + +// $ExpectType SpyInstance +spy5 = jest.spyOn(spiedTarget, 'setValue'); +// $ExpectError +spy5 = jest.spyOn(spiedTarget, 'returnsString'); + +// $ExpectType SpyInstance +const spy6 = jest.spyOn(spiedTarget2, 'value', 'get'); +// $ExpectError +spy6.mockReturnValue('5'); + +// $ExpectType SpyInstance +jest.spyOn(spiedTarget2, 'value', 'set'); + +let spyInterfaceImpl: SpyInterface = {}; +// $ExpectError +jest.spyOn(spyInterfaceImpl, 'method', 'get'); +// $ExpectError +jest.spyOn(spyInterfaceImpl, 'prop'); +// $ExpectType SpyInstance +jest.spyOn(spyInterfaceImpl, 'prop', 'get'); +// $ExpectType SpyInstance +jest.spyOn(spyInterfaceImpl, 'method'); + +class SpyableClass { + constructor(a: number, b: string) {} + foo() {} +} +// $ExpectType SpyInstance +jest.spyOn({ SpyableClass }, "SpyableClass"); + +interface Type1 { + a: number; +} +interface Type2 { + b: number; +} +class TestMocked { + field: string; + test1(x: Type1): Promise { + return Promise.resolve(x); + } + test2(x: Promise): Promise { + return x; + } + test3(x: Promise): Promise { + return x.then(() => ({ b: 1 })); + } + test4(x: Type1): Type1 { + return x; + } +} + +const mocked: jest.Mocked = new TestMocked() as any; +mocked.test1.mockImplementation(() => Promise.resolve({ a: 1 })); +// $ExpectType (x: Type1) => Promise | undefined +mocked.test1.getMockImplementation(); +mocked.test1.mockReturnValue(Promise.resolve({ a: 1 })); +// $ExpectType MockInstance, [Type1]> & ((x: Type1) => Promise) +mocked.test1.mockResolvedValue({ a: 1 }); +mocked.test1.mockResolvedValueOnce({ a: 1 }); +// $ExpectType MockInstance, [Type1]> & ((x: Type1) => Promise) +mocked.test1.mockResolvedValue(Promise.resolve({ a: 1 })); +mocked.test1.mockResolvedValueOnce(Promise.resolve({ a: 1 })); +// $ExpectType MockInstance, [Promise]> & ((x: Promise) => Promise) +mocked.test2.mockResolvedValue({ a: 1 }); +mocked.test2.mockResolvedValueOnce({ a: 1 }); +// $ExpectType MockInstance, [Promise]> & ((x: Promise) => Promise) +mocked.test2.mockResolvedValue(Promise.resolve({ a: 1 })); +mocked.test2.mockResolvedValueOnce(Promise.resolve({ a: 1 })); +// $ExpectType MockInstance, [Promise]> & ((x: Promise) => Promise) +mocked.test3.mockResolvedValue({ b: 1 }); +mocked.test3.mockResolvedValueOnce({ b: 1 }); +// $ExpectType MockInstance, [Promise]> & ((x: Promise) => Promise) +mocked.test3.mockResolvedValue(Promise.resolve({ b: 1 })); +mocked.test3.mockResolvedValueOnce(Promise.resolve({ b: 1 })); +mocked.test3.mockRejectedValue(new Error()); +mocked.test3.mockRejectedValueOnce(new Error()); +// $ExpectError +mocked.test4.mockResolvedValue({ a: 1 }); +// $ExpectError +mocked.test4.mockResolvedValueOnce({ a: 1 }); +// $ExpectError +mocked.test4.mockResolvedValue(Promise.resolve({ a: 1 })); +// $ExpectError +mocked.test4.mockResolvedValueOnce(Promise.resolve({ a: 1 })); +// $ExpectError +mocked.test4.mockRejectedValue(new Error()); +// $ExpectError +mocked.test4.mockRejectedValueOnce(new Error()); + +class TestClass { + testClassMethod(str: string, num: number): boolean { + return true; + } + + constructor(stringValue: string) {} +} + +const module = { + testFunction(num: number, str: string): boolean { + return true; + }, + testLambdaFunction: (num: number, str: string): boolean => { + return true; + }, + TestClass, + testClassInstance: new TestClass('test'), +}; + +const mockedModule = module as jest.Mocked; +mockedModule.testFunction.mock.calls[0][0]; // $ExpectType number +mockedModule.testFunction.mock.calls[0][1]; // $ExpectType string +const testFunction_0_ret = mockedModule.testFunction.mock.results[0]; +if (testFunction_0_ret.type === 'return') { + testFunction_0_ret.value; // $ExpectType boolean +} + +mockedModule.TestClass.mock.calls[0][0]; // $ExpectType string +mockedModule.TestClass.mock.instances[0]; // $ExpectType TestClass + +mockedModule.TestClass.prototype.testClassMethod.mock.calls[0][0]; // $ExpectType string +mockedModule.TestClass.prototype.testClassMethod.mock.calls[0][1]; // $ExpectType number +const TestClass_testClassMethod_0_ret = mockedModule.TestClass.prototype.testClassMethod.mock.results[0]; +if (TestClass_testClassMethod_0_ret.type === 'return') { + TestClass_testClassMethod_0_ret.value; // $ExpectType boolean +} + +const mockedTestFunction = module.testFunction as jest.MockedFunction; +mockedTestFunction.mock.calls[0][0]; // $ExpectType number +mockedTestFunction.mock.calls[0][1]; // $ExpectType string +const mockedTestFunction_0_ret = mockedTestFunction.mock.results[0]; +if (mockedTestFunction_0_ret.type === 'return') { + mockedTestFunction_0_ret.value; // $ExpectType boolean +} + +const mockedTestLambdaFunction = module.testLambdaFunction as jest.MockedFunction; +mockedTestLambdaFunction.mock.calls[0][0]; // $ExpectType number +mockedTestLambdaFunction.mock.calls[0][1]; // $ExpectType string +const mockedTestLambdaFunction_0_ret = mockedTestLambdaFunction.mock.results[0]; +if (mockedTestLambdaFunction_0_ret.type === 'return') { + mockedTestLambdaFunction_0_ret.value; // $ExpectType boolean +} + +const MockedTestClass = module.TestClass as jest.MockedClass; +MockedTestClass.prototype.testClassMethod.mock.calls[0][0]; // $ExpectType string +MockedTestClass.prototype.testClassMethod.mock.calls[0][1]; // $ExpectType number +const MockedTestClass_testClassMethod_0_ret = mockedModule.TestClass.prototype.testClassMethod.mock.results[0]; +if (MockedTestClass_testClassMethod_0_ret.type === 'return') { + MockedTestClass_testClassMethod_0_ret.value; // $ExpectType boolean +} + +const mockResult = jest.fn(() => 1).mock.results[0]; +switch (mockResult.type) { + case 'return': + mockResult.value; // $ExpectType number + break; + case 'incomplete': + mockResult.value; // $ExpectType undefined + break; + case 'throw': + mockResult.value; // $ExpectType any + break; +} + +/* getState and setState */ +// $ExpectError +expect.setState(true); +expect.setState({for: 'state'}); +const expectState = expect.getState(); +// $ExpectType string +expectState.currentTestName; +// $ExpectType string +expectState.testPath; +// $ExpectType boolean +expectState.expand; +// $ExpectType number +expectState.assertionCalls; +// $ExpectType number +expectState.expectedAssertionsNumber; +// $ExpectType boolean | undefined +expectState.isExpectingAssertions; +// $ExpectType Error[] +expectState.suppressedErrors; +// allows additional state properties added by getState +expectState.for; + +/* Snapshot serialization */ + +const snapshotSerializerPlugin: jest.SnapshotSerializerPlugin = { + print: () => '', + test: () => true, +}; + +expect.addSnapshotSerializer(snapshotSerializerPlugin); + +expect.addSnapshotSerializer({ + print: (value: unknown) => '', + test: (value: {}) => value === value, +}); + +expect.addSnapshotSerializer({ + print: (value: unknown, serialize: (val: {}) => string, indent: (str: string) => string, opts: {}) => '', + test: (value: {}) => value === value, +}); + +expect.addSnapshotSerializer({ + serialize(value, config, indentation, depth, refs, printer) { + let result = ''; + + if (config.callToJSON !== undefined && config.callToJSON) { + result += ' '; + } + + result += config.spacingInner; + result += config.spacingOuter; + + if (config.escapeRegex !== undefined && config.escapeRegex) { + result += ' '; + } + + if (indentation !== undefined) { + result += indentation; + } + + if (config.maxDepth !== undefined) { + result = result.substring(0, config.maxDepth); + } + + if (config.min !== undefined && config.min) { + result += ' '; + } + + if (config.plugins !== undefined) { + for (const plugin of config.plugins) { + expect.addSnapshotSerializer(plugin); + } + } + + if (config.printFunctionName !== undefined && config.printFunctionName) { + result += ' '; + } + + return result; + }, + test: (value: {}) => value === value, +}); + +// old API +expect.addSnapshotSerializer({ + print(value, serialize, indent, opts, colors) { + let result = ''; + + result += opts.edgeSpacing; + result += opts.spacing; + + if (opts.min !== undefined && opts.min) { + result += ' '; + } + + for (const color of [colors.comment, colors.content, colors.prop, colors.tag, colors.value]) { + result += color.open; + result += color.close; + } + + return result; + }, + test: (value: {}) => value === value, +}); + +/* expect extensions */ + +const expectExtendMap: jest.ExpectExtendMap = {}; + +expect.extend(expectExtendMap); +expect.extend({}); +expect.extend({ + foo(this: jest.MatcherContext, received: {}, ...actual: Array<{}>) { + return { + message: () => JSON.stringify(received), + pass: false, + }; + }, +}); +// $ExpectError +const customMatcherResultMessage: jest.CustomMatcherResult['message'] = 'msg'; +expect.extend({ + async foo(this: jest.MatcherContext, received: {}, ...actual: Array<{}>) { + return { + message: () => JSON.stringify(received), + pass: false, + }; + }, +}); + +expect.extend({ + foo(this: jest.MatcherContext) { + const isNot: boolean = this.isNot; + const expand: boolean = this.expand; + + const expectedColor = this.utils.EXPECTED_COLOR('blue'); + const receivedColor = this.utils.EXPECTED_COLOR('red'); + + const diff: string | null = this.utils.diff({}, {}); + + this.utils.ensureActualIsNumber({}, 'matcher'); + + this.utils.ensureExpectedIsNumber({}, 'matcher'); + + this.utils.ensureNoExpected({}, 'matcher'); + + this.utils.ensureNumbers({}, {}, 'matcher'); + + this.utils.matcherHint('matcher'); + this.utils.matcherHint('matcher', 'received'); + this.utils.matcherHint('matcher', 'received', 'expected'); + this.utils.matcherHint('matcher', 'received', 'expected', {}); + this.utils.matcherHint('matcher', 'received', 'expected', { + isDirectExpectCall: true, + }); + this.utils.matcherHint('matcher', 'received', 'expected', { + secondArgument: '', + }); + this.utils.matcherHint('matcher', 'received', 'expected', { + isDirectExpectCall: true, + secondArgument: '', + }); + + const plural: string = this.utils.pluralize('word', 3); + + const expectedPrinted: string = this.utils.printExpected({}); + + const receivedPrinted: string = this.utils.printReceived({}); + + const printedWithType: string = this.utils.printWithType('name', {}, (value: {}) => ''); + + const stringified: string = this.utils.stringify({}); + const stringifiedWithMaxDepth: string = this.utils.stringify({}, 3); + + const equals: boolean = this.equals({}, {}); + + this.dontThrow(); + this.fromState; + const currentTestName: string = this.currentTestName; + const testPath: string = this.testPath; + + return { + message: () => `Can use ${this.promise} for failure message`, + pass: false, + }; + }, +}); + +/* Basic matchers */ + +describe('', () => { + it('', () => { + /* Corrections of previous typings */ + // $ExpectError + expect('').not.not; + // $ExpectError + expect('').resolves.resolves; + // $ExpectType void + expect('').toEqual(''); + // $ExpectType Promise + expect(Promise.resolve('')).resolves.toEqual(''); + + expect(jest.fn()).lastCalledWith(); + expect(jest.fn()).lastCalledWith('jest'); + expect(jest.fn()).lastCalledWith({}, {}); + + expect(jest.fn()).lastReturnedWith('jest'); + expect(jest.fn()).lastReturnedWith({}); + + expect(jest.fn()).nthCalledWith(0, 'jest'); + expect(jest.fn()).nthCalledWith(1, {}); + + expect(jest.fn()).nthReturnedWith(0, 'jest'); + expect(jest.fn()).nthReturnedWith(1, {}); + + expect({}).toBe({}); + expect([]).toBe([]); + expect(10).toBe(10); + + expect(jest.fn()).toBeCalled(); + + expect(jest.fn()).toBeCalledTimes(1); + + expect(jest.fn()).toBeCalledWith(); + expect(jest.fn()).toBeCalledWith('jest'); + expect(jest.fn()).toBeCalledWith({}, {}); + + // $ExpectError + expect(jest.fn()).toBeCalledWith<[string, number]>(1, 'two'); + // $ExpectError + expect({}).toEqual<{ p1: string, p2: number }>({ p1: 'hello' }); + + expect(0).toBeCloseTo(1); + expect(0).toBeCloseTo(1, 2); + + expect(undefined).toBeDefined(); + expect({}).toBeDefined(); + + expect(true).toBeFalsy(); + expect(false).toBeFalsy(); + expect(0).toBeFalsy(); + + expect(0).toBeGreaterThan(1); + + expect(0).toBeGreaterThanOrEqual(1); + + expect(3).toBeInstanceOf(Number); + + expect(0).toBeLessThan(1); + + expect(0).toBeLessThanOrEqual(1); + + expect(0n).toBeGreaterThan(1n); + + expect(0n).toBeGreaterThanOrEqual(1n); + + expect(0n).toBeLessThan(1n); + + expect(0n).toBeLessThanOrEqual(1n); + + expect(null).toBeNull(); + expect(undefined).toBeNull(); + + expect(true).toBeTruthy(); + expect(false).toBeFalsy(); + expect(1).toBeTruthy(); + + expect(undefined).toBeUndefined(); + expect({}).toBeUndefined(); + + expect(NaN).toBeNaN(); + expect(Infinity).toBeNaN(); + + expect([]).toContain({}); + expect(['abc']).toContain('abc'); + expect(['abc']).toContain('def'); + expect('abc').toContain('bc'); + + expect([]).toContainEqual({}); + expect(['abc']).toContainEqual('def'); + + expect([]).toEqual([]); + expect({}).toEqual({}); + + expect(jest.fn()).toHaveBeenCalled(); + + expect(jest.fn()).toHaveBeenCalledTimes(0); + expect(jest.fn()).toHaveBeenCalledTimes(1); + + expect(jest.fn()).toHaveBeenCalledWith(); + expect(jest.fn()).toHaveBeenCalledWith('jest'); + expect(jest.fn()).toHaveBeenCalledWith({}, {}); + + expect(jest.fn()).toHaveBeenCalledWith(0); + expect(jest.fn()).toHaveBeenCalledWith(1, 'jest'); + expect(jest.fn()).toHaveBeenCalledWith(2, {}, {}); + + expect(jest.fn()).toHaveBeenLastCalledWith(); + expect(jest.fn()).toHaveBeenLastCalledWith('jest'); + expect(jest.fn()).toHaveBeenLastCalledWith({}, {}); + + expect(jest.fn()).toHaveLastReturnedWith('jest'); + expect(jest.fn()).toHaveLastReturnedWith({}); + + expect([]).toHaveLength(0); + expect('').toHaveLength(1); + + expect(jest.fn()).toHaveNthReturnedWith(0, 'jest'); + expect(jest.fn()).toHaveNthReturnedWith(1, {}); + + expect({}).toHaveProperty('property'); + expect({}).toHaveProperty('property', {}); + expect({}).toHaveProperty(['property']); + expect({}).toHaveProperty(['property'], {}); + expect({}).toHaveProperty(['property', 'deep']); + expect({}).toHaveProperty(['property', 'deep'], {}); + + expect(jest.fn()).toHaveReturned(); + + expect(jest.fn()).toHaveReturnedTimes(0); + expect(jest.fn()).toHaveReturnedTimes(1); + + expect(jest.fn()).toHaveReturnedWith('jest'); + expect(jest.fn()).toHaveReturnedWith({}); + + expect('').toMatch(''); + expect('').toMatch(/foo/); + + expect({}).toMatchObject({}); + expect({ abc: 'def' }).toMatchObject({ abc: 'def' }); + expect({}).toMatchObject([{}, {}]); + expect({ abc: 'def' }).toMatchObject([{ abc: 'def' }, { invalid: 'property' }]); + expect({ abc: 'def' }).toMatchObject<{ abc: string }>({ abc: 'def' }); + expect([{ abc: 'def' }, { abc: 'def' }]).toMatchObject<[{ abc: string }, { abc: string }]>([ + { abc: 'def' }, + { abc: 'def' }, + ]); + + expect({}).toMatchSnapshot(); + expect({}).toMatchSnapshot('snapshotName'); + expect({ abc: 'def' }).toMatchSnapshot({ abc: expect.any(String) }, 'snapshotName'); + expect({ + one: 1, + two: '2', + three: 3, + four: { four: 3 }, + date: new Date(), + }).toMatchSnapshot({ + one: expect.any(Number), + // Leave 'two' to the auto-generated snapshot + three: 3, + four: { four: expect.any(Number) }, + date: expect.any(Date), + }); + + expect({}).toMatchInlineSnapshot(); + expect({}).toMatchInlineSnapshot('snapshot'); + expect({ abc: 'def' }).toMatchInlineSnapshot({ abc: expect.any(String) }, 'snapshot'); + expect({ + one: 1, + two: '2', + three: 3, + four: { four: 3 }, + date: new Date(), + }).toMatchInlineSnapshot({ + one: expect.any(Number), + // leave out two + three: 3, + four: { four: expect.any(Number) }, + date: expect.any(Date), + }); + + expect(jest.fn()).toReturn(); + + expect(jest.fn()).toReturnTimes(0); + expect(jest.fn()).toReturnTimes(1); + + expect(jest.fn()).toReturnWith('jest'); + expect(jest.fn()).toReturnWith({}); + + expect(true).toStrictEqual(false); + expect({}).toStrictEqual({}); + + const errInstance = new Error(); + const willThrow = () => { + throw new Error(); + }; + expect(() => {}).toThrow(); + expect(willThrow).toThrow(''); + expect(willThrow).toThrow(errInstance); + expect(jest.fn()).toThrow(Error); + expect(jest.fn(willThrow)).toThrow(/foo/); + + expect(() => {}).toThrowErrorMatchingSnapshot(); + expect(willThrow).toThrowErrorMatchingSnapshot(); + expect(jest.fn()).toThrowErrorMatchingSnapshot(); + expect(jest.fn(willThrow)).toThrowErrorMatchingSnapshot(); + + expect(() => {}).toThrowErrorMatchingInlineSnapshot(); + expect(() => {}).toThrowErrorMatchingInlineSnapshot('Error Message'); + expect(willThrow).toThrowErrorMatchingInlineSnapshot(); + expect(willThrow).toThrowErrorMatchingInlineSnapshot('Error Message'); + expect(jest.fn()).toThrowErrorMatchingInlineSnapshot(); + expect(jest.fn()).toThrowErrorMatchingInlineSnapshot('Error Message'); + expect(jest.fn(willThrow)).toThrowErrorMatchingInlineSnapshot(); + expect(jest.fn(willThrow)).toThrowErrorMatchingInlineSnapshot('Error Message'); + + /* not */ + + expect({}).not.toEqual({}); + expect([]).not.toStrictEqual([]); + + /* Promise matchers */ + + expect(Promise.reject('jest')).rejects.toEqual('jest').then(() => {}); + expect(Promise.reject('jest')).rejects.not.toEqual('other').then(() => {}); + + expect(Promise.resolve('jest')).resolves.toEqual('jest').then(() => {}); + expect(Promise.resolve('jest')).resolves.not.toEqual('other').then(() => {}); + /* type matchers */ + + expect({}).toBe(expect.anything()); + + expect({}).toBe(expect.any(class Foo {})); + expect(new Error()).toBe(expect.any(Error)); + expect(7).toBe(expect.any(Number)); + + expect({}).toBe(expect.arrayContaining(['a', 'b'])); + expect(['abc']).toBe(expect.arrayContaining(['a', 'b'])); + + expect.objectContaining({}); + expect.stringMatching('foo'); + expect.stringMatching(/foo/); + expect.stringContaining('foo'); + + expect({ abc: 'def' }).toBe( + expect.objectContaining({ + abc: expect.arrayContaining([expect.any(Date), {}]), + def: expect.objectContaining({ + foo: 'bar', + }), + ghi: expect.stringMatching('foo'), + }) + ); + + /* Inverse type matchers */ + + expect('How are you?').toEqual(expect.not.stringContaining('Hello world!')); + expect('How are you?').toEqual(expect.not.stringMatching(/Hello world!/)); + expect({ bar: 'baz' }).toEqual(expect.not.objectContaining({ foo: 'bar' })); + expect(['Alice', 'Bob', 'Eve']).toEqual(expect.not.arrayContaining(['Samantha'])); + + /* Miscellaneous */ + + expect.hasAssertions(); + expect.assertions(0); + expect.assertions(9001); + }); +}); + +/* Custom matchers and CustomExpect */ +describe('', () => { + it('', () => { + const customMatcher = (expected: any, actual: {prop: string}, option1: boolean) => { + return {pass: true, message: () => ''}; + }; + const asyncMatcher = () => { + return Promise.resolve({pass: true, message: () => ''}); + }; + + const customMatchers = {customMatcher, asyncMatcher}; + expect.extend(customMatchers); + const extendedExpect: jest.ExtendedExpect = expect as any; + + // extracting matcher types + const matchers = extendedExpect({thing: true}); + let nonPromiseMatchers: jest.NonPromiseMatchers = matchers; + const isNot = true; + if (isNot) { + nonPromiseMatchers = matchers.not; + } + // retains U from (actual: U) => JestExtendedMatchers; - BUT CANNOT DO THAT WITH CUSTOM... + nonPromiseMatchers.toMatchInlineSnapshot({thing: extendedExpect.any(Boolean)}); + // $ExpectError + nonPromiseMatchers.toMatchInlineSnapshot({notthing: extendedExpect.any(Boolean)}); + + let promiseMatchers: jest.PromiseMatchers = matchers.rejects; + if (isNot) { + promiseMatchers = matchers.rejects.not; + } + // $ExpectType Promise + promiseMatchers.customMatcher({prop: ''}, true); + + // retains built in asymmetric matcher + extendedExpect.not.arrayContaining; + + extendedExpect.customMatcher({prop: 'good'}, false).asymmetricMatch({}).valueOf(); + // $ExpectError + extendedExpect.customMatcher({prop: {not: 'good'}}, false); + + extendedExpect.not.customMatcher({prop: 'good'}, false).asymmetricMatch({}).valueOf(); + // $ExpectError + extendedExpect.not.customMatcher({prop: 'good'}, 'bad').asymmetricMatch({}).valueOf(); + + // $ExpectError + const asynMatcherExcluded = extendedExpect.asyncMatcher; + + extendedExpect('').customMatcher({prop: 'good'}, true); + // $ExpectError + extendedExpect('').customMatcher({prop: 'good'}, 'bad'); + + extendedExpect('').not.customMatcher({prop: 'good'}, true); + // $ExpectError + extendedExpect('').not.customMatcher({prop: 'good'}, 'bad'); + + extendedExpect(Promise.resolve('')).resolves.customMatcher({prop: 'good'}, true).then(() => {}); + // $ExpectError + extendedExpect(Promise.resolve('')).resolves.customMatcher({prop: 'good'}, 'bad').then(() => {}); + + extendedExpect(Promise.resolve('')).resolves.not.customMatcher({prop: 'good'}, true).then(() => {}); + // $ExpectError + extendedExpect(Promise.resolve('')).resolves.not.customMatcher({prop: 'good'}, 'bad').then(() => {}); + + extendedExpect(Promise.reject('')).rejects.customMatcher({prop: 'good'}, true).then(() => {}); + // $ExpectError + extendedExpect(Promise.reject('')).rejects.customMatcher({prop: 'good'}, 'bad').then(() => {}); + + extendedExpect(Promise.reject('')).rejects.not.customMatcher({prop: 'good'}, true).then(() => {}); + // $ExpectError + extendedExpect(Promise.reject('')).rejects.not.customMatcher({prop: 'good'}, 'bad').then(() => {}); + }); +}); + +/* Jasmine status changers */ + +describe('', () => { + it('', () => { + pending(); + pending('reason'); + + fail(); + fail('error'); + fail(new Error('reason')); + fail({}); + }); +}); + +/* Jasmine clocks and timing */ + +jasmine.DEFAULT_TIMEOUT_INTERVAL = 9001; + +const clock = jasmine.clock(); + +clock.install(); + +clock.mockDate(); +clock.mockDate(undefined); +clock.mockDate(new Date()); + +clock.tick(0); +clock.tick(9001); + +/* Jasmine matchers */ + +expect({}).toBe(jasmine.anything()); + +expect({}).toBe(jasmine.any(class Foo {})); +expect(new Error()).toBe(jasmine.any(Error)); +expect(7).toBe(jasmine.any(Number)); + +expect({}).toBe(jasmine.arrayContaining(['a', 'b'])); +expect(['abc']).toBe(jasmine.arrayContaining(['a', 'b'])); + +jasmine.arrayContaining([]); +new (jasmine.arrayContaining([]))([]); +const arrayContained: boolean = jasmine.arrayContaining([]).asymmetricMatch([]); +const arrayContainedName: string = jasmine.arrayContaining([]).jasmineToString(); + +jasmine.objectContaining({}); +new (jasmine.objectContaining({}))({}); +const objectContained: boolean = jasmine.objectContaining({}).jasmineMatches({}, ['abc'], ['def']); +const objectContainedName: string = jasmine.objectContaining({}).jasmineToString(); + +jasmine.stringMatching('foo'); +jasmine.stringMatching(/foo/); +new (jasmine.stringMatching('foo'))({}); +const stringContained: boolean = jasmine.stringMatching(/foo/).jasmineMatches({}); +const stringContainedName: string = jasmine.stringMatching('foo').jasmineToString(); + +expect({ abc: 'def' }).toBe( + jasmine.objectContaining({ + abc: jasmine.arrayContaining([jasmine.any(Date), {}]), + def: jasmine.objectContaining({ + foo: 'bar', + }), + ghi: jasmine.stringMatching('foo'), + }) +); + +/* Jasmine spies */ + +describe('', () => { + it('', () => { + let spy = jasmine.createSpy(); + jasmine.createSpy('name'); + jasmine.createSpy('name', () => {}); + jasmine.createSpy('name', (arg: {}) => arg); + jasmine.createSpy('name', (...args: string[]) => args.join('')); + + spy = jasmine + .createSpy() + .and.callFake(() => {}) + .and.callFake((arg: {}) => arg) + .and.callFake((...args: string[]) => args.join('')) + .and.callThrough() + .and.returnValue('jasmine') + .and.returnValue({}) + .and.returnValues() + .and.returnValues('jasmine') + .and.returnValues({}, {}) + .and.stub() + .and.throwError('message'); + + const identity: string = spy.identity; + + let args: any[]; + args = spy.mostRecentCall.args; + args = spy.argsForCall[0]; + args = spy.calls.allArgs(); + args = spy.calls.argsFor(0); + + const spyCalled: boolean = spy.calls.any(); + + const wasCalled: boolean = spy.wasCalled; + + for (const call of [...spy.calls.all(), spy.calls.first(), spy.calls.mostRecent()]) { + const callType: jasmine.CallInfo = call; + const callArgs: any[] = call.args; + const { object, returnValue } = call; + } + + spy.calls.reset(); + + const spyReturn = spy(); + + /* Jasmine spy objects */ + + let spyObject = { + abc() { + return ''; + }, + def: 7, + }; + + spyObject = jasmine.createSpyObj('baseName', ['abc']); + spyObject = jasmine.createSpyObj('baseName', ['abc']); + + const newSpyObject: typeof spyObject = jasmine.createSpyObj('baseName', ['abc']); + }); +}); + +/* Jasmine pp */ + +const pp: string = jasmine.pp({}); + +/* Jasmine equality testers */ + +const equalityTesterObject = (first: {}, second: {}) => false; +const equalityTesterString: jasmine.CustomEqualityTester = (first: string, second: string) => first === second; + +jasmine.addCustomEqualityTester(equalityTesterObject); +jasmine.addCustomEqualityTester(equalityTesterObject); + +/* Jasmine matchers */ + +const customMatcherFactoriesNone = {}; +const customMatcherFactoriesIndex: { [i: string]: jasmine.CustomMatcherFactory } = {}; +const customMatcherFactoriesManual = { + abc: () => ({ + compare: (actual: '', expected: '', ...args: Array<{}>) => ({ + pass: true, + message: '', + }), + }), + def: (util: jasmine.MatchersUtil, customEqualityTestesr: jasmine.CustomEqualityTester): jasmine.CustomMatcher => ({ + compare(actual: T, expected: T): jasmine.CustomMatcherResult { + return { + pass: actual === expected, + message: () => 'foo', + }; + }, + }), +}; + +const matchersUtil1 = { + buildFailureMessage: () => '', + contains: (haystack: string, needle: string) => haystack.indexOf(needle) !== -1, + equals: (a: {}, b: {}) => false, +}; + +let matchersUtil2: jasmine.MatchersUtil = { + buildFailureMessage(matcherName: string, isNot: boolean, actual: any, ...expected: any[]): string { + return `${matcherName}${isNot ? '1' : '0'}${actual}${expected.join('')}`; + }, + contains(haystack: T[], needle: T, customTesters?: jasmine.CustomEqualityTester[]) { + return true; + }, + equals: (a: {}, b: {}, customTesters?: jasmine.CustomEqualityTester[]) => false, +}; + +// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/26368 + +describe.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])('.add(%i, %i)', (a: number, b: number, expected: number) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); +}); + +interface Case { + a: number; + b: number; + expected: number; +} + +describe.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('$a + $b', ({ a, b, expected }: Case) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); +}); + +describe.only.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])('.add(%i, %i)', (a, b, expected) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); +}); + +describe.only.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('$a + $b', ({ a, b, expected }: Case) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); +}); + +describe.skip.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])('.add(%i, %i)', (a, b, expected) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); +}); + +describe.skip.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('$a + $b', ({ a, b, expected }: Case) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); +}); + +test.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])('.add(%i, %i)', (a, b, expected) => { + expect(a + b).toBe(expected); +}); + +test.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])( + '.add(%i, %i)', + (a, b, expected) => { + expect(a + b).toBe(expected); + }, + 5000 +); + +declare const constCases: [['a', 'b', 'ab'], ['d', 2, 'd2']]; +test.each(constCases)('%s + %s', (...args) => { + // following assertion is skipped because of flaky testing + // _$ExpectType ["a", "b", "ab"] | ["d", 2, "d2"] + args; +}); + +declare const constCasesWithMoreThanTen: [ + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], + [91, 92, 93, 94, 95, 96, 97, 98, 99, 910, 911] +]; + +test.each(constCasesWithMoreThanTen)('should fall back with more than 10 args', (...args) => { + // following assertion is skipped because of flaky testing + // _$ExpectType [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] | [91, 92, 93, 94, 95, 96, 97, 98, 99, 910, 911] + args; +}); + +test.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('returns $expected when $a is added $b', ({ a, b, expected }: Case) => { + expect(a + b).toBe(expected); +}); + +test.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`( + 'returns $expected when $a is added $b', + ({ a, b, expected }: Case) => { + expect(a + b).toBe(expected); + }, + 5000 +); + +test.each([ + [1, "1"], + [2, "2"] +])("", (a, b) => { + a; // $ExpectType number + b; // $ExpectType string +}); + +test.only.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])('.add(%i, %i)', (a, b, expected) => { + expect(a + b).toBe(expected); +}); + +test.only.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('returns $expected when $a is added $b', ({ a, b, expected }: Case) => { + expect(a + b).toBe(expected); +}); + +expect('').toHaveProperty('path.to.thing'); diff --git a/types/jest/ts3.2/tsconfig.json b/types/jest/ts3.2/tsconfig.json new file mode 100644 index 000000000000000..dc2701483baba15 --- /dev/null +++ b/types/jest/ts3.2/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["dom", "es6", "esnext", "es2020"], + "noImplicitAny": true, + "noImplicitThis": false, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../../", + "typeRoots": ["../../"], + "target": "esnext", + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "jest-tests.ts" + ] +} diff --git a/types/jest/ts3.2/tslint.json b/types/jest/ts3.2/tslint.json new file mode 100644 index 000000000000000..ad93d8fc0d9ca6b --- /dev/null +++ b/types/jest/ts3.2/tslint.json @@ -0,0 +1,6 @@ +{ + "extends": "dtslint/dt.json", + "rules": { + "no-unnecessary-generics": false + } +} \ No newline at end of file diff --git a/types/jest/ts3.8/index.d.ts b/types/jest/ts3.8/index.d.ts new file mode 100644 index 000000000000000..59c85752f824720 --- /dev/null +++ b/types/jest/ts3.8/index.d.ts @@ -0,0 +1,1466 @@ +declare var beforeAll: jest.Lifecycle; +declare var beforeEach: jest.Lifecycle; +declare var afterAll: jest.Lifecycle; +declare var afterEach: jest.Lifecycle; +declare var describe: jest.Describe; +declare var fdescribe: jest.Describe; +declare var xdescribe: jest.Describe; +declare var it: jest.It; +declare var fit: jest.It; +declare var xit: jest.It; +declare var test: jest.It; +declare var xtest: jest.It; + +declare const expect: jest.Expect; + +type ExtractEachCallbackArgs> = { + 1: [T[0]], + 2: [T[0], T[1]], + 3: [T[0], T[1], T[2]], + 4: [T[0], T[1], T[2], T[3]], + 5: [T[0], T[1], T[2], T[3], T[4]], + 6: [T[0], T[1], T[2], T[3], T[4], T[5]], + 7: [T[0], T[1], T[2], T[3], T[4], T[5], T[6]], + 8: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7]], + 9: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8]], + 10: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9]], + 'fallback': Array<(T extends ReadonlyArray? U: any)> +}[ + T extends Readonly<[any]> ? 1 + : T extends Readonly<[any, any]> ? 2 + : T extends Readonly<[any, any, any]> ? 3 + : T extends Readonly<[any, any, any, any]> ? 4 + : T extends Readonly<[any, any, any, any, any]> ? 5 + : T extends Readonly<[any, any, any, any, any, any]> ? 6 + : T extends Readonly<[any, any, any, any, any, any, any]> ? 7 + : T extends Readonly<[any, any, any, any, any, any, any, any]> ? 8 + : T extends Readonly<[any, any, any, any, any, any, any, any, any]> ? 9 + : T extends Readonly<[any, any, any, any, any, any, any, any, any, any]> ? 10 + : 'fallback' +]; + +interface NodeRequire { + /** + * Returns the actual module instead of a mock, bypassing all checks on + * whether the module should receive a mock implementation or not. + * + * @deprecated Use `jest.requireActual` instead. + */ + requireActual(moduleName: string): any; + /** + * Returns a mock module instead of the actual module, bypassing all checks + * on whether the module should be required normally or not. + * + * @deprecated Use `jest.requireMock`instead. + */ + requireMock(moduleName: string): any; +} + +declare namespace jest { + /** + * Provides a way to add Jasmine-compatible matchers into your Jest context. + */ + function addMatchers(matchers: jasmine.CustomMatcherFactories): typeof jest; + /** + * Disables automatic mocking in the module loader. + */ + function autoMockOff(): typeof jest; + /** + * Enables automatic mocking in the module loader. + */ + function autoMockOn(): typeof jest; + /** + * Clears the mock.calls and mock.instances properties of all mocks. + * Equivalent to calling .mockClear() on every mocked function. + */ + function clearAllMocks(): typeof jest; + /** + * Resets the state of all mocks. + * Equivalent to calling .mockReset() on every mocked function. + */ + function resetAllMocks(): typeof jest; + /** + * available since Jest 21.1.0 + * Restores all mocks back to their original value. + * Equivalent to calling .mockRestore on every mocked function. + * Beware that jest.restoreAllMocks() only works when mock was created with + * jest.spyOn; other mocks will require you to manually restore them. + */ + function restoreAllMocks(): typeof jest; + /** + * Removes any pending timers from the timer system. If any timers have + * been scheduled, they will be cleared and will never have the opportunity + * to execute in the future. + */ + function clearAllTimers(): typeof jest; + /** + * Returns the number of fake timers still left to run. + */ + function getTimerCount(): number; + /** + * Indicates that the module system should never return a mocked version + * of the specified module, including all of the specificied module's dependencies. + */ + function deepUnmock(moduleName: string): typeof jest; + /** + * Disables automatic mocking in the module loader. + */ + function disableAutomock(): typeof jest; + /** + * Mocks a module with an auto-mocked version when it is being required. + */ + function doMock(moduleName: string, factory?: () => unknown, options?: MockOptions): typeof jest; + /** + * Indicates that the module system should never return a mocked version + * of the specified module from require() (e.g. that it should always return the real module). + */ + function dontMock(moduleName: string): typeof jest; + /** + * Enables automatic mocking in the module loader. + */ + function enableAutomock(): typeof jest; + /** + * Creates a mock function. Optionally takes a mock implementation. + */ + function fn(): Mock; + /** + * Creates a mock function. Optionally takes a mock implementation. + */ + function fn(implementation?: (...args: Y) => T): Mock; + /** + * Use the automatic mocking system to generate a mocked version of the given module. + */ + function genMockFromModule(moduleName: string): T; + /** + * Returns whether the given function is a mock function. + */ + function isMockFunction(fn: any): fn is Mock; + /** + * Mocks a module with an auto-mocked version when it is being required. + */ + function mock(moduleName: string, factory?: () => unknown, options?: MockOptions): typeof jest; + /** + * Returns the actual module instead of a mock, bypassing all checks on + * whether the module should receive a mock implementation or not. + */ + function requireActual(moduleName: string): any; + /** + * Returns a mock module instead of the actual module, bypassing all checks + * on whether the module should be required normally or not. + */ + function requireMock(moduleName: string): any; + /** + * Resets the module registry - the cache of all required modules. This is + * useful to isolate modules where local state might conflict between tests. + */ + function resetModuleRegistry(): typeof jest; + /** + * Resets the module registry - the cache of all required modules. This is + * useful to isolate modules where local state might conflict between tests. + */ + function resetModules(): typeof jest; + /** + * Creates a sandbox registry for the modules that are loaded inside the callback function.. + * This is useful to isolate specific modules for every test so that local module state doesn't conflict between tests. + */ + function isolateModules(fn: () => void): typeof jest; + /** + * Runs failed tests n-times until they pass or until the max number of retries is exhausted. + * This only works with jest-circus! + */ + function retryTimes(numRetries: number): typeof jest; + /** + * Exhausts tasks queued by setImmediate(). + */ + function runAllImmediates(): typeof jest; + /** + * Exhausts the micro-task queue (usually interfaced in node via process.nextTick). + */ + function runAllTicks(): typeof jest; + /** + * Exhausts the macro-task queue (i.e., all tasks queued by setTimeout() and setInterval()). + */ + function runAllTimers(): typeof jest; + /** + * Executes only the macro-tasks that are currently pending (i.e., only the + * tasks that have been queued by setTimeout() or setInterval() up to this point). + * If any of the currently pending macro-tasks schedule new macro-tasks, + * those new tasks will not be executed by this call. + */ + function runOnlyPendingTimers(): typeof jest; + /** + * (renamed to `advanceTimersByTime` in Jest 21.3.0+) Executes only the macro + * task queue (i.e. all tasks queued by setTimeout() or setInterval() and setImmediate()). + */ + function runTimersToTime(msToRun: number): typeof jest; + /** + * Advances all timers by msToRun milliseconds. All pending "macro-tasks" that have been + * queued via setTimeout() or setInterval(), and would be executed within this timeframe + * will be executed. + */ + function advanceTimersByTime(msToRun: number): typeof jest; + /** + * Advances all timers by the needed milliseconds so that only the next + * timeouts/intervals will run. Optionally, you can provide steps, so it + * will run steps amount of next timeouts/intervals. + */ + function advanceTimersToNextTimer(step?: number): void; + /** + * Explicitly supplies the mock object that the module system should return + * for the specified module. + */ + function setMock(moduleName: string, moduleExports: T): typeof jest; + /** + * Set the default timeout interval for tests and before/after hooks in milliseconds. + * Note: The default timeout interval is 5 seconds if this method is not called. + */ + function setTimeout(timeout: number): typeof jest; + /** + * Creates a mock function similar to jest.fn but also tracks calls to `object[methodName]` + * + * Note: By default, jest.spyOn also calls the spied method. This is different behavior from most + * other test libraries. + * + * @example + * + * const video = require('./video'); + * + * test('plays video', () => { + * const spy = jest.spyOn(video, 'play'); + * const isPlaying = video.play(); + * + * expect(spy).toHaveBeenCalled(); + * expect(isPlaying).toBe(true); + * + * spy.mockReset(); + * spy.mockRestore(); + * }); + */ + function spyOn>>( + object: T, + method: M, + accessType: 'get' + ): SpyInstance[M], []>; + function spyOn>>( + object: T, + method: M, + accessType: 'set' + ): SpyInstance[M]]>; + function spyOn>>( + object: T, + method: M + ): Required[M] extends (...args: any[]) => any + ? SpyInstance[M]>, ArgsType[M]>> + : never; + function spyOn>>( + object: T, + method: M + ): Required[M] extends new (...args: any[]) => any + ? SpyInstance[M]>, ConstructorArgsType[M]>> + : never; + /** + * Indicates that the module system should never return a mocked version of + * the specified module from require() (e.g. that it should always return the real module). + */ + function unmock(moduleName: string): typeof jest; + /** + * Instructs Jest to use fake versions of the standard timer functions. + */ + function useFakeTimers(): typeof jest; + /** + * Instructs Jest to use the real versions of the standard timer functions. + */ + function useRealTimers(): typeof jest; + + interface MockOptions { + virtual?: boolean; + } + + type EmptyFunction = () => void; + type ArgsType = T extends (...args: infer A) => any ? A : never; + type ConstructorArgsType = T extends new (...args: infer A) => any ? A : never; + type RejectedValue = T extends PromiseLike ? any : never; + type ResolvedValue = T extends PromiseLike ? U | T : never; + // see https://github.com/Microsoft/TypeScript/issues/25215 + type NonFunctionPropertyNames = { [K in keyof T]: T[K] extends (...args: any[]) => any ? never : K }[keyof T] & + string; + type FunctionPropertyNames = { [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never }[keyof T] & + string; + type ConstructorPropertyNames = { [K in keyof T]: T[K] extends new (...args: any[]) => any ? K : never }[keyof T] & + string; + + interface DoneCallback { + (...args: any[]): any; + fail(error?: string | { message: string }): any; + } + + type ProvidesCallback = (cb: DoneCallback) => any; + + type Lifecycle = (fn: ProvidesCallback, timeout?: number) => any; + + interface FunctionLike { + readonly name: string; + } + + interface Each { + // Exclusively arrays. + (cases: ReadonlyArray): (name: string, fn: (...args: T) => any, timeout?: number) => void; + >(cases: ReadonlyArray): (name: string, fn: (...args: ExtractEachCallbackArgs) => any, timeout?: number) => void; + // Not arrays. + (cases: ReadonlyArray): (name: string, fn: (...args: T[]) => any, timeout?: number) => void; + (cases: ReadonlyArray>): ( + name: string, + fn: (...args: any[]) => any, + timeout?: number + ) => void; + (strings: TemplateStringsArray, ...placeholders: any[]): ( + name: string, + fn: (arg: any) => any, + timeout?: number + ) => void; + } + + /** + * Creates a test closure + */ + interface It { + /** + * Creates a test closure. + * + * @param name The name of your test + * @param fn The function for your test + * @param timeout The timeout for an async function test + */ + (name: string, fn?: ProvidesCallback, timeout?: number): void; + /** + * Only runs this test in the current file. + */ + only: It; + /** + * Skips running this test in the current file. + */ + skip: It; + /** + * Sketch out which tests to write in the future. + */ + todo: It; + /** + * Experimental and should be avoided. + */ + concurrent: It; + /** + * Use if you keep duplicating the same test with different data. `.each` allows you to write the + * test once and pass data in. + * + * `.each` is available with two APIs: + * + * #### 1 `test.each(table)(name, fn)` + * + * - `table`: Array of Arrays with the arguments that are passed into the test fn for each row. + * - `name`: String the title of the test block. + * - `fn`: Function the test to be ran, this is the function that will receive the parameters in each row as function arguments. + * + * + * #### 2 `test.each table(name, fn)` + * + * - `table`: Tagged Template Literal + * - `name`: String the title of the test, use `$variable` to inject test data into the test title from the tagged template expressions. + * - `fn`: Function the test to be ran, this is the function that will receive the test data object.. + * + * @example + * + * // API 1 + * test.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])( + * '.add(%i, %i)', + * (a, b, expected) => { + * expect(a + b).toBe(expected); + * }, + * ); + * + * // API 2 + * test.each` + * a | b | expected + * ${1} | ${1} | ${2} + * ${1} | ${2} | ${3} + * ${2} | ${1} | ${3} + * `('returns $expected when $a is added $b', ({a, b, expected}) => { + * expect(a + b).toBe(expected); + * }); + * + */ + each: Each; + } + + interface Describe { + // tslint:disable-next-line ban-types + (name: number | string | Function | FunctionLike, fn: EmptyFunction): void; + /** Only runs the tests inside this `describe` for the current file */ + only: Describe; + /** Skips running the tests inside this `describe` for the current file */ + skip: Describe; + each: Each; + } + + type PrintLabel = (string: string) => string; + + type MatcherHintColor = (arg: string) => string; + + interface MatcherHintOptions { + comment?: string; + expectedColor?: MatcherHintColor; + isDirectExpectCall?: boolean; + isNot?: boolean; + promise?: string; + receivedColor?: MatcherHintColor; + secondArgument?: string; + secondArgumentColor?: MatcherHintColor; + } + + interface ChalkFunction { + (text: TemplateStringsArray, ...placeholders: any[]): string; + (...text: any[]): string; + } + + interface ChalkColorSupport { + level: 0 | 1 | 2 | 3; + hasBasic: boolean; + has256: boolean; + has16m: boolean; + } + + type MatcherColorFn = ChalkFunction & { supportsColor: ChalkColorSupport }; + + type EqualityTester = (a: any, b: any) => boolean | undefined; + + interface MatcherUtils { + readonly isNot: boolean; + readonly dontThrow: () => void; + readonly promise: string; + readonly assertionCalls: number; + readonly expectedAssertionsNumber: number | null; + readonly isExpectingAssertions: boolean; + readonly suppressedErrors: any[]; + readonly expand: boolean; + readonly testPath: string; + readonly currentTestName: string; + utils: { + readonly EXPECTED_COLOR: MatcherColorFn; + readonly RECEIVED_COLOR: MatcherColorFn; + readonly INVERTED_COLOR: MatcherColorFn; + readonly BOLD_WEIGHT: MatcherColorFn; + readonly DIM_COLOR: MatcherColorFn; + readonly SUGGEST_TO_CONTAIN_EQUAL: string; + diff(a: any, b: any, options?: import("jest-diff").DiffOptions): string | null; + ensureActualIsNumber(actual: any, matcherName: string, options?: MatcherHintOptions): void; + ensureExpectedIsNumber(actual: any, matcherName: string, options?: MatcherHintOptions): void; + ensureNoExpected(actual: any, matcherName: string, options?: MatcherHintOptions): void; + ensureNumbers(actual: any, expected: any, matcherName: string, options?: MatcherHintOptions): void; + ensureExpectedIsNonNegativeInteger(expected: any, matcherName: string, options?: MatcherHintOptions): void; + matcherHint( + matcherName: string, + received?: string, + expected?: string, + options?: MatcherHintOptions + ): string; + matcherErrorMessage( + hint: string, + generic: string, + specific: string + ): string; + pluralize(word: string, count: number): string; + printReceived(object: any): string; + printExpected(value: any): string; + printWithType(name: string, value: any, print: (value: any) => string): string; + stringify(object: {}, maxDepth?: number): string; + highlightTrailingWhitespace(text: string): string; + + printDiffOrStringify(expected: any, received: any, expectedLabel: string, receivedLabel: string, expand: boolean): string; + + getLabelPrinter(...strings: string[]): PrintLabel; + + iterableEquality: EqualityTester; + subsetEquality: EqualityTester; + }; + /** + * This is a deep-equality function that will return true if two objects have the same values (recursively). + */ + equals(a: any, b: any, customTesters?: EqualityTester[], strictCheck?: boolean): boolean; + [other: string]: any; + } + + interface ExpectExtendMap { + [key: string]: CustomMatcher; + } + + type MatcherContext = MatcherUtils & Readonly; + type CustomMatcher = ( + this: MatcherContext, + received: any, + ...actual: any[] + ) => CustomMatcherResult | Promise; + + interface CustomMatcherResult { + pass: boolean; + message: () => string; + } + + type SnapshotSerializerPlugin = import('pretty-format').Plugin; + + interface InverseAsymmetricMatchers { + /** + * `expect.not.arrayContaining(array)` matches a received array which + * does not contain all of the elements in the expected array. That is, + * the expected array is not a subset of the received array. It is the + * inverse of `expect.arrayContaining`. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: E[]): any; + /** + * `expect.not.objectContaining(object)` matches any received object + * that does not recursively match the expected properties. That is, the + * expected object is not a subset of the received object. Therefore, + * it matches a received object which contains properties that are not + * in the expected object. It is the inverse of `expect.objectContaining`. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: E): any; + /** + * `expect.not.stringMatching(string | regexp)` matches the received + * string that does not match the expected regexp. It is the inverse of + * `expect.stringMatching`. + */ + stringMatching(str: string | RegExp): any; + /** + * `expect.not.stringContaining(string)` matches the received string + * that does not contain the exact expected string. It is the inverse of + * `expect.stringContaining`. + */ + stringContaining(str: string): any; + } + interface MatcherState { + assertionCalls: number; + currentTestName: string; + expand: boolean; + expectedAssertionsNumber: number; + isExpectingAssertions?: boolean; + suppressedErrors: Error[]; + testPath: string; + } + /** + * The `expect` function is used every time you want to test a value. + * You will rarely call `expect` by itself. + */ + interface Expect { + /** + * The `expect` function is used every time you want to test a value. + * You will rarely call `expect` by itself. + * + * @param actual The value to apply matchers against. + */ + (actual: T): JestMatchers; + /** + * Matches anything but null or undefined. You can use it inside `toEqual` or `toBeCalledWith` instead + * of a literal value. For example, if you want to check that a mock function is called with a + * non-null argument: + * + * @example + * + * test('map calls its argument with a non-null argument', () => { + * const mock = jest.fn(); + * [1].map(x => mock(x)); + * expect(mock).toBeCalledWith(expect.anything()); + * }); + * + */ + anything(): any; + /** + * Matches anything that was created with the given constructor. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * @example + * + * function randocall(fn) { + * return fn(Math.floor(Math.random() * 6 + 1)); + * } + * + * test('randocall calls its callback with a number', () => { + * const mock = jest.fn(); + * randocall(mock); + * expect(mock).toBeCalledWith(expect.any(Number)); + * }); + */ + any(classType: any): any; + /** + * Matches any array made up entirely of elements in the provided array. + * You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. + * + * Optionally, you can provide a type for the elements via a generic. + */ + arrayContaining(arr: E[]): any; + /** + * Verifies that a certain number of assertions are called during a test. + * This is often useful when testing asynchronous code, in order to + * make sure that assertions in a callback actually got called. + */ + assertions(num: number): void; + /** + * Verifies that at least one assertion is called during a test. + * This is often useful when testing asynchronous code, in order to + * make sure that assertions in a callback actually got called. + */ + hasAssertions(): void; + /** + * You can use `expect.extend` to add your own matchers to Jest. + */ + extend(obj: ExpectExtendMap): void; + /** + * Adds a module to format application-specific data structures for serialization. + */ + addSnapshotSerializer(serializer: SnapshotSerializerPlugin): void; + /** + * Matches any object that recursively matches the provided keys. + * This is often handy in conjunction with other asymmetric matchers. + * + * Optionally, you can provide a type for the object via a generic. + * This ensures that the object contains the desired structure. + */ + objectContaining(obj: E): any; + /** + * Matches any string that contains the exact provided string + */ + stringMatching(str: string | RegExp): any; + /** + * Matches any received string that contains the exact expected string + */ + stringContaining(str: string): any; + + not: InverseAsymmetricMatchers; + + setState(state: object): void; + getState(): MatcherState & Record; + } + + type JestMatchers = JestMatchersShape, Matchers, T>>; + + type JestMatchersShape = { + /** + * 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: AndNot, + /** + * Unwraps the reason of a rejected promise so any other matcher can be chained. + * If the promise is fulfilled the assertion fails. + */ + rejects: AndNot + } & AndNot; + type AndNot = T & { + not: T + }; + // should be R extends void|Promise but getting dtslint error + interface Matchers { + /** + * Ensures the last call to a mock function was provided specific args. + * + * Optionally, you can provide a type for the expected arguments via a generic. + * Note that the type must be either an array or a tuple. + */ + lastCalledWith(...args: E): R; + /** + * Ensure that the last call to a mock function has returned a specified value. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + lastReturnedWith(value: E): R; + /** + * Ensure that a mock function is called with specific arguments on an Nth call. + * + * Optionally, you can provide a type for the expected arguments via a generic. + * Note that the type must be either an array or a tuple. + */ + nthCalledWith(nthCall: number, ...params: E): R; + /** + * Ensure that the nth call to a mock function has returned a specified value. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + nthReturnedWith(n: number, value: E): R; + /** + * Checks that a value is what you expect. It uses `Object.is` to check strict equality. + * Don't use `toBe` with floating-point numbers. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toBe(expected: E): R; + /** + * Ensures that a mock function is called. + */ + toBeCalled(): R; + /** + * Ensures that a mock function is called an exact number of times. + */ + toBeCalledTimes(expected: number): R; + /** + * Ensure that a mock function is called with specific arguments. + * + * Optionally, you can provide a type for the expected arguments via a generic. + * Note that the type must be either an array or a tuple. + */ + toBeCalledWith(...args: E): R; + /** + * Using exact equality with floating point numbers is a bad idea. + * Rounding means that intuitive things fail. + * The default for numDigits is 2. + */ + toBeCloseTo(expected: number, numDigits?: number): R; + /** + * Ensure that a variable is not undefined. + */ + toBeDefined(): R; + /** + * When you don't care what a value is, you just want to + * ensure a value is false in a boolean context. + */ + toBeFalsy(): R; + /** + * For comparing numbers or big integer values. + */ + toBeGreaterThan(expected: number | bigint): R; + /** + * For comparing numbers or big integer values. + */ + toBeGreaterThanOrEqual(expected: number | bigint): R; + /** + * Ensure that an object is an instance of a class. + * This matcher uses `instanceof` underneath. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toBeInstanceOf(expected: E): R; + /** + * For comparing numbers or big integer values. + */ + toBeLessThan(expected: number | bigint): R; + /** + * For comparing numbers or big integer values. + */ + toBeLessThanOrEqual(expected: number | bigint): R; + /** + * 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. + */ + toBeNull(): R; + /** + * 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. + */ + toBeTruthy(): R; + /** + * Used to check that a variable is undefined. + */ + toBeUndefined(): R; + /** + * Used to check that a variable is NaN. + */ + toBeNaN(): R; + /** + * 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. + * It can also check whether a string is a substring of another string. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toContain(expected: E): R; + /** + * 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. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toContainEqual(expected: E): R; + /** + * 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. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toEqual(expected: E): R; + /** + * Ensures that a mock function is called. + */ + toHaveBeenCalled(): R; + /** + * Ensures that a mock function is called an exact number of times. + */ + toHaveBeenCalledTimes(expected: number): R; + /** + * Ensure that a mock function is called with specific arguments. + * + * Optionally, you can provide a type for the expected arguments via a generic. + * Note that the type must be either an array or a tuple. + */ + toHaveBeenCalledWith(...params: E): R; + /** + * Ensure that a mock function is called with specific arguments on an Nth call. + * + * Optionally, you can provide a type for the expected arguments via a generic. + * Note that the type must be either an array or a tuple. + */ + toHaveBeenNthCalledWith(nthCall: number, ...params: E): R; + /** + * If you have a mock function, you can use `.toHaveBeenLastCalledWith` + * to test what arguments it was last called with. + * + * Optionally, you can provide a type for the expected arguments via a generic. + * Note that the type must be either an array or a tuple. + */ + toHaveBeenLastCalledWith(...params: E): 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 + * no matter what value you provided as the expected return value. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toHaveLastReturnedWith(expected: E): R; + /** + * Used to check that an object has a `.length` property + * and it is set to a certain numeric value. + */ + toHaveLength(expected: number): R; + /** + * 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. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toHaveNthReturnedWith(nthCall: number, expected: E): 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 + * the keyPath for deep references. + * + * Optionally, you can provide a value to check if it's equal to the value present at keyPath + * on the target object. This matcher uses 'deep equality' (like `toEqual()`) and recursively checks + * the equality of all fields. + * + * @example + * + * expect(houseForSale).toHaveProperty('kitchen.area', 20); + */ + toHaveProperty(propertyPath: string | any[], value?: E): R; + /** + * Use to test that the mock function successfully returned (i.e., did not throw an error) at least one time + */ + toHaveReturned(): R; + /** + * 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. + */ + toHaveReturnedTimes(expected: number): R; + /** + * Use to ensure that a mock function returned a specific value. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toHaveReturnedWith(expected: E): R; + /** + * Check that a string matches a regular expression. + */ + toMatch(expected: string | RegExp): R; + /** + * Used to check that a JavaScript object matches a subset of the properties of an object + * + * Optionally, you can provide an object to use as Generic type for the expected value. + * This ensures that the matching object matches the structure of the provided object-like type. + * + * @example + * + * type House = { + * bath: boolean; + * bedrooms: number; + * kitchen: { + * amenities: string[]; + * area: number; + * wallColor: string; + * } + * }; + * + * expect(desiredHouse).toMatchObject(...standardHouse, kitchen: {area: 20}) // wherein standardHouse is some base object of type House + */ + toMatchObject(expected: E): R; + /** + * This ensures that a value matches the most recent snapshot with property matchers. + * Check out [the Snapshot Testing guide](http://facebook.github.io/jest/docs/snapshot-testing.html) for more information. + */ + toMatchSnapshot(propertyMatchers: Partial, snapshotName?: string): R; + /** + * This ensures that a value matches the most recent snapshot. + * Check out [the Snapshot Testing guide](http://facebook.github.io/jest/docs/snapshot-testing.html) 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](http://facebook.github.io/jest/docs/snapshot-testing.html) for more information. + */ + toMatchInlineSnapshot(propertyMatchers: Partial, 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](http://facebook.github.io/jest/docs/snapshot-testing.html) for more information. + */ + toMatchInlineSnapshot(snapshot?: string): R; + /** + * Ensure that a mock function has returned (as opposed to thrown) at least once. + */ + toReturn(): R; + /** + * Ensure that a mock function has returned (as opposed to thrown) a specified number of times. + */ + toReturnTimes(count: number): R; + /** + * Ensure that a mock function has returned a specified value at least once. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toReturnWith(value: E): R; + /** + * Use to test that objects have the same types as well as structure. + * + * Optionally, you can provide a type for the expected value via a generic. + * This is particuarly useful for ensuring expected objects have the right structure. + */ + toStrictEqual(expected: E): R; + /** + * Used to test that a function throws when it is called. + */ + toThrow(error?: string | Constructable | RegExp | Error): R; + /** + * If you want to test that a specific error is thrown inside a function. + */ + toThrowError(error?: string | Constructable | RegExp | Error): R; + /** + * Used to test that a function throws a error matching the most recent snapshot when it is called. + */ + toThrowErrorMatchingSnapshot(): 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. + */ + toThrowErrorMatchingInlineSnapshot(snapshot?: string): R; + } + + type RemoveFirstFromTuple = + T['length'] extends 0 ? [] : + (((...b: T) => void) extends (a: any, ...b: infer I) => void ? I : []); + + type Parameters any> = T extends (...args: infer P) => any ? P : never; + + interface AsymmetricMatcher { + asymmetricMatch(other: unknown): boolean; + } + type NonAsyncMatchers = { + [K in keyof TMatchers]: ReturnType extends Promise? never: K + }[keyof TMatchers]; + type CustomAsyncMatchers = {[K in NonAsyncMatchers]: CustomAsymmetricMatcher}; + type CustomAsymmetricMatcher any> = (...args: RemoveFirstFromTuple>) => AsymmetricMatcher; + + // should be TMatcherReturn extends void|Promise but getting dtslint error + type CustomJestMatcher any, TMatcherReturn> = (...args: RemoveFirstFromTuple>) => TMatcherReturn; + + type ExpectProperties= { + [K in keyof Expect]: Expect[K] + }; + // should be TMatcherReturn extends void|Promise but getting dtslint error + // Use the `void` type for return types only. Otherwise, use `undefined`. See: https://github.com/Microsoft/dtslint/blob/master/docs/void-return.md + // have added issue https://github.com/microsoft/dtslint/issues/256 - Cannot have type union containing void ( to be used as return type only + type ExtendedMatchers = Matchers & {[K in keyof TMatchers]: CustomJestMatcher}; + type JestExtendedMatchers = JestMatchersShape, ExtendedMatchers, TActual>>; + + // when have called expect.extend + type ExtendedExpectFunction = (actual: TActual) => JestExtendedMatchers; + + type ExtendedExpect= + ExpectProperties & + AndNot> & + ExtendedExpectFunction; + /** + * Construct a type with the properties of T except for those in type K. + */ + type Omit = Pick>; + type NonPromiseMatchers = Omit; + type PromiseMatchers = Omit; + + interface Constructable { + new (...args: any[]): any; + } + + interface Mock extends Function, MockInstance { + new (...args: Y): T; + (...args: Y): T; + } + + interface SpyInstance extends MockInstance {} + + /** + * Represents a function that has been spied on. + */ + type SpiedFunction any> = SpyInstance, ArgsType>; + + /** + * Wrap a function with mock definitions + * + * @example + * + * import { myFunction } from "./library"; + * jest.mock("./library"); + * + * const mockMyFunction = myFunction as jest.MockedFunction; + * expect(mockMyFunction.mock.calls[0][0]).toBe(42); + */ + type MockedFunction any> = MockInstance, ArgsType> & T; + + /** + * Wrap a class with mock definitions + * + * @example + * + * import { MyClass } from "./libary"; + * jest.mock("./library"); + * + * const mockedMyClass = MyClass as jest.MockedClass; + * + * expect(mockedMyClass.mock.calls[0][0]).toBe(42); // Constructor calls + * expect(mockedMyClass.prototype.myMethod.mock.calls[0][0]).toBe(42); // Method calls + */ + + type MockedClass = MockInstance< + InstanceType, + T extends new (...args: infer P) => any ? P : never + > & { + prototype: T extends { prototype: any } ? Mocked : never; + } & T; + + /** + * Wrap an object or a module with mock definitions + * + * @example + * + * jest.mock("../api"); + * import * as api from "../api"; + * + * const mockApi = api as jest.Mocked; + * api.MyApi.prototype.myApiMethod.mockImplementation(() => "test"); + */ + type Mocked = { + [P in keyof T]: T[P] extends (...args: any[]) => any + ? MockInstance, ArgsType> + : T[P] extends Constructable + ? MockedClass + : T[P] + } & + T; + + interface MockInstance { + /** Returns the mock name string set by calling `mockFn.mockName(value)`. */ + getMockName(): string; + /** Provides access to the mock's metadata */ + mock: MockContext; + /** + * Resets all information stored in the mockFn.mock.calls and mockFn.mock.instances arrays. + * + * Often this is useful when you want to clean up a mock's usage data between two assertions. + * + * Beware that `mockClear` will replace `mockFn.mock`, not just `mockFn.mock.calls` and `mockFn.mock.instances`. + * You should therefore avoid assigning mockFn.mock to other variables, temporary or not, to make sure you + * don't access stale data. + */ + mockClear(): this; + /** + * Resets all information stored in the mock, including any initial implementation and mock name given. + * + * This is useful when you want to completely restore a mock back to its initial state. + * + * Beware that `mockReset` will replace `mockFn.mock`, not just `mockFn.mock.calls` and `mockFn.mock.instances`. + * You should therefore avoid assigning mockFn.mock to other variables, temporary or not, to make sure you + * don't access stale data. + */ + mockReset(): this; + /** + * Does everything that `mockFn.mockReset()` does, and also restores the original (non-mocked) implementation. + * + * This is useful when you want to mock functions in certain test cases and restore the original implementation in others. + * + * Beware that `mockFn.mockRestore` only works when mock was created with `jest.spyOn`. Thus you have to take care of restoration + * yourself when manually assigning `jest.fn()`. + * + * The [`restoreMocks`](https://jestjs.io/docs/en/configuration.html#restoremocks-boolean) configuration option is available + * to restore mocks automatically between tests. + */ + mockRestore(): void; + /** + * Returns the function that was set as the implementation of the mock (using mockImplementation). + */ + getMockImplementation(): (...args: Y) => T | undefined; + /** + * Accepts a function that should be used as the implementation of the mock. The mock itself will still record + * all calls that go into and instances that come from itself – the only difference is that the implementation + * will also be executed when the mock is called. + * + * Note: `jest.fn(implementation)` is a shorthand for `jest.fn().mockImplementation(implementation)`. + */ + mockImplementation(fn?: (...args: Y) => T): this; + /** + * Accepts a function that will be used as an implementation of the mock for one call to the mocked function. + * Can be chained so that multiple function calls produce different results. + * + * @example + * + * const myMockFn = jest + * .fn() + * .mockImplementationOnce(cb => cb(null, true)) + * .mockImplementationOnce(cb => cb(null, false)); + * + * myMockFn((err, val) => console.log(val)); // true + * + * myMockFn((err, val) => console.log(val)); // false + */ + mockImplementationOnce(fn: (...args: Y) => T): this; + /** Sets the name of the mock`. */ + mockName(name: string): this; + /** + * Just a simple sugar function for: + * + * @example + * + * jest.fn(function() { + * return this; + * }); + */ + mockReturnThis(): this; + /** + * Accepts a value that will be returned whenever the mock function is called. + * + * @example + * + * const mock = jest.fn(); + * mock.mockReturnValue(42); + * mock(); // 42 + * mock.mockReturnValue(43); + * mock(); // 43 + */ + mockReturnValue(value: T): this; + /** + * Accepts a value that will be returned for one call to the mock function. Can be chained so that + * successive calls to the mock function return different values. When there are no more + * `mockReturnValueOnce` values to use, calls will return a value specified by `mockReturnValue`. + * + * @example + * + * const myMockFn = jest.fn() + * .mockReturnValue('default') + * .mockReturnValueOnce('first call') + * .mockReturnValueOnce('second call'); + * + * // 'first call', 'second call', 'default', 'default' + * console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn()); + * + */ + mockReturnValueOnce(value: T): this; + /** + * Simple sugar function for: `jest.fn().mockImplementation(() => Promise.resolve(value));` + */ + mockResolvedValue(value: ResolvedValue): this; + /** + * Simple sugar function for: `jest.fn().mockImplementationOnce(() => Promise.resolve(value));` + * + * @example + * + * test('async test', async () => { + * const asyncMock = jest + * .fn() + * .mockResolvedValue('default') + * .mockResolvedValueOnce('first call') + * .mockResolvedValueOnce('second call'); + * + * await asyncMock(); // first call + * await asyncMock(); // second call + * await asyncMock(); // default + * await asyncMock(); // default + * }); + * + */ + mockResolvedValueOnce(value: ResolvedValue): this; + /** + * Simple sugar function for: `jest.fn().mockImplementation(() => Promise.reject(value));` + * + * @example + * + * test('async test', async () => { + * const asyncMock = jest.fn().mockRejectedValue(new Error('Async error')); + * + * await asyncMock(); // throws "Async error" + * }); + */ + mockRejectedValue(value: RejectedValue): this; + + /** + * Simple sugar function for: `jest.fn().mockImplementationOnce(() => Promise.reject(value));` + * + * @example + * + * test('async test', async () => { + * const asyncMock = jest + * .fn() + * .mockResolvedValueOnce('first call') + * .mockRejectedValueOnce(new Error('Async error')); + * + * await asyncMock(); // first call + * await asyncMock(); // throws "Async error" + * }); + * + */ + mockRejectedValueOnce(value: RejectedValue): this; + } + + /** + * Represents the result of a single call to a mock function with a return value. + */ + interface MockResultReturn { + type: 'return'; + value: T; + } + /** + * Represents the result of a single incomplete call to a mock function. + */ + interface MockResultIncomplete { + type: 'incomplete'; + value: undefined; + } + /** + * Represents the result of a single call to a mock function with a thrown error. + */ + interface MockResultThrow { + type: 'throw'; + value: any; + } + + type MockResult = MockResultReturn | MockResultThrow | MockResultIncomplete; + + interface MockContext { + calls: Y[]; + instances: T[]; + invocationCallOrder: number[]; + /** + * List of results of calls to the mock function. + */ + results: Array>; + } +} + +// Jest ships with a copy of Jasmine. They monkey-patch its APIs and divergence/deprecation are expected. +// Relevant parts of Jasmine's API are below so they can be changed and removed over time. +// This file can't reference jasmine.d.ts since the globals aren't compatible. + +declare function spyOn(object: T, method: keyof T): jasmine.Spy; +/** + * If you call the function pending anywhere in the spec body, + * no matter the expectations, the spec will be marked pending. + */ +declare function pending(reason?: string): void; +/** + * Fails a test when called within one. + */ +declare function fail(error?: any): never; +declare namespace jasmine { + let DEFAULT_TIMEOUT_INTERVAL: number; + function clock(): Clock; + function any(aclass: any): Any; + function anything(): Any; + function arrayContaining(sample: any[]): ArrayContaining; + function objectContaining(sample: any): ObjectContaining; + function createSpy(name?: string, originalFn?: (...args: any[]) => any): Spy; + function createSpyObj(baseName: string, methodNames: any[]): any; + function createSpyObj(baseName: string, methodNames: any[]): T; + function pp(value: any): string; + function addCustomEqualityTester(equalityTester: CustomEqualityTester): void; + function addMatchers(matchers: CustomMatcherFactories): void; + function stringMatching(value: string | RegExp): Any; + + interface Clock { + install(): void; + uninstall(): void; + /** + * Calls to any registered callback are triggered when the clock isticked forward + * via the jasmine.clock().tick function, which takes a number of milliseconds. + */ + tick(ms: number): void; + mockDate(date?: Date): void; + } + + interface Any { + new (expectedClass: any): any; + jasmineMatches(other: any): boolean; + jasmineToString(): string; + } + + interface ArrayContaining { + new (sample: any[]): any; + asymmetricMatch(other: any): boolean; + jasmineToString(): string; + } + + interface ObjectContaining { + new (sample: any): any; + jasmineMatches(other: any, mismatchKeys: any[], mismatchValues: any[]): boolean; + jasmineToString(): string; + } + + interface Spy { + (...params: any[]): any; + identity: string; + and: SpyAnd; + calls: Calls; + mostRecentCall: { args: any[] }; + argsForCall: any[]; + wasCalled: boolean; + } + + interface SpyAnd { + /** + * By chaining the spy with and.callThrough, the spy will still track all + * calls to it but in addition it will delegate to the actual implementation. + */ + callThrough(): Spy; + /** + * By chaining the spy with and.returnValue, all calls to the function + * will return a specific value. + */ + returnValue(val: any): Spy; + /** + * By chaining the spy with and.returnValues, all calls to the function + * will return specific values in order until it reaches the end of the return values list. + */ + returnValues(...values: any[]): Spy; + /** + * By chaining the spy with and.callFake, all calls to the spy + * will delegate to the supplied function. + */ + callFake(fn: (...args: any[]) => any): Spy; + /** + * By chaining the spy with and.throwError, all calls to the spy + * will throw the specified value. + */ + throwError(msg: string): Spy; + /** + * When a calling strategy is used for a spy, the original stubbing + * behavior can be returned at any time with and.stub. + */ + stub(): Spy; + } + + interface Calls { + /** + * By chaining the spy with calls.any(), + * will return false if the spy has not been called at all, + * and then true once at least one call happens. + */ + any(): boolean; + /** + * By chaining the spy with calls.count(), + * will return the number of times the spy was called + */ + count(): number; + /** + * By chaining the spy with calls.argsFor(), + * will return the arguments passed to call number index + */ + argsFor(index: number): any[]; + /** + * By chaining the spy with calls.allArgs(), + * will return the arguments to all calls + */ + allArgs(): any[]; + /** + * By chaining the spy with calls.all(), will return the + * context (the this) and arguments passed all calls + */ + all(): CallInfo[]; + /** + * By chaining the spy with calls.mostRecent(), will return the + * context (the this) and arguments for the most recent call + */ + mostRecent(): CallInfo; + /** + * By chaining the spy with calls.first(), will return the + * context (the this) and arguments for the first call + */ + first(): CallInfo; + /** + * By chaining the spy with calls.reset(), will clears all tracking for a spy + */ + reset(): void; + } + + interface CallInfo { + /** + * The context (the this) for the call + */ + object: any; + /** + * All arguments passed to the call + */ + args: any[]; + /** + * The return value of the call + */ + returnValue: any; + } + + interface CustomMatcherFactories { + [index: string]: CustomMatcherFactory; + } + + type CustomMatcherFactory = (util: MatchersUtil, customEqualityTesters: CustomEqualityTester[]) => CustomMatcher; + + interface MatchersUtil { + equals(a: any, b: any, customTesters?: CustomEqualityTester[]): boolean; + contains(haystack: ArrayLike | string, needle: any, customTesters?: CustomEqualityTester[]): boolean; + buildFailureMessage(matcherName: string, isNot: boolean, actual: any, ...expected: any[]): string; + } + + type CustomEqualityTester = (first: any, second: any) => boolean; + + interface CustomMatcher { + compare(actual: T, expected: T, ...args: any[]): CustomMatcherResult; + compare(actual: any, ...expected: any[]): CustomMatcherResult; + } + + interface CustomMatcherResult { + pass: boolean; + message: string | (() => string); + } + + interface ArrayLike { + length: number; + [n: number]: T; + } +} diff --git a/types/jest/ts3.8/jest-tests.ts b/types/jest/ts3.8/jest-tests.ts new file mode 100644 index 000000000000000..499c303e55add1d --- /dev/null +++ b/types/jest/ts3.8/jest-tests.ts @@ -0,0 +1,1448 @@ +/* Lifecycle events */ + +beforeAll(() => {}); +beforeAll((done: jest.DoneCallback) => {}); +beforeAll((done: jest.DoneCallback) => done.fail(), 9001); + +beforeEach(() => {}); +beforeEach((done: jest.DoneCallback) => {}); +beforeEach((done: jest.DoneCallback) => done.fail(), 9001); + +afterAll(() => {}); +afterAll((done: jest.DoneCallback) => {}); +afterAll((done: jest.DoneCallback) => done.fail(), 9001); + +afterEach(() => {}); +afterEach((done: jest.DoneCallback) => {}); +afterEach((done: jest.DoneCallback) => done.fail(), 9001); + +/* describe */ + +describe(0, () => {}); +describe('name', () => {}); +describe(() => {}, () => {}); +describe({ name: 'name' }, () => {}); + +describe.only(0, () => {}); +describe.only('name', () => {}); +describe.only(() => {}, () => {}); +describe.only({ name: 'name' }, () => {}); + +describe.skip(0, () => {}); +describe.skip('name', () => {}); +describe.skip(() => {}, () => {}); +describe.skip({ name: 'name' }, () => {}); + +fdescribe(0, () => {}); +fdescribe('name', () => {}); +fdescribe(() => {}, () => {}); +fdescribe({ name: 'name' }, () => {}); + +fdescribe.only(0, () => {}); +fdescribe.only('name', () => {}); +fdescribe.only(() => {}, () => {}); +fdescribe.only({ name: 'name' }, () => {}); + +fdescribe.skip(0, () => {}); +fdescribe.skip('name', () => {}); +fdescribe.skip(() => {}, () => {}); +fdescribe.skip({ name: 'name' }, () => {}); + +xdescribe(0, () => {}); +xdescribe('name', () => {}); +xdescribe(() => {}, () => {}); +xdescribe({ name: 'name' }, () => {}); + +xdescribe.only(0, () => {}); +xdescribe.only('name', () => {}); +xdescribe.only(() => {}, () => {}); +xdescribe.only({ name: 'name' }, () => {}); + +xdescribe.skip(0, () => {}); +xdescribe.skip('name', () => {}); +xdescribe.skip(() => {}, () => {}); +xdescribe.skip({ name: 'name' }, () => {}); + +/* it */ + +it('name', () => {}); +it('name', async () => {}); +it('name', () => {}, 9001); +it('name', async () => {}, 9001); +it('name', (callback: jest.DoneCallback) => {}, 9001); + +it.only('name', () => {}); +it.only('name', async () => {}); +it.only('name', () => {}, 9001); +it.only('name', async () => {}, 9001); +it.only('name', (callback: jest.DoneCallback) => {}, 9001); + +it.skip('name', () => {}); +it.skip('name', async () => {}); +it.skip('name', () => {}, 9001); +it.skip('name', async () => {}, 9001); +it.skip('name', (callback: jest.DoneCallback) => {}, 9001); + +it.todo('name', () => {}); +it.todo('name', async () => {}); +it.todo('name', () => {}, 9001); +it.todo('name', async () => {}, 9001); +it.todo('name', (callback: jest.DoneCallback) => {}, 9001); + +it.concurrent('name', () => {}); +it.concurrent('name', async () => {}); +it.concurrent('name', () => {}, 9001); +it.concurrent('name', async () => {}, 9001); +it.concurrent('name', (callback: jest.DoneCallback) => {}, 9001); + +fit('name', () => {}); +fit('name', async () => {}); +fit('name', () => {}, 9001); +fit('name', async () => {}, 9001); +fit('name', (callback: jest.DoneCallback) => {}, 9001); + +fit.only('name', () => {}); +fit.only('name', async () => {}); +fit.only('name', () => {}, 9001); +fit.only('name', async () => {}, 9001); +fit.only('name', (callback: jest.DoneCallback) => {}, 9001); + +fit.skip('name', () => {}); +fit.skip('name', async () => {}); +fit.skip('name', () => {}, 9001); +fit.skip('name', async () => {}, 9001); +fit.skip('name', (callback: jest.DoneCallback) => {}, 9001); + +fit.todo('name', () => {}); +fit.todo('name', async () => {}); +fit.todo('name', () => {}, 9001); +fit.todo('name', async () => {}, 9001); +fit.todo('name', (callback: jest.DoneCallback) => {}, 9001); + +fit.concurrent('name', () => {}); +fit.concurrent('name', async () => {}); +fit.concurrent('name', () => {}, 9001); +fit.concurrent('name', async () => {}, 9001); +fit.concurrent('name', (callback: jest.DoneCallback) => {}, 9001); + +xit('name', () => {}); +xit('name', async () => {}); +xit('name', () => {}, 9001); +xit('name', async () => {}, 9001); +xit('name', (callback: jest.DoneCallback) => {}, 9001); + +xit.only('name', () => {}); +xit.only('name', async () => {}); +xit.only('name', () => {}, 9001); +xit.only('name', async () => {}, 9001); +xit.only('name', (callback: jest.DoneCallback) => {}, 9001); + +xit.skip('name', () => {}); +xit.skip('name', async () => {}); +xit.skip('name', () => {}, 9001); +xit.skip('name', async () => {}, 9001); +xit.skip('name', (callback: jest.DoneCallback) => {}, 9001); + +xit.todo('name', () => {}); +xit.todo('name', async () => {}); +xit.todo('name', () => {}, 9001); +xit.todo('name', async () => {}, 9001); +xit.todo('name', (callback: jest.DoneCallback) => {}, 9001); + +xit.concurrent('name', () => {}); +xit.concurrent('name', async () => {}); +xit.concurrent('name', () => {}, 9001); +xit.concurrent('name', async () => {}, 9001); +xit.concurrent('name', (callback: jest.DoneCallback) => {}, 9001); + +test('name', () => {}); +test('name', async () => {}); +test('name', () => {}, 9001); +test('name', async () => {}, 9001); +test('name', (callback: jest.DoneCallback) => {}, 9001); + +test.only('name', () => {}); +test.only('name', async () => {}); +test.only('name', () => {}, 9001); +test.only('name', async () => {}, 9001); +test.only('name', (callback: jest.DoneCallback) => {}, 9001); + +test.skip('name', () => {}); +test.skip('name', async () => {}); +test.skip('name', () => {}, 9001); +test.skip('name', async () => {}, 9001); +test.skip('name', (callback: jest.DoneCallback) => {}, 9001); + +test.todo('name', () => {}); +test.todo('name', async () => {}); +test.todo('name', () => {}, 9001); +test.todo('name', async () => {}, 9001); +test.todo('name', (callback: jest.DoneCallback) => {}, 9001); + +test.concurrent('name', () => {}); +test.concurrent('name', async () => {}); +test.concurrent('name', () => {}, 9001); +test.concurrent('name', async () => {}, 9001); +test.concurrent('name', (callback: jest.DoneCallback) => {}, 9001); + +xtest('name', () => {}); +xtest('name', async () => {}); +xtest('name', () => {}, 9001); +xtest('name', async () => {}, 9001); +xtest('name', (callback: jest.DoneCallback) => {}, 9001); + +xtest.only('name', () => {}); +xtest.only('name', async () => {}); +xtest.only('name', () => {}, 9001); +xtest.only('name', async () => {}, 9001); +xtest.only('name', (callback: jest.DoneCallback) => {}, 9001); + +xtest.skip('name', () => {}); +xtest.skip('name', async () => {}); +xtest.skip('name', () => {}, 9001); +xtest.skip('name', async () => {}, 9001); +xtest.skip('name', (callback: jest.DoneCallback) => {}, 9001); + +xtest.todo('name', () => {}); +xtest.todo('name', async () => {}); +xtest.todo('name', () => {}, 9001); +xtest.todo('name', async () => {}, 9001); +xtest.todo('name', (callback: jest.DoneCallback) => {}, 9001); + +xtest.concurrent('name', () => {}); +xtest.concurrent('name', async () => {}); +xtest.concurrent('name', () => {}, 9001); +xtest.concurrent('name', async () => {}, 9001); +xtest.concurrent('name', (callback: jest.DoneCallback) => {}, 9001); + +/* Done callbacks */ + +describe('', () => { + it('', (callback: jest.DoneCallback): void => { + callback(); + callback(''); + callback('', 3); + callback.fail(); + callback.fail('error'); + callback.fail({ message: 'message' }); + }); +}); + +/* NodeRequire interface (require extensions) */ + +declare const nodeRequire: NodeRequire; + +// $ExpectType any +nodeRequire.requireActual('moduleName'); + +// $ExpectType any +nodeRequire.requireMock('moduleName'); + +/* Top-level jest namespace functions */ + +const customMatcherFactories: jasmine.CustomMatcherFactories = {}; + +jest.addMatchers(customMatcherFactories) + .addMatchers({}) + .addMatchers(customMatcherFactories) + .autoMockOff() + .autoMockOn() + .clearAllMocks() + .clearAllTimers() + .resetAllMocks() + .restoreAllMocks() + .clearAllTimers() + .deepUnmock('moduleName') + .disableAutomock() + .doMock('moduleName') + .doMock('moduleName', jest.fn()) + .doMock('moduleName', jest.fn(), {}) + .doMock('moduleName', jest.fn(), { virtual: true }) + .dontMock('moduleName') + .enableAutomock() + .mock('moduleName') + .mock('moduleName', jest.fn()) + .mock('moduleName', jest.fn(), {}) + .mock('moduleName', jest.fn(), { virtual: true }) + .resetModuleRegistry() + .resetModules() + .isolateModules(() => {}) + .retryTimes(3) + .runAllImmediates() + .runAllTicks() + .runAllTimers() + .runOnlyPendingTimers() + .runTimersToTime(9001) + .advanceTimersByTime(9001) + .setMock('moduleName', {}) + .setMock<{}>('moduleName', {}) + .setMock<{ a: 'b' }>('moduleName', { a: 'b' }) + .setTimeout(9001) + .unmock('moduleName') + .useFakeTimers() + .useRealTimers(); + +jest.advanceTimersToNextTimer(); +jest.advanceTimersToNextTimer(2); + +// https://jestjs.io/docs/en/jest-object#jestrequireactualmodulename +jest.requireActual('./thisReturnsTheActualModule'); + +// https://jestjs.io/docs/en/jest-object#jestrequiremockmodulename +jest.requireMock('./thisAlwaysReturnsTheMock'); + +/* Mocks and spies */ + +// $ExpectType Mock +const mock1: jest.Mock = jest.fn(); +// $ExpectType Mock +const mock2 = jest.fn(() => undefined); +// $ExpectType Mock +const mock3 = jest.fn(() => 'abc'); +// $ExpectType Mock<"abc", []> +const mock4 = jest.fn((): 'abc' => 'abc'); +// $ExpectType Mock +const mock5 = jest.fn((...args: string[]) => args.join('')); +// $ExpectType Mock<{}, [{}]> +const mock6 = jest.fn((arg: {}) => arg); +// $ExpectType Mock +const mock7 = jest.fn((arg: number) => arg); +// $ExpectType Mock +const mock8: jest.Mock = jest.fn((arg: number) => arg); +// $ExpectType Mock, [number, string, {}, [], boolean]> +const mock9 = jest.fn((a: number, _b: string, _c: {}, _iReallyDontCare: [], _makeItStop: boolean) => + Promise.resolve(_makeItStop) +); +// $ExpectType Mock +const mock10 = jest.fn(() => { + throw new Error(); +}); +// $ExpectType Mock +const mock11 = jest.fn((arg: unknown) => arg); +interface TestApi { + test(x: number): string; +} +// $ExpectType Mock +const mock12 = jest.fn, jest.ArgsType>(); + +// $ExpectType number +mock1('test'); + +// $ExpectError +mock7('abc'); +// $ExpectError +mock7.mockImplementation((arg: string) => 1); + +// compiles because mock8 is declared as jest.Mock<{}, any> +mock8('abc'); +mock8.mockImplementation((arg: string) => 1); + +// mockImplementation not required to declare all arguments +mock9.mockImplementation((a: number) => Promise.resolve(a === 0)); + +const genMockModule1: {} = jest.genMockFromModule('moduleName'); +const genMockModule2: { a: 'b' } = jest.genMockFromModule<{ a: 'b' }>('moduleName'); + +const isStringMock: boolean = jest.isMockFunction('foo'); +const isMockMock: boolean = jest.isMockFunction(mock1); + +const maybeMock = () => {}; +if (jest.isMockFunction(maybeMock)) { + maybeMock.getMockName(); +} + +const mockName: string = jest.fn().getMockName(); +const mockContextVoid = jest.fn().mock; +const mockContextString = jest.fn(() => '').mock; + +jest.fn().mockClear(); +jest.fn().mockReset(); +jest.fn().mockRestore(); +jest.fn().mockImplementation((test: number) => test); +jest.fn().mockResolvedValue(1); + +interface SpyInterface { + prop?: number; + method?: (arg1: boolean) => void; +} +const spiedTarget = { + returnsVoid(): void {}, + setValue(value: string): void { + this.value = value; + }, + returnsString(): string { + return ''; + }, +}; +class SpiedTargetClass { + private _value = 3; + private _value2 = ''; + get value() { + return this._value; + } + set value(value) { + this._value = value; + } + get value2() { + return this._value2; + } + set value2(value2) { + this._value2 = value2; + } +} + +const spiedTarget2 = new SpiedTargetClass(); + +// $ExpectError +jest.spyOn(spiedTarget, 'setValue', 'get'); +// $ExpectError +jest.spyOn(spiedTarget2, 'value'); + +const spy1 = jest.spyOn(spiedTarget, 'returnsVoid'); +const spy3 = jest.spyOn(spiedTarget, 'returnsString'); +const spy1Name: string = spy1.getMockName(); + +const spy1Calls: Array<[]> = spy1.mock.calls; + +spy1.mockClear(); +spy1.mockReset(); + +const spy3Mock = spy3 + .mockImplementation(() => '') + .mockImplementation() + // $ExpectError + .mockImplementation((arg: {}) => arg) + .mockImplementation((...args: string[]) => args.join('')) + .mockImplementationOnce(() => '') + .mockName('name') + .mockReturnThis() + .mockReturnValue('value') + .mockReturnValueOnce('value'); + +const spiedPromiseTarget = { + resolvesString() { + return Promise.resolve('string'); + } +}; +jest.spyOn(spiedPromiseTarget, 'resolvesString') + .mockResolvedValue('value') + .mockResolvedValueOnce('value') + .mockRejectedValue('value') + .mockRejectedValueOnce('value'); + +let spy4: jest.SpyInstance; +// $ExpectType SpyInstance +spy4 = jest.spyOn(spiedTarget, 'returnsString'); +// compiles because spy4 is declared as jest.SpyInstance +spy4.mockImplementation(() => 1); +spy4.mockRestore(); + +let spy5: jest.SpiedFunction; + +// $ExpectType SpyInstance +spy5 = jest.spyOn(spiedTarget, 'setValue'); +// $ExpectError +spy5 = jest.spyOn(spiedTarget, 'returnsString'); + +// $ExpectType SpyInstance +const spy6 = jest.spyOn(spiedTarget2, 'value', 'get'); +// $ExpectError +spy6.mockReturnValue('5'); + +// $ExpectType SpyInstance +jest.spyOn(spiedTarget2, 'value', 'set'); + +let spyInterfaceImpl: SpyInterface = {}; +// $ExpectError +jest.spyOn(spyInterfaceImpl, 'method', 'get'); +// $ExpectError +jest.spyOn(spyInterfaceImpl, 'prop'); +// $ExpectType SpyInstance +jest.spyOn(spyInterfaceImpl, 'prop', 'get'); +// $ExpectType SpyInstance +jest.spyOn(spyInterfaceImpl, 'method'); + +class SpyableClass { + constructor(a: number, b: string) {} + foo() {} +} +// $ExpectType SpyInstance +jest.spyOn({ SpyableClass }, "SpyableClass"); + +interface Type1 { + a: number; +} +interface Type2 { + b: number; +} +class TestMocked { + field: string; + test1(x: Type1): Promise { + return Promise.resolve(x); + } + test2(x: Promise): Promise { + return x; + } + test3(x: Promise): Promise { + return x.then(() => ({ b: 1 })); + } + test4(x: Type1): Type1 { + return x; + } +} + +const mocked: jest.Mocked = new TestMocked() as any; +mocked.test1.mockImplementation(() => Promise.resolve({ a: 1 })); +// $ExpectType (x: Type1) => Promise | undefined +mocked.test1.getMockImplementation(); +mocked.test1.mockReturnValue(Promise.resolve({ a: 1 })); +// $ExpectType MockInstance, [Type1]> & ((x: Type1) => Promise) +mocked.test1.mockResolvedValue({ a: 1 }); +mocked.test1.mockResolvedValueOnce({ a: 1 }); +// $ExpectType MockInstance, [Type1]> & ((x: Type1) => Promise) +mocked.test1.mockResolvedValue(Promise.resolve({ a: 1 })); +mocked.test1.mockResolvedValueOnce(Promise.resolve({ a: 1 })); +// $ExpectType MockInstance, [Promise]> & ((x: Promise) => Promise) +mocked.test2.mockResolvedValue({ a: 1 }); +mocked.test2.mockResolvedValueOnce({ a: 1 }); +// $ExpectType MockInstance, [Promise]> & ((x: Promise) => Promise) +mocked.test2.mockResolvedValue(Promise.resolve({ a: 1 })); +mocked.test2.mockResolvedValueOnce(Promise.resolve({ a: 1 })); +// $ExpectType MockInstance, [Promise]> & ((x: Promise) => Promise) +mocked.test3.mockResolvedValue({ b: 1 }); +mocked.test3.mockResolvedValueOnce({ b: 1 }); +// $ExpectType MockInstance, [Promise]> & ((x: Promise) => Promise) +mocked.test3.mockResolvedValue(Promise.resolve({ b: 1 })); +mocked.test3.mockResolvedValueOnce(Promise.resolve({ b: 1 })); +mocked.test3.mockRejectedValue(new Error()); +mocked.test3.mockRejectedValueOnce(new Error()); +// $ExpectError +mocked.test4.mockResolvedValue({ a: 1 }); +// $ExpectError +mocked.test4.mockResolvedValueOnce({ a: 1 }); +// $ExpectError +mocked.test4.mockResolvedValue(Promise.resolve({ a: 1 })); +// $ExpectError +mocked.test4.mockResolvedValueOnce(Promise.resolve({ a: 1 })); +// $ExpectError +mocked.test4.mockRejectedValue(new Error()); +// $ExpectError +mocked.test4.mockRejectedValueOnce(new Error()); + +class TestClass { + testClassMethod(str: string, num: number): boolean { + return true; + } + + constructor(stringValue: string) {} +} + +const module = { + testFunction(num: number, str: string): boolean { + return true; + }, + testLambdaFunction: (num: number, str: string): boolean => { + return true; + }, + TestClass, + testClassInstance: new TestClass('test'), +}; + +const mockedModule = module as jest.Mocked; +mockedModule.testFunction.mock.calls[0][0]; // $ExpectType number +mockedModule.testFunction.mock.calls[0][1]; // $ExpectType string +const testFunction_0_ret = mockedModule.testFunction.mock.results[0]; +if (testFunction_0_ret.type === 'return') { + testFunction_0_ret.value; // $ExpectType boolean +} + +mockedModule.TestClass.mock.calls[0][0]; // $ExpectType string +mockedModule.TestClass.mock.instances[0]; // $ExpectType TestClass + +mockedModule.TestClass.prototype.testClassMethod.mock.calls[0][0]; // $ExpectType string +mockedModule.TestClass.prototype.testClassMethod.mock.calls[0][1]; // $ExpectType number +const TestClass_testClassMethod_0_ret = mockedModule.TestClass.prototype.testClassMethod.mock.results[0]; +if (TestClass_testClassMethod_0_ret.type === 'return') { + TestClass_testClassMethod_0_ret.value; // $ExpectType boolean +} + +const mockedTestFunction = module.testFunction as jest.MockedFunction; +mockedTestFunction.mock.calls[0][0]; // $ExpectType number +mockedTestFunction.mock.calls[0][1]; // $ExpectType string +const mockedTestFunction_0_ret = mockedTestFunction.mock.results[0]; +if (mockedTestFunction_0_ret.type === 'return') { + mockedTestFunction_0_ret.value; // $ExpectType boolean +} + +const mockedTestLambdaFunction = module.testLambdaFunction as jest.MockedFunction; +mockedTestLambdaFunction.mock.calls[0][0]; // $ExpectType number +mockedTestLambdaFunction.mock.calls[0][1]; // $ExpectType string +const mockedTestLambdaFunction_0_ret = mockedTestLambdaFunction.mock.results[0]; +if (mockedTestLambdaFunction_0_ret.type === 'return') { + mockedTestLambdaFunction_0_ret.value; // $ExpectType boolean +} + +const MockedTestClass = module.TestClass as jest.MockedClass; +MockedTestClass.prototype.testClassMethod.mock.calls[0][0]; // $ExpectType string +MockedTestClass.prototype.testClassMethod.mock.calls[0][1]; // $ExpectType number +const MockedTestClass_testClassMethod_0_ret = mockedModule.TestClass.prototype.testClassMethod.mock.results[0]; +if (MockedTestClass_testClassMethod_0_ret.type === 'return') { + MockedTestClass_testClassMethod_0_ret.value; // $ExpectType boolean +} + +const mockResult = jest.fn(() => 1).mock.results[0]; +switch (mockResult.type) { + case 'return': + mockResult.value; // $ExpectType number + break; + case 'incomplete': + mockResult.value; // $ExpectType undefined + break; + case 'throw': + mockResult.value; // $ExpectType any + break; +} + +/* getState and setState */ +// $ExpectError +expect.setState(true); +expect.setState({for: 'state'}); +const expectState = expect.getState(); +// $ExpectType string +expectState.currentTestName; +// $ExpectType string +expectState.testPath; +// $ExpectType boolean +expectState.expand; +// $ExpectType number +expectState.assertionCalls; +// $ExpectType number +expectState.expectedAssertionsNumber; +// $ExpectType boolean | undefined +expectState.isExpectingAssertions; +// $ExpectType Error[] +expectState.suppressedErrors; +// allows additional state properties added by getState +expectState.for; + +/* Snapshot serialization */ + +const snapshotSerializerPlugin: jest.SnapshotSerializerPlugin = { + print: () => '', + test: () => true, +}; + +expect.addSnapshotSerializer(snapshotSerializerPlugin); + +expect.addSnapshotSerializer({ + print: (value: unknown) => '', + test: (value: {}) => value === value, +}); + +expect.addSnapshotSerializer({ + print: (value: unknown, serialize: (val: {}) => string, indent: (str: string) => string, opts: {}) => '', + test: (value: {}) => value === value, +}); + +expect.addSnapshotSerializer({ + serialize(value, config, indentation, depth, refs, printer) { + let result = ''; + + if (config.callToJSON !== undefined && config.callToJSON) { + result += ' '; + } + + result += config.spacingInner; + result += config.spacingOuter; + + if (config.escapeRegex !== undefined && config.escapeRegex) { + result += ' '; + } + + if (indentation !== undefined) { + result += indentation; + } + + if (config.maxDepth !== undefined) { + result = result.substring(0, config.maxDepth); + } + + if (config.min !== undefined && config.min) { + result += ' '; + } + + if (config.plugins !== undefined) { + for (const plugin of config.plugins) { + expect.addSnapshotSerializer(plugin); + } + } + + if (config.printFunctionName !== undefined && config.printFunctionName) { + result += ' '; + } + + return result; + }, + test: (value: {}) => value === value, +}); + +// old API +expect.addSnapshotSerializer({ + print(value, serialize, indent, opts, colors) { + let result = ''; + + result += opts.edgeSpacing; + result += opts.spacing; + + if (opts.min !== undefined && opts.min) { + result += ' '; + } + + for (const color of [colors.comment, colors.content, colors.prop, colors.tag, colors.value]) { + result += color.open; + result += color.close; + } + + return result; + }, + test: (value: {}) => value === value, +}); + +/* expect extensions */ + +const expectExtendMap: jest.ExpectExtendMap = {}; + +expect.extend(expectExtendMap); +expect.extend({}); +expect.extend({ + foo(this: jest.MatcherContext, received: {}, ...actual: Array<{}>) { + return { + message: () => JSON.stringify(received), + pass: false, + }; + }, +}); +// $ExpectError +const customMatcherResultMessage: jest.CustomMatcherResult['message'] = 'msg'; +expect.extend({ + async foo(this: jest.MatcherContext, received: {}, ...actual: Array<{}>) { + return { + message: () => JSON.stringify(received), + pass: false, + }; + }, +}); + +expect.extend({ + foo(this: jest.MatcherContext) { + const isNot: boolean = this.isNot; + const expand: boolean = this.expand; + + const expectedColor = this.utils.EXPECTED_COLOR('blue'); + const receivedColor = this.utils.EXPECTED_COLOR('red'); + + const diff: string | null = this.utils.diff({}, {}); + + this.utils.ensureActualIsNumber({}, 'matcher'); + + this.utils.ensureExpectedIsNumber({}, 'matcher'); + + this.utils.ensureNoExpected({}, 'matcher'); + + this.utils.ensureNumbers({}, {}, 'matcher'); + + this.utils.matcherHint('matcher'); + this.utils.matcherHint('matcher', 'received'); + this.utils.matcherHint('matcher', 'received', 'expected'); + this.utils.matcherHint('matcher', 'received', 'expected', {}); + this.utils.matcherHint('matcher', 'received', 'expected', { + isDirectExpectCall: true, + }); + this.utils.matcherHint('matcher', 'received', 'expected', { + secondArgument: '', + }); + this.utils.matcherHint('matcher', 'received', 'expected', { + isDirectExpectCall: true, + secondArgument: '', + }); + + const plural: string = this.utils.pluralize('word', 3); + + const expectedPrinted: string = this.utils.printExpected({}); + + const receivedPrinted: string = this.utils.printReceived({}); + + const printedWithType: string = this.utils.printWithType('name', {}, (value: {}) => ''); + + const stringified: string = this.utils.stringify({}); + const stringifiedWithMaxDepth: string = this.utils.stringify({}, 3); + + const equals: boolean = this.equals({}, {}); + + this.dontThrow(); + this.fromState; + const currentTestName: string = this.currentTestName; + const testPath: string = this.testPath; + + return { + message: () => `Can use ${this.promise} for failure message`, + pass: false, + }; + }, +}); + +/* Basic matchers */ + +describe('', () => { + it('', () => { + /* Corrections of previous typings */ + // $ExpectError + expect('').not.not; + // $ExpectError + expect('').resolves.resolves; + // $ExpectType void + expect('').toEqual(''); + // $ExpectType Promise + expect(Promise.resolve('')).resolves.toEqual(''); + + expect(jest.fn()).lastCalledWith(); + expect(jest.fn()).lastCalledWith('jest'); + expect(jest.fn()).lastCalledWith({}, {}); + + expect(jest.fn()).lastReturnedWith('jest'); + expect(jest.fn()).lastReturnedWith({}); + + expect(jest.fn()).nthCalledWith(0, 'jest'); + expect(jest.fn()).nthCalledWith(1, {}); + + expect(jest.fn()).nthReturnedWith(0, 'jest'); + expect(jest.fn()).nthReturnedWith(1, {}); + + expect({}).toBe({}); + expect([]).toBe([]); + expect(10).toBe(10); + + expect(jest.fn()).toBeCalled(); + + expect(jest.fn()).toBeCalledTimes(1); + + expect(jest.fn()).toBeCalledWith(); + expect(jest.fn()).toBeCalledWith('jest'); + expect(jest.fn()).toBeCalledWith({}, {}); + + // $ExpectError + expect(jest.fn()).toBeCalledWith<[string, number]>(1, 'two'); + // $ExpectError + expect({}).toEqual<{ p1: string, p2: number }>({ p1: 'hello' }); + + expect(0).toBeCloseTo(1); + expect(0).toBeCloseTo(1, 2); + + expect(undefined).toBeDefined(); + expect({}).toBeDefined(); + + expect(true).toBeFalsy(); + expect(false).toBeFalsy(); + expect(0).toBeFalsy(); + + expect(0).toBeGreaterThan(1); + + expect(0).toBeGreaterThanOrEqual(1); + + expect(3).toBeInstanceOf(Number); + + expect(0).toBeLessThan(1); + + expect(0).toBeLessThanOrEqual(1); + + expect(0n).toBeGreaterThan(1n); + + expect(0n).toBeGreaterThanOrEqual(1n); + + expect(0n).toBeLessThan(1n); + + expect(0n).toBeLessThanOrEqual(1n); + + expect(null).toBeNull(); + expect(undefined).toBeNull(); + + expect(true).toBeTruthy(); + expect(false).toBeFalsy(); + expect(1).toBeTruthy(); + + expect(undefined).toBeUndefined(); + expect({}).toBeUndefined(); + + expect(NaN).toBeNaN(); + expect(Infinity).toBeNaN(); + + expect([]).toContain({}); + expect(['abc']).toContain('abc'); + expect(['abc']).toContain('def'); + expect('abc').toContain('bc'); + + expect([]).toContainEqual({}); + expect(['abc']).toContainEqual('def'); + + expect([]).toEqual([]); + expect({}).toEqual({}); + + expect(jest.fn()).toHaveBeenCalled(); + + expect(jest.fn()).toHaveBeenCalledTimes(0); + expect(jest.fn()).toHaveBeenCalledTimes(1); + + expect(jest.fn()).toHaveBeenCalledWith(); + expect(jest.fn()).toHaveBeenCalledWith('jest'); + expect(jest.fn()).toHaveBeenCalledWith({}, {}); + + expect(jest.fn()).toHaveBeenCalledWith(0); + expect(jest.fn()).toHaveBeenCalledWith(1, 'jest'); + expect(jest.fn()).toHaveBeenCalledWith(2, {}, {}); + + expect(jest.fn()).toHaveBeenLastCalledWith(); + expect(jest.fn()).toHaveBeenLastCalledWith('jest'); + expect(jest.fn()).toHaveBeenLastCalledWith({}, {}); + + expect(jest.fn()).toHaveLastReturnedWith('jest'); + expect(jest.fn()).toHaveLastReturnedWith({}); + + expect([]).toHaveLength(0); + expect('').toHaveLength(1); + + expect(jest.fn()).toHaveNthReturnedWith(0, 'jest'); + expect(jest.fn()).toHaveNthReturnedWith(1, {}); + + expect({}).toHaveProperty('property'); + expect({}).toHaveProperty('property', {}); + expect({}).toHaveProperty(['property']); + expect({}).toHaveProperty(['property'], {}); + expect({}).toHaveProperty(['property', 'deep']); + expect({}).toHaveProperty(['property', 'deep'], {}); + + expect(jest.fn()).toHaveReturned(); + + expect(jest.fn()).toHaveReturnedTimes(0); + expect(jest.fn()).toHaveReturnedTimes(1); + + expect(jest.fn()).toHaveReturnedWith('jest'); + expect(jest.fn()).toHaveReturnedWith({}); + + expect('').toMatch(''); + expect('').toMatch(/foo/); + + expect({}).toMatchObject({}); + expect({ abc: 'def' }).toMatchObject({ abc: 'def' }); + expect({}).toMatchObject([{}, {}]); + expect({ abc: 'def' }).toMatchObject([{ abc: 'def' }, { invalid: 'property' }]); + expect({ abc: 'def' }).toMatchObject<{ abc: string }>({ abc: 'def' }); + expect([{ abc: 'def' }, { abc: 'def' }]).toMatchObject<[{ abc: string }, { abc: string }]>([ + { abc: 'def' }, + { abc: 'def' }, + ]); + + expect({}).toMatchSnapshot(); + expect({}).toMatchSnapshot('snapshotName'); + expect({ abc: 'def' }).toMatchSnapshot({ abc: expect.any(String) }, 'snapshotName'); + expect({ + one: 1, + two: '2', + three: 3, + four: { four: 3 }, + date: new Date(), + }).toMatchSnapshot({ + one: expect.any(Number), + // Leave 'two' to the auto-generated snapshot + three: 3, + four: { four: expect.any(Number) }, + date: expect.any(Date), + }); + + expect({}).toMatchInlineSnapshot(); + expect({}).toMatchInlineSnapshot('snapshot'); + expect({ abc: 'def' }).toMatchInlineSnapshot({ abc: expect.any(String) }, 'snapshot'); + expect({ + one: 1, + two: '2', + three: 3, + four: { four: 3 }, + date: new Date(), + }).toMatchInlineSnapshot({ + one: expect.any(Number), + // leave out two + three: 3, + four: { four: expect.any(Number) }, + date: expect.any(Date), + }); + + expect(jest.fn()).toReturn(); + + expect(jest.fn()).toReturnTimes(0); + expect(jest.fn()).toReturnTimes(1); + + expect(jest.fn()).toReturnWith('jest'); + expect(jest.fn()).toReturnWith({}); + + expect(true).toStrictEqual(false); + expect({}).toStrictEqual({}); + + const errInstance = new Error(); + const willThrow = () => { + throw new Error(); + }; + expect(() => {}).toThrow(); + expect(willThrow).toThrow(''); + expect(willThrow).toThrow(errInstance); + expect(jest.fn()).toThrow(Error); + expect(jest.fn(willThrow)).toThrow(/foo/); + + expect(() => {}).toThrowErrorMatchingSnapshot(); + expect(willThrow).toThrowErrorMatchingSnapshot(); + expect(jest.fn()).toThrowErrorMatchingSnapshot(); + expect(jest.fn(willThrow)).toThrowErrorMatchingSnapshot(); + + expect(() => {}).toThrowErrorMatchingInlineSnapshot(); + expect(() => {}).toThrowErrorMatchingInlineSnapshot('Error Message'); + expect(willThrow).toThrowErrorMatchingInlineSnapshot(); + expect(willThrow).toThrowErrorMatchingInlineSnapshot('Error Message'); + expect(jest.fn()).toThrowErrorMatchingInlineSnapshot(); + expect(jest.fn()).toThrowErrorMatchingInlineSnapshot('Error Message'); + expect(jest.fn(willThrow)).toThrowErrorMatchingInlineSnapshot(); + expect(jest.fn(willThrow)).toThrowErrorMatchingInlineSnapshot('Error Message'); + + /* not */ + + expect({}).not.toEqual({}); + expect([]).not.toStrictEqual([]); + + /* Promise matchers */ + + expect(Promise.reject('jest')).rejects.toEqual('jest').then(() => {}); + expect(Promise.reject('jest')).rejects.not.toEqual('other').then(() => {}); + + expect(Promise.resolve('jest')).resolves.toEqual('jest').then(() => {}); + expect(Promise.resolve('jest')).resolves.not.toEqual('other').then(() => {}); + /* type matchers */ + + expect({}).toBe(expect.anything()); + + expect({}).toBe(expect.any(class Foo {})); + expect(new Error()).toBe(expect.any(Error)); + expect(7).toBe(expect.any(Number)); + + expect({}).toBe(expect.arrayContaining(['a', 'b'])); + expect(['abc']).toBe(expect.arrayContaining(['a', 'b'])); + + expect.objectContaining({}); + expect.stringMatching('foo'); + expect.stringMatching(/foo/); + expect.stringContaining('foo'); + + expect({ abc: 'def' }).toBe( + expect.objectContaining({ + abc: expect.arrayContaining([expect.any(Date), {}]), + def: expect.objectContaining({ + foo: 'bar', + }), + ghi: expect.stringMatching('foo'), + }) + ); + + /* Inverse type matchers */ + + expect('How are you?').toEqual(expect.not.stringContaining('Hello world!')); + expect('How are you?').toEqual(expect.not.stringMatching(/Hello world!/)); + expect({ bar: 'baz' }).toEqual(expect.not.objectContaining({ foo: 'bar' })); + expect(['Alice', 'Bob', 'Eve']).toEqual(expect.not.arrayContaining(['Samantha'])); + + /* Miscellaneous */ + + expect.hasAssertions(); + expect.assertions(0); + expect.assertions(9001); + }); +}); + +/* Custom matchers and CustomExpect */ +describe('', () => { + it('', () => { + const customMatcher = (expected: any, actual: {prop: string}, option1: boolean) => { + return {pass: true, message: () => ''}; + }; + const asyncMatcher = () => { + return Promise.resolve({pass: true, message: () => ''}); + }; + + const customMatchers = {customMatcher, asyncMatcher}; + expect.extend(customMatchers); + const extendedExpect: jest.ExtendedExpect = expect as any; + + // extracting matcher types + const matchers = extendedExpect({thing: true}); + let nonPromiseMatchers: jest.NonPromiseMatchers = matchers; + const isNot = true; + if (isNot) { + nonPromiseMatchers = matchers.not; + } + // retains U from (actual: U) => JestExtendedMatchers; - BUT CANNOT DO THAT WITH CUSTOM... + nonPromiseMatchers.toMatchInlineSnapshot({thing: extendedExpect.any(Boolean)}); + // $ExpectError + nonPromiseMatchers.toMatchInlineSnapshot({notthing: extendedExpect.any(Boolean)}); + + let promiseMatchers: jest.PromiseMatchers = matchers.rejects; + if (isNot) { + promiseMatchers = matchers.rejects.not; + } + // $ExpectType Promise + promiseMatchers.customMatcher({prop: ''}, true); + + // retains built in asymmetric matcher + extendedExpect.not.arrayContaining; + + extendedExpect.customMatcher({prop: 'good'}, false).asymmetricMatch({}).valueOf(); + // $ExpectError + extendedExpect.customMatcher({prop: {not: 'good'}}, false); + + extendedExpect.not.customMatcher({prop: 'good'}, false).asymmetricMatch({}).valueOf(); + // $ExpectError + extendedExpect.not.customMatcher({prop: 'good'}, 'bad').asymmetricMatch({}).valueOf(); + + // $ExpectError + const asynMatcherExcluded = extendedExpect.asyncMatcher; + + extendedExpect('').customMatcher({prop: 'good'}, true); + // $ExpectError + extendedExpect('').customMatcher({prop: 'good'}, 'bad'); + + extendedExpect('').not.customMatcher({prop: 'good'}, true); + // $ExpectError + extendedExpect('').not.customMatcher({prop: 'good'}, 'bad'); + + extendedExpect(Promise.resolve('')).resolves.customMatcher({prop: 'good'}, true).then(() => {}); + // $ExpectError + extendedExpect(Promise.resolve('')).resolves.customMatcher({prop: 'good'}, 'bad').then(() => {}); + + extendedExpect(Promise.resolve('')).resolves.not.customMatcher({prop: 'good'}, true).then(() => {}); + // $ExpectError + extendedExpect(Promise.resolve('')).resolves.not.customMatcher({prop: 'good'}, 'bad').then(() => {}); + + extendedExpect(Promise.reject('')).rejects.customMatcher({prop: 'good'}, true).then(() => {}); + // $ExpectError + extendedExpect(Promise.reject('')).rejects.customMatcher({prop: 'good'}, 'bad').then(() => {}); + + extendedExpect(Promise.reject('')).rejects.not.customMatcher({prop: 'good'}, true).then(() => {}); + // $ExpectError + extendedExpect(Promise.reject('')).rejects.not.customMatcher({prop: 'good'}, 'bad').then(() => {}); + }); +}); + +/* Jasmine status changers */ + +describe('', () => { + it('', () => { + pending(); + pending('reason'); + + fail(); + fail('error'); + fail(new Error('reason')); + fail({}); + }); +}); + +/* Jasmine clocks and timing */ + +jasmine.DEFAULT_TIMEOUT_INTERVAL = 9001; + +const clock = jasmine.clock(); + +clock.install(); + +clock.mockDate(); +clock.mockDate(undefined); +clock.mockDate(new Date()); + +clock.tick(0); +clock.tick(9001); + +/* Jasmine matchers */ + +expect({}).toBe(jasmine.anything()); + +expect({}).toBe(jasmine.any(class Foo {})); +expect(new Error()).toBe(jasmine.any(Error)); +expect(7).toBe(jasmine.any(Number)); + +expect({}).toBe(jasmine.arrayContaining(['a', 'b'])); +expect(['abc']).toBe(jasmine.arrayContaining(['a', 'b'])); + +jasmine.arrayContaining([]); +new (jasmine.arrayContaining([]))([]); +const arrayContained: boolean = jasmine.arrayContaining([]).asymmetricMatch([]); +const arrayContainedName: string = jasmine.arrayContaining([]).jasmineToString(); + +jasmine.objectContaining({}); +new (jasmine.objectContaining({}))({}); +const objectContained: boolean = jasmine.objectContaining({}).jasmineMatches({}, ['abc'], ['def']); +const objectContainedName: string = jasmine.objectContaining({}).jasmineToString(); + +jasmine.stringMatching('foo'); +jasmine.stringMatching(/foo/); +new (jasmine.stringMatching('foo'))({}); +const stringContained: boolean = jasmine.stringMatching(/foo/).jasmineMatches({}); +const stringContainedName: string = jasmine.stringMatching('foo').jasmineToString(); + +expect({ abc: 'def' }).toBe( + jasmine.objectContaining({ + abc: jasmine.arrayContaining([jasmine.any(Date), {}]), + def: jasmine.objectContaining({ + foo: 'bar', + }), + ghi: jasmine.stringMatching('foo'), + }) +); + +/* Jasmine spies */ + +describe('', () => { + it('', () => { + let spy = jasmine.createSpy(); + jasmine.createSpy('name'); + jasmine.createSpy('name', () => {}); + jasmine.createSpy('name', (arg: {}) => arg); + jasmine.createSpy('name', (...args: string[]) => args.join('')); + + spy = jasmine + .createSpy() + .and.callFake(() => {}) + .and.callFake((arg: {}) => arg) + .and.callFake((...args: string[]) => args.join('')) + .and.callThrough() + .and.returnValue('jasmine') + .and.returnValue({}) + .and.returnValues() + .and.returnValues('jasmine') + .and.returnValues({}, {}) + .and.stub() + .and.throwError('message'); + + const identity: string = spy.identity; + + let args: any[]; + args = spy.mostRecentCall.args; + args = spy.argsForCall[0]; + args = spy.calls.allArgs(); + args = spy.calls.argsFor(0); + + const spyCalled: boolean = spy.calls.any(); + + const wasCalled: boolean = spy.wasCalled; + + for (const call of [...spy.calls.all(), spy.calls.first(), spy.calls.mostRecent()]) { + const callType: jasmine.CallInfo = call; + const callArgs: any[] = call.args; + const { object, returnValue } = call; + } + + spy.calls.reset(); + + const spyReturn = spy(); + + /* Jasmine spy objects */ + + let spyObject = { + abc() { + return ''; + }, + def: 7, + }; + + spyObject = jasmine.createSpyObj('baseName', ['abc']); + spyObject = jasmine.createSpyObj('baseName', ['abc']); + + const newSpyObject: typeof spyObject = jasmine.createSpyObj('baseName', ['abc']); + }); +}); + +/* Jasmine pp */ + +const pp: string = jasmine.pp({}); + +/* Jasmine equality testers */ + +const equalityTesterObject = (first: {}, second: {}) => false; +const equalityTesterString: jasmine.CustomEqualityTester = (first: string, second: string) => first === second; + +jasmine.addCustomEqualityTester(equalityTesterObject); +jasmine.addCustomEqualityTester(equalityTesterObject); + +/* Jasmine matchers */ + +const customMatcherFactoriesNone = {}; +const customMatcherFactoriesIndex: { [i: string]: jasmine.CustomMatcherFactory } = {}; +const customMatcherFactoriesManual = { + abc: () => ({ + compare: (actual: '', expected: '', ...args: Array<{}>) => ({ + pass: true, + message: '', + }), + }), + def: (util: jasmine.MatchersUtil, customEqualityTestesr: jasmine.CustomEqualityTester): jasmine.CustomMatcher => ({ + compare(actual: T, expected: T): jasmine.CustomMatcherResult { + return { + pass: actual === expected, + message: () => 'foo', + }; + }, + }), +}; + +const matchersUtil1 = { + buildFailureMessage: () => '', + contains: (haystack: string, needle: string) => haystack.indexOf(needle) !== -1, + equals: (a: {}, b: {}) => false, +}; + +let matchersUtil2: jasmine.MatchersUtil = { + buildFailureMessage(matcherName: string, isNot: boolean, actual: any, ...expected: any[]): string { + return `${matcherName}${isNot ? '1' : '0'}${actual}${expected.join('')}`; + }, + contains(haystack: T[], needle: T, customTesters?: jasmine.CustomEqualityTester[]) { + return true; + }, + equals: (a: {}, b: {}, customTesters?: jasmine.CustomEqualityTester[]) => false, +}; + +// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/26368 + +describe.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])('.add(%i, %i)', (a: number, b: number, expected: number) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); +}); + +interface Case { + a: number; + b: number; + expected: number; +} + +describe.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('$a + $b', ({ a, b, expected }: Case) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); +}); + +describe.only.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])('.add(%i, %i)', (a, b, expected) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); +}); + +describe.only.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('$a + $b', ({ a, b, expected }: Case) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); +}); + +describe.skip.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])('.add(%i, %i)', (a, b, expected) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); +}); + +describe.skip.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('$a + $b', ({ a, b, expected }: Case) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); +}); + +test.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])('.add(%i, %i)', (a, b, expected) => { + expect(a + b).toBe(expected); +}); + +test.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])( + '.add(%i, %i)', + (a, b, expected) => { + expect(a + b).toBe(expected); + }, + 5000 +); + +declare const constCases: [['a', 'b', 'ab'], ['d', 2, 'd2']]; +test.each(constCases)('%s + %s', (...args) => { + // following assertion is skipped because of flaky testing + // _$ExpectType ["a", "b", "ab"] | ["d", 2, "d2"] + args; +}); + +declare const constCasesWithMoreThanTen: [ + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], + [91, 92, 93, 94, 95, 96, 97, 98, 99, 910, 911] +]; + +test.each(constCasesWithMoreThanTen)('should fall back with more than 10 args', (...args) => { + // following assertion is skipped because of flaky testing + // _$ExpectType [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] | [91, 92, 93, 94, 95, 96, 97, 98, 99, 910, 911] + args; +}); + +test.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('returns $expected when $a is added $b', ({ a, b, expected }: Case) => { + expect(a + b).toBe(expected); +}); + +test.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`( + 'returns $expected when $a is added $b', + ({ a, b, expected }: Case) => { + expect(a + b).toBe(expected); + }, + 5000 +); + +test.each([ + [1, "1"], + [2, "2"] +])("", (a, b) => { + a; // $ExpectType number + b; // $ExpectType string +}); + +test.only.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])('.add(%i, %i)', (a, b, expected) => { + expect(a + b).toBe(expected); +}); + +test.only.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('returns $expected when $a is added $b', ({ a, b, expected }: Case) => { + expect(a + b).toBe(expected); +}); + +expect('').toHaveProperty('path.to.thing'); diff --git a/types/jest/ts3.8/tsconfig.json b/types/jest/ts3.8/tsconfig.json new file mode 100644 index 000000000000000..18de26be8c24998 --- /dev/null +++ b/types/jest/ts3.8/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["dom", "es6", "esnext", "es2020"], + "noImplicitAny": true, + "noImplicitThis": false, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../../", + "typeRoots": ["../../"], + "target": "es2020", + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "jest-tests.ts" + ] +} diff --git a/types/jest/ts3.8/tslint.json b/types/jest/ts3.8/tslint.json new file mode 100644 index 000000000000000..ad93d8fc0d9ca6b --- /dev/null +++ b/types/jest/ts3.8/tslint.json @@ -0,0 +1,6 @@ +{ + "extends": "dtslint/dt.json", + "rules": { + "no-unnecessary-generics": false + } +} \ No newline at end of file