Friday, 1 April 2016

Setting up Karma to play nice with JSPM

The TL;DR version

I was getting quite frustrated with unit testing today because when I was attempting to use ES6 features like Array.find I was greeted with errors like this one.

TypeError: undefined is not a constructor (evaluating 'categories.find(function (cat) {
                                return cat._id === id;
                            })') (line 19)


I noticed I was also getting a message like this in my stack trace:

tryCatchReject (http://localhost:9876/base/jspm_packages/system-polyfills.src.js

Why couldn't SystemJS load polyfills? It was managing it fine in my browser, at least that is what I assumed.

I made a mistake and thought that I must need to pre-process my unit tests so that they become babelified or ES6 ified or JS2015 ified etc...

I started looking at this...
https://github.com/babel/karma-babel-preprocessor
This made it worse because I was trying to re-implement using a different tool the same task which is being undertaken by JSPM and SystemJS.

In the end the answer was rather than keep adding configuration, strip out configuration and then add just one extra line.

I actually found this tip/clue from the karma-babel-preprocessor configuration page.

Polyfill

If you need polyfill, make sure to include it in files.
npm install babel-polyfill --save-dev
module.exports = function (config) {
  config.set({
    files: [
      'node_modules/babel-polyfill/dist/polyfill.js',
      // ...
    ],
    // ...
  });
});
I added the line above to the files array and "hey presto" all my unit tests were working fine with array.find. To prove that "karma-babel-preprocessor" was not needed I uninstalled it and re-ran my tests.

I later found that I also needed to reference babels polyfill.js in the client-side code that was using the find method.

The only reason I had not noticed was because Chrome has a native implementation. However MS Edge and all other IE browsers do not, so nothing worked on those browsers - a dead giveaway. I added this line to the files in question:
import "babel-polyfill";
See: https://babeljs.io/docs/usage/polyfill/

I found later that sometimes the unit tests would still crash PhantomJS. The final solution to this was to split the specification files from the implementation files using the following from karm-jspm:

jspm: {
    loadFiles: ['test/**/*.js'],
    serveFiles: ['src/**/*.js']
}

The theory being that you don't need to load the actual files to be tested until you have initially loaded the tests themselves.

I think it is fair to say that sometimes Karma does not like to play nicely with JSPM, although this does seem to depend on your project structure as well. I hope these little tips either help to resolve an issue or go someway to alleviate some confusion.

No comments:

Post a Comment