Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test behavior in the link function of a directive

In some of my directives, I'm adding functions to the scope to handle logic specific for the directive. For example:

link: function(scope, element, attrs) {          scope.doStuff = function() {             //do a bunch of stuff I want to test          }               } 

How do I go about testing that function? I googled around for how test a directive, but the things I found were more about testing changes on the element. I can certainly compile my directive before each of my tests, but that would wipe out my scope every time. I want to test the function as properties in my scope changes.

Is there any way to get a hold of the object that is returned from the directive definition? Then I could just call the link function directly and test the behavior of each of the functions defined on the scope. Is there a better way to do all this?

I'm using Jasmine to run my tests, and I'm wanting to my scope setup in the describe functions, so I can have multiple it functions for the same scope data.

like image 217
dnc253 Avatar asked Nov 15 '12 21:11

dnc253


People also ask

What does link function do in a directive?

link function is basically used to manipulate the DOM( Document Object Model ) element using custom directive. link option in custom directive registers DOM listener and also update the DOM.

How do you call a method in a directive?

Inside the directive it is creating an updateMap() method on the scope object in the directive and then calling the setFn() method which is mapped to the $scope. setDirectiveFn() method by this line: <map set-fn="setDirectiveFn(theDirFn)"></map> in your HTML and this line: scope: { setFn: '&' } in your directive.

What is the difference between controller and link in directives?

Answer:The link option is just a shortcut to setting up a post-link function. controller: The directive controller can be passed to another directive linking/compiling phase. It can be injected into other directices as a mean to use in inter-directive communication.

What is a directive in Javascript?

Directives are markers on the DOM element which tell AngularJS to attach a specified behavior to that DOM element or even transform the DOM element with its children. Simple AngularJS allows extending HTML with new attributes called Directives.


Video Answer


1 Answers

Basically, rather than test the link function itself, you'd test the outcome(s) of the directive programmatically. What you would do is write out the directive to a string, and use $compile to have angular process it. Then you test the output to make sure everything is wired up correctly.

Angular's source is full of good examples of how to do this... for example Angular's test of the ngRepeat directive

You can see what they're doing is setting up the directive, Changing the scope (in this case $rootScope) making sure it's $digested, and then testing the DOM it outputs to make sure everything is wired up correctly. You can also test what's in the scope, if the directive is altering that.

The test for ngClick is also pretty interesting, because it shows testing of a browser interaction and it's effect on the scope.

For sake of completeness, here's a snippet from the ngClick tests that I think sums up testing a directive fairly well:

 it('should get called on a click', inject(function($rootScope, $compile) {    element = $compile('<div ng-click="clicked = true"></div>')($rootScope);    $rootScope.$digest();    expect($rootScope.clicked).toBeFalsy();     browserTrigger(element, 'click');    expect($rootScope.clicked).toEqual(true);  })); 

So in the case of your scope.doStuff function, I wouldn't test what it's doing, so much as I'd test whatever it's affected on the scope, and it's subsequently effected DOM elements.

like image 156
Ben Lesh Avatar answered Oct 05 '22 05:10

Ben Lesh