Unittests - lumen-org/LumenReact GitHub Wiki
Run test with yarn test
- Tests are always called by
Componentname.test.js
- the global file
setupTests.js
is run at the beginning of the a testrun -
beforEach()
andafterEach()
are run before or after each individual test
import React from "react";
import { unmountComponentAtNode } from "react-dom";
import TestRenderer from "react-test-renderer";
import Field from "./Field";
/// mock children components for shallow rendering
jest.mock("../../components/Titles/TitleH2", () => (props) => (
<h2>{props.value}</h2>
));
jest.mock("../../components/FieldList/FieldList", () => (props) => (
<div>FieldList</div>
));
/// executed before every describe
let container = null;
let spy = null;
beforeEach(() => {
// setup a DOM element as a render target
container = document.createElement("div");
document.body.appendChild(container);
spy = jest.spyOn(console, 'error').mockImplementation(); /// prevents console from showing the errors while simultaniously being able to catch errors
});
/// executed after every describe
afterEach(() => {
// cleanup on exiting
unmountComponentAtNode(container);
container.remove();
container = null;
console.clear();
spy.mockRestore(); // important so errors are displayed again
});
/// Test missing Values
describe("Field.js Missing Values Test", () => {
it("missing value data", () => {
let title = "TestTitle";
TestRenderer.create(<Field title={title} />);
expect(console.error).toHaveBeenCalledTimes(1);
});
it("missing value title", () => {
let data = ["TestTitle"];
TestRenderer.create(<Field data={data} />);
expect(console.error).toHaveBeenCalledTimes(1);
});
});
/// test normal rendering and additional functionality
describe("Field.js Functionality Test", () => {
it("render normally", () => {
let title = "TestTitle";
let data = ["Test", "Test", "Test"];
const component = TestRenderer.create(<Field title={title} data={data} />);
let tree = component.toJSON();
expect(console.error).not.toBeCalled();
expect(tree).toMatchSnapshot();
});
});
- imports
- mock all child components
- before and after setup
- encapsulate tests with describe
- test the functionality (if it does what it is supposed to, what happens for border cases...)
- create snapshots for that purpose
- test if the internal state of the component changes as expected (always from the outside. Dont test the state directly!)
- only test the specific component. If possible mock as many relying components as possible without changing the functionality of the tested component or use shallow
- mock api calls
- test if there exists some kind of typecheck for the input parameter (e.g. propTypes)
- only renders a component one level deep -> no worrying about the behaviour of child components
const component = TestRenderer.create(
<Component property1={argument1} property2={argument2} />
)
- renders everything which is depended on the rendered
components are mocked by calling
jest.mock("path/to/component", () => (props) => {
<div>
{props.argument}
</div>
}
- to create a snapshot run
expect(componentAsJson).toMatchSnapshot()
- a snapshot is automatically created when a snapshot test is run the first time. The snapshot is placed under the folder snapshot in the same directory
- update snapshots with
yarn test --updateSnapshot
or interactively in watch mode by pressing u or i -its also possible to compare to inlinesnapshotsexpect(componentAsJson).toMatchInlineSnapshot();
- the next time you run yarn test the component tree will be evaluated and written as argument to
toMatchInlineSnapshot(componentTree)
see: https://reactjs.org/docs/testing.html
see: https://redux.js.org/recipes/writing-tests
todo:: redux todo:: id testing >.>