question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

deepEqual may ignore object's null/undefined properties, by configuration

See original GitHub issue

I think it would be nice to have a chai configuration property to set chai to ignore null or undefined properties on object deepEqual assertion (e.g. chai.config.ignoreNullOrUndefinedProperties = true).

    var objA = {
        foo: 'bar',
        not_relevant: undefined,
        not_serializable: null
    };

    expect(objA).to.eql({foo: 'bar'});
    // false

    expect(JSON.pase(JSON.stringify(objA)).to.eql({foo: 'bar'}));
    // true

This is useful for instance when we want to filter objects’s properties before serialization (e.g REST APIs). These objects may have optional properties set to undefined which won’t be serialized. Example:

  var pick = require('mout/object/pick');
  var USER_FILTER = ['login','company'];

  function filterUser(user) {
    if(!user) return;

    return {
      login: user.login,
      company: user.company,
    };
    // same as: return pick(user, USER_FILTER);
  };

  var usersBD = {
    bob: {
      login: 'bob',
      lastLoggin: '2014-12-27T00:00:00+00:00',
      password: 'some_hash',
    },
    alice: {
      login: 'alice',
      lastLoggin: '2014-12-27T00:00:00+00:00',
      password: 'some_hash',
      company: 'Wonderland'
    }
  };

  //
  //
  expect(filterUser(usersBD['bob'])).to.eql({login: 'bob'});
  // will fail because filterUser(usersBD['bob']) returns
  // {login: 'bob', company: 'udefined'}
  // but since the object will be  serialized to JSON
  // does not matter

  expect(filterUser(usersBD['alice'])).to.eql({
    login: 'alice',
    company: 'Wonderland'
  }); // success

For this simple case scenario, I cloud do something like:

function filterUser(user) {
  if (!user) return;

  var filteredUser = {
    login: user.login
  };

  if (user.company) {
    filteredUser.company = user.company;
  }

  return filteredUser;
};

But sometimes we have several optional properties which will require more verbose code polluted with if statements.

Currently I overcome this with JSON.stringify.

Is this a good feature, does it meet chai purpose?

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Reactions:11
  • Comments:14 (8 by maintainers)

github_iconTop GitHub Comments

3reactions
evtaranovcommented, Apr 21, 2016

+1 I have a similar case to test, where i need to ignore undefined values, because after JSON.parse(JSON.toString(…)) they are lost and deepEqual() return false.

2reactions
keithamuscommented, Oct 31, 2018

Sure @ronjouch! Specifically https://github.com/chaijs/chai/projects/2#card-10444381 and https://github.com/chaijs/chai/projects/2#card-10444260 capture the desired functionality. This is a matcher API which would allow you to pass expectations as properties in a deep-eql assertion, e.g.

expect({ a: 1, b: 2, c: 3 }).to.deep.eql({ a: 1, b: 2, c: expect.to.be.a('number')  }); 

or in the case of the OPs example for a users table you could do something like:

  expect(usersBD['alice']).to.eql({
    login: 'alice',
    password: expect.to.be.a('string').with.lengthOf(40),
    lastLogin: expect.to.be.a('string'),
    company: 'Wonderland'
  }); // success

If you’re looking for an assertion which only tests the existance of some keys, we already have this available. But we think having a matcher API to make more broad assertions on object properties is the right direction here.

Read more comments on GitHub >

github_iconTop Results From Across the Web

node.js - Compare javascript objects with `undefined` attributes?
this will strip out undefined and preserve the other desirable properties of assert.deepEqual and _.isEqual like insensitivity to attribute ...
Read more >
hoek v10.0.1 - hapi.dev
Clones an object or an array. A deep copy is made (duplicates everything, including values that are objects, as well as non-enumerable properties)...
Read more >
Assert | Node.js v19.3.0 Documentation
assert.deepEqual() can have surprising results. Deep equality means that the enumerable "own" properties of child objects are also recursively evaluated by the ...
Read more >
`undefined` vs. `null` revisited - 2ality
It indicates that a variable does not currently point to an object – for example, when it hasn't been initialized yet. In contrast,...
Read more >
Usage - qs - npm
assert.deepEqual(nullObject, { a: { hasOwnProperty: 'b' } });. By default parameters that would overwrite properties on the object prototype ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found