2014-02-09

Testing AngularJS directives with templateUrl generated with Yeoman's generator-angular

Are you in trouble while testing your reusable directive you are developing with AngularJS? Because are you testing your application, right?!

I had to solve some problems testing my AngularJS directive and if you are in trouble I hope you will save time reading this post. One of them is:
  • testing directives that use the templateUrl statement

directives that use the templateUrl statement (and Yeoman)

The templateUrl option let you put the directive template into external html files instead of inlining html into your Javascript code.

It's a very useful option but if you try to test your directive with the templateUrl option you will get a nasty error:
Error: Unexpected request: GET views/yourdirectivetemplate.html
If you want to solve you can use use the ng-html2js Karma preprocessor. This way Karma immediately generates the js file, that puts the html into $templateCache. Alternatively you can alter the $templateCache by hand, not covered in this post.

All you need to know about testing AngularJS directives with templateUrl is described here:
Once followed all vojtajina's hints you will get this error if you have used the Yeoman's generator-angular because you have a different code structure (remember the app folder?):
Error: [$injector:modulerr] Failed to instantiate module views/yourdirectivetemplate.html due to: Error: [$injector:nomod] Module 'views/yourdirectivetemplate.html' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
Don't worry, you only need to to adjust the karma.conf.js as suggested here (see the stripPrefix usage of ngHtml2JsPreprocessor):

Summary

Hope it might help you. Let me summarize what you need to do in order to fix your tests.

Happy testing!

[update 20140210] Install karma-ng-html2js-preprocessor

Remember to install the html2js Karma preprocessor:
$ npm install karma-ng-html2js-preprocessor --save-dev
Your package.json should contains the following line into devDependencies:
+    "karma-ng-html2js-preprocessor": "~0.1.0"

karma.conf.js

module.exports = function(config) {
  config.set({
    // base path, that will be used to resolve files and exclude
    basePath: '',

    // testing framework to use (jasmine/mocha/qunit/...)
    frameworks: ['jasmine'],

+    // generate js files from html templates
+    preprocessors: {+      'app/views/*.html': 'ng-html2js'+    },
+
+    // needed if you have used the Yeoman's generator-angular or the app dir 

+    ngHtml2JsPreprocessor: {
+      stripPrefix: 'app/',
+    },
+

    // list of files / patterns to load in the browser
    files: [
      'app/bower_components/angular/angular.js',
      'app/bower_components/angular-mocks/angular-mocks.js',
+    'app/views/*.html',
      'app/scripts/*.js',
      'app/scripts/**/*.js',
      'test/mock/**/*.js',
      'test/spec/**/*.js'
    ],

test/spec/directives/yourdirective.js

describe('Directive: yourdirective', function () {

  // load the directive's module
  ...
+  beforeEach(module('views/yourdirectivetemplate.html'));

3 comments:

  1. This really helped me. Thanks!

    ReplyDelete
  2. how to use JSP page as the template url in the module.driective
    sample code is as follows:
    module.directive("bookingDrpdwn", function($timeout){
    return {
    templateUrl: 'partial.jsp'
    };
    });

    ReplyDelete