Unit testing with jspm, karma, mocha and react

Javascript biggest downside is all the dependencies you need to bring in and configuration needed to get something similar as unit testing going. Imagine your psyched for this idea of a code project you just had and just wan’t to get started coding. But after a few nights of your precious spare time you almost give up because you even haven’t started coding yet. All this packages and configuration is killing your motivation. Javascript fatigue… Enough ranting…

I’ve been struggling for some days now to get unit testing with react in a project using jspm. I’m documenting this to hopefully save future me and someone else the hours and frustration.

Jspm

Jspm is a package manager for Javascript that aims to solve the problem of different module formats in JavaScript(ES6, AMD, CommonJS, and globals). Jspm uses the SystemJS module loader which handles all this cases and also can handle registries other than npm like github.

When developing your Javascript application jspm uses a transpiler of your choice to transpile your next generation Javascript code, TypeScript or whatever needs transpiling directly in the browser. When going to production you can produce a bundle.

Karma

Karma is a test runner which runs your tests in a browser or even headless browsers like PhantomJS.  It spawns a web server that executes the test against each browser which then displays the results in the command line. It’s primary usage is for unit testing and not end to end testing.

Karma can watch specified files and run the tests whenever something changes. It also has the functionality to load preprocessors which means that your javascript files can be processed before getting served to the browser. One example could be running the files through babel or webpack.

It’s testing framework agnostic and there’s support for every popular testing framework out there like Mocha, QUnit and Jasmine and so on. If it doesn’t you can build your own adapter.

Mocha

My previous post was about unit testing with mocha. Read it here.

React

React is Javascript library for building user interfaces. Enough of that. Let’s get started.

Installation

I’ve already created jspm-react-boilerplace. I will use that as a starting point. So start by cloning the github repo and install the packages.

$ git clone https://github.com/Jontem/jspm-react-boilerplate.git
$ npm install
$ jspm install

After the 1000 dependencies have finished installing we need to install karma and mocha along with some required karma plugins.

$ npm install --save-dev karma karma-chrome-launcher karma-jspm karma-mocha mocha

After another 1000 packages is downloaded we can run.

$ ./node_modules/.bin/karma init

Just choose mocha as the testing framework and Chrome for browser then choose the defaults. We will edit the config file directly. If you don’t want to specify the path to karma you can install it globally. But after we add an npm script we don’t need to worry about that.

Open karma.conf.js and find the frameworks property and add jspm.

    frameworks: [
      'jspm',
      'mocha'
    ]

After frameworks add a jspm configuration section

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

This will make jspm run a transpiler on the files specified before handing them over to mocha.

The last thing we need to add to the karma cofig is the proxies property and this is because karma loads our specified files under the base url /base/. We can tell the karma webserver that som paths should automatically be proxied to /base/

proxies: {
      '/test/': '/base/test/',
      '/src/': '/base/src/',
      '/jspm_packages/': '/base/jspm_packages/'
    }

Let’s install two more packages… Chai which is an assertion library and react-addons-test-utils

$ jspm install --dev npm:chai npm:react-addons-test-utils

Now edit package.json so we can run npm test. The script property should have these entries.

"scripts": {
    "start": "npm run webserver & npm run watch",
    "webserver": "node server.js",
    "watch": "chokidar-socket-emitter",
    "test": "karma start"
  }

Running npm start launches a browser that will execute the tests. But it will fail because it won’t find any tests. So lets add one. We start by creating the test/ and src/ directories.

Create a file hello_world_component.test.js under the test/ directory.

import {assert} from "chai";
import TestUtils from "react-addons-test-utils";
import * as React from "react";
import DOM from "react-dom";
import {HelloWorld} from "../src/hello_world_component";

describe("Hello world component", function () {

    it("should should display the text hello world", function () {
        var renderer = TestUtils.createRenderer();
        const result = renderer.render(<HelloWorld />);

        assert.equal(result.type, "div");
        assert.deepEqual(result.props.children, [
            <h1>Hello world</h1>,
            <span>test</span>
        ]);
    });

});

Next we create the file which defines the component hello_world_component.js under src/

import * as React from "react";

export const HelloWorld = React.createClass({
    render() {
        return (
            <div>
                <h1>Hello world</h1>
                <span>test</span>
            </div>
        );
    }
});

Now run npm test and you should have one green test!

The benefit of using karma is that we’re running our tests in a browser environment which means we have access to DOM which some of React test utils needs for simulating DOM events or rendering deeper hierarchies of react components. In our tests above we make use of shallow rendering which only renders react components one level deep and doesn’t need access to a DOM. Read more about React test utils on reacts website.

If you think this post was long you don’t have any idea of the struggle to get this working :). Oh one last thing… If you want to use the renderIntoDocument method be aware that stateless components cannot be tested. It will only return null, I don’t know why… But it was hidden somewhere in the documentation.