Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS how to unit test to ensure directives like ng-click point to valid code

I'm using Jasmine to write unit tests for our controllers, but wanted to get community feedback on how to handle this situation...

I have a controller - InvoiceController, like this:

angular.module('myModule').controller('myController', ['$scope',
    function($scope) {
        $scope.doSomething = function() {
            $scope.something = 'bar';
        };
    }
]});

In my unit tests I verify that my controller has the expected methods:

it('should be able to do some work', function() {

    // initialize scope properties
    scope.someProperty = 'foo';

    // load controller using those properties
    injectController();

    // do I have all of the functions necessary to do this work?
    expect(typeof (scope.doSomething)).toBe('function');

    // now execute test
    scope.doSomething();
    expect(scope.something).toBe('bar');       

}

And finally, in my html I have an element with an ng-click, like this:

<button ng-click="doSomehing()">Do Something</button>

Looks good, right? BUT, did anyone catch what I did wrong?

My ng-click method is misspelled, but all tests are green and life seems rosy...until I try to click on that guy and nothing happens. No render time error, no error on click. Hmm.

Several times now as I'm refactoring code this has got me. I rename doSomething to doSomethingCooler in the unit test and in the controller but miss a place in the html. After a minute of head scratching I see what was missed.

I'd love a way to ensure that the markup is valid. E2E tests seem to be the obvious solution, but those are prone to fragility so we are hoping there are some alternatives.

If this were ASP.Net I would attach the click events from code behind so that I would get compile time errors vs run time errors.

Thoughts??

Thad

like image 277
Thad Peiffer Avatar asked Aug 15 '13 19:08

Thad Peiffer


1 Answers

One thing you could do is get the template text and run $compile on it. And then link it to your controller's scope. Then you could do something like dom.find('[ng-click]').click();, which should throw if any of them is not defined in your controller's scope. This is similar to how you generally test directives.

like image 191
Daniel Tabuenca Avatar answered Oct 11 '22 11:10

Daniel Tabuenca