AngularJs Unit Testing Part 3 – Directives

This is blog post is a part of a series related AngularJs unit testing.

Directives are arguably the most import part of the AngularJs framework moreover, they are certainly the most complex and hardest to grasp. That’s why, I believe its essential to set up unit tests around directives when you are writing AngularJs applications. Directives are tricky to write so having unit tests can help you catch errors early.

Unit testing directives are a bit different from testing controllers and services as this is where you want to check your HTML to make sure you are rendering the HTML correctly, so let’s look at how to do that.

The Directive

I took the hero image that was on the home page and I made it into a directive that allows you to change the image by clicking “Prev” and “Next”.

Here is what the template looks like.

I moved the image HTML from the main view and replaced it with the directive element.

Testing the Directive

Here is the unit test code for the directive:

There are few things I need to set up before I can start testing.

  • I need to add the directive element. I essentially want to take the directive element and make sure I can compile it to the desired HTML.
  • I need to set up my scope and the data I want to pass to the directive.
  • I need to compile the directive.

The compiling of the directive is key for the test, and usually I take that code and extract it out into another file so I can use it in other tests.

To compile the directive, AngularJs has a service called “$compile”. This service is actually a function, and when you pass it the html converted to an “angular.element”, it will return to you a new function. This returned function then takes the scope and will return to you the compiled HTML. I have shortened the code to one line above, but to understand it better, you could also write it more explicitly like this:

Once compiled, you then need to run the $digest command so everything is in sync between your scope and the directive.

The Tests

First, I want to test that the directive compiled, so typically I search for a DOM element in the HTML that was not part of the original directive HTML.

Testing Interactions

In the case of this directive, I want to test that when I click the previous button, the previous image in the list of images displayed. However, since the current image being displayed, is the first image in the list, I want to make sure that the last image displayed.

The question here, is since this is a unit test and there is no user interaction, how do I trigger a click even to check that my scope changed?

Well since AngularJs has a dependency to JqLite, we can trigger events using the “triggerHandler” function and tell it what event to trigger.

Then to make sure that our scope is up to date, we then need to run the digest cycle.

We can now check to see if our scope changed.

Here, I am checking that original selected image was unselected and that last image in the list is now selected.

Now if I check my “spec” page, I can see that all my tests passed.

directive_tests

Conclusion

I have updated the code on Github, which also includes the code for other posts.

Leave a Reply

Skip to toolbar