To understand better the difference between these three Jasmine matchers – toBe(true) vs toBeTruthy() vs toBeTrue() – we have to check the source code, to see how they are implemented.
Let’s take them one by one, by showing you the definition and some basic examples.
expect.toBe()
Jasmin implementation for this matcher is:
getJasmineRequireObj().toBe = function () { function toBe() { return { compare: function (actual, expected) { return { pass: actual === expected }; } }; } return toBe; };
The condition to pass the test is done with the non-converting comparison operator ===, which means that no conversion occurs. When the operands are of different types, the operator returns false, and only compares the values when they share the same type.
In this case expect(foo).toBe(true) passes only if foo has the value true.
Some examples using expect().toBe():
expect(true).toBe(true) → PASS expect(false).toBeTrue() → FAIL expect(‘true’).toBe(true) → FAIL expect({true}).toBe(true) → FAIL
expect().toBeTruthy()
Jasmin implementation for this matcher is:
getJasmineRequireObj().toBeTruthy = function () { function toBeTruthy() { return { compare: function (actual) { return { pass: !!actual }; } }; } return toBeTruthy; };
The double exclamation !! operator is used (also known as not not operator, double negation, or double bang) which performs type coercion. It is important first to understand what this means so I will try to explain it shortly and give you some examples.
In JavaScript type coercion is the process of converting a value from one type to another ( string to number, object to boolean, etc). Here you can read more about basic JavaScript Type Conversion and JavaScript Expressions and Operators.
The not not operator converts a value to a boolean. A value will be truthy if the coercion of the value will return true. Everything that is not 0, “”, null, undefined, NaN or false is truthy.
"Foo" → "foo" !"foo" → false !!"foo" → true !!0 → false !!"" → false !!null → false !!undefined → false !!NaN → false !!false → false !!'false' → true !![1,2,3] → true !![] → true !!13 → true
expect().toBeTrue()
Is a custom matcher introduced in Jasmine-Matchers defined as:
function toBeTrue(actual) { return actual === true || is(actual, 'Boolean') && actual.valueOf(); }
It is similar with expect.toBe(true) with the difference that expect().toBeTrue() also tests if it’s dealing with a Boolean object, not only primitive values.
expect(new Boolean(true)).toBeTrue() → PASS expect(new Boolean(true)).toBe(true) → FAIL
This happens because:
new Boolean(true) → {true} new Boolean(false) → {false} new Boolean(true) == true → true new Boolean(false) == true → false new Boolean(true) == false → false new Boolean(false) == false → true new Boolean(true) === true → false new Boolean(false) === true → false new Boolean(true) === false → false new Boolean(false) === false → false !!new Boolean(true) → true
Conclusion
Do not confuse the primitive Boolean values true and false with the true and false values of the Boolean object. If you are dealing with Boolean objects then use expect().toBeTrue() custom matcher in your tests, otherwise stick with the plain old expect.toBe(true) matcher.
Be First to Comment