Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add createMockFromModule to replace genMockFromModule #9962

Merged
merged 2 commits into from
May 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
16 changes: 10 additions & 6 deletions docs/JestObjectAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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`

Expand Down Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions docs/ManualMocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion e2e/runtime-internal-module-registry/__mocks__/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

'use strict';

const fs = jest.genMockFromModule('fs');
const fs = jest.createMockFromModule('fs');

let mkdirWasCalled = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion examples/manual-mocks/__mocks__/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion examples/manual-mocks/__mocks__/lodash.js
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
2 changes: 1 addition & 1 deletion examples/manual-mocks/models/__mocks__/user.js
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
2 changes: 1 addition & 1 deletion examples/module-mock/__tests__/partial_mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-config/src/__mocks__/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

'use strict';

const fs = jest.genMockFromModule('fs');
const fs = jest.createMockFromModule('fs');

const mockFiles = new Map();
function __setMockFiles(newMockFiles) {
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-config/src/__mocks__/os.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

'use strict';

const os = jest.genMockFromModule('os');
const os = jest.createMockFromModule('os');

let cpus;
function __setCpus(newCpus) {
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-environment-jsdom/src/__mocks__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions packages/jest-environment/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-haste-map/src/__tests__/worker.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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']));
});
});
2 changes: 1 addition & 1 deletion packages/jest-haste-map/src/lib/dependencyExtractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
10 changes: 8 additions & 2 deletions packages/jest-regex-util/src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
});
Expand All @@ -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;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()})),
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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);
Expand All @@ -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();
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1483,6 +1483,8 @@ class Runtime {
autoMockOn: enableAutomock,
clearAllMocks,
clearAllTimers: () => _getFakeTimers().clearAllTimers(),
createMockFromModule: (moduleName: string) =>
this._generateMock(from, moduleName),
deepUnmock,
disableAutomock,
doMock: mock,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

jest.mock('graceful-fs', () => ({
...jest.genMockFromModule<typeof import('fs')>('fs'),
...jest.createMockFromModule<typeof import('fs')>('fs'),
existsSync: jest.fn().mockReturnValue(true),
readdirSync: jest.fn().mockReturnValue([]),
statSync: jest.fn(filePath => ({
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-snapshot/src/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

jest.mock('graceful-fs', () => ({
...jest.genMockFromModule<typeof import('fs')>('fs'),
...jest.createMockFromModule<typeof import('fs')>('fs'),
existsSync: jest.fn().mockReturnValue(true),
}));

Expand Down
2 changes: 1 addition & 1 deletion packages/jest-source-map/src/__tests__/getCallsite.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import getCallsite from '../getCallsite';

// Node 10.5.x compatibility
jest.mock('graceful-fs', () => ({
...jest.genMockFromModule<typeof import('fs')>('fs'),
...jest.createMockFromModule<typeof import('fs')>('fs'),
ReadStream: jest.requireActual('fs').ReadStream,
WriteStream: jest.requireActual('fs').WriteStream,
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => '{}'),
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down