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: [

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:
    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.

Monday, 8 June 2015

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

So, we started off by outlining building a small application with modern JavaScript tools, and then built a small module for Conway's Game of Life. This was test-driven using Karma. Now, we are going to introduce Webpack and React into the mix.

In this article, I'll set the stage for creating the front-end component for the game. We'll introduce Webpack and react-hot-loader to ease the development of the project and build an HTML-only React component for our simple UI.

Installing Webpack and react-hot-loader

Webpack is kind of a multi-purpose bundler for JavaScript applications.  It has tons of great features (like support for all type of module systems etc.) and you should definitely check out the project website to read the details. I'm going to assume that you know what the tool does and just focus on the details of installation.  The configuration is going to be quite basic, but I'll also introduce react-hot-loader so that the project live reloads in the browser.  This is going to help make the development work easy because we won't have to continually refresh to see changes.

Ok, since we already have npm set up, the first thing we'll do is pull in some new packages:

$ npm install webpack --save-dev
$ npm install react-hot-loader --save-dev 
$ npm install babel-loader --save-dev
$ npm install webpack-dev-server --save-dev

Installing the packages give us everything we need to progress with the project.

The babel-loader could be replaced with jsx-loader, but the Babel project allows us to also use some ES6 (ES2015) features if we want to in the future.  Later, we might integrate Babel with Karma, but at the moment, there is no need.  Babel supports the transpilation of our React jsx syntax and that is what we are after for this project.

The react-hot-loader works with the webpack-dev-server to create a web socket connection that it can use to live reload.  So, we need the webpack-dev-server project to support those requirements. react-hot-loader holds a dependency on React, so there is no need to install it separately.

At this point, Webpack isn't going to do much.  It requires a simple config file so that it knows what directories and files to watch and where to deliver them.  So, we'll create a new file named webpack.config.js and add it the root directory.  Inside the file will look like this:

There are a few areas of the file that are interesting. The entry section shows that we are building up the runtime of the app by passing through the webpack-dev-server.  Finally, we give index.js as the entry point for the application.  We'll create that file in a minute.

The next section to look at is the output section.  This section shows were the files will be delivered in order to sever them.  The /assets/ directory (in our case) will only be virtually served through the development server, so there is no need to create this directory.

Finally, the module section is interesting because it shows the loader pipeline that the code will go through.  First, the react-hot loader will watch for file changes.  Then, the babel-loader will transpile the files in order to serve them up.  The test property gives a regular expression indicating that we are interested in .js files for this pipeline.  For this project, we won't use the .jsx extension.  We'll just use .js and Babel will take care of the rest.

At the moment, running the webpack command from the root directory will complain with the following message:

Module not found: Error: Cannot resolve 'file' or 'directory' ./index.js in /home/life/src

So, let's create the index.js file in the /src directory. At the moment just create a completely empty file /src/index.js.  Now, go back to the root directory and run the following command:

$ webpack

This time you should see a successful build.  We didn't add any code, but if you look in the /dist/bundle.js file, you can see that a lot of dependencies have been included.  So, we are now set up to configure the hot loading capability.
As a side node.  The index.js file acts as an entry point for the application.  It is important to separate the entry point file from the files that make up your components so that the hot loader can live reload the files that change.  If you put everything inside the main entry point file, the react-hot-loader will complain that any change requires a complete refresh.
In order to configure hot loading, we need a dev server.  The dev server runs as an express app, so the easiest thing is to add a server.js file the the root directory with the following contents:

This is taken from the awesome react-hot-boilerplate project by gaearon.  You can see that in the file we reference the Webpack config publicPath.  This was the /assets/ directory mentioned earlier.

After adding the server.js file, we'll add an npm script in the package.json file to start up the server:

The scripts property is a top-level property of the package.json file. Here we define a start command that will run our previously defined server.js file with node.

Run the following command to build and run the dev server:

$ npm start

You should see a server start on port 3000 (or your configured port) and then the bundle.js file created and served.

We still aren't serving anything of interest, so let's add an index.html file in the root directory and link in our /assets/bundle.js.  So create a file named index.html in the root directory with the following contents:

Inside the above file we set up a div with the id set to content.  This will be our application root for the React component.

We still are not going to be able to see the react-hot-loader in action.  This is because only dependencies of the entry point file index.js will be involved in the live reload.  In order to show that working, let's begin to create the skeleton of the React application.

A Simple React Application with react-hot-loader

In order to create an flat React application, let's add a new directory named components inside the /src directory. Then, inside the new /src/components directory, add a new file named game-of-life.js.  Add the following contents to the new file:

In the above file, we create a div with the text "Game of Life." inside and render that in a React component. It is important to remember to export the component so that we can require this as a dependency in the index.js file.

We also have to make a slight addition to the /src/game.js file in order to require it in the above file.  We must export the Game function so that game-of-life.js can require it.  We'll do this by passing in module or window and binding the function returned in the module:

The defensive check to see if (typeof module !== 'undefined') is important because this code also has to run under the Karma tests.  And we have not set up Karma to understand modules.

Finally, let's require the game-of-life.js dependency by adding this to index.js:

The code above requires the game-of-life module and then binds it to the content div in index.html.

Now, if we run the command npm start, the dev server will start up.  Open a browser and visit http://localhost:3000. You should see the text "Game of Life." rendered to the screen.  Now the fun part.  Open up the /src/game-of-life.js file in your favourite text editor and change "Game of Life." to "Conways Game of Life.".  After saving the file, you should see the value automatically update in the browser!

We are now all set up with Webpack and react-hot-loader.  In the next article, we'll start to build the component for Conway's Game of Life.  You can check out the completed repository now if you want.

Sunday, 7 June 2015

Test-Driven React with Karma and Webpack: #2 Game Logic

This article continues from the first instalment in this series where we set up the JavaScript environment with Karma to run begin test-driving Conway's Game of Life.

Alright, this time we are going to finish off test-driving the game logic. Let's jump right in with the next test.

Test-Driving the Game Module

Now, we want to introduce the ability to set a cell in the grid.  The following test will make sure that we can set a single cell in the grid:

Running the karma start command now will run red because the setCell method is not defined yet.  Not to worry, let's implement it now:

Now run the following command:

$ karma start

You should now see 2 tests running green!

Conway's Game of Life has 4 rules:
  1. Any live cell with fewer than two live neighbours dies, as if caused by under-population.
  2. Any live cell with two or three live neighbours lives on to the next generation.
  3. Any live cell with more than three live neighbours dies, as if by overcrowding.
  4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
Here are the tests for the first rule:

This describe needs to be nested inside the original describe in order to apply the beforeEach to each of the tests. Let's get that to pass by adding the nextFrame function. The nextFrame function is where most of the game is implemented.  It represents one generation in The Game of Life.  It will use the existing state of the internal data structure _grid and use the rules of the game to mutate the game state.

The code above is mostly concerned with counting neighbour cells and protecting against hitting the boundary of the grid.  In Conway's Game of Life, each cell has 8 neighbours.  However, if the cell is against the edge of the grid, it could have only 5.  And if the cell is in the corner of the grid, only 3.  Once the neighbour count is done, the 1st rule is straight forward:

The second rule tests are next:

The surprising thing about these tests, is that they all pass without any changes to the code! This is because at the moment our original rule covers both cases.  Let's now add tests for the 3rd rule of the game:

Now the tests will run red because now we are introducing the rule that if there are over 3 neighbours the cell dies. And before we were only catering for the case where there were under 2 live neighbours. Let's fix that by very slightly adjusting our rule logic:

Now that we added that a cell dies when live neighbours are greater than 3, everything works as expected. Almost done, we just have to add tests for the final rule:

Finally, this test is asserting that if we have exactly 3 live neightbors, then the cell becomes alive as well. At first this runs red, but let's update our code to finish off the game:

Adding the final completes the game logic for Game of Life! Running the command $ karma start, should now show all tests passing.  You can see all of the tests and code at the completed repository if you get into any trouble.

Ok, now we are in the position to add the environment for React and start to build up our web components.  This will be topic of the next instalment.

Thursday, 4 June 2015

Test-Driven React with Karma and Webpack

Over the past few months, I've been digging deeper into React and tools. I've come to really enjoy developing web components with React.

So far, I have not looked into the React Flux patten much and intend to do that soon. However, I wanted to go through a step-by-step guide to getting up and running with React.

In this series, I want to go a bit further than showing just how React props and events work. I'll introduce building modules that can be consumed with React using test-driven development, Webpack for React, and react-hot-loader to make browser development more seamless.

For this guide, I'm going to use Karma as the Jasmine test runner.  Also, I'm not going to use Bower for JavaScript package management at all.  I'll favour using npm as both package manager and task runner.

In this example, I'm going to build a small Conway's Game of Life.  It will be fairly simple, but complete.  You can see the completed repository on github (feel free to send pull requests!).

Getting the environment set up

I'm going to be working on a Ubuntu flavor Linux machine, but I'm fairly certain all of these commands will work the same on any platform.  I'm going to assume you have node and npm installed (I'm using node.js v0.10.36).

