29

What I'd like to do is compare 2 arrays of primitives using chai.js, but without considering the order of elements - like if they were 2 sets.

Now obviously I can do something like this:

const actual = ['a', 'b', 'c'];
const expected = ['b', 'c', 'a'];
expect(actual).to.have.length(expected.length);
expected.forEach(e => expect(actual).to.include(e));

But I'm curious if there is a prefered 'built in' way of doing this (I couldn't find it in the docs).

Balázs Édes
  • 13,452
  • 6
  • 54
  • 89
  • without the order it's tricky in arrays... your code should be able to differ `["a", "b" ,"c" ,"b"]` and `["a", "c", b", "c"]` – Redu Jun 07 '16 at 19:59

3 Answers3

45

You can use the built in check 'members':

expect([4, 2]).to.have.members([2, 4])

AncientSwordRage
  • 7,086
  • 19
  • 90
  • 173
Delapouite
  • 9,469
  • 5
  • 36
  • 41
  • Very good, thanks, this is exactly what I have been looking for. – Balázs Édes Jun 07 '16 at 20:05
  • 1
    This does not rule out superfluous elements, so it technically does not answer the question. This is why I gave -1 here. – Jonathan Scholbach Jan 10 '22 at 10:17
  • 1
    For an array of objects, `to.include.deep.members()` works. – David Jul 25 '22 at 19:56
  • @JonathanScholbach that is not true, or at least not in the current version of chai. From the linked docs: "By default, both arrays must be the same size. Add .include earlier in the chain to require that the target’s members be a superset of the expected members." – Danilo Bargen Jan 10 '23 at 13:46
  • I am not sure whether this changed during chai updates. But `expect([1, 2, 2]).to.have.members([1, 1, 2])` is still an edge case uncovered by the answer. – Jonathan Scholbach Jan 10 '23 at 19:25
17

Answers above expect([4, 2]).to.have.members([2, 4]) won't check the size as author mentioned about. expect([1,2,2]).to.have.members([1,2]) will pass the test.

The best option is to use https://www.chaijs.com/plugins/deep-equal-in-any-order/

  • 1
    You can additionally assert that the length matches. Which ensures that exactly the members you expect are in the array. – Narretz Aug 25 '21 at 16:35
  • @Narretz , yes and It requires one extra check, so deep equal in order is one raw instead of two or extra code .and – Вячеслав Гордиевский Aug 26 '21 at 17:44
  • That is not the case, at least not in the current version of Chai. From the docs (https://www.chaijs.com/api/bdd/#method_members): "By default, both arrays must be the same size. Add .include earlier in the chain to require that the target’s members be a superset of the expected members." – Danilo Bargen Jan 10 '23 at 13:46
3

You can use the members assertion from chai BDD.

var mocha = require('mocha');
var should = require('chai').should();

let a = ['a', 'b', 'c'];
let b = ['c', 'a', 'b'];
let c = ['d', 'e', 'c', 'b'];

describe('test members', function() {
    it('should pass', function() {
        a.should.have.members(b);
    });

    it('should fail', function() {
        a.should.not.have.members(c);
    });
});
peteb
  • 18,552
  • 9
  • 50
  • 62