How to test AngularJS directives
Solution 1
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 usegrunt-html2js
grunt task.In your tests, use the
inject
helper in abeforeEach
to inject $compile and $rootScope and any other services you'll need. Usevar myScope = $rootScope.$new()
to create a fresh scope for each test. You can dovar 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/
.
Solution 2
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.
Related videos on Youtube
toadjamb
Updated on July 09, 2022Comments
-
toadjamb almost 2 years
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?
-
Philipp Gayret about 11 yearsGiven plunker does not seem to work anymore, do you have a working version? The documentation on testing directives with Jasmine for AngularJS is super bad and hurting for an example like the one at the plunker.
-
Stepan Suvorov about 10 yearsare you sure about myElement.children().scope()? I does not work for me =( -> UPD: I had to do $scope.$apply()