Javascript React测试:React浅层渲染单元测试中的事件处理程序 背景

Javascript React测试:React浅层渲染单元测试中的事件处理程序 背景,javascript,unit-testing,testing,reactjs,mocha.js,Javascript,Unit Testing,Testing,Reactjs,Mocha.js,我正在尝试学习如何使用React-Shallow-Rendering-TestUtil,并让测试通过,直到我将onClick事件处理程序添加到两者;看来我在Accordion.test.js中尝试使用的Accordion.toggle函数与Accordion.js中的这个.toggle函数肯定有一些不同,但我无法理解 问题: 如何让Accordian.test.js中突出显示的两个测试通过 复制步骤 克隆 npm安装 npm运行dev-单击“Lorem Ipsum”时查看组件是否工作 npm运行

我正在尝试学习如何使用React-Shallow-Rendering-TestUtil,并让测试通过,直到我将
onClick
事件处理程序添加到两者;看来我在
Accordion.test.js中尝试使用的
Accordion.toggle
函数与
Accordion.js中的
这个.toggle
函数肯定有一些不同,但我无法理解

问题: 如何让
Accordian.test.js
中突出显示的两个测试通过

复制步骤
  • 克隆
  • npm安装
  • npm运行dev
    -单击“Lorem Ipsum”时查看组件是否工作
  • npm运行测试:观察
    -查看测试是否失败

  • 要测试用户事件,如
    onClick
    ,必须使用
    TestUtils.Simulate。单击

    现在不可能使用ReactTestUtils.Simulate进行浅层渲染,我认为接下来的问题应该是:


    有许多问题阻止您的测试通过

    查看测试“默认情况下应处于非活动状态”:

  • 测试中的
    Accordion.toggle
    Accordion
    类的一个属性,而代码中的
    toggle
    Accordion
    类的一个实例的属性-因此在本例中,您比较了两个不同的东西。要访问测试中的“实例”方法,可以将
    Accordion.toggle
    替换为
    Accordion.prototype.toggle
    。如果没有
    this.toggle=this.toggle.bind(this),它将起作用代码。这就引出了第二点

  • 在函数上调用.bind()时,它会在运行时创建一个新函数,因此无法将其与原始的
    Accordion.prototype.toggle
    进行比较。解决此问题的唯一方法是从渲染结果中拉出“绑定”函数:

    let toggle = result.props.children[0].props.onClick;
    
    assert.deepEqual(result.props.children, [
      <a onClick={toggle}>This is a summary</a>,
      <p style={{display: 'none'}}>This is some details</p>
    ]);
    
    现在应该说:

    global.document = {};
    result.props.children[0].props.onClick();
    
    请参阅“修复损坏的设置状态()”一节和

  • 编写了一个很好的解决方案,用于测试使用浅层渲染的单击处理程序

    给定一个带有
    onClick
    prop的嵌套元素和一个上下文绑定到组件的处理程序:

    render() {
      return (
        <div>
          <a className="link" href="#" onClick={this.handleClick}>
            {this.state.linkText}
          </a>
          <div>extra child to make props.children an array</div>
        </div>
      );
    }
    
    handleClick(e) {
      e.preventDefault();
      this.setState({ linkText: 'clicked' });
    }
    
    import './ButtonIcon.scss';
    
    import React from 'react';
    import classnames from 'classnames';
    
    const ButtonIcon = props => {
      const {icon, onClick, color, text, showText} = props,
        buttonIconContainerClass = classnames('button-icon-container', {
          active: showText
        });
    
      return (
        <div
          className={buttonIconContainerClass}
          onClick={onClick}
          style={{borderColor: color}}>
          <div className={`icon-container ${icon}`}></div>
          <div
            className="text-container"
            style={{display: showText ? '' : 'none'}}>{text}</div>
        </div>
      );
    }
    
    ButtonIcon.propTypes = {
      icon: React.PropTypes.string.isRequired,
      onClick: React.PropTypes.func.isRequired,
      color: React.PropTypes.string,
      text: React.PropTypes.string,
      showText: React.PropTypes.bool
    }
    
    export default ButtonIcon;
    
    <div><ButtonIcon icon={iconMock} onClick={clickSpy} /></div>
    

    我已在无状态组件中成功测试了我的单击。以下是如何:

    我的组成部分:

    render() {
      return (
        <div>
          <a className="link" href="#" onClick={this.handleClick}>
            {this.state.linkText}
          </a>
          <div>extra child to make props.children an array</div>
        </div>
      );
    }
    
    handleClick(e) {
      e.preventDefault();
      this.setState({ linkText: 'clicked' });
    }
    
    import './ButtonIcon.scss';
    
    import React from 'react';
    import classnames from 'classnames';
    
    const ButtonIcon = props => {
      const {icon, onClick, color, text, showText} = props,
        buttonIconContainerClass = classnames('button-icon-container', {
          active: showText
        });
    
      return (
        <div
          className={buttonIconContainerClass}
          onClick={onClick}
          style={{borderColor: color}}>
          <div className={`icon-container ${icon}`}></div>
          <div
            className="text-container"
            style={{display: showText ? '' : 'none'}}>{text}</div>
        </div>
      );
    }
    
    ButtonIcon.propTypes = {
      icon: React.PropTypes.string.isRequired,
      onClick: React.PropTypes.func.isRequired,
      color: React.PropTypes.string,
      text: React.PropTypes.string,
      showText: React.PropTypes.bool
    }
    
    export default ButtonIcon;
    
    <div><ButtonIcon icon={iconMock} onClick={clickSpy} /></div>
    
    import'/ButtonIcon.scss';
    从“React”导入React;
    从“类名称”导入类名称;
    const ButtonIcon=props=>{
    const{icon,onClick,color,text,showText}=props,
    ButtonNiconContainerClass=类名('button-icon-container'{
    活动:showText
    });
    返回(
    {text}
    );
    }
    ButtonIcon.propTypes={
    图标:React.PropTypes.string.isRequired,
    onClick:React.PropTypes.func.isRequired,
    颜色:React.PropTypes.string,
    文本:React.PropTypes.string,
    showText:React.PropTypes.bool
    }
    导出默认按钮;
    
    我的测试:

    it('should call onClick prop when clicked', () => {
      const iconMock = 'test',
        clickSpy = jasmine.createSpy(),
        wrapper = ReactTestUtils.renderIntoDocument(<div><ButtonIcon icon={iconMock} onClick={clickSpy} /></div>);
    
      const component = findDOMNode(wrapper).children[0];
    
      ReactTestUtils.Simulate.click(component);
    
      expect(clickSpy).toHaveBeenCalled();
      expect(component).toBeDefined();
    });
    
    it('单击时应调用onClick prop',()=>{
    const iconMock='test',
    单击Spy=jasmine.createSpy(),
    wrapper=reactestutils.renderIntoDocument();
    const component=findDOMNode(包装器).children[0];
    reactestutils.Simulate.click(组件);
    期望(单击Spy).toHaveBeenCalled();
    expect(component.toBeDefined();
    });
    
    重要的是包装组件:

    render() {
      return (
        <div>
          <a className="link" href="#" onClick={this.handleClick}>
            {this.state.linkText}
          </a>
          <div>extra child to make props.children an array</div>
        </div>
      );
    }
    
    handleClick(e) {
      e.preventDefault();
      this.setState({ linkText: 'clicked' });
    }
    
    import './ButtonIcon.scss';
    
    import React from 'react';
    import classnames from 'classnames';
    
    const ButtonIcon = props => {
      const {icon, onClick, color, text, showText} = props,
        buttonIconContainerClass = classnames('button-icon-container', {
          active: showText
        });
    
      return (
        <div
          className={buttonIconContainerClass}
          onClick={onClick}
          style={{borderColor: color}}>
          <div className={`icon-container ${icon}`}></div>
          <div
            className="text-container"
            style={{display: showText ? '' : 'none'}}>{text}</div>
        </div>
      );
    }
    
    ButtonIcon.propTypes = {
      icon: React.PropTypes.string.isRequired,
      onClick: React.PropTypes.func.isRequired,
      color: React.PropTypes.string,
      text: React.PropTypes.string,
      showText: React.PropTypes.bool
    }
    
    export default ButtonIcon;
    
    <div><ButtonIcon icon={iconMock} onClick={clickSpy} /></div>
    
    
    
    希望能有帮助