Tuesday, 21 May 2013

Implementing SignalR Stock Ticker using Angular JS - Part2

In last post, we implemented SignalR part of the stock ticker sample using Angular JS and modified the HTML page to use Angular’s directives. As promised earlier, we will finish the implementation in this post by incorporating UI changes using directives and filters.

Angular JS is designed with separation of concerns in mind. One of the best architectural features of Angular JS is, it makes it easier to separate HTML and JavaScript separated from each other while playing together at the same time. Features like directives and filters can be used to easily extend Angular’s expressions and behaviour of HTML elements without wasting a lot of time and energy.

In the original Stock Ticker sample, following changes are made while binding data on the page:

  • Change in stock value is prepended with a up or down symbol based on value
  • Percentage value is multiplied with 100 and % symbol is appended to it

It also has the following UI effects on the page:

  • jQuery Colour flash effect on rows of table and list items
  • List item keeps scrolling when the stock market is open
  • Buttons are enabled and disabled based on current market state


Creating filters to represent data more effectively

Let’s write a couple of filters to manipulate change and percent change while presenting on the screen:

app.filter('percentage', function () {
    return function (changeFraction) {
        return (changeFraction * 100).toFixed(2) + "%";
    }
});
 
app.filter('change', function () {
    return function (changeAmount) {
        if (changeAmount > 0) {
            return "▲ " + changeAmount.toFixed(2);
        }
        else if (changeAmount < 0) {
            return "▼ " + changeAmount.toFixed(2);
        }
        else {
            return changeAmount.toFixed(2);
        }
    }
});

As you see the above code, implementation of the filters is pretty straight forward. Value on which the filter has to act is passed into the filter function. All we need to do is, manipulate the value as needed and return it. Using these filters is very easy as well, following snippet demonstrates the usage:
<td>
    {{stock.Change | change}}
</td>
<td>
    {{stock.PercentChange | percentage}}
</td>

Creating directives to make UI better

The buttons Open market and Reset have to be enabled when market is closed and close market button has to be enabled when market is opened. We can simulate this behaviour using the Boolean property marketIsOpen inside expression ({{ }}).

To evaluate expressions inside a directive, we need $interpolate service. The directive also needs to watch for change of the value to immediately change state of the button. Following is the implementation of the directive:

app.directive('disable', function ($interpolate) {
    return function (scope, elem, attrs) {
        var exp = $interpolate(elem.attr('data-disable'));
        function updateDisabled() {
            var val = scope.$eval(exp);
            if (val == "true") {
                elem[0].disabled = 'disabled';
            }
            else {
                elem[0].disabled = '';
            }
        }
 
        scope.$watch(exp, function (value) {
            updateDisabled();
        });
    }
});

While using the directive, we should assign it with a Boolean expression.
<input type="button" id="open" value="Open Market" data-disable="{{marketIsOpen}}"
            data-ng-click="openMarket()" />
<input type="button" id="close" value="Close Market" data-disable="{{!marketIsOpen}}"
            data-ng-click="closeMarket()" />

To indicate change of a stock value, the corresponding row in the table should flash. Let’s write a directive to do this:
app.directive('flash', function ($) {
    return function (scope, elem, attrs) {
        var flag = elem.attr('data-flash');
        var $elem = $(elem);
 
        function flashRow() {
            var value = scope.stock.LastChange;
            var changeStatus = scope.$eval(flag);
            if (changeStatus) {
                var bg = value === 0
                            ? '255,216,0' // yellow
                            : value > 0
                            ? '154,240,117' // green
                            : '255,148,148'; // red
 
                $elem.flash(bg, 1000);
            }
        }
 
        scope.$watch(flag, function (value) {
            flashRow();
        });
    }
});

The directive can be applied on any element that needs the scroll effect. Following is a sample table row using this directive:
<tr data-ng-repeat="stock in stocks" data-flash="marketIsOpen">
 ...
 ...
</tr>

The final directive that we have to create will be used to make the stock list scrollable. Again, values will keep scrolling when the market is opened. Following is the implementation:
app.directive('scrollTicker', function ($) {
    return function (scope, elem, attrs) {
        var $scrollTickerUI = $(elem);
        var flag = elem.attr('data-scroll-ticker');
        scroll();
 
        function scroll() {
            if (scope.$eval(flag)) {
                var w = $scrollTickerUI.width();
                $scrollTickerUI.css({ marginLeft: w });
                $scrollTickerUI.animate({ marginLeft: -w }, 15000, 'linear', scroll);
            }
            else
                $scrollTickerUI.stop();
        }
 
        scope.$watch(flag, function (value) {
            scroll();
        });
    }
});

It is applied on the list as:
<ul data-scroll-ticker="marketIsOpen">
 ...
 ...
</ul>

Now open the new scroll ticker page on a browser. Open the original jQuery based implementation on another browser window and play with both the screens. Now both of them have same look and behaviour.


This sample demonstrates how to make best use of features of Angular JS with SignalR to create real-time data oriented applications. The beauty of this approach is, we have several independent components playing pretty well together. This approach eases organization of code and makes each component testable in isolation.

 Code covered in this series is available on Github. Feel free to fork the code if you think that any part of it can be improved!!

Happy coding!

Sunday, 19 May 2013

Implementing SignalR Stock Ticker using Angular JS - Part1

In my last post, we saw how to use ASP.NET SignalR and Angular JS together using a Hello World type of example. Now that we got some idea on using both the technologies together, we will take a look at a more advanced scenario to make the frameworks work better together.

I assume that you have already seen the SignalR Stock ticker sample. If not, download it from Github or add the NuGet Package to an existing ASP.NET web application. Make sure that you take some time to run the sample at least once on multiple browsers and have a glance at the code before you proceed further.

