Testing angular controllers with Jasmine

Testing angular controllers with Jasmine

by pablojim

HTML

<script src="http://pivotal.github.io/jasmine/lib/jasmine-1.3.1/jasmine.js"></script>
<script src="http://pivotal.github.io/jasmine/lib/jasmine-1.3.1/jasmine-html.js"></script>
<link rel="stylesheet" href="http://pivotal.github.io/jasmine/lib/jasmine-1.3.1/jasmine.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular-mocks.js"></script>
<script src="https://rawgithub.com/chieffancypants/angular-loading-bar/master/build/loading-bar.js"></script>

JavaScript

//--- CODE --------------------------
    // Create module with controller
angular.module('myApp.controllers', ['chieffancypants.loadingBar'])
    .controller('MyCtrl', ['$scope', 'MyService', function ($scope, MyService) {
        //Get promise and once resolved set it in the scope
        MyService.fetchData('foo').then(function(result) {
            $scope.result = result;
        });
    }]);

jasmineNG = {};
//set $q in your test
jasmineNG.$q = null;
//Could make similar to test a failing promise
jasmineNG.createPromiseReturningSpy = function(retval) {
    return jasmine.createSpy().andCallFake(function() {
      res = jasmineNG.$q.defer();
      res.resolve(retval)        
      return res.promise
    });
}

// ---SPECS-------------------------
describe('myApp', function () {
    var scope,
        controller,
        service;
    beforeEach(function () {
        module('myApp.controllers');
    });
    
    // Mock service
    beforeEach(module(function ($provide) {
        service = {fetchData: jasmineNG.createPromiseReturningSpy("RESULT")}    
        $provide.value('MyService', service);
    }));
    
    describe('MyCtrl', function () {
        beforeEach(inject(function ($rootScope, $controller, $q) {
            //IMPORTANT! set $q on the test helper
            jasmineNG.$q = $q;
            scope = $rootScope.$new();
            controller = $controller('MyCtrl', {
                '$scope': scope
            });
        }));
        
        it('should call service and set result on scope', function () {
            expect(scope.result).not.toBeDefined();
            expect(service.fetchData).toHaveBeenCalledWith('foo');
            //Call apply to propogate changes
            scope.$apply();
            expect(scope.result).toBe('RESULT');
        });
 
        
    });
});

// --- Runner -------------------------
(function () {
    var jasmineEnv = jasmine.getEnv();
    jasmineEnv.updateInterval = 1000;

    var htmlReporter = new...