Skip to content

Commit 806fb97

Browse files
committed
feat(runtime): support require.resolve with options.paths
1 parent 17206c9 commit 806fb97

File tree

5 files changed

+122
-2
lines changed

5 files changed

+122
-2
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Copyright (c) 2014-present, Facebook, Inc. 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+
* @flow
8+
*/
9+
'use strict';
10+
11+
const {resolve} = require('path');
12+
13+
const runJest = require('../runJest');
14+
const {writeFiles, cleanup} = require('../Utils');
15+
16+
const workdirNodeModules = resolve(
17+
__dirname,
18+
'..',
19+
'resolve-with-paths',
20+
'node_modules',
21+
);
22+
23+
beforeAll(() => {
24+
writeFiles(resolve(workdirNodeModules, 'mod'), {
25+
'index.js': 'module.exports = 42;',
26+
});
27+
});
28+
29+
afterAll(() => {
30+
cleanup(workdirNodeModules);
31+
});
32+
33+
test('require.resolve with paths', () => {
34+
const {status} = runJest('resolve-with-paths');
35+
expect(status).toBe(0);
36+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Copyright (c) 2014-present, Facebook, Inc. 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+
'use strict';
8+
9+
import {resolve} from 'path';
10+
11+
test('finds a module relative to one of the given paths', () => {
12+
expect(require.resolve('./mod.js', {paths: ['../dir']})).toEqual(
13+
resolve(__dirname, '..', 'dir', 'mod.js')
14+
);
15+
});
16+
17+
test('finds a module without a leading "./" relative to one of the given paths', () => {
18+
expect(require.resolve('mod.js', {paths: ['../dir']})).toEqual(
19+
resolve(__dirname, '..', 'dir', 'mod.js')
20+
);
21+
});
22+
23+
test('finds a node_module above one of the given paths', () => {
24+
expect(require.resolve('mod', {paths: ['../dir']})).toEqual(
25+
resolve(__dirname, '..', 'node_modules', 'mod', 'index.js')
26+
);
27+
});
28+
29+
test('finds a native node module when paths are given', () => {
30+
expect(require.resolve('fs', {paths: ['../dir']})).toEqual('fs');
31+
});
32+
33+
test('throws an error if the module cannot be found from given paths', () => {
34+
expect(() => require.resolve('./mod.js', {paths: ['..']})).toThrowError(
35+
"Cannot resolve module './mod.js' from paths ['..'] from "
36+
);
37+
});

e2e/resolve-with-paths/dir/mod.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* Copyright (c) 2014-present, Facebook, Inc. 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 = 'mod';
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"jest": {
3+
"testEnvironment": "node"
4+
}
5+
}

packages/jest-runtime/src/index.js

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,40 @@ class Runtime {
495495
return to ? this._resolver.resolveModule(from, to) : from;
496496
}
497497

498+
_requireResolve(
499+
from: Path,
500+
moduleName?: string,
501+
{paths}: {paths?: Path[]} = {},
502+
) {
503+
if (moduleName == null) {
504+
throw new Error(
505+
'The first argument to require.resolve must be a string. Received null or undefined.',
506+
);
507+
}
508+
509+
if (paths) {
510+
for (const p of paths) {
511+
const absolutePath = path.resolve(from, '..', p);
512+
const module = this._resolver._resolveModuleFromDirIfExists(
513+
absolutePath,
514+
moduleName,
515+
// required to also resolve files without leading './' directly in the path
516+
{paths: [absolutePath]},
517+
);
518+
if (module) {
519+
return module;
520+
}
521+
}
522+
throw new Error(
523+
`Cannot resolve module '${moduleName}' from paths ['${paths.join(
524+
"', '",
525+
)}'] from ${from}`,
526+
);
527+
}
528+
529+
return this._resolveModule(from, moduleName);
530+
}
531+
498532
_execModule(
499533
localModule: Module,
500534
options: ?InternalModuleOptions,
@@ -721,8 +755,8 @@ class Runtime {
721755
moduleRequire.extensions = Object.create(null);
722756
moduleRequire.requireActual = this.requireModule.bind(this, from.filename);
723757
moduleRequire.requireMock = this.requireMock.bind(this, from.filename);
724-
moduleRequire.resolve = moduleName =>
725-
this._resolveModule(from.filename, moduleName);
758+
moduleRequire.resolve = (moduleName, options) =>
759+
this._requireResolve(from.filename, moduleName, options);
726760
Object.defineProperty(
727761
moduleRequire,
728762
'main',

0 commit comments

Comments
 (0)