diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a9eeb537f3c..4bc906e72563 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,8 @@ - `[expect]` Improves the failing message for `toStrictEqual` matcher. ([#7224](https://github.com/facebook/jest/pull/7224)) - `[jest-mock]` [**BREAKING**] Fix bugs with mock/spy result tracking of recursive functions ([#6381](https://github.com/facebook/jest/pull/6381)) - `[jest-resolve]` Fix not being able to resolve path to mapped file with custom platform ([#7312](https://github.com/facebook/jest/pull/7312)) +- `[jest-message-util]` Improve parsing of error messages for unusually formatted stack traces ([#7319](https://github.com/facebook/jest/pull/7319)) +- `[jest-runtime]` Ensure error message text is not lost on errors with code frames ([#7319](https://github.com/facebook/jest/pull/7319)) ### Chore & Maintenance diff --git a/e2e/__tests__/__snapshots__/expect-async-matcher.test.js.snap b/e2e/__tests__/__snapshots__/expect-async-matcher.test.js.snap index 2b179d34966a..21c961f43033 100644 --- a/e2e/__tests__/__snapshots__/expect-async-matcher.test.js.snap +++ b/e2e/__tests__/__snapshots__/expect-async-matcher.test.js.snap @@ -9,9 +9,8 @@ exports[`shows the correct errors in stderr when failing tests 1`] = ` ● fail with expected non promise values - Error + Expected value to have length: - Error: Expected value to have length: 2 Received: 1 @@ -20,9 +19,8 @@ exports[`shows the correct errors in stderr when failing tests 1`] = ` ● fail with expected non promise values and not - Error + Expected value to not have length: - Error: Expected value to not have length: 2 Received: 1,2 diff --git a/e2e/__tests__/__snapshots__/failures.test.js.snap b/e2e/__tests__/__snapshots__/failures.test.js.snap index 274061f1e37b..ab3f4c76b947 100644 --- a/e2e/__tests__/__snapshots__/failures.test.js.snap +++ b/e2e/__tests__/__snapshots__/failures.test.js.snap @@ -13,9 +13,7 @@ exports[`not throwing Error objects 2`] = ` "FAIL __tests__/throw_string.test.js ● Test suite failed to run - Error - - banana + banana " `; diff --git a/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.js.snap b/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.js.snap index a39921bd1894..4cf7e417890e 100644 --- a/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.js.snap +++ b/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.js.snap @@ -22,6 +22,22 @@ exports[`formatStackTrace should strip node internals 1`] = ` " `; +exports[`retains message in babel code frame error 1`] = ` +" Babel test + + + packages/react/src/forwardRef.js: Unexpected token, expected , (20:10) + + 18 | false, + 19 | 'forwardRef requires a render function but received a \`memo\` ' + > 20 | 'component. Instead of forwardRef(memo(...)), use ' + + | ^ + 21 | 'memo(forwardRef(...)).', + 22 | ); + 23 | } else if (typeof render !== 'function') { +" +`; + exports[`should exclude jasmine from stack trace for Unix paths. 1`] = ` " Unix test diff --git a/packages/jest-message-util/src/__tests__/messages.test.js b/packages/jest-message-util/src/__tests__/messages.test.js index 6f8c9964e0c6..0a2078ca299c 100644 --- a/packages/jest-message-util/src/__tests__/messages.test.js +++ b/packages/jest-message-util/src/__tests__/messages.test.js @@ -58,6 +58,19 @@ const vendorStack = at Object.asyncFn (__tests__/vendor/sulu/node_modules/sulu-content-bundle/best_component.js:1:5) `; +const babelStack = + ' ' + + ` + packages/react/src/forwardRef.js: Unexpected token, expected , (20:10) + \u001b[0m \u001b[90m 18 | \u001b[39m \u001b[36mfalse\u001b[39m\u001b[33m,\u001b[39m + \u001b[90m 19 | \u001b[39m \u001b[32m'forwardRef requires a render function but received a \`memo\` '\u001b[39m + \u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 20 | \u001b[39m \u001b[32m'component. Instead of forwardRef(memo(...)), use '\u001b[39m \u001b[33m+\u001b[39m + \u001b[90m | \u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m + \u001b[90m 21 | \u001b[39m \u001b[32m'memo(forwardRef(...)).'\u001b[39m\u001b[33m,\u001b[39m + \u001b[90m 22 | \u001b[39m )\u001b[33m;\u001b[39m + \u001b[90m 23 | \u001b[39m } \u001b[36melse\u001b[39m \u001b[36mif\u001b[39m (\u001b[36mtypeof\u001b[39m render \u001b[33m!==\u001b[39m \u001b[32m'function'\u001b[39m) {\u001b[0m +`; + it('should exclude jasmine from stack trace for Unix paths.', () => { const messages = formatResultsErrors( [ @@ -134,3 +147,23 @@ it('should not exclude vendor from stack trace', () => { expect(messages).toMatchSnapshot(); }); + +it('retains message in babel code frame error', () => { + const messages = formatResultsErrors( + [ + { + ancestorTitles: [], + failureMessages: [babelStack], + title: 'Babel test', + }, + ], + { + rootDir: '', + }, + { + noStackTrace: false, + }, + ); + + expect(messages).toMatchSnapshot(); +}); diff --git a/packages/jest-message-util/src/index.js b/packages/jest-message-util/src/index.js index 1f8f4d5f62ba..c09af5c3f84f 100644 --- a/packages/jest-message-util/src/index.js +++ b/packages/jest-message-util/src/index.js @@ -62,7 +62,6 @@ const TITLE_BULLET = chalk.bold('\u25cf '); const STACK_TRACE_COLOR = chalk.dim; const STACK_PATH_REGEXP = /\s*at.*\(?(\:\d*\:\d*|native)\)?/; const EXEC_ERROR_MESSAGE = 'Test suite failed to run'; -const ERROR_TEXT = 'Error: '; const NOT_EMPTY_LINE_REGEXP = /^(?!$)/gm; const indentAllLines = (lines: string, indent: string) => @@ -335,13 +334,18 @@ export const separateMessageFromStack = (content: string) => { return {message: '', stack: ''}; } - const messageMatch = content.match(/(^(.|\n)*?(?=\n\s*at\s.*\:\d*\:\d*))/); - let message = messageMatch ? messageMatch[0] : 'Error'; - const stack = messageMatch ? content.slice(message.length) : content; - // If the error is a plain error instead of a SyntaxError or TypeError - // we remove it from the message because it is generally not useful. - if (message.startsWith(ERROR_TEXT)) { - message = message.substr(ERROR_TEXT.length); + // All lines up to what looks like a stack -- or if nothing looks like a stack + // (maybe it's a code frame instead), just the first non-empty line. + // If the error is a plain "Error:" instead of a SyntaxError or TypeError we + // remove the prefix from the message because it is generally not useful. + const messageMatch = content.match( + /^(?:Error: )?([\s\S]*?(?=\n\s*at\s.*\:\d*\:\d*)|\s*.*)([\s\S]*)$/, + ); + if (!messageMatch) { + // For flow + throw new Error('If you hit this error, the regex above is buggy.'); } + const message = messageMatch[1]; + const stack = messageMatch[2]; return {message, stack}; }; diff --git a/packages/jest-runtime/src/script_transformer.js b/packages/jest-runtime/src/script_transformer.js index 96014c5ba088..a25683156afd 100644 --- a/packages/jest-runtime/src/script_transformer.js +++ b/packages/jest-runtime/src/script_transformer.js @@ -329,7 +329,7 @@ export default class ScriptTransformer { }; } catch (e) { if (e.codeFrame) { - e.stack = e.codeFrame; + e.stack = e.message + '\n' + e.codeFrame; } if (