Daft
Daft

Reputation: 10964

Jasmine unit test for Angular directive

I have the following angular directive, which adds a tooltip when I hover over a span.

angular.module('mainMod')
    .directive('toolTip', [function() {
        return {
            restrict: 'A',
            scope: {
                theTooltip: '@toolTip'
            },
            link: function(scope, element, attrs){
                element.tooltip({ 
                        delay: 0, 
                        showURL: false, 
                        bodyHandler: function() {
                            return jQuery('<div class="hover">').text(scope.theTooltip);
                        } 
                });
            }
        }
    }])
    ;


<span ng-show="data.tooltip" class="icon" tool-tip="{{data.tooltip}}"></span>

I'm looking to write a unit test for this directive, atm I can't use jasmine-jquery.

I'm fairly new to writing unit tests, could anyone possibly help me out?

Give me some pointers or point me towards some helpful resources?

Any advice or suggestions would be greatly appreciated.

What I have atm isn't much...

describe('Unit testing tooltip', function() {
    var $compile;
    var $rootScope;

    // Load the myApp module, which contains the directive
    beforeEach(module('mainMod'));

    // Store references to $rootScope and $compile
    // so they are available to all tests in this describe block
    beforeEach(inject(function(_$compile_, _$rootScope_){
      // The injector unwraps the underscores (_) from around the parameter names when matching
      $compile = _$compile_;
      $rootScope = _$rootScope_;
    }));


    it(' ', function() {
        // Compile a piece of HTML containing the directive
        FAILS HERE --> var element = $compile("<span class='icon' tool-tip='{{data.tooltip}}'></span>")($rootScope); 

        $rootScope.$digest();

    });
});

It's failing with a message of

TypeError: undefined is not a function

I think it's being caused by the ($rootScope) at the end of the line I've specified above.

Upvotes: 1

Views: 2628

Answers (2)

themyth92
themyth92

Reputation: 1738

You have to wrap your DOM content with angular.element first before compiling it. I am not sure what the tooltip module you are using but I used the jQuery UI tooltip instead.

    //create a new scope with $rootScope if you want
    $scope  = $rootScope.$new();

    var element = angular.element("<span class='icon' tool-tip='This is the tooltip data'></span>");

    //use the current scope has just been created above for the directive
    $compile(element)($scope);

One more thing, because you are using isolate scope in your directive, to get the current scope from your directive, you need to call

   element.isolateScope()

based on this reference : How to Unit Test Isolated Scope Directive in AngularJS

For a working fiddle, you can found it here : http://jsfiddle.net/themyth92/4w52wsms/1/

Upvotes: 2

hon2a
hon2a

Reputation: 7214

Any unit test is basically the same - mock the environment, construct the unit, check that the unit interacts with the environment in the expected manner. In this instance, you'd probably want to mock the tooltip creator

spyOn(jQuery.fn, 'tooltip');

then compile some template using the directive (which you're already doing), then simulate the hover event on the compiled element and then check that the tooltip creator was called in the expected manner

expect(jQuery.fn.tooltip).toHaveBeenCalledWith(jasmine.objectContaining({
    // ... (expected properties)
}));

How you simulate the event depends on how the element.tooltip is supposed to work. If it really works the way you're using it in the question code, you don't need to simulate anything at all and just check the expected interaction right after template compilation.

Upvotes: -1

Related Questions