Протестируйте форму с помощью Jest и React JS TestUtils

У меня есть форма с тремя переключателями вроде следующих (поддельные имена):

<form className="myForm" onSubmit={this.done}>
  <input className="myRadio" checked={ŧrue} type="radio" name="myRadio" onChange={this.change} value="value1"
  <input className="myRadio" type="radio" name="myRadio" onChange={this.change} value="value2"
  <input className="myRadio" type="radio" name="myRadio" onChange={this.change} value="value3"
<input type="submit" className="submit" />
</form>

И мне очень тяжело пытаться проверить события onChange и onSubmit.

inputs = TestUtils.scryRenderedDOMComponentsWithClass(MyComponentRendered, 'myRadio');
myForm = TestUtils.findRenderedDOMComponentWithClass(MyComponentRendered, 'myForm');

У меня есть тест вроде:

it("changes the checked state when clicked", function() {
  MyComponent.change = jest.genMockFunction();

  expect(inputs[0].getDOMNode().checked).toBe(true);
  TestUtils.Simulate.change(inputs[1], {target: {value: 'value2'}});
  expect(inputs[0].getDOMNode().checked).toBe(false);
  expect(inputs[1].getDOMNode().checked).toBe(true);
  expect(inputs[2].getDOMNode().checked).toBe(false);

  expect(MyComponent.change).toBeCalled(); //Fails
  expect(MyComponent.change.mock.calls.length).toBe(1); //Fails too
});

Это работает, кроме функции (MyComponent.change), которая должна быть вызвана, но это не так.

У меня также есть один тест для onSubmit:

it("saves on submit", function()
  MyComponent.done = jest.genMockFunction();
  MyComponent.insideDone = jest.genMockFunction();
  TestUtils.Simulate.submit(myForm);
  expect(MyComponent.done).toBeCalled(); //Fails
  expect(MyComponent.insideDone).toBeCalled(); //Success
});

Примечание: MyComponent.insideDone - это функция, которая вызывается функцией "done".

Что тоже не получается. Я уверен, что проблема в том, что я не правильно имитирую события. Тем не менее, я не нашел примера этого, используя Jest и TestUtils из React.

Ответ 1

Проблема заключается в том, что вы заменяете функцию после того, как вы уже дали исходную функцию React. Выражение onSubmit={this.done} является этой функцией и устанавливается как обработчик события. После завершения функции рендеринга вы заменяете instance.done, но React уже получил старую функцию. Вместо этого вы должны сделать следующее:

<form className="myForm" onSubmit={() => this.done()}>

Это гарантирует, что обработчик события всегда вызывает метод экземпляра (тот, который вы заменили). Это имеет хороший побочный эффект от будущей совместимости с React, поскольку они прекратят автоматическое связывание всех методов с экземпляром.