Skip to content

Commit dd859ac

Browse files
authored
Ensure test modules can require.resolve absolute paths (#11943)
1 parent 1547740 commit dd859ac

3 files changed

Lines changed: 79 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
### Fixes
66

7+
- `[jest-runtime]` Ensure absolute paths can be resolved within test modules ([11943](https://github.com/facebook/jest/pull/11943))
8+
79
### Chore & Maintenance
810

911
### Performance

packages/jest-runtime/src/__tests__/runtime_require_resolve.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
*
77
*/
88

9+
import os from 'os';
10+
import path from 'path';
11+
import {promises as fs} from 'graceful-fs';
912
import type {Config} from '@jest/types';
1013
import type Runtime from '..';
1114
import {createOutsideJestVmPath} from '../helpers';
@@ -15,6 +18,9 @@ let createRuntime: (
1518
config?: Config.InitialOptions,
1619
) => Promise<Runtime & {__mockRootPath: string}>;
1720

21+
const getTmpDir = async () =>
22+
await fs.mkdtemp(path.join(os.tmpdir(), 'jest-resolve-test-'));
23+
1824
describe('Runtime require.resolve', () => {
1925
beforeEach(() => {
2026
createRuntime = require('createRuntime');
@@ -29,6 +35,47 @@ describe('Runtime require.resolve', () => {
2935
expect(resolved).toEqual(require.resolve('./test_root/resolve_self.js'));
3036
});
3137

38+
it('resolves an absolute module path', async () => {
39+
const absoluteFilePath = path.join(await getTmpDir(), 'test.js');
40+
await fs.writeFile(
41+
absoluteFilePath,
42+
'module.exports = require.resolve(__filename);',
43+
'utf-8',
44+
);
45+
46+
const runtime = await createRuntime(__filename);
47+
const resolved = runtime.requireModule(
48+
runtime.__mockRootPath,
49+
absoluteFilePath,
50+
);
51+
52+
expect(resolved).toEqual(require.resolve(absoluteFilePath));
53+
});
54+
55+
it('required modules can resolve absolute module paths with no paths entries passed', async () => {
56+
const tmpdir = await getTmpDir();
57+
const entrypoint = path.join(tmpdir, 'test.js');
58+
const target = path.join(tmpdir, 'target.js');
59+
60+
// we want to test the require.resolve implementation within a
61+
// runtime-required module, so we need to create a module that then resolves
62+
// an absolute path, so we need two files: the entrypoint, and an absolute
63+
// target to require.
64+
await fs.writeFile(
65+
entrypoint,
66+
`module.exports = require.resolve(${JSON.stringify(
67+
target,
68+
)}, {paths: []});`,
69+
'utf-8',
70+
);
71+
72+
await fs.writeFile(target, `module.exports = {}`, 'utf-8');
73+
74+
const runtime = await createRuntime(__filename);
75+
const resolved = runtime.requireModule(runtime.__mockRootPath, entrypoint);
76+
expect(resolved).toEqual(require.resolve(target, {paths: []}));
77+
});
78+
3279
it('resolves a module path with moduleNameMapper', async () => {
3380
const runtime = await createRuntime(__filename, {
3481
moduleNameMapper: {

packages/jest-runtime/src/index.ts

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,28 +1242,39 @@ export default class Runtime {
12421242
);
12431243
}
12441244

1245-
const {paths} = options;
1246-
1247-
if (paths) {
1248-
for (const p of paths) {
1249-
const absolutePath = path.resolve(from, '..', p);
1250-
const module = this._resolver.resolveModuleFromDirIfExists(
1251-
absolutePath,
1252-
moduleName,
1253-
// required to also resolve files without leading './' directly in the path
1254-
{conditions: this.cjsConditions, paths: [absolutePath]},
1255-
);
1256-
if (module) {
1257-
return module;
1258-
}
1245+
if (path.isAbsolute(moduleName)) {
1246+
const module = this._resolver.resolveModuleFromDirIfExists(
1247+
moduleName,
1248+
moduleName,
1249+
{conditions: this.cjsConditions, paths: []},
1250+
);
1251+
if (module) {
1252+
return module;
12591253
}
1254+
} else {
1255+
const {paths} = options;
1256+
if (paths) {
1257+
for (const p of paths) {
1258+
const absolutePath = path.resolve(from, '..', p);
1259+
const module = this._resolver.resolveModuleFromDirIfExists(
1260+
absolutePath,
1261+
moduleName,
1262+
// required to also resolve files without leading './' directly in the path
1263+
{conditions: this.cjsConditions, paths: [absolutePath]},
1264+
);
1265+
if (module) {
1266+
return module;
1267+
}
1268+
}
12601269

1261-
throw new Resolver.ModuleNotFoundError(
1262-
`Cannot resolve module '${moduleName}' from paths ['${paths.join(
1263-
"', '",
1264-
)}'] from ${from}`,
1265-
);
1270+
throw new Resolver.ModuleNotFoundError(
1271+
`Cannot resolve module '${moduleName}' from paths ['${paths.join(
1272+
"', '",
1273+
)}'] from ${from}`,
1274+
);
1275+
}
12661276
}
1277+
12671278
try {
12681279
return this._resolveModule(from, moduleName, {
12691280
conditions: this.cjsConditions,

0 commit comments

Comments
 (0)