How to test React components using Karma and webpack
I’m working on a project at Twitter that uses React and webpack. After a few conversations with @sokra last year, this is the setup I put in place for testing React components (authored using JSX and ES6) using Karma.
Dependencies
You’ll need to install various packages. It looks like a lot of dependencies, but all the non-Karma packages will be necessary for general module bundling during development.
Full set of required packages:
- babel-core: to transform JSX and transpile ES6.
- babel-loader: webpack loader for Babel.
- karma: the test runner.
- karma-chai-plugins: assertion library (or your library of choice).
- karma-chrome-launcher: Chrome browser launcher.
- karma-cli: CLI tool for Karma.
- karma-mocha: adapter for the Mocha testing framework.
- karma-sourcemap-loader: sourcemap loader.
- karma-webpack: to use webpack with Karma.
- react
- webpack: module bundler
webpack entry file
If you use webpack-specific features in your modules (e.g., loaders, plugins) you will need to use webpack to build a test bundle. The fastest and simplest approach is to create a single, test-specific entry file.
Create a file named tests.bundle.js
. Within this file, you create a webpack
context to match all the
files that conform to a naming pattern – in this case *.spec.js(x)
.
var context = require.context('.', true, /.+\.spec\.jsx?$/);
context.keys().forEach(context);
module.exports = context;
Next, you point Karma to this file.
Karma config
Karma is configured using a karma.conf.js
file. The browsers, plugins, and
frameworks are specified in the standard way.
Point Karma at the tests.bundle.js
file, and run it through the relevant
preprocessor plugins (see example below).
The karma-webpack
plugin relies on 2 custom properties of the Karma config:
webpack
and webpackMiddleware
. The value of the former must be a webpack
config object.
module.exports = function (config) {
config.set({
browsers: [ 'Chrome' ],
// karma only needs to know about the test bundle
files: [
'tests.bundle.js'
],
frameworks: [ 'chai', 'mocha' ],
plugins: [
'karma-chrome-launcher',
'karma-chai',
'karma-mocha',
'karma-sourcemap-loader',
'karma-webpack',
],
// run the bundle through the webpack and sourcemap plugins
preprocessors: {
'tests.bundle.js': [ 'webpack', 'sourcemap' ]
},
reporters: [ 'dots' ],
singleRun: true,
// webpack config object
webpack: {
devtool: 'inline-source-map',
module: {
loaders: [
{
exclude: /node_modules/,
loader: 'babel-loader,
test: /\.jsx?$/
}
],
}
},
webpackMiddleware: {
noInfo: true,
}
});
};
Rather than duplicating your webpack config, you can require
it in the Karma
config file and override the devtool
value to get sourcemaps working.
var webpackConfig = require('./webpack.config');
webpackConfig.devtool = 'inline-source-map';
module.exports = function (config) {
config.set({
...
webpack: webpackConfig
});
};
That’s all you need to do to configure Karma to use webpack to load your JSX, ES6 React components.