酶模拟提交表单,无法读取未定义的属性"值"

j_q*_*lly 7 javascript reactjs jestjs enzyme

我在使用jest和酶测试组件时遇到了一些困难.我想要做的是测试在名称字段中提交没有值的表单.这将确保组件显示错误.但是,当我运行其余的时,我在控制台中收到错误:

TypeError:无法读取未定义的属性"value"

我对前端测试和一般测试都很陌生.所以,我不完全确定我正在使用酶进行这种类型的测试.我不知道我的测试是否不正确,或者我是否刚编写了一个不易测试的组件.我愿意改变我的组件,如果这样可以更容易测试吗?

零件

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

  onFormSubmit(e) {
    e.preventDefault();
    // this is where the error comes 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,
};
Run Code Online (Sandbox Code Playgroud)

测试

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

  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.');
    });

  });
Run Code Online (Sandbox Code Playgroud)

Wit*_*ult 6

我认为您不需要传递事件对象来模拟提交事件。这应该有效。

  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.');
    });

  });
Run Code Online (Sandbox Code Playgroud)

  • 我相信我必须传递事件对象,否则我会收到一个错误 ```TypeError: Cannot read property 'preventDefault' of undefined```。http://airbnb.io/enzyme/docs/api/ShallowWrapper/simulate.html 当酶模拟提交表单时,它调用 ```onFormSubmit``` 方法,该方法又调用事件对象 ```preventDefault```方法。如果不传递空白的 ```preventDefault``` 方法,测试将抛出错误。检查 ```inputForm``` 类以更好地理解。 (3认同)

小智 2

根据经验,您应该尽可能避免使用 refs,为什么?这里

对于您的情况,我建议更好的方法之一可能是:

  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>
          );
      }
    }
Run Code Online (Sandbox Code Playgroud)

我想这会解决你的问题。这样你的测试应该可以正常运行。