Andresch Serj
Andresch Serj

Reputation: 37318

karma: unit testing controller that listens on angular-ui-router event

I try to unit test an angularJS controller with Kara/Sinon/Jasmine. The controller listens to state changes from angular-ui-router to call a service.

I stubbed the service method (update) using sinon and i use $broadcast to throw the event in the tests. I use $apply to fire the event.

However, it seems the controller does not seem to react.

I try to check for teh sinon stubbed method and i also use console.log to see weather or not the controller reacts - but it does not. It does in the manual browser test, so i guess it is my test that needs to be fixed (should be the other way round, i know).

What am i doing wrong here?

the karma test specs:

'use strict';    
describe('controllers', function() {
    beforeEach(module('myApp.controllers'));
    beforeEach(module('myApp.services'));
    beforeEach(module('ui.router'));

    describe('myAppController', function() {
        var scope, ctrl;

        beforeEach(inject(function(
            $rootScope, $controller, $injector,ParamsHelper) {

            scope = $rootScope.$new();
            scope.ParamsHelperStub  = sinon.stub(ParamsHelper, 'update');

            ctrl = $controller('myAppController', {
                $scope: scope,
                ParamsHelper: scope.ParamsHelperStub
            });


        }));

        it('should use ParamsHelper if is deepLink', function() {
            var event       = {};
            var toState     = {name:'regions'};
            var toParams    = ['test'];
            scope.AppSettingsStub.state.isDeepLink = true;
            scope.$broadcast("$stateChangeStart", event, toState, toParams);
            scope.$apply();

            expect(scope.ParamsHelperStub.calledWith(['test'])).toBeTruthy();
        });

    });
});

From the controller:

...

rootScope.$on('$stateChangeStart',
  function(event, toState, toParams) {
    console.log('VibeController: $stateChangeStart Event catched');
    ParamsHelper.update(toParams);

    ...

Upvotes: 2

Views: 1961

Answers (1)

Andresch Serj
Andresch Serj

Reputation: 37318

The problem was in the scope. To fire an event that can be recognized by the controller i need to fire it in the rootScope context.

I added the rootScope in the initial injection and then edited the broadcasting command accordingly:

describe('myAppController', function() {
  var scope, ctrl, rootScope;

  beforeEach(inject(function(
    $rootScope, $controller, $injector, ParamsHelper) {

    rootScope = $rootScope;

    ...

    rootCope.$broadcast("$stateChangeStart", event, toState, toParams);

Upvotes: 3

Related Questions