1

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... :-(

0

1 Answer 1

2

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();.
Sign up to request clarification or add additional context in comments.

3 Comments

Another point is that toEqual() can also be important compared with toBe(). If its not the same object then you should check with toEqual as dmahapatro has done. You can also check with contains().
@Asta You are right, contains() is the right method here... But this is not the main point.
@dmahapatro: Thanks! I suppose your answer is right... I have a problem now with my protractor "to sync with the page", here at work, dunno what the problem is... As soon as I get home (where I have a headed linux box, and protractor just works) I'll test your answer... I must say I finally could see a successful test just embracing the <form>...</form> inside a <div> tag... I suppose it has to do with protractor's "root.element" default value (a "<div>"...).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.