web-dev-qa-db-ja.com

酵素シミュレーション送信フォーム、未定義のプロパティ「値」を読み取れません

冗談と酵素を使ってコンポーネントをテストするのに少し苦労しています。私がやりたいのは、名前フィールドに値を指定せずにフォームをテスト送信することです。これにより、コンポーネントがエラーを表示していることを確認できます。ただし、残りを実行すると、コンソールでエラーが発生します。

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,
};

テスト

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

  });
7
j_quelly

経験則として、可能な限りrefの使用を避ける必要があります。なぜですか。 ここ

あなたの場合、より良いアプローチの1つは次のようになることをお勧めします。

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

これで問題は解決すると思います。これにより、テストは正常に実行されます。

2

送信イベントをシミュレートするためにイベントオブジェクトを渡す必要はないと思います。これはうまくいくはずです。

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

  });
4
WitVault

この問題は このスレッド ですでに議論されています。
そして、この解決策は私のために働きます。

  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();
    });
  });

冗談の代わりにモカ+チャイを使用しています。しかし、あなたはそれを行う方法のアイデアを得ることができます。

0
Fakhruddin Abdi