AngularJS Testing Tips and Tricks | ng-html2js

Testing directives with Karma can be a bit tricky, especially when templateUrl is used to retrieve an external template. Out of the box, Karma has difficulty retrieving these asynchronously loaded templates. If you’ve ever seen something like “Unexpected Request: GET”, then you know what we are talking about.

Thankfully, things like karma-ng-html2js-preprocessor exist to address the issue. In this tutorial, we quickly demonstrate how to use the karma-ng-html2js-preprocessor plugin with your Angular unit tests.

The first step is to install the karma-ng-html2js-preprocessor plugin. Simply run the following to install the npm module:

npm install karma-ng-html2js-preprocessor --save

This will install the plugin in your node modules directory and save it to your package.json file.

Configuring Karma

Since this is a plugin, we have to configure Karma to recognize and use it. In your configuration file, add the following:

karma.conf.js

preprocessors:{
‘app/views/yourTemplate.html’: [‘ng-htmljs’]
}

ngHtml2JsPreprocessor:{
stripPrefix: ‘app/',
moduleName:'templates'
},

files:[
//Other files for karma
moduleName:'templates'
],

We’ve done a few things here. First, we’ve added the ng-html2js preprocessor to our configuration file. Then we’ve given our preprocessor an alias ‘templates’ so that we can more easily reference it in our spec files. Notice the stripPrefix attribute. This is only necessary if the absolute path to your file does not match the referenced path in your directive. For example, if your directive references the template like templateUrl:'views/yourTemplate.html' then you need to strip the app/ prefix from the path for Karma to recognize it.

Include the Plugin in Your Spec File

Now that Karma is configured correctly, it’s time to use the ng-html2js preprocessor in your unit test.

describe(‘my directive’, function(){
beforeEach(module(‘templates’));
beforeEach(inject(function(_$compile_, _$rootScope_){
$compile = _$compile_;
$rootScope = _$rootScope_;
}));
it(‘has correct html’, function(){
var element = $compile(‘’)($rootScope);
$rootScope.$digest();
expect(element.html()).toContain(‘html from template’);
}
})

Notice how we’ve included the reference to our preprocessor via beforeEach(module(‘templates’)).

Conclusion

The ng-html2js preprocessor provides an easy solution for testing directives that reference template urls. Other preprocessors exist and have similar configurations, but ng-html2js is one of the most popular. While you can avoid using plugins by hard coding templates into directives or using $httpBackend, the simplicity of ng-html2js and other preprocessors makes these the more cumbersome alternatives. Keep it simple. Use ng-html2js preprocessors to test your directives with external templates.

Your thoughts?