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

Allow deepEqual to use a custom comparator #1520

Closed
forty opened this issue May 30, 2023 · 6 comments
Closed

Allow deepEqual to use a custom comparator #1520

forty opened this issue May 30, 2023 · 6 comments
Milestone

Comments

@forty
Copy link
Contributor

forty commented May 30, 2023

deep-eql, the underlying library doing deep equality supports passing a custom comparator https://github.com/chaijs/deep-eql/blob/main/index.js#L87

Exposing it in chai would be super useful. This idea has been mentioned in several comments (especially on issue about loose equality, which is one use case for it) for example #644 (comment) (2016) but I did not find a proper ticket for it.

Syntax:

expect({a: 1}).to.eql({b: 2}, 'nooo why fail??', comparator);
expect({a: 1}, 'nooo why fail??').to.eql({b: 2}, comparator);
// maybe
expect({a: 1}, 'nooo why fail??').usingComparator(comparator).to.eql({b: 2});

// assert style
 assert.deepEqual({ tea: 'green' }, { tea: 'green' }, comparator);

Example use case: interval

const comparator = (left, right) => {
   if(right && typeof right == 'object' && typeof right.__interval' === 'number' && typeof right.__value === number){
      // right is of the form {__value: 100, __interval: 5}, use custom comparison
      if(typeof left !== 'number){
         return false;
      } else {
         return Math.abs(right.__value - left) < right.__interval
      } 
   } else {
      return null; // use default comparison
   }
}
assert.deepEqual({ amount: 103}, { amount: {__value: 100, __interval: 5} }, comparator);

(ugly example to make it clear how that would work, but it'd certainly be more elegant with an IntervalComparison class for example which would work the same)

@forty
Copy link
Contributor Author

forty commented May 30, 2023

I had a quick look at the code, and unless I'm mistaken, that doesn't seem horribly hard to do (but I only looked very quickly tbh), at least for the simple expect and assert syntax (which to be frank is all that matters to me, I hate.expect.syntax.with.a.passion but from my understanding of the code, the easiest is to implement it for both interfaces anyway)

@forty
Copy link
Contributor Author

forty commented May 30, 2023

One step further (or maybe it'd be the first step as it doesn't involve changing the API) could be to be able to change the default comparator

chai.config.defaultComparator = comparator;

which would be even more useful

@keithamus keithamus added this to the 5.0 milestone Jul 22, 2023
@koddsson
Copy link
Member

koddsson commented Nov 2, 2023

Hey @forty; I'm not sure if we're able to land this in 5.0 but I think we can do this in a way that it's not a breaking change so it could be done in a minor version after 5.0.

A pull request with this feature would help tremendously but otherwise it's just a matter of time until someone has the time to pick this up to work on.

@forty
Copy link
Contributor Author

forty commented Nov 10, 2023

@koddsson thank you for you answer. I just pushed a MR to implement this on the 5.x.x branch. Thanks in advance for your feedback.

@koddsson
Copy link
Member

I think we can close this now that the linked PR is merged? Feel free to re-open if not.

@olsonpm
Copy link

olsonpm commented Jul 1, 2024

This seems useful but the docs don't mention this functionality. Is that being considered in a separate PR ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants