Using Modernizr in Angular unit test

I have an Angular app defined in a Grails gsp file. The Modernizr library is included at the gsp level.

I need to use a library in a unit test directive. Since I don't have Modernizr defined as a module, since it is used outside of the Angular application as well as inside it, how do I put it into my Angular unit test?

Here's my directive:

'use strict';

angular.module('simplify.directives').directive('img', ['$timeout', function ($timeout) {
    return {
        restrict: 'A',
        link: function (elem, attrs) {
            if ( typeof Modernizr !== 'undefined' && !Modernizr.svg ) {
                $timeout(function(){
                    elem.attr('src', attrs.src.replace('.svg', '.png'));
                });
            }
        }
    };
}]);

      

Here's my unit test code:

'use strict';

describe('Testing SVG to PNG directive', function() {
    var scope,
        elem;

    beforeEach(module('app'));

    beforeEach(module(function($provide) {
        $provide.service('appConstants', function(){});
    }));

    beforeEach(inject(function($compile, $rootScope) {
        elem = angular.element('<img ng-src="test-img.svg" />');
        scope = $rootScope;
        $compile(elem)(scope);
        scope.$digest();
    }));

    it('Should swap svg for png image if svg is not supported', function() {
       //force Modernizr.svg to be undefined here for purposes of the test
        expect(elem.attr('src')).toBe('test-img.png');
    });

});

      

What's the best way to do this?

+3


source to share


1 answer


You can do this by updating the directive to inject $window

and get an instance Modernizr

from $window

.

i.e: -

.directive('img', ['$timeout','$window', function ($timeout, $window) {
    return {
        restrict: 'E',
        link: function (scope, elem, attrs) {

            if ( typeof $window.Modernizr !== 'undefined' && !$window.Modernizr.svg ) {
                $timeout(function(){
                    elem.attr('src', attrs.src.replace('.svg', '.png'));
                });
            }
        }
    };
}]); 

      

In your test, just mock Modernizr and since you are using $timeout

you need to reset timeout

by doing $timeout.flush()

inorder for the timeout callback to execute.

describe('Testing SVG to PNG directive', function() {
    var scope,
        elem, 
        ModernizerMock = {svg:false};// <-- use this for mocking various conditions

    beforeEach(module('app'));

    beforeEach(module(function($provide) {
        $provide.service('appConstants', function(){});
    }));

    beforeEach(inject(function($compile, $rootScope, $timeout, $window) {
        elem = angular.element('<img ng-src="test-img.svg" />');
        scope = $rootScope;
        $window.Modernizr = ModernizerMock; //Set the mock
        $compile(elem)(scope);
        scope.$digest();
        $timeout.flush(); //<-- Flush the timeout
    }));

    it('Should swap svg for png image if svg is not supported', function() {
       //force Modernizr.svg to be undefined here for purposes of the test
          expect(elem.attr('src')).toBe('test-img.png');
    });
});

      



Plnkr

and your directive was like this:

.directive('img', ['$window', function ($window) {
        return {
          restrict: 'E',
          compile: function (elem, attrs) {
            if ( typeof $window.Modernizr !== 'undefined' && !$window.Modernizr.svg ) {
               attrs.$set('ngSrc', attrs.ngSrc.replace('.svg', '.png'));
            }
          }
      };
 }]);

      

It would be less effort to test with no timeout logic. Plnkr

+2


source







All Articles