Skip to content
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 @@ -6,6 +6,7 @@

### Fixes

- `[expect, @jest/expect-utils]` `toThrow` should handle custom `Error` classes ([#13607](https://github.com/facebook/jest/pull/13607))
- `[@jest/expect-utils]` `toMatchObject` should handle `Symbol` properties ([#13639](https://github.com/facebook/jest/pull/13639))
- `[jest-resolve]` Add global paths to `require.resolve.paths` ([#13633](https://github.com/facebook/jest/pull/13633))

Expand Down
4 changes: 3 additions & 1 deletion packages/expect-utils/src/jasmineUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ function eq(
}

if (a instanceof Error && b instanceof Error) {
return a.message == b.message;
// Compare just error messages only if not strict check
if (!strictCheck) return a.message == b.message;
if (a.message != b.message) return false;
Copy link
Member

Choose a reason for hiding this comment

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

this seems somewhat odd to me - should we stop comparing Errors unless their message matches? Is the thought that we want to treat that as any other objects?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With the previous implementation, the discriminant determining Errors equality was only the message field.
With this implementation, you compare only the messages for non-strict equality, and you treat the two objects as any other object for strict equality checks.

It probably depends on how you think strict equality should be intended for Error objects.

}

if (Object.is(a, b)) {
Expand Down
39 changes: 39 additions & 0 deletions packages/expect/src/__tests__/matchers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2334,3 +2334,42 @@ describe('toMatchObject()', () => {
});
});
});

describe('Error match', () => {
// Issue 13604
class CustomError extends Error {
constructor(message, otherField) {
super(message);
this.otherField = otherField;
}
}

class CustomObject {
constructor(someField) {
this.someField = someField;
}
}

it('custom error strict equality', () => {
jestExpect(new CustomError('message1', 'value1')).toStrictEqual(
new CustomError('message1', 'value1'),
);
jestExpect(new CustomError('message1', 'value1')).not.toStrictEqual(
new CustomError('message2', 'value1'),
);
jestExpect(new CustomError('message1', 'value1')).not.toStrictEqual(
new CustomError('message2', 'value2'),
);
jestExpect(new CustomError('message1', 'value1')).not.toStrictEqual(
new CustomError('message1', 'value2'),
);
});

it('throw custom object not extending Error', () => {
const fn = () => {
throw new CustomObject('value');
};

jestExpect(fn).toThrow(new CustomObject('value'));
});
});
6 changes: 4 additions & 2 deletions packages/expect/src/toThrowMatchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

/* eslint-disable local/ban-types-eventually */

import {isError} from '@jest/expect-utils';
import {equals, isError, iterableEquality} from '@jest/expect-utils';
import {
EXPECTED_COLOR,
MatcherHintOptions,
Expand Down Expand Up @@ -225,7 +225,9 @@ const toThrowExpectedObject = (
thrown: Thrown | null,
expected: Error,
): SyncExpectationResult => {
const pass = thrown !== null && thrown.message === expected.message;
const pass =
thrown !== null &&
equals(thrown.value, expected, [iterableEquality], !thrown.isError);

const message = pass
? () =>
Expand Down