50

I need to set the test to succeed if one of the two expectations is met:

expect(mySpy.mostRecentCall.args[0]).toEqual(jasmine.any(Number));
expect(mySpy.mostRecentCall.args[0]).toEqual(false);

I expected it to look like this:

expect(mySpy.mostRecentCall.args[0]).toEqual(jasmine.any(Number)).or.toEqual(false);

Is there anything I missed in the docs or do I have to write my own matcher?

1
  • I checked the documentation and i tried some code, but i think we can't do that "easily" sorry. But according to what i have found, you can create your own "chainable" matcher.
    – Magus
    Commented Nov 23, 2012 at 14:08

4 Answers 4

75

Add multiple comparable strings into an array and then compare. Reverse the order of comparison.

expect(["New", "In Progress"]).toContain(Status);
4
  • 2
    Great idea, very succinct! And gives much clearer error messages than expect( Status == "New" || Status == "In Progress").toBe(true); Commented Aug 24, 2017 at 4:03
  • 1
    Wondering why is this not the selected answer? This is the simplest solution to test one of the two expectations.
    – Pankaj
    Commented Dec 23, 2019 at 22:01
  • Smart idea and easy to read implementation. Works great!
    – Campalo
    Commented Nov 19, 2020 at 10:19
  • This is nice, thank you. I wish there was a way that didn't invert the "expect" -> "matcher" semantics, like this solution. Commented Feb 2, 2023 at 23:26
20

This is an old question, but in case anyone is still looking I have another answer.

How about building the logical OR expression and just expecting that? Like this:

var argIsANumber = !isNaN(mySpy.mostRecentCall.args[0]);
var argIsBooleanFalse = (mySpy.mostRecentCall.args[0] === false);

expect( argIsANumber || argIsBooleanFalse ).toBe(true);

This way, you can explicitly test/expect the OR condition, and you just need to use Jasmine to test for a Boolean match/mismatch. Will work in Jasmine 1 or Jasmine 2 :)

1
  • Did it for me nice one Commented Sep 12, 2019 at 23:13
13

Note: This solution contains syntax for versions prior to Jasmine v2.0. For more information on custom matchers now, see: https://jasmine.github.io/2.0/custom_matcher.html


Matchers.js works with a single 'result modifier' only - not:

core/Spec.js:

jasmine.Spec.prototype.expect = function(actual) {
  var positive = new (this.getMatchersClass_())(this.env, actual, this);
  positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
  return positive;

core/Matchers.js:

jasmine.Matchers = function(env, actual, spec, opt_isNot) {
  ...
  this.isNot = opt_isNot || false;
}
...
jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
  return function() {
    ...
    if (this.isNot) {
      result = !result;
    }
  }
}

So it looks like you indeed need to write your own matcher (from within a before or it bloc for correct this). For example:

this.addMatchers({
   toBeAnyOf: function(expecteds) {
      var result = false;
      for (var i = 0, l = expecteds.length; i < l; i++) {
        if (this.actual === expecteds[i]) {
          result = true;
          break;
        }
      }
      return result;
   }
});
1
  • 1
    All I needed was 'there are no multi matches', this answer is so much more! :) Thanks for the code. I don't think it handles the jasmine.any(Number) case, but I can work it out. I'll put it in your answer once figured out if you don't mind.
    – naugtur
    Commented Nov 23, 2012 at 19:19
1

You can take the comparison out of the expect statement to gain full use of comparison operators.

let expectResult = (typeof(await varA) == "number" || typeof(await varA) == "object" );
expect (expectResult).toBe(true);

Not the answer you're looking for? Browse other questions tagged or ask your own question.