diff --git a/JavaScript/React/React Tests.md b/JavaScript/React/React Tests.md new file mode 100644 index 0000000..b2302da --- /dev/null +++ b/JavaScript/React/React Tests.md @@ -0,0 +1,176 @@ +# 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": [ + "./tools/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)$": "/tools/fileMock.js", + "\\.(css|less)$": "/tools/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 +// /tools/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 "react-testing-library"; + +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 +}); +```