0

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();
            }
        };
    }
]);

2 Answers 2

3

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

Comments

0

After reading the angular documentation for directives,i was able to solve this. Since the restrict is marked as E, the directive can only be injected through a element name. Earlier i was trying through div like below.

angular.element('<div new-frame></div>')

This will work if restrict is marked as A (attributes). Now i changed my injection in he spec file to match the directive with element name.

angular.element('<new-frame></new-frame>')

Now i was able to get the template and scope attributes in my spec. Just to be sure to accept everything, the combination of A (aatributes), E (elements) and C (class name) can be used in the restrict or any 2 as needed.

Comments

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.