简体   繁体   中英

Write a Unit test in Jest for a React form

I have a form as follow:

import React from 'react/lib/ReactWithAddons';
import { server } from '../data/server';
export const Report = React.createClass({
    mixins: [React.addons.LinkedStateMixin],

    sendReport(event) {
        event.preventDefault();
        var data = {
            ac: this.ab.checked,
            cp: this.cp.checked,
            nr: this.nr.checked,
            il: this.il.checked,
            message: this.message.value,
            name: this.name.value,
            affiliation: this.affiliation.value,
            email: this.email.value,
            address: this.address.value,
            city: this.city.value,
            country: this.country.value,
            zipcode: this.zipcode.value,
            phone: this.phone.value,
        };
        server.report(this.props.params.id, data,() => {  .....  });
    },

    render: function() {
        return (
            <form  onSubmit={this.sendReport}>
                <div><input id='reason' ref={(ref) => this.ab = ref} name='reason'  type='radio' value='ab'  required /></div>
                <div><input id='reason' ref={(ref) => this.cp = ref} name='reason' type='radio' value='cp' /></div>
                <div><input id='reason' ref={(ref) => this.nr = ref} name='reason' type='radio' value='nr'  /></div>
                <div><input id='reason' ref={(ref) => this.il = ref} name='reason' type='radio' value='il'  /></div>
                <div><textarea ref={(ref) => this.message = ref}  name='message' className="form-control" type='textarea' rows="4" cols="50"  required/></div>
                <div><input id='name' ref={(ref) => this.name = ref} name='name' className="form-control" type='text'  required /></div>
                <div><input id='affiliation' ref={(ref) => this.affiliation = ref}  name='affiliation' className="form-control" type='text' required /></div>
                <div><input id='email' ref={(ref) => this.email = ref} name='email' className="form-control" type='email' required /></div>
                <div><input id='address' ref={(ref) => this.address = ref} name='address' className="form-control" type='text'  required /></div>
                <div><input id='city' ref={(ref) => this.city = ref} name='city' className="form-control" type='text'  required /></div>
                <div><select id='country' ref={(ref) => this.country = ref} name='country' className="form-control" defaultValue=""  required >
                    <option value="">Choose country</option>
                    <option value="Canada" >Canada</option> 
                    .... 
                    </select></div>
                <div><input id='zipcode' ref={(ref) => this.zipcode = ref} name='zipcode' className="form-control" type='text'  required /></div>
                <div><input id='phone' ref={(ref) => this.phone = ref} name="phone" type='text'  pattern="[0-9]*" className="form-control" title= "Numbers Only" required /></div>
                <div><button id='send' type="submit" >Send</button></div>
            </form>
        );
    }
});

Here is how I'm trying to write a unit test for it:

import { Report } from '../src/components/report';
import { server } from '../src/data/server';
import { shallow } from 'enzyme';
import React from 'react/lib/ReactWithAddons';
import { shallowToJson } from 'enzyme-to-json';
import ReactTestUtils from 'react-addons-test-utils';

describe('Report form', () => {
    const component = shallow(<Report params={{ id: '1033083fe' }} />);
    const sendReport = jest.fn();

    it('sends the form correctrly', ()=> {
        var data = {cp:true, message: 'testmessage', name:'testname', affiliation:'testaaa', email:'sss@test.com', address:'test address', city:'testcity', country:'testcountry', zipcode:'12345', phone: '0987654321'}
        const button = component.find('button');
        const cp = component.find('#cp');
        const message = component.find('#message');
        const name = component.find('#name');
        const affiliation = component.find('#affiliation');
        const email = component.find('#email');
        const address = component.find('#address');
        const city = component.find('#city');
        const country = component.find('#country');
        const zipcode = component.find('#zipcode');
        const phone = component.find('#phone');

        component.setState({ phone: '0987654321' });
        expect(component.find('#phone').length).toEqual(1);

        ## cp.simulate('change', { target: { value: true } });
        ## message.simulate('change', { target: { value: 'testmessage' } });
        name.simulate('change', { target: { value: 'testname' } });
        affiliation.simulate('change', { target: { value: 'testaaa' } });
        email.simulate('change', { target: { value: 'sss@test.com' } });
        address.simulate('change', { target: { value: 'test address' } });
        city.simulate('change', { target: { value: 'testcity' } });
        country.simulate('change', { target: { value: 'testcountry' } });
        zipcode.simulate('change', { target: { value: '12345' } });
        phone.simulate('change', { target: { value: '0987654321' } });
        button.simulate('click');

        expect(sendReport).toBeCalledWith(data);        
        expect(shallowToJson(component)).toMatchSnapshot();
    });
});

The goal is to check if the form sends the data correctly to the sendreport() method or not (after clicking the send button). All the fields are mandatory. The simulation of 'cp' and message fields returns this error:

Method “props” is only meant to be run on a single node. 0 found instead.

So I had to comment them. But then I'll get this error:

expect(jest.fn()).toBeCalledWith(expected)

Expected mock function to have been called with:
  [{cp:true, message: 'testmessage', name:'testname', affiliation:'testaaa', email:'sss@test.com', address:'test address', city:'testcity', country:'testcountry', zipcode:'12345', phone: '0987654321'}]
But it was not called.

I assume that server is some external module that you import into your react component file like this:

import server from 'server'

Then you need to mock it in your test file like like this

import server from '../src/data/server'
jest.mock('../src/data/server', ()=> ({server: {report: jest.fn()}}))

In your test you can then expect thar server.report was called:

expect(server.report.mock).toBeCalledWith(data); 

And to find only one element use closest instead of find as the later always returns an array of elements where you cant use prop on. If you use find you need to do it like this component.find.first('button') , this would be the same as component.closest('button')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM