Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test AngularJS directives

I am working on a Rails 3.2 app that will be using AngularJS. I can get Angular to do what I need, but I am having a very difficult time figuring out how to test what I'm doing. I am using guard-jasmine to run Jasmine specs using PhantomJS.

Here is the (relevant) html:

<html id="ng-app" ng-app="app">   <div id="directive-element" class="directive-element">   </div> </html> 

The javascript (in coffeescript) looks like:

window.Project =   App: angular.module('app', [])   Directive: {}  Project.Directive.DirectiveElement =   ->     restrict: 'C'     link: (scope, element, attrs) ->       element.html 'hello world' Project.App.directive 'directiveElement', Project.Directive.DirectiveElement 

The code above does exactly what it is intended to do. The tests are the problem. I can't get them to work at all. This is one thing I had tried. Posting this is mostly just to start the conversation somewhere.

describe 'App.Directive.DirectiveElement', ->   it 'updates directive-element', ->     inject ($compile, $rootScope) ->       element = $compile('<div id="app" ng-app="app"><div id="directive'element" class="directive-element"></div></div>')       expect(element.text()).toEqual('hello world') 

As an aside, I am new to AngularJS, so if there are any best practices regarding namespacing, modules, etc. that I am not following, guidance would be appreciated.

How do I get a test for this to work?

like image 793
toadjamb Avatar asked Oct 05 '12 23:10

toadjamb


People also ask

Is AngularJS code unit testable?

AngularJS is written with testability in mind, but it still requires that you do the right thing. We tried to make the right thing easy, but if you ignore these guidelines you may end up with an untestable application.

What are the directives in AngularJS?

AngularJS directives are extended HTML attributes with the prefix ng- . The ng-app directive initializes an AngularJS application. The ng-init directive initializes application data. The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.


2 Answers

Here's how alert directive is tested in angular-ui/bootstrap.

Here's another simple set of tests, for the buttons directive.

Here are a few tips:

  • Be sure to tell the test runner what module you are testing with beforeEach(module('myModule')).

  • If you have external templateUrls in your directives, you'll want to somehow pre-cache them for the test runner. The test runner can't asynchronously GET templates. In bootstrap, we inject the templates into the javascript with a build step, and make each template a module. We use grunt-html2js grunt task.

  • In your tests, use the inject helper in a beforeEach to inject $compile and $rootScope and any other services you'll need. Use var myScope = $rootScope.$new() to create a fresh scope for each test. You can do var myElement = $compile('<my-directive></my-directive>')(myScope); to create an instance of your directive, and have access to its element.

  • If a directive creates its own scope and you want to test against it, you can get access to that directive's scope by doing var directiveScope = myElement.children().scope() - It will get the element's child (the directive itself), and get the scope for that.

  • For testing timeouts, you can use $timeout.flush() to end all pending timeouts.

  • For testing promises, remember that when you resolve a promise, it will not call its then callbacks until the next digest. So in tests you have to do this a lot: deferred.resolve(); scope.$apply();.

You can find tests for directives of varying complexity in the bootstrap repo. Just look in src/{directiveName}/test/.

like image 79
Andrew Joslin Avatar answered Sep 25 '22 12:09

Andrew Joslin


Angular Test Patterns may help you, there are examples in both coffeescript and javascript.

Here's a testing pattern to verify the example directive is rendering the expected output.

like image 41
SavoryBytes Avatar answered Sep 23 '22 12:09

SavoryBytes