Writing JavaScript Tests Using Jasmine Framework

Introduction

 
Here, we are going to use a framework called Jasmine to write and test our unit test cases. Jasmine is a behavior-driven development framework to test our JavaScript codes. The interesting thing about the Jasmine framework is, it doesn’t even require a DOM,  is independent on any framework, and clean and easy. Here, I will show you how we can create and run our JavaScript tests. I am going to use Visual Studio 2015 for development. I hope, you will like this article. 
 
Download source code
Background
 
As a developer, we all write JavaScript codes for our client-side developments. Am I right? It is more important to check, whether the written codes work well. Thus, the developers usually do unit testing, a few developers are doing manual testing to just check whether the functionality is working or not. Most of the MNC’s have a set of rules to be followed while developing any functionalities, and one of them is writing test cases. Once the test cases passes, only then will you be allowed to move your codes to other environments. Here, I will show you, how we can write the client-side test cases with the help of a framework called Jasmine.
 

Setting up the project

 
To get started, please create an empty project in your Visual Studio.
 
 
empty_project
 
Now, we will install jQuery, jQueryUI from NuGet Package Manager. 
 
 
nuget_package_manager
 
We are all set to start our coding now.
 
Creating page and needed JS file
 
Next, we are going to create a page as preceding with two text boxes and needed references.
  1. <!DOCTYPE html>    
  2. <html>    
  3.     
  4. <head>    
  5.     <title>Writing JavaScript test cases with Jasmine framework - Sibeesh Passion</title>    
  6.     <meta charset="utf-8" />    
  7.     <link href="Content/themes/base/jquery-ui.min.css" rel="stylesheet" />    
  8.     <link href="Content/themes/base/base.css" rel="stylesheet" />    
  9.     <script src="Scripts/jquery-3.1.1.min.js"></script>    
  10.     <script src="Scripts/jquery-ui-1.12.1.min.js"></script>    
  11.     <script src="Scripts/Index.js"></script>    
  12. </head>    
  13.     
  14. <body> Start Date: <input type="text" name="name" value="" id="dtStartDate" /> End Date: <input type="text" name="name" value="" id="dtEndDate" /> </body>    
  15.     
  16. </html>   
Now, we can start writing our JavaScript codes in the file Index.js. We will start with a document ready function as preceding.
  1. $(function() {    
  2.     $("#dtStartDate").datepicker();    
  3.     $("#dtEndDate").datepicker();    
  4.     $("#dtEndDate").on("change leave"function() {});    
  5. });   
Shall we create our validation functions? We will be creating a namespace indexPage and functions. You can see the validations, as given below.
  1. var indexPage = {};    
  2. indexPage.validationFunctions = (function() {    
  3.     return {    
  4.         getStartDateSelectedValue: function() {    
  5.             return $("#dtStartDate").val();    
  6.         },    
  7.         getEndDateSelectedValue: function() {    
  8.             return $("#dtEndDate").val();    
  9.         },    
  10.         isNullValue: function(selVal) {    
  11.             if (selVal.trim() == "") {    
  12.                 return true;    
  13.             } else {    
  14.                 return false;    
  15.             }    
  16.         },    
  17.         isNullValueWithUIElements: function() {    
  18.             if (indexPage.validationFunctions.isNullValue(indexPage.validationFunctions.getStartDateSelectedValue()) && indexPage.validationFunctions.isNullValue(indexPage.validationFunctions.getEndDateSelectedValue())) {    
  19.                 alert("The values can't be null!.");    
  20.             }    
  21.         },    
  22.         isEndDateGreaterStart: function() {    
  23.             var startDate = new Date(indexPage.validationFunctions.getStartDateSelectedValue());    
  24.             var endDate = new Date(indexPage.validationFunctions.getEndDateSelectedValue());    
  25.             if (startDate < endDate) {    
  26.                 return true;    
  27.             } else {    
  28.                 alert("End date must be greater than start date!.")    
  29.                 return false;    
  30.             }    
  31.         }    
  32.     }    
  33. }(jQuery));   
I hope you are able to understand the written codes. We wrote some validations like Null value check, end date greater than start date, etc…
 
Now, please run your Application and check whether the validations are working fine or not. 

 
null_validation_check 
 
 
date_validation_check
 
Now, here comes the real part.
 

Setting up Jasmine Framework

 
To set Jasmine, we will add a new project to our solution.
 
 
add_new_project
 
Now, install Jasmine from NuGet Package Manager.
 
 
jasmine_nuget_package
 
Once you are done, the required files would be added to your project. We will be discussing Jasmine, once everything is set. Thus, no worries.
 
