Question

I can't successfully unit test my angular.js directive (karma + jasmine)...

Basically, in my directive's compile function, I do replace element contents with a form.
When unit-testing, after

scope = $rootScope;
element = angular.element('<my-directive></my-directive>');
$compile(element)($rootScope);
scope.$digest();

I'd expect to find element to contain my form, with '... abc ...'...
That's not the case... :-(

This is my (simplified) directive:

angular.module('myApp')
  .directive('myDirective', function() {
    return {
      restrict: 'E',
      scope: {},
      compile: function(element) {
        element.replaceWith('<form> ... abc ... </form>');
      }
    };
  });

This is my test:

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

  beforeEach(angular.mock.module('myApp'));

  var element, scope;

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

  it('replaced content should contain abc', function() {
    expect(element.html()).toContain('abc');
  });

});

The directive works (in the browser I see 'abc'), but the "expect" test always fails: I do not get 'abc' in element's html(), but always get 'xyz'...

I'm sure I'm missing something obvious... :-(

Was it helpful?

Solution

I would have the test written as below. Demo PLUNKER

describe('Directive: paypalButton', function () {
  var element, scope, $compile;

  beforeEach(function(){
      module('myApp');

      inject(function ($rootScope, $compile) {
          scope = $rootScope;
          element = angular.element('<my-directive></my-directive>');
          $compile(element)(scope);
      });
  });

  it('replaced content should be abc', function() {
      element.scope().$digest();

      expect(element.text()).toEqual(' ... abc ... ');
  });
});

with this change in directive:

app.directive('myDirective', function() {
    return {
      restrict: 'E',
      scope: {},
      compile: function(element) {
          element.append('<form> ... abc ... </form>');  
      }
    };
  });

Note:-

  • I think while testing it does not like to replace the element altogether because directives scope is bound to that element. You can try append() on element.
  • Also, since you are using isolated scope in directive, digest cycle has to be initiated in the isolated scope. Therefore, element.scope().$digest();.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top