Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit test angular directive that uses ngModel

I am trying to unit test a directive that uses ngModel and having difficulties. It seems that the link function of my directive is never being called...

Here is my directive code:

coreModule.directive('coreUnit', ['$timeout', function ($timeout) {
    return {
        restrict: 'E',
        require: '?ngModel',
        template: "{{output}}",
        link: function (scope, elem, attrs, ngModelCtrl) {
            ngModelCtrl.$render = function () {
                render(ngModelCtrl.$modelValue);
            };
            console.log("called");
            function render(unit) {
                if (unit) {
                    var output = '(' +
                        unit.numerator +
                        (unit.denominator == '' ? '' : '/') +
                        unit.denominator +
                        (unit.rate == 'NONE' || unit.rate == '' ? '' : '/' + unit.rate) +
                        ')';
                    scope.output = output == '()' ? '' : output;
                }
            }
        }
    }
}]);

Here is my test spec:

describe('core', function () {
    describe('coreUnitDirective', function () {
        beforeEach(module('core'));

        var scope,
            elem;

        var tpl = '<core-unit ng-model="myUnit"></core-unit>';

        beforeEach(inject(function ($rootScope, $compile) {
            scope = $rootScope.$new();
            scope.myUnit = {};
            elem = $compile(tpl)(scope);
            scope.$digest();
        }));

        it('the unit should be empty', function () {
            expect(elem.html()).toBe('');
        });

        it('should show (boe)', function () {
            scope.myUnit = {
                numerator: 'boe',
                denominator: "",
                rate: ""
            };
            scope.$digest();
            expect(elem.html()).toContain('(boe)');
        });
    });
});

The console log output "called" is never occurring and obviously the elem in my test spec is never updating.

What am I doing wrong??

like image 749
mcottingham Avatar asked Aug 29 '14 17:08

mcottingham


People also ask

How to use ngmodel in angular?

In this article, we will see ngModel concept in Angular and its example with simple code in two steps. The ngmodel directive binds the value of HTML controls (input, select, textarea) to application data. With the ng-model directive you can bind the value of an input field to a variable created in Angular. The binding goes both ways.

Why do we need unit testing in angular?

By writing a unit test for your blocks (components, services, etc.), you can easily detect when there is a break. Our example Angular app has a service, a component, and an async task to simulate data being fetched from the server. How do you write an Angular test?

What are the different types of angular testing?

There are two types of Angular testing: Unit testing is the process of testing small, isolated pieces of code. Also known as isolated testing, unit tests do not use external resources, such as the network or a database

What are the reasons for not testing AngularJS?

With AngularJS, there is no excuse for not testing. Separation of Concerns Unit testing, as the name implies, is about testing individual units of code. Unit tests try to answer questions such as "Did I think about the logic correctly?" or "Does the sort function order the list in the right order?"


2 Answers

Turns out that I wasn't including the directive in my karma.config file :S. Adding it in resolved all of my issues.

like image 190
mcottingham Avatar answered Oct 05 '22 23:10

mcottingham


You can try out two things.

First, instead of using just a string tpl, try angular.element().

var tpl = angular.element('<core-unit ng-model="myUnit"></core-unit>');

Second, place the tpl in the beforeEach block. So the result should look like this:

beforeEach(inject(function ($rootScope, $compile) {
    var tpl = angular.element('<core-unit ng-model="myUnit"></core-unit>');
    scope = $rootScope.$new();
    scope.myUnit = {};
    elem = $compile(tpl)(scope);
    scope.$digest();
}));
like image 45
4kochi Avatar answered Oct 06 '22 00:10

4kochi