Unit testing with react-scripts
Table of contents
You can use react-scripts to write unit tests without setting up a build process with Babel and Webpack/Rollup. It’s useful when you want to quickly test an idea, but you’re not sure if you want to create a library yet. It can also be useful when your code lives inside a yarn workspace and doesn’t need a build process.
Install react-scripts
Install react-scripts
as a devDependency
by typing in your terminal:
yarn add -D react-scripts
Write test scripts
Create some test scripts in your package.json
, that will help you run the tests:
{
"scripts": {
"test": "react-scripts test",
"test:ci": "cross-env CI=true react-scripts test",
"test:ci:alt": "react-scripts test --ci --watchAll=false",
"test:jsdom": "yarn test --env=jsdom",
"test:staged": "yarn test:ci --findRelatedTests",
"test:coverage": "yarn test:ci --coverage"
}
}
What the test scripts do
- The
test
script runs the tests in watch mode—which is the default option. - If you want to run the tests and exit, you can set the
CI
environmental variable totrue
. That’s what thetest:ci
script does, with the help of the cross-env package. An alternative to that is to set the--watchAll
flag tofalse
. - If your tests require the DOM—if you are testing React components for example—you can use the
test:jsdom
script which sets the--env
flag tojsdom
. - The
test:staged
script is useful for running tests with a pre-commit hook—with husky and lint-staged for example. - Finally, the
test:coverage
script runs the tests and creates a coverage report. You can configure the coverage script further if you want.
Write tests
To write tests, use the test
or it
functions and assert your logic with the expect
function. You can optionally organize your tests inside a describe
function. In the following snippet, I wrote some tests for a “flatten” function, that takes a nested array as input and returns a flat array.
The tests:
import flatten from "./flatten";
describe("Flatten tests:", () => {
it("Flattens an array.", () => {
const nestedArray = [[1, 2, 3], [4]];
const flatArray = [1, 2, 3, 4];
expect(flatten(nestedArray)).toEqual(flatArray);
});
it("Returns empty array when the input is an empty array.", () => {
const array = [];
const result = flatten(array);
const expectedResult = [];
expect(result).toEqual(expectedResult);
});
});
describe("Infinite nesting tests:", () => {
it("Goes 4 levels deep.", () => {
const nestedArray = [[1, 2, [3, [[4], 5]]], [6]];
const flatArray = [1, 2, 3, 4, 5, 6];
const result = flatten(nestedArray);
expect(result).toEqual(flatArray);
});
});
describe("Exact level tests:", () => {
it("Goes exactly two levels deep.", () => {
const nestedArray = [[1, [2, [3]], 4], [5]];
const flatArray = [1, 2, [3], 4, 5];
const result = flatten(nestedArray, 2);
expect(result).toEqual(flatArray);
});
});
The flatten function:
const flatten = (array, level = 9999) => {
if (!Array.isArray(array)) return array;
const shouldGoDeeper = (lvl) => lvl + 1 <= level;
const toFlat = (lvl) => (result, item) => {
if (shouldGoDeeper(lvl) && Array.isArray(item))
return item.reduce(toFlat(lvl + 1), result);
return result.concat(item);
};
return array.reduce(toFlat(1), []);
};
export default flatten;
Useful links
Other things to read
Popular
- Reveal animations on scroll with react-spring
- Gatsby background image example
- Extremely fast loading with Gatsby and self-hosted fonts