# Testing React ## [Jest](https://jestjs.io/) ### Jest Configuration ```js // jest.config.js module.exports = { testEnvironment: 'jsdom', moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx', 'json', 'node'], setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'], // add testing-library methods to expect() transform: { '^.+\\.tsx?$': 'ts-jest'} // use ts-jest fo ts files } ``` ### 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 renderer from "react-test-renderer"; import Component from "./path/to/Component"; // import mock data if necessary it("test description", () => { // renders the DOM tree of the component const tree = renderer.create(); // save a snapshot of the component at this point in time ( in __snapshots__ 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-adapter-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 description" () => { 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 }); ```