Testing a React app with Jasmine NPM
The Jasmine NPM package was originally designed just to run specs against your Node.js code, but with a couple of other packages, you can use it to run your React specs as well. This tutorial assumes you’re using babel to compile your code and either enzyme or React Testing Library to test it. We’ll also be using jsdom to provide a fake HTML DOM for the specs.
Basic setup
Install these packages if you haven’t already:
$ yarn add --dev @babel/core \
@babel/register \
babel-preset-react-app \
cross-env \
jsdom \
jasmine
Then initialize Jasmine:
$ yarn run jasmine init
That command will create spec/support/jasmine.json and populate it with an
initial default configuration. With Jasmine initialized, the first thing we’ll
do is make a helper to register babel into the require chain. This will cause
TypeScript files to be compiled to Javascript on the fly when they’re loaded.
Make a new file called babel.js in the spec/helpers directory:
require('@babel/register');
Or, if using TypeScript:
require('@babel/register')({
"extensions": [".js", ".jsx", ".ts", ".tsx"]
});
We need to tell Babel what flavor of Javascript we want by adding the following
to package.json:
"babel": {
"presets": ["react-app"]
}
Next, we need to provide a simulated browser environment. Create jsdom.js in
spec/helpers with the following contents:
import {JSDOM} from 'jsdom';
const dom = new JSDOM('<html><body></body></html>');
global.document = dom.window.document;
global.window = dom.window;
global.navigator = dom.window.navigator;
In order to ensure these files are loaded before any specs run, we’ll edit
spec/support/jasmine.json. We need the Babel helper to be loaded before any
helpers that contain TypeScript code, so we modify jasmine.json like so:
"helpers": [
"helpers/babel.js",
"helpers/**/*.js"
],
Or, if using Typescript:
"helpers": [
"helpers/babel.js",
"helpers/**/*.{js,ts}"
],
Next, set up the test script in package.json to run Jasmine:
"scripts": {
"test": "cross-env NODE_ENV=test jasmine",
Handling CSS and image imports
It’s common for React code to import CSS or image files. Normally those imports are resolved at build time but they’ll produce errors when the specs are run in Node. To fix that, we add one more package:
$ yarn add --dev ignore-styles
And put the following code in spec/helpers/exclude.js.
import 'ignore-styles';
Optional: Spec file pattern configuration
You also might want to change the way that Jasmine looks for spec files.
Jasmine traditionally looks for files in the spec directory with names ending
in .spec.js, but a common convention in React projects is to put spec files
in the same directories as the code they test and give them names ending in
.test.js. If you want to follow that convention, change the spec_dir,
spec_files, and helpers setting in spec/support/jasmine.json accordingly:
"spec_dir": "src",
"spec_files": [
"**/*.test.*"
],
"helpers": [
"../spec/helpers/babel.js",
"../spec/helpers/**/*.js"
],
Or, for TypeScript:
"spec_dir": "src",
"spec_files": [
"**/*.test.*"
],
"helpers": [
"../spec/helpers/babel.js",
"../spec/helpers/**/*.{js,ts}"
],
Setting up a React testing utility
We’ll need a way to render React components and inspect the result. There are several utility libraries that provide that functionality. The most popular are enzyme and React Testing Library.
Enzyme
To set up Enzyme, we’ll first install these packages:
$ yarn add --dev enzyme \
enzyme-adapter-react-16 \
jasmine-enzyme
Then we’ll want to make sure that we have enzyme loaded up, so make another
file in spec/helpers, we’ll call this one enzyme.js for Javascript or
enzyme.ts for TypeScript. (The file extension is important. While most of the
helpers can be .js regardless of whether we’re using Javascript or
TypeScript, this one has to be .ts in a TypeScript project. Otherwise the
type definitions for jasmine-enzyme won’t be imported and spec files that use
those matchers will fail to type check.)
import jasmineEnzyme from 'jasmine-enzyme';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
beforeEach(function() {
jasmineEnzyme();
});
See the Enzyme documentation for more information about using Enzyme, and the jasmine-enzyme documenatation for a list of available matchers.
React Testing Library
Setup for react-testing-library is simple. All we need to do is make sure the
@testing-library/react package is installed. If you used a recent version of
create-react-app to initialize your application, it might already be there.
If not, install it:
$ yarn add --dev @testing-library/react
See the React Testing Library documentation for more information. The related jasmine-dom matcher library may also be of interest.
Wrapping up
You’re all set. Write your specs and run them:
$ yarn test