Chai: deep.equal() and deep.include() doesn't work with Error

Created on 26 Jul 2017  路  6Comments  路  Source: chaijs/chai

deep.equal() and deep.include() doesn't compare the object keys as I expect it to. I found the issue when upgrading to v4 as the deep.equal() works fine in v3.5. It stopped working in v4+.

Here is a code to confirm the issue: https://jsfiddle.net/wLzrucae/3/.

I tried adding error to the allowed types for include() assertion, but it still failed on comparison. Any ideas?

bug

Most helpful comment

I've had the same issue with .deep.include when updating Chai to v4.

Real code (GitHub diff): link does not pass _.expectTypes because of custom @@toStringTag.

Simplified example:

expect({ a: 1 }).to.include({ a: 1 }) // pass
expect({ a: 1, [Symbol.toStringTag]: "foo" }).to.include({ a: 1 }) // fail

I believe we should not special-case Error, but make this branch work for all objects (expect for arrays/collections of course), regardless of what Object#toString returns.

All 6 comments

Thanks for the issue @marian-r.

The behavior of deep.equal is expected. The deep equality algorithm was rewritten for v4. Error objects are now checked for referential equality (per #608). That issue goes into detail, but essentially it was decided that if two Error objects have different stack traces, then they're not deeply equal.

The behavior of deep.include is a bug. The .include assertion should accept any object, including Error objects. The fix isn't as straightforward as adding error to the _.expectTypes check, but it is fixable.

@meeber does this fixes it?

  function include (val, msg) {
    if (msg) flag(this, 'message', msg);

    _.expectTypes(this, [
      'array', 'error', 'object', // added error here
      'string', 'map', 'set',
      'weakset'
    ]);

    var obj = flag(this, 'object')
      , objType = _.type(obj).toLowerCase();

    // This block is for asserting a subset of properties in an object.
    if (objType === 'object' || objType === 'error') { // added error here
      var props = Object.keys(val)
        , negate = flag(this, 'negate')
        , firstErr = null
        , numErrs = 0;
....
....

@vieiralucas Yup that fixes the problem for error objects. I'm just wondering if the way we're using type-detect here will cause problems for other types of objects, particularly custom objects.

I've had the same issue with .deep.include when updating Chai to v4.

Real code (GitHub diff): link does not pass _.expectTypes because of custom @@toStringTag.

Simplified example:

expect({ a: 1 }).to.include({ a: 1 }) // pass
expect({ a: 1, [Symbol.toStringTag]: "foo" }).to.include({ a: 1 }) // fail

I believe we should not special-case Error, but make this branch work for all objects (expect for arrays/collections of course), regardless of what Object#toString returns.

@meeber thanks and sorry I haven't seen notifications before. I will try the fix tomorrow.

@meeber I confirm that the fix for .include() works. Thanks 馃憤

Was this page helpful?
0 / 5 - 0 ratings

Related issues

andipavllo picture andipavllo  路  3Comments

JuHwon picture JuHwon  路  5Comments

huaguzheng picture huaguzheng  路  3Comments

sverrirs picture sverrirs  路  3Comments

meeber picture meeber  路  4Comments