Oleg Belousov
Oleg Belousov

Reputation: 10111

Testing a directive that changes an attribute an img element upon error

Test:

'use strict';

describe('Directive: avatar', function () {

  // load the directive's module
  beforeEach(module('app'));

  var element,
    scope,
    avatar_conf,
    timeout,
    mocked_avatar = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';

  beforeEach(inject(function ($rootScope, _$timeout_, _avatar_conf_) {
    scope = $rootScope.$new();
    avatar_conf = _avatar_conf_;
    timeout = _$timeout_;
  }));

  it('should set default alt property for an avatar that cannot be loaded', inject(function ($compile) {
    element = angular.element('<img avatar src="mock.jpg">');
    element = $compile(element)(scope);
    scope.$digest();
    expect(element.attr('alt')).toBe(avatar_conf.default_alt);
  }));

Code:

!(function (window, angular) {
    'use strict';

    /**
     * @ngdoc directive
     * @name app.directive:social
     * @description
     * # social
     */
    angular.module('app.directives')
        .directive('avatar', function(avatar_conf) {
            return {
                restrict: 'A',
                link: function(scope, element, attrs) {
                    element.bind('error', function() {
                        if(!scope.$$phase){
                            scope.$apply(function(){
                                attrs.$set('src', avatar_conf.default_image);
                                attrs.$set('alt', avatar_conf.default_alt);
                            });
                        }

                    });
                }
            };
        });
}(window, window.angular));

Problem: Assertion always happens before the linker gets a chance to change the attrs. Placing the assertion inside of a timeout of 0 caused it to to be invoked at all(a hack that used to work for making the assertion after the DOM is loaded).

Upvotes: 1

Views: 1777

Answers (1)

Oleg Belousov
Oleg Belousov

Reputation: 10111

solution was upgrading to Jasmine 2.0 and defining an async test:

Upgrade Jasmine, karma-jasmine, and grunt-jasmine

$ npm install jasmine --save-dev
$ npm install karma-jasmine --save-dev
$ npm install grunt-jasmine --save-dev

test:

  it('should set default alt property for an avatar that cannot be loaded', function(done){
    element = angular.element('<img avatar src="mock.jpg">');
    element = $compile(element)(scope);
    scope.$digest();

    setTimeout(function(){
        expect(element.attr('alt')).toBe(avatar_conf.default_alt);
        done();
    }, 200);

  });

Upvotes: 1

Related Questions