diff --git a/CHANGELOG.md b/CHANGELOG.md index 34dd103e6227..1a386a795440 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,7 @@ - `[jest-reporters]` Make node-notifier an optional dependency ([#8918](https://github.com/facebook/jest/pull/8918)) - `[jest-reporters]` Make all arguments to methods on `BaseReporter` optional ([#9159](https://github.com/facebook/jest/pull/9159)) - `[jest-resolve]`: Set MODULE_NOT_FOUND as error code when module is not resolved from paths ([#8487](https://github.com/facebook/jest/pull/8487)) +- `[jest-resolve-dependencies]` Handle dynamic dependencies correctly even when using module maps ([#9303](https://github.com/facebook/jest/pull/9303)) - `[jest-snapshot]` Remove only the added newlines in multiline snapshots ([#8859](https://github.com/facebook/jest/pull/8859)) - `[jest-snapshot]` Distinguish empty string from external snapshot not written ([#8880](https://github.com/facebook/jest/pull/8880)) - `[jest-snapshot]` [**BREAKING**] Distinguish empty string from internal snapshot not written ([#8898](https://github.com/facebook/jest/pull/8898)) diff --git a/e2e/__tests__/dynamicRequireDependencies.ts b/e2e/__tests__/dynamicRequireDependencies.ts new file mode 100644 index 000000000000..3f6c96a9731a --- /dev/null +++ b/e2e/__tests__/dynamicRequireDependencies.ts @@ -0,0 +1,17 @@ +/** + * 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. + */ + +import * as path from 'path'; +import {json as runWithJson} from '../runJest'; + +const dir = path.resolve(__dirname, '../dynamic-require-dependencies'); + +test('successfully runs tests with dynamic dependencies', () => { + const {json} = runWithJson(dir, ['--findRelatedTests', 'dynamicRequire.js']); + expect(json.success).toBe(true); + expect(json.numTotalTests).toBe(2); +}); diff --git a/e2e/dynamic-require-dependencies/__tests__/dynamicRequire.test.js b/e2e/dynamic-require-dependencies/__tests__/dynamicRequire.test.js new file mode 100644 index 000000000000..dc9599defc4a --- /dev/null +++ b/e2e/dynamic-require-dependencies/__tests__/dynamicRequire.test.js @@ -0,0 +1,16 @@ +/** + * 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. + */ + +test('loading a file with a dynamic local require should work', () => { + const {withStandardResolution} = require('../dynamicRequire'); + expect(withStandardResolution()).toBe(1); +}); + +test('loading a file with a dynamic require and custom resolve should work', () => { + const {withCustomResolution} = require('../dynamicRequire'); + expect(withCustomResolution()).toBe(1); +}); diff --git a/e2e/dynamic-require-dependencies/dynamicRequire.js b/e2e/dynamic-require-dependencies/dynamicRequire.js new file mode 100644 index 000000000000..c154ef61656d --- /dev/null +++ b/e2e/dynamic-require-dependencies/dynamicRequire.js @@ -0,0 +1,13 @@ +/** + * 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. + */ + +const dynamicModuleName = 'source'; + +module.exports.withStandardResolution = () => + require(`./${dynamicModuleName}.js`); +module.exports.withCustomResolution = () => + require(`$asdf/${dynamicModuleName}.js`); diff --git a/e2e/dynamic-require-dependencies/package.json b/e2e/dynamic-require-dependencies/package.json new file mode 100644 index 000000000000..956feac1e475 --- /dev/null +++ b/e2e/dynamic-require-dependencies/package.json @@ -0,0 +1,7 @@ +{ + "jest": { + "moduleNameMapper": { + "^\\$asdf/(.*)$": "/$1" + } + } +} diff --git a/e2e/dynamic-require-dependencies/source.js b/e2e/dynamic-require-dependencies/source.js new file mode 100644 index 000000000000..61193c4c1d16 --- /dev/null +++ b/e2e/dynamic-require-dependencies/source.js @@ -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 = 1; diff --git a/packages/jest-resolve-dependencies/src/__tests__/dependency_resolver.test.ts b/packages/jest-resolve-dependencies/src/__tests__/dependency_resolver.test.ts index 7efd09980a9e..d0edebc0f83f 100644 --- a/packages/jest-resolve-dependencies/src/__tests__/dependency_resolver.test.ts +++ b/packages/jest-resolve-dependencies/src/__tests__/dependency_resolver.test.ts @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +import Resolver = require('jest-resolve'); import {tmpdir} from 'os'; import * as path from 'path'; import {Config} from '@jest/types'; @@ -15,6 +16,7 @@ import DependencyResolver from '../index'; const maxWorkers = 1; let dependencyResolver: DependencyResolver; +let runtimeContextResolver: Resolver; let Runtime; let config: Config.ProjectConfig; const cases: Record = { @@ -29,11 +31,13 @@ beforeEach(() => { config = makeProjectConfig({ cacheDirectory: path.resolve(tmpdir(), 'jest-resolve-dependencies-test'), moduleDirectories: ['node_modules'], + moduleNameMapper: [['^\\$asdf/(.*)$', '/$1']], rootDir: '.', roots: ['./packages/jest-resolve-dependencies'], }); return Runtime.createContext(config, {maxWorkers, watchman: false}).then( (runtimeContext: any) => { + runtimeContextResolver = runtimeContext.resolver; dependencyResolver = new DependencyResolver( runtimeContext.resolver, runtimeContext.hasteFS, @@ -106,3 +110,18 @@ test('resolves inverse dependencies from available snapshot', () => { ]), ); }); + +test('resolves dependencies correctly when dependency resolution fails', () => { + jest.spyOn(runtimeContextResolver, 'resolveModule').mockImplementation(() => { + throw new Error('resolveModule has failed'); + }); + jest.spyOn(runtimeContextResolver, 'getMockModule').mockImplementation(() => { + throw new Error('getMockModule has failed'); + }); + + const resolved = dependencyResolver.resolve( + path.resolve(__dirname, '__fixtures__', 'file.test.js'), + ); + + expect(resolved).toEqual([]); +}); diff --git a/packages/jest-resolve-dependencies/src/index.ts b/packages/jest-resolve-dependencies/src/index.ts index 1a6345e565c9..6f2d377b9f30 100644 --- a/packages/jest-resolve-dependencies/src/index.ts +++ b/packages/jest-resolve-dependencies/src/index.ts @@ -58,8 +58,12 @@ class DependencyResolver { dependency, options, ); - } catch (e) { - resolvedDependency = this._resolver.getMockModule(file, dependency); + } catch { + try { + resolvedDependency = this._resolver.getMockModule(file, dependency); + } catch { + // leave resolvedDependency as undefined if nothing can be found + } } if (resolvedDependency) {