Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve message/stack parsing for Babel code frame errors #7319

Merged
merged 1 commit into from
Nov 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 2 additions & 4 deletions e2e/__tests__/__snapshots__/expect-async-matcher.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is worse? I dunno.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nah, this is better 🙂 more closely matches the sync matcher


Error: Expected value to have length:
2
Received:
1
Expand All @@ -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
Expand Down
4 changes: 1 addition & 3 deletions e2e/__tests__/__snapshots__/failures.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ exports[`not throwing Error objects 2`] = `
"FAIL __tests__/throw_string.test.js
● Test suite failed to run

Error

banana
banana

"
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ exports[`formatStackTrace should strip node internals 1`] = `
"
`;

exports[`retains message in babel code frame error 1`] = `
"<bold><red> <bold>● <bold>Babel test</></>


packages/react/src/forwardRef.js: Unexpected token, expected , (20:10)
<dim></>
<dim> </> <gray> 18 | </> <cyan>false</><yellow>,</></>
<dim> <gray> 19 | </> <green>'forwardRef requires a render function but received a \`memo\` '</> </>
<dim> <red><bold>><dim></><gray> 20 | </> <green>'component. Instead of forwardRef(memo(...)), use '</> <yellow>+</></>
<dim> <gray> | </> <red><bold>^<dim></></>
<dim> <gray> 21 | </> <green>'memo(forwardRef(...)).'</><yellow>,</></>
<dim> <gray> 22 | </> )<yellow>;</></>
<dim> <gray> 23 | </> } <cyan>else</> <cyan>if</> (<cyan>typeof</> render <yellow>!==</> <green>'function'</>) {</></>
"
`;

exports[`should exclude jasmine from stack trace for Unix paths. 1`] = `
"<bold><red> <bold>● <bold>Unix test</></>

Expand Down
33 changes: 33 additions & 0 deletions packages/jest-message-util/src/__tests__/messages.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(
[
Expand Down Expand Up @@ -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();
});
20 changes: 12 additions & 8 deletions packages/jest-message-util/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) =>
Expand Down Expand Up @@ -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};
};
2 changes: 1 addition & 1 deletion packages/jest-runtime/src/script_transformer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down