web-dev-qa-db-ja.com

React要素のクリックをシミュレートするテストレンダラー

Jest v16.0.1、react-test-renderer v15.4.0、react-addons-test-utils v15.4.0を使用してReactコンポーネントをテストしています。

コンポーネントはボタンをレンダリングしました:

<button
    type="button"
    className="btn btn-lg btn-primary btn-danger"
    disabled={this.state.cancelButtonDisabled}
    onClick={() => this.handleCancel()}
    ref="cancelButton"
>Cancel</button>);

そして私のテストでは、コンポーネントを次のようにレンダリングしています:

const component = renderer.create(
    <MyComponent />
);

const instance = component.getInstance();
// This works but is ugly
component.toJSON().children[1].children[0].props.onClick();
// This doesn't work
ReactTestUtils.Simulate.click(instance.refs.cancelButton);

let tree = component.toJSON();
expect(tree).toMatchSnapshot();

このボタンのクリックをシミュレートするための推奨される方法は何ですか?コンポーネントのJSON表現をトラバースすることはできますが、それらはより良い方法であるように思われます。

以前は、ReactTestUtils.renderIntoDocumentを使用していたときに、refを使用してコンポーネントへの参照をReactTestUtils.Simulate.clickに渡すことができました。

私はこの質問を見ました- ReactTestRenderer/Jestによってレンダリングされたコンポーネントを操作する方法 しかし、私のコンポーネントインスタンスにはfind()メソッドがないため、APIが変更されたと思います。

16
Aaron Kalair

解決策を見つけました。反応を使用しているので、onClickハンドラー関数が小道具の一部としてボタンに渡されると想定しています。したがって、ボタンの小道具を介してそれにアクセスできます。

component.root.findByType('button').props.onClick();

または、複数のボタンがある場合、これを行うことができます:

component.root.findByProps({className="btn btn-lg btn-primary btn-danger"}).props.onClick();
10
Bohan Liu

遅すぎるかもしれませんが、findは酵素のAPIです。あなたが想定酵素について言及した質問に対する回答は、コメントに記載されているとおりに使用されます。

このようなものが動作するはずです。

MyComponent.jsx

import React from 'react';

class MyComponent extends React.Component {
  constructor() {
    super();
    this.state = {
      cancelButtonDisabled: false,
    };
  }
  handleCancel() {
    this.props.cancelAction();
  }
  render() {
    return (
      <button
        type="button"
        className="btn btn-lg btn-primary btn-danger"
        disabled={this.state.cancelButtonDisabled}
        onClick={() => this.handleCancel()}
        ref="cancelButton"
      >
        Cancel
      </button>
    );
  }
}

export default MyComponent;

MyComponent.test.jsx

import React from 'react';
import {mount} from 'enzyme';
import MyComponent from './MyComponent';

describe('Test MyComponent', () => {
  it('should be able to click the button', () => {
    const mockFunction = jest.fn();
    const element = mount(<MyComponent cancelAction={mockFunction} />);
    element.find('button').simulate('click');
    expect(mockFunction).toHaveBeenCalled();
  });
});

酵素がなければ、このようになります。

MyComponentWithoutEnzyme.test.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import ReactTestUtils from 'react-addons-test-utils';
import MyComponent from './MyComponent';

describe('Test MyComponent', () => {
  it('should be able to click the button', () => {
    const mockFunction = jest.fn();
    const element = ReactTestUtils.renderIntoDocument(
      <MyComponent cancelAction={mockFunction} />,
    );
    const button = ReactDOM.findDOMNode(element);
    ReactTestUtils.Simulate.click(button);
    expect(mockFunction).toHaveBeenCalled();
  });
});
3
daiki