The directory structure is very simple:

├── src
│   ├── components
│   └── game
├── styles
└── tests
    └── game

The root directory will hold the index.html that we'll serve (as well as some config files).

Let's start to pull in some of the tools that we'll be using:

First, install Karma, Jasmine and PhantomJS from npm with:

$ npm install karma --save-dev 
$ npm install karma-jasmine karma-phantomjs-launcher --save-dev 

I also installed the karma-cli in order to make running Karma slightly easier:

$ npm install -g karma-cli

This should be enough to get started writing the game module.  In order to test that everything is set up correctly, let's run a few commands:

$ phantomjs --version
$ 1.9.0

$ karma --version
$ Karma version: 0.12.35

The last thing we have to do before writing some code is to configure Karma.  I used the command karma init command to generate a new config file.  Most of the questions should be straight forward.  Select jasmine as the testing framework and PhantomJS as the browser.  Finally, we need to add the /src and /tests directory to the files array so that Karma will track these files:

    // list of files / patterns to load in the browser
    files: [

Some Test-Driving with Karma

We are now ready to add a test harness for the game module.  Add a new file named game-test.js to the /tests/game directory.

The first test that we'll write will be to create a 30 x 30 grid.  The grid will be represented as a simple array of arrays:

Now create a new file in /src/game named game.js where we can begin to implement the game. We can now create an empty Game module:

Run Karma to see a red test:

$ karma start

This should fail and give because the grid() function isn't defined yet.  Let's change that now:

Now when we re-run our tests with karma, it should run green.

In the next post, we'll finish the Game module and start to introduce React with Webpack.