web-dev-qa-db-ja.com

React with Enzymeで子コンポーネントコールバックによって呼び出されるコンポーネントコールバックをテストする方法は?

次のアプリケーションがあるとします。

class Child extends React.Component {
    render() {
        return <button onClick={this.handleChildOnClick}>{this.props.children}</button>;
    }

    handleChildOnClick() {
        this.props.onChildClick('foo');
    }
}

class Parent extends React.Component {
    render() {
        return <Child onChildClick={this.handleParentOnClick}>click me</Child>;
    }

    handleParentOnClick(text) {
        this.props.onParentClick(12345);
    }
}

class App extends React.Component {
    render() {
        return <Parent onParentClick={(num) => console.log(num)} />;
    }
}

Parentコンポーネントをテストする適切な方法を見つけるのに苦労しています。 ChildAppは問題ありませんが、Parent .. ..

つまり、Childコンポーネントをクリックすると、次のことなしにParentクリックコールバックが呼び出されることをテストするにはどうすればよいですか。

  1. ...レンダリングChildParentは、浅いレンダリングとして単独でテストする必要があります。 Childも個別にテストされ、マウントレンダリングを実行する場合、基本的にChildのクリックコールバックを2回テストします。
  2. ... handleParentOnClickインスタンスでParentを直接呼び出します。これについては、Parentの正確な実装に依存するべきではありません。コールバック関数の名前を変更すると、テストが失敗し、誤検知になる可能性があります。

3番目のオプションはありますか?

11
rfgamaral

Parentのテスト中に、次のことができます。

import { shallow } from 'enzyme';
import { stub } from 'sinon';

describe('<Parent/>', () => {
  it('should handle a child click', () => {
    const onParentClick = stub();
    const wrapper = shallow(<Parent onParentClick={onParentClick} />);
    wrapper.find("Child").prop('onChildClick')('foo');
    expect(onParentClick.callCount).to.be.equal(1);
    // You can also check if the 'foo' argument was passed to onParentClick
  });
});
14

これはあなたにいくつかのアイデアを与えることができると思います。

//コンポーネント

class Child extends React.Component {
  render() {
    return <button onClick={this.handleChildOnClick} className="t-btn">{this.props.children}</button>;
  }
  handleChildOnClick() {
    this.props.onChildClick('foo');
  }
}

//テスト

import { spy, stub } from 'sinon';
import { shallow } from 'enzyme';

describe('Child Component', () => {
  it('should check handle click', () => {
    spy(Child.prototype, 'handleChildOnClick');
    const onChildClick = stub();
    const wrapper = shallow(<Child onChildClick={onChildClick}>);
    wrapper.find(".t-btn").simulate('click');
    expect(Child.prototype.handleChildOnClick.callCount).to.equal(1);
  });

  it('should check onChildClick', () => {
    const onChildClick = stub();
    const wrapper = shallow(<Child onChildClick={onChildClick}>);
    wrapper.find(".t-btn").simulate('click');
    expect(onChildClick.callCount).to.equal(1);
  });
});

親と子コンポーネントをテストするには

import { stub } from 'sinon';
import { shallow } from 'enzyme';
import Child from '../Components/Child';

describe('Parent Component', () => {
  it('should check handle click', () => {
    const onParentClick = stub();
    const wrapper = shallow(<Parent onParentClick={onParentClick} />);
    wrapper.find(".t-btn").simulate('click');
    expect(Child.prototype.handleChildOnClick.callCount).to.equal(1);
  });

  it('should check onChildClick', () => {
    const onChildClick = stub();
    const wrapper = shallow(<Child onChildClick={onChildClick}>);
    wrapper.find(Child).prop('onChildClick')('foo');
    expect(onParentClick.callCount).to.be.equal(1);
  });
});

上記のコードは1つのコンポーネントのみを処理しますが、これで要点がわかると思います。構文がどこかで壊れている場合は申し訳ありません。

0
anoop