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

Show exception stack trace when errors are thrown by plugins of pretty-format #4738

Closed
wants to merge 5 commits into from
Closed
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* `[jest-runtime]` Move `babel-core` to peer dependencies so it works with Babel 7 ([#4557](https://github.com/facebook/jest/pull/4557))
* `[jest-util]` Fix `runOnlyPendingTimers` for `setTimeout` inside `setImmediate` ([#4608](https://github.com/facebook/jest/pull/4608))
* `[jest-message-util]` Always remove node internals from stacktraces ([#4695](https://github.com/facebook/jest/pull/4695))
* `[pretty-format]` Show exception stack trace when errors are thrown by plugins ([#4738](https://github.com/facebook/jest/pull/4738))

### Features
* `[jest-environment-*]` [**BREAKING**] Add Async Test Environment APIs, dispose is now teardown ([#4506](https://github.com/facebook/jest/pull/4506))
Expand Down
51 changes: 51 additions & 0 deletions packages/pretty-format/src/__tests__/pretty_format.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,57 @@ describe('prettyFormat()', () => {
}).toThrow();
});

it('throws the plugin error stack when test throws an error', () => {
const error = new Error();
const options = {
plugins: [
{
print: () => '',
test() {
throw error;
},
},
],
};
expect(() => {
prettyFormat('', options);
}).toThrow(error.stack);
});

it('throws the plugin error stack when print throws an error', () => {
const error = new Error();
const options = {
plugins: [
{
print: () => {
throw error;
},
test: () => true,
},
],
};
expect(() => {
prettyFormat('', options);
}).toThrow(error.stack);
});

it('throws the plugin error stack when serialize throws an error', () => {
const error = new Error();
const options = {
plugins: [
{
serialize: () => {
throw error;
},
test: () => true,
},
],
};
expect(() => {
prettyFormat('', options);
}).toThrow(error.stack);
});

it('supports plugins with deeply nested arrays (#24)', () => {
const val = [[1, 2], [3, 4]];
expect(
Expand Down
53 changes: 32 additions & 21 deletions packages/pretty-format/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,25 +240,32 @@ function printPlugin(
depth: number,
refs: Refs,
): string {
const printed = plugin.serialize
? plugin.serialize(val, config, indentation, depth, refs, printer)
: plugin.print(
val,
valChild => printer(valChild, config, indentation, depth, refs),
str => {
const indentationNext = indentation + config.indent;
return (
indentationNext +
str.replace(NEWLINE_REGEXP, '\n' + indentationNext)
);
},
{
edgeSpacing: config.spacingOuter,
min: config.min,
spacing: config.spacingInner,
},
config.colors,
);
let printed;

try {
printed = plugin.serialize
? plugin.serialize(val, config, indentation, depth, refs, printer)
: plugin.print(
val,
valChild => printer(valChild, config, indentation, depth, refs),
str => {
const indentationNext = indentation + config.indent;
return (
indentationNext +
str.replace(NEWLINE_REGEXP, '\n' + indentationNext)
);
},
{
edgeSpacing: config.spacingOuter,
min: config.min,
spacing: config.spacingInner,
},
config.colors,
);
} catch (error) {
throw new Error(error.stack);
}

if (typeof printed !== 'string') {
throw new Error(
`pretty-format: Plugin must return type "string" but instead returned "${typeof printed}".`,
Expand All @@ -269,8 +276,12 @@ function printPlugin(

function findPlugin(plugins: Plugins, val: any) {
for (let p = 0; p < plugins.length; p++) {
if (plugins[p].test(val)) {
return plugins[p];
try {
if (plugins[p].test(val)) {
return plugins[p];
}
} catch (error) {
throw new Error(error.stack);
}
}

Expand Down