Win Win - 2 months ago 16
AngularJS Question

How to Unit test an angular directive that has a bind('error', function(){})?

I have an angular directive that replaces the image src of an element if the file does not exist and a 404 is returned. Here it is:

myApp.directive('fallBackSrc', function() {
var fallBackSrc = {
link: function postLink(scope, element, attrs) {
element.bind('error', function () {
angular.element(this).attr("src", '/images/image-not-available.png');
});
}
}
return fallBackSrc;
}]);


This works as expected but now I am trying to unit test this directive, how will I trigger the 'error' that this function is bound to in jasmine?

Answer

In order to test this you will need to spyOn the element.bind using Jasmine and also use Jasmines 2.0 done function.

So in my example in jsfiddle I have added a place holder image as a replacement image to stop it causing an error.

angular.module('components', [])
    .directive('fallBackSrc', function() {
        var fallBackSrc = {
            link: function postLink(scope, element, attrs) {
                element.bind('error', function () {
                    angular.element(this).attr("src", 'http://placehold.it/350x150');
                });
            }
        }
        return fallBackSrc;
    });

and in the test we can spyOn element.bind and return error when it is called

spyOn(element, 'bind').and.returnValue('error');

Also we need to use the done function for running specs that require testing asynchronous operations by passing it into the test to use in the setTimeOut.

describe('Directive: fallBackSrc', function() {
        describe('if the image does not exist it', function() {

        var element, scope;

        beforeEach(module('components'));

        beforeEach(inject(function($rootScope, $compile) {
            element = angular.element('<img fall-back-src src="images/no-image.jpg" />');
            spyOn(element, 'bind').and.returnValue('error');
            scope = $rootScope;
            $compile(element)(scope);
            scope.$digest();
        }));

        it("should contain the place holder img src", function(done) {          
            setTimeout(function(){  
                console.log(element.attr('src'));
                expect(element.attr('src')).toEqual('http://placehold.it/350x150'); 
                done();
            }, 2000);
        });
    });

});