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!
Top comments (0)