From f8b4850425f115c8a23dead7ec0716b61663aed6 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Mon, 11 Jun 2018 17:45:29 -0700 Subject: [PATCH] Jest: Upgrade Flow Definition in RN + Metro Reviewed By: sahrens Differential Revision: D8371076 fbshipit-source-id: 12d03c545ca190a5fda1ff319e5ea906173d2241 --- flow/jest.js | 592 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 528 insertions(+), 64 deletions(-) diff --git a/flow/jest.js b/flow/jest.js index 7f6b795732556c..ebd7c9ec07261b 100644 --- a/flow/jest.js +++ b/flow/jest.js @@ -4,30 +4,124 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * Modified from https://raw.githubusercontent.com/flowtype/flow-typed/e3b0f3034929e0f0fb85c790450a201b380ac2fd/definitions/npm/jest_v17.x.x/flow_v0.33.x-/jest_v17.x.x.js + * Modified from https://raw.githubusercontent.com/flowtype/flow-typed/b43dff3e0ed5ccf7033839045f4819e8db40faa9/definitions/npm/jest_v20.x.x/flow_v0.22.x-/jest_v20.x.x.js * Duplicated from www/flow/shared/jest.js + * List of modifications: + * - added function fail + * - added jest.requireActual + * - added jest.requireMock + * - added JestMockFn.mockName + * - added JestMockFn.mockRejectedValue + * - added JestMockFn.mockRejectedValueOnce + * - added JestMockFn.mockResolvedValue + * - added JestMockFn.mockResolvedValueOnce + * - added JestMockFn.mock.thrownErrors + * - added JestMockFn.mock.returnValues + * - added jest.setTimeout * @flow * @format */ -'use strict'; +/* eslint-disable lint/no-unclear-flowtypes */ -type JestMockFn = { - (...args: Array): any, +type JestMockFn, TReturn> = { + (...args: TArguments): TReturn, + /** + * An object for introspecting mock calls + */ mock: { - calls: Array>, - instances: mixed, + /** + * An array that represents all calls that have been made into this mock + * function. Each call is represented by an array of arguments that were + * passed during the call. + */ + calls: Array, + /** + * An array that contains all the object instances that have been + * instantiated from this mock function. + */ + instances: Array, + /** + * An array containing the results of a method, and whether they were + * returned or thrown. + */ + results: Array<{isThrown: boolean}>, }, - mockClear(): Function, - mockReset(): Function, - mockImplementation(fn: Function): JestMockFn, - mockImplementationOnce(fn: Function): JestMockFn, + /** + * 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. + */ + mockClear(): void, + /** + * Resets all information stored in the mock. This is useful when you want to + * completely restore a mock back to its initial state. + */ + mockReset(): void, + /** + * Removes the mock and restores the initial 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(). + */ + mockRestore(): void, + /** + * 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. + */ + mockImplementation( + fn: (...args: TArguments) => TReturn, + ): JestMockFn, + /** + * 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. + */ + mockImplementationOnce( + fn: (...args: TArguments) => TReturn, + ): JestMockFn, + /** + * Accepts a string to use in test result output in place of "jest.fn()" to + * indicate which mock function is being referenced. + */ + mockName(name: string): JestMockFn, + /** + * Sugar for: jest.fn().mockReturnValue(Promise.reject(value)); + */ + mockRejectedValue(value: TReturn): JestMockFn, + /** + * Sugar for: jest.fn().mockReturnValueOnce(Promise.reject(value)); + */ + mockRejectedValueOnce(value: TReturn): JestMockFn, + /** + * Sugar for: jest.fn().mockReturnValue(Promise.resolve(value)); + */ + mockResolvedValue(value: TReturn): JestMockFn, + /** + * Sugar for: jest.fn().mockReturnValueOnce(Promise.resolve(value)); + */ + mockResolvedValueOnce(value: TReturn): JestMockFn, + /** + * Just a simple sugar function for returning `this` + */ mockReturnThis(): void, - mockReturnValue(value: any): JestMockFn, - mockReturnValueOnce(value: any): JestMockFn, + /** + * Deprecated: use jest.fn(() => value) instead + */ + mockReturnValue(value: TReturn): JestMockFn, + /** + * Sugar for only returning a value once inside your mock + */ + mockReturnValueOnce(value: TReturn): JestMockFn, }; type JestAsymmetricEqualityType = { + /** + * A custom Jasmine equality tester + */ asymmetricMatch(value: mixed): boolean, }; @@ -44,7 +138,7 @@ type JestCallsType = { type JestClockType = { install(): void, mockDate(date: Date): void, - tick(): void, + tick(milliseconds?: number): void, uninstall(): void, }; @@ -68,105 +162,471 @@ type JestPromiseType = { resolves: JestExpectType, }; +/** + * Plugin: jest-enzyme + */ +type EnzymeMatchersType = { + toBeChecked(): void, + toBeDisabled(): void, + toBeEmpty(): void, + toBePresent(): void, + toContainReact(element: React$Element): void, + toHaveClassName(className: string): void, + toHaveHTML(html: string): void, + toHaveProp(propKey: string, propValue?: any): void, + toHaveRef(refName: string): void, + toHaveState(stateKey: string, stateValue?: any): void, + toHaveStyle(styleKey: string, styleValue?: any): void, + toHaveTagName(tagName: string): void, + toHaveText(text: string): void, + toIncludeText(text: string): void, + toHaveValue(value: any): void, + toMatchElement(element: React$Element): void, + toMatchSelector(selector: string): void, +}; + type JestExpectType = { - not: JestExpectType, + not: JestExpectType & EnzymeMatchersType, + /** + * If you have a mock function, you can use .lastCalledWith to test what + * arguments it was last called with. + */ lastCalledWith(...args: Array): void, + /** + * toBe just checks that a value is what you expect. It uses === to check + * strict equality. + */ toBe(value: any): void, + /** + * Use .toHaveBeenCalled to ensure that a mock function got called. + */ toBeCalled(): void, + /** + * Use .toBeCalledWith to ensure that a mock function was called with + * specific arguments. + */ toBeCalledWith(...args: Array): void, + /** + * Using exact equality with floating point numbers is a bad idea. Rounding + * means that intuitive things fail. + */ toBeCloseTo(num: number, delta: any): void, + /** + * Use .toBeDefined to check that a variable is not undefined. + */ toBeDefined(): void, + /** + * Use .toBeFalsy when you don't care what a value is, you just want to + * ensure a value is false in a boolean context. + */ toBeFalsy(): void, + /** + * To compare floating point numbers, you can use toBeGreaterThan. + */ toBeGreaterThan(number: number): void, + /** + * To compare floating point numbers, you can use toBeGreaterThanOrEqual. + */ toBeGreaterThanOrEqual(number: number): void, + /** + * To compare floating point numbers, you can use toBeLessThan. + */ toBeLessThan(number: number): void, + /** + * To compare floating point numbers, you can use toBeLessThanOrEqual. + */ toBeLessThanOrEqual(number: number): void, + /** + * Use .toBeInstanceOf(Class) to check that an object is an instance of a + * class. + */ toBeInstanceOf(cls: Class<*>): void, + /** + * .toBeNull() is the same as .toBe(null) but the error messages are a bit + * nicer. + */ toBeNull(): void, + /** + * Use .toBeTruthy when you don't care what a value is, you just want to + * ensure a value is true in a boolean context. + */ toBeTruthy(): void, + /** + * Use .toBeUndefined to check that a variable is undefined. + */ toBeUndefined(): void, + /** + * Use .toContain 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. + */ toContain(item: any): void, + /** + * Use .toContainEqual 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. + */ toContainEqual(item: any): void, + /** + * Use .toEqual 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. + */ toEqual(value: any): void, + /** + * Use .toHaveBeenCalled to ensure that a mock function got called. + */ toHaveBeenCalled(): void, + /** + * Use .toHaveBeenCalledTimes to ensure that a mock function got called exact + * number of times. + */ toHaveBeenCalledTimes(number: number): void, + /** + * Use .toHaveBeenCalledWith to ensure that a mock function was called with + * specific arguments. + */ toHaveBeenCalledWith(...args: Array): void, - toHaveProperty(path: string, value?: any): void, - toMatch(regexp: RegExp): void, + /** + * Use .toHaveBeenLastCalledWith to ensure that a mock function was last called + * with specific arguments. + */ + toHaveBeenLastCalledWith(...args: Array): void, + /** + * Check that an object has a .length property and it is set to a certain + * numeric value. + */ + toHaveLength(number: number): void, + /** + * + */ + toHaveProperty(propPath: string, value?: any): void, + /** + * Use .toMatch to check that a string matches a regular expression or string. + */ + toMatch(regexpOrString: RegExp | string): void, + /** + * Use .toMatchObject to check that a javascript object matches a subset of the properties of an object. + */ toMatchObject(object: Object): void, - toMatchSnapshot(): void, - toThrow(message?: string | Error | Class): void, - toThrowError(message?: string | Error | Class | RegExp): void, + /** + * This ensures that a React component matches the most recent snapshot. + */ + toMatchSnapshot(name?: string): void, + /** + * Use .toThrow to test that a function throws when it is called. + * If you want to test that a specific error gets thrown, you can provide an + * argument to toThrow. The argument can be a string for the error message, + * a class for the error, or a regex that should match the error. + * + * Alias: .toThrowError + */ + toThrow(message?: string | Error | RegExp): void, + toThrowError(message?: string | Error | RegExp): void, + /** + * Use .toThrowErrorMatchingSnapshot to test that a function throws a error + * matching the most recent snapshot when it is called. + */ toThrowErrorMatchingSnapshot(): void, }; +type JestObjectType = { + /** + * Disables automatic mocking in the module loader. + * + * After this method is called, all `require()`s will return the real + * versions of each module (rather than a mocked version). + */ + disableAutomock(): JestObjectType, + /** + * An un-hoisted version of disableAutomock + */ + autoMockOff(): JestObjectType, + /** + * Enables automatic mocking in the module loader. + */ + enableAutomock(): JestObjectType, + /** + * An un-hoisted version of enableAutomock + */ + autoMockOn(): JestObjectType, + /** + * Clears the mock.calls and mock.instances properties of all mocks. + * Equivalent to calling .mockClear() on every mocked function. + */ + clearAllMocks(): JestObjectType, + /** + * Resets the state of all mocks. Equivalent to calling .mockReset() on every + * mocked function. + */ + resetAllMocks(): JestObjectType, + /** + * Restores all mocks back to their original value. + */ + restoreAllMocks(): JestObjectType, + /** + * Removes any pending timers from the timer system. + */ + clearAllTimers(): void, + /** + * The same as `mock` but not moved to the top of the expectation by + * babel-jest. + */ + doMock(moduleName: string, moduleFactory?: any): JestObjectType, + /** + * The same as `unmock` but not moved to the top of the expectation by + * babel-jest. + */ + dontMock(moduleName: string): JestObjectType, + /** + * Returns a new, unused mock function. Optionally takes a mock + * implementation. + */ + fn, TReturn>( + implementation?: (...args: TArguments) => TReturn, + ): JestMockFn, + /** + * Determines if the given function is a mocked function. + */ + isMockFunction(fn: Function): boolean, + /** + * Given the name of a module, use the automatic mocking system to generate a + * mocked version of the module for you. + */ + genMockFromModule(moduleName: string): any, + /** + * Mocks a module with an auto-mocked version when it is being required. + * + * The second argument can be used to specify an explicit module factory that + * is being run instead of using Jest's automocking feature. + * + * The third argument can be used to create virtual mocks -- mocks of modules + * that don't exist anywhere in the system. + */ + mock( + moduleName: string, + moduleFactory?: any, + options?: Object, + ): JestObjectType, + /** + * Resets the module registry - the cache of all required modules. This is + * useful to isolate modules where local state might conflict between tests. + */ + resetModules(): JestObjectType, + /** + * Exhausts the micro-task queue (usually interfaced in node via + * process.nextTick). + */ + runAllTicks(): void, + /** + * Exhausts the macro-task queue (i.e., all tasks queued by setTimeout(), + * setInterval(), and setImmediate()). + */ + runAllTimers(): void, + /** + * Exhausts all tasks queued by setImmediate(). + */ + runAllImmediates(): void, + /** + * Executes only the macro task queue (i.e. all tasks queued by setTimeout() + * or setInterval() and setImmediate()). + */ + advanceTimersByTime(msToRun: number): void, + /** + * Executes only the macro task queue (i.e. all tasks queued by setTimeout() + * or setInterval() and setImmediate()). + * + * Renamed to `advanceTimersByTime`. + */ + runTimersToTime(msToRun: number): void, + /** + * 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) + */ + runOnlyPendingTimers(): void, + /** + * Explicitly supplies the mock object that the module system should return + * for the specified module. Note: It is recommended to use jest.mock() + * instead. + */ + setMock(moduleName: string, moduleExports: any): JestObjectType, + /** + * 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). + */ + unmock(moduleName: string): JestObjectType, + /** + * Instructs Jest to use fake versions of the standard timer functions + * (setTimeout, setInterval, clearTimeout, clearInterval, nextTick, + * setImmediate and clearImmediate). + */ + useFakeTimers(): JestObjectType, + /** + * Instructs Jest to use the real versions of the standard timer functions. + */ + useRealTimers(): JestObjectType, + /** + * Creates a mock function similar to jest.fn but also tracks calls to + * object[methodName]. + */ + spyOn(object: Object, methodName: string): JestMockFn, + /** + * 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. + */ + setTimeout(timeout: number): JestObjectType, + + // These methods are added separately and not a part of flow-typed OSS + // version of this file. They were added in jest@21.0.0.alpha-2 which is not + // yet publicly released yet. + // TODO T21262347 Add them to OSS version of flow-typed + requireActual(module: string): any, + requireMock(module: string): any, +}; + type JestSpyType = { calls: JestCallsType, }; -declare function afterEach(fn: Function): void; -declare function beforeEach(fn: Function): void; -declare function afterAll(fn: Function): void; -declare function beforeAll(fn: Function): void; -declare function describe(name: string, fn: Function): void; +/** Runs this function after every test inside this context */ +declare function afterEach( + fn: (done: () => void) => ?Promise, + timeout?: number, +): void; +/** Runs this function before every test inside this context */ +declare function beforeEach( + fn: (done: () => void) => ?Promise, + timeout?: number, +): void; +/** Runs this function after all tests have finished inside this context */ +declare function afterAll( + fn: (done: () => void) => ?Promise, + timeout?: number, +): void; +/** Runs this function before any tests have started inside this context */ +declare function beforeAll( + fn: (done: () => void) => ?Promise, + timeout?: number, +): void; + +/** A context for grouping tests together */ +declare var describe: { + /** + * Creates a block that groups together several related tests in one "test suite" + */ + (name: string, fn: () => void): void, + + /** + * Only run this describe block + */ + only(name: string, fn: () => void): void, + + /** + * Skip running this describe block + */ + skip(name: string, fn: () => void): void, +}; + +/** An individual test unit */ declare var it: { - (name: string, fn: Function): ?Promise, - only(name: string, fn: Function): ?Promise, - skip(name: string, fn: Function): ?Promise, + /** + * An individual test unit + * + * @param {string} Name of Test + * @param {Function} Test + * @param {number} Timeout for the test, in milliseconds. + */ + ( + name: string, + fn?: (done: () => void) => ?Promise, + timeout?: number, + ): void, + /** + * Only run this test + * + * @param {string} Name of Test + * @param {Function} Test + * @param {number} Timeout for the test, in milliseconds. + */ + only( + name: string, + fn?: (done: () => void) => ?Promise, + timeout?: number, + ): void, + /** + * Skip running this test + * + * @param {string} Name of Test + * @param {Function} Test + * @param {number} Timeout for the test, in milliseconds. + */ + skip( + name: string, + fn?: (done: () => void) => ?Promise, + timeout?: number, + ): void, + /** + * Run the test concurrently + * + * @param {string} Name of Test + * @param {Function} Test + * @param {number} Timeout for the test, in milliseconds. + */ + concurrent( + name: string, + fn?: (done: () => void) => ?Promise, + timeout?: number, + ): void, }; -declare function fit(name: string, fn: Function): ?Promise; -declare function pit(name: string, fn: () => Promise): Promise; +declare function fit( + name: string, + fn: (done: () => void) => ?Promise, + timeout?: number, +): void; +/** An individual test unit */ declare var test: typeof it; +/** A disabled group of tests */ declare var xdescribe: typeof describe; +/** A focused group of tests */ declare var fdescribe: typeof describe; +/** A disabled individual test */ declare var xit: typeof it; +/** A disabled individual test */ declare var xtest: typeof it; +/** The expect function is used every time you want to test a value */ declare var expect: { - (value: any): JestExpectType & JestPromiseType, - any: any, + /** The object that you want to make assertions against */ + (value: any): JestExpectType & JestPromiseType & EnzymeMatchersType, + /** Add additional Jasmine matchers to Jest's roster */ extend(matchers: {[name: string]: JestMatcher}): void, - objectContaining(any): void, + /** Add a module that formats application-specific data structures. */ + addSnapshotSerializer(serializer: (input: Object) => string): void, + assertions(expectedAssertions: number): void, + hasAssertions(): void, + any(value: mixed): JestAsymmetricEqualityType, + anything(): void, + arrayContaining(value: Array): void, + objectContaining(value: Object): void, + /** Matches any received string that contains the exact expected string. */ + stringContaining(value: string): void, + stringMatching(value: string | RegExp): void, }; + declare function fail(message?: string): void; // TODO handle return type // http://jasmine.github.io/2.4/introduction.html#section-Spies declare function spyOn(value: mixed, method: string): Object; -type Jest = { - autoMockOff(): Jest, - autoMockOn(): Jest, - resetAllMocks(): Jest, - clearAllTimers(): void, - currentTestPath(): void, - disableAutomock(): Jest, - doMock(moduleName: string, moduleFactory?: any): void, - dontMock(moduleName: string): Jest, - enableAutomock(): Jest, - fn(implementation?: Function): JestMockFn, - genMockFromModule(moduleName: string): any, - isMockFunction(fn: Function): boolean, - mock( - moduleName: string, - moduleFactory?: any, - options?: {virtual?: boolean}, - ): Jest, - resetModuleRegistry(): Jest, // undocumented alias for resetModuleRegistry - resetModules(): Jest, - restoreAllMocks(): Jest, - runAllTicks(): Jest, - runAllTimers(): Jest, - runTimersToTime(msToRun: number): Jest, - runOnlyPendingTimers(): Jest, - setMock(moduleName: string, moduleExports: any): Jest, - unmock(moduleName: string): Jest, - useFakeTimers(): Jest, - useRealTimers(): Jest, -}; - -declare var jest: Jest; +/** Holds all functions related to manipulating test runner */ +declare var jest: JestObjectType; +/** + * The global Jamine object, this is generally not exposed as the public API, + * using features inside here could break in later versions of Jest. + */ declare var jasmine: { DEFAULT_TIMEOUT_INTERVAL: number, any(value: mixed): JestAsymmetricEqualityType, @@ -174,6 +634,10 @@ declare var jasmine: { arrayContaining(value: Array): void, clock(): JestClockType, createSpy(name: string): JestSpyType, + createSpyObj( + baseName: string, + methodNames: Array, + ): {[methodName: string]: JestSpyType}, objectContaining(value: Object): void, stringMatching(value: string): void, };