Applying different matchers to the Jasmine test
Jasmine provides a rich set of matchers to test JavaScript code. In this recipe, you will learn to apply various matchers in different situations.
To understand this recipe, let's assume that you are developing an application and you have to implement test code for various scenarios by applying different Jasmine matchers.
"As a developer, I want to apply different Jasmine matchers so that I can implement a test condition successfully."
Let's consider some scenarios in the preceding context, that is, where Jasmine matchers should be applied for different test conditions:
- Scenario-1: The '
toMatch
' matcher should be applied successfully for regular expressions - Scenario-2: The '
toEqual
' matcher should be applied successfully for literals, variables, and objects - Scenario-3: The '
toBe
' matcher should be applied successfully for literals, variables, and objects - Scenario-4: The '
toBeDefined
' matcher should be applied successfully to compares against defined - Scenario-5: The '
toBeUndefined
' matcher should be applied successfully to compares against undefined - Scenario-6: The '
toBeNull
' matcher should be applied successfully to compare against null - Scenario-7: The '
toBeTruthy
' matcher should be applied successfully for Boolean casting testing - Scenario-8: The '
toBeFalsy
' matcher should be applied successfully for Boolean casting testing - Scenario-9: The '
toContain
' matcher should be applied successfully for finding an item in an array - Scenario-10: The '
toBeLessThan
' matcher should be applied successfully for mathematical comparisons - Scenario-11: The '
toBeGreaterThan
' matcher should be applied successfully for mathematical comparisons - Scenario-12: The '
toBeCloseTo
' matcher should be applied for precision math comparison
How to do it…
To apply different matchers to your Jasmine tests, you need to perform the following steps in the preceding scenarios:
- Create the
JasmineMatchers_spec.js
file under the/spec
folder and code the following lines:describe("Jasmine Matchers", function() { //Scenario – 1 });
- Now, use the following code to define and implement the spec for scenario 1 using the
toMatch
matcher:describe("Jasmine Matchers",function(){ //Scenario -1 it("'toMatch' matcher should be applied successfully for regular expressions", function() { var strString1 = "Packt Cookbooks are an excellent source of learning"; var strPhone = "001-789-56-67"; expect(strString1).toMatch(/Cookbooks/); expect(strString1).toMatch(/cookbooks/i); expect(strString1).not.toMatch(/Java/); expect(strPhone).toMatch(/\d{3}-\d{3}-\d{2}-\d{2}/); }); });
Note
A regular expression is a sequence of characters that forms a search pattern. Search patterns can be defined based on a single character, combination of characters/strings, or more complicated patterns. To explore more about regular expressions in greater depth, visit the following website:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
- The next step is to run the spec file (
JasmineMatchers_spec.js
) using the Jasmine runner, and you will see that the test passes, as shown in the following screenshot: - Now, use following code to implement scenario 2 and scenario 3:
describe("Jasmine Matchers",function(){ //Scenario - 2 describe("toEqual matcher should be applied successfully", function(){ it("if numbers are equal", function() { var intVar = 15; expect(intVar).toEqual(15); }); it("if strings are equal", function() { var strVar = "Jasmine Cookbook"; expect(strVar).toEqual("Jasmine Cookbook"); }); it("if objects are equal", function() { var MyObectj1 = {a: 12, b: 13}; var MyObectj2 = {a: 12, b: 13}; expect(MyObectj1).toEqual(MyObectj2); expect(MyObectj1.a).toEqual(MyObectj2.a); expect(MyObectj1.a).not.toEqual(MyObectj2.b); }); it("if arrays are equal", function() { expect([8, 9, 10]).toEqual([8, 9, 10]); expect([8, 9, 10, 11]).not.toEqual([8, 9, 10]); }); }); //Scenario - 3 it("toBe matcher should be applied successfully for literals, variables and objects", function() { var MyObj = {foo: "foo"}; var MySameObj = {foo: "foo"}; var strVar = "Jasmine Cookbook"; var myArr = [8, 9, 10]; expect(MyObj).toBe(MyObj); expect(MySameObj).not.toBe(MyObj); expect(MySameObj).toEqual(MyObj); expect(strVar).toBe("Jasmine Cookbook"); expect(myArr).toEqual([8, 9, 10]); expect(myArr).not.toBe([8, 9, 10]); }); });
In the preceding code snapshot, notice that we created two objects (that is,
MyObj
andMySameObj
). Both look similar and equal, but they are two different objects with exactly the same attributes. Furthermore, you can observe the behavior of thetoBe
andtoEqual
matchers. Here, while comparing both the objects, the assertion value will returntrue
with thetoEqual
matcher andfalse
with thetoBe
matcher. Also, this is true for an array object (that is,myArr
).Note
The
toEqual()
matcher checks equivalence. On the other hand, thetoBe()
matcher ensures that they are the exact same objects. - Next, run the spec file (
JasmineMatchers_spec.js
) for scenario 2 and scenario 3 using the Jasmine runner. The tests should run successfully, as shown in the following screenshot: - Use the following code to implement scenario 4:
describe("Jasmine Matchers",function(){ //Scenario - 4 it("toBeDefined should be applied successfully to compares against defined.", function() { var MyObj = { foo: "foo" }; var Myfunction = (function() {})(); var strUndefined; expect("Jasmine Cookbooks").toBeDefined(); expect(MyObj).toBeDefined(); expect(MyObj.foo).toBeDefined(); expect(Myfunction).not.toBeDefined(); expect(strUndefined).not.toBeDefined(); }); });
Note
Undefined
is a built-in JavaScript type. In JavaScript, if we declare a variable without assigning a value, its type is undefined. Also, JavaScript functions without a return statement or with empty return statements return undefined. To learn more about undefined and how it works, visit the following website:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined
- Use the following code to implement scenario 5:
describe("Jasmine Matchers",function(){ //Scenario - 5 it("toBeUndefined should be applied successfully to compares against undefined.", function() { var MyObj = { foo: "foo" }; var Myfunction = (function() {})(); var strUndefined; expect(MyObj).not.toBeUndefined(); expect(MyObj.foo).not.toBeUndefined(); expect(Myfunction).toBeUndefined(); expect(strUndefined).toBeUndefined(); }); });
- Now, run the spec file (for scenario 4 and 5) with the Jasmine runner. You will see that all Jasmine tests pass for both the scenarios, as shown in the following screenshot:
- To implement scenario 6, use the following code:
describe("Jasmine Matchers",function(){ //Scenario - 6 it("toBeNull matcher should be applied successfully to compare against null", function() { var nullValue = null; var valueUndefined; var notNull = "notNull"; expect(null).toBeNull(); expect(nullValue).toBeNull(); expect(valueUndefined).not.toBeNull(); expect(notNull).not.toBeNull(); }); });
- To see how Jasmine handles null values using the
toBeNull
matcher, run the spec file (only for scenario 6) with the Jasmine runner. You will see that the test passes, as shown in the following screenshot: - Use the following code to implement scenarios 7 and 8:
describe("Jasmine Matchers",function(){ //Scenario - 7 it("toBeTruthy matcher should be applied successfully for Boolean casting testing", function() { var MyVar1=12, MyVar2 = "True for Non Empty Strings"; expect(true).toBeTruthy(); expect("Jasmine Cookbook").toBeTruthy(); expect(MyVar1).toBeTruthy(); expect(MyVar2).toBeTruthy(); }); //Scenario - 8 it("toBeFalsy matcher should be applied successfully for Boolean casting testing", function() { var MyVar1=12, MyVar2 = "True for Non Empty Strings"; expect(false).toBeFalsy(); expect(null).toBeFalsy(); expect(true).not.toBeFalsy(); expect("Jasmine Cookbook").not.toBeFalsy(); expect(MyVar1).not.toBeFalsy(); expect(MyVar2).not.toBeFalsy(); }); });
- Next, run the spec file (for scenarios 7 and 8) with the Jasmine runner and you will see that both the Jasmine tests pass, as shown in the following screenshot:
- Use the following code to implement scenario 9:
describe("Jasmine Matchers",function(){ it("toContain matcher should be applied successfully for finding an item in an Array", function() { var MyArray = ["Jasmine", "Cookbook", "JavaScript"]; expect([1, 2, 3]).toContain(2); expect([1, 2, 3]).toContain(2,3); expect(MyArray).toContain("Cookbook"); expect([1, 2, 3]).not.toContain(4); expect(MyArray).not.toContain("Java"); }); });
- Now, run the spec file (only for scenario 9) with the Jasmine runner and you will see that all the test conditions pass for scenario 9, as shown in the following screenshot:
- Use the following code to implement scenarios 10 and 11:
describe("Jasmine Matchers",function(){ //Scenario - 10 it("toBeLessThan matcher should be applied successfully for mathematical comparisons", function() { var pi = 3.1415926, g = 9.71; num1=5, num2=9; expect(pi).toBeLessThan(g); expect(num1).toBeLessThan(num2); expect(g).not.toBeLessThan(pi); expect(num2).not.toBeLessThan(num1); }); //Scenario - 11 it("toBeGreaterThan matcher should be applied successfully for mathematical comparisons", function() { var pi = 3.1415926, g = 9.71; num1=5, num2=6; expect(g).toBeGreaterThan(pi); expect(num2).toBeGreaterThan(num1); expect(pi).not.toBeGreaterThan(g); expect(num1).not.toBeGreaterThan(num2); }); });
- Run the spec file (for scenarios 10 and 11) with the Jasmine runner and you will see that both the tests pass, as shown in the following screenshot:
- To implement scenario 12, use the following code:
describe("Jasmine Matchers",function(){ it("toBeCloseTo matcher should be applied for precision math comparison", function() { var pi = 3.1415926, e = 2.78; expect(pi).not.toBeCloseTo(e); expect(pi).toBeCloseTo(e,0); expect(4.334).toBeCloseTo(4.334); expect(4.334).toBeCloseTo(4.3345,1); expect(4.334).toBeCloseTo(4.3345,2); expect(4.334).not.toBeCloseTo(4.3,2); expect(4.223).not.toBeCloseTo(4.22,3); expect(4.223).not.toBeCloseTo(4.22,4); }); });
- Next, run the spec file (for scenario 12) with the Jasmine runner and you will see that all the test conditions pass:
- Finally, to run all the 12 scenarios in one go, make a single spec file with the entire test code and run it (
JasmineMatchers_spec.js
) with the Jasmine runner. You will see that all the tests pass:
How it works...
Let's take a look at the steps of this recipe.
In steps 1 to 3, we implemented scenario 1 with the toMatch
matcher. It checks whether something is matched for a regular expression. You can use the toMatch
matcher to test search patterns. In our case, we implemented the test code to find out search patterns with different regular expressions.
In steps 4 and 5, we defined the specs for scenario 2 and 3, and we implemented the test code corresponding to specs using the toEqual
and toBe
matchers. Here, notice that toBe
looks similar to toEqual
, but that is not the case. The toBe
matcher returns the value true
if the objects are equal. For example, in our case, MyObj
and MySameObj
look like the same objects, but in fact both are different objects with exactly the same attribute/behavior. Therefore, the assertion will return a true
value with the toEqual
matcher, but a false
value with the toBe
matcher.
In steps 6 to 8, we implemented scenarios 4 and 5 and saw how the toBeDefine
and toBeUndefine
matchers are applied to test JavaScript's Undefined
type. In step 7, we first implemented a test condition for a non-empty string and two test conditions with object variable MyObj
. We also implemented test conditions for the strUndefined
variable and the MyFunction()
function by applying negative assertions. Conversely, in step 8, we implemented test conditions with the object variable MyObj
by applying negative assertions.
In step 9, we implemented test code for scenario 6 using the toBeNull
matcher. In step 10, we saw test conditions pass for null
values. However, we applied negative assertions to pass test conditions for not Null
and Undefined
values.
In step 11, we implemented scenario 7 and scenario 8 using the toBeTruthy
and toBeFalsy
matchers. We use the toBeTruthy
matcher to check whether something returns/evaluates to true
. Similarly, we use the toBeFalsy
matcher to check whether something returns/evaluates to false. In our case, we applied the toBeTruthy
matcher for true value, non-empty strings and numbers other than zero. Similarly, we applied toBeFalsy
matcher to validate false, null, and empty strings.
In step 13, we implemented the test code for scenario 9 using the toContain
matcher. Here, we implemented test conditions to find out an element(s)/item(s) of an array using the toContain
matcher. Similarly, we implemented test conditions to check if an element/an item does did not exist in an array by applying negative assertions.
In step 15, we implemented scenario 10 and scenario 11 to compare mathematical values using the toBeLessThan
and toBeGreaterThan
matchers.
In step 17, we implemented scenario 12 using the toBeCloseTo
matcher. This matcher is used to check whether a number is close to another number, up to a given level of decimal precision. In our case, we checked whether the expected number was equal to the actual number with a given level of decimal precision.