diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d13a1c27a04..8618f3a162ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - `[jest-core]` Fix incorrect `passWithNoTests` warning ([#8595](https://github.com/facebook/jest/pull/8595)) - `[jest-snapshots]` Fix test retries that contain snapshots ([#8629](https://github.com/facebook/jest/pull/8629)) - `[jest-mock]` Fix incorrect assignments when restoring mocks in instances where they originally didn't exist ([#8631](https://github.com/facebook/jest/pull/8631)) +- `[jest-resolve]`: Improve error on module not found ([#8704](https://github.com/facebook/jest/pull/8704) ### Chore & Maintenance diff --git a/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap b/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap index a3759f42c96f..770bef15172e 100644 --- a/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap +++ b/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap @@ -32,4 +32,5 @@ FAIL __tests__/index.js at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:501:17) at Object.require (index.js:10:1) + at Object.require (__tests__/index.js:10:20) `; diff --git a/e2e/__tests__/__snapshots__/requireMissingExt.test.ts.snap b/e2e/__tests__/__snapshots__/requireMissingExt.test.ts.snap new file mode 100644 index 000000000000..2c1802570af1 --- /dev/null +++ b/e2e/__tests__/__snapshots__/requireMissingExt.test.ts.snap @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`shows a proper error from deep requires 1`] = ` +FAIL ./test.js + ● Test suite failed to run + + Cannot find module '../package' from 'node_modules/discord.js/src/index.js' + + However, Jest was able to find: + '../package.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-array-string + + 8 | 'use strict'; + 9 | + > 10 | require('discord.js'); + | ^ + 11 | + 12 | test('dummy', () => { + 13 | expect(1).toBe(1); + + at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:259:17) + at Object. (node_modules/discord.js/src/index.js:21:12) + at Object.require (test.js:10:1) +`; diff --git a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap index 7a66f6098b01..64b8afe59385 100644 --- a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap +++ b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap @@ -35,4 +35,5 @@ FAIL __tests__/test.js at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:259:17) at Object.require (index.js:3:18) + at Object.require (__tests__/test.js:3:11) `; diff --git a/e2e/__tests__/requireMissingExt.test.ts b/e2e/__tests__/requireMissingExt.test.ts new file mode 100644 index 000000000000..a3eb2c264767 --- /dev/null +++ b/e2e/__tests__/requireMissingExt.test.ts @@ -0,0 +1,24 @@ +/** + * 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 path from 'path'; +import wrap from 'jest-snapshot-serializer-raw'; +import {extractSummary, run} from '../Utils'; +import runJest from '../runJest'; + +const dir = path.resolve(__dirname, '../require-missing-ext'); + +beforeEach(() => { + run('yarn', dir); +}); + +test('shows a proper error from deep requires', () => { + const {stderr} = runJest(dir); + const {rest} = extractSummary(stderr); + + expect(wrap(rest)).toMatchSnapshot(); +}); diff --git a/e2e/__tests__/stackTrace.test.ts b/e2e/__tests__/stackTrace.test.ts index a65a73883748..a9a6b1ef275e 100644 --- a/e2e/__tests__/stackTrace.test.ts +++ b/e2e/__tests__/stackTrace.test.ts @@ -78,7 +78,7 @@ describe('Stack Trace', () => { // Make sure we show Jest's jest-resolve as part of the stack trace expect(stderr).toMatch( - /Cannot find module 'this-module-does-not-exist' from 'testError.test\.js'/, + /Cannot find module 'this-module-does-not-exist' from '__tests__\/testError\.test\.js'/, ); expect(stderr).toMatch( diff --git a/e2e/require-missing-ext/package.json b/e2e/require-missing-ext/package.json new file mode 100644 index 000000000000..9a156e8c5f0a --- /dev/null +++ b/e2e/require-missing-ext/package.json @@ -0,0 +1,11 @@ +{ + "jest": { + "moduleFileExtensions": [ + "js" + ], + "testEnvironment": "node" + }, + "dependencies": { + "discord.js": "11.5.1" + } +} diff --git a/e2e/require-missing-ext/test.js b/e2e/require-missing-ext/test.js new file mode 100644 index 000000000000..55370ccafe8f --- /dev/null +++ b/e2e/require-missing-ext/test.js @@ -0,0 +1,14 @@ +/** + * 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. + */ + +'use strict'; + +require('discord.js'); + +test('dummy', () => { + expect(1).toBe(1); +}); diff --git a/e2e/require-missing-ext/yarn.lock b/e2e/require-missing-ext/yarn.lock new file mode 100644 index 000000000000..6db023090213 --- /dev/null +++ b/e2e/require-missing-ext/yarn.lock @@ -0,0 +1,46 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +async-limiter@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== + +discord.js@11.5.1: + version "11.5.1" + resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-11.5.1.tgz#910fb9f6410328581093e044cafb661783a4d9e8" + integrity sha512-tGhV5xaZXE3Z+4uXJb3hYM6gQ1NmnSxp9PClcsSAYFVRzH6AJH74040mO3afPDMWEAlj8XsoPXXTJHTxesqcGw== + dependencies: + long "^4.0.0" + prism-media "^0.0.3" + snekfetch "^3.6.4" + tweetnacl "^1.0.0" + ws "^6.0.0" + +long@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== + +prism-media@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/prism-media/-/prism-media-0.0.3.tgz#8842d4fae804f099d3b48a9a38e3c2bab6f4855b" + integrity sha512-c9KkNifSMU/iXT8FFTaBwBMr+rdVcN+H/uNv1o+CuFeTThNZNTOrQ+RgXA1yL/DeLk098duAeRPP3QNPNbhxYQ== + +snekfetch@^3.6.4: + version "3.6.4" + resolved "https://registry.yarnpkg.com/snekfetch/-/snekfetch-3.6.4.tgz#d13e80a616d892f3d38daae4289f4d258a645120" + integrity sha512-NjxjITIj04Ffqid5lqr7XdgwM7X61c/Dns073Ly170bPQHLm6jkmelye/eglS++1nfTWktpP6Y2bFXjdPlQqdw== + +tweetnacl@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.1.tgz#2594d42da73cd036bd0d2a54683dd35a6b55ca17" + integrity sha512-kcoMoKTPYnoeS50tzoqjPY3Uv9axeuuFAZY9M/9zFnhoVvRfxz9K29IMPD7jGmt2c8SW7i3gT9WqDl2+nV7p4A== + +ws@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== + dependencies: + async-limiter "~1.0.0" diff --git a/packages/jest-environment-node/src/index.ts b/packages/jest-environment-node/src/index.ts index bc82af123b5e..4b469839ea47 100644 --- a/packages/jest-environment-node/src/index.ts +++ b/packages/jest-environment-node/src/index.ts @@ -52,6 +52,9 @@ class NodeEnvironment implements JestEnvironment { global.TextDecoder = TextDecoder; } installCommonGlobals(global, config.globals); + // Node's error-message stack size is limited at 10, but it's pretty useful + // to see more than that when a test fails. + global.Error.stackTraceLimit = 100; this.moduleMocker = new ModuleMocker(global); const timerIdToRef = (id: number) => ({ diff --git a/packages/jest-resolve/src/index.ts b/packages/jest-resolve/src/index.ts index 9e21e5faa806..fedfe7362f72 100644 --- a/packages/jest-resolve/src/index.ts +++ b/packages/jest-resolve/src/index.ts @@ -208,9 +208,9 @@ class Resolver { // 5. Throw an error if the module could not be found. `resolve.sync` only // produces an error based on the dirname but we have the actual current // module name available. - const relativePath = path.relative(dirname, from); + const relativePath = path.relative(this._options.rootDir, from) || '.'; const err: Error & {code?: string} = new Error( - `Cannot find module '${moduleName}' from '${relativePath || '.'}'`, + `Cannot find module '${moduleName}' from '${relativePath}'`, ); err.code = 'MODULE_NOT_FOUND'; throw err; diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index 860105dc99e1..7589813c9c37 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -84,6 +84,9 @@ async function runTestInternal( resolver: Resolver, context?: TestRunnerContext, ): Promise { + // Node's error-message stack size is limited at 10, but it's pretty useful + // to see more than that when a test fails. + Error.stackTraceLimit = 100; const testSource = fs.readFileSync(path, 'utf8'); const docblockPragmas = docblock.parse(docblock.extract(testSource)); const customEnvironment = docblockPragmas['jest-environment'];