From bcee67c37a3862584187ff3fa849f8161b40873a Mon Sep 17 00:00:00 2001 From: Matthias Dailey Date: Thu, 24 Mar 2022 15:45:39 -0400 Subject: [PATCH 01/15] Add contexts to mocks (https://github.com/facebook/jest/issues/11235) --- packages/jest-cli/src/cli/args.ts | 2 +- .../__tests__/__snapshots__/init.test.js.snap | 2 +- packages/jest-cli/src/init/questions.ts | 2 +- packages/jest-config/src/Descriptions.ts | 2 +- packages/jest-environment/src/index.ts | 2 +- .../__typetests__/mock-functions.test.ts | 4 ++- .../jest-mock/src/__tests__/index.test.ts | 33 +++++++++++++++++++ packages/jest-mock/src/index.ts | 6 ++++ .../version-25.x/JestObjectAPI.md | 2 +- .../version-25.x/MockFunctionAPI.md | 27 ++++++++++++++- .../version-25.x/MockFunctions.md | 3 ++ website/versioned_docs/version-26.x/CLI.md | 2 +- .../version-26.x/Configuration.md | 2 +- .../version-26.x/JestObjectAPI.md | 2 +- 14 files changed, 80 insertions(+), 11 deletions(-) diff --git a/packages/jest-cli/src/cli/args.ts b/packages/jest-cli/src/cli/args.ts index 57c55a59f129..289c737dd8fe 100644 --- a/packages/jest-cli/src/cli/args.ts +++ b/packages/jest-cli/src/cli/args.ts @@ -154,7 +154,7 @@ export const options = { }, clearMocks: { description: - 'Automatically clear mock calls, instances and results before every test. ' + + 'Automatically clear mock calls, instances, contexts and results before every test. ' + 'Equivalent to calling jest.clearAllMocks() before each test.', type: 'boolean', }, diff --git a/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap b/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap index 157419444c3d..2f6e62e9d149 100644 --- a/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap +++ b/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap @@ -108,7 +108,7 @@ Array [ }, Object { "initial": false, - "message": "Automatically clear mock calls, instances and results before every test?", + "message": "Automatically clear mock calls, instances, contexts and results before every test?", "name": "clearMocks", "type": "confirm", }, diff --git a/packages/jest-cli/src/init/questions.ts b/packages/jest-cli/src/init/questions.ts index fd4e9325ff7f..9d86faa6ccc2 100644 --- a/packages/jest-cli/src/init/questions.ts +++ b/packages/jest-cli/src/init/questions.ts @@ -43,7 +43,7 @@ const defaultQuestions: Array = [ { initial: false, message: - 'Automatically clear mock calls, instances and results before every test?', + 'Automatically clear mock calls, instances, contexts and results before every test?', name: 'clearMocks', type: 'confirm', }, diff --git a/packages/jest-config/src/Descriptions.ts b/packages/jest-config/src/Descriptions.ts index 795637460a1d..9f4549e5fb22 100644 --- a/packages/jest-config/src/Descriptions.ts +++ b/packages/jest-config/src/Descriptions.ts @@ -13,7 +13,7 @@ const descriptions: {[key in keyof Config.InitialOptions]: string} = { cacheDirectory: 'The directory where Jest should store its cached dependency information', clearMocks: - 'Automatically clear mock calls, instances and results before every test', + 'Automatically clear mock calls, instances, contexts and results before every test', collectCoverage: 'Indicates whether the coverage information should be collected while executing the test', collectCoverageFrom: diff --git a/packages/jest-environment/src/index.ts b/packages/jest-environment/src/index.ts index ac7fe89c30cc..6a96143ada73 100644 --- a/packages/jest-environment/src/index.ts +++ b/packages/jest-environment/src/index.ts @@ -71,7 +71,7 @@ export interface Jest { */ autoMockOn(): Jest; /** - * Clears the `mock.calls`, `mock.instances` and `mock.results` properties of + * Clears the `mock.calls`, `mock.instances`, `mock.contexts` and `mock.results` properties of * all mocks. Equivalent to calling `.mockClear()` on every mocked function. */ clearAllMocks(): Jest; diff --git a/packages/jest-mock/__typetests__/mock-functions.test.ts b/packages/jest-mock/__typetests__/mock-functions.test.ts index e1ace1d254f4..80d81e0a08bd 100644 --- a/packages/jest-mock/__typetests__/mock-functions.test.ts +++ b/packages/jest-mock/__typetests__/mock-functions.test.ts @@ -118,7 +118,9 @@ expectType< }> >(MockObject.mock.instances); -const returnValue = mockFn.mock.results[0]; +const returnValue = + +mockFn.mock.contexts[0]; expectType<'incomplete' | 'return' | 'throw'>(returnValue.type); expectType(returnValue.value); diff --git a/packages/jest-mock/src/__tests__/index.test.ts b/packages/jest-mock/src/__tests__/index.test.ts index bbfc2677d2b9..371ba0a04ea8 100644 --- a/packages/jest-mock/src/__tests__/index.test.ts +++ b/packages/jest-mock/src/__tests__/index.test.ts @@ -424,20 +424,53 @@ describe('moduleMocker', () => { expect(fn.mock.instances[1]).toBe(instance2); }); + it('tracks context objects passed to mock calls', () => { + const fn = moduleMocker.fn(); + expect(fn.mock.instances).toEqual([]); + + const ctx0 = {}; + fn.apply(ctx0, []); + expect(fn.mock.contexts[0]).toBe(ctx0); + + const ctx1 = {}; + fn.call(ctx1); + expect(fn.mock.contexts[1]).toBe(ctx1); + + const ctx2 = {}; + const bound2 = fn.bind(ctx2); + bound2(); + expect(fn.mock.contexts[2]).toBe(ctx2); + + // null context + fn.apply(null, []); + expect(fn.mock.contexts[3]).toBe(null); + fn.call(null); + expect(fn.mock.contexts[4]).toBe(null); + fn.bind(null)(); + expect(fn.mock.contexts[5]).toBe(null); + + // Unspecified context is `undefined` in strict mode (like in this test) and `window` otherwise. + fn(); + expect(fn.mock.contexts[6]).toBe(undefined); + }); + it('supports clearing mock calls', () => { const fn = moduleMocker.fn(); expect(fn.mock.calls).toEqual([]); fn(1, 2, 3); expect(fn.mock.calls).toEqual([[1, 2, 3]]); + expect(fn.mock.contexts).toEqual([undefined]); fn.mockReturnValue('abcd'); fn.mockClear(); expect(fn.mock.calls).toEqual([]); + expect(fn.mock.contexts).toEqual([]); fn('a', 'b', 'c'); expect(fn.mock.calls).toEqual([['a', 'b', 'c']]); + expect(fn.mock.contexts).toEqual([undefined]); expect(fn()).toEqual('abcd'); }); diff --git a/packages/jest-mock/src/index.ts b/packages/jest-mock/src/index.ts index 8358cbe36631..aa3be6c46019 100644 --- a/packages/jest-mock/src/index.ts +++ b/packages/jest-mock/src/index.ts @@ -201,6 +201,10 @@ type MockFunctionState = { * List of all the object instances that have been instantiated from the mock. */ instances: Array>; + /** + * List of all the function contexts that have been applied to calls to the mock. + */ + contexts: Array; /** * List of the call order indexes of the mock. Jest is indexing the order of * invocations of all mocks in a test file. The index is starting with `1`. @@ -570,6 +574,7 @@ export class ModuleMocker { return { calls: [], instances: [], + contexts: [], invocationCallOrder: [], results: [], }; @@ -636,6 +641,7 @@ export class ModuleMocker { const mockState = mocker._ensureMockState(f); const mockConfig = mocker._ensureMockConfig(f); mockState.instances.push(this); + mockState.contexts.push(this); mockState.calls.push(args); // Create and record an "incomplete" mock result immediately upon // calling rather than waiting for the mock to return. This avoids diff --git a/website/versioned_docs/version-25.x/JestObjectAPI.md b/website/versioned_docs/version-25.x/JestObjectAPI.md index 3437f2f9d5f9..170396e87919 100644 --- a/website/versioned_docs/version-25.x/JestObjectAPI.md +++ b/website/versioned_docs/version-25.x/JestObjectAPI.md @@ -560,7 +560,7 @@ test('plays audio', () => { ### `jest.clearAllMocks()` -Clears the `mock.calls`, `mock.instances` and `mock.results` properties of all mocks. Equivalent to calling [`.mockClear()`](MockFunctionAPI.md#mockfnmockclear) on every mocked function. +Clears the `mock.calls`, `mock.instances`, `mock.contexts` and `mock.results` properties of all mocks. Equivalent to calling [`.mockClear()`](MockFunctionAPI.md#mockfnmockclear) on every mocked function. Returns the `jest` object for chaining. diff --git a/website/versioned_docs/version-25.x/MockFunctionAPI.md b/website/versioned_docs/version-25.x/MockFunctionAPI.md index 5bb3925c81a1..6a4abfc1541b 100644 --- a/website/versioned_docs/version-25.x/MockFunctionAPI.md +++ b/website/versioned_docs/version-25.x/MockFunctionAPI.md @@ -79,9 +79,34 @@ mockFn.mock.instances[0] === a; // true mockFn.mock.instances[1] === b; // true ``` + +### `mockFn.mock.contexts` + +An array that contains the contexts for all calls of the mock function. + +A context is the `this` value that a function receives when called. +The context can be set using +`Function.prototype.bind`, `Function.prototype.call` or `Function.prototype.apply`. + +For example: + +```js +const mockFn = jest.fn(); + +const boundMockFn = mockFn.bind(thisContext0); +boundMockFn('a', 'b'); +mockFn.call(thisContext1, 'a', 'b'); +mockFn.apply(thisContext2, ['a', 'b']); + +mockFn.mock.contexts[0] === thisContext0; // true +mockFn.mock.contexts[1] === thisContext1; // true +mockFn.mock.contexts[2] === thisContext2; // true +``` + + ### `mockFn.mockClear()` -Clears all information stored in the [`mockFn.mock.calls`](#mockfnmockcalls), [`mockFn.mock.instances`](#mockfnmockinstances) and [`mockFn.mock.results`](#mockfnmockresults) arrays. Often this is useful when you want to clean up a mocks usage data between two assertions. +Clears all information stored in the [`mockFn.mock.calls`](#mockfnmockcalls), [`mockFn.mock.instances`](#mockfnmockinstances) [`mockFn.mock.contexts`](#mockfnmockcontexts) and [`mockFn.mock.results`](#mockfnmockresults) arrays. Often this is useful when you want to clean up a mocks usage data between two assertions. Beware that `mockClear` will replace `mockFn.mock`, not just these three properties! You should, therefore, avoid assigning `mockFn.mock` to other variables, temporary or not, to make sure you don't access stale data. diff --git a/website/versioned_docs/version-25.x/MockFunctions.md b/website/versioned_docs/version-25.x/MockFunctions.md index d583d55bdca8..3525fccbe3d9 100644 --- a/website/versioned_docs/version-25.x/MockFunctions.md +++ b/website/versioned_docs/version-25.x/MockFunctions.md @@ -69,6 +69,9 @@ expect(someMockFunction.mock.calls[0][1]).toBe('second arg'); // The return value of the first call to the function was 'return value' expect(someMockFunction.mock.results[0].value).toBe('return value'); +// The function was called with a certain `this` context: the `element` object. +expect(someMockFunction.mock.contexts[0]).toBe(element); + // This function was instantiated exactly twice expect(someMockFunction.mock.instances.length).toBe(2); diff --git a/website/versioned_docs/version-26.x/CLI.md b/website/versioned_docs/version-26.x/CLI.md index 23dc787bf2e8..a103e560b30c 100644 --- a/website/versioned_docs/version-26.x/CLI.md +++ b/website/versioned_docs/version-26.x/CLI.md @@ -140,7 +140,7 @@ Deletes the Jest cache directory and then exits without running tests. Will dele ### `--clearMocks` -Automatically clear mock calls, instances and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. +Automatically clear mock calls, instances, contexts, and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. ### `--collectCoverageFrom=` diff --git a/website/versioned_docs/version-26.x/Configuration.md b/website/versioned_docs/version-26.x/Configuration.md index b3e3fa0a8551..443aa97d4e5b 100644 --- a/website/versioned_docs/version-26.x/Configuration.md +++ b/website/versioned_docs/version-26.x/Configuration.md @@ -146,7 +146,7 @@ Jest attempts to scan your dependency tree once (up-front) and cache it in order Default: `false` -Automatically clear mock calls, instances and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. +Automatically clear mock calls, instances, contexts and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. ### `collectCoverage` \[boolean] diff --git a/website/versioned_docs/version-26.x/JestObjectAPI.md b/website/versioned_docs/version-26.x/JestObjectAPI.md index e2f4bdd0142a..13cb35822736 100644 --- a/website/versioned_docs/version-26.x/JestObjectAPI.md +++ b/website/versioned_docs/version-26.x/JestObjectAPI.md @@ -564,7 +564,7 @@ test('plays audio', () => { ### `jest.clearAllMocks()` -Clears the `mock.calls`, `mock.instances` and `mock.results` properties of all mocks. Equivalent to calling [`.mockClear()`](MockFunctionAPI.md#mockfnmockclear) on every mocked function. +Clears the `mock.calls`, `mock.instances`, `mock.contexts` and `mock.results` properties of all mocks. Equivalent to calling [`.mockClear()`](MockFunctionAPI.md#mockfnmockclear) on every mocked function. Returns the `jest` object for chaining. From 70161ae9c7e508f50266fed39b2b07515be93005 Mon Sep 17 00:00:00 2001 From: Matthias Dailey Date: Thu, 24 Mar 2022 15:50:29 -0400 Subject: [PATCH 02/15] Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index efa038f928b6..a535095dd1b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features +- `[jest-mock]` Add `contexts` member to mocks ([#12601](https://github.com/facebook/jest/pull/12601)) - `[babel-jest]` Export `createTransformer` function ([#12399](https://github.com/facebook/jest/pull/12399)) - `[expect]` Expose `AsymmetricMatchers`, `MatcherFunction` and `MatcherFunctionWithState` interfaces ([#12363](https://github.com/facebook/jest/pull/12363), [#12376](https://github.com/facebook/jest/pull/12376)) - `[jest-circus, jest-jasmine2]` Allowed classes and functions as `describe` and `it`/`test` names ([#12484](https://github.com/facebook/jest/pull/12484)) From 241bb047864c4b158a0b7bd2bfa1b350931d0d5f Mon Sep 17 00:00:00 2001 From: Matthias Dailey Date: Thu, 24 Mar 2022 17:11:06 -0400 Subject: [PATCH 03/15] Fix snapshots --- .../jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap b/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap index 2f6e62e9d149..830b5349d4fc 100644 --- a/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap +++ b/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap @@ -131,7 +131,7 @@ module.exports = { // The directory where Jest should store its cached dependency information // cacheDirectory: "/tmp/jest", - // Automatically clear mock calls, instances and results before every test + // Automatically clear mock calls, instances, contexts and results before every test // clearMocks: false, // Indicates whether the coverage information should be collected while executing the test From 68bd32785469f833b46c7fd64cbf485fff323032 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 25 Mar 2022 11:06:53 -0400 Subject: [PATCH 04/15] Use `ThisParameterType` to infer context type Co-authored-by: Tom Mrazauskas --- packages/jest-mock/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-mock/src/index.ts b/packages/jest-mock/src/index.ts index aa3be6c46019..43a5d297a949 100644 --- a/packages/jest-mock/src/index.ts +++ b/packages/jest-mock/src/index.ts @@ -204,7 +204,7 @@ type MockFunctionState = { /** * List of all the function contexts that have been applied to calls to the mock. */ - contexts: Array; + contexts: Array>; /** * List of the call order indexes of the mock. Jest is indexing the order of * invocations of all mocks in a test file. The index is starting with `1`. From 50c47190a367f18a7d48194f6171b6be31a61f1c Mon Sep 17 00:00:00 2001 From: Matthias Dailey Date: Fri, 25 Mar 2022 11:18:21 -0400 Subject: [PATCH 05/15] Move docs changes to docs/ and revert website/ changes --- docs/CLI.md | 2 +- docs/Configuration.md | 2 +- docs/JestObjectAPI.md | 2 +- docs/MockFunctionAPI.md | 27 ++++++++++++++++++- docs/MockFunctions.md | 17 +++++++----- .../version-25.x/MockFunctionAPI.md | 27 +------------------ .../version-25.x/MockFunctions.md | 3 --- website/versioned_docs/version-26.x/CLI.md | 2 +- .../version-26.x/Configuration.md | 2 +- .../version-26.x/JestObjectAPI.md | 2 +- 10 files changed, 44 insertions(+), 42 deletions(-) diff --git a/docs/CLI.md b/docs/CLI.md index d1cc0aecd2ae..6d50893f4c57 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -158,7 +158,7 @@ Clearing the cache will reduce performance. ### `--clearMocks` -Automatically clear mock calls, instances and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. +Automatically clear mock calls, instances, contexts and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. ### `--collectCoverageFrom=` diff --git a/docs/Configuration.md b/docs/Configuration.md index 7f9fa35a1b43..9c5d4905c26f 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -150,7 +150,7 @@ Jest attempts to scan your dependency tree once (up-front) and cache it in order Default: `false` -Automatically clear mock calls, instances and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. +Automatically clear mock calls, instances, contexts and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. ### `collectCoverage` \[boolean] diff --git a/docs/JestObjectAPI.md b/docs/JestObjectAPI.md index ed99e97fc3d0..aff9a86b5ff6 100644 --- a/docs/JestObjectAPI.md +++ b/docs/JestObjectAPI.md @@ -570,7 +570,7 @@ test('plays audio', () => { ### `jest.clearAllMocks()` -Clears the `mock.calls`, `mock.instances` and `mock.results` properties of all mocks. Equivalent to calling [`.mockClear()`](MockFunctionAPI.md#mockfnmockclear) on every mocked function. +Clears the `mock.calls`, `mock.instances`, `mock.contexts` and `mock.results` properties of all mocks. Equivalent to calling [`.mockClear()`](MockFunctionAPI.md#mockfnmockclear) on every mocked function. Returns the `jest` object for chaining. diff --git a/docs/MockFunctionAPI.md b/docs/MockFunctionAPI.md index 35a28365e986..89d6db9f648e 100644 --- a/docs/MockFunctionAPI.md +++ b/docs/MockFunctionAPI.md @@ -92,6 +92,31 @@ mockFn.mock.instances[0] === a; // true mockFn.mock.instances[1] === b; // true ``` + +### `mockFn.mock.contexts` + +An array that contains the contexts for all calls of the mock function. + +A context is the `this` value that a function receives when called. +The context can be set using +`Function.prototype.bind`, `Function.prototype.call` or `Function.prototype.apply`. + +For example: + +```js +const mockFn = jest.fn(); + +const boundMockFn = mockFn.bind(thisContext0); +boundMockFn('a', 'b'); +mockFn.call(thisContext1, 'a', 'b'); +mockFn.apply(thisContext2, ['a', 'b']); + +mockFn.mock.contexts[0] === thisContext0; // true +mockFn.mock.contexts[1] === thisContext1; // true +mockFn.mock.contexts[2] === thisContext2; // true +``` + + ### `mockFn.mock.lastCall` An array containing the call arguments of the last call that was made to this mock function. If the function was not called, it will return `undefined`. @@ -104,7 +129,7 @@ For example: A mock function `f` that has been called twice, with the arguments ### `mockFn.mockClear()` -Clears all information stored in the [`mockFn.mock.calls`](#mockfnmockcalls), [`mockFn.mock.instances`](#mockfnmockinstances) and [`mockFn.mock.results`](#mockfnmockresults) arrays. Often this is useful when you want to clean up a mocks usage data between two assertions. +Clears all information stored in the [`mockFn.mock.calls`](#mockfnmockcalls), [`mockFn.mock.instances`](#mockfnmockinstances), [`mockFn.mock.contexts`](#mockfnmockcontexts) and [`mockFn.mock.results`](#mockfnmockresults) arrays. Often this is useful when you want to clean up a mocks usage data between two assertions. Beware that `mockFn.mockClear()` will replace `mockFn.mock`, not just these three properties! You should, therefore, avoid assigning `mockFn.mock` to other variables, temporary or not, to make sure you don't access stale data. diff --git a/docs/MockFunctions.md b/docs/MockFunctions.md index 38870027a515..d1f1752de2d1 100644 --- a/docs/MockFunctions.md +++ b/docs/MockFunctions.md @@ -43,15 +43,17 @@ expect(mockCallback.mock.results[0].value).toBe(42); All mock functions have this special `.mock` property, which is where data about how the function has been called and what the function returned is kept. The `.mock` property also tracks the value of `this` for each call, so it is possible to inspect this as well: ```javascript -const myMock = jest.fn(); +const myMock1 = jest.fn(); +const a = new myMock1(); +console.log(myMock1.mock.instances); +// > [ ] -const a = new myMock(); +const myMock2 = jest.fn(); const b = {}; -const bound = myMock.bind(b); +const bound = myMock2.bind(b); bound(); - -console.log(myMock.mock.instances); -// > [ , ] +console.log(myMock2.mock.contexts); +// > [ ] ``` These mock members are very useful in tests to assert how these functions get called, instantiated, or what they returned: @@ -69,6 +71,9 @@ expect(someMockFunction.mock.calls[0][1]).toBe('second arg'); // The return value of the first call to the function was 'return value' expect(someMockFunction.mock.results[0].value).toBe('return value'); +// The function was called with a certain `this` context: the `element` object. +expect(someMockFunction.mock.contexts[0]).toBe(element); + // This function was instantiated exactly twice expect(someMockFunction.mock.instances.length).toBe(2); diff --git a/website/versioned_docs/version-25.x/MockFunctionAPI.md b/website/versioned_docs/version-25.x/MockFunctionAPI.md index 6a4abfc1541b..5bb3925c81a1 100644 --- a/website/versioned_docs/version-25.x/MockFunctionAPI.md +++ b/website/versioned_docs/version-25.x/MockFunctionAPI.md @@ -79,34 +79,9 @@ mockFn.mock.instances[0] === a; // true mockFn.mock.instances[1] === b; // true ``` - -### `mockFn.mock.contexts` - -An array that contains the contexts for all calls of the mock function. - -A context is the `this` value that a function receives when called. -The context can be set using -`Function.prototype.bind`, `Function.prototype.call` or `Function.prototype.apply`. - -For example: - -```js -const mockFn = jest.fn(); - -const boundMockFn = mockFn.bind(thisContext0); -boundMockFn('a', 'b'); -mockFn.call(thisContext1, 'a', 'b'); -mockFn.apply(thisContext2, ['a', 'b']); - -mockFn.mock.contexts[0] === thisContext0; // true -mockFn.mock.contexts[1] === thisContext1; // true -mockFn.mock.contexts[2] === thisContext2; // true -``` - - ### `mockFn.mockClear()` -Clears all information stored in the [`mockFn.mock.calls`](#mockfnmockcalls), [`mockFn.mock.instances`](#mockfnmockinstances) [`mockFn.mock.contexts`](#mockfnmockcontexts) and [`mockFn.mock.results`](#mockfnmockresults) arrays. Often this is useful when you want to clean up a mocks usage data between two assertions. +Clears all information stored in the [`mockFn.mock.calls`](#mockfnmockcalls), [`mockFn.mock.instances`](#mockfnmockinstances) and [`mockFn.mock.results`](#mockfnmockresults) arrays. Often this is useful when you want to clean up a mocks usage data between two assertions. Beware that `mockClear` will replace `mockFn.mock`, not just these three properties! You should, therefore, avoid assigning `mockFn.mock` to other variables, temporary or not, to make sure you don't access stale data. diff --git a/website/versioned_docs/version-25.x/MockFunctions.md b/website/versioned_docs/version-25.x/MockFunctions.md index 3525fccbe3d9..d583d55bdca8 100644 --- a/website/versioned_docs/version-25.x/MockFunctions.md +++ b/website/versioned_docs/version-25.x/MockFunctions.md @@ -69,9 +69,6 @@ expect(someMockFunction.mock.calls[0][1]).toBe('second arg'); // The return value of the first call to the function was 'return value' expect(someMockFunction.mock.results[0].value).toBe('return value'); -// The function was called with a certain `this` context: the `element` object. -expect(someMockFunction.mock.contexts[0]).toBe(element); - // This function was instantiated exactly twice expect(someMockFunction.mock.instances.length).toBe(2); diff --git a/website/versioned_docs/version-26.x/CLI.md b/website/versioned_docs/version-26.x/CLI.md index a103e560b30c..2ca0d72671bb 100644 --- a/website/versioned_docs/version-26.x/CLI.md +++ b/website/versioned_docs/version-26.x/CLI.md @@ -140,7 +140,7 @@ Deletes the Jest cache directory and then exits without running tests. Will dele ### `--clearMocks` -Automatically clear mock calls, instances, contexts, and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. +Automatically clear mock calls, instances, and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. ### `--collectCoverageFrom=` diff --git a/website/versioned_docs/version-26.x/Configuration.md b/website/versioned_docs/version-26.x/Configuration.md index 443aa97d4e5b..b3e3fa0a8551 100644 --- a/website/versioned_docs/version-26.x/Configuration.md +++ b/website/versioned_docs/version-26.x/Configuration.md @@ -146,7 +146,7 @@ Jest attempts to scan your dependency tree once (up-front) and cache it in order Default: `false` -Automatically clear mock calls, instances, contexts and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. +Automatically clear mock calls, instances and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. ### `collectCoverage` \[boolean] diff --git a/website/versioned_docs/version-26.x/JestObjectAPI.md b/website/versioned_docs/version-26.x/JestObjectAPI.md index 13cb35822736..e2f4bdd0142a 100644 --- a/website/versioned_docs/version-26.x/JestObjectAPI.md +++ b/website/versioned_docs/version-26.x/JestObjectAPI.md @@ -564,7 +564,7 @@ test('plays audio', () => { ### `jest.clearAllMocks()` -Clears the `mock.calls`, `mock.instances`, `mock.contexts` and `mock.results` properties of all mocks. Equivalent to calling [`.mockClear()`](MockFunctionAPI.md#mockfnmockclear) on every mocked function. +Clears the `mock.calls`, `mock.instances` and `mock.results` properties of all mocks. Equivalent to calling [`.mockClear()`](MockFunctionAPI.md#mockfnmockclear) on every mocked function. Returns the `jest` object for chaining. From 39215f50c764ae9cc1b527282f2959e5c80bdc1f Mon Sep 17 00:00:00 2001 From: Matthias Dailey Date: Fri, 25 Mar 2022 11:19:40 -0400 Subject: [PATCH 06/15] .. --- website/versioned_docs/version-25.x/JestObjectAPI.md | 2 +- website/versioned_docs/version-26.x/CLI.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/website/versioned_docs/version-25.x/JestObjectAPI.md b/website/versioned_docs/version-25.x/JestObjectAPI.md index 170396e87919..3437f2f9d5f9 100644 --- a/website/versioned_docs/version-25.x/JestObjectAPI.md +++ b/website/versioned_docs/version-25.x/JestObjectAPI.md @@ -560,7 +560,7 @@ test('plays audio', () => { ### `jest.clearAllMocks()` -Clears the `mock.calls`, `mock.instances`, `mock.contexts` and `mock.results` properties of all mocks. Equivalent to calling [`.mockClear()`](MockFunctionAPI.md#mockfnmockclear) on every mocked function. +Clears the `mock.calls`, `mock.instances` and `mock.results` properties of all mocks. Equivalent to calling [`.mockClear()`](MockFunctionAPI.md#mockfnmockclear) on every mocked function. Returns the `jest` object for chaining. diff --git a/website/versioned_docs/version-26.x/CLI.md b/website/versioned_docs/version-26.x/CLI.md index 2ca0d72671bb..23dc787bf2e8 100644 --- a/website/versioned_docs/version-26.x/CLI.md +++ b/website/versioned_docs/version-26.x/CLI.md @@ -140,7 +140,7 @@ Deletes the Jest cache directory and then exits without running tests. Will dele ### `--clearMocks` -Automatically clear mock calls, instances, and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. +Automatically clear mock calls, instances and results before every test. Equivalent to calling [`jest.clearAllMocks()`](JestObjectAPI.md#jestclearallmocks) before each test. This does not remove any mock implementation that may have been provided. ### `--collectCoverageFrom=` From 3784fe888b048c5a9c4437485d0e84df43d4b089 Mon Sep 17 00:00:00 2001 From: Matthias Dailey Date: Fri, 25 Mar 2022 11:21:49 -0400 Subject: [PATCH 07/15] fix diff newline --- packages/jest-mock/__typetests__/mock-functions.test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/jest-mock/__typetests__/mock-functions.test.ts b/packages/jest-mock/__typetests__/mock-functions.test.ts index 80d81e0a08bd..50c68e69f3de 100644 --- a/packages/jest-mock/__typetests__/mock-functions.test.ts +++ b/packages/jest-mock/__typetests__/mock-functions.test.ts @@ -118,9 +118,7 @@ expectType< }> >(MockObject.mock.instances); -const returnValue = - -mockFn.mock.contexts[0]; +const returnValue = mockFn.mock.contexts[0]; expectType<'incomplete' | 'return' | 'throw'>(returnValue.type); expectType(returnValue.value); From 2b8de1732a388cd005f8c9cb56f5a40fde82e0ea Mon Sep 17 00:00:00 2001 From: Matthias Dailey Date: Fri, 25 Mar 2022 11:42:01 -0400 Subject: [PATCH 08/15] Fix up type tests, member ordering --- packages/jest-mock/__typetests__/mock-functions.test.ts | 8 ++++++-- packages/jest-mock/src/index.ts | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/jest-mock/__typetests__/mock-functions.test.ts b/packages/jest-mock/__typetests__/mock-functions.test.ts index 50c68e69f3de..d03c1b41edd0 100644 --- a/packages/jest-mock/__typetests__/mock-functions.test.ts +++ b/packages/jest-mock/__typetests__/mock-functions.test.ts @@ -66,7 +66,8 @@ expectType never>>( ); expectError(fn('moduleName')); -const mockFn = fn((a: string, b?: number) => true); +declare const mockFnImpl: (this: Date, a: string, b?: number) => true; +const mockFn = fn(mockFnImpl); const mockAsyncFn = fn(async (p: boolean) => 'value'); expectType(mockFn('one', 2)); @@ -118,7 +119,7 @@ expectType< }> >(MockObject.mock.instances); -const returnValue = mockFn.mock.contexts[0]; +const returnValue = mockFn.mock.results[0]; expectType<'incomplete' | 'return' | 'throw'>(returnValue.type); expectType(returnValue.value); @@ -135,6 +136,9 @@ if (returnValue.type === 'throw') { expectType(returnValue.value); } +const context = mockFn.mock.contexts[0]; +expectType(context); + expectType boolean>>( mockFn.mockClear(), ); diff --git a/packages/jest-mock/src/index.ts b/packages/jest-mock/src/index.ts index 43a5d297a949..85fe4aeb229c 100644 --- a/packages/jest-mock/src/index.ts +++ b/packages/jest-mock/src/index.ts @@ -573,8 +573,8 @@ export class ModuleMocker { private _defaultMockState(): MockFunctionState { return { calls: [], - instances: [], contexts: [], + instances: [], invocationCallOrder: [], results: [], }; From e8e2666c5c08ede60b4b2e0f02d5256b75220d41 Mon Sep 17 00:00:00 2001 From: Matthias Dailey Date: Fri, 25 Mar 2022 11:47:33 -0400 Subject: [PATCH 09/15] Sort changelog entry --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a535095dd1b4..c10ff583345e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,6 @@ ### Features -- `[jest-mock]` Add `contexts` member to mocks ([#12601](https://github.com/facebook/jest/pull/12601)) - `[babel-jest]` Export `createTransformer` function ([#12399](https://github.com/facebook/jest/pull/12399)) - `[expect]` Expose `AsymmetricMatchers`, `MatcherFunction` and `MatcherFunctionWithState` interfaces ([#12363](https://github.com/facebook/jest/pull/12363), [#12376](https://github.com/facebook/jest/pull/12376)) - `[jest-circus, jest-jasmine2]` Allowed classes and functions as `describe` and `it`/`test` names ([#12484](https://github.com/facebook/jest/pull/12484)) @@ -27,9 +26,9 @@ - `[jest-haste-map]` [**BREAKING**] `HasteMap.create` now returns a promise ([#12008](https://github.com/facebook/jest/pull/12008)) - `[jest-haste-map]` Add support for `dependencyExtractor` written in ESM ([#12008](https://github.com/facebook/jest/pull/12008)) - `[jest-mock]` [**BREAKING**] Rename exported utility types `ClassLike`, `FunctionLike`, `ConstructorLikeKeys`, `MethodLikeKeys`, `PropertyLikeKeys`; remove exports of utility types `ArgumentsOf`, `ArgsType`, `ConstructorArgumentsOf` - TS builtin utility types `ConstructorParameters` and `Parameters` should be used instead ([#12435](https://github.com/facebook/jest/pull/12435), [#12489](https://github.com/facebook/jest/pull/12489)) -- `[jest-mock]` Improve `isMockFunction` to infer types of passed function ([#12442](https://github.com/facebook/jest/pull/12442)) - `[jest-mock]` [**BREAKING**] Improve the usage of `jest.fn` generic type argument ([#12489](https://github.com/facebook/jest/pull/12489)) - `[jest-mock]` Add support for auto-mocking async generator functions ([#11080](https://github.com/facebook/jest/pull/11080)) +- `[jest-mock]` Add `contexts` member to mocks ([#12601](https://github.com/facebook/jest/pull/12601))- `[jest-mock]` Improve `isMockFunction` to infer types of passed function ([#12442](https://github.com/facebook/jest/pull/12442)) - `[jest-resolve]` [**BREAKING**] Add support for `package.json` `exports` ([#11961](https://github.com/facebook/jest/pull/11961), [#12373](https://github.com/facebook/jest/pull/12373)) - `[jest-resolve, jest-runtime]` Add support for `data:` URI import and mock ([#12392](https://github.com/facebook/jest/pull/12392)) - `[jest-resolve, jest-runtime]` Add support for async resolver ([#11540](https://github.com/facebook/jest/pull/11540)) From 49d1ed193e0317c2f1c334a3451d9c08aff81d30 Mon Sep 17 00:00:00 2001 From: Matthias Dailey Date: Fri, 25 Mar 2022 11:53:18 -0400 Subject: [PATCH 10/15] revert changelog typo --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c10ff583345e..08f77fa43a35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,9 +26,10 @@ - `[jest-haste-map]` [**BREAKING**] `HasteMap.create` now returns a promise ([#12008](https://github.com/facebook/jest/pull/12008)) - `[jest-haste-map]` Add support for `dependencyExtractor` written in ESM ([#12008](https://github.com/facebook/jest/pull/12008)) - `[jest-mock]` [**BREAKING**] Rename exported utility types `ClassLike`, `FunctionLike`, `ConstructorLikeKeys`, `MethodLikeKeys`, `PropertyLikeKeys`; remove exports of utility types `ArgumentsOf`, `ArgsType`, `ConstructorArgumentsOf` - TS builtin utility types `ConstructorParameters` and `Parameters` should be used instead ([#12435](https://github.com/facebook/jest/pull/12435), [#12489](https://github.com/facebook/jest/pull/12489)) +- `[jest-mock]` Improve `isMockFunction` to infer types of passed function ([#12442](https://github.com/facebook/jest/pull/12442)) - `[jest-mock]` [**BREAKING**] Improve the usage of `jest.fn` generic type argument ([#12489](https://github.com/facebook/jest/pull/12489)) - `[jest-mock]` Add support for auto-mocking async generator functions ([#11080](https://github.com/facebook/jest/pull/11080)) -- `[jest-mock]` Add `contexts` member to mocks ([#12601](https://github.com/facebook/jest/pull/12601))- `[jest-mock]` Improve `isMockFunction` to infer types of passed function ([#12442](https://github.com/facebook/jest/pull/12442)) +- `[jest-mock]` Add `contexts` member to mocks ([#12601](https://github.com/facebook/jest/pull/12601)) - `[jest-resolve]` [**BREAKING**] Add support for `package.json` `exports` ([#11961](https://github.com/facebook/jest/pull/11961), [#12373](https://github.com/facebook/jest/pull/12373)) - `[jest-resolve, jest-runtime]` Add support for `data:` URI import and mock ([#12392](https://github.com/facebook/jest/pull/12392)) - `[jest-resolve, jest-runtime]` Add support for async resolver ([#11540](https://github.com/facebook/jest/pull/11540)) From d3d31b791276f8416922ffe509fe37a00e03ed90 Mon Sep 17 00:00:00 2001 From: Matthias Dailey Date: Fri, 25 Mar 2022 12:28:00 -0400 Subject: [PATCH 11/15] Fix type tests --- packages/jest-mock/__typetests__/mock-functions.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-mock/__typetests__/mock-functions.test.ts b/packages/jest-mock/__typetests__/mock-functions.test.ts index d03c1b41edd0..04949f6036e1 100644 --- a/packages/jest-mock/__typetests__/mock-functions.test.ts +++ b/packages/jest-mock/__typetests__/mock-functions.test.ts @@ -66,7 +66,7 @@ expectType never>>( ); expectError(fn('moduleName')); -declare const mockFnImpl: (this: Date, a: string, b?: number) => true; +declare const mockFnImpl: (this: Date, a: string, b?: number) => boolean; const mockFn = fn(mockFnImpl); const mockAsyncFn = fn(async (p: boolean) => 'value'); From 8c629cf9b9f36a00aeb51c0471f0e0ad899af5b0 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Fri, 25 Mar 2022 17:38:25 +0100 Subject: [PATCH 12/15] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08f77fa43a35..97cb51312edc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,7 @@ - `[jest-mock]` Improve `isMockFunction` to infer types of passed function ([#12442](https://github.com/facebook/jest/pull/12442)) - `[jest-mock]` [**BREAKING**] Improve the usage of `jest.fn` generic type argument ([#12489](https://github.com/facebook/jest/pull/12489)) - `[jest-mock]` Add support for auto-mocking async generator functions ([#11080](https://github.com/facebook/jest/pull/11080)) -- `[jest-mock]` Add `contexts` member to mocks ([#12601](https://github.com/facebook/jest/pull/12601)) +- `[jest-mock]` Add `contexts` member to mock functions ([#12601](https://github.com/facebook/jest/pull/12601)) - `[jest-resolve]` [**BREAKING**] Add support for `package.json` `exports` ([#11961](https://github.com/facebook/jest/pull/11961), [#12373](https://github.com/facebook/jest/pull/12373)) - `[jest-resolve, jest-runtime]` Add support for `data:` URI import and mock ([#12392](https://github.com/facebook/jest/pull/12392)) - `[jest-resolve, jest-runtime]` Add support for async resolver ([#11540](https://github.com/facebook/jest/pull/11540)) From fd616307313e2378638c13ccc3715a7cb340cc55 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 28 Mar 2022 11:13:02 -0400 Subject: [PATCH 13/15] Combine contexts type assertion into one line Co-authored-by: Tom Mrazauskas --- packages/jest-mock/__typetests__/mock-functions.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/jest-mock/__typetests__/mock-functions.test.ts b/packages/jest-mock/__typetests__/mock-functions.test.ts index 04949f6036e1..6be5a35b7b77 100644 --- a/packages/jest-mock/__typetests__/mock-functions.test.ts +++ b/packages/jest-mock/__typetests__/mock-functions.test.ts @@ -136,8 +136,7 @@ if (returnValue.type === 'throw') { expectType(returnValue.value); } -const context = mockFn.mock.contexts[0]; -expectType(context); +expectType>(mockFn.mock.contexts); expectType boolean>>( mockFn.mockClear(), From fa3fb3eff590244d5dd98e9e6177a89f7df3b57b Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 28 Mar 2022 11:13:53 -0400 Subject: [PATCH 14/15] Clarify `mockClear` Co-authored-by: Tom Mrazauskas --- docs/MockFunctionAPI.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/MockFunctionAPI.md b/docs/MockFunctionAPI.md index 89d6db9f648e..8b97180ad035 100644 --- a/docs/MockFunctionAPI.md +++ b/docs/MockFunctionAPI.md @@ -131,7 +131,7 @@ For example: A mock function `f` that has been called twice, with the arguments Clears all information stored in the [`mockFn.mock.calls`](#mockfnmockcalls), [`mockFn.mock.instances`](#mockfnmockinstances), [`mockFn.mock.contexts`](#mockfnmockcontexts) and [`mockFn.mock.results`](#mockfnmockresults) arrays. Often this is useful when you want to clean up a mocks usage data between two assertions. -Beware that `mockFn.mockClear()` will replace `mockFn.mock`, not just these three properties! You should, therefore, avoid assigning `mockFn.mock` to other variables, temporary or not, to make sure you don't access stale data. +Beware that `mockFn.mockClear()` will replace `mockFn.mock`, not just reset the values of its properties! You should, therefore, avoid assigning `mockFn.mock` to other variables, temporary or not, to make sure you don't access stale data. The [`clearMocks`](configuration#clearmocks-boolean) configuration option is available to clear mocks automatically before each tests. From 245a3ac5b6723e9785a7a0941a8d8509b4f651c7 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 29 Mar 2022 10:04:57 +0200 Subject: [PATCH 15/15] prettier --- docs/MockFunctionAPI.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/MockFunctionAPI.md b/docs/MockFunctionAPI.md index 8b97180ad035..0ac4de121f65 100644 --- a/docs/MockFunctionAPI.md +++ b/docs/MockFunctionAPI.md @@ -92,14 +92,11 @@ mockFn.mock.instances[0] === a; // true mockFn.mock.instances[1] === b; // true ``` - ### `mockFn.mock.contexts` An array that contains the contexts for all calls of the mock function. -A context is the `this` value that a function receives when called. -The context can be set using -`Function.prototype.bind`, `Function.prototype.call` or `Function.prototype.apply`. +A context is the `this` value that a function receives when called. The context can be set using `Function.prototype.bind`, `Function.prototype.call` or `Function.prototype.apply`. For example: @@ -116,7 +113,6 @@ mockFn.mock.contexts[1] === thisContext1; // true mockFn.mock.contexts[2] === thisContext2; // true ``` - ### `mockFn.mock.lastCall` An array containing the call arguments of the last call that was made to this mock function. If the function was not called, it will return `undefined`.