JackMorrissey
JackMorrissey

Reputation: 2697

Is it possible to check against multiple types within a toEqual in Jasmine.Js?

I'm very new to Jasmine and ran across a situation where I would expect either a String or null. I attempted to do an or within the toEqual, but I'm seeing some odd results which leads me to believe I'm going about this the wrong way. What is the best way to go about a situation like this?

Perhaps I'm just going about my testing wrong. Should I just scrap this idea of having one test to test both situations?

describe("Jasmine", function () {

    //1
    it("should be able to handle any(String) || null within toEqual for string", function () {
        expect("aString").toEqual(jasmine.any(String) || null);
    });

    //2
    it("should be able to handle any(String) || null within toEqual for null", function () {
        expect(null).toEqual(jasmine.any(String) || null);
    });

    //3
    it("should be able to handle null || any(String) within toEqual for string", function () {
        expect("aString").toEqual(null || jasmine.any(String));
    });

    //4
    it("should be able to handle null || any(String) within toEqual for null", function () {
        expect(null).toEqual(null || jasmine.any(String));
    });
});
  1. Pass
  2. Expected null to equal <jasmine.any(function String() { [native code] })>.
  3. Pass
  4. Expected null to equal <jasmine.any(function String() { [native code] })>.

I realize there is also a toBeNull() which is probably why the results are so wonky, but without an "or" chaining I didn't know how to incorporate it.

(Running Jasmine 1.3.1 revision 1354556913)

Solved! Full solution below if anyone is interested

describe("Jasmine", function () {

    beforeEach(function () {
        this.addMatchers({

            toBeStringOrNull: function () {
                var actual = this.actual;

                this.message = function () {
                    return "Expected " + actual + " to be either string or null";
                };

                return typeof actual === 'string' || actual instanceof String || actual === null;
            }

        });
    });

    //1
    it("should be able to handle any(String) || null within toEqual for string", function () {
        expect("aString").toBeStringOrNull();
    });

    //2
    it("should be able to handle any(String) || null within toEqual for null", function () {
        expect(null).toBeStringOrNull();
    });

    //3
    it("should be able to handle null || any(String) within toEqual for string", function () {
        expect("aString").toBeStringOrNull();
    });

    //4
    it("should be able to handle null || any(String) within toEqual for null", function () {
        expect(null).toBeStringOrNull();
    });
});

Upvotes: 6

Views: 6801

Answers (2)

tekumara
tekumara

Reputation: 8807

Write your own custom matcher:

toBeStringOrNull: function() {
  var actual = this.actual;

  this.message = function () {
    return "Expected " + actual + " to be either string or null";
  }

  return typeof actual === 'string' || actual instanceof String || actual === null;
}

Upvotes: 12

Felipe
Felipe

Reputation: 440

Provided that you definitely want those cases to work on the same test, you could write your own matcher. Something like

toBeStringOrNull: function() {
  var actual = this.actual;

  this.message = function () {
    return "Expected " + actual + " to be either string or null";
  }

  return jasmine.any(String) || actual === null;
}

Upvotes: 1

Related Questions