Priyabrat Nanda Priyabrat Nanda -4 years ago 117
AngularJS Question

angularjs directive unit testing with jasmine with template and link

I have a directive as below which i want to cover as part of my jasmine unit test but not sure how to get the template value and the values inside the link in my test case. This is the first time i am trying to unit test a directive.

angular.module('newFrame', ['ngResource'])
.directive('newFrame', [
function () {

function onAdd() {
$log.info('Clicked onAdd()');
}

return {
restrict: 'E',
replace: 'true',
transclude: true,
scope: {
filter: '=',
expand: '='
},
template:
'<div class="voice ">' +
'<section class="module">' +
'<h3>All Frames (00:11) - Summary View</h3>' +
'<button class="btn" ng-disabled="isDisabled" ng-hide="isReadOnly" ng-click="onAdd()">Add a frame</button>' +
'</section>' +
'</div>',
link: function (scope) {

scope.isDisabled = false;
scope.isReadOnly = false;

scope.onAdd = onAdd();
}
};
}
]);

Answer Source

Here is an example with explanation:

describe('newFrame', function() {

  var $compile,
    $rootScope,
    $scope,
    $log,
    getElement;

  beforeEach(function() {

    // Load module and wire up $log correctly
    module('newFrame', function($provide) {
      $provide.value('$log', console);
    });

    // Retrieve needed services
    inject(function(_$compile_, _$rootScope_, _$log_) {
      $compile = _$compile_;
      $rootScope = _$rootScope_;
      $scope = $rootScope.$new();
      $log = _$log_;
    });

    // Function to retrieve a compiled element linked to passed scope
    getCompiledElement = function(scope) {
      var element = $compile('<new-frame></new-frame>')(scope);
      $rootScope.$digest();
      return element;
    }

    // Set up spies
    spyOn($log, 'info').and.callThrough();
  });

  it('test', function() {

    // Prepare scope for the specific test
    $scope.filter = 'Filter';
    $scope.expand = false;

    // This will be the compiled element wrapped in jqLite
    // To get reference to the DOM element do: element[0]
    var element = getCompiledElement($scope);

    // Get a reference to the button element wrapped in jqLite
    var button = element.find('button');

    // Verify button is not hidden by ng-hide
    expect(button.hasClass('ng-hide')).toBe(false);

    // Verify button is not disabled
    expect(button.attr('disabled')).toBeFalsy();

    // Click the button and verify that it generated a call to $log.info
    button.triggerHandler('click');
    expect($log.info).toHaveBeenCalled();
  });
});

Demo: http://plnkr.co/edit/tOJ0puOd6awgVvRLmfAD?p=preview

Note that I changed the code for the directive:

  1. Injected the $log service
  2. Changed scope.onAdd = onAdd(); to scope.onAdd = onAdd;
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download