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.