1/16/2015

You Got Karma in My Require, You Got Require in My Karma, No Worries We Have Define

Karma is a pretty powerful test runner for JavaScript. Most of our code is in Angular, so we load our Karma test context with every file in our project. This should be easy...except...we do have a few libraries that only load on demand. This is no problem for the Karma context since the file is loaded along with everything else. The problem is that we use require to load it. This is a problem for two reasons:

  1. Karma changes the base path for the environment for it's own reasons. Therefore, trying to load a file from vendor/angular.min.js will work in the wild, but will fail in Karma. In Karma, the new path will be base/vendor/angular.min.js.
  2. Since require wasn't the one to load the library initially, require doesn't know it's loaded. That means as soon as require fires it won't see the existing library and skip it, require will try to load it again.
There are workarounds for this. The most successful workaround I have seen is to make a configuration script which pulls all the libraries out of the context then reloads them manually through require.

We weren't willing to add extra code, and therefore, an extra variable to our testing environment so we looked for a different way. The brilliant NateFerro came up with a shortcut. As long as a library works with context level properties, such as injecting code into a global variable, then this will work. Require.js is good about being helpful and not getting in the way of the rest of your code. To this end, it has created the define block. If in your karma configuration, you include

  ...
  files:[
    /vendor/vendorLibrary.js
    ...
  ]
  ...

and your code is used in a block similar to

  require('/vendor/vendorLibrary.js', function (){..do something...});

then use the define clause in your test like this:

  define('/vendor/vendorLibrary.js', []);
  describe('This is my test', function (){
    ....

If you have lots and lots of require loaded libraries then this may be a lot of extra work for you. If your required library list is small, or you use a server side package manager like browserify, then this might save you from having to load a separate require friendly karma config file.