From c665f229e7abbec25a6e35ecea4aaf5defa24ae3 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 3 May 2020 20:37:51 +0200 Subject: [PATCH] feat: add `createMockFromModule` to replace `genMockFromModule` (#9962) --- CHANGELOG.md | 1 + docs/JestObjectAPI.md | 16 +++++++++------ docs/ManualMocks.md | 4 ++-- .../__mocks__/fs.js | 2 +- ...e.test.js => createMockFromModule.test.js} | 4 ++-- examples/manual-mocks/__mocks__/fs.js | 2 +- examples/manual-mocks/__mocks__/lodash.js | 2 +- .../manual-mocks/models/__mocks__/user.js | 2 +- .../module-mock/__tests__/partial_mock.js | 2 +- packages/jest-config/src/__mocks__/fs.js | 2 +- packages/jest-config/src/__mocks__/os.js | 2 +- .../src/__mocks__/index.ts | 2 +- packages/jest-environment/src/index.ts | 10 ++++++++++ .../src/__tests__/worker.test.js | 2 +- .../lib/__tests__/dependencyExtractor.test.js | 20 +++++++++++++++++++ .../src/lib/dependencyExtractor.ts | 2 +- .../src/__tests__/index.test.ts | 10 ++++++++-- .../src/__tests__/coverage_reporter.test.js | 2 +- ...> runtime_create_mock_from_module.test.js} | 10 +++++----- ... => mapped_module_createMockFromModule.js} | 0 packages/jest-runtime/src/index.ts | 2 ++ .../src/__tests__/inline_snapshots.test.ts | 2 +- .../jest-snapshot/src/__tests__/utils.test.ts | 2 +- .../src/__tests__/getCallsite.test.ts | 2 +- .../src/__tests__/test_sequencer.test.js | 2 +- .../src/__tests__/script_transformer.test.js | 2 +- 26 files changed, 76 insertions(+), 33 deletions(-) rename examples/automatic-mocks/__tests__/{genMockFromModule.test.js => createMockFromModule.test.js} (76%) rename packages/jest-runtime/src/__tests__/{runtime_gen_mock_from_module.test.js => runtime_create_mock_from_module.test.js} (86%) rename packages/jest-runtime/src/__tests__/test_root/{mapped_module_genMockFromModule.js => mapped_module_createMockFromModule.js} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15750ac69f9d..0e0db1897e2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - `[jest-environment-jsdom]` [**BREAKING**] Upgrade `jsdom` to v16 ([#9606](https://github.com/facebook/jest/pull/9606)) - `[@jest/fake-timers]` Add possibility to use a modern implementation of fake timers, backed by `@sinonjs/fake-timers` ([#7776](https://github.com/facebook/jest/pull/7776)) +- `[jest-runtime]` Add `createMockFromModule` as an alias for `genMockFromModule` ([#9962](https://github.com/facebook/jest/pull/9962)) ### Fixes diff --git a/docs/JestObjectAPI.md b/docs/JestObjectAPI.md index 7a6a39a2e28c..2a30948e86e3 100644 --- a/docs/JestObjectAPI.md +++ b/docs/JestObjectAPI.md @@ -90,7 +90,11 @@ test('original implementation', () => { _Note: this method was previously called `autoMockOn`. When using `babel-jest`, calls to `enableAutomock` will automatically be hoisted to the top of the code block. Use `autoMockOn` if you want to explicitly avoid this behavior._ -### `jest.genMockFromModule(moduleName)` +### `jest.createMockFromModule(moduleName)` + +##### renamed in Jest **26.0.0+** + +Also under the alias: `.genMockFromModule(moduleName)` Given the name of a module, use the automatic mocking system to generate a mocked version of the module for you. @@ -109,17 +113,17 @@ export default { ``` ```js -// __tests__/genMockFromModule.test.js -const utils = jest.genMockFromModule('../utils').default; +// __tests__/createMockFromModule.test.js +const utils = jest.createMockFromModule('../utils').default; utils.isAuthorized = jest.fn(secret => secret === 'not wizard'); -test('implementation created by jest.genMockFromModule', () => { +test('implementation created by jest.createMockFromModule', () => { expect(utils.authorize.mock).toBeTruthy(); expect(utils.isAuthorized('not wizard')).toEqual(true); }); ``` -This is how `genMockFromModule` will mock the following data types: +This is how `createMockFromModule` will mock the following data types: #### `Function` @@ -176,7 +180,7 @@ module.exports = { ```js // __tests__/example.test.js -const example = jest.genMockFromModule('./example'); +const example = jest.createMockFromModule('./example'); test('should run example code', () => { // creates a new mocked function with no formal arguments. diff --git a/docs/ManualMocks.md b/docs/ManualMocks.md index e2ae28acf3ea..a64816d71664 100644 --- a/docs/ManualMocks.md +++ b/docs/ManualMocks.md @@ -64,7 +64,7 @@ Since we'd like our tests to avoid actually hitting the disk (that's pretty slow const path = require('path'); -const fs = jest.genMockFromModule('fs'); +const fs = jest.createMockFromModule('fs'); // This is a custom function that our tests can use during setup to specify // what the files on the "mock" filesystem should look like when any of the @@ -124,7 +124,7 @@ describe('listFilesInDirectorySync', () => { }); ``` -The example mock shown here uses [`jest.genMockFromModule`](JestObjectAPI.md#jestgenmockfrommodulemodulename) to generate an automatic mock, and overrides its default behavior. This is the recommended approach, but is completely optional. If you do not want to use the automatic mock at all, you can export your own functions from the mock file. One downside to fully manual mocks is that they're manual – meaning you have to manually update them any time the module they are mocking changes. Because of this, it's best to use or extend the automatic mock when it works for your needs. +The example mock shown here uses [`jest.createMockFromModule`](JestObjectAPI.md#jestcreatemockfrommodulemodulename) to generate an automatic mock, and overrides its default behavior. This is the recommended approach, but is completely optional. If you do not want to use the automatic mock at all, you can export your own functions from the mock file. One downside to fully manual mocks is that they're manual – meaning you have to manually update them any time the module they are mocking changes. Because of this, it's best to use or extend the automatic mock when it works for your needs. To ensure that a manual mock and its real implementation stay in sync, it might be useful to require the real module using [`jest.requireActual(moduleName)`](JestObjectAPI.md#jestrequireactualmodulename) in your manual mock and amending it with mock functions before exporting it. diff --git a/e2e/runtime-internal-module-registry/__mocks__/fs.js b/e2e/runtime-internal-module-registry/__mocks__/fs.js index 86e21919deab..38ea4f886dbd 100644 --- a/e2e/runtime-internal-module-registry/__mocks__/fs.js +++ b/e2e/runtime-internal-module-registry/__mocks__/fs.js @@ -7,7 +7,7 @@ 'use strict'; -const fs = jest.genMockFromModule('fs'); +const fs = jest.createMockFromModule('fs'); let mkdirWasCalled = false; diff --git a/examples/automatic-mocks/__tests__/genMockFromModule.test.js b/examples/automatic-mocks/__tests__/createMockFromModule.test.js similarity index 76% rename from examples/automatic-mocks/__tests__/genMockFromModule.test.js rename to examples/automatic-mocks/__tests__/createMockFromModule.test.js index 274e1b8d5ca8..79881c511189 100644 --- a/examples/automatic-mocks/__tests__/genMockFromModule.test.js +++ b/examples/automatic-mocks/__tests__/createMockFromModule.test.js @@ -7,8 +7,8 @@ test('implementation created by automock', () => { expect(utils.isAuthorized()).toBeUndefined(); }); -test('implementation created by jest.genMockFromModule', () => { - const utils = jest.genMockFromModule('../utils').default; +test('implementation created by jest.createMockFromModule', () => { + const utils = jest.createMockFromModule('../utils').default; utils.isAuthorized = jest.fn(secret => secret === 'not wizard'); expect(utils.authorize.mock).toBeTruthy(); diff --git a/examples/manual-mocks/__mocks__/fs.js b/examples/manual-mocks/__mocks__/fs.js index 64b2bb76c7e4..8e5cd3838217 100644 --- a/examples/manual-mocks/__mocks__/fs.js +++ b/examples/manual-mocks/__mocks__/fs.js @@ -4,7 +4,7 @@ const path = require('path'); -const fs = jest.genMockFromModule('fs'); +const fs = jest.createMockFromModule('fs'); // This is a custom function that our tests can use during setup to specify // what the files on the "mock" filesystem should look like when any of the diff --git a/examples/manual-mocks/__mocks__/lodash.js b/examples/manual-mocks/__mocks__/lodash.js index b726843310b5..2039270fc09b 100644 --- a/examples/manual-mocks/__mocks__/lodash.js +++ b/examples/manual-mocks/__mocks__/lodash.js @@ -1,6 +1,6 @@ // Copyright 2004-present Facebook. All Rights Reserved. -const lodash = jest.genMockFromModule('lodash'); +const lodash = jest.createMockFromModule('lodash'); lodash.head = arr => 5; diff --git a/examples/manual-mocks/models/__mocks__/user.js b/examples/manual-mocks/models/__mocks__/user.js index 56a0e0d68492..57a95c398434 100644 --- a/examples/manual-mocks/models/__mocks__/user.js +++ b/examples/manual-mocks/models/__mocks__/user.js @@ -1,6 +1,6 @@ // Copyright 2004-present Facebook. All Rights Reserved. -const user = jest.genMockFromModule('../user'); +const user = jest.createMockFromModule('../user'); user.getAuthenticated = () => ({ age: 622, diff --git a/examples/module-mock/__tests__/partial_mock.js b/examples/module-mock/__tests__/partial_mock.js index 7e2b92434e13..6d7e610677fc 100644 --- a/examples/module-mock/__tests__/partial_mock.js +++ b/examples/module-mock/__tests__/partial_mock.js @@ -9,7 +9,7 @@ import defaultExport, {apple, strawberry} from '../fruit'; jest.mock('../fruit', () => { const originalModule = jest.requireActual('../fruit'); - const mockedModule = jest.genMockFromModule('../fruit'); + const mockedModule = jest.createMockFromModule('../fruit'); //Mock the default export and named export 'apple'. return { diff --git a/packages/jest-config/src/__mocks__/fs.js b/packages/jest-config/src/__mocks__/fs.js index c754fb89e64c..c4324a7869df 100644 --- a/packages/jest-config/src/__mocks__/fs.js +++ b/packages/jest-config/src/__mocks__/fs.js @@ -7,7 +7,7 @@ 'use strict'; -const fs = jest.genMockFromModule('fs'); +const fs = jest.createMockFromModule('fs'); const mockFiles = new Map(); function __setMockFiles(newMockFiles) { diff --git a/packages/jest-config/src/__mocks__/os.js b/packages/jest-config/src/__mocks__/os.js index 3d2c361f318b..a17b60dc17e7 100644 --- a/packages/jest-config/src/__mocks__/os.js +++ b/packages/jest-config/src/__mocks__/os.js @@ -7,7 +7,7 @@ 'use strict'; -const os = jest.genMockFromModule('os'); +const os = jest.createMockFromModule('os'); let cpus; function __setCpus(newCpus) { diff --git a/packages/jest-environment-jsdom/src/__mocks__/index.ts b/packages/jest-environment-jsdom/src/__mocks__/index.ts index b6f34c08f441..c87188636ec8 100644 --- a/packages/jest-environment-jsdom/src/__mocks__/index.ts +++ b/packages/jest-environment-jsdom/src/__mocks__/index.ts @@ -8,7 +8,7 @@ const vm = jest.requireActual('vm'); -const JSDOMEnvironment = jest.genMockFromModule('../index') as jest.Mock; +const JSDOMEnvironment = jest.createMockFromModule('../index') as jest.Mock; JSDOMEnvironment.mockImplementation(function (config) { // @ts-ignore diff --git a/packages/jest-environment/src/index.ts b/packages/jest-environment/src/index.ts index d886d7128535..21970ecd1543 100644 --- a/packages/jest-environment/src/index.ts +++ b/packages/jest-environment/src/index.ts @@ -126,8 +126,18 @@ export interface Jest { * * This is useful when you want to create a manual mock that extends the * automatic mock's behavior. + * + * @deprecated Use `jest.createMockFromModule()` instead */ genMockFromModule(moduleName: string): unknown; + /** + * Given the name of a module, use the automatic mocking system to generate a + * mocked version of the module for you. + * + * This is useful when you want to create a manual mock that extends the + * automatic mock's behavior. + */ + createMockFromModule(moduleName: string): unknown; /** * Determines if the given function is a mocked function. */ diff --git a/packages/jest-haste-map/src/__tests__/worker.test.js b/packages/jest-haste-map/src/__tests__/worker.test.js index cf313fe2e042..35d049ef76fe 100644 --- a/packages/jest-haste-map/src/__tests__/worker.test.js +++ b/packages/jest-haste-map/src/__tests__/worker.test.js @@ -38,7 +38,7 @@ jest.mock('graceful-fs', () => { }; return { - ...jest.genMockFromModule('graceful-fs'), + ...jest.createMockFromModule('graceful-fs'), readFileSync: jest.fn((path, options) => { if (mockFs[path]) { return options === 'utf8' ? mockFs[path] : Buffer.from(mockFs[path]); diff --git a/packages/jest-haste-map/src/lib/__tests__/dependencyExtractor.test.js b/packages/jest-haste-map/src/lib/__tests__/dependencyExtractor.test.js index d4f8ab691942..f2196a19c4b5 100644 --- a/packages/jest-haste-map/src/lib/__tests__/dependencyExtractor.test.js +++ b/packages/jest-haste-map/src/lib/__tests__/dependencyExtractor.test.js @@ -243,4 +243,24 @@ describe('dependencyExtractor', () => { `; expect(extract(code)).toEqual(new Set(['dep1', 'dep2', 'dep3', 'dep4'])); }); + + it('should extract dependencies from `jest.createMockFromModule` calls', () => { + const code = ` + // Good + jest.createMockFromModule('dep1'); + const dep2 = jest.createMockFromModule( + "dep2", + ); + if (jest.createMockFromModule(\`dep3\`).cond) {} + jest + .requireMock('dep4'); + + // Bad + ${COMMENT_NO_NEG_LB} foo . jest.createMockFromModule('inv1') + xjest.createMockFromModule('inv2'); + jest.createMockFromModulex('inv3'); + jest.createMockFromModule('inv4', 'inv5'); + `; + expect(extract(code)).toEqual(new Set(['dep1', 'dep2', 'dep3', 'dep4'])); + }); }); diff --git a/packages/jest-haste-map/src/lib/dependencyExtractor.ts b/packages/jest-haste-map/src/lib/dependencyExtractor.ts index e99a513701ec..56dce5ebfd81 100644 --- a/packages/jest-haste-map/src/lib/dependencyExtractor.ts +++ b/packages/jest-haste-map/src/lib/dependencyExtractor.ts @@ -63,7 +63,7 @@ const IMPORT_OR_EXPORT_RE = createRegExp( const JEST_EXTENSIONS_RE = createRegExp( [ ...functionCallStart( - 'jest\\s*\\.\\s*(?:requireActual|requireMock|genMockFromModule)', + 'jest\\s*\\.\\s*(?:requireActual|requireMock|genMockFromModule|createMockFromModule)', ), CAPTURE_STRING_LITERAL(1), WHITESPACE, diff --git a/packages/jest-regex-util/src/__tests__/index.test.ts b/packages/jest-regex-util/src/__tests__/index.test.ts index ca3ed9d1001f..ecfa008fd662 100644 --- a/packages/jest-regex-util/src/__tests__/index.test.ts +++ b/packages/jest-regex-util/src/__tests__/index.test.ts @@ -10,7 +10,10 @@ describe('replacePathSepForRegex()', () => { describe('posix', () => { beforeAll(() => { - jest.mock('path', () => ({...jest.genMockFromModule('path'), sep: '/'})); + jest.mock('path', () => ({ + ...jest.createMockFromModule('path'), + sep: '/', + })); jest.isolateModules(() => { replacePathSepForRegex = require('../').replacePathSepForRegex; }); @@ -24,7 +27,10 @@ describe('replacePathSepForRegex()', () => { describe('win32', () => { beforeAll(() => { - jest.mock('path', () => ({...jest.genMockFromModule('path'), sep: '\\'})); + jest.mock('path', () => ({ + ...jest.createMockFromModule('path'), + sep: '\\', + })); jest.isolateModules(() => { replacePathSepForRegex = require('../').replacePathSepForRegex; }); diff --git a/packages/jest-reporters/src/__tests__/coverage_reporter.test.js b/packages/jest-reporters/src/__tests__/coverage_reporter.test.js index 7e1cf5c4ceb6..e15df8cbdd59 100644 --- a/packages/jest-reporters/src/__tests__/coverage_reporter.test.js +++ b/packages/jest-reporters/src/__tests__/coverage_reporter.test.js @@ -13,7 +13,7 @@ jest summarizers: {pkg: jest.fn(() => ({visit: jest.fn()}))}, })) .mock('istanbul-reports', () => ({ - ...jest.genMockFromModule('istanbul-reports'), + ...jest.createMockFromModule('istanbul-reports'), create: jest.fn(() => ({execute: jest.fn()})), })); diff --git a/packages/jest-runtime/src/__tests__/runtime_gen_mock_from_module.test.js b/packages/jest-runtime/src/__tests__/runtime_create_mock_from_module.test.js similarity index 86% rename from packages/jest-runtime/src/__tests__/runtime_gen_mock_from_module.test.js rename to packages/jest-runtime/src/__tests__/runtime_create_mock_from_module.test.js index 818b87eaec97..301c4e3910fa 100644 --- a/packages/jest-runtime/src/__tests__/runtime_gen_mock_from_module.test.js +++ b/packages/jest-runtime/src/__tests__/runtime_create_mock_from_module.test.js @@ -19,7 +19,7 @@ describe('Runtime', () => { createRuntime = require('createRuntime'); }); - describe('genMockFromModule', () => { + describe('createMockFromModule', () => { it('does not cause side effects in the rest of the module system when generating a mock', () => createRuntime(__filename).then(runtime => { const testRequire = runtime.requireModule.bind( @@ -33,7 +33,7 @@ describe('Runtime', () => { expect(origModuleStateValue).toBe('default'); // Generate a mock for a module with side effects - const mock = module.jest.genMockFromModule('ModuleWithSideEffects'); + const mock = module.jest.createMockFromModule('ModuleWithSideEffects'); // Make sure we get a mock. expect(mock.fn()).toBe(undefined); @@ -43,8 +43,8 @@ describe('Runtime', () => { it('resolves mapped modules correctly', () => createRuntime(__filename, {moduleNameMapper}).then(runtime => { const root = runtime.requireModule(runtime.__mockRootPath); - const mockModule = root.jest.genMockFromModule( - 'module/name/genMockFromModule', + const mockModule = root.jest.createMockFromModule( + 'module/name/createMockFromModule', ); expect(mockModule.test.mock).toBeTruthy(); @@ -59,7 +59,7 @@ describe('Runtime', () => { ); const module = testRequire('RegularModule'); - const mockModule = module.jest.genMockFromModule('RegularModule'); + const mockModule = module.jest.createMockFromModule('RegularModule'); const testObjectPrototype = Object.getPrototypeOf(module.object); const mockObjectPrototype = Object.getPrototypeOf(mockModule.object); expect(mockObjectPrototype).toBe(testObjectPrototype); diff --git a/packages/jest-runtime/src/__tests__/test_root/mapped_module_genMockFromModule.js b/packages/jest-runtime/src/__tests__/test_root/mapped_module_createMockFromModule.js similarity index 100% rename from packages/jest-runtime/src/__tests__/test_root/mapped_module_genMockFromModule.js rename to packages/jest-runtime/src/__tests__/test_root/mapped_module_createMockFromModule.js diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 1acaa3647d3e..6c42dba9b8bc 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -1483,6 +1483,8 @@ class Runtime { autoMockOn: enableAutomock, clearAllMocks, clearAllTimers: () => _getFakeTimers().clearAllTimers(), + createMockFromModule: (moduleName: string) => + this._generateMock(from, moduleName), deepUnmock, disableAutomock, doMock: mock, diff --git a/packages/jest-snapshot/src/__tests__/inline_snapshots.test.ts b/packages/jest-snapshot/src/__tests__/inline_snapshots.test.ts index cf7cba34c07e..b605a863eff1 100644 --- a/packages/jest-snapshot/src/__tests__/inline_snapshots.test.ts +++ b/packages/jest-snapshot/src/__tests__/inline_snapshots.test.ts @@ -6,7 +6,7 @@ */ jest.mock('graceful-fs', () => ({ - ...jest.genMockFromModule('fs'), + ...jest.createMockFromModule('fs'), existsSync: jest.fn().mockReturnValue(true), readdirSync: jest.fn().mockReturnValue([]), statSync: jest.fn(filePath => ({ diff --git a/packages/jest-snapshot/src/__tests__/utils.test.ts b/packages/jest-snapshot/src/__tests__/utils.test.ts index 6f00aed6c0c4..d84e9358866b 100644 --- a/packages/jest-snapshot/src/__tests__/utils.test.ts +++ b/packages/jest-snapshot/src/__tests__/utils.test.ts @@ -6,7 +6,7 @@ */ jest.mock('graceful-fs', () => ({ - ...jest.genMockFromModule('fs'), + ...jest.createMockFromModule('fs'), existsSync: jest.fn().mockReturnValue(true), })); diff --git a/packages/jest-source-map/src/__tests__/getCallsite.test.ts b/packages/jest-source-map/src/__tests__/getCallsite.test.ts index c8bdf09eb76c..1eecf64fb65e 100644 --- a/packages/jest-source-map/src/__tests__/getCallsite.test.ts +++ b/packages/jest-source-map/src/__tests__/getCallsite.test.ts @@ -11,7 +11,7 @@ import getCallsite from '../getCallsite'; // Node 10.5.x compatibility jest.mock('graceful-fs', () => ({ - ...jest.genMockFromModule('fs'), + ...jest.createMockFromModule('fs'), ReadStream: jest.requireActual('fs').ReadStream, WriteStream: jest.requireActual('fs').WriteStream, })); diff --git a/packages/jest-test-sequencer/src/__tests__/test_sequencer.test.js b/packages/jest-test-sequencer/src/__tests__/test_sequencer.test.js index 4239f37bd8da..bebb86400145 100644 --- a/packages/jest-test-sequencer/src/__tests__/test_sequencer.test.js +++ b/packages/jest-test-sequencer/src/__tests__/test_sequencer.test.js @@ -10,7 +10,7 @@ import * as fs from 'graceful-fs'; import TestSequencer from '../index'; jest.mock('graceful-fs', () => ({ - ...jest.genMockFromModule('fs'), + ...jest.createMockFromModule('fs'), existsSync: jest.fn(() => true), readFileSync: jest.fn(() => '{}'), })); diff --git a/packages/jest-transform/src/__tests__/script_transformer.test.js b/packages/jest-transform/src/__tests__/script_transformer.test.js index 4d2796689fa6..d8d2281e5d78 100644 --- a/packages/jest-transform/src/__tests__/script_transformer.test.js +++ b/packages/jest-transform/src/__tests__/script_transformer.test.js @@ -13,7 +13,7 @@ jest .mock('graceful-fs', () => // Node 10.5.x compatibility ({ - ...jest.genMockFromModule('fs'), + ...jest.createMockFromModule('fs'), ReadStream: jest.requireActual('fs').ReadStream, WriteStream: jest.requireActual('fs').WriteStream, readFileSync: jest.fn((path, options) => {