Setting up Karma to work with Enzyme, Mocha, and Webpack in 2017

Jason Chambers
6 min readApr 9, 2017

--

Karma shown using nyan-reporter npm package

So after struggling for most of my Saturday night working on getting my Karma test suite up and running, I decided I would write out a short guide on the steps I took to get it working. This way hopefully no one else has to struggle with the setup process and be able to jump straight into writing some tests with Mocha and Enzyme. I’ll do my best to keep it general, however be aware that not all lines will be the same as your specific needs.

Install all the things

Heres a list of every single npm package I needed to get my test suite up and running. I have some extra (most likely unneeded) babel packages for transpiling ES8 async functions and await methods (out of scope for this post, but here’s a link if you’re interested) but it probably wouldn’t hurt to just install them all and get it out of the way.

Here’s a sweet command that will let you install every single package you need in one go. If you want to have a look in an easy to read format of every single one, I linked the final result of the package.json file below this command.

npm install --save-dev mocha sinon react-addons-test-utils chai enzyme webpack karma-webpack karma-sourcemap-loader karma-phantomjs-launcher karma-nyan-reporter babel-cli babel-core babel-loader babel-plugin-transform-decorators-legacy babel-plugin-transform-es2015-destructuring babel-plugin-transform-object-rest-spread babel-plugin-transform-regenerator babel-polyfill babel-preset-es2015 babel-preset-react babel-preset-stage-1 babel-register json-loader karma karma-babel-preprocessor karma-chrome-launcher karma-mocha

And the final result in your package.json.

"devDependencies": {
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-loader": "^6.4.1",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-es2015-destructuring": "^6.23.0",
"babel-plugin-transform-object-rest-spread": "^6.23.0",
"babel-plugin-transform-regenerator": "^6.24.1",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-1": "^6.24.1",
"babel-register": "^6.24.1",
"chai": "^3.5.0",
"enzyme": "^2.8.0",
"json-loader": "^0.5.4",
"karma": "^1.6.0",
"karma-babel-preprocessor": "^6.0.1",
"karma-chrome-launcher": "^2.0.0",
"karma-mocha": "^1.3.0",
"karma-nyan-reporter": "^0.2.5",
"karma-phantomjs-launcher": "^1.0.4",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^2.0.3",
"mocha": "^3.2.0",
"react-addons-test-utils": "^15.5.1",
"sinon": "^2.1.0",
"webpack": "^2.3.3"
}

In addition to the above, run npm install -g karma-cli to be able to run karma itself after setup. When running tests, you will call karma start.

I’d also like to add that I am assuming you already have your react dependencies installed (react, react-dom, react-dom-router, etc..) so I left those out to try and keep the clutter to a minimum.

Setting up karma.conf.js

Now that you have installed your 30 something dependencies, you will need to set up your karma.conf.js file. I’ll try and step through what each line does so you have a better understanding of what could be going wrong if this guide doesn’t work for you 100%.

Here’s the whole file, now lets break it down piece by piece.

const path = require('path');module.exports = function(config) {
config.set({
basePath: '',
browsers: ['PhantomJS'],
frameworks: ['mocha'],
files: [
'node_modules/babel-polyfill/dist/polyfill.js',
'test/**/*.js'
],
preprocessors: {
'src/public/AppEntry.js': ['webpack', 'sourcemap'],
'test/**/*.js': ['webpack', 'sourcemap']
},
webpack: {
devtool: 'inline-source-map',
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: path.resolve(__dirname, 'node_modules'),
query: {
plugins: ['transform-decorators-legacy', 'transform-regenerator'],
presets: ['react', 'es2015', 'stage-1']
}
},
{
test: /\.json$/,
loader: 'json-loader',
},
]
},
externals: {
'react/addons': true,
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': true
}
},
webpackServer: {
noInfo: true
},
reporters: ['nyan'], nyanReporter: {
suppressErrorHighlighting: true,
},

port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
singleRun: false,
});
};

Here’s the whole file, now lets break it down piece by piece..

Config.set

config.set({
basePath: '',
...
}

Base path is just the root path you want to start from when resolving paths defined in files and exclude. If a base path is not given, it resolves to the __dirname of this config file.

browsers: ['PhantomJS'],

What browser you want Karma to run in. I’m using PhantomJS which allows me to run tests without needing to have a browser open.

frameworks: ['mocha'],

This is just telling Karma what testing framework we will be using.

files: [
'node_modules/babel-polyfill/dist/polyfill.js',
'test/**/*.js'
],

These are pathnames to the test files you will be using, relative to the basePath. As I mentioned earlier I have babel-polyfill listed since it’s needed for await / async functions. If you aren’t using those methods you can omit that line.

preprocessors: {
'src/public/AppEntry.js': ['webpack', 'sourcemap'],
'test/**/*.js': ['webpack', 'sourcemap']
}

This block here is telling Karma what you want it to do with the listed files before running the tests basically. Since we’re writing with ES6 / ES7 methods, we will need to be transpiling with babel using webpack(which we will be covering below). We also want to create a sourcemap for our transpiled files so we can understand any error messages that arise on failed tests. If you’re unfamiliar with sourcemaps this stackoverflow post has a good explanation on the topic.

The Webpack Section

Time for the webpack section of the karma.conf.js file! This will most likely be similar to your own webpack.config.js with a few minor changes.

devtool: 'inline-source-map',

Basically this is saying to add the sourcemap as a DataURL at the bottom of the file. Don’t need to worry about this much, it’s the default setting.

module: {
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: path.resolve(__dirname, 'node_modules'),
query: {
plugins: ['transform-decorators-legacy', 'transform-regenerator'],
presets: ['react', 'es2015', 'stage-1']
}
},

NOTE: Your query / plugins / presets WILL be different. Look at your webpack.config.js file and use the ones you currently have. They are the same thing.

Here we’re basically saying how we want to load our .js files. Using babel-loader with our plugins / presets to correctly transpile the code. And of course we want to exclude our node_modules directory.

{
test: /\.json$/,
loader: 'json-loader',
},

Same as above, specifying that the json-loader package will load our .json files.

externals: {
'react/addons': true,
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': true
}

The externals object varies based on your current version of webpack / react. I’d recommend looking up what version you’re running and using the recommended options here.

webpackServer: {
noInfo: true
},

This is just saying we don’t want webpack spamming us with thousands of console messages while its working. If you love clutter and chaos, feel free to set this to false. I wouldn’t recommend it.

reporters: ['nyan'],

My favorite part! This presents error messages in a more intuitive way, plus you get to see nyan cat travel across your terminal as your tests are running. Perfect.

nyanReporter: {
suppressErrorHighlighting: true,
},

Tells nyan-reporter to not display a solid red background on error messages. I personally find it easier to read with this setting. If you want the red background, set this to false.

port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
singleRun: false,

Lastly, port specifies what port you want Karma to be ran on.

Colors gives you an easier to read terminal.

LogLevel is what type of errors you want displayed.

AutoWatch means that you can run the tests once, and they will auto run again on file change. This is the best feature, don’t have to keep tabbing out and refreshing browsers and running npm commands every time you want to run tests.

SingleRun just specifies whether you want the tests to be ran once and exit, or to keep the connection open.

The Finale

Now that you have all your dependencies and your karma.conf.js file setup, you can just create a “test” folder in the root directory of your repo, and start writing some tests! Here’s the enzyme official docs for more info on testing.

The End

That sums it all up, you now have a fully functional Karma test suite using Enzyme and webpack.

--

--