Skip to content

Commit

Permalink
Ensure mocks get resolved too (#7687)
Browse files Browse the repository at this point in the history
  • Loading branch information
mjesun committed Jan 24, 2019
1 parent 1d1c3f9 commit 28971c5
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
- `[babel-plugin-jest-hoist]` Ignore TS type annotations when looking for out-of-scope references ([#7641](https://github.com/facebook/jest/pull/7641))
- `[jest-config]` Add name to project if one does not exist to pick correct resolver ([#5862](https://github.com/facebook/jest/pull/5862))
- `[jest-runtime]` Pass `watchPathIgnorePatterns` to Haste instance ([#7585](https://github.com/facebook/jest/pull/7585))
- `[jest-runtime]` Resolve mock files via Haste when using `require.resolve` ([#7687](https://github.com/facebook/jest/pull/7585))

### Chore & Maintenance

Expand Down
2 changes: 1 addition & 1 deletion e2e/__tests__/__snapshots__/moduleNameMapper.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ FAIL __tests__/index.js
12 | module.exports = () => 'test';
13 |
at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:433:17)
at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:435:17)
at Object.require (index.js:10:1)
`;
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ FAIL __tests__/test.js
| ^
4 |
at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:200:17)
at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:202:17)
at Object.require (index.js:3:18)
`;
10 changes: 10 additions & 0 deletions e2e/resolve/Test5.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Test5
*/

module.exports = {key: 'real'};
8 changes: 8 additions & 0 deletions e2e/resolve/__mocks__/Test5.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

module.exports = {key: 'mock'};
8 changes: 8 additions & 0 deletions e2e/resolve/__mocks__/Test6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

module.exports = {key: 'mock'};
31 changes: 31 additions & 0 deletions e2e/resolve/__tests__/resolve.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,34 @@ test('should preserve identity for symlinks', () => {
require('jest-resolve')
);
});

test('should require resolve haste files correctly', () => {
// We unmock Test5 (they should already be, but to be sure).
jest.unmock('Test5');

// Test5 is a standard module, that has a mock (but it is unmocked here).
expect(require.resolve('Test5')).toBe(require.resolve('../Test5'));

expect(require('Test5').key).toBe('real');

// Test6 only exits as a mock; so even when unmocked, we resolve to the mock.
expect(require.resolve('Test6')).toBe(require.resolve('../__mocks__/Test6'));

expect(require('Test6').key).toBe('mock');
});

test('should require resolve haste mocks correctly', () => {
// Now we mock Test5 and Test6.
jest.mock('Test5');
jest.mock('Test6');

// The resolution still points to the real one, but requires the mock.
expect(require.resolve('Test5')).toBe(require.resolve('../Test5'));

expect(require('Test5').key).toBe('mock');

// And Test6 points to the mock, because Test6 does not exist as a module.
expect(require.resolve('Test6')).toBe(require.resolve('../__mocks__/Test6'));

expect(require('Test6').key).toBe('mock');
});
20 changes: 20 additions & 0 deletions e2e/resolve/hasteImpl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow
*/

const path = require('path');

module.exports = {
getHasteName(filePath) {
const name = path.parse(filePath).name;
const isMock = filePath.indexOf('__mocks__') !== -1;

// Mocks are automatically parsed by Jest already.
return name.startsWith('Test') && !isMock ? name : null;
},
};
3 changes: 2 additions & 1 deletion e2e/resolve/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"platforms": [
"native"
],
"defaultPlatform": "android"
"defaultPlatform": "android",
"hasteImplModulePath": "<rootDir>/hasteImpl.js"
},
"testEnvironment": "node",
"moduleNameMapper": {
Expand Down
30 changes: 16 additions & 14 deletions packages/jest-resolve/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ class Resolver {
const key = dirname + path.delimiter + moduleName;
const defaultPlatform = this._options.defaultPlatform;
const extensions = this._options.extensions.slice();
let module;

if (this._supportsNativePlatform) {
extensions.unshift(
...this._options.extensions.map(ext => '.' + NATIVE_PLATFORM + ext),
Expand All @@ -133,24 +135,24 @@ class Resolver {
);
}

// 0. If we have already resolved this module for this directory name,
// return a value from the cache.
// 1. If we have already resolved this module for this directory name,
// return a value from the cache.
if (this._moduleNameCache[key]) {
return this._moduleNameCache[key];
}

// 1. Check if the module is a haste module.
let module = this.getModule(moduleName);
// 2. Check if the module is a haste module.
module = this.getModule(moduleName);
if (module) {
return (this._moduleNameCache[key] = module);
}

// 2. Check if the module is a node module and resolve it based on
// the node module resolution algorithm.
// If skipNodeResolution is given we ignore all modules that look like
// node modules (ie. are not relative requires). This enables us to speed
// up resolution when we build a dependency graph because we don't have
// to look at modules that may not exist and aren't mocked.
// 3. Check if the module is a node module and resolve it based on
// the node module resolution algorithm. If skipNodeResolution is given we
// ignore all modules that look like node modules (ie. are not relative
// requires). This enables us to speed up resolution when we build a
// dependency graph because we don't have to look at modules that may not
// exist and aren't mocked.
const skipResolution =
options && options.skipNodeResolution && !moduleName.includes(path.sep);

Expand All @@ -173,7 +175,7 @@ class Resolver {
}
}

// 3. Resolve "haste packages" which are `package.json` files outside of
// 4. Resolve "haste packages" which are `package.json` files outside of
// `node_modules` folders anywhere in the file system.
const parts = moduleName.split('/');
const hastePackage = this.getPackage(parts.shift());
Expand Down Expand Up @@ -206,9 +208,9 @@ class Resolver {
);
if (module) return module;

// (4.) Throw an error if the module could not be found. `resolve.sync`
// only produces an error based on the dirname but we have the actual
// current module name available.
// 5. Throw an error if the module could not be found. `resolve.sync` only
// produces an error based on the dirname but we have the actual current
// module name available.
const relativePath = path.relative(dirname, from);
const err = new Error(
`Cannot find module '${moduleName}' from '${relativePath || '.'}'`,
Expand Down
11 changes: 10 additions & 1 deletion packages/jest-runtime/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -589,8 +589,17 @@ class Runtime {
)}'] from ${from}`,
);
}
try {
return this._resolveModule(from, moduleName);
} catch (err) {
const module = this._resolver.getMockModule(from, moduleName);

return this._resolveModule(from, moduleName);
if (module) {
return module;
} else {
throw err;
}
}
}

_requireResolvePaths(from: Path, moduleName?: string) {
Expand Down

0 comments on commit 28971c5

Please sign in to comment.