Chai: Deep equal with sorted keys in an object.

Created on 4 Nov 2017  路  9Comments  路  Source: chaijs/chai

Is there a way to perform a deep equal to check if the keys are in a defined order?
example:

let a = {
   a: 1,
   b: {
     a: {
        a: 1,
        b: 1
      }
    }
};

let b = {
  b: {
    a: {
      b: 1
      a: 1,
    }
  },
  a: 1
};

Here a is equal to b as they have the same properties.
But since they are not in the given order, i would like for the test to fail.

Most helpful comment

I think deep.ordered.keys sounds like a fantastic assertion to add!

All 9 comments

@pratishshr I don't think there's currently a way to do that with a single assertion. If you only care about the ordering of the parent object's properties, you could do something like this:

expect(a).to.deep.equal(b);
expect(Object.keys(a)).to.deep.equal(Object.keys(b));

@pratishshr

Is there a need to rely on the order of the keys in a JSON object?
Are you trying to model an ordered dict behaviour here?

@samarth Yes I was writing a utility to sort the object keys in a given order.

I ended up writing this function to concatenate the keys and testing the array instead.

/**
 * Traverse object to get the concatenated keys.
 * 
 * @example
 * getDeepKeys({a: {a: 1}, b: 2}) => ['a.a', 'b']
 * 
 * @param {Object} obj 
 */
function getDeepKeys(obj) {
  let keys = [];

  for (let [key, value] of Object.entries(obj)) {
    keys.push(key);

    if (isObject(value)) {
      let subkeys = getDeepKeys(obj[key]);
      keys = keys.concat(subkeys.map(subkey => key + '.' + subkey));
    }
  }

  return keys;
}
expect(getDeepKeys(input)).to.have.ordered.members(getDeepKeys(sortedOutput));

@ancmikesmullin unfortunately this is no longer true. The ES6 and above specs specify that keys are ordered by creation order.

@keithamus nice 馃憤
So, will chai support testing for sorted keys in any of its future releases?

I was thinking about this earlier today and I agree about adding an assertion for it given the reasonable amount of code people would have to write in order to do that kind of test.

I'm just concerned about making the API look good and reusable.

Do you have any suggestions on what it should look like?

I was thinking about something like:

// This would test against an array or an object
expect(myObject).to.have.deep.ordered.keys(orderedKeysArrOrObj)

I think deep.ordered.keys sounds like a fantastic assertion to add!

Hey @pratishshr thanks for the issue.

We've added this to our Roadmap https://github.com/chaijs/chai/projects/2! We'll be releasing chai 5 soon, but for now I'll close this issue because it is tracked on our roadmap.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

meeber picture meeber  路  3Comments

JuHwon picture JuHwon  路  5Comments

domenic picture domenic  路  4Comments

jockster picture jockster  路  4Comments

basherr picture basherr  路  4Comments