I hope you had a look at the code on both server and client side of the stock ticker sample. We will not make any modification to the server code and the layout of the page. But we will rewrite the JavaScript part using features of Angular JS. As there is a lot of client side code to convert, let’s do it in a two-part series:

  1. Creating a custom service to communicate with hub on the server and using the service in a controller (This post)
  2. Performing UI changes on the page like enabling/disabling buttons, scrolling stock values in a list, adding animation effect to values in table and list (Next post)

Make a copy of the StockTicker.html file and give it a name of your choice. Add two files JavaScript files, controller.js and factory.js to the project. We will add script to these files in sometime. Modify the script reference section of the page to include the following script files:

<script src="../../bundles/jquery"></script>
<script src="../../bundles/jquerycolor"></script>
<script src="../../Scripts/jquery.signalR-1.0.1.js"></script>
    
<script type="text/javascript" src="../../Scripts/angular.js"></script>
<script type="text/javascript" src="factory.js"></script>
<script type="text/javascript" src="controller.js"></script>
Let’s start implementing SignalR part inside a custom service. To keep the controller free from doing anything other than providing data to the view and handle view events, we are creating a custom service to handle the hub communication logic. The service is responsible for:
  1. Creating objects needed for communication
  2. Configuring client functions to proxy to respond when market is opened, closed, reset or a stock value is updated
  3. Starting a hub connection
  4. Getting current values of stocks and current market status once the connection is started
  5. Opening, closing or resetting market on demand
Following is the module and the factory that handles the functionality mentioned above:
var app = angular.module('app', []);
app.value('$', $);
app.factory('stockTickerData', ['$', '$rootScope', function ($, $rootScope) {
    function stockTickerOperations() {
        //Objects needed for SignalR
        var connection;
        var proxy;
 
        //To set values to fields in the controller
        var setMarketState;
        var setValues;
        var updateStocks;
 
 //This function will be called by controller to set callback functions
        var setCallbacks = function (setMarketStateCallback, setValuesCallback, updateStocksCallback) {
            setMarketState = setMarketStateCallback;
            setValues = setValuesCallback;
            updateStocks = updateStocksCallback;
        };
 
        var initializeClient = function () {
            //Creating connection and proxy objects
            connection = $.hubConnection();
            proxy = connection.createHubProxy('stockTicker');
 
            configureProxyClientFunctions();
 
            start();
        };
 
        var configureProxyClientFunctions = function () {
            proxy.on('marketOpened', function () {
                //set market state as open
                $rootScope.$apply(setMarketState(true));
            });
 
            proxy.on('marketClosed', function () {
                //set market state as closed
                $rootScope.$apply(setMarketState(false));
            });
 
            proxy.on('marketReset', function () {
                //Reset stock values
                initializeStockMarket();
            });
 
            proxy.on('updateStockPrice', function (stock) {
                $rootScope.$apply(updateStocks(stock));
            });
        };
 
        var initializeStockMarket = function () {
            //Getting values of stocks from the hub and setting it to controllers field
            proxy.invoke('getAllStocks').done(function (data) {
                $rootScope.$apply(setValues(data));
            }).pipe(function () {
                //Setting market state to field in controller based on the current state
                proxy.invoke('getMarketState').done(function (state) {
                    if (state == 'Open')
                        $rootScope.$apply(setMarketState(true));
                    else
                        $rootScope.$apply(setMarketState(false));
                });
            });
        };
 
        var start = function () {
            //Starting the connection and initializing market
            connection.start().pipe(function () {
                initializeStockMarket();
            });
        };
 
        var openMarket = function () {
            proxy.invoke('openMarket');
        };
 
        var closeMarket = function () {
            proxy.invoke('closeMarket');
        };
 
        var reset = function () {
            proxy.invoke('reset');
        };
 
        return {
            initializeClient: initializeClient,
            openMarket: openMarket,
            closeMarket: closeMarket,
            reset: reset,
            setCallbacks: setCallbacks
        }
    };
 
    return stockTickerOperations;
} ]);
We need a controller to start the work. The controller will have following components:

  1. An array to store current stock values and a Boolean value to store current market state
  2. Setters to assign values to the fields 
  3. A function to modify the value of an entry in the stocks array
  4. Functions to handle open, close and reset operations when corresponding button is clicked
  5. Set callbacks to the service and ask the service to kick off the communication

Following is the code in the controller:

var StockTickerCtrl = function ($scope, stockTickerData) {
 
    $scope.stocks = [];
    $scope.marketIsOpen = false;
 
    $scope.openMarket = function () {
        ops.openMarket();
    }
 
    $scope.closeMarket = function () {
        ops.closeMarket();
    }
 
    $scope.reset = function () {
        ops.reset();
    }
 
    function assignStocks(stocks) {
        $scope.stocks = stocks;
    }
 
    function replaceStock(stock) {
        for (var count = 0; count < $scope.stocks.length; count++) {
            if ($scope.stocks[count].Symbol == stock.Symbol) {
                $scope.stocks[count] = stock;
            }
        }
    }
 
    function setMarketState(isOpen) {
        $scope.marketIsOpen = isOpen;
    }
 
    var ops = stockTickerData();
    ops.setCallbacks(setMarketState, assignStocks, replaceStock);
    ops.initializeClient();
}

