Material UI + Enzyme testing component

前端 未结 3 1028
一生所求
一生所求 2021-02-04 11:25

I have component in React which I\'m trying to test with Jest, unfortunately test do not pass.

The component code:

import React, {Component} from \'react         


        
相关标签:
3条回答
  • 2021-02-04 12:18

    Something like this worked for me:

    import {createMount} from '@material-ui/core/test-utils';
    
    const WrappedComponent = () => 
        <MUIThemeStuffEtc>
            <MyComponent />
        </MUIThemeStuffEtc>
    
    const render = createMount();
    const wrapper = render(<WrappedComponent />);
    
    const state = wrapper.find(MyComponent).instance().wrappedInstance.state
    
    0 讨论(0)
  • 2021-02-04 12:20

    Following is a humble attempt to provide a more complete answer from create-react-app and @material-ui perspective.

    1. Create setupTests.js directly in src folder and paste the following code.

    import { configure } from "enzyme";
    import Adapter from "enzyme-adapter-react-16";
    
    configure({ adapter: new Adapter() });
    

    2. The following is react stateless component which uses material-ui components.

    import React from "react";
    import TextField from "@material-ui/core/TextField";
    
    const SearchField = props => (
       <TextField InputProps={{ disableUnderline: true }} fullWidth
                  placeholder={props.placeholder}
                  onChange={props.onChange}
       />
    );
    
    export default SearchField;
    

    Note that in the above component, the component expects parent component to pass the props for placeholder and onChange() event handler

    3. Coming to the test case for for the above component we can write either in a way material-ui suggests or in a pure enzyme style. Both will work.

    Pure Enzyme Style

    import React from "react";
    import { mount } from "enzyme";
    import TextField from "@material-ui/core/TextField";
    import SearchField from "../SearchField";
    describe("SearchField Enzyme mount() ", () => {
      const fieldProps = {
        placeholder: "A placeholder",
        onChange: jest.fn()
      };
      const Composition = props => {
        return <SearchField {...fieldProps} />;
      };
    
      it("renders a <TextField/> component with expected props", () => {
        const wrapper = mount(<Composition />);
        expect(wrapper.childAt(0).props().placeholder).toEqual("A placeholder");
        expect(wrapper.childAt(0).props().onChange).toBeDefined();
      });
      it("should trigger onChange on <SearchField/> on key press", () => {
        const wrapper = mount(<Composition />);
        wrapper.find("input").simulate("change");
        expect(fieldProps.onChange).toHaveBeenCalled();
      });
      it("should render <TextField />", () => {
        const wrapper = mount(<Composition />);
        expect(wrapper.find(TextField)).toHaveLength(1);
        expect(wrapper.find(TextField).props().InputProps.disableUnderline).toBe(
          true
        );
      });
    });
    

    Material UI style

    import React from "react";
    import { createMount } from "@material-ui/core/test-utils";
    import TextField from "@material-ui/core/TextField";
    import SearchField from "../SearchField";
    describe("SearchField", () => {
      let mount;
      const fieldProps = {
        placeholder: "A placeholder",
        onChange: jest.fn()
      };
      beforeEach(() => {
        mount = createMount();
      });
    
      afterEach(() => {
        mount.cleanUp();
      });
    
      it("renders a <TextField/> component with expected props", () => {
        const wrapper = mount(<SearchField {...fieldProps} />);
        expect(wrapper.props().placeholder).toEqual("A placeholder");
        expect(wrapper.props().onChange).toBeDefined();
      });
      it("should trigger onChange on <SearchField/> on key press", () => {
        const wrapper = mount(<SearchField {...fieldProps} />);
        wrapper.find("input").simulate("change");
        expect(fieldProps.onChange).toHaveBeenCalled();
      });
    });
    

    5. The error you are getting is due to the fact that babel is not getting a chance to process your file. The create-react-app expects you to run tests like yarn run test and not like jest your/test/file.js. If you use latter babel won't be employed.

    If you want to use jest to run the file you will have to write a jest.config.js file or configure jest in package.json file to use babel-jest + other babel dependencies to transpile your code before jest tries to execute tests.

    I was in the same boat yesterday as I tried to use @material-ui for the first time and came here to get a more complete answer.

    0 讨论(0)
  • 2021-02-04 12:29

    It's something different when you're using @material-ui.

    You've to use @material-ui's Built-in API(s). Such as createMount, createShallow, createRender in order to use enzyme's shallow, mount & render.

    These APIs are built on top of enzyme, so you can't use enzyme directly for testing @material-ui.


    Example of Shallow Rendering with @material-ui

    import { createShallow } from '@material-ui/core/test-utils';
    
    describe('<MyComponent />', () => {
      let shallow;
    
      before(() => {
        shallow = createShallow(); 
      });
    
      it('should work', () => {
        const wrapper = shallow(<MyComponent />);
      });
    });
    

    Reference: Official Docs of @material-ui

    0 讨论(0)
提交回复
热议问题