Флажок не установлен после имитации «изменения» с помощью фермента

Я попытался использовать фермент для имитации события change для флажка и использовать chai-enzyme, чтобы подтвердить, было ли оно проверено.

Это мой компонент реакции Hello:

import React from 'react';

class Hello extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      checked: false
    }
  }

  render() {
    const {checked} = this.state;
    return <div>
      <input type="checkbox" defaultChecked={checked} onChange={this._toggle.bind(this)}/>
      {
        checked ? "checked" : "not checked"
      }
    </div>
  }

  _toggle() {
    const {onToggle} = this.props;
    this.setState({checked: !this.state.checked});
    onToggle();
  }
}

export default Hello;

И мой тест:

import React from "react";
import Hello from "../src/hello.jsx";
import chai from "chai";
import {mount} from "enzyme";
import chaiEnzyme from "chai-enzyme";
import jsdomGlobal from "jsdom-global";
import spies  from 'chai-spies';

function myAwesomeDebug(wrapper) {
  let html = wrapper.html();
  console.log(html);
  return html
}

jsdomGlobal();
chai.should();
chai.use(spies);
chai.use(chaiEnzyme(myAwesomeDebug));


describe('<Hello />', () => {

  it('checks the checkbox', () => {
    const onToggle = chai.spy();
    const wrapper = mount(<Hello onToggle={onToggle}/>);

    var checkbox = wrapper.find('input');
    checkbox.should.not.be.checked();
    checkbox.simulate('change', {target: {checked: true}});
    onToggle.should.have.been.called.once();

    console.log(checkbox.get(0).checked);
    checkbox.should.be.checked();
  });

});

Когда я запускаю этот тест, checkbox.get(0).checked равно false, а утверждение checkbox.should.be.checked() сообщает об ошибке:

AssertionError: expected the node in <Hello /> to be checked <input type="checkbox" checked="checked">

Вы можете видеть, что сообщение довольно странное, так как в выводе уже есть checked="checked".

Я не уверен, где не так, так как это включает в себя слишком много вещей.

Вы также можете увидеть демонстрационный проект здесь: https://github.com/js-demos/react-enzyme-simulate-checkbox-events-demo, обратите внимание на эти строки


person Freewind    schedule 06.10.2016    source источник


Ответы (3)


Я думаю, что некоторые детали моего объяснения могут быть немного неправильными, но мое понимание таково:

Когда вы делаете

var checkbox = wrapper.find('input');

Он сохраняет ссылку на этот узел Enzyme в checkbox, но бывают случаи, когда дерево Enzyme обновляется, а checkbox — нет. Я не знаю, связано ли это с тем, что ссылка в дереве изменилась, и поэтому checkbox теперь является ссылкой на узел в старой версии дерева.

Мне кажется, что функция checkbox работает, потому что теперь значение checkbox() всегда берется из самого современного дерева.

var checkbox = () => wrapper.find('input');
checkbox().should.not.be.checked();
checkbox().simulate('change', {target: {checked: true}});
///...
person rogeliog    schedule 09.12.2016

Это не баг, а "работает как задумано".

Базовый фермент использует утилиты тестирования реакции для взаимодействия с реакцией, особенно с симуляцией API.

Simulate на самом деле не обновляет dom, он просто запускает обработчики событий реакции, прикрепленные к компоненту, возможно, с дополнительными параметрами, которые вы передаете.

Согласно ответу, который я получил здесь (https://github.com/facebook/react/issues/4950 ) это связано с тем, что обновление dom потребует от React повторной реализации многих функций браузера, что, вероятно, все равно приведет к непредвиденному поведению, поэтому они решили просто полагаться на браузер для выполнения обновления.

Единственный способ проверить это — вручную обновить dom самостоятельно, а затем вызвать API-интерфейс имитации.

person mastrolindus    schedule 24.10.2016

Ниже решение лучше всего сработало для меня:

it('should check checkbox handleClick event on Child component under Parent', () => {
const handleClick = jest.fn();
const wrapper = mount(
<Parent onChange={handleClick} {...dependencies}/>,); // dependencies, if any
checked = false;
wrapper.setProps({ checked: false });
const viewChildren = wrapper.find(Children);
const checkbox = viewChildren.find('input[type="checkbox"]').first(); // If you've multiple checkbox nodes and want to select first
checkbox.simulate('change', { target: { checked: true } });
expect(handleClick).toHaveBeenCalled();
});

Надеюсь это поможет.

person sid7747    schedule 29.05.2020