Saturday 27 June 2015

Test-Driven React with Karma and Webpack: #4 React Karma Setup

So far in this series, we have set up Karma with PhantomJS to run Jasmine tests.  Then, we built a little Conway's Game of Life module for game logic.  Finally, we set up everything we need to use Webpack with React.  This article will complete the environment by adding the ability to run React tests with Karma.

This is largely inspired by the Karma configuration used on the react-router project.  However, in this project, the requirement is to keep the existing tests running and add React tests (using the React Test Utilities).

Adding npm packages for React Karma testing

In order to support testing with Karma we need to add a few npm packages to the project.  These packages help to support a Karma pipeline that will use Webpack to package all the test and production code up so that we can make assertions about its state.

Here is a list of the npm commands to install the packages:

$ npm install karma-webpack --save-dev
$ npm install karma-sourcemap-loader --save-dev
$ npm install karma-chrome-launcher --save-dev

I'll tell you why we need the karma-chrome-launcher package in a minute.  However, the karma-webpack package will allow Webpack to run in the Karma pipeline as a preprocessor.  The karma-sourcemap-loader makes debugging easier when Webpack munges all of our files together.

With these packages installed, we are ready to add some configuration to the karma.conf.js file.

Adding configuration for Karma

In order to support the discovery of the files that we need to test, let's add a file named tests.webpack.js to the root directory with the following contents:

This file is used to tell Karma about what files to be concerned with.  The parts of the file that are of interest to us is the path './tests/components' and the regex /-test\.js$/. The path is resolving the working directory that we want to add tests to.  The regex is selecting all JavaScript files that end with -test.js.

There are a number of additions and modifications that we now can make to the karma.conf.js in order to run our React tests as part of the Karma test run.

First, change the files array to look like:

    // list of files / patterns to load in the browser
    files: [
      'src/**/*.js',
      'tests/game/**/*.js',
      'tests.webpack.js'
    ],

In the files array, first we limit old-style tests to the 'tests/game' directory.  Then, we add our new file to the mix.

Next, we add the preprocessor object:

    preprocessors: {
      'tests.webpack.js': [ 'webpack', 'sourcemap' ]
    },

This object looks at the files resolved in our new file and pipes them through webpack and sourcemap preprocessors before beginning a Karma test run.

Next, we add the webpack and webpackServer configuration:

    webpack: {
      devtool: 'inline-source-map',
      module: {
        loaders: [
          { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' }
        ]
      }
    },

    webpackServer: {
      noInfo: true
    }, 

These new configuration objects mirror the Webpack configuration file webpack.config.js that we have already set up in the project root directory.  We also add support for sourcemaps.

Now that we are going to potentially run some asynchronous tests, it is a good idea to add a no activity timeout:

browserNoActivityTimeout: 30000,

Finally, we switch to Chrome to run the tests:

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome'],

This is necessary because, currently, there is a bug in PhantomJS 1.x (perhaps now fixed in 2.x) that does not allow using the React Test Utilities.  At the moment, the Karma launcher for PhantomJS is still pointing to the 1.x branch, but this is likely to change (more on this in a future post).  This is the reason we needed the karma-chrome-launcher package earlier.

That concludes the set up tasks.  We are now ready to write a test to prove the environment.

Adding the first simple React test

Let's go ahead and add a file in the /tests/components directory named game-of-life-test.js with the following contents:
This should look familiar if you've written tests with React before.  I'll quickly describe some of the key bits.

Since we are using Webpack, we can use require to pull in react, ReactTestUtils, and the component that we want to test (in this case, game-of-life).

In the test itself, we render <GameOfLife/> component into the Virtual DOM using TestUtils.renderIntoDocument.  Then, we find a rendered piece of our component with TestUtils.findRenderedDOMComponentWithClass and make assertions on it.

We can now run the tests with the following command:

$ karma start

We should now see 16 tests pass.

In the next article, we'll continue by test-driving the UI for the Game of Life.  If you want to see the finished code, check out the repo.  Thanks, and see you soon.

No comments:

Post a Comment