Skip to content

Commit f11c8bb

Browse files
fix: error cause bug (#15339)
Co-authored-by: Simen Bekkhus <[email protected]>
1 parent fdd1a41 commit f11c8bb

File tree

3 files changed

+63
-10
lines changed

3 files changed

+63
-10
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
- `[expect]` Check error instance type for `toThrow/toThrowError` ([#14576](https://github.com/jestjs/jest/pull/14576))
6161
- `[expect]` Improve diff for failing `expect.objectContaining` ([#15038](https://github.com/jestjs/jest/pull/15038))
6262
- `[expect]` Use `Array.isArray` to check if an array is an `Array` ([#15101](https://github.com/jestjs/jest/pull/15101))
63+
- `[expect]` Fix Error `cause` assertion errors ([#15339](https://github.com/jestjs/jest/pull/15339))
6364
- `[jest-changed-files]` Print underlying errors when VCS commands fail ([#15052](https://github.com/jestjs/jest/pull/15052))
6465
- `[jest-changed-files]` Abort `sl root` call if output resembles a steam locomotive ([#15053](https://github.com/jestjs/jest/pull/15053))
6566
- `[jest-circus]` [**BREAKING**] Prevent false test failures caused by promise rejections handled asynchronously ([#14315](https://github.com/jestjs/jest/pull/14315))

packages/expect/src/__tests__/toThrowMatchers.test.ts

+31
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,37 @@ describe('toThrow', () => {
307307
throw new Error('good', {cause: errorA});
308308
}).not.toThrow(expected);
309309
});
310+
311+
test('isNot false, compare Error with object', () => {
312+
jestExpect(() => {
313+
throw errorB;
314+
}).toThrow({
315+
cause: {
316+
message: 'A',
317+
},
318+
message: 'B',
319+
});
320+
});
321+
322+
test('isNot false, cause is string', () => {
323+
jestExpect(() => {
324+
throw new Error('Message', {cause: 'line 123'});
325+
}).toThrow({
326+
cause: 'line 123',
327+
message: 'Message',
328+
});
329+
});
330+
331+
test('isNot false, cause is object', () => {
332+
jestExpect(() => {
333+
throw new Error('Message', {
334+
cause: {prop1: true, prop2: false, prop3: null, prop4: undefined},
335+
});
336+
}).toThrow({
337+
cause: {prop1: true, prop2: false, prop3: null, prop4: undefined},
338+
message: 'Message',
339+
});
340+
});
310341
});
311342

312343
describe('fail', () => {

packages/expect/src/toThrowMatchers.ts

+31-10
Original file line numberDiff line numberDiff line change
@@ -465,22 +465,43 @@ const formatStack = (thrown: Thrown | null) =>
465465
},
466466
);
467467

468-
function createMessageAndCauseMessage(error: Error): string {
469-
if (error.cause instanceof Error) {
470-
return `{ message: ${error.message}, cause: ${createMessageAndCauseMessage(
471-
error.cause,
472-
)}}`;
468+
function createMessageAndCause(error: Error) {
469+
if (error.cause) {
470+
const seen = new WeakSet();
471+
return JSON.stringify(buildSerializeError(error), (_, value) => {
472+
if (isObject(value)) {
473+
if (seen.has(value)) return;
474+
seen.add(value); // stop circular references
475+
}
476+
return value === undefined ? String(undefined) : value;
477+
});
473478
}
474479

475-
return `{ message: ${error.message} }`;
480+
return error.message;
476481
}
477482

478-
function createMessageAndCause(error: Error) {
479-
if (error.cause instanceof Error) {
480-
return createMessageAndCauseMessage(error);
483+
function buildSerializeError(error: {[key: string]: any}) {
484+
if (!isObject(error)) {
485+
return error;
481486
}
482487

483-
return error.message;
488+
const result: {[key: string]: any} = {};
489+
for (const name of Object.getOwnPropertyNames(error).sort()) {
490+
if (['stack', 'fileName', 'lineNumber'].includes(name)) {
491+
continue;
492+
}
493+
if (name === 'cause') {
494+
result[name] = buildSerializeError(error['cause']);
495+
continue;
496+
}
497+
result[name] = error[name];
498+
}
499+
500+
return result;
501+
}
502+
503+
function isObject(obj: unknown) {
504+
return obj != null && typeof obj === 'object';
484505
}
485506

486507
function messageAndCause(error: Error) {

0 commit comments

Comments
 (0)