0
votes

How would i be able to unit-test onChange method on this component.

Comment.js

import React  from "react";
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';
const Comment = (props) => (
    <div>

        <form onSubmit={props.onSubmit}>
             <TextField
                type="text"
                id="outlined-multiline-static"
                label="Write A Comment"
                multiline
                name="comment_body"
                value={props.commentBody}
                rows="10"
                fullWidth
                margin="normal"
                variant="outlined"
                onChange={props.commentChange}
            />
            {/* <Button type="submit" variant="outlined" component="span" color="primary">
                Post A Comment
            </Button> */}
             <button type="submit" variant="outlined" component="span" color="primary">
                Write a Comment
            </button>
        </form>
    </div>
)

export default Comment;

This is my attempt to unit test the onChange component, getting a

Method “simulate” is meant to be run on 1 node. 0 found instead

around this line

const component = shallow(<Comment commentChange={onChangeMock} commentBody={'test'} />) component.find('input').simulate('change');

Comment.test.js

import React from 'react';
import ReactDOM from 'react-dom';
import { shallow } from 'enzyme';

import Comment from './Comment';




describe('Should render <Comment/> component', () => {

    it('Should render form', () => {
        const wrapper = shallow(<Comment/>)
        // wrapper.find('Form').at(0)
        expect(wrapper.find("form")).toHaveLength(1); // checks if there is a form. 

    })

    it('Should render button', () => {
        const wrapper = shallow(<Comment/>)
        expect(wrapper.find('button')).toHaveLength(1);
    })

    it('should check for onChange method', () => {
        // const wrapper = shallow(<Comment onChange={}/>)
        const onChangeMock = jest.fn();
        // const event = {
        //     preventDefualt(){},
        //     target: {
        //         value: 'testing'
        //     }
        // }
        const component = shallow(<Comment commentChange={onChangeMock} commentBody={'test'} />)
        component.find('input').simulate('change');
        expect(onChangeMock).toBeCalledWith('test')
    })



})

The Comment component is being passed in another component like this:

ImageContainer.js

 state = {
      isComment: false,
      comment_body: ""
    }
    handleCommentChange = (e) => {
        this.setState({
           comment_body: e.target.value
        })             
    }

    commentSubmit = (event, id) => {
        event.preventDefault();
        console.log(this.state.comment_body); // doesn't get console.log
        // note that commentBody is being used for the req.body as well so its called by req.body.commentBody
        const commentBody = this.state.comment_body
        const data = {   
            commentBody,
            id
        }   
        this.props.postComment(data);
        this.setState({
            comment_body: ''
        })

    }

    <Comment onSubmit={(e) => this.commentSubmit(e, img.id)} 
                commentBody={this.state.comment_body } 
                commentChange={this.handleCommentChange}/> 
1

1 Answers

3
votes

The reason you are having the error is because when you call component.find('input') it returns an array of matched components, so what you want to do is

  1. component.find('input').at(0).simulate('change')

However, there is another way you can test this, which is my preferred method.

  1. component.find('input').at(0).props().onChange()

Below is the correct way to do the test with both methods

import React from "react";
import Enzyme, { shallow } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import Comment from "./Comment";
import TextField from "@material-ui/core/TextField";

Enzyme.configure({ adapter: new Adapter() });

describe("Should render <Comment/> component", () => {
  it("should check for onChange method (1)", () => {
    // const wrapper = shallow(<Comment onChange={}/>)
    const onChangeMock = jest.fn();

    const component = shallow(
      <Comment commentChange={onChangeMock} commentBody={"test"} />
    );
    component
      .find(TextField)
      .at(0)
      .simulate("change", "test");
    expect(onChangeMock).toBeCalledWith("test");
  });

  it("should check for onChange method (2)", () => {
    // const wrapper = shallow(<Comment onChange={}/>)
    const onChangeMock = jest.fn();

    const component = shallow(
      <Comment commentChange={onChangeMock} commentBody={"test"} />
    );
    component
      .find(TextField)
      .at(0)
      .props()
      .onChange();
    expect(onChangeMock).toBeCalled();
  });
});

For this particular test it will be better if you just use toBeCalled rather than toBeCalledWith. There is no need to test the value it is called with.