Skip to content

Commit

Permalink
feat(runtime): support require.resolve with options.paths
Browse files Browse the repository at this point in the history
  • Loading branch information
jeysal committed Jun 16, 2018
1 parent 17206c9 commit 806fb97
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 2 deletions.
36 changes: 36 additions & 0 deletions e2e/__tests__/resolve-with-paths.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. 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.
*
* @flow
*/
'use strict';

const {resolve} = require('path');

const runJest = require('../runJest');
const {writeFiles, cleanup} = require('../Utils');

const workdirNodeModules = resolve(
__dirname,
'..',
'resolve-with-paths',
'node_modules',
);

beforeAll(() => {
writeFiles(resolve(workdirNodeModules, 'mod'), {
'index.js': 'module.exports = 42;',
});
});

afterAll(() => {
cleanup(workdirNodeModules);
});

test('require.resolve with paths', () => {
const {status} = runJest('resolve-with-paths');
expect(status).toBe(0);
});
37 changes: 37 additions & 0 deletions e2e/resolve-with-paths/__tests__/resolve-with-paths.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. 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.
*/
'use strict';

import {resolve} from 'path';

test('finds a module relative to one of the given paths', () => {
expect(require.resolve('./mod.js', {paths: ['../dir']})).toEqual(
resolve(__dirname, '..', 'dir', 'mod.js')
);
});

test('finds a module without a leading "./" relative to one of the given paths', () => {
expect(require.resolve('mod.js', {paths: ['../dir']})).toEqual(
resolve(__dirname, '..', 'dir', 'mod.js')
);
});

test('finds a node_module above one of the given paths', () => {
expect(require.resolve('mod', {paths: ['../dir']})).toEqual(
resolve(__dirname, '..', 'node_modules', 'mod', 'index.js')
);
});

test('finds a native node module when paths are given', () => {
expect(require.resolve('fs', {paths: ['../dir']})).toEqual('fs');
});

test('throws an error if the module cannot be found from given paths', () => {
expect(() => require.resolve('./mod.js', {paths: ['..']})).toThrowError(
"Cannot resolve module './mod.js' from paths ['..'] from "
);
});
8 changes: 8 additions & 0 deletions e2e/resolve-with-paths/dir/mod.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. 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 = 'mod';
5 changes: 5 additions & 0 deletions e2e/resolve-with-paths/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"jest": {
"testEnvironment": "node"
}
}
38 changes: 36 additions & 2 deletions packages/jest-runtime/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,40 @@ class Runtime {
return to ? this._resolver.resolveModule(from, to) : from;
}

_requireResolve(
from: Path,
moduleName?: string,
{paths}: {paths?: Path[]} = {},
) {
if (moduleName == null) {
throw new Error(
'The first argument to require.resolve must be a string. Received null or undefined.',
);
}

if (paths) {
for (const p of paths) {
const absolutePath = path.resolve(from, '..', p);
const module = this._resolver._resolveModuleFromDirIfExists(
absolutePath,
moduleName,
// required to also resolve files without leading './' directly in the path
{paths: [absolutePath]},
);
if (module) {
return module;
}
}
throw new Error(
`Cannot resolve module '${moduleName}' from paths ['${paths.join(
"', '",
)}'] from ${from}`,
);
}

return this._resolveModule(from, moduleName);
}

_execModule(
localModule: Module,
options: ?InternalModuleOptions,
Expand Down Expand Up @@ -721,8 +755,8 @@ class Runtime {
moduleRequire.extensions = Object.create(null);
moduleRequire.requireActual = this.requireModule.bind(this, from.filename);
moduleRequire.requireMock = this.requireMock.bind(this, from.filename);
moduleRequire.resolve = moduleName =>
this._resolveModule(from.filename, moduleName);
moduleRequire.resolve = (moduleName, options) =>
this._requireResolve(from.filename, moduleName, options);
Object.defineProperty(
moduleRequire,
'main',
Expand Down

0 comments on commit 806fb97

Please sign in to comment.