Now, please add a new HTML file to your Jasmine project. This is the page, where we can see the test cases in action and add all the references, as follows.
  1. <!DOCTYPE html>    
  2. <html lang="en" xmlns="http://www.w3.org/1999/xhtml">    
  3.     
  4. <head>    
  5.     <meta charset="utf-8" />    
  6.     <title>Jasmine Spec Runner - Sibeesh Passion</title>    
  7.     <link href="content/jasmine/jasmine.css" rel="stylesheet" />    
  8.     <script src="http://localhost:12387/Scripts/jquery-3.1.1.min.js"></script>    
  9.     <script src="http://localhost:12387/Scripts/jquery-ui-1.12.1.min.js"></script>    
  10.     <script src="scripts/jasmine/jasmine.js"></script>    
  11.     <script src="scripts/jasmine/jasmine-html.js"></script>    
  12.     <script src="scripts/jasmine/console.js"></script>    
  13.     <script src="scripts/jasmine/boot.js"></script>    
  14.     <script src="scripts/indextests.js"></script>    
  15.     <script src="http://localhost:12387/Scripts/Index.js"></script>    
  16. </head>    
  17.     
  18. <body> </body>    
  19.     
  20. </html>   
Please do not forget to include JS files, where we actually have written the validations, jQuery, jQueryui (if needed). Here indextests.js is the file, where we are going to write the test cases.
 
Normally, this page is called Spec Runner. Now, you may be thinking what is a Spec? Before going further, there are some terms you must be aware of, which are listed below. 
  • Suites
     
    A suite is the starting point of Jasmine test cases. It actually calls the global Jasmine function. It can have two parameters, a string value, which describes the suit and a function, which implements the suit.
     
  • Spec
     
    Like suites, a spec starts with a string, which can be the title of the suite and a function, where we write the tests. A spec can contain one or more expectation, which tests the state of our code.
     
  • Expectation
     
    The value of an expectation is either true or false, an expectation starts with the function. It takes a value and calls the actual one.
     
    You can always read more here. Now, please run your SpecRunner.html page. If everything is fine, you can see a page, as given below.
     
     
    jasmine_spec_runner_page
Are you all set? Shall we go and write our test cases? Please go to your IndexTest.js file and create a suit and spec as preceding.
  1. describe("Includes validations for index page"function() {    
  2.     var indexPage;    
  3.     beforeEach(function() {    
  4.         indexPage = window.indexPage.validationFunctions;    
  5.     });    
  6.     it("Check for null values"function() {    
  7.         // We are going to pass "" (null) value to the function     
  8.         var retVal = indexPage.isNullValue("");    
  9.         expect(retVal).toBeTruthy();    
  10.     });    
  11. });   
Here, the expectation is true and we give toBeTruthy(). Now, let's go and find whether the test is passed or not. Please run the SpecRunner.html page again.
 
 
test_jasmine_specs
 
Now, we will write test cases for our function isEndDateGreaterStart, if you have noticed the functionisEndDateGreaterStart, you can see that there are dependencies (UI elements). Inside of the function, we are getting the values from the UI elements.
  1. var startDate = new Date(indexPage.validationFunctions.getStartDateSelectedValue());     
  2. var endDate = new Date(indexPage.validationFunctions.getEndDateSelectedValue());    
In this case, we need to mock these values. It is known as ‘Spy’ in Jasmine. We can use a function calledSpyOn for this.
  1. it("Spy call for datepicker date validation"function() {    
  2.     //Start date as 2015-03-25     
  3.     spyOn(indexPage, "getStartDateSelectedValue").and.returnValue("2015-03-25");    
  4.     //End date as 2015-03-24     
  5.     spyOn(indexPage, "getEndDateSelectedValue").and.returnValue("2015-03-24");    
  6.     var retVal = indexPage.isEndDateGreaterStart();    
  7.     expect(retVal).toBeFalsy();    
  8. });   
Here, we are giving start date as 2015-03-25 and end date as 2015-03-24 and we know 2015-03-25 < 2015-03-24 is false, so here, we are giving an expectation as false (toBeFalsy()). Now, you are getting an alert as follows right?[caption id="attachment_11912" align="alignnone" width="766"] alert_in_spyon_jasmine[/caption]
 
 
In the testing framework, we don’t need any alerts right? To get rid of this, you must create a spy for window.alert function and add it, so that it can be used for each specs. You can do that as follows.
  1. window.alert = jasmine.createSpy("alert").and.callFake(function () { });    
Once you add this code, the alert message won’t be thrown. Now, please add another spec with the true values (Start date – 2015-03-25, End date – 2015-03-26), so that it will return true.
  1. it("Spy call for datepicker date validation toBeTruthy"function() {    
  2.     //Start date as 2015-03-25     
  3.     spyOn(indexPage, "getStartDateSelectedValue").and.returnValue("2015-03-25");    
  4.     //End date as 2015-03-26     
  5.     spyOn(indexPage, "getEndDateSelectedValue").and.returnValue("2015-03-26");    
  6.     var retVal = indexPage.isEndDateGreaterStart();    
  7.     expect(retVal).toBeTruthy();    
  8. });   
Now, you can see all of your specs are passed.
 
 
run_all_specs_in_jasmine
 
Please see this article on my blog here.
 

Conclusion

 
Did I miss anything that you may think is needed? Did you find this post useful? I hope, you liked this article. Please share with me your valuable suggestions and feedback.