Chai: deep.equal assetion between function?

Created on 4 May 2016  路  2Comments  路  Source: chaijs/chai

When I try to use deep.equal assertion between function

expect(() => {}).to.deep.equal(() => {});

I got a AssertionError

AssertionError: expected [Function] to deeply equal [Function]
+ expected - actual

Is this a expected behavior? When not just use .toString() to compare between functions?

> (() => {}).toString()
'() => {}'

Most helpful comment

This just had me waste two days on failing tests. This should be explicitly called out on the docs, it's easy to slide right past the implications. :(

All 2 comments

Hey @chentsulin thanks for the issue.

I have two points to make on this:

  1. Deep equal is designed to compare _deeply_ not _loosely_, if that makes sense. In other words, it is designed to traverse the keys of an object or array (and soon iterables) and compare the values of those properties with each other. Importantly, when it gets to a value that isn't an iterable, array, or object, it actually uses a stricter-than-strict equality comparison (it uses SameValue). Functions are not iterables, they have no keys which could make a good quality comparison, and as such are given the SameValue treatment.
  2. As an extra convenience, it also compares Regular Expressions (because if their String representation then they have identical behaviours) and Dates (because if their numeric representation is identical then they are identical dates). Functions, however, are much more nuanced and possibly too difficult to compare like this. For example:
// Are these the same?
const foo = (x) => x;
const bar = (x) => { return x };
function baz(x) { return x }

// They have the same behaviours but different string representations
foo.toString() === 'function (x) => x'
bar.toString() === 'function (x) => { return x }'
baz.toString() === 'function baz(x) { return x }'

// Are these the same?
const foo = (x) => {
  // foo
  return x;
}
const bar = (x) => {
  // bar
  return x;
}

// They also are identical in behaviour, but return different strings:
foo.toString() === '(x) => {\n  // foo\n  return x;\n}';
bar.toString() === '(x) => {''n  // bar\n  return x;\n}';

Hopefully this illustrates the minefield that would be comparing functions by source. If a function has the same source, it is likely the same reference.

However, I'm going to go on a hunch and suggest you take a look at #644 which might solve the problems you're having in your tests. We will eventually have a matcher API whereby you can make loose assertions inside deep.equal, including on functions.

I'll close this issue - because I'm pretty sure you want #644. If not, then I think realistically we won't support loose equality on functions because of the above 2 points. Feel free to continue the discussion here, or in #644 if you have ideas there.

This just had me waste two days on failing tests. This should be explicitly called out on the docs, it's easy to slide right past the implications. :(

Was this page helpful?
0 / 5 - 0 ratings

Related issues

danthegoodman picture danthegoodman  路  3Comments

endymion00 picture endymion00  路  3Comments

kharandziuk picture kharandziuk  路  4Comments

huaguzheng picture huaguzheng  路  3Comments

ghost picture ghost  路  4Comments