1

I have the following controller...

 angular.module('jobBoard').controller('JobListController', ['$scope','$window', function($scope, $window){

    $scope.keywordPlaceholder = 'What kind of job?';
    $scope.locationPlaceholder = 'Where? (city, state or zip)';

    $scope.onResize = function(){
        if ($window.innerWidth <= 480){
            $scope.keywordPlaceholder = 'What?';
            $scope.locationPlaceholder = 'Where?';
        }
    }

    angular.element($window).bind('resize', function(){
        $scope.onResize();
        $scope.$apply();
    })

    $scope.onResize();
    $scope.loadJobs();
}]);

and this is the jasmine test...

describe('JobListController', function(){
    var scope, controller;

    describe('binding resize to window', function(){
        var mockWindow = {
            resize: function(){}
        }

        beforeEach(inject(function($rootScope, $controller){
            scope = $rootScope.$new();
            $controller('JobListController', { $scope:scope, $window: mockWindow});
        }))

        it('binds to the resize function', function(){
            spyOn(scope, 'onResize');
            spyOn(scope, '$apply');
            mockWindow.resize();
            expect(scope.onResize).toHaveBeenCalled();
            expect(scope.$apply).toHaveBeenCalled();
        })
    })
})

but it's failing on the scope.onResize expectation. I've googled like crazy on how to properly do this but can't seem to find the right answer. Any ideas? Thanks.

2 Answers 2

1

To be honest, I've never tried this, so I can't tell you if it's going to work. However - you're confusing calling a function with triggering an event. Your bind statement binds to an event, not a function call.

From the MDN docs on javascript events, you should be able to do something like this to create an event with the name "resize" and trigger it:

describe('binding resize to window', function(){
    // Get a DOM element (there's probably a better way to do this...)
    var mockWindow = angular.element('<div>')[0];
    // create the event
    var resizeEvent = new Event('resize');


    beforeEach(inject(function($rootScope, $controller){
        scope = $rootScope.$new();
        $controller('JobListController', { $scope:scope, $window: mockWindow});
    }))

    it('binds to the resize function', function(){
        spyOn(scope, 'onResize');
        spyOn(scope, '$apply');
        // call the event.
        mockWindow.dispatchEvent(event);
        expect(scope.onResize).toHaveBeenCalled();
        expect(scope.$apply).toHaveBeenCalled();
    })
})
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. This works fine for chrome but phantomjs complains about the new Event. Apparently this is an issue with phantomjs.
@geoffswartz: I've posted another solution that work well in PhantomJS.
0

If you want to test that you attach to the event, Angular's $window service serves that purpose nicely:

describe('JobListController', function(){
  var scope, controller;

  describe('binding resize to window', function(){
    beforeEach(inject(function($rootScope, $controller){
      scope = $rootScope.$new();
      spyOn($window, 'addEventListener').and.callThrough();
      $controller('JobListController', { $scope:scope });
    }))

    it('binds to the resize function', function() {
      expect($window.addEventListener).toHaveBeenCalledWith('resize', scope.onResize);
    })
  })
})

In your controller, bind using addEventListener instead:

$window.addEventListener('resize', scope.onResize);

It allow to test when you unbind the event, too:

it('stop listening to window resize', function () {
    compileDirective();
    spyOn($window, 'removeEventListener');

    scope.$destroy();

    expect($window.removeEventListener).toHaveBeenCalledWith('resize', scope.onResize);
});

After that, you're free to test your scope.onResize logic independently.

Pros:

  • Easy to do.
  • Allow to test the unbind of event
  • Works well in any browser (even PhantomJS)

Cons:

  • It does not test the interaction between each parts (the event, the listener, the handler). I rely on higher level tests for that (ie: E2E).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.