Friday, August 28, 2015

Proper karma-ng-html2js-preprocessor Setup

If you want to test directives in AngularJS, using Karma, and those directives use external templates, you'll have to use the karma-ng-html2js-preprocessor plugin for Karma.  It took me a few tries to get it right so hopefully these instructions help somebody (even if it's me) down the road.

 The first thing you'll want to do is install the preprocessor through npm using this command: npm install karma-ng-html2js-preprocessor.  You can use the -g switch to install it globally, or not.

Once you have it installed, you'll need to update your Karma config file to pull it in and use it, and that's where my first issue came about.  First, include the preprocessor in the plugins section of the config:

   1:  plugins: [
   2:      'karma-phantomJS-launcher',
   3:      'karma-jasmine',
   4:      'karma-ng-html2js-preprocessor',
   5:      'karma-coverage'
   6:  ],

The next thing you'll need to do is setup the preprocess to pull in your html files:

   1:  preprocessors: {
   2:      './Templates/*.html': ['ng-html2js'],
   3:      './Content/Controls/*.html': ['ng-html2js']
   4:  }

Now, you can't forget to do the next thing, which is to include your html files in your list of files:

   1:  files: [
   2:      'Templates/*.html',
   3:      'Content/Controls/*.html'
   4:  ]

If you don't do that part, the templates won't be imported by the preprocessor and your tests will fail.

You can configure the preprocessor if you need to, and you may have to.  I'm not gonna lie here: I don't know how to configure this completely.  I know what I had to do to get everything to work and that's what I'm sharing here.  If you want more details on the configuration options, check out the Github page for the preprocessor.

In our solution we use the forward slash to reference our external templates.  In the directive, the templateUrl may look like this: /templates/sample.html.  Karma won't automatically know to do that (I think this has to do with the way the web server is started and the way the browser finds the "root" of the application, but I'm not 100% on that).  What we have to do to make this work is prepend the templates with a forward slash.  Easy enough once you know it needs to be done:

   1:  ngHtml2JsPreprocessor: {
   2:      // setting this option will create only a single module that contains templates
   3:      // from all the files, so you can load them all with module('foo')
   4:      moduleName: 'templates',
   5:      // since our templateUrls have to be prefixed with a forward slash in order for them to be found during normal rendering
   6:      // we need to prefix the them with the forward slash so karma can find them and the preprocessor can cache them with
   7:      // the forward slash
   8:      prependPrefix: '/'
   9:  }

There's also an option to stripPrefix, but as you can see I didn't have to use that one.  The point here is to be aware that you can configure the preprocessor and it can be confusing when you try to do it so play with it for a while.  If I can find the blog that put me on the right track, I'll throw up a link to it.

Bonus: If you need to see what's going on while you're trying to figure this out, you can change the log level (and therefore the verbosity of the logging) by finding the logLevel section in the Karma config and changing it to config.LOG_DEBUG.  That's how I figured out my issues with prependPrefix.

Second Bonus: If you need even more logging than that, you can hack away on the logging module itself.  Since everything in node.js (AFAIK) is JavaScript, you can make changes on the fly and watch the enhanced output.  To do that, just find the logger JavaScript file and start making changes to it.  Rerun your tests to see the modified output.

No comments:

Post a Comment