Квадратчето за отметка не е „отметнато“ след симулиране на „промяна“ с ензим

Опитах се да използвам ензим, за да симулирам 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');

Той запазва препратка към този ензимен възел в checkbox, но има моменти, когато дървото на ензима се актуализира, но 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.

Симулацията всъщност не актуализира 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