Layout of the HTML page will remain unchanged. But we need to change the way data is rendered on the screen. The stock ticker sample uses poor man’s template technique to render content in the table and in the scrolling list. Since we are using Angular JS, let’s replace it with expressions. Following is the mark-up on the page in Angular’s style:
<div data-ng-app="app" data-ng-controller="StockTickerCtrl">
        <h1>
            ASP.NET SignalR Stock Ticker Sample</h1>
        <input type="button" id="open" value="Open Market" data-ng-click="openMarket()" />
        <input type="button" id="close" value="Close Market" data-ng-click="closeMarket()" />
        <input type="button" id="reset" value="Reset" data-ng-click="reset()" />

        <h2>
            Live Stock Table</h2>
        <div id="stockTable">
            <table border="1">
                <thead>
                    <tr>
                        <th>Symbol</th>
                        <th>Price</th>
                        <th>Open</th>
                        <th>High</th>
                        <th>Low</th>
                        <th>Change</th>
                        <th>%</th>
                    </tr>
                </thead>
                <tbody>
                    <tr class="loading" data-ng-show="stocks.length==0">
                        <td colspan="7">
                            loading...
                        </td>
                    </tr>
                    <tr data-ng-repeat="stock in stocks">
                        <td>
                            {{stock.Symbol}}
                        </td>
                        <td>
                            {{stock.Price | number:2}}
                        </td>
                        <td>
                            {{stock.DayOpen | number:2}}
                        </td>
                        <td>
                            {{stock.DayHigh | number:2}}
                        </td>
                        <td>
                            {{stock.DayLow | number:2}}
                        </td>
                        <td>
                            {{stock.Change}}
                        </td>
                        <td>
                            {{stock.PercentChange}}
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
        <h2>
            Live Stock Ticker</h2>
        <div id="stockTicker">
            <div class="inner">
                <ul>
                    <li class="loading" data-ng-show="stocks.length==0">loading...</li>
                    <li data-ng-repeat="stock in stocks" data-symbol="{{stock.Symbol}}"><span class="symbol">
                        {{stock.Symbol}}</span> <span class="price">{{stock.Price | number:2}}</span><span
                            class="change">{{stock.Change}} ({{stock.PercentChange}})</span>
                    </li>
                </ul>
            </div>
        </div>
    </div>


Open this page on a browser and the original stock ticker page on another browser window and play with the buttons. You will see both the screens with same data at any given point of time. The only difference would be the state of buttons, colour and scrolling list. We will fix them in the next post.




Happy coding! 

Hooking up ASP.NET SignalR with Angular JS

ASP.NET SignalR is a great framework to do real-time communication. I love this framework and I wrote some posts on it in the past. On the other hand, we have Angular JS, the super-heroic JavaScript library to build rich web applications. How about using these frameworks together to build an application with data getting pushed from server continuously and binding it on UI with nicely architected JavaScript code? It definitely sounds great. Let’s see it in action.

In this post, we will create a simple Hello World kind of application using SignalR and Angular JS. We will look at a more advanced scenario in a future post.

Creating Hub
Open Visual Studio (2010 or 2012) and create a new web application. Add SignalR’s NuGet package to this project. Add a Hub class to this project and add the following code to it:

public class HelloWorldHub : Hub
{
    public void GreetAll()
    {
        Clients.All.acceptGreet("Good morning! The time is " + DateTime.Now.ToString());
    }
}


On client side
A client can communicate with hub either using a proxy script generated by SignalR or without using proxy. I personally like the no-proxy approach, as it is easier to take control over certain things when we follow this approach. In an Angular JS application, it is always recommended to wrap calls to data sources in a separate service. In such service, we need to take control to add callbacks easily. For this reason, we will follow the no-proxy approach. Following are the scripts required on the page:

<script type="text/javascript" src="../Scripts/jquery-1.9.1.js"></script>
<script type="text/javascript" src="../Scripts/angular.js"></script>
<script type="text/javascript" src="../Scripts/jquery.signalR-1.0.1.min.js"></script>

The page will have a button and a span. When someone clicks on the button, method on the hub will be called to send a greeting message to all clients, which will be displayed on the span. Following is the mark-up on the page:
<div data-ng-app="app" data-ng-controller="SignalRAngularCtrl">
<input type="button" name="GreetAll" value="Greet All" data-ng-click="greetAll()" />
<span>{{text}}</span>
</div>

As stated earlier, the recommended way to call any external data source in Angular JS is using a custom service. We can create a factory or service to solve this purpose. In the following snippet, we create a new module and add a factory performing all SignalR operations to it:
var app = angular.module('app', []);
app.value('$', $);
        
app.factory('signalRSvc', function ($, $rootScope) {
    return {
        proxy: null,
        initialize: function (acceptGreetCallback) {
            //Getting the connection object
            connection = $.hubConnection();
 
            //Creating proxy
            this.proxy = connection.createHubProxy('helloWorldHub');
 
            //Starting connection
            connection.start();
 
            //Attaching a callback to handle acceptGreet client call
            this.proxy.on('acceptGreet', function (message) {
                $rootScope.$apply(function () {
                    acceptGreetCallback(message);
                });
            });
        },
        sendRequest: function (callback) {
            //Invoking greetAll method defined in hub
            this.proxy.invoke('greetAll');
        }
    }
});


Notice the callback passed to initialize method. This callback is a function defined in controller to set data received from server to a scope variable.

Also, notice the way the callback is invoked in proxy.on(). It is wrapped inside $rootScope.$apply(). This is because, the callback of proxy.on() gets executed outside Angular’s realm. Model modification done inside this function will not be processed unless it is called using $apply.

Finally, we need a controller to make everything work together.
function SignalRAngularCtrl($scope, signalRSvc) {
    $scope.text = "";
 
    $scope.greetAll = function () {
        signalRSvc.sendRequest();
    }
 
    updateGreetingMessage = function (text) {
        $scope.text = text;
    }

    signalRSvc.initialize(updateGreetingMessage);
}

As you see, the controller is pretty straight forward. As everything gets kicked off from controller, we need an object of the custom service, which is injected into the controller. The controller invokes the initialize method of the service as soon as it is instantiated. This is to start the connection and configure proxy with required callbacks.

Now open the page created above on two different browsers and click on button in one of the browser. You should be able to see a greeting message with current time.

Happy coding!

Wednesday, 1 May 2013

Basics - LINQ Expressions

LINQ is one of the most useful and most talked features added to .NET framework. It made our lives easier by providing a nice interface to program against list data and helps in writing readable code.

