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 3d3c18a
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
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
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
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
Expand Up @@ -16,6 +16,7 @@ import StackUtils = require('stack-utils');
import type {Config, TestResult} from '@jest/types';
import {format as prettyFormat} from 'pretty-format';
import type {Frame} from './types';
import {types} from 'util';

export type {Frame} from './types';

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 3d3c18a

Please sign in to comment.