Testing a React app in Node.js with Jasmine
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 React Testing Library to test it. We’ll also be using jsdom to provide a fake HTML DOM for the specs.
A complete working example of this setup is also available.
Choose the package managment tool you’ll be using:
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
$ npm install --save-dev @babel/core \
@babel/register \
babel-preset-react-app \
cross-env \
jsdom \
jasmine
Then initialize Jasmine:
$ yarn run jasmine init
$ npx 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 a Babel configuration with the following contents:
{
"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, JSX, or any other code that needs to be
transpiled, 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
$ npm install --save-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 is 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
$ npm install --save-dev @testing-library/react
See the React Testing Library documentation for more information. The related jasmine-dom matcher library may also be of interest.
Note that most of the React Testing Library docs are written for Jest, so the code samples require some translation before they’ll work in Jasmine. In particular:
- The Jasmine equivalent of
test()
isit()
. - Although there’s a lot of overlap, Jest and Jasmine have different built-in matchers.
- Jest creates an implicit top-level suite in each file. Jasmine doesn’t, so
wrapping the contents of each file in a well-named
describe
is highly recommended.
When translating code samples from Jest to Jasmine, you may find it helpful to refer to the Jasmine tutorial, the list of matchers that come with Jasmine, and the list of matchers that come with jasmine-dom.
Wrapping up
You’re all set. Write your specs and run them:
$ yarn test
$ npm test