To support querying against in-memory collections, a number of extension methods were added to the interface IEnumerable. Following listing shows signatures of some of these extension methods:

public static long? Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, long?> selector);
public static long Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, long> selector);
public static IEnumerable<TSource> Take<TSource>(this IEnumerable<TSource> source, int count);
public static IEnumerable<TSource> TakeWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
public static IEnumerable<TSource> TakeWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate);

We have the interface IQueryable to support querying against remote collections. Any collection that doesn’t reside in the program’s memory is a remote collection. It can be a table in the database, a collection exposed through a service or anything similar. Following listing shows signature of corresponding extension methods defined in IQueryable:
public static long? Sum<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, long?>> selector);
public static long Sum<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, long>> selector);
public static IQueryable<TSource> Take<TSource>(this IQueryable<TSource> source, int count);
public static IQueryable<TSource> TakeWhile<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);
public static IQueryable<TSource> TakeWhile<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, int, bool>> predicate);

Notice the difference in the signatures of methods. Methods of IEnumerable accept Func and predicate, whereas the corresponding methods of IQueryable accept Expression<Func> and Expression<Predicate>.

The difference between Func and Expression<Func> is, Func is a delegate type and Expression<Func> is a data structure. An Expression is represented in the form of a tree. Each node of the tree contains some information which can be inspected. An expression can be created very easily using lambda. An example is shown below:

Expression<Func<int, bool>> compareExpression = (num) => num == 5;

Expression Tree Visualizer is a nice tool to view an expression in the form of a tree while debugging the application. To use it on a computer, one just needs to copy the library into Visual Studio visualizers folder. You can find the instructions in the codeplex site of the sample.

Following screenshot shows tree form of the expression defined above:


A simplified version of the above expression tree can be the following:



As we see, each node contains an expression. In other words, each individual part of an expression is also an expression. These expression types are defined in the namespace System.Linq.Expressions. This means, we can create a lambda expression by hand. Following code snippet demonstrates it:
//Parameter expression for the parameter num
var parameterNumExpr = Expression.Parameter(typeof(int), "num");

//Constant expression for the constant value 5
var constantVal5Expr = Expression.Constant(5);

//Lambda expression that accepts a parameter and compares with a constant
var lambdaCompareExpression = Expression.Lambda<Func<int, bool>>(Expression.MakeBinary(ExpressionType.Equal, parameterNumExpr, constantVal5Expr), parameterNumExpr);

If you view the above created lambdaCompareExpression using Expression Tree Visualizer, you should be able to see the same tree structure as of the previous expression. This expression can be used to query select all 5’s from an array of integers as follows:

int[] array = {2,6,5,1,343,54,5,23,75,46,5,18,3287,328,012,2,5 };
var nums = array.AsQueryable().Where(lambdaCompare);

The collection nums will have 4 5’s after execution of the above statement. As you saw, it takes quite a bit of work to create and use expressions by hand. But it is important to understand how an expression is formed and its components as we use them almost everyday. Following are some of the scenarios where expressions are used:

  • Converting LINQ queries to database queries in LINQ to SQL, Entity Framework, NHibernate
  • Creating OData URLs in WCF Data Services and Web API
  • Fetching data from Windows Azure Table storage
  • Configuring entities and their properties in Entity Framework code first fluent API
  • Generating HTML input tags with validation attributes in ASP.NET MVC (K. Scott Allen explained this in his blog post on Why All the Lambdas?)
  • Features like automatic paging and sorting list data with model binding in ASP.NET 4.5 Web Forms

Expressions are heavily used in .NET framework to provide a friendly interface to the programmers. While writing queries against LINQ to SQL or Entity Framework we feel as if the queries fetch data from in-memory collection. But there is a lot of work done under the covers. Data is extracted from each expression in the query and a SQL query is formed based on the information gathered. This query is fired against the database to fetch data.

Happy coding!

Saturday, 6 April 2013

Unit Testing AngularJS Controller Using Jasmine

Building and using single page JavaScript applications is fun. It brings richness on client side without having to install any external plugins. While building these applications, we write a lot of JavaScript code to run on client side. Releasing such large amount of code to client without testing will be a sin. We might leave the code with some unnoticed bugs if we do not test.

Right from the first post on Angular JS, I have mentioned several times that unit testability is one of its primary design goals. Tutorial series on Angular’s website demonstrates end-to-end testing using Jasmine’s BDD style. I cannot have sound sleep unless I write some tests for the AngularShoppingCart application. In this post, we will see how a controller can be unit tested using Jasmine.

If you haven’t followed earlier posts, take a look at the code on GitHub.

Jasmine and setting up
Jasmine is a BDD (Behaviour Driven Development) framework for testing JavsScript code. It doesn’t depend on any other JavaScript library. It has nice support to create spies (mocks), which helps to easily get rid of some concrete dependencies. Jasmine can be used to unit test anything written in JavaScript.

In order to run jasmine tests and view their results, we need to create an HTML page. Following references should be added to the page:

  1. Jasmine core library
  2. Jasmine HTML library
  3. Jasmine style sheet
  4. Source files of the script to be tested, which is also referred as System under test (SUT)
  5. File containing unit tests for the above source
  6. Any other library (like jQuery, jQuery UI, Angular) on which the source depends

As we will be testing code written using Angular JS, we should include angular-mocks.js library, which has mock services to replace some of the most commonly used services.

