loading...

Setting up Jest with React and Webpacker

aergonaut profile image Chris Fung ・3 min read

Webpacker is a great library that was introduced in Rails 5.1. It gives an easy, out-of-the-box way to configure the latest Javascript tools, including Babel, Webpack, and React, to work seamlessly with Rails.

Generating a new React project with Webpacker is as easy as running one rails command. But how to write tests for your new React components is a little less clear. There's a myriad of different testing libraries out there for Javascript code, and the ecosystem can be a little confusing.

In this post, I'll show how I set up testing for my React components using Jest, and how I integrated Jest into my existing CI workflow for my Rails app.

Installing Jest

Jest is a Javascript testing library that's easy to set up and fast. It was developed by Facebook and has lots of support for testing React components.

Because Webpacker uses Babel, setting up Jest requires installing one extra package: babel-jest. This allows Jest to transpile code using Babel while testing. Install them both with bin/yarn:

bin/yarn install jest babel-jest

Creating a test

By default Jest will look for any file in a __tests__ directory or any file ending in *test.js and treat those files as test suites. "Suite" is Jest's term for a file containing one or more tests.

With Webpacker, React components are stored in the app/javascript directory. I had a directory structure like this:

app/javascript
├── packs
└── pulls
    └── components

The components directory is where all my components live, so I made a __tests__ directory inside that.

Running Jest

To run Jest, I added a new script to my package.json:

{
  "scripts": {
    "test": "jest"
  }
}

Now you can run Jest with Yarn:

bin/yarn test

However when I did this initially, I got an error:

$ bin/yarn test
yarn run v1.5.1
$ jest
 FAIL  config/webpack/test.js
  ● Test suite failed to run

    Your test suite must contain at least one test.

What's going on here is that Jest is assuming Webpacker's test.js config file is a test file because it ends in test.js. That's obviously not right! Luckily we can tell Jest to ignore certain file patterns with the testPathIgnorePatterns configuration option.

Jest configuration goes in package.json under the jest key. We just need to add config/webpack/test.js to the list of ignored paths:

{
  "jest": {
    "testPathIgnorePatterns": [
      "/node_modules/",
      "<rootDir>/config/webpack/test.js"
    ]
  }
}

Babel modules

Another error I ran into was:

SyntaxError: Unexpected token import

The problem here is that because Jest runs in Node, it needs to compile your code into CommonJS modules. However, by default, Webpacker configures Babel with "modules": false which tells Babel to skip transpiling ES6 modules into another format.

There's two ways to fix this. The first way is to remove "modules": false from Babel in the test environment. You can do this using the env option in .babelrc. However, when I tried this, I got different errors when Babel was transpiling my components. Ultimately, I decided that this way was not going to work out for me.

The second way is to add babel-plugin-transform-es2015-modules-commonjs to the test environment. This plugin will transform ES modules into CommonJS modules. I installed the plugin and added it to my .babelrc:

{
  "env": {
    "test": {
      "plugins": ["transform-es2015-modules-commonjs"]
    }
  }
}

Now running bin/yarn test is successful!

Running on Travis CI

I use Travis CI to run my tests, so I wanted to run Jest on Travis as well. Adding the test command to my .travis.yml file was simple enough, but I started getting more errors from Jest trying to run other Javascript files just because they were named with test.js at the end.

This turned out to be because Travis installs the Webpacker gem to the vendor directory in your project, which puts it in the path of searchable directories for Jest to discover tests in. I had to add the vendor directory to my list of ignored paths.

Conclusion

All in all, setting up Jest to work with Webpacker had a few minor hiccups but they were all easy to overcome. Testing React components with Jest is very easy, and I was surprised that it worked so well with Webpacker's config out of the box!

Posted on by:

aergonaut profile

Chris Fung

@aergonaut

Code monkey. Sorcerer. Collector of obscure phone games. I write code and sometimes write about writing code. E89B 5EC4 67AC 51D8

Discussion

markdown guide