From b2561c2225cc36fe0f415321972aa7f887895b34 Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Mon, 16 Mar 2020 23:13:22 -0300 Subject: [PATCH 01/26] added require stack error, missing yarn pnp error surfacing and printing require stack relative to rootdir instead of absolute --- .vscode/launch.json | 5 +-- .vscode/settings.json | 2 +- e2e/resolve/Test7.js | 12 +++++++ e2e/resolve/__tests__/resolve.test.js | 43 +++++++++++++++++++++---- e2e/resolve/requiresUnexistingModule.js | 12 +++++++ packages/jest-runtime/src/helpers.ts | 6 ++++ packages/jest-runtime/src/index.ts | 26 +++++++++++++-- 7 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 e2e/resolve/Test7.js create mode 100644 e2e/resolve/requiresUnexistingModule.js diff --git a/.vscode/launch.json b/.vscode/launch.json index f4106b4f6605..f3d8aff8c99e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,8 +9,9 @@ "request": "launch", "name": "Debug Jest with current test file", "program": "${workspaceFolder}/packages/jest-cli/bin/jest.js", - "args": ["--runInBand", "${file}"], - "runtimeArgs": ["-r", "flow-remove-types/register"] + "cwd": "${workspaceFolder}/e2e/resolve", + "sourceMaps": true, + "outFiles": ["${workspaceFolder}/packages/**/build/**"] } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 0478de9c2561..ff28aae6af54 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,7 +3,7 @@ "files.exclude": { "**/.git": true, "**/node_modules": true, - "**/build": true + "**/build": false }, "javascript.validate.enable": false, "jest.pathToJest": "yarn jest --", diff --git a/e2e/resolve/Test7.js b/e2e/resolve/Test7.js new file mode 100644 index 000000000000..1df1689b6a56 --- /dev/null +++ b/e2e/resolve/Test7.js @@ -0,0 +1,12 @@ +/** + * 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. + * + */ + +require('./test1'); +const requiresUnexistingModule = require('./requiresUnexistingModule'); + +module.exports = {module: requiresUnexistingModule}; diff --git a/e2e/resolve/__tests__/resolve.test.js b/e2e/resolve/__tests__/resolve.test.js index 56f99f7ee945..9b37c5cd7a57 100644 --- a/e2e/resolve/__tests__/resolve.test.js +++ b/e2e/resolve/__tests__/resolve.test.js @@ -6,6 +6,8 @@ */ 'use strict'; +const path = require('path'); + let platform; function testRequire(filename) { @@ -99,11 +101,40 @@ test('should require resolve haste mocks correctly', () => { expect(require('Test6').key).toBe('mock'); }); +test('should throw module not found error if the module has dependencies that cannot be found', () => { + try { + require('Test7'); + throw new Error('Requiring Test7 should have thrown an error'); + } catch (error) { + expect(error.code).toBe('MODULE_NOT_FOUND'); + + expect(error.message).toMatchInlineSnapshot(` + "Cannot find module 'nope' from 'requiresUnexistingModule.js' + + Require stack: + jest/e2e/resolve/e2e/resolve/requiresUnexistingModule.js + jest/e2e/resolve/e2e/resolve/Test7.js + jest/e2e/resolve/e2e/resolve/__tests__/resolve.test.js + + + However, Jest was able to find: + './requiresUnexistingModule.js' + + You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node']. + + See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring" + `); + } +}); + test('should throw module not found error if the module cannot be found', () => { - expect(() => require('Test7')).toThrow( - expect.objectContaining({ - code: 'MODULE_NOT_FOUND', - message: "Cannot find module 'Test7' from 'resolve.test.js'", - }) - ); + try { + require('Test8'); + throw new Error('Requiring Test8 should have thrown an error'); + } catch (error) { + expect(error.code).toBe('MODULE_NOT_FOUND'); + expect(error.message.split('\n')[0]).toBe( + "Cannot find module 'Test8' from 'resolve.test.js'" + ); + } }); diff --git a/e2e/resolve/requiresUnexistingModule.js b/e2e/resolve/requiresUnexistingModule.js new file mode 100644 index 000000000000..9b964750bede --- /dev/null +++ b/e2e/resolve/requiresUnexistingModule.js @@ -0,0 +1,12 @@ +/** + * 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. + * + */ + +require('./test2'); +const unexistedModule = require('nope'); + +module.exports = {module: unexistedModule}; diff --git a/packages/jest-runtime/src/helpers.ts b/packages/jest-runtime/src/helpers.ts index 885d508e2e20..02f340a8fa12 100644 --- a/packages/jest-runtime/src/helpers.ts +++ b/packages/jest-runtime/src/helpers.ts @@ -53,3 +53,9 @@ export const findSiblingsWithFileExtension = ( return ''; }; + +export const printRequireStack = (requireStack: Array): string => ` + +Require stack: + ${requireStack.join('\n ')} +`; diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index c96b2912e5e6..1757c61225d5 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -34,7 +34,7 @@ import {CoverageInstrumenter, V8Coverage} from 'collect-v8-coverage'; import * as fs from 'graceful-fs'; import {run as cliRun} from './cli'; import {options as cliOptions} from './cli/args'; -import {findSiblingsWithFileExtension} from './helpers'; +import {findSiblingsWithFileExtension, printRequireStack} from './helpers'; import {Context as JestContext} from './types'; import jestMock = require('jest-mock'); import HasteMap = require('jest-haste-map'); @@ -122,6 +122,7 @@ class Runtime { private _transitiveShouldMock: BooleanObject; private _unmockList: RegExp | undefined; private _virtualMocks: BooleanObject; + private _requireStack: Array; constructor( config: Config.ProjectConfig, @@ -158,6 +159,7 @@ class Runtime { this._sourceMapRegistry = Object.create(null); this._fileTransforms = new Map(); this._virtualMocks = Object.create(null); + this._requireStack = []; this._mockMetaDataCache = Object.create(null); this._shouldMockModuleCache = Object.create(null); @@ -504,13 +506,30 @@ class Runtime { requireModuleOrMock(from: Config.Path, moduleName: string): unknown { try { + let result; + + if (this._requireStack[this._requireStack.length - 1] !== from) { + this._requireStack.push(from); + } + if (this._shouldMock(from, moduleName)) { - return this.requireMock(from, moduleName); + result = this.requireMock(from, moduleName); } else { - return this.requireModule(from, moduleName); + result = this.requireModule(from, moduleName); } + + this._requireStack.pop(); + return result; } catch (e) { if (e.code === 'MODULE_NOT_FOUND') { + if (!e.requireStack) { + e.requireStack = [...this._requireStack].reverse(); + + if (e.requireStack.length > 1) { + e.message += printRequireStack(e.requireStack); + } + } + const appendedMessage = findSiblingsWithFileExtension( this._config.moduleFileExtensions, from, @@ -521,6 +540,7 @@ class Runtime { e.message += appendedMessage; } } + this._requireStack.pop(); throw e; } } From 785bc10b998f76c12faf116eb9d78c56d5c7896c Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Mon, 16 Mar 2020 23:15:52 -0300 Subject: [PATCH 02/26] wip --- .vscode/launch.json | 5 ++--- .vscode/settings.json | 2 +- e2e/resolve/__tests__/resolve.test.js | 2 -- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index f3d8aff8c99e..f4106b4f6605 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,9 +9,8 @@ "request": "launch", "name": "Debug Jest with current test file", "program": "${workspaceFolder}/packages/jest-cli/bin/jest.js", - "cwd": "${workspaceFolder}/e2e/resolve", - "sourceMaps": true, - "outFiles": ["${workspaceFolder}/packages/**/build/**"] + "args": ["--runInBand", "${file}"], + "runtimeArgs": ["-r", "flow-remove-types/register"] } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index ff28aae6af54..0478de9c2561 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,7 +3,7 @@ "files.exclude": { "**/.git": true, "**/node_modules": true, - "**/build": false + "**/build": true }, "javascript.validate.enable": false, "jest.pathToJest": "yarn jest --", diff --git a/e2e/resolve/__tests__/resolve.test.js b/e2e/resolve/__tests__/resolve.test.js index 9b37c5cd7a57..2a092896174f 100644 --- a/e2e/resolve/__tests__/resolve.test.js +++ b/e2e/resolve/__tests__/resolve.test.js @@ -6,8 +6,6 @@ */ 'use strict'; -const path = require('path'); - let platform; function testRequire(filename) { From dbf1de3567451a580ff3089737fd823b14550190 Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Tue, 17 Mar 2020 22:05:01 -0300 Subject: [PATCH 03/26] all done, pending all tests run --- e2e/pnp/__tests__/undeclared-dependency.test.js | 16 ++++++++++++++++ e2e/pnp/package.json | 3 ++- e2e/pnp/undeclared-dependency/index.js | 11 +++++++++++ e2e/pnp/undeclared-dependency/package.json | 3 +++ e2e/resolve/__tests__/resolve.test.js | 6 +++--- packages/jest-resolve/src/index.ts | 13 ++++++++++--- packages/jest-runtime/src/helpers.ts | 8 ++++++-- packages/jest-runtime/src/index.ts | 5 ++++- 8 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 e2e/pnp/__tests__/undeclared-dependency.test.js create mode 100644 e2e/pnp/undeclared-dependency/index.js create mode 100644 e2e/pnp/undeclared-dependency/package.json diff --git a/e2e/pnp/__tests__/undeclared-dependency.test.js b/e2e/pnp/__tests__/undeclared-dependency.test.js new file mode 100644 index 000000000000..d3706a323f4c --- /dev/null +++ b/e2e/pnp/__tests__/undeclared-dependency.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. + * + */ + +it('should surface pnp errors', () => { + try { + require('undeclared'); + throw new Error('UNDECLARED_DEPENDENCY should have been thrown'); + } catch (error) { + expect(error.code).toBe('UNDECLARED_DEPENDENCY'); + } +}); diff --git a/e2e/pnp/package.json b/e2e/pnp/package.json index e25e02bd2111..13e3f22c227d 100644 --- a/e2e/pnp/package.json +++ b/e2e/pnp/package.json @@ -1,6 +1,7 @@ { "dependencies": { - "foo": "link:./lib" + "foo": "link:./lib", + "undeclared": "link:./underclared-dependency" }, "installConfig": { "pnp": true diff --git a/e2e/pnp/undeclared-dependency/index.js b/e2e/pnp/undeclared-dependency/index.js new file mode 100644 index 000000000000..18d7d48326eb --- /dev/null +++ b/e2e/pnp/undeclared-dependency/index.js @@ -0,0 +1,11 @@ +/** + * 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 nope = require('jest'); + +module.exports = () => nope; diff --git a/e2e/pnp/undeclared-dependency/package.json b/e2e/pnp/undeclared-dependency/package.json new file mode 100644 index 000000000000..1be1b18fe5a8 --- /dev/null +++ b/e2e/pnp/undeclared-dependency/package.json @@ -0,0 +1,3 @@ +{ + "version": "0.0.0" +} diff --git a/e2e/resolve/__tests__/resolve.test.js b/e2e/resolve/__tests__/resolve.test.js index 2a092896174f..c213b15ac440 100644 --- a/e2e/resolve/__tests__/resolve.test.js +++ b/e2e/resolve/__tests__/resolve.test.js @@ -110,9 +110,9 @@ test('should throw module not found error if the module has dependencies that ca "Cannot find module 'nope' from 'requiresUnexistingModule.js' Require stack: - jest/e2e/resolve/e2e/resolve/requiresUnexistingModule.js - jest/e2e/resolve/e2e/resolve/Test7.js - jest/e2e/resolve/e2e/resolve/__tests__/resolve.test.js + requiresUnexistingModule.js + Test7.js + __tests__/resolve.test.js However, Jest was able to find: diff --git a/packages/jest-resolve/src/index.ts b/packages/jest-resolve/src/index.ts index ec6c3ab48657..9952d9c2faa8 100644 --- a/packages/jest-resolve/src/index.ts +++ b/packages/jest-resolve/src/index.ts @@ -24,6 +24,7 @@ type FindNodeModuleConfig = { paths?: Array; resolver?: Config.Path | null; rootDir?: Config.Path; + throwIfNotFound?: boolean; }; type BooleanObject = Record; @@ -105,7 +106,11 @@ class Resolver { paths: paths ? (nodePaths || []).concat(paths) : nodePaths, rootDir: options.rootDir, }); - } catch (e) {} + } catch (e) { + if (options.throwIfNotFound) { + throw e; + } + } return null; } @@ -155,7 +160,7 @@ class Resolver { const skipResolution = options && options.skipNodeResolution && !moduleName.includes(path.sep); - const resolveNodeModule = (name: Config.Path) => + const resolveNodeModule = (name: Config.Path, throwIfNotFound = false) => Resolver.findNodeModule(name, { basedir: dirname, browser: this._options.browser, @@ -164,10 +169,12 @@ class Resolver { paths, resolver: this._options.resolver, rootDir: this._options.rootDir, + throwIfNotFound, }); if (!skipResolution) { - module = resolveNodeModule(moduleName); + // @ts-ignore: the "pnp" version named isn't in DefinitelyTyped + module = resolveNodeModule(moduleName, Boolean(process.versions.pnp)); if (module) { this._moduleNameCache.set(key, module); diff --git a/packages/jest-runtime/src/helpers.ts b/packages/jest-runtime/src/helpers.ts index 02f340a8fa12..bc07c87cb6c1 100644 --- a/packages/jest-runtime/src/helpers.ts +++ b/packages/jest-runtime/src/helpers.ts @@ -9,6 +9,7 @@ import * as path from 'path'; import slash = require('slash'); import glob = require('glob'); import {Config} from '@jest/types'; +import {Path} from '@jest/types/src/Config'; export const findSiblingsWithFileExtension = ( moduleFileExtensions: Config.ProjectConfig['moduleFileExtensions'], @@ -54,8 +55,11 @@ export const findSiblingsWithFileExtension = ( return ''; }; -export const printRequireStack = (requireStack: Array): string => ` +export const printRequireStack = ( + requireStack: Array, + rootDir: Path, +): string => ` Require stack: - ${requireStack.join('\n ')} + ${requireStack.map(path => path.replace(`${rootDir}/`, '')).join('\n ')} `; diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 1757c61225d5..50dcabb736f3 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -526,7 +526,10 @@ class Runtime { e.requireStack = [...this._requireStack].reverse(); if (e.requireStack.length > 1) { - e.message += printRequireStack(e.requireStack); + e.message += printRequireStack( + e.requireStack, + this._config.rootDir, + ); } } From 3b344669aa1c2c7e9ae644b11e0b568d13c81e6d Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Wed, 18 Mar 2020 00:34:03 -0300 Subject: [PATCH 04/26] passing tests, updated snapshots --- e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap | 4 ++-- .../__snapshots__/resolveNoFileExtensions.test.ts.snap | 7 ++++++- e2e/__tests__/pnp.test.ts | 2 +- e2e/pnp/package.json | 2 +- e2e/pnp/undeclared-dependency/index.js | 2 +- e2e/pnp/yarn.lock | 4 ++++ 6 files changed, 15 insertions(+), 6 deletions(-) diff --git a/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap b/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap index 0ea10ceef1a3..211fe3b838e1 100644 --- a/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap +++ b/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap @@ -36,7 +36,7 @@ FAIL __tests__/index.js 12 | module.exports = () => 'test'; 13 | - at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:519:17) + at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:525:17) at Object.require (index.js:10:1) `; @@ -65,6 +65,6 @@ FAIL __tests__/index.js 12 | module.exports = () => 'test'; 13 | - at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:519:17) + at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:525:17) at Object.require (index.js:10:1) `; diff --git a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap index 45ac2b1ca98d..265cba91eccc 100644 --- a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap +++ b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap @@ -19,6 +19,11 @@ FAIL __tests__/test.js Cannot find module './some-json-file' from 'index.js' + Require stack: + index.js + __tests__/test.js + + However, Jest was able to find: './some-json-file.json' @@ -32,6 +37,6 @@ FAIL __tests__/test.js | ^ 9 | - at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:276:11) + at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) at Object.require (index.js:8:18) `; diff --git a/e2e/__tests__/pnp.test.ts b/e2e/__tests__/pnp.test.ts index 29d8f77362d0..fd60348a3820 100644 --- a/e2e/__tests__/pnp.test.ts +++ b/e2e/__tests__/pnp.test.ts @@ -24,5 +24,5 @@ it('sucessfully runs the tests inside `pnp/`', () => { nodeOptions: `--require ${DIR}/.pnp.js`, }); expect(json.success).toBe(true); - expect(json.numTotalTestSuites).toBe(1); + expect(json.numTotalTestSuites).toBe(2); }); diff --git a/e2e/pnp/package.json b/e2e/pnp/package.json index 13e3f22c227d..78792eab2194 100644 --- a/e2e/pnp/package.json +++ b/e2e/pnp/package.json @@ -1,7 +1,7 @@ { "dependencies": { "foo": "link:./lib", - "undeclared": "link:./underclared-dependency" + "undeclared": "link:./undeclared-dependency" }, "installConfig": { "pnp": true diff --git a/e2e/pnp/undeclared-dependency/index.js b/e2e/pnp/undeclared-dependency/index.js index 18d7d48326eb..a00d5facdf0e 100644 --- a/e2e/pnp/undeclared-dependency/index.js +++ b/e2e/pnp/undeclared-dependency/index.js @@ -6,6 +6,6 @@ * */ -const nope = require('jest'); +const nope = require('unesitent_module__'); module.exports = () => nope; diff --git a/e2e/pnp/yarn.lock b/e2e/pnp/yarn.lock index 3f73f0689ff3..c9416ac9b6f6 100644 --- a/e2e/pnp/yarn.lock +++ b/e2e/pnp/yarn.lock @@ -5,3 +5,7 @@ "foo@link:./lib": version "0.0.0" uid "" + +"undeclared@link:./undeclared-dependency": + version "0.0.0" + uid "" From a1c2362c00168db89ac566ba2bceea8a208a532a Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Wed, 18 Mar 2020 00:43:07 -0300 Subject: [PATCH 05/26] updated changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 169c2270b0f7..ab54c38893ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features +- `[jest-runtime]` Require stack in the errors message when a module cannot be resolved ([#9681](https://github.com/facebook/jest/pull/9681)) - `[jest-config]` Support ESM config files with `.js` extension ([#9573](https://github.com/facebook/jest/pull/9573)). - `[jest-runtime]` Override `module.createRequire` to return a Jest-compatible `require` function ([#9469](https://github.com/facebook/jest/pull/9469)) - `[jest-haste-map]` [**BREAKING**] Remove `mapper` option ([#9581](https://github.com/facebook/jest/pull/9581)) @@ -10,6 +11,7 @@ ### Fixes +- `[jest-runtime]` Yarn PnP errors surfaced to the user ([#9681](https://github.com/facebook/jest/pull/9681)) - `[expect]` Handle readonly properties correctly ([#9575](https://github.com/facebook/jest/pull/9575)) - `[jest-cli]` Set `coverageProvider` correctly when provided in config ([#9562](https://github.com/facebook/jest/pull/9562)) - `[jest-cli]` Allow specifying `.cjs` and `.mjs` config files by `--config` CLI option ([#9578](https://github.com/facebook/jest/pull/9578)) From 8d4d0364306edb05a8dd5a650e3b44c9048646cd Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Wed, 18 Mar 2020 15:35:39 -0300 Subject: [PATCH 06/26] support windows separator --- .../resolveNoFileExtensions.test.ts.snap | 28 ------------------- e2e/__tests__/resolveNoFileExtensions.test.ts | 28 ++++++++++++++++++- e2e/resolve/__tests__/resolve.test.js | 4 ++- packages/jest-runtime/src/helpers.ts | 2 +- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap index 265cba91eccc..198492fd4309 100644 --- a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap +++ b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap @@ -12,31 +12,3 @@ exports[`show error message when no js moduleFileExtensions 1`] = ` https://jestjs.io/docs/configuration.html `; - -exports[`show error message with matching files 1`] = ` -FAIL __tests__/test.js - ● Test suite failed to run - - Cannot find module './some-json-file' from 'index.js' - - Require stack: - index.js - __tests__/test.js - - - However, Jest was able to find: - './some-json-file.json' - - You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. - - See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring - - 6 | */ - 7 | - > 8 | module.exports = require('./some-json-file'); - | ^ - 9 | - - at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) - at Object.require (index.js:8:18) -`; diff --git a/e2e/__tests__/resolveNoFileExtensions.test.ts b/e2e/__tests__/resolveNoFileExtensions.test.ts index 824eef1bf8c9..416f488bed35 100644 --- a/e2e/__tests__/resolveNoFileExtensions.test.ts +++ b/e2e/__tests__/resolveNoFileExtensions.test.ts @@ -20,7 +20,33 @@ test('show error message with matching files', () => { const {rest} = extractSummary(stderr); expect(exitCode).toBe(1); - expect(wrap(rest)).toMatchSnapshot(); + expect(wrap(rest)).toMatchInlineSnapshot(` + FAIL __tests__/test.js + ● Test suite failed to run + + Cannot find module './some-json-file' from 'index.js' + + Require stack: + index.js + __tests__${path.sep}test.js + + + However, Jest was able to find: + './some-json-file.json' + + You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. + + See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring + + 6 | */ + 7 | + > 8 | module.exports = require('./some-json-file'); + | ^ + 9 | + + at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) + at Object.require (index.js:8:18) + `); }); test('show error message when no js moduleFileExtensions', () => { diff --git a/e2e/resolve/__tests__/resolve.test.js b/e2e/resolve/__tests__/resolve.test.js index c213b15ac440..96c21c0de9df 100644 --- a/e2e/resolve/__tests__/resolve.test.js +++ b/e2e/resolve/__tests__/resolve.test.js @@ -8,6 +8,8 @@ let platform; +const path = require('path'); + function testRequire(filename) { return () => (platform = require(filename)); } @@ -112,7 +114,7 @@ test('should throw module not found error if the module has dependencies that ca Require stack: requiresUnexistingModule.js Test7.js - __tests__/resolve.test.js + __tests__${path.sep}resolve.test.js However, Jest was able to find: diff --git a/packages/jest-runtime/src/helpers.ts b/packages/jest-runtime/src/helpers.ts index bc07c87cb6c1..5f8fac207d2e 100644 --- a/packages/jest-runtime/src/helpers.ts +++ b/packages/jest-runtime/src/helpers.ts @@ -61,5 +61,5 @@ export const printRequireStack = ( ): string => ` Require stack: - ${requireStack.map(path => path.replace(`${rootDir}/`, '')).join('\n ')} + ${requireStack.map(p => p.replace(`${rootDir}${path.sep}`, '')).join('\n ')} `; From 19b47e8f7546ff7209c0f2d3fc2ec8e2ca60c35f Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Wed, 18 Mar 2020 22:26:35 -0300 Subject: [PATCH 07/26] git fixes for windows --- .../resolveNoFileExtensions.test.ts.snap | 56 +++++++++++++++++++ e2e/__tests__/resolveNoFileExtensions.test.ts | 34 +++-------- e2e/resolve/__tests__/resolve.test.js | 11 ++-- 3 files changed, 71 insertions(+), 30 deletions(-) diff --git a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap index 198492fd4309..7d1120f69fa9 100644 --- a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap +++ b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap @@ -12,3 +12,59 @@ exports[`show error message when no js moduleFileExtensions 1`] = ` https://jestjs.io/docs/configuration.html `; + +exports[`show error message with matching files 1`] = ` +FAIL __tests__/test.js + ● Test suite failed to run + + Cannot find module './some-json-file' from 'index.js' + + Require stack: + index.js + __tests__/test.js + + + However, Jest was able to find: + './some-json-file.json' + + You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. + + See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring + + 6 | */ + 7 | + > 8 | module.exports = require('./some-json-file'); + | ^ + 9 | + + at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) + at Object.require (index.js:8:18) +`; + +exports[`show error message with matching files: show error message with matching files - windows 1`] = ` +FAIL __tests__/test.js + ● Test suite failed to run + + Cannot find module './some-json-file' from 'index.js' + + Require stack: + index.js + __tests__\\test.js + + + However, Jest was able to find: + './some-json-file.json' + + You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. + + See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring + + 6 | */ + 7 | + > 8 | module.exports = require('./some-json-file'); + | ^ + 9 | + + at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) + at Object.require (index.js:8:18) +`; diff --git a/e2e/__tests__/resolveNoFileExtensions.test.ts b/e2e/__tests__/resolveNoFileExtensions.test.ts index 416f488bed35..548eca84c1c2 100644 --- a/e2e/__tests__/resolveNoFileExtensions.test.ts +++ b/e2e/__tests__/resolveNoFileExtensions.test.ts @@ -6,9 +6,9 @@ */ import * as path from 'path'; -import {wrap} from 'jest-snapshot-serializer-raw'; import runJest from '../runJest'; import {cleanup, extractSummary, writeFiles} from '../Utils'; +import {wrap} from 'jest-snapshot-serializer-raw'; const DIR = path.resolve(__dirname, '../resolve-no-extensions-no-js'); @@ -20,33 +20,15 @@ test('show error message with matching files', () => { const {rest} = extractSummary(stderr); expect(exitCode).toBe(1); - expect(wrap(rest)).toMatchInlineSnapshot(` - FAIL __tests__/test.js - ● Test suite failed to run - - Cannot find module './some-json-file' from 'index.js' - - Require stack: - index.js - __tests__${path.sep}test.js - - - However, Jest was able to find: - './some-json-file.json' - - You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. - - See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring - 6 | */ - 7 | - > 8 | module.exports = require('./some-json-file'); - | ^ - 9 | + if (process.platform === 'win32') { + expect(wrap(rest)).toMatchSnapshot( + 'show error message with matching files - windows', + ); + return; + } - at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) - at Object.require (index.js:8:18) - `); + expect(wrap(rest)).toMatchSnapshot(); }); test('show error message when no js moduleFileExtensions', () => { diff --git a/e2e/resolve/__tests__/resolve.test.js b/e2e/resolve/__tests__/resolve.test.js index 96c21c0de9df..7755de52ff50 100644 --- a/e2e/resolve/__tests__/resolve.test.js +++ b/e2e/resolve/__tests__/resolve.test.js @@ -8,8 +8,6 @@ let platform; -const path = require('path'); - function testRequire(filename) { return () => (platform = require(filename)); } @@ -108,13 +106,14 @@ test('should throw module not found error if the module has dependencies that ca } catch (error) { expect(error.code).toBe('MODULE_NOT_FOUND'); - expect(error.message).toMatchInlineSnapshot(` + if (process.platform === 'win32') { + expect(error.message).toMatchInlineSnapshot(` "Cannot find module 'nope' from 'requiresUnexistingModule.js' Require stack: requiresUnexistingModule.js Test7.js - __tests__${path.sep}resolve.test.js + __tests__\\\\resolve.test.js However, Jest was able to find: @@ -124,6 +123,10 @@ test('should throw module not found error if the module has dependencies that ca See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring" `); + return; + } + + expect(error.message).toMatchInlineSnapshot(); } }); From 74ef00d26feafad32b0d6fb18818c424fc7ca4b8 Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Wed, 18 Mar 2020 22:43:52 -0300 Subject: [PATCH 08/26] tests in mac --- e2e/__tests__/resolveNoFileExtensions.test.ts | 2 +- e2e/resolve/__tests__/resolve.test.js | 25 +++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/e2e/__tests__/resolveNoFileExtensions.test.ts b/e2e/__tests__/resolveNoFileExtensions.test.ts index 548eca84c1c2..8e1d898a8db2 100644 --- a/e2e/__tests__/resolveNoFileExtensions.test.ts +++ b/e2e/__tests__/resolveNoFileExtensions.test.ts @@ -6,9 +6,9 @@ */ import * as path from 'path'; +import {wrap} from 'jest-snapshot-serializer-raw'; import runJest from '../runJest'; import {cleanup, extractSummary, writeFiles} from '../Utils'; -import {wrap} from 'jest-snapshot-serializer-raw'; const DIR = path.resolve(__dirname, '../resolve-no-extensions-no-js'); diff --git a/e2e/resolve/__tests__/resolve.test.js b/e2e/resolve/__tests__/resolve.test.js index 7755de52ff50..dab820f6c987 100644 --- a/e2e/resolve/__tests__/resolve.test.js +++ b/e2e/resolve/__tests__/resolve.test.js @@ -108,12 +108,31 @@ test('should throw module not found error if the module has dependencies that ca if (process.platform === 'win32') { expect(error.message).toMatchInlineSnapshot(` + "Cannot find module 'nope' from 'requiresUnexistingModule.js' + + Require stack: + requiresUnexistingModule.js + Test7.js + __tests__\\\\resolve.test.js + + + However, Jest was able to find: + './requiresUnexistingModule.js' + + You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node']. + + See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring" + `); + return; + } + + expect(error.message).toMatchInlineSnapshot(` "Cannot find module 'nope' from 'requiresUnexistingModule.js' Require stack: requiresUnexistingModule.js Test7.js - __tests__\\\\resolve.test.js + __tests__/resolve.test.js However, Jest was able to find: @@ -123,10 +142,6 @@ test('should throw module not found error if the module has dependencies that ca See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring" `); - return; - } - - expect(error.message).toMatchInlineSnapshot(); } }); From 57e8a125bc08ad69876f5fbbf7143245227e2f88 Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Wed, 18 Mar 2020 23:26:13 -0300 Subject: [PATCH 09/26] use inline snapshots for conditional snapshots --- .../resolveNoFileExtensions.test.ts.snap | 56 ------------------ e2e/__tests__/resolveNoFileExtensions.test.ts | 58 +++++++++++++++++-- 2 files changed, 54 insertions(+), 60 deletions(-) diff --git a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap index 7d1120f69fa9..198492fd4309 100644 --- a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap +++ b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap @@ -12,59 +12,3 @@ exports[`show error message when no js moduleFileExtensions 1`] = ` https://jestjs.io/docs/configuration.html `; - -exports[`show error message with matching files 1`] = ` -FAIL __tests__/test.js - ● Test suite failed to run - - Cannot find module './some-json-file' from 'index.js' - - Require stack: - index.js - __tests__/test.js - - - However, Jest was able to find: - './some-json-file.json' - - You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. - - See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring - - 6 | */ - 7 | - > 8 | module.exports = require('./some-json-file'); - | ^ - 9 | - - at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) - at Object.require (index.js:8:18) -`; - -exports[`show error message with matching files: show error message with matching files - windows 1`] = ` -FAIL __tests__/test.js - ● Test suite failed to run - - Cannot find module './some-json-file' from 'index.js' - - Require stack: - index.js - __tests__\\test.js - - - However, Jest was able to find: - './some-json-file.json' - - You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. - - See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring - - 6 | */ - 7 | - > 8 | module.exports = require('./some-json-file'); - | ^ - 9 | - - at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) - at Object.require (index.js:8:18) -`; diff --git a/e2e/__tests__/resolveNoFileExtensions.test.ts b/e2e/__tests__/resolveNoFileExtensions.test.ts index 8e1d898a8db2..dc660997acec 100644 --- a/e2e/__tests__/resolveNoFileExtensions.test.ts +++ b/e2e/__tests__/resolveNoFileExtensions.test.ts @@ -22,13 +22,63 @@ test('show error message with matching files', () => { expect(exitCode).toBe(1); if (process.platform === 'win32') { - expect(wrap(rest)).toMatchSnapshot( - 'show error message with matching files - windows', - ); + expect(wrap(rest)).toMatchInlineSnapshot(` +FAIL __tests__/test.js + ● Test suite failed to run + + Cannot find module './some-json-file' from 'index.js' + + Require stack: + index.js + __tests__\\test.js + + + However, Jest was able to find: + './some-json-file.json' + + You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. + + See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring + + 6 | */ + 7 | + > 8 | module.exports = require('./some-json-file'); + | ^ + 9 | + + at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) + at Object.require (index.js:8:18) +`); return; } - expect(wrap(rest)).toMatchSnapshot(); + expect(wrap(rest)).toMatchInlineSnapshot(` +FAIL __tests__/test.js + ● Test suite failed to run + + Cannot find module './some-json-file' from 'index.js' + + Require stack: + index.js + __tests__/test.js + + + However, Jest was able to find: + './some-json-file.json' + + You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. + + See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring + + 6 | */ + 7 | + > 8 | module.exports = require('./some-json-file'); + | ^ + 9 | + + at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) + at Object.require (index.js:8:18) +`); }); test('show error message when no js moduleFileExtensions', () => { From 0483d94c4b418110c00c66018ff555a8fbdd5d1e Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Thu, 19 Mar 2020 15:57:50 -0300 Subject: [PATCH 10/26] update spanshot --- e2e/__tests__/resolveNoFileExtensions.test.ts | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/e2e/__tests__/resolveNoFileExtensions.test.ts b/e2e/__tests__/resolveNoFileExtensions.test.ts index dc660997acec..43feeda924a2 100644 --- a/e2e/__tests__/resolveNoFileExtensions.test.ts +++ b/e2e/__tests__/resolveNoFileExtensions.test.ts @@ -23,62 +23,62 @@ test('show error message with matching files', () => { if (process.platform === 'win32') { expect(wrap(rest)).toMatchInlineSnapshot(` -FAIL __tests__/test.js - ● Test suite failed to run + FAIL __tests__/test.js + ● Test suite failed to run - Cannot find module './some-json-file' from 'index.js' + Cannot find module './some-json-file' from 'index.js' - Require stack: - index.js - __tests__\\test.js + Require stack: + index.js + __tests__\\test.js - However, Jest was able to find: - './some-json-file.json' + However, Jest was able to find: + './some-json-file.json' - You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. + You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. - See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring + See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring - 6 | */ - 7 | - > 8 | module.exports = require('./some-json-file'); - | ^ - 9 | + 6 | */ + 7 | + > 8 | module.exports = require('./some-json-file'); + | ^ + 9 | - at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) - at Object.require (index.js:8:18) -`); + at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) + at Object.require (index.js:8:18) + `); return; } expect(wrap(rest)).toMatchInlineSnapshot(` -FAIL __tests__/test.js - ● Test suite failed to run + FAIL __tests__/test.js + ● Test suite failed to run - Cannot find module './some-json-file' from 'index.js' + Cannot find module './some-json-file' from 'index.js' - Require stack: - index.js - __tests__/test.js + Require stack: + index.js + __tests__/test.js - However, Jest was able to find: - './some-json-file.json' + However, Jest was able to find: + './some-json-file.json' - You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. + You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. - See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring + See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring - 6 | */ - 7 | - > 8 | module.exports = require('./some-json-file'); - | ^ - 9 | + 6 | */ + 7 | + > 8 | module.exports = require('./some-json-file'); + | ^ + 9 | - at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) - at Object.require (index.js:8:18) -`); + at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) + at Object.require (index.js:8:18) + `); }); test('show error message when no js moduleFileExtensions', () => { From 644a5aa2142401429562c4bcab93b54fd2f905c5 Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Thu, 19 Mar 2020 16:33:45 -0300 Subject: [PATCH 11/26] windows snapshots --- e2e/__tests__/resolveNoFileExtensions.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/__tests__/resolveNoFileExtensions.test.ts b/e2e/__tests__/resolveNoFileExtensions.test.ts index 43feeda924a2..355bad11bd5e 100644 --- a/e2e/__tests__/resolveNoFileExtensions.test.ts +++ b/e2e/__tests__/resolveNoFileExtensions.test.ts @@ -34,7 +34,7 @@ test('show error message with matching files', () => { However, Jest was able to find: - './some-json-file.json' + './some-json-file.json' You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. From f51e1c4734a6c367c1045d91723bbda83417bbe0 Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Mon, 23 Mar 2020 16:36:00 -0300 Subject: [PATCH 12/26] unix paths in require stack error --- packages/jest-runtime/src/helpers.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/jest-runtime/src/helpers.ts b/packages/jest-runtime/src/helpers.ts index 5f8fac207d2e..0dfd44befd26 100644 --- a/packages/jest-runtime/src/helpers.ts +++ b/packages/jest-runtime/src/helpers.ts @@ -61,5 +61,8 @@ export const printRequireStack = ( ): string => ` Require stack: - ${requireStack.map(p => p.replace(`${rootDir}${path.sep}`, '')).join('\n ')} + ${requireStack + .map(p => p.replace(`${rootDir}${path.sep}`, '')) + .map(slash) + .join('\n ')} `; From 1b92748e4838695d6c76e9ec25a7f04860345ca7 Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Mon, 23 Mar 2020 18:05:01 -0300 Subject: [PATCH 13/26] build require stack from module parent in the modules runtime, unix paths for all prints --- .../resolveNoFileExtensions.test.ts.snap | 28 +++++ e2e/__tests__/resolveNoFileExtensions.test.ts | 59 +--------- e2e/resolve/__tests__/resolve.test.js | 20 ---- .../src/RuntimeModuleNotFoundError.ts | 42 +++++++ packages/jest-runtime/src/helpers.ts | 13 --- packages/jest-runtime/src/index.ts | 104 +++++++++--------- 6 files changed, 123 insertions(+), 143 deletions(-) create mode 100644 packages/jest-runtime/src/RuntimeModuleNotFoundError.ts diff --git a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap index 198492fd4309..265cba91eccc 100644 --- a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap +++ b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap @@ -12,3 +12,31 @@ exports[`show error message when no js moduleFileExtensions 1`] = ` https://jestjs.io/docs/configuration.html `; + +exports[`show error message with matching files 1`] = ` +FAIL __tests__/test.js + ● Test suite failed to run + + Cannot find module './some-json-file' from 'index.js' + + Require stack: + index.js + __tests__/test.js + + + However, Jest was able to find: + './some-json-file.json' + + You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. + + See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring + + 6 | */ + 7 | + > 8 | module.exports = require('./some-json-file'); + | ^ + 9 | + + at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) + at Object.require (index.js:8:18) +`; diff --git a/e2e/__tests__/resolveNoFileExtensions.test.ts b/e2e/__tests__/resolveNoFileExtensions.test.ts index 355bad11bd5e..06b073528773 100644 --- a/e2e/__tests__/resolveNoFileExtensions.test.ts +++ b/e2e/__tests__/resolveNoFileExtensions.test.ts @@ -21,64 +21,7 @@ test('show error message with matching files', () => { expect(exitCode).toBe(1); - if (process.platform === 'win32') { - expect(wrap(rest)).toMatchInlineSnapshot(` - FAIL __tests__/test.js - ● Test suite failed to run - - Cannot find module './some-json-file' from 'index.js' - - Require stack: - index.js - __tests__\\test.js - - - However, Jest was able to find: - './some-json-file.json' - - You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. - - See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring - - 6 | */ - 7 | - > 8 | module.exports = require('./some-json-file'); - | ^ - 9 | - - at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) - at Object.require (index.js:8:18) - `); - return; - } - - expect(wrap(rest)).toMatchInlineSnapshot(` - FAIL __tests__/test.js - ● Test suite failed to run - - Cannot find module './some-json-file' from 'index.js' - - Require stack: - index.js - __tests__/test.js - - - However, Jest was able to find: - './some-json-file.json' - - You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js']. - - See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring - - 6 | */ - 7 | - > 8 | module.exports = require('./some-json-file'); - | ^ - 9 | - - at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) - at Object.require (index.js:8:18) - `); + expect(wrap(rest)).toMatchSnapshot(); }); test('show error message when no js moduleFileExtensions', () => { diff --git a/e2e/resolve/__tests__/resolve.test.js b/e2e/resolve/__tests__/resolve.test.js index dab820f6c987..c213b15ac440 100644 --- a/e2e/resolve/__tests__/resolve.test.js +++ b/e2e/resolve/__tests__/resolve.test.js @@ -106,26 +106,6 @@ test('should throw module not found error if the module has dependencies that ca } catch (error) { expect(error.code).toBe('MODULE_NOT_FOUND'); - if (process.platform === 'win32') { - expect(error.message).toMatchInlineSnapshot(` - "Cannot find module 'nope' from 'requiresUnexistingModule.js' - - Require stack: - requiresUnexistingModule.js - Test7.js - __tests__\\\\resolve.test.js - - - However, Jest was able to find: - './requiresUnexistingModule.js' - - You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node']. - - See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring" - `); - return; - } - expect(error.message).toMatchInlineSnapshot(` "Cannot find module 'nope' from 'requiresUnexistingModule.js' diff --git a/packages/jest-runtime/src/RuntimeModuleNotFoundError.ts b/packages/jest-runtime/src/RuntimeModuleNotFoundError.ts new file mode 100644 index 000000000000..3c8b47d97d8a --- /dev/null +++ b/packages/jest-runtime/src/RuntimeModuleNotFoundError.ts @@ -0,0 +1,42 @@ +/** + * 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 {ModuleNotFoundError} from 'jest-resolve'; +import {Config} from '@jest/types'; +import slash = require('slash'); + +export default class RuntimeModuleNotFoundError extends ModuleNotFoundError { + public hint?: string; + public requireStack?: Array; + public stackTraceBuilt?: boolean; + + public static buildMessage( + error: RuntimeModuleNotFoundError, + rootDir: Config.Path, + ): void { + if ( + !error.stackTraceBuilt && + error?.requireStack?.length && + error?.requireStack?.length > 1 + ) { + error.message += ` + +Require stack: + ${(error.requireStack as Array) + .map(p => p.replace(`${rootDir}${path.sep}`, '')) + .map(slash) + .join('\n ')} +`; + error.stackTraceBuilt = true; + } + + if (error.hint) { + error.message += error.hint; + } + } +} diff --git a/packages/jest-runtime/src/helpers.ts b/packages/jest-runtime/src/helpers.ts index 0dfd44befd26..885d508e2e20 100644 --- a/packages/jest-runtime/src/helpers.ts +++ b/packages/jest-runtime/src/helpers.ts @@ -9,7 +9,6 @@ import * as path from 'path'; import slash = require('slash'); import glob = require('glob'); import {Config} from '@jest/types'; -import {Path} from '@jest/types/src/Config'; export const findSiblingsWithFileExtension = ( moduleFileExtensions: Config.ProjectConfig['moduleFileExtensions'], @@ -54,15 +53,3 @@ export const findSiblingsWithFileExtension = ( return ''; }; - -export const printRequireStack = ( - requireStack: Array, - rootDir: Path, -): string => ` - -Require stack: - ${requireStack - .map(p => p.replace(`${rootDir}${path.sep}`, '')) - .map(slash) - .join('\n ')} -`; diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 50dcabb736f3..91c2e8463746 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -34,13 +34,14 @@ import {CoverageInstrumenter, V8Coverage} from 'collect-v8-coverage'; import * as fs from 'graceful-fs'; import {run as cliRun} from './cli'; import {options as cliOptions} from './cli/args'; -import {findSiblingsWithFileExtension, printRequireStack} from './helpers'; +import {findSiblingsWithFileExtension} from './helpers'; import {Context as JestContext} from './types'; import jestMock = require('jest-mock'); import HasteMap = require('jest-haste-map'); import Resolver = require('jest-resolve'); import Snapshot = require('jest-snapshot'); import stripBOM = require('strip-bom'); +import RuntimeModuleNotFoundError from './RuntimeModuleNotFoundError'; type HasteMapOptions = { console?: Console; @@ -122,7 +123,6 @@ class Runtime { private _transitiveShouldMock: BooleanObject; private _unmockList: RegExp | undefined; private _virtualMocks: BooleanObject; - private _requireStack: Array; constructor( config: Config.ProjectConfig, @@ -159,7 +159,6 @@ class Runtime { this._sourceMapRegistry = Object.create(null); this._fileTransforms = new Map(); this._virtualMocks = Object.create(null); - this._requireStack = []; this._mockMetaDataCache = Object.create(null); this._shouldMockModuleCache = Object.create(null); @@ -506,44 +505,19 @@ class Runtime { requireModuleOrMock(from: Config.Path, moduleName: string): unknown { try { - let result; - - if (this._requireStack[this._requireStack.length - 1] !== from) { - this._requireStack.push(from); - } - if (this._shouldMock(from, moduleName)) { - result = this.requireMock(from, moduleName); + return this.requireMock(from, moduleName); } else { - result = this.requireModule(from, moduleName); + return this.requireModule(from, moduleName); } - - this._requireStack.pop(); - return result; } catch (e) { if (e.code === 'MODULE_NOT_FOUND') { - if (!e.requireStack) { - e.requireStack = [...this._requireStack].reverse(); - - if (e.requireStack.length > 1) { - e.message += printRequireStack( - e.requireStack, - this._config.rootDir, - ); - } - } - - const appendedMessage = findSiblingsWithFileExtension( + e.hint = findSiblingsWithFileExtension( this._config.moduleFileExtensions, from, moduleName, ); - - if (appendedMessage) { - e.message += appendedMessage; - } } - this._requireStack.pop(); throw e; } } @@ -864,28 +838,32 @@ class Runtime { return; } - compiledFunction.call( - localModule.exports, - localModule as NodeModule, // module object - localModule.exports, // module exports - localModule.require as typeof require, // require implementation - dirname, // __dirname - filename, // __filename - this._environment.global, // global object - this._createJestObjectFor( - filename, - localModule.require as LocalModuleRequire, - ), // jest object - ...this._config.extraGlobals.map(globalVariable => { - if (this._environment.global[globalVariable]) { - return this._environment.global[globalVariable]; - } + try { + compiledFunction.call( + localModule.exports, + localModule as NodeModule, // module object + localModule.exports, // module exports + localModule.require as typeof require, // require implementation + dirname, // __dirname + filename, // __filename + this._environment.global, // global object + this._createJestObjectFor( + filename, + localModule.require as LocalModuleRequire, + ), // jest object + ...this._config.extraGlobals.map(globalVariable => { + if (this._environment.global[globalVariable]) { + return this._environment.global[globalVariable]; + } - throw new Error( - `You have requested '${globalVariable}' as a global variable, but it was not present. Please check your config or your global environment.`, - ); - }), - ); + throw new Error( + `You have requested '${globalVariable}' as a global variable, but it was not present. Please check your config or your global environment.`, + ); + }), + ); + } catch (error) { + this.handleExecutionError(error, localModule); + } this._isCurrentlyExecutingManualMock = origCurrExecutingManualMock; this._currentlyExecutingModulePath = lastExecutingModulePath; @@ -1309,6 +1287,28 @@ class Runtime { ...this._config.extraGlobals, ]; } + + private handleExecutionError(e: Error, module: InitialModule): void { + const runtimeModuleNotFoundError = e as RuntimeModuleNotFoundError; + if (runtimeModuleNotFoundError.code === 'MODULE_NOT_FOUND') { + runtimeModuleNotFoundError.requireStack = [module.filename || module.id]; + + for (let cursor = module.parent; cursor; cursor = cursor.parent) { + runtimeModuleNotFoundError.requireStack.push( + cursor.filename || cursor.id, + ); + } + + RuntimeModuleNotFoundError.buildMessage( + runtimeModuleNotFoundError, + this._config.rootDir, + ); + + throw runtimeModuleNotFoundError; + } + + throw e; + } } export = Runtime; From 949730318d8174c9243fb60b31966cee3129cabf Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Mon, 23 Mar 2020 19:09:41 -0300 Subject: [PATCH 14/26] fix in runtime errors --- .../src/RuntimeModuleNotFoundError.ts | 22 ++++++----- packages/jest-runtime/src/index.ts | 37 +++++++++++-------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/packages/jest-runtime/src/RuntimeModuleNotFoundError.ts b/packages/jest-runtime/src/RuntimeModuleNotFoundError.ts index 3c8b47d97d8a..80a12e76113e 100644 --- a/packages/jest-runtime/src/RuntimeModuleNotFoundError.ts +++ b/packages/jest-runtime/src/RuntimeModuleNotFoundError.ts @@ -13,18 +13,21 @@ import slash = require('slash'); export default class RuntimeModuleNotFoundError extends ModuleNotFoundError { public hint?: string; public requireStack?: Array; - public stackTraceBuilt?: boolean; + + private _originalMessage?: string; public static buildMessage( error: RuntimeModuleNotFoundError, rootDir: Config.Path, ): void { - if ( - !error.stackTraceBuilt && - error?.requireStack?.length && - error?.requireStack?.length > 1 - ) { - error.message += ` + if (!error._originalMessage) { + error._originalMessage = error.message || ''; + } + + let message = error._originalMessage; + + if (error?.requireStack?.length && error?.requireStack?.length > 1) { + message += ` Require stack: ${(error.requireStack as Array) @@ -32,11 +35,12 @@ Require stack: .map(slash) .join('\n ')} `; - error.stackTraceBuilt = true; } if (error.hint) { - error.message += error.hint; + message += error.hint; } + + error.message = message; } } diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 91c2e8463746..adb10b7ead89 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -512,11 +512,14 @@ class Runtime { } } catch (e) { if (e.code === 'MODULE_NOT_FOUND') { - e.hint = findSiblingsWithFileExtension( - this._config.moduleFileExtensions, - from, - moduleName, - ); + if (!e.hint) { + e.hint = findSiblingsWithFileExtension( + this._config.moduleFileExtensions, + from, + moduleName, + ); + } + RuntimeModuleNotFoundError.buildMessage(e, this._config.rootDir); } throw e; } @@ -1291,20 +1294,22 @@ class Runtime { private handleExecutionError(e: Error, module: InitialModule): void { const runtimeModuleNotFoundError = e as RuntimeModuleNotFoundError; if (runtimeModuleNotFoundError.code === 'MODULE_NOT_FOUND') { - runtimeModuleNotFoundError.requireStack = [module.filename || module.id]; + if (!runtimeModuleNotFoundError.requireStack) { + runtimeModuleNotFoundError.requireStack = [ + module.filename || module.id, + ]; + + for (let cursor = module.parent; cursor; cursor = cursor.parent) { + runtimeModuleNotFoundError.requireStack.push( + cursor.filename || cursor.id, + ); + } - for (let cursor = module.parent; cursor; cursor = cursor.parent) { - runtimeModuleNotFoundError.requireStack.push( - cursor.filename || cursor.id, + RuntimeModuleNotFoundError.buildMessage( + runtimeModuleNotFoundError, + this._config.rootDir, ); } - - RuntimeModuleNotFoundError.buildMessage( - runtimeModuleNotFoundError, - this._config.rootDir, - ); - - throw runtimeModuleNotFoundError; } throw e; From 006e5656f7ea9277ffd7fd598d600a8b9b240200 Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Mon, 23 Mar 2020 19:15:55 -0300 Subject: [PATCH 15/26] fix return type for handleRuntimeError --- packages/jest-runtime/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index adb10b7ead89..7d70f0e701d1 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -1291,7 +1291,7 @@ class Runtime { ]; } - private handleExecutionError(e: Error, module: InitialModule): void { + private handleExecutionError(e: Error, module: InitialModule): never { const runtimeModuleNotFoundError = e as RuntimeModuleNotFoundError; if (runtimeModuleNotFoundError.code === 'MODULE_NOT_FOUND') { if (!runtimeModuleNotFoundError.requireStack) { From 8b690e17477a592347ecf664d1c803d1982c2e18 Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Mon, 23 Mar 2020 19:45:19 -0300 Subject: [PATCH 16/26] extend ModuleNotFoundError to accomodate requireStack and hint coexistence --- e2e/__tests__/resolveNoFileExtensions.test.ts | 1 - .../jest-resolve/src/ModuleNotFoundError.ts | 33 +++++++++++++ .../src/RuntimeModuleNotFoundError.ts | 46 ------------------- packages/jest-runtime/src/index.ts | 32 ++++++------- 4 files changed, 46 insertions(+), 66 deletions(-) delete mode 100644 packages/jest-runtime/src/RuntimeModuleNotFoundError.ts diff --git a/e2e/__tests__/resolveNoFileExtensions.test.ts b/e2e/__tests__/resolveNoFileExtensions.test.ts index 06b073528773..824eef1bf8c9 100644 --- a/e2e/__tests__/resolveNoFileExtensions.test.ts +++ b/e2e/__tests__/resolveNoFileExtensions.test.ts @@ -20,7 +20,6 @@ test('show error message with matching files', () => { const {rest} = extractSummary(stderr); expect(exitCode).toBe(1); - expect(wrap(rest)).toMatchSnapshot(); }); diff --git a/packages/jest-resolve/src/ModuleNotFoundError.ts b/packages/jest-resolve/src/ModuleNotFoundError.ts index 6ddfd2c9f372..7d370f617006 100644 --- a/packages/jest-resolve/src/ModuleNotFoundError.ts +++ b/packages/jest-resolve/src/ModuleNotFoundError.ts @@ -5,6 +5,39 @@ * LICENSE file in the root directory of this source tree. */ +import * as path from 'path'; +import type {Config} from '@jest/types'; +import slash = require('slash'); + export default class ModuleNotFoundError extends Error { code = 'MODULE_NOT_FOUND'; + public hint?: string; + public requireStack?: Array; + + private _originalMessage?: string; + + public buildMessage(rootDir: Config.Path): void { + if (!this._originalMessage) { + this._originalMessage = this.message || ''; + } + + let message = this._originalMessage; + + if (this?.requireStack?.length && this!.requireStack!.length > 1) { + message += ` + +Require stack: + ${(this.requireStack as Array) + .map(p => p.replace(`${rootDir}${path.sep}`, '')) + .map(slash) + .join('\n ')} +`; + } + + if (this.hint) { + message += this.hint; + } + + this.message = message; + } } diff --git a/packages/jest-runtime/src/RuntimeModuleNotFoundError.ts b/packages/jest-runtime/src/RuntimeModuleNotFoundError.ts deleted file mode 100644 index 80a12e76113e..000000000000 --- a/packages/jest-runtime/src/RuntimeModuleNotFoundError.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * 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 {ModuleNotFoundError} from 'jest-resolve'; -import {Config} from '@jest/types'; -import slash = require('slash'); - -export default class RuntimeModuleNotFoundError extends ModuleNotFoundError { - public hint?: string; - public requireStack?: Array; - - private _originalMessage?: string; - - public static buildMessage( - error: RuntimeModuleNotFoundError, - rootDir: Config.Path, - ): void { - if (!error._originalMessage) { - error._originalMessage = error.message || ''; - } - - let message = error._originalMessage; - - if (error?.requireStack?.length && error?.requireStack?.length > 1) { - message += ` - -Require stack: - ${(error.requireStack as Array) - .map(p => p.replace(`${rootDir}${path.sep}`, '')) - .map(slash) - .join('\n ')} -`; - } - - if (error.hint) { - message += error.hint; - } - - error.message = message; - } -} diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 25f8db774862..bf877125fe7e 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -32,6 +32,7 @@ import { import type {V8CoverageResult} from '@jest/test-result'; import {CoverageInstrumenter, V8Coverage} from 'collect-v8-coverage'; import * as fs from 'graceful-fs'; +import type ModuleNotFoundError from 'jest-resolve/build/ModuleNotFoundError'; import {run as cliRun} from './cli'; import {options as cliOptions} from './cli/args'; import {findSiblingsWithFileExtension} from './helpers'; @@ -41,7 +42,6 @@ import HasteMap = require('jest-haste-map'); import Resolver = require('jest-resolve'); import Snapshot = require('jest-snapshot'); import stripBOM = require('strip-bom'); -import RuntimeModuleNotFoundError from './RuntimeModuleNotFoundError'; type HasteMapOptions = { console?: Console; @@ -511,17 +511,18 @@ class Runtime { return this.requireModule(from, moduleName); } } catch (e) { - if (e.code === 'MODULE_NOT_FOUND') { - if (!e.hint) { - e.hint = findSiblingsWithFileExtension( + const moduleNotFound = e as ModuleNotFoundError; + if (moduleNotFound.code === 'MODULE_NOT_FOUND') { + if (!moduleNotFound.hint) { + moduleNotFound.hint = findSiblingsWithFileExtension( this._config.moduleFileExtensions, from, moduleName, ); } - RuntimeModuleNotFoundError.buildMessage(e, this._config.rootDir); + moduleNotFound.buildMessage(this._config.rootDir); } - throw e; + throw moduleNotFound; } } @@ -1292,23 +1293,16 @@ class Runtime { } private handleExecutionError(e: Error, module: InitialModule): never { - const runtimeModuleNotFoundError = e as RuntimeModuleNotFoundError; - if (runtimeModuleNotFoundError.code === 'MODULE_NOT_FOUND') { - if (!runtimeModuleNotFoundError.requireStack) { - runtimeModuleNotFoundError.requireStack = [ - module.filename || module.id, - ]; + const moduleNotFoundError: ModuleNotFoundError = e as ModuleNotFoundError; + if (moduleNotFoundError.code === 'MODULE_NOT_FOUND') { + if (!moduleNotFoundError.requireStack) { + moduleNotFoundError.requireStack = [module.filename || module.id]; for (let cursor = module.parent; cursor; cursor = cursor.parent) { - runtimeModuleNotFoundError.requireStack.push( - cursor.filename || cursor.id, - ); + moduleNotFoundError.requireStack.push(cursor.filename || cursor.id); } - RuntimeModuleNotFoundError.buildMessage( - runtimeModuleNotFoundError, - this._config.rootDir, - ); + moduleNotFoundError.buildMessage(this._config.rootDir); } } From aeea7916030f89731dfc9d6686927e8534752645 Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Mon, 23 Mar 2020 20:03:51 -0300 Subject: [PATCH 17/26] fix test reporter test, better ModuleNotFoundError constructor --- .../jest-reporters/src/__tests__/notify_reporter.test.ts | 6 ++++-- packages/jest-resolve/src/ModuleNotFoundError.ts | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/jest-reporters/src/__tests__/notify_reporter.test.ts b/packages/jest-reporters/src/__tests__/notify_reporter.test.ts index 8c34af32d2ab..cbaaac084810 100644 --- a/packages/jest-reporters/src/__tests__/notify_reporter.test.ts +++ b/packages/jest-reporters/src/__tests__/notify_reporter.test.ts @@ -7,6 +7,7 @@ import type {AggregatedResult} from '@jest/test-result'; import type {Config} from '@jest/types'; +import Resolver from 'jest-resolve'; import NotifyReporter from '../notify_reporter'; import {makeGlobalConfig} from '../../../../TestUtils'; @@ -223,8 +224,9 @@ describe('node-notifier is an optional dependency', () => { test('without node-notifier uses mock function that throws an error', () => { jest.doMock('node-notifier', () => { - const error: any = new Error("Cannot find module 'node-notifier'"); - error.code = 'MODULE_NOT_FOUND'; + const error: any = new Resolver.ModuleNotFoundError( + "Cannot find module 'node-notifier'", + ); throw error; }); diff --git a/packages/jest-resolve/src/ModuleNotFoundError.ts b/packages/jest-resolve/src/ModuleNotFoundError.ts index 7d370f617006..d07ab060c452 100644 --- a/packages/jest-resolve/src/ModuleNotFoundError.ts +++ b/packages/jest-resolve/src/ModuleNotFoundError.ts @@ -16,6 +16,11 @@ export default class ModuleNotFoundError extends Error { private _originalMessage?: string; + constructor(message: string) { + super(message); + this._originalMessage = message; + } + public buildMessage(rootDir: Config.Path): void { if (!this._originalMessage) { this._originalMessage = this.message || ''; From a5660af80cca7d45d2b0f4afc3670869ab3606fe Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Mon, 23 Mar 2020 21:47:04 -0300 Subject: [PATCH 18/26] Update CHANGELOG.md --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab54c38893ec..d3b7b047554b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ### Features -- `[jest-runtime]` Require stack in the errors message when a module cannot be resolved ([#9681](https://github.com/facebook/jest/pull/9681)) +- `[jest-runtime]` Require stack when a module cannot be resolved ([#9681](https://github.com/facebook/jest/pull/9681)) - `[jest-config]` Support ESM config files with `.js` extension ([#9573](https://github.com/facebook/jest/pull/9573)). - `[jest-runtime]` Override `module.createRequire` to return a Jest-compatible `require` function ([#9469](https://github.com/facebook/jest/pull/9469)) - `[jest-haste-map]` [**BREAKING**] Remove `mapper` option ([#9581](https://github.com/facebook/jest/pull/9581)) @@ -11,7 +11,7 @@ ### Fixes -- `[jest-runtime]` Yarn PnP errors surfaced to the user ([#9681](https://github.com/facebook/jest/pull/9681)) +- `[jest-runtime]` Yarn PnP errors displayed to the user ([#9681](https://github.com/facebook/jest/pull/9681)) - `[expect]` Handle readonly properties correctly ([#9575](https://github.com/facebook/jest/pull/9575)) - `[jest-cli]` Set `coverageProvider` correctly when provided in config ([#9562](https://github.com/facebook/jest/pull/9562)) - `[jest-cli]` Allow specifying `.cjs` and `.mjs` config files by `--config` CLI option ([#9578](https://github.com/facebook/jest/pull/9578)) From 17b33464d919bfc030c8c0712a5941c9c1b71f2c Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Tue, 24 Mar 2020 19:49:23 -0300 Subject: [PATCH 19/26] fix moduelnotfounderror casting and extension hint reporting --- e2e/resolve/__tests__/resolve.test.js | 9 +-------- packages/jest-resolve/src/ModuleNotFoundError.ts | 9 ++++++++- packages/jest-resolve/src/index.ts | 16 ++++++++++++++++ packages/jest-runtime/src/index.ts | 15 ++++++++------- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/e2e/resolve/__tests__/resolve.test.js b/e2e/resolve/__tests__/resolve.test.js index c213b15ac440..7f22635215c5 100644 --- a/e2e/resolve/__tests__/resolve.test.js +++ b/e2e/resolve/__tests__/resolve.test.js @@ -113,14 +113,7 @@ test('should throw module not found error if the module has dependencies that ca requiresUnexistingModule.js Test7.js __tests__/resolve.test.js - - - However, Jest was able to find: - './requiresUnexistingModule.js' - - You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node']. - - See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring" + " `); } }); diff --git a/packages/jest-resolve/src/ModuleNotFoundError.ts b/packages/jest-resolve/src/ModuleNotFoundError.ts index d07ab060c452..a45f715219ed 100644 --- a/packages/jest-resolve/src/ModuleNotFoundError.ts +++ b/packages/jest-resolve/src/ModuleNotFoundError.ts @@ -13,12 +13,14 @@ export default class ModuleNotFoundError extends Error { code = 'MODULE_NOT_FOUND'; public hint?: string; public requireStack?: Array; + public moduleName?: string; private _originalMessage?: string; - constructor(message: string) { + constructor(message: string, moduleName?: string) { super(message); this._originalMessage = message; + this.moduleName = moduleName; } public buildMessage(rootDir: Config.Path): void { @@ -45,4 +47,9 @@ Require stack: this.message = message; } + + public static duckType(error: ModuleNotFoundError): ModuleNotFoundError { + error.buildMessage = ModuleNotFoundError.prototype.buildMessage; + return error; + } } diff --git a/packages/jest-resolve/src/index.ts b/packages/jest-resolve/src/index.ts index f1f9f8b5d065..15856fb5aeb2 100644 --- a/packages/jest-resolve/src/index.ts +++ b/packages/jest-resolve/src/index.ts @@ -83,6 +83,21 @@ class Resolver { static ModuleNotFoundError = ModuleNotFoundError; + static tryCastModuleNotFoundError( + error: unknown, + ): ModuleNotFoundError | null { + if (error instanceof ModuleNotFoundError) { + return error as ModuleNotFoundError; + } + + const casted = error as ModuleNotFoundError; + if (casted.code === 'MODULE_NOT_FOUND') { + return ModuleNotFoundError.duckType(casted); + } + + return null; + } + static clearDefaultResolverCache(): void { clearDefaultResolverCache(); } @@ -222,6 +237,7 @@ class Resolver { throw new ModuleNotFoundError( `Cannot find module '${moduleName}' from '${relativePath || '.'}'`, + moduleName, ); } diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index bf877125fe7e..8d4a0ce8f4e3 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -32,7 +32,6 @@ import { import type {V8CoverageResult} from '@jest/test-result'; import {CoverageInstrumenter, V8Coverage} from 'collect-v8-coverage'; import * as fs from 'graceful-fs'; -import type ModuleNotFoundError from 'jest-resolve/build/ModuleNotFoundError'; import {run as cliRun} from './cli'; import {options as cliOptions} from './cli/args'; import {findSiblingsWithFileExtension} from './helpers'; @@ -511,18 +510,19 @@ class Runtime { return this.requireModule(from, moduleName); } } catch (e) { - const moduleNotFound = e as ModuleNotFoundError; - if (moduleNotFound.code === 'MODULE_NOT_FOUND') { + const moduleNotFound = Resolver.tryCastModuleNotFoundError(e); + if (moduleNotFound) { if (!moduleNotFound.hint) { moduleNotFound.hint = findSiblingsWithFileExtension( this._config.moduleFileExtensions, from, - moduleName, + moduleNotFound.moduleName || moduleName, ); } moduleNotFound.buildMessage(this._config.rootDir); + throw moduleNotFound; } - throw moduleNotFound; + throw e; } } @@ -1293,8 +1293,8 @@ class Runtime { } private handleExecutionError(e: Error, module: InitialModule): never { - const moduleNotFoundError: ModuleNotFoundError = e as ModuleNotFoundError; - if (moduleNotFoundError.code === 'MODULE_NOT_FOUND') { + const moduleNotFoundError = Resolver.tryCastModuleNotFoundError(e); + if (moduleNotFoundError) { if (!moduleNotFoundError.requireStack) { moduleNotFoundError.requireStack = [module.filename || module.id]; @@ -1304,6 +1304,7 @@ class Runtime { moduleNotFoundError.buildMessage(this._config.rootDir); } + throw moduleNotFoundError; } throw e; From 27628f4ddda4441b6de9fee489c251156588d0e1 Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Tue, 24 Mar 2020 20:09:36 -0300 Subject: [PATCH 20/26] update snapshots --- e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap b/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap index 211fe3b838e1..0ea10ceef1a3 100644 --- a/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap +++ b/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap @@ -36,7 +36,7 @@ FAIL __tests__/index.js 12 | module.exports = () => 'test'; 13 | - at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:525:17) + at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:519:17) at Object.require (index.js:10:1) `; @@ -65,6 +65,6 @@ FAIL __tests__/index.js 12 | module.exports = () => 'test'; 13 | - at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:525:17) + at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:519:17) at Object.require (index.js:10:1) `; From 685d2daeeca7ac976f1d8c39e4c1dce5cea0819e Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Tue, 24 Mar 2020 20:27:10 -0300 Subject: [PATCH 21/26] try to find a sibling with a similar extension only once, when when the error bubles to the original requiring module --- e2e/resolve/__tests__/nope.txt | 0 e2e/resolve/__tests__/resolve.test.js | 9 ++++++++- packages/jest-resolve/src/ModuleNotFoundError.ts | 1 + packages/jest-runtime/src/index.ts | 8 +++++++- 4 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 e2e/resolve/__tests__/nope.txt diff --git a/e2e/resolve/__tests__/nope.txt b/e2e/resolve/__tests__/nope.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/e2e/resolve/__tests__/resolve.test.js b/e2e/resolve/__tests__/resolve.test.js index 7f22635215c5..2186c256a731 100644 --- a/e2e/resolve/__tests__/resolve.test.js +++ b/e2e/resolve/__tests__/resolve.test.js @@ -113,7 +113,14 @@ test('should throw module not found error if the module has dependencies that ca requiresUnexistingModule.js Test7.js __tests__/resolve.test.js - " + + + However, Jest was able to find: + './nope.txt' + + You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node']. + + See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring" `); } }); diff --git a/packages/jest-resolve/src/ModuleNotFoundError.ts b/packages/jest-resolve/src/ModuleNotFoundError.ts index a45f715219ed..064d07c4a9ae 100644 --- a/packages/jest-resolve/src/ModuleNotFoundError.ts +++ b/packages/jest-resolve/src/ModuleNotFoundError.ts @@ -13,6 +13,7 @@ export default class ModuleNotFoundError extends Error { code = 'MODULE_NOT_FOUND'; public hint?: string; public requireStack?: Array; + public siblingWithSimilarExtensionFound?: boolean; public moduleName?: string; private _originalMessage?: string; diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 8d4a0ce8f4e3..39a43443c26c 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -512,12 +512,18 @@ class Runtime { } catch (e) { const moduleNotFound = Resolver.tryCastModuleNotFoundError(e); if (moduleNotFound) { - if (!moduleNotFound.hint) { + if ( + moduleNotFound.siblingWithSimilarExtensionFound === null || + moduleNotFound.siblingWithSimilarExtensionFound === undefined + ) { moduleNotFound.hint = findSiblingsWithFileExtension( this._config.moduleFileExtensions, from, moduleNotFound.moduleName || moduleName, ); + moduleNotFound.siblingWithSimilarExtensionFound = Boolean( + moduleNotFound.hint, + ); } moduleNotFound.buildMessage(this._config.rootDir); throw moduleNotFound; From fcfc5def7a3815c629da84a8866734d2ce728b2a Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Tue, 24 Mar 2020 20:28:17 -0300 Subject: [PATCH 22/26] updated snapshots --- e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap b/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap index 0ea10ceef1a3..d43ffe5dce4f 100644 --- a/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap +++ b/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap @@ -36,7 +36,7 @@ FAIL __tests__/index.js 12 | module.exports = () => 'test'; 13 | - at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:519:17) + at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:540:17) at Object.require (index.js:10:1) `; @@ -65,6 +65,6 @@ FAIL __tests__/index.js 12 | module.exports = () => 'test'; 13 | - at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:519:17) + at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:540:17) at Object.require (index.js:10:1) `; From 5a4eafdb1b79d2f94398a5a42db19e0da184fa35 Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Tue, 24 Mar 2020 20:57:28 -0300 Subject: [PATCH 23/26] updated snapshots --- .../__snapshots__/resolveNoFileExtensions.test.ts.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap index 265cba91eccc..a62a66e69f80 100644 --- a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap +++ b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap @@ -37,6 +37,6 @@ FAIL __tests__/test.js | ^ 9 | - at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:282:11) + at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:296:11) at Object.require (index.js:8:18) `; From 5a805e5a3cf5443cc419e6fd0b796f3c6e3d6a5b Mon Sep 17 00:00:00 2001 From: Marco Scabbiolo Date: Tue, 24 Mar 2020 21:22:56 -0300 Subject: [PATCH 24/26] updated snapshots --- e2e/resolve/__tests__/resolve.test.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/e2e/resolve/__tests__/resolve.test.js b/e2e/resolve/__tests__/resolve.test.js index 2186c256a731..7f22635215c5 100644 --- a/e2e/resolve/__tests__/resolve.test.js +++ b/e2e/resolve/__tests__/resolve.test.js @@ -113,14 +113,7 @@ test('should throw module not found error if the module has dependencies that ca requiresUnexistingModule.js Test7.js __tests__/resolve.test.js - - - However, Jest was able to find: - './nope.txt' - - You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node']. - - See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring" + " `); } }); From b3cb4092ba74844f712036dc50ce2f06010534f2 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Wed, 25 Mar 2020 08:35:14 +0100 Subject: [PATCH 25/26] use .toThrow rather than try-catch in tests --- .../__tests__/undeclared-dependency.test.js | 7 +-- e2e/resolve/__tests__/resolve.test.js | 46 +++++++++---------- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/e2e/pnp/__tests__/undeclared-dependency.test.js b/e2e/pnp/__tests__/undeclared-dependency.test.js index d3706a323f4c..59372ad294a3 100644 --- a/e2e/pnp/__tests__/undeclared-dependency.test.js +++ b/e2e/pnp/__tests__/undeclared-dependency.test.js @@ -7,10 +7,7 @@ */ it('should surface pnp errors', () => { - try { + expect(() => { require('undeclared'); - throw new Error('UNDECLARED_DEPENDENCY should have been thrown'); - } catch (error) { - expect(error.code).toBe('UNDECLARED_DEPENDENCY'); - } + }).toThrow(expect.objectContaining({code: 'UNDECLARED_DEPENDENCY'})); }); diff --git a/e2e/resolve/__tests__/resolve.test.js b/e2e/resolve/__tests__/resolve.test.js index 7f22635215c5..f4bcdd199e73 100644 --- a/e2e/resolve/__tests__/resolve.test.js +++ b/e2e/resolve/__tests__/resolve.test.js @@ -6,6 +6,8 @@ */ 'use strict'; +const dedent = require('dedent'); + let platform; function testRequire(filename) { @@ -100,32 +102,30 @@ test('should require resolve haste mocks correctly', () => { }); test('should throw module not found error if the module has dependencies that cannot be found', () => { - try { + expect(() => { require('Test7'); - throw new Error('Requiring Test7 should have thrown an error'); - } catch (error) { - expect(error.code).toBe('MODULE_NOT_FOUND'); - - expect(error.message).toMatchInlineSnapshot(` - "Cannot find module 'nope' from 'requiresUnexistingModule.js' - - Require stack: - requiresUnexistingModule.js - Test7.js - __tests__/resolve.test.js - " - `); - } + }).toThrow( + expect.objectContaining({ + code: 'MODULE_NOT_FOUND', + message: dedent` + Cannot find module 'nope' from 'requiresUnexistingModule.js' + + Require stack: + requiresUnexistingModule.js + Test7.js + __tests__/resolve.test.js\n + `, + }) + ); }); test('should throw module not found error if the module cannot be found', () => { - try { + expect(() => { require('Test8'); - throw new Error('Requiring Test8 should have thrown an error'); - } catch (error) { - expect(error.code).toBe('MODULE_NOT_FOUND'); - expect(error.message.split('\n')[0]).toBe( - "Cannot find module 'Test8' from 'resolve.test.js'" - ); - } + }).toThrow( + expect.objectContaining({ + code: 'MODULE_NOT_FOUND', + message: "Cannot find module 'Test8' from 'resolve.test.js'", + }) + ); }); From d3340518fef4d27c46c14b9bd7a353cd73e45234 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Wed, 25 Mar 2020 08:42:23 +0100 Subject: [PATCH 26/26] whitespace --- e2e/resolve/__tests__/resolve.test.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/e2e/resolve/__tests__/resolve.test.js b/e2e/resolve/__tests__/resolve.test.js index f4bcdd199e73..bd993a99f8aa 100644 --- a/e2e/resolve/__tests__/resolve.test.js +++ b/e2e/resolve/__tests__/resolve.test.js @@ -102,9 +102,7 @@ test('should require resolve haste mocks correctly', () => { }); test('should throw module not found error if the module has dependencies that cannot be found', () => { - expect(() => { - require('Test7'); - }).toThrow( + expect(() => require('Test7')).toThrow( expect.objectContaining({ code: 'MODULE_NOT_FOUND', message: dedent` @@ -120,9 +118,7 @@ test('should throw module not found error if the module has dependencies that ca }); test('should throw module not found error if the module cannot be found', () => { - expect(() => { - require('Test8'); - }).toThrow( + expect(() => require('Test8')).toThrow( expect.objectContaining({ code: 'MODULE_NOT_FOUND', message: "Cannot find module 'Test8' from 'resolve.test.js'",