In body tag of the HTML page, a couple of statements are to be added to bootstrap Jasmine. Following is the template of a Jasmine spec runner page:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title>Jasmine Test Runner</title>

    <!-- Jasmine stylesheet -->
    <link rel="stylesheet" type="text/css" href="../../Styles/Jasmine.css">
 
    <!-- Jasmine core and HTML -->
    <script type="text/javascript" src="../../Scripts/jasmine.js"></script>
    <script type="text/javascript" src="../../Scripts/jasmine-html.js"></script>
    <script type="text/javascript" src="../../Scripts/jasmine.async.js"></script>
 
    <!-- JavaScript libraries on which source depends -->
    <script type="text/javascript" src="../../Scripts/angular.js"></script>
    <script type="text/javascript" src="../../Scripts/angular-mocks.js"></script>
 
    <!-- Script source to test and other files on which source depends -->
    <script type="text/javascript" src="../../Scripts/app/ShoppingModule.03.js"></script>
    <script type="text/javascript" src="../../Scripts/app/ShoppingCartController.03.js"></script>
    <script type="text/javascript" src="../../Scripts/app/CartCheckoutController.js"></script>
    
    <!-- Test script -->
    <script type="text/javascript" src="ShoppingCartControllerSpec.js"></script>
    <!--<script type="text/javascript" src="CartCheckoutTestSpec.js"></script>-->
</head>
<body>
    <script type="text/javascript">
        jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
        jasmine.getEnv().execute();
    </script>
</body>
</html>

Specs and Suits
Jasmine has a set of functions defined to create suits, specs and assertions. Following listing explains each of them in brief:

  1. describe: Used to define a suite. Accepts two parameters, name of the suite and a function containing statements to be contained in a suite
  2. it: Used to define a spec. Accepts a name and function containing logic to be executed. The logic contains assertions to evaluate the behaviour
  3. beforeEach: To set up dependencies before any spec under a suite runs
  4. afterEach: To clear any dependency after being used in the test cases
  5. expect: A function that accepts an object to be asserted
  6. matcher: Jasmine defines several matchers like toBe, toHaveBeenCalled, toEqual to perform a Boolean match between actual and expected values. We can write custom matchers too

In-depth discussion about above topics is beyond the scope of this article. Refer to Jasmine’s documentation for more details.

Unit testing ShoppingCartController
Let’s start testing the functions defined in ShoppingCartController.

Dependencies of the controller are clearly visible from the signature. As we need to inspect behaviour of the controller in isolation, we must mock these services. Following is the signature of ShoppingCartController:

function ShoppingCartCtrl($scope, $window, shoppingData, shared) {
}

As these services will be used across specs, it is better to create them globally and initialize them in beforeEach block. Since we will not hit the actual service, we need to use some static data to make the job of testing AJAX calls easier.
var shoppingCartStaticData = [
    { "ID": 1, "Name": "Item1", "Price": 100, "Quantity": 5 },
    { "ID": 2, "Name": "Item2", "Price": 55, "Quantity": 10 },
    { "ID": 3, "Name": "Item3", "Price": 60, "Quantity": 20 },
    {"ID": 4, "Name": "Item4", "Price": 65, "Quantity": 8 }
];
 
