Как проверить компонент обратного вызова вызывается дочерний компонент обратного вызова в реакцию с ферментом?


Скажем, у меня есть следующее приложение:

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. Child и App один-это не проблема, а Parent...

Я имею в виду, как проверить, что щелчок по компоненту Child вызовет обратный вызов Parent Без:

  1. ...рендеринг Child. Parent должен быть испытан изолированно как неглубокий рендер. Child также будет проверяться изолированно, и если я сделаю рендер монтирования, Я в основном тестирую обратный вызов щелчка на Child дважды.
  2. ...прямой вызов handleParentOnClick в экземпляре Parent. Я не должен зависеть от точной реализации Parent для этого. Если я изменю имя функции обратного вызова, тест будет прерван,и это вполне может быть ложноположительным.

Есть ли третий вариант?

2 8

2 ответа:

Во время тестирования 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
  });
});

Я думаю, что это может дать вам некоторое представление.

/ / компонент

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

Выше код просто обрабатывает только один компонент, но я надеюсь, что это может дать вам некоторую суть. Извините, если синтаксис где-то ломается..