Skip to content

Commit ab64cc8

Browse files
grostoSimenB
authored andcommitted
Fix for mocks not working with module name mapper (#7787)
1 parent 006b0b9 commit ab64cc8

File tree

10 files changed

+117
-31
lines changed

10 files changed

+117
-31
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
### Fixes
1313

14+
- `[jest-runtime]` Fix for mocks not working with module name mapper ([#7787](https://github.com/facebook/jest/pull/7787))
1415
- `[jest-cli]` Break dependency cycle when using Jest programmatically ([#7707](https://github.com/facebook/jest/pull/7707))
1516
- `[jest-config]` Extract setupFilesAfterEnv from preset ([#7724](https://github.com/facebook/jest/pull/7724))
1617
- `[jest-cli]` Do not execute any `globalSetup` or `globalTeardown` if there are no tests to execute ([#7745](https://github.com/facebook/jest/pull/7745))

e2e/__tests__/moduleNameMapper.test.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @flow
88
*/
99

10-
import runJest from '../runJest';
10+
import runJest, {json as runWithJson} from '../runJest';
1111
import {extractSummary} from '../Utils';
1212
import {wrap} from 'jest-snapshot-serializer-raw';
1313

@@ -28,3 +28,9 @@ test('moduleNameMapper correct configuration', () => {
2828
expect(status).toBe(0);
2929
expect(wrap(rest)).toMatchSnapshot();
3030
});
31+
32+
test('moduleNameMapper with mocking', () => {
33+
const {json} = runWithJson('module-name-mapper-mock');
34+
expect(json.numTotalTests).toBe(2);
35+
expect(json.success).toBe(true);
36+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
const {Track} = require('../../../src/storage/track/Track');
9+
jest.mock('@@storage/track/Track');
10+
11+
test('relative import', () => {
12+
const track = new Track();
13+
expect(track.someRandomFunction).not.toBeCalled();
14+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
const {Track} = require('@@storage/track/Track');
9+
jest.mock('@@storage/track/Track');
10+
11+
test('through moduleNameMapper', () => {
12+
const track = new Track();
13+
expect(track.someRandomFunction).not.toBeCalled();
14+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"jest": {
3+
"moduleNameMapper": {
4+
"^@@storage/(.*)$": "<rootDir>/src/storage/$1"
5+
},
6+
"testEnvironment": "node"
7+
}
8+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
module.exports.Track = class Track {
9+
someRandomFunction() {
10+
return 42;
11+
}
12+
};

packages/jest-resolve/src/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ class Resolver {
252252
if (mock) {
253253
return mock;
254254
} else {
255-
const moduleName = this._resolveStubModuleName(from, name);
255+
const moduleName = this.resolveStubModuleName(from, name);
256256
if (moduleName) {
257257
return this.getModule(moduleName) || moduleName;
258258
}
@@ -341,7 +341,7 @@ class Resolver {
341341
);
342342
}
343343

344-
_resolveStubModuleName(from: Path, moduleName: string): ?Path {
344+
resolveStubModuleName(from: Path, moduleName: string): ?Path {
345345
const dirname = path.dirname(from);
346346
const paths = this._options.modulePaths;
347347
const extensions = this._options.extensions.slice();

packages/jest-runtime/src/__tests__/runtime_gen_mock_from_module.test.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010

1111
let createRuntime;
1212

13+
const moduleNameMapper = {
14+
'module/name/(.*)': '<rootDir>/mapped_module_$1.js',
15+
};
16+
1317
describe('Runtime', () => {
1418
beforeEach(() => {
1519
createRuntime = require('createRuntime');
@@ -35,6 +39,16 @@ describe('Runtime', () => {
3539
expect(mock.fn()).toBe(undefined);
3640
expect(module.getModuleStateValue()).toBe(origModuleStateValue);
3741
}));
42+
43+
it('resolves mapped modules correctly', () =>
44+
createRuntime(__filename, {moduleNameMapper}).then(runtime => {
45+
const root = runtime.requireModule(runtime.__mockRootPath);
46+
const mockModule = root.jest.genMockFromModule(
47+
'module/name/genMockFromModule',
48+
);
49+
50+
expect(mockModule.test.mock).toBeTruthy();
51+
}));
3852
});
3953

4054
it('creates mock objects in the right environment', () =>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
module.exports = {
9+
test: () => '42',
10+
};

packages/jest-runtime/src/index.js

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -389,37 +389,43 @@ class Runtime {
389389
return (mockRegistry[moduleID] = this._mockFactories[moduleID]());
390390
}
391391

392-
let manualMock = this._resolver.getMockModule(from, moduleName);
392+
const manualMockOrStub = this._resolver.getMockModule(from, moduleName);
393393
let modulePath;
394-
if (manualMock) {
395-
modulePath = this._resolveModule(from, manualMock);
394+
if (manualMockOrStub) {
395+
modulePath = this._resolveModule(from, manualMockOrStub);
396396
} else {
397397
modulePath = this._resolveModule(from, moduleName);
398398
}
399-
// If the actual module file has a __mocks__ dir sitting immediately next
400-
// to it, look to see if there is a manual mock for this file.
401-
//
402-
// subDir1/my_module.js
403-
// subDir1/__mocks__/my_module.js
404-
// subDir2/my_module.js
405-
// subDir2/__mocks__/my_module.js
406-
//
407-
// Where some other module does a relative require into each of the
408-
// respective subDir{1,2} directories and expects a manual mock
409-
// corresponding to that particular my_module.js file.
410-
const moduleDir = path.dirname(modulePath);
411-
const moduleFileName = path.basename(modulePath);
412-
const potentialManualMock = path.join(
413-
moduleDir,
414-
'__mocks__',
415-
moduleFileName,
416-
);
417-
if (fs.existsSync(potentialManualMock)) {
418-
manualMock = true;
419-
modulePath = potentialManualMock;
420-
}
421399

422-
if (manualMock) {
400+
let isManualMock =
401+
manualMockOrStub &&
402+
!this._resolver.resolveStubModuleName(from, moduleName);
403+
if (!isManualMock) {
404+
// If the actual module file has a __mocks__ dir sitting immediately next
405+
// to it, look to see if there is a manual mock for this file.
406+
//
407+
// subDir1/my_module.js
408+
// subDir1/__mocks__/my_module.js
409+
// subDir2/my_module.js
410+
// subDir2/__mocks__/my_module.js
411+
//
412+
// Where some other module does a relative require into each of the
413+
// respective subDir{1,2} directories and expects a manual mock
414+
// corresponding to that particular my_module.js file.
415+
416+
const moduleDir = path.dirname(modulePath);
417+
const moduleFileName = path.basename(modulePath);
418+
const potentialManualMock = path.join(
419+
moduleDir,
420+
'__mocks__',
421+
moduleFileName,
422+
);
423+
if (fs.existsSync(potentialManualMock)) {
424+
isManualMock = true;
425+
modulePath = potentialManualMock;
426+
}
427+
}
428+
if (isManualMock) {
423429
const localModule: Module = {
424430
children: [],
425431
exports: {},
@@ -730,8 +736,9 @@ class Runtime {
730736
}
731737

732738
_generateMock(from: Path, moduleName: string) {
733-
const modulePath = this._resolveModule(from, moduleName);
734-
739+
const modulePath =
740+
this._resolver.resolveStubModuleName(from, moduleName) ||
741+
this._resolveModule(from, moduleName);
735742
if (!(modulePath in this._mockMetaDataCache)) {
736743
// This allows us to handle circular dependencies while generating an
737744
// automock

0 commit comments

Comments
 (0)