-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
this.equals not available in custom matcher #8295
Comments
The custom matcher that you provide as argument to The built-in asymmetric matchers include However, If Can you write the assertion in a way that you don’t need to embed the custom matcher? For example, access the property path to get to the received value for custom matcher assertion: const received = val.key.path;
expect(received).customMatcher(expected); If you can give an example closer to your use case (without revealing propriety info) we might be able to give a more specific suggestion. |
Thanks for the elaborate response @pedrottimark. I see that I mixed up asymmetric and custom matchers. I made a concrete example for matching JSON encoded data with both a custom and a asymmetric matcher: const diff = require('jest-diff');
const { equals } = require('expect/build/jasmineUtils');
expect.extend({
toBeJson(received, expected) {
const options = {
comment: 'Object.is equality',
isNot: this.isNot,
promise: this.promise,
};
const pass = this.equals(JSON.parse(received), expected);
return {
pass,
message: () => {
if (pass) {
return this.utils.matcherHint('toBeJson', undefined, undefined, options) +
'\n\n' +
`Expected: ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(received)}`;
}
const difference = diff(expected, received, {
expand: this.expand,
});
return (
this.utils.matcherHint('toBeJson', undefined, undefined, options) +
'\n\n' +
(difference && difference.includes('- Expect')
? `Difference:\n\n${diffString}`
: `Expected: ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(received)}`)
);
},
};
}
});
class JsonMatching {
constructor(expected) {
this.expected = expected;
}
asymmetricMatch(received) {
return equals(JSON.parse(received), this.expected);
}
toString() {
return `JsonMatching`;
}
}
const jsonMatching = expected => new JsonMatching(expected);
test('custom matcher success', () => {
expect('{}').toBeJson({});
expect('{"foo":"bar"}').toBeJson({foo:'bar'});
});
test('custom matcher fail', () => {
expect('{"foo":"bar"}').toBeJson({foo:'baz'});
});
test('asymmetric matcher success', () => {
expect({ foo: 'bar', body: '{}' }).toEqual({
foo: 'bar',
body: jsonMatching({}),
});
expect({ foo: 'bar', body: '{"foo":"bar"}' }).toEqual({
foo: 'bar',
body: jsonMatching({
foo: 'bar',
}),
});
});
test('asymmetric matcher fail', () => {
expect({ foo: 'bar', body: '{"foo":"bar"}' }).toEqual({
foo: 'baz',
body: jsonMatching({
foo: 'baz',
}),
});
}); So I would still need to access Is there cleaner way to build an asymmetric matcher and be able to use |
Your example of requiring into the package is at the cutting edge of what is possible. It reminds me of Seriously I knew but had forgotten that Your example is very interesting to me, because a looong-term goal has been to compute a “data-driven diff” for the report after a deep equality assertion fails, to solve some problems with a diff of serialized data (for example, distracting bogus difference for expected asymmetric matcher that passes and the corresponding received value). Not sure, but good to think if there is any way to provide extension points for custom matchers, user-defined asymmetric matchers, and user-defined snapshot serializers. A parting comment is to compare the cost and benefit of alternatives:
In this particular case, I would be interested to know if either alternative is better or worse to trouble-shoot if |
I'm aware that I'm not supposed to require into the package. I'm merely trying to show why I would like to be able to use
Currently if the asymmetric matcher fails, I don't have any way to return a message with a pretty diff to show what caused it to fail. If this were a possibility, it would be easy to catch errors parsing JSON and showing that in the resulting error message. |
Please forgive me for teasing. I needed a reminder that I can do that to experiment and trouble shoot. You make an important point about limitation of (even built-in) asymmetric matchers to return the reason for failure. That is why I am thankful for your realistic example to stretch my thinking about what a more complete API would need to support. Would you like me to include a mention of your user name in relevant future issues or pull requests, so you can follow and influence our attempts to improve assertions in Jest? |
Sure! |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
🐛 Bug Report
Depending on how a custom matcher is used,
this.equals
might not be defined:To Reproduce
Steps to reproduce the behavior:
Note that I added a
console.debug()
statement because the message from the custom matcher is not actually shown (as discussed in #7492).Expected behavior
I'd expect
this.equals
to be defined in both invocations.Run
npx envinfo --preset jest
The text was updated successfully, but these errors were encountered: