21

我尝试使用酶来模拟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).checkedisfalse和断言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 ,注意这些行

4

4 回答 4

25

我认为我的解释的一些细节可能有点错误,但我的理解是:

当你这样做

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}});
///...
于 2016-12-09T19:02:03.710 回答
7

这不是错误,而是“它按设计工作”。

Enzyme 底层使用 react 测试工具与 react 交互,尤其是与模拟 api 交互。

Simulate 实际上并没有更新 dom,它只是触发附加到组件的 react 事件处理程序,可能带有您传入的其他参数。

根据我在这里得到的答案(https://github.com/facebook/react/issues/4950),这是因为更新 dom 需要 React 重新实现很多浏览器功能,可能仍然会导致无法预料的行为,所以他们决定仅依靠浏览器进行更新。

实际测试这一点的唯一方法是自己手动更新 dom,然后调用模拟 api。

于 2016-10-24T07:12:38.723 回答
1

以下解决方案最适合我:

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

希望这可以帮助。

于 2020-05-29T07:46:54.020 回答
0

这对我有用:

wrapper.find(CCToggle)
       .find('input[type="checkbox"]')
       .simulate('change', { target: { checked: true } })

CCToggle是我的组件。

于 2021-11-05T20:12:22.620 回答