describe("ShoppingCartCtrl", function () {
 
    //Mocks
    var windowMock, httpBackend, _shoppingData, sharedMock;
 
    //Controller
    var ctrl;
 
    //Scope
    var ctrlScope;
 
    //Data
    var storedItems;
 
    //Loading shopping module
    beforeEach(function () {
        module("shopping");
    });
 
    beforeEach(inject(function ($rootScope, $httpBackend, $controller, shoppingData) {
        //Mock the services here
    }

});

The second beforeEach block will set-up all dependencies for the controller. So, it needs a number of services to perform its job. We will discuss their importance in shortly.

Resolving Dependencies
First and most important dependency of the controller is the $scope service. We need to create our own scope and pass it as a parameter while creating object of the controller. Using $rootScope, it is very easy to create our own scope:

ctrlScope = $rootScope.$new();

Second dependency is the $window service. As we are using href property of location alone, we can create a custom object with this property alone.
windowMock = { location: { href: ""} };

Third dependency shoppingData service is a wrapper to call backend data services. It used another service, $http to send AJAX requests. Angular JS team has made our job easy by creating $httpBackend, a mock for $http. $httpBackend provides a nice interface to send our own response when an AJAX request is made.

shoppingData service has three functions: getAllItems, addAnItem and removeItem. Let’s create spies for these functions as follows:

httpBackend = $httpBackend;
_shoppingData = shoppingData;
spyOn(shoppingData, 'getAllItems').andCallThrough();
spyOn(shoppingData, 'addAnItem').andCallThrough();
spyOn(shoppingData, 'removeItem').andCallThrough();

The function andCallThrough delegate calls to the actual implementations. The function getAllItems sends an HTTP GET request to the service. Following statement configures a custom response on $httpBackend when Angular detects any such request:
httpBackend.expectGET('/api/shoppingCart/').respond(storedItems);

Fourth and final dependency is the shared service. Following snippet creates a mock shared service with a spy for setCartItems, the only function used in ShoppingCartCtrl:
sharedMock = {
    setCartItems: jasmine.createSpy('setCartItems')
};

Now that we have all the mocks ready, let’s create an object of the controller.
ctrl = $controller(ShoppingCartCtrl, { $scope: ctrlScope, $window: windowMock, shoppingData: _shoppingData, shared: sharedMock });

Testing behaviour of the controller
On creation of the controller, it calls getAllItems function of shoppingData service to fetch details of all items. The test for this behaviour should check if the right function is called and if it sets value to the items property. Following test shows this:

it("Should call getAllItems function on creation of controller and set items property", function () {
    expect(_shoppingData.getAllItems).toHaveBeenCalled();
    httpBackend.flush();
    expect(ctrlScope.items.length).not.toBe(0);
});

Upon calling addItem function of the controller, it calls addAnItem function of shoppingData service. As it makes an HTTP post request to the service, $httpBackend should be configured to respond when it finds a post request. Test looks as follows:
it("Should call addAnItem function of the shoppingData service", function () {
    httpBackend.expectPOST('/api/shoppingCart/', {}).respond(storedItems.push({ "Id": 5, "Name": "Item5", "Price": 70, "Quantity": 10 }));
    ctrlScope.addItem({});
    expect(_shoppingData.addAnItem).toHaveBeenCalled();
    httpBackend.flush();
    expect(storedItems.length).toBe(5);
});

The function removeItem can also be tested in similar way. But, what if a request fails? The $errorMessage property of scope should be assigned with a friendly error message. A request can be forced to fail by passing a JavaScript object literal with an error status code to $httpBackend. Let’s see this in action:
it("Should assign an error message", function () {
    httpBackend.expectDELETE('/api/shoppingCart/1').respond({ status: 500 });
    ctrlScope.removeItem(1);
    expect(ctrlScope.errorMessage).not.toBe("");
});

mySortFunction is used to convert numeric value to number. We can test this function by passing a number in the form of a string and checking if it returned a number to us. We need to set the property sortExpression before calling the function.
it("Should return a number when a number is passed in", function () {
    var item = { "Number": "123" };
    ctrlScope.sortExpression = "Number";
    var numVal = ctrlScope.mySortFunction(item);
    expect(typeof numVal).toBe("number");
});

The totalPrice function is very easy to test, as we need to just check if it sets some value to the returned variable.

On click of Purchase Items link on the page, the user has to be navigated to CheckoutItems view and setCartItems function of shared service should be called to pass the items array to the second view. As we are setting navigation URL to window.location.href, for which we created a mock, the test has to check if this property is set to some value. Following test verifies these functionalities:

it("Should set value in shared and value of href set", function () {
    ctrlScope.items = storedItems;
    ctrlScope.purchase();
 
    expect(sharedMock.setCartItems).toHaveBeenCalled();
    expect(windowMock.location.href).not.toBe("");
});

Now view the test runner page on browser. All the tests should be passed. I encourage you to play a bit with the code and tests and check the result of test after the changes. This way, we will get to know more about Jasmine's behavior as well as unit testing.

You can download the code including unit tests from the following GitHub repo: AngularShoppingCart

Happy coding!

Wednesday, 27 March 2013

Templates, Routing and Sharing Data Between Views in an Angular JS Application

Till last post, we saw the capabilities of Angular JS within a single page with a form and how to interact with service using AJAX. Another key feature that Angular JS provides is, view composition. We can compose multiple views on the same page, based on some templates which will be loaded as and when they are required. We will discuss about these features in this post.

To make an HTML page able to compose multiple views using AngularJS, we need to add an element with ng-view attribute. Content will be dynamically added inside this element based on certain rules defined by the programmer. Following is the mark-up inside the body tag after removing all content and adding a div with ng-view attribute:

<body ng-app="shopping">
    <div ng-view>
    </div>
</body>

The entire mark-up that we had earlier on the page is moved to AddRemoveItems.htm. No change has been made to the mark-up.
<div>
    Sort by:
    <select ng-model="sortExpression">
        <option value="Name">Name</option>
        <option value="Price">Price</option>
        <option value="Quantity">Quantity</option>
    </select>
</div>
<div>
    <strong>Filter Results</strong></div>
<table>
    <tr>
        <td>
            By Any:
        </td>
        <td>
            <input type="text" ng-model="search.$" />
        </td>
    </tr>
    <tr>
        <td>
            By Name:
        </td>
        <td>
            <input type="text" ng-model="search.Name" />
        </td>
    </tr>
    <tr>
        <td>
            By Price:
        </td>
        <td>
            <input type="text" ng-model="search.Price" />
        </td>
    </tr>
    <tr>
        <td>
            By Quantity:
        </td>
        <td>
            <input type="text" ng-model="search.Quantity" />
        </td>
    </tr>
</table>
<table border="1">
    <thead>
        <tr>
            <td>
                Name
            </td>
            <td>
                Price
            </td>
            <td>
                Quantity
            </td>
            <td>
                Remove
            </td>
        </tr>
    </thead>
    <tbody ng-repeat="item in items | orderBy:mySortFunction | filter: search">
        <tr>
            <td>
                {{item.Name}}
            </td>
            <td>
                {{item.Price | rupee}}
            </td>
            <td>
                {{item.Quantity}}
            </td>
            <td>
                <input type="button" value="Remove" ng-click="removeItem(item.ID)" />
            </td>
        </tr>
    </tbody>
</table>
<div>
    Total Price: {{totalPrice() | rupee}}</div>
<a ng-click="purchase()">Purchase Items</a>
<form name="itemForm" novalidate>
<table>
    <tr>
        <td>
            Name:
        </td>
        <td>
            <input name="name" type="text" ng-model="item.Name" required ng-pattern="name" />
        </td>
    </tr>
    <tr>
        <td>
            Price:
        </td>
        <td>
            <input name="price" type="text" ng-model="item.Price" required valid-price />
        </td>
    </tr>
    <tr>
        <td>
            Quantity:
        </td>
        <td>
            <input name="quantity" type="number" ng-model="item.Quantity" min="1" max="90" ng-pattern="integerval"
                required />
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <input type="Button" value="Add" ng-click="addItem(item)" ng-disabled="itemForm.$invalid" />
        </td>
    </tr>
</table>
</form>
<div class="errorText">
    {{error}}</div>
<div ng-show="itemForm.name.$dirty && itemForm.name.$invalid">
    <span ng-show="itemForm.name.$error.required">Name cannot be left blank</span> <span
        ng-show="itemForm.name.$error.pattern">Name cannot contain numbers or special characters</span>
</div>
<div ng-show="itemForm.price.$dirty && itemForm.price.$invalid">
    <span ng-show="itemForm.price.$error.required">Price cannot be blank</span> <span
        ng-show="itemForm.price.$error.validPrice">Price should be a number between 50 and
        5000 with maximum 2 digits after decimal point</span>
</div>
<div ng-show="itemForm.quantity.$dirty && itemForm.quantity.$invalid">
    <span ng-show="itemForm.quantity.$error.required">Quantity cannot be blank</span>
    <span ng-show="itemForm.quantity.$error.pattern || itemForm.quantity.$error.min || itemForm.quantity.$error.max">
        Quantity should be an integer between 1 and 90</span>
</div>

Once a user adds all desired items to the cart, he should be able to check out the cart. For this, we should navigate the user to another page where the user can see the items on the cart and checkout the items. I created another template file, CheckoutItems.htm. This template will be rendered when the user clicks on checkout link on the AddremoveItems page. You can check the template from the project on Github.

The aim is to render one of these templates on the page based on the current URL. To make this happen, we need to configure routes to the module. Process of adding routes is similar to adding routes in Global.asax ASP.NET MVC. Each route will hold the following information:

  • URL template of the page
  • Path of the HTML template to be rendered
  • Name of the controller
Following is the syntax of configuring routes to the module:
module.config([‘$routeProvider’,<other dependencies>, function($routeProvider,<other parameters>){
 $routeProvider.when(‘<url-template>’,{templateUrl:’<path-of-html-template>’,controller:<name-of-controller>})
   .otherwise({redirectTo:’<default-url-template-to-render>’});
}]);

To learn more on routing, refer to Angular JS official documentation.

Let’s configure routes to shopping module keeping the above syntax in mind. Following are the templates added to the module in our application:

shoppingModule.config(['$routeProvider', function($routeProvider){
        $routeProvider.when('/addRemoveItems',{templateUrl:'Templates/AddRemoveItems.htm',controller:ShoppingCartCtrl})
                      .when('/checkoutItems',{templateUrl:'Templates/CheckoutItems.htm',controller:CartCheckoutCtrl})
                      .otherwise({redirectTo: '/addRemoveItems'});
    }]);

In the AddRemoveItems view, we should have a hyper link to navigate to the CheckoutItems page. When the user clicks on this link, we should send shopping cart data to the checkout view. Since both views have separate controllers, we have to store the data at a central place to make it accessible in the controller of second page. Let’s add a service to the shopping module to hold this data.
shoppingModule.service('shared',function(){
        var cartItems= [];
        return{
            getCartItems: function(){
                return cartItems;
            },
            setCartItems: function(value){
                cartItems=value;
            }
        };
    })

On click of the link on the AddRemoveItems page, the data has to be assigned to cartItems field in the above service and the control has to be navigated to checkout view. This is done using the following function:
$scope.purchase = function () {
        shared.setCartItems($scope.items);
        $window.location.href = "#/checkoutItems";
};

$window used in the above function is a service in Angular JS that references to the browser’s window object. Since we are using it in the controller, it should be injected through parameter. This data can be accessed in checkout view using the shared service. Following code shows how to do it:
function CartCheckoutCtrl($scope, shared){
    function loadItems() {
        $scope.items = shared.getCartItems();
    }
 
    loadItems();
}

Now we have a tiny shopping cart application with two pages. This is definitely not a great application, but it covers most of the useful features of Angular JS.

Complete code of the application is available in the following github repo: AngularShopping

Cart Run the application setting ShoppingCart-MultipleViews.htm as the start-up page. Notice the URL once the page is loaded on browser. Click on the link, it should move to the Checkout view, with an update to the URL. You can also switch between the views using browser’s back and forward buttons.

The point to be observed during navigation is, the page is not fully refreshed. You won’t see the progress bar showing load status when the navigation happens. This is because, we are rendering a small part of the page(portion in the div marked with ng-view) using a template.

Happy coding!

Wednesday, 13 March 2013

Moving AJAX calls to a custom service in Angular JS

In my last post on Angular JS, we moved the data into an ASP.NET Web API controller and invoked the data using $http, a service in Angular JS that abstracts AJAX calls. But the code resided in the controller and that is not good. Responsibility of the controller should be to sit between data and view, but not to call services using AJAX. So, let’s move the AJAX calls to a separate component.

The AJAX calls made using $http service are executed asynchronously. They return promise objects, using which their status can be tracked. As we will be moving them into a custom service, the controller depending on them should be notified with the status of completion. The notification can be sent using the promise object returned by the service functions or, we can create our own deferred object using $q service.

I discussed about deferred and promise in jQuery earlier in a post. Basic usage of the pattern remains the same with $q as well, except a small difference syntax. Following snippet is shows the way of creating a deferred object, calling success and failure functions using $q:

function myAsyncFunc(){
//Creating a deferred object
var deferred = $q.defer();
operation().success(function(){
    //Calling resolve of deferred object to execute the success callback
    deferred.resolve(data);
  }).error(function(){
    //Calling reject of deferred object to execute failure callback
    deferred.reject();
  });
  //Returning the corresponding promise object
  return deferred.promise;
}

While calling the above function, a callback to be called on success and a callback to be handled on failure should be attached. It might look as follows:
myAsyncFunction().then(function(data){
    //Update UI using data or use the data to call another service
  },
  function(){
    //Display an error message
  });

The functions responsible for making AJAX calls should follow this pattern as the functions in $http are executed asynchronously. To notify the dependent logic about state of execution of the functionality, we have to use the promise pattern.

As we will be enclosing this functionality in a custom service which requires $http for AJAX and $q for promise, these dependencies will be injected at the runtime when the module is loaded. Following snippet demonstrates the implementation of a function to retrieve items in shopping cart calling Web API service:

angular.module('shopping', []).
  factory('shoppingData',function($http, $q){
    return{
      apiPath:'/api/shoppingCart/',
      getAllItems: function(){
        //Creating a deferred object
        var deferred = $q.defer();

        //Calling Web API to fetch shopping cart items
        $http.get(this.apiPath).success(function(data){
          //Passing data to deferred's resolve function on successful completion
          deferred.resolve(data);
      }).error(function(){

        //Sending a friendly error message in case of failure
        deferred.reject("An error occured while fetching items");
      });

      //Returning the promise object
      return deferred.promise;
    }
  }

Following is the controller consuming the above custom service:
function ShoppingCartCtrl($scope, shoppingData) {
  $scope.items = [];

  function refreshItems(){
    shoppingData.getAllItems().then(function(data){
      $scope.items = data;
    },
    function(errorMessage){
      $scope.error=errorMessage;
    });
  };

  refreshItems();
};

As you see parameters of the controller, the second parameter shoppingData will be injected by the dependency injector during runtime. The function refreshItems follows the same convention as the snippet we discussed earlier. It does the following:
  • On successful completion of getAllItems() function, it assigns data to a property of $scope object which will be used to bind data
  • If the execution fails, it assigns the error message to another property of $scope object using which we can display the error message on the screen

The controller is free from any logic other than updating data that is displayed on the UI.

Functions to add a new item and remove an existing item also follow similar pattern. You can find the complete code in the following github repo: AngularShoppingCart

Happy coding!

Friday, 8 March 2013

Understanding Promise Pattern in JavaScript Using jQuery’s Deferred Object

Asynchronous programming is used almost everywhere these days. JavaScript is no exception. In rich JavaScript applications, we have to perform several tasks like calling a service using AJAX, caching data, applying animations and some new cases might arise while writing the application.

Irrespective of whether an operation is synchronous or asynchronous, we need a response from the when the operation is succeeded or even when it fails. Synchronous operations are usually enclosed within try…catch blocks to check for errors. As asynchronous operations run in background and we can’t determine when they will complete, their failures cannot be caught by the catch block. Even in case of successful completion, the response won’t be available for the immediate next statement. These cases are handled using callbacks.

We see several patterns in which callbacks are registered. While using raw AJAX invocations with XMLHttpRequest, we assign the callback to onreadystatechange property of the object, as shown below:

var xhr = new XMLHttpRequest();
xhr.open(“GET”,url, true);
xhr.send();

xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        if(xhr.status == 200){
     successCallback(xhr.responseText);
        }
        else{
            failureCallback(xhr.responseText);
        }
    }
};

We also see the cases where the asynchronous function accepts a callback function as a parameter.
invokingAsyncFunction(successCallback(data), failureCallback(error));

These callbacks look good unless we have a chain of three or more asynchronous calls. When the number goes up, it becomes difficult to handle them and the code becomes less readable.

We can overcome this difficulty using the Promise pattern. The Promise pattern believes in returning a deferred object that can be used to call a piece of logic when the underlying asynchronous operation is either resolved or rejected. In other words, we can say the pattern promises us that it would send a result when it gets. The result can be data if the operation is successful or details of an error in case of failure.

The deferred object will hold the current state of the asynchronous operation. At any given time, the deferred object will have one of the three states: unresolved, resolved and rejected.

The deferred object would be in unresolved state when it is waiting for the asynchronous operation to complete. Once the operation is completed successfully, it enters resolved state. Otherwise, it enters rejected state.

jQuery library added support of deferred in jQuery 1.5. The library itself uses this feature for implementation of AJAX features.

jQuery’s deferred object makes it easy to write asynchronous code in JavaScript. Following steps must be followed while writing an asynchronous function using deferred object:

  1. Get a deferred object by calling the $.Deferred() constructor
  2. In case of success, call resolve function passing result of the operation
  3. In case of failure, call reject function passing the error details
  4. Return deferred’s promise object, which provides ways to attach callbacks and determine current state of the deferred object

With this understanding, let’s put the above AJAX logic in a function and make it asynchronous using jQuery’s deferred object:
function ajaxCallToAUrl(url){
  var deferred = $.Deferred();    //Getting a deferred object
  var xhr = new XMLHttpRequest();

  xhr.open(“GET”,url,true);
  xhr.send();

  xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
      if(xhr.status==200)
        deferred.resolve(xhr.responseText);  //Calling resolve() in case of success
      
      else
        deferred.reject(xhr.responseText);  //Calling reject() in case of failure
    }
  }
  return deferred.promise();  //Returning the promise object
}

