web-dev-qa-db-ja.com

React、ユニットテスト用のユーザー入力をシミュレートする方法は?

私はユーザー入力を取り込むreactコンポーネントをユニットテストしようとしています。具体的には、reactコンポーネント内のonChange関数をテストしようとしています。しかし、入力値を設定できないようです。インターネットで提案されているいくつかの異なる方法を試しましたが、どれも機能していないようです。以下は、私がテストしようとしているコンポーネントです。

class Input extends Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    /* Check if max length has been set. If max length has been
    set make sure the user input is less than max Length, otherwise
    return before updating the text string. */
    if(this.props.maxLength) {
      if(event.target.value.length > this.props.maxLength) {
        return;
      }
    }
    this.setState({ value: event.target.value });
  }

  render () {
    const { disabled, label, maxLength, multiline, type, value, ...others} = this.props;
    const theme = themeable(others.theme);

    let inputClassName = classNames({
      "input": type !== 'checkbox',
      "checkbox": type == 'checkbox',
      disabled,
      multiline,
      value,
      [`${this.props.className}`]: !!this.props.className
    });

    return (
      <div {...theme(1, 'container')}>
        {this.props.label ? <label htmlFor={this.props.htmlFor} {...theme(2, 'label')}>{label}</label> : null}
          <input value={this.state.value} {...theme(3, ...inputClassName)} onChange={this.handleChange} type={type} />
      </div>
    );
  }
}

私はこの問題を見つけました: https://github.com/airbnb/enzyme/issues/76 そして下に向かって提案を試みました、私は未定義または空白の文字列を取得し続けます。私は酵素のシミュレートされた変化を使用するというレビブゾリックの提案を試しました。これは以下に見ることができます。ただし、これはAssertionError: expected '' to equal 'abcdefghij'を返すだけです。

it('Make sure inputted text is shorter than max length', function() {
    const result = mount(<Input maxLength={10}></Input>);
    result.find('input').simulate('change', {target: {value: 'abcdefghijk'}});
    expect(result.state().value).to.equal("abcdefghij");
});

それから私はまた下にあるtakkyuuplayerの提案を試みました。これもAssertionError: expected '' to equal 'abcdefghij'で失敗します

  it('Make sure inputted text is shorter than max length', function() {
    const result = mount(<Input maxLength={10}></Input>);
    result.find('input').node.value = 'abcdefghijk';
    expect(result.state().value).to.equal("abcdefghij");
  });

私はこの記事を見つけました: https://medium.com/javascript-inside/testing-in-react-getting-off-the-ground-5f569f3088a#.f4gcjbaak そして彼らのやり方を試しましたが失敗しました。

  it('Make sure inputted text is shorter than max length', function() {
    const result = mount(<Input maxLength={10}></Input>);
    let input = result.find('input');
    input.get(0).value = 'abcdefghijk';
    input.simulate('change');
    expect(result.state().value).to.equal("abcdefghij");
  });

最後に、 reactJs TestUtilsを使用したテキスト入力のシミュレーション で提案されているようにreact test utilsを使用してみました。以下は試したコードですが、エラーメッセージが表示されて失敗しました:TypeError: Cannot read property '__reactInternalInstance$z78dboxwwtrznrmuut6wjc3di' of undefined

  it('Make sure inputted text is shorter than max length', function() {
    const result = mount(<Input maxLength={10}></Input>);
    let input = result.find('input');
    TestUtils.Simulate.change(input, { target: { value: 'abcdefghijk' } });
    expect(result.state().value).to.equal("abcdefghij");
  });

では、ユーザーがonChange関数をテストできるように、ユーザー入力をどのようにシミュレートするのでしょうか。

6
2trill2spill

入力コンポーネントにバグがあるようです。いつ event.target.value.length > this.props.maxLength実際の状態を設定することはなく、state.value なので ''。値に設定されていると予想していたようですが、maxLengthに切り捨てられています。自分で追加する必要があります。

handleChange(event) {
  /* Check if max length has been set. If max length has been
  set make sure the user input is less than max Length, otherwise
  return before updating the text string. */
  if (this.props.maxLength) {
    if (event.target.value.length > this.props.maxLength) {
      // ** Truncate value to maxLength
      this.setState({ value: event.target.value.substr(0, this.props.maxLength) });
      return;
    }
  }
  this.setState({ value: event.target.value });
}

...その後、次のテストが機能し、合格します。

it('Make sure inputted text is shorter than max length', () => {
  const result = mount(<Input maxLength={10}></Input>);
  result.find('input').simulate('change', { target: { value: '1234567890!!!' } });
  expect(result.state().value).to.equal("1234567890");
});
10
Jeff McCloud

これを試して:

component = shallow(<Input value={'100.00'} />);


it('The component should display new value on the user input', () => {
        component.find(Input).simulate('change', { target: { value: '200.00' } });
        const input = component.find(Input);
        expect(input.prop('value')).not.toBe('100.00');
        expect(input.prop('value')).toBe('200.00');
      });
0