toBe(true) vs toBeTruthy() vs toBeTrue()

alecxe picture alecxe · Sep 16, 2015 · Viewed 103.7k times · Source

What is the difference between expect(something).toBe(true), expect(something).toBeTruthy() and expect(something).toBeTrue()?

Note that toBeTrue() is a custom matcher introduced in jasmine-matchers among other useful and handy matchers like toHaveMethod() or toBeArrayOfStrings().


The question is meant to be generic, but, as a real-world example, I'm testing that an element is displayed in protractor. Which matcher should I use in this case?

expect(elm.isDisplayed()).toBe(true);
expect(elm.isDisplayed()).toBeTruthy();
expect(elm.isDisplayed()).toBeTrue();

Answer

Louis picture Louis · Sep 24, 2015

What I do when I wonder something like the question asked here is go to the source.

toBe()

expect().toBe() is defined as:

function toBe() {
  return {
    compare: function(actual, expected) {
      return {
        pass: actual === expected
      };
    }
  };
}

It performs its test with === which means that when used as expect(foo).toBe(true), it will pass only if foo actually has the value true. Truthy values won't make the test pass.

toBeTruthy()

expect().toBeTruthy() is defined as:

function toBeTruthy() {
  return {
    compare: function(actual) {
      return {
        pass: !!actual
      };
    }
  };
}

Type coercion

A value is truthy if the coercion of this value to a boolean yields the value true. The operation !! tests for truthiness by coercing the value passed to expect to a boolean. Note that contrarily to what the currently accepted answer implies, == true is not a correct test for truthiness. You'll get funny things like

> "hello" == true
false
> "" == true
false
> [] == true
false
> [1, 2, 3] == true
false

Whereas using !! yields:

> !!"hello"
true
> !!""
false
> !![1, 2, 3]
true
> !![] 
true

(Yes, empty or not, an array is truthy.)

toBeTrue()

expect().toBeTrue() is part of Jasmine-Matchers (which is registered on npm as jasmine-expect after a later project registered jasmine-matchers first).

expect().toBeTrue() is defined as:

function toBeTrue(actual) {
  return actual === true ||
    is(actual, 'Boolean') &&
    actual.valueOf();
}

The difference with expect().toBeTrue() and expect().toBe(true) is that expect().toBeTrue() tests whether it is dealing with a Boolean object. expect(new Boolean(true)).toBe(true) would fail whereas expect(new Boolean(true)).toBeTrue() would pass. This is because of this funny thing:

> new Boolean(true) === true
false
> new Boolean(true) === false
false

At least it is truthy:

> !!new Boolean(true)
true

Which is best suited for use with elem.isDisplayed()?

Ultimately Protractor hands off this request to Selenium. The documentation states that the value produced by .isDisplayed() is a promise that resolves to a boolean. I would take it at face value and use .toBeTrue() or .toBe(true). If I found a case where the implementation returns truthy/falsy values, I would file a bug report.