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-scriptsWrite 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
testscript runs the tests in watch mode—which is the default option. - If you want to run the tests and exit, you can set the
CIenvironmental variable totrue. That’s what thetest:ciscript does, with the help of the cross-env package. An alternative to that is to set the--watchAllflag tofalse. - If your tests require the DOM—if you are testing React components for example—you can use the
test:jsdomscript which sets the--envflag tojsdom. - The
test:stagedscript is useful for running tests with a pre-commit hook—with husky and lint-staged for example. - Finally, the
test:coveragescript 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