import "raf/polyfill"; import React from "react"; import { App, appName, Link, titleName } from "./App"; import { configure, shallow, mount } from "enzyme"; import Adapter from "enzyme-adapter-react-16"; import toJson from "enzyme-to-json"; // Configure Enzyme for the React version we are using. // Could be in a test setup file. Required for React 16, 15, 0.14, 0.13. configure({ adapter: new Adapter() }); describe(" shallow rendering", () => { const wrapper = shallow(); it("should find its elements", () => { // There is one

in : only one shoud be present in shallow rendering. expect(wrapper.find("p").length).toBe(3); expect(wrapper.find("p.App-intro").exists()).toBe(true); expect(wrapper.find("ul").hasClass("tyler")).toBe(true); expect(wrapper.find("ul").children().length).toBe(3); expect(wrapper.find("h1").text()).toBe("Welcome to React"); }); it("should find using props", () => { // "key" and "ref" could not be used that way. // CSS attribute syntax. expect(wrapper.find("[text='Some title']").length).toBe(1); // Object property selector. expect(wrapper.find({ text: "Some title" }).length).toBe(1); }); // FIXME cannot make sense of video. // @see http://airbnb.io/enzyme/docs/api/ReactWrapper/find.html test.skip("should find using a constructor", () => { // expect(wrapper.find(function App() { return ... }).length).toBe(1); }); it("should find using displayName", () => { const w = mount(); expect(w.find(appName).length).toBe(1); expect(w.find(titleName).length).toBe(1); }); it("matches the snapshot", () => { const tree = shallow(); expect(toJson(tree)).toMatchSnapshot(); }); it("should change p text on button click", () => { const button = wrapper.find("button"); expect(wrapper.find(".button-state").text()).toBe("No!"); // Simulate() will fetch the onClick prop on the component and call it. button.simulate("click"); expect(wrapper.find(".button-state").text()).toBe("Yes!"); }); it("should update className with new State", () => { expect(wrapper.find(".blue").length).toBe(1); expect(wrapper.find(".red").length).toBe(0); // Invoking setState() on the wrapper invokes in on the underlying component, // and causes a rerender. wrapper.setState({ mainColor: "red" }); expect(wrapper.find(".blue").length).toBe(0); expect(wrapper.find(".red").length).toBe(1); }); it("should change title text on input change", () => { const input = wrapper.find("input"); const expected = "Tyler"; expect(wrapper.find("h2").text()).toBe(""); // The optional parameter is the mocked event. input.simulate("change", { currentTarget: { value: expected } }); expect(wrapper.find("h2").text()).toBe(expected); }); it("should call componentDidMount, update p tag text", () => { jest.spyOn(App.prototype, "componentDidMount"); const w = shallow(); // Needs the method to be defined on the component for it to be invoked. expect(App.prototype.componentDidMount.mock.calls.length).toBe(1); expect(w.find(".lifeCycle").text()).toBe("componentDidMount"); }); it("should call componentWillReceiveProps", () => { jest.spyOn(App.prototype, "componentWillReceiveProps"); const w = shallow(); expect(w.find(".lifeCycle").text()).toBe("componentDidMount"); // Needs the method to be defined on the component for it to be invoked. expect(App.prototype.componentWillReceiveProps.mock.calls.length).toBe(0); w.setProps({ hide: true }); expect(App.prototype.componentWillReceiveProps.mock.calls.length).toBe(1); expect(w.find(".lifeCycle").text()).toBe("componentWillReceiveProps"); }); it("should return correctly from handleStrings()", () => { // instance() provides access to the underlying class implementing the component. const expectations = { "Hello, world": true, "": false, }; for (const [value, expected] of Object.entries(expectations)) { const actual = wrapper.instance().handleStrings(value); expect(actual).toBe(expected); } }); }); describe(" mount rendering", () => { it("h1 contains correct text", () => { // Second parameter is optional. const wrapper = mount(, { context: {}, attachTo: document.createElement("div"), }); expect(wrapper.find("h1").text()).toBe("Welcome to React"); // Tests can affect each other if mounted components are not unmounted, // since they will remain mounted in the same DOM. // Unmount() can also be used to simulate an unmount/mount cycle in React. wrapper.unmount(); }); it("matches the snapshot", () => { const tree = mount(); expect(toJson(tree)).toMatchSnapshot(); tree.unmount(); }); }); describe("", () => { const expected = "www.google.com"; it("link component accepts address prop", () => { const wrapper = shallow(); // wrapper.instance() is the React component. "props" is a property. expect(wrapper.instance().props.address).toBe(expected); }); // wrapper itself is the ShallowWrapper instance, not the React component. it("tag node renders href correctly", () => { const wrapper = shallow(); // Check its rendering: // console.log(wrapper.html(), wrapper.props()); expect(wrapper.prop("href")).toBe(expected); // Here "props" is a method, not a property. expect(wrapper.props().href).toBe(expected); }); it("returns null with true hide prop", () => { const wrapper = shallow(); expect(wrapper.find("a").length).toBe(1); expect(wrapper.props().href).toBe(expected); // Causes a rerender() of the component. // - triggers componentWillReceiveProps() wrapper.setProps({ hide: true }); expect(wrapper.find("a").length).toBe(0); // Dangerous: some versions of React might inject comments in HTML. // expect(wrapper.html()).toBeNull(); // expect(wrapper.getNode()).toBeNull(); // Obsolete: getNode() is deprecated. // Recommended way https://github.com/airbnb/enzyme/issues/52 expect(wrapper.getElement()).toBe(null); expect(wrapper.getElement()).toBeNull(); // Get() returns the node at the given index on the wrapper. expect(wrapper.get(0)).toBeNull(); }); });