'Jest: test that an array contains none of these values?

I want to verify that a given array doesn't contain any of a list of values. There is expect.arrayContaining but I don't get how it is supposed to be used for this.

See this example:

expect(["1", "2", "3"]).not.toEqual(expect.arrayContaining(["3"])

This test fails which is the expected behavior. I want to verify that "3" is not included in the array. Everything fine.

However, now I have multiple values for which I want the test to fail if the array contains any of them.

expect(["1", "2", "3"]).not.toEqual(expect.arrayContaining(["3", "4"])

This test does not fail even though I would expect it to fail because the array contains the "3".

What I could do is this:

expect(["1", "2", "3"]).not.toEqual(expect.arrayContaining(["3"])
expect(["1", "2", "3"]).not.toEqual(expect.arrayContaining(["4"])
...

But having to repeat the whole expect line for every single value doesn't seem to be the right way. Especially when arrayContaining takes an array as argument while it looks like you can only pass it a single value to be useful.

I'm sure there are valid use-cases for this behavior but I'm asking how I can implement by use-case in a more concise way. Basically, I want the test to fail as soon as the array contains one or more values of the second array. Sort of a "blacklist".



Solution 1:[1]

Instead of trying to get Jest to check whether your arrays intersect, I'd instead create a small function to check that and then apply an assertion on the result e.g.

const doArraysIntersect 
 = (array1, array2) => array1.some(item1 => array2.includes(item1))

expect(doArraysIntersect(["1", "2", "3"], ["3"])).toBe(true);

I would also recommend using positive logic (i.e. try and minimize the use of not) as I have done in my example, as negative logic (e.g. muliple instances of negative logic e.g. using shouldntHave and not in the same assertion) can be harder to reason with.

EDIT: To be clear, I quite like custom matchers when used appropriately. When sorting through somebody else's code to fix a bug, I don't want to have to pause at tests which use double negatives. Assertions should be simple and obvious :D

Solution 2:[2]

Don't overthink the perfect matcher, just write your test and move on:

const shouldntHave = [4,5,6];
const subject = [1,2,3]

shouldntHave.map(m => expect(subject).not.toContain(m));

EDIT: To be clear, I despise custom matchers. I'm already sorting through somebody else's code to fix a bug, I don't want to have to dive deep into testing infrastructure as well. Assertions should be simple and obvious.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2