Skip to content

Commit

Permalink
feat(jest-message-util): add support for error causes
Browse files Browse the repository at this point in the history
  • Loading branch information
brodo committed Feb 8, 2023
1 parent 5a9870b commit e893b26
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### Features

- `[@jest/core]` Instrument significant lifecycle events with [`performance.mark()`](https://nodejs.org/docs/latest-v16.x/api/perf_hooks.html#performancemarkname-options) ([#13859](https://github.com/facebook/jest/pull/13859))
- `[jest-message-util]` Add support for [error causes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause)

### Fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,18 @@ exports[`should not exclude vendor from stack trace 1`] = `
<dim> <dim>at Object.asyncFn (</intensity><dim>__tests__/vendor/sulu/node_modules/sulu-content-bundle/best_component.js<dim>:1:5)</intensity><dim></intensity>
"
`;
exports[`should return the error cause if there is one 1`] = `
" <bold>● </intensity>Test suite failed to run
Test exception
<dim>at Object.<anonymous> (</intensity>packages/jest-message-util/src/__tests__/messages.test.ts<dim>:418:17)</intensity>
Cause:
Cause Error
<dim>at Object.<anonymous> (</intensity>packages/jest-message-util/src/__tests__/messages.test.ts<dim>:421:17)</intensity>
"
`;
36 changes: 36 additions & 0 deletions packages/jest-message-util/src/__tests__/messages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,3 +413,39 @@ it('getTopFrame should return a path for mjs files', () => {

expect(frame!.file).toBe(expectedFile);
});

it('should return the error cause if there is one', () => {
const error = new Error('Test exception');
// TODO pass `cause` to the `Error` constructor when lowest supported Node version is 16.9.0 and above
// See https://github.com/nodejs/node/blob/main/doc/changelogs/CHANGELOG_V16.md#error-cause
error.cause = new Error('Cause Error');
const message = formatExecError(
error,
{
rootDir: '',
testMatch: [],
},
{
noStackTrace: false,
},
);
expect(message).toMatchSnapshot();
});

it('should print all the errors contained in an AggregateError', () => {
const error = new AggregateError([
new Error('error 1'),
new Error('error 2'),
]);
const message = formatExecError(
error,
{
rootDir: '',
testMatch: [],
},
{
noStackTrace: false,
},
);
console.log(message);
});
29 changes: 26 additions & 3 deletions packages/jest-message-util/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import * as path from 'path';
import {fileURLToPath} from 'url';
import {types} from 'util';
import {codeFrameColumns} from '@babel/code-frame';
import chalk = require('chalk');
import * as fs from 'graceful-fs';
Expand Down Expand Up @@ -122,18 +123,20 @@ function warnAboutWrongTestEnvironment(error: string, env: 'jsdom' | 'node') {
// `before/after each` hooks). If it's thrown, none of the tests in the file
// are executed.
export const formatExecError = (
error: Error | TestResult.SerializableError | string | undefined,
error: Error | TestResult.SerializableError | string | number | undefined,
config: StackTraceConfig,
options: StackTraceOptions,
testPath?: string,
reuseMessage?: boolean,
noTitle?: boolean,
): string => {
if (!error || typeof error === 'number') {
error = new Error(`Expected an Error, but "${String(error)}" was thrown`);
error.stack = '';
}

let message, stack;
let cause = '';

if (typeof error === 'string' || !error) {
error || (error = 'EMPTY ERROR');
Expand All @@ -145,6 +148,25 @@ export const formatExecError = (
typeof error.stack === 'string'
? error.stack
: `thrown: ${prettyFormat(error, {maxDepth: 3})}`;
if ('cause' in error) {
const prefix = '\n\nCause:\n';
if (typeof error.cause === 'string' || typeof error.cause === 'number') {
cause += `${prefix}${error.cause}`;
} else if (types.isNativeError(error.cause)) {
const formatted = formatExecError(
error.cause,
config,
options,
testPath,
reuseMessage,
true,
);
cause += `${prefix}${formatted}`;
}
}
}
if (cause !== '') {
cause = indentAllLines(cause);
}

const separated = separateMessageFromStack(stack || '');
Expand Down Expand Up @@ -174,13 +196,14 @@ export const formatExecError = (

let messageToUse;

if (reuseMessage) {
if (reuseMessage || noTitle) {
messageToUse = ` ${message.trim()}`;
} else {
messageToUse = `${EXEC_ERROR_MESSAGE}\n\n${message}`;
}
const title = noTitle ? '' : `${TITLE_INDENT + TITLE_BULLET}`;

return `${TITLE_INDENT + TITLE_BULLET + messageToUse + stack}\n`;
return `${title + messageToUse + stack + cause}\n`;
};

const removeInternalStackEntries = (
Expand Down

0 comments on commit e893b26

Please sign in to comment.