最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - enzyme simulate submit form, Cannot read property 'value' of undefined - Stack Overflow

programmeradmin6浏览0评论

I'm having some difficulty testing a ponent with jest and enzyme. What I would like to do is test submitting the form without a value in the name field. This will make certain that the ponent is displaying an error. However, when I run the rest I am getting an error in my console:

TypeError: Cannot read property 'value' of undefined

I'm fairly new to front-end testing, and testing in general. So, I'm not entirely sure I'm using enzyme correctly for this type of test. I don't know if my tests are incorrect or if I've just written a ponent that is not easily tested. I'm open to changing my ponent if that will make it easier to test?

Component

class InputForm extends Component {
  constructor(props) {
    super(props);
    this.onFormSubmit = this.onFormSubmit.bind(this);
  }

  onFormSubmit(e) {
    e.preventDefault();
    // this is where the error es from
    const name = this.name.value;
    this.props.submitForm(name);
  }

  render() {
    let errorMsg = (this.props.validationError ? 'Please enter your name.' : null);
    return (
      <form onSubmit={(e) => this.onFormSubmit(e)}>
        <input
          type="text"
          placeholder="Name"
          ref={ref => {
                 this.name = ref
               }}
        />
        <p className="error">
          {errorMsg}
        </p>
        <input
          type="submit"
          className="btn"
          value="Submit"
        />
      </form>
      );
  }
}
InputForm.propTypes = {
  submitForm: React.PropTypes.func.isRequired,
};

Test

  // all other code omitted
  // bear in mind I am shallow rendering the ponent

  describe('the user does not populate the input field', () => {

    it('should display an error', () => {
      const form = wrapper.find('form').first();
      form.simulate('submit', {
        preventDefault: () => {
        },
        // below I am trying to set the value of the name field
        target: [
          {
            value: '',
          }
        ],
      });
      expect(
        wrapper.text()
      ).toBe('Please enter your name.');
    });

  });

I'm having some difficulty testing a ponent with jest and enzyme. What I would like to do is test submitting the form without a value in the name field. This will make certain that the ponent is displaying an error. However, when I run the rest I am getting an error in my console:

TypeError: Cannot read property 'value' of undefined

I'm fairly new to front-end testing, and testing in general. So, I'm not entirely sure I'm using enzyme correctly for this type of test. I don't know if my tests are incorrect or if I've just written a ponent that is not easily tested. I'm open to changing my ponent if that will make it easier to test?

Component

class InputForm extends Component {
  constructor(props) {
    super(props);
    this.onFormSubmit = this.onFormSubmit.bind(this);
  }

  onFormSubmit(e) {
    e.preventDefault();
    // this is where the error es from
    const name = this.name.value;
    this.props.submitForm(name);
  }

  render() {
    let errorMsg = (this.props.validationError ? 'Please enter your name.' : null);
    return (
      <form onSubmit={(e) => this.onFormSubmit(e)}>
        <input
          type="text"
          placeholder="Name"
          ref={ref => {
                 this.name = ref
               }}
        />
        <p className="error">
          {errorMsg}
        </p>
        <input
          type="submit"
          className="btn"
          value="Submit"
        />
      </form>
      );
  }
}
InputForm.propTypes = {
  submitForm: React.PropTypes.func.isRequired,
};

Test

  // all other code omitted
  // bear in mind I am shallow rendering the ponent

  describe('the user does not populate the input field', () => {

    it('should display an error', () => {
      const form = wrapper.find('form').first();
      form.simulate('submit', {
        preventDefault: () => {
        },
        // below I am trying to set the value of the name field
        target: [
          {
            value: '',
          }
        ],
      });
      expect(
        wrapper.text()
      ).toBe('Please enter your name.');
    });

  });
Share Improve this question edited Dec 23, 2016 at 6:22 j_quelly asked Dec 23, 2016 at 5:40 j_quellyj_quelly 1,4494 gold badges17 silver badges40 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 6

I think that you don't need to pass event object to simulate the submit event. This should work.

  describe('the user does not populate the input field', () => {

    it('should display an error', () => {
      const form = wrapper.find('form').first();
      form.simulate('submit');
      expect(
        wrapper.find('p.error').first().text()
      ).toBe('Please enter your name.');
    });

  });

As a rule of thumb, you should avoid using refs whenever possible, why? here

In your case, I suggest one of the better approaches could be :

  class InputForm extends Component {
      constructor(props) {
        super(props);
        this.state = {
            name : ''
        }
        this.onFormSubmit = this.onFormSubmit.bind(this);
        this.handleNameChange = this.handleNameChange.bind(this);
      }


      handleNameChange(e){
        this.setState({name:e.target.value})
      }

      onFormSubmit(e) {
        e.preventDefault();
        this.props.submitForm(this.state.name);
      }

      render() {
        let errorMsg = (this.props.validationError ? 'Please enter your name.' : null);
        return (
          <form onSubmit={(e) => this.onFormSubmit(e)}>
            <input
              type="text"
              placeholder="Name"
              onChange={this.handleNameChange}
            />
            <p className="error">
              {errorMsg}
            </p>
            <input
              type="submit"
              className="btn"
              value="Submit"
            />
          </form>
          );
      }
    }

I guess this will solve your problem. With this your test should run fine.

The issue has been discussed in this thread already.
And this solution works for me.

  import { mount, shallow } from 'enzyme';
  import InputForm from '../InputForm':
  import React from 'react';
  import { spy } from 'sinon';

  describe('Form', () => {
    it('submit event when click submit', () => {
      const callback = spy();
      const wrapper = mount(<InputForm />);
      wrapper.find('[type="submit"]').get(0).click();
      expect(callback).to.have.been.called();
    });
  });

Its using mocha + chai instead of jest. But you can get an idea of how to do it.

发布评论

评论列表(0)

  1. 暂无评论