# Testing React ## [Jest](https://jestjs.io/) ### Jest Configuration In `package.json`: ```json { // ... "scripts": { "test": "jest --watch" // watch re-runs test on save }, "jest": { // calls additional setups for enzyme, react tesing library, ... "setupFiles": [ "path/to/testSetup.js" ], "moduleNameMapper": { // file imports to ignore "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "path/to/fileMock.js", "\\.(css|less)$": "path/to/styleMock.js" } }, } ``` In `fileMock.js`: ```js // Mocks file imports for Jest. As suggested by https://jestjs.io/docs/en/webpack module.exports = "test-file-stub"; ``` In `styleMock.js`: ```js // Mocks CSS imports for Jest. As suggested by https://jestjs.io/docs/en/webpack module.exports = {}; ``` ### Jest Tests [Expect docs](https://jestjs.io/docs/expect) ```js // .spec.js or .test.js it("test description", () => { // test body expect(expected).toEqual(actual); }); // group related tests describe("test group name", () => { it(/* ... */); it(/* ... */); }); ``` ### Snapshots In `Component.Snapshots.js`: ```js import React from "react"; import rederer from "react-test-renderer"; import Component from "./path/to/Component"; // import mock data if necessary it("test descrtiption", () => { // renders the DOM tree of the component const tree = renderer.create(); // save a snaphot of the component at this point in time ( in __snaphsots__ folder) // in future test it will be checked to avoid regressions // can be updated during jest --watch pressing "u" expect(tree).matchSnapshot(); }); ``` --- ## [Enzyme](https://enzymejs.github.io/enzyme/) ### Enzyme Configuration ```js // testSetup.js import { configure } from "enzyme"; import Adapter from "enzyme-adapert-react-"; configure({ adapter: new Adapter() }); ``` ### Enzyme Tests In `Component.test.js`: ```js import React from "react"; import { shallow, mount } from "enzyme"; // eventual wrapper components (react-router, react-redux's provider, ...) for mount render // shallow renders single component w/o children, no DOM generated // mount renders component w/ it's children import Component from "./path/to/Component"; // factory to setup shallow test easily function testHelper(args) { const defaultProps = { /* default value for props in each test */ }; const props = { ...defaultProps, ...args }; return shallow(); } // shallow rendering test it("test description", () => { const dom = testHelper(/* optional args */); // or const dom = shallow(); // check a property of expected component // selector can be from raw JSX (name of a component) expect(dom.find("selector").property).toBe(expected); }); // mount rendering test if("test descriotion" () => { const dom = mount( ); // selector has to be HTML selector since the component is rendered completely // possible to test child components expect(dom.find("selector").property).toBe(expected); }); ``` --- ## [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/) Encourages to write test based on what the user sees. So components are always *mounted* and fully rendered. ### React Testing Library Tests In `Components.test.js`: ```js import React from "react"; import { cleanup, render } from "@testing-library/react"; import Component from "./path/to/Component"; afterEach(cleanup); // factory to setup test easily function testHelper(args) { const defaultProps = { /* default value for props in each test */ }; const props = { ...defaultProps, ...args }; return render(); } it("test description", () => { const { getByText } = testHelper(); // react testing library func getByText("text"); // check if test is present in the rendered component }); ```