Setting up Jest with React and Webpacker
Tags: rails, webpacker, jest, react
Published: 2018-05-10 06:11:51

---
title: Setting up Jest with React and Webpacker
published: true
description: 
tags: rails, webpacker, jest, react
---

[Webpacker](https://github.com/rails/webpacker) is a great library that was [introduced](http://weblog.rubyonrails.org/2017/4/27/Rails-5-1-final/) 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](https://facebook.github.io/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`:

```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`](https://facebook.github.io/jest/docs/en/configuration.html#testpathignorepatterns-array-string) 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:

```json
{
  "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](https://babeljs.io/docs/usage/babelrc/#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`:

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

Now running `bin/yarn test` is successful!

## Running on Travis CI

I use [Travis CI](https://travis-ci.org/) 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!