Is there an Array equality match function that ignores element position in jest.js?
Solution 1
There is no built-in method to compare arrays without comparing the order, but you can simply sort the arrays using .sort()
before making a comparison:
expect(["ping wool", "diorite"].sort()).toEqual(["diorite", "pink wool"].sort());
You can check the example in this fiddle.
Solution 2
Put the elements into a set. Jest knows how to match these.
expect(new Set(["pink wool", "diorite"])).toEqual(new Set(["diorite", "pink wool"]));
Solution 3
As already mentioned expect.arrayContaining
checks if the actual
array contains the expected
array as a subset.
To check for equivalence one may
- either assert that the length of both arrays is the same (but that wouldn't result in a helpful failure message)
- or assert the reverse: That the
expected
array contains theactual
array:
// This is TypeScript, but remove the types and you get JavaScript
const expectArrayEquivalence = <T>(actual: T[], expected: T[]) => {
expect(actual).toEqual(expect.arrayContaining(expected));
expect(expected).toEqual(expect.arrayContaining(actual));
};
This still has the problem that when the test fails in the first assertion one is only made aware of the elements missing from actual
and not of the extra ones that are not in expected
.
Solution 4
this does not answer the question exactly, but still may help people that end up here by google search:
if you only care that a subset of the array has certain elements, use expect.arrayContaining()
https://jestjs.io/docs/en/expect#expectarraycontainingarray
e.g.,
expect(["ping wool", "diorite"])
.toEqual(expect.arrayContaining(["diorite", "pink wool"]));
Solution 5
Another way is to use the custom matcher .toIncludeSameMembers()
from jest-community/jest-extended.
Example given from the README
test('passes when arrays match in a different order', () => {
expect([1, 2, 3]).toIncludeSameMembers([3, 1, 2]);
expect([{ foo: 'bar' }, { baz: 'qux' }]).toIncludeSameMembers([{ baz: 'qux' }, { foo: 'bar' }]);
});
It might not make sense to import a library just for one matcher but they have a lot of other useful matchers I've find useful.
Comments
-
Benjamin H Boruff over 2 years
I get that
.toEqual()
checks equality of all fields for plain objects:expect( {"key1":"pink wool","key2":"diorite"} ).toEqual( {"key2":"diorite","key1":"pink wool"} );
So this passes.
But the same is not true for arrays:
expect(["pink wool", "diorite"]).toEqual(["diorite", "pink wool"]);
There does not seem to be a matcher function that does this in the jest docs, i.e. that tests for the equality of two arrays irrespective of their elements positions. Do I have to test each element in one array against all the elements in the other and vice versa? Or is there another way?
-
Andreas Herd over 5 yearsThis will not fail if arrays have additional values. Point was to check of equality.
-
jkondratowicz over 5 yearsThis was introduced in Jest 23.0.0, so won't work with previous versions.
-
Jezzamon over 5 yearsThis will ignore duplicate values, which is probably not what you want.
["a", "a", "b"]
will match["a", "b"]
. -
Avinav about 5 yearsthis will not work if you are working with array of objects. Because the object would be converted to [Object object] and won't be sorted. And your comparison may still fail. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/….
-
Jimmy Kane over 4 yearsDo not use this as duplicate elements are not counted. Avoid before you break your head
-
Zakalwe almost 4 yearsYou can always test the length of the array to ensure that this test matches what is expected rather than a subset of what is expected.
-
Xanlantos over 3 yearsI would highly encourage you to delete this answer as it is in almost every way inferior to the accepted. The only time I could imagine your answer to be better is a case where we have a lot of duplicates and therefore the comparison afterwards could be faster. If that is what you want to say please make it more clear. If not your answer is very misleading and can cause a lot of damage in an application as it looks fine and will work until it doesn't anymore then the damage can be dramatic.
-
Avin Kavish over 3 yearsyeah, I mean you have to provide a suitable comparator to the sort function according to the data type.
-
Davide Rossetto about 3 yearsmore compact way: const sortByKey = (a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0)
-
Gergő Horváth almost 3 yearsBe careful as this - as the name suggests - checks if the array contains the items in the other array. The test will pass if you check if
expect(['a','b']).toEqual(expect.arrayContaining(['a']));
as mentioned in other answers. -
2oppin over 2 yearsbe aware that this solution will work only for arrays with unique values. Try to compare ['pink wool', 'diorite', 'diorite'] with ['pink wool', 'pink wool', 'diorite']
-
ankush981 about 2 yearsWow, so looks like Jest is smart enough to do an item-by-item comparison?