47

How do I do an or test with chai.should?

e.g. something like

total.should.equal(4).or.equal(5)

or

total.should.equal.any(4,5)

What's the right syntax? I couldn't find anything in the documentation.

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
MonkeyBonkey
  • 46,433
  • 78
  • 254
  • 460

5 Answers5

49

Asserts that the target is a member of the given array list. However, it’s often best to assert that the target is equal to its expected value.

expect(1).to.be.oneOf([1, 2, 3]);
expect(1).to.not.be.oneOf([2, 3, 4]);

https://www.chaijs.com/api/bdd/#method_oneof

Pang
  • 9,564
  • 146
  • 81
  • 122
Esqarrouth
  • 38,543
  • 21
  • 161
  • 168
44

Viewing the Chai expect / should documentation, there are several ways to do this test.

Note that you can chain using "and" but apparently not "or" - wish they had this functionality.

  1. Check whether an object passes a truth test:

.satisfy(method)

@param{ Function }matcher
@param{ String }message_optional_

Asserts that the target passes a given truth test.

Example:

expect(1).to.satisfy(function(num) { return num > 0; });

In your case, to test an "or" condition:

yourVariable.should.satisfy(function (num) {
    if ((num === 4) || (num === 5)) {
        return true;
    } else {
        return false;
    }
});
  1. Check whether a number is within a range:

.within(start, finish)

@param{ Number }startlowerbound inclusive
@param{ Number }finishupperbound inclusive
@param{ String }message_optional_

Asserts that the target is within a range.

Example:

expect(7).to.be.within(5,10);
nyarasha
  • 1,119
  • 1
  • 14
  • 24
  • 4
    that would work - we could also do something like `(num === 4 || num === 5).should.be.true – MonkeyBonkey Dec 05 '15 at 12:32
  • 1
    I suspect the reasoning for omitting `or` is to not deal with operation precedence in a library designed for readability. – aaaaaa Oct 27 '18 at 15:14
  • `expect(variable).satisfy(function(value) { return true; });` worked for me (using `satisfy` in the statement errored out with version `4.2.0` of chai. – jbaranski Apr 01 '19 at 19:44
  • 1
    This doesn't tell you, at a glance which of the multiple failing cases, which failed and which succeeded, when all cases fail. – TamusJRoyce Mar 06 '20 at 17:03
3

I have a similar problem to write tests to postman. I solved using the following script:

// delete all products, need token with admin role to complete this operation
pm.test("response is ok and should delete all products", function() {
    pm.expect(pm.response.code).to.satisfy((status) => status === 204 || status === 404);
});
Ângelo Polotto
  • 8,463
  • 2
  • 36
  • 37
  • 1
    Why not simply `.satisfy((status) => status === 204 || status === 404)`? So you don't need that `if else` construct – winklerrr Jan 28 '21 at 12:24
  • I always prefer the more easy way to understand to me. This is one case where I prefer write more code to be more clear. – Ângelo Polotto Jun 01 '21 at 20:18
  • 1
    What you wrote is something like this: `if (boolVar) { return true; } else { return false; }`. This can simply be abbreviated by `return boolVar`. Think about it: you are if-checking a boolean expression to then return the exact same value of the checked boolean expression. – winklerrr Jun 04 '21 at 11:36
  • Yes, I agree with you, I got your point, It really doesn't make much sense when simplified, I'll edit it. – Ângelo Polotto Jun 04 '21 at 13:10
0

Here, I shared exactly what you need to check.

expect(true).to.satisfy(() => {
    if (total == 4 || total == 5) return true;
    else return false;
});
-5

Because chai assertions throw error you could use try/catch construction:

try {
    total.should.equal(4)
} catch (e) {
    total.should.equal(5)
}

example of more difficult case:

try {
    expect(result).to.have.nested.property('data.' + options.path, null)
} catch (e) {
    expect(result).to.have.property('data', null)
}
rapthead
  • 1
  • 1
  • 2