Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS: Directive restrict : 'E' prevents element click() event being called in Jasmine unit test

Here are a couple of directives, and unit tests.

Here is the first directive:

directive('myTestDirective', function() {
    return {
        link: function(scope, element, attrs) {
            element.on("click", function(e) {
            scope.clicked = true;
            console.log("clicked");
        }
    }
});

And the unit test:

describe('my test directive', function() {
    beforeEach(function() {
        .....
        inject($compile, $rootScope) {
            scope = $rootScope.$new();
            html = '<div my-test-directive></div>';
            elem = angular.element(html);
            compiled = $compile(elem);
            compiled(scope);
            scope.$digest();
        }
    });
    it('should set clicked to true when click() is called', function() {
        elem[0].click();
        expect(scope.clicked).toBe(true);
    });
});

When the above unit test is run, the test passes and clicked is logged to the console.

However, consider this directive with restrict: E added:

directive('myDirective', function() {
    return {
        restrict: 'E',
        link: function(scope, element, attrs) {
            element.on("click", function(e) {
            scope.clicked = true;
            console.log("clicked");
        }
    }
});

And the unit test:

describe('my directive', function() {
    beforeEach(function() {
        .....
        inject($compile, $rootScope) {
            scope = $rootScope.$new();
            html = '<my-directive></my-directive>';
            elem = angular.element(html);
            compiled = $compile(elem);
            compiled(scope);
            scope.$digest();
        }
    });
    it('should set clicked to true when click() is called', function() {
        elem[0].click();
        expect(scope.clicked).toBe(true);
    });
});

This test fails. clicked is not logged to the console. From debugging I can see that the function bound the click() binding for the directive is not being executed.

How can I continue to use restrict : 'E', while still retaining the ability to simulate clicks in unit tests?

Update: I have it working, thanks to Michal's plunkr.

I changed the inject() function to be:

inject(function($compile, $rootScope, $document) {
    scope = $rootScope.$new();
    html = '<my-test-directive-element></my-test-directive-element>';
    elem = angular.element(html);
    $compile(elem)(scope);
    scope.$digest();
});

After this, both clicking using restrict attribute and restrict element work.

Plukr is here: http://plnkr.co/edit/fgcKrYUEyCJAyqc4jj7P

like image 250
div5 Avatar asked Nov 02 '22 08:11

div5


1 Answers

Using jqLite on('click') is not very Angular-ish and I don't think it would be processed by Angular digest cycle (thus whatever you would add to your scope within that callback wouldn't be rendered in your DOM unless you do it manually). You should prefer using the built-in ng-click directive within yours, so the html code becomes:

<my-directive ng-click="onClick()"></my-directive>

and your directive:

directive('myDirective', function() {
  return {
    restrict: 'E',
    link: function(scope, element, attrs) {
      scope.onClick = function() {
        scope.clicked = true;
        console.log("clicked");
      }
    }
  }
});
like image 189
floribon Avatar answered Nov 11 '22 14:11

floribon