Following are the steps to be followed while calling the above function:
  1. Call the function and store the returned promise in an object
  2. Attach a callback to done() function of promise. It will be called when the deferred object enters resolved state
  3. Attach a callback to fail() function of promise. It will be called when the deferred object enters rejected state

Following snippet demonstrates it:
var promise = ajaxCalToAUrl(url);
promise.done(function(data){
    //Update the UI to bind data obtained
}.fail(function(error){
    //Display the error message
});

The success and failure functions can also be attached to the promise object using then function as well. The then() function accepts three callbacks, first one is for success, second one is for failure and the third one is for handling progress. Failure and progress callbacks are optional. Progress callback is executed when deferred receives a progress notification. Above implementation can be expressed as follows using then function:
promise.then(function(data){
    //Update the UI to bind data obtained
}, function(error){
    //Display the error message
}, function(){
    //Notify user that the operation is in progress
});

Using then(), we can chain multiple operations as well. Following snippet demonstrates chaining:
var secondPromise = firstPromise.then(function(data){
    return callAnotherAsyncFunction(data);     //Assuming the function callAnotherAsyncFunction returns a promise
});

secondPromise.done(function(data){
    //Chained request is successful. Update UI with the data obtained
});
We can also combine multiple requests using $.when(). The when() function accepts multiple deferred objects. It returns a promise object. State of the when function changes to resolved when all the operations are successfully completed. If any of the operation is failed, state of when changes to rejected.
$.when(deferred1, deferred2).done(function(){
    //Logic to be executed on successful execution
}).fail(function(){
    //Logic to be executed upon failure of any of the operations
});

This is a beginning to using promises. jQuery's deferred object offers capabilities to forcefully reject the operation, notify change of status and some other features that we may require in an application.

References:


Documentation on jQuery’s official site about deferred objects
Article about deferred and promise on MSDN ScriptJunkie


Happy coding!