Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 单元测试在组件外部进行_Javascript_Unit Testing_Reactjs_Jestjs_Enzyme - Fatal编程技术网

Javascript 单元测试在组件外部进行

Javascript 单元测试在组件外部进行,javascript,unit-testing,reactjs,jestjs,enzyme,Javascript,Unit Testing,Reactjs,Jestjs,Enzyme,使用“中的代码”解决在零部件外部单击的问题: componentDidMount() { document.addEventListener('mousedown', this.handleClickOutside); } componentWillUnmount() { document.removeEventListener('mousedown', this.handleClickOutside); } setWrapperRef(node) { this.wr

使用“中的代码”解决在零部件外部单击的问题:

componentDidMount() {
    document.addEventListener('mousedown', this.handleClickOutside);
}

componentWillUnmount() {
    document.removeEventListener('mousedown', this.handleClickOutside);
}

setWrapperRef(node) {
    this.wrapperRef = node;
}

handleClickOutside(event) {
    if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
        this.props.actions.something() // Eg. closes modal
    }
}
我不知道如何对不愉快的路径进行单元测试,以使警报不运行,目前为止我得到了什么:

it('Handles click outside of component', () => {
  props = {
    actions: {
      something: jest.fn(),
    }
  }
  const wrapper = mount(
    <Component {... props} />,
  )
  expect(props.actions.something.mock.calls.length).toBe(0)

  // Happy path should trigger mock

  wrapper.instance().handleClick({
    target: 'outside',
  })

  expect(props.actions.something.mock.calls.length).toBe(1)  //true

  // Unhappy path should not trigger mock here ???

  expect(props.actions.something.mock.calls.length).toBe(1)
})
it('Handles click out of component',()=>{
道具={
行动:{
某物:jest.fn(),
}
}
常量包装器=装入(
,
)
expect(props.actions.something.mock.calls.length).toBe(0)
//快乐之路应该引发嘲笑
wrapper.instance().handleClick({
目标:“外部”,
})
expect(props.actions.something.mock.calls.length).toBe(1)//true
//不愉快的路径不应该在这里触发mock???
expect(道具、动作、某物、模拟、呼叫、长度)toBe(1)
})
我试过:

  • 通过
    wrapper.html()发送
  • .find
    调用节点并发送(不模拟
    事件。目标
  • .simulate
    ing
    单击内部元素上的
    (不触发事件侦听器)

我确信我遗漏了一些小的东西,但我在任何地方都找不到这样的例子。

使用
sinon
跟踪
handleclickout
是否被调用。顺便说一下,我刚刚发布了我们的项目,需要在
Nav
组件中进行单元测试。实际上,当您单击外部时,所有子菜单都应该关闭

import sinon from 'sinon';
import Component from '../src/Component';

it('handle clicking outside', () => {
     const handleClickOutside = sinon.spy(Component.prototype, 'handleClickOutside');
     const wrapper = mount(
         <div> 
           <Component {... props} />
           <div><a class="any-element-outside">Anylink</a></div>
         </div>
      ); 

      wrapper.find('.any-element-outside').last().simulate('click'); 
      expect(handleClickOutside.called).toBeTruthy(); 
      handleClickOutside.restore(); 
})
从“sinon”导入sinon;
从“../src/Component”导入组件;
它('点击外部的手柄',()=>{
const handleClickOutside=sinon.spy(Component.prototype,'handleClickOutside');
常量包装器=装入(
任意链接
); 
find('.any element out').last().simulate('click');
expect(handleClickOutside.called).toBeTruthy();
handleClickOutside.restore();
})
从“酶”导入{mount}
从“React”导入React
从“react dom”导入react dom
它('在组件内部单击时不应调用操作',()=>{
常量映射={}
document.addEventListener=jest.fn((事件,cb)=>{
映射[事件]=cb
})
常量道具={
行动:{
某物:jest.fn(),
}
}
const wrapper=mount()
穆斯敦地图({
目标:ReactDOM.findDOMNode(wrapper.instance()),
})
expect(props.actions.something).not.toHaveBeenCalled()
})

github上酶问题的解决方案。

所选答案未涵盖
handleClickOutside的else路径

我在ref元素上添加了mousedown事件,以触发
handleClickOutside

从“酶”导入{mount}
从“React”导入React
从“react dom”导入react dom
它('在组件内部单击时不应调用操作',()=>{
常量映射={}
document.addEventListener=jest.fn((事件,cb)=>{
映射[事件]=cb
})
常量道具={
行动:{
某物:jest.fn(),
}
}
//测试手柄的路径是否在外侧
const wrapper=mount()
穆斯敦地图({
目标:ReactDOM.findDOMNode(wrapper.instance()),
})
//handleClickOutside的测试路径
常量refWrapper=mount()
穆斯敦地图({
目标:ReactDOM.findDOMNode(refWrapper.instance()),
})
expect(props.actions.something).not.toHaveBeenCalled()
})

我发现可以避免使用
ReactDOM.findDOMNode
的情况/解决方案。处理以下示例:

import React from 'react';
import { shallow } from 'enzyme';

const initFireEvent = () => {
  const map = {};

  document.addEventListener = jest.fn((event, cb) => {
    map[event] = cb;
  });

  document.removeEventListener = jest.fn(event => {
    delete map[event];
  });

  return map;
};

describe('<ClickOutside />', () => {
  const fireEvent = initFireEvent();
  const children = <button type="button">Content</button>;

  it('should call actions.something() when clicking outside', () => {
    const props = {
      actions: {
       something: jest.fn(),
     }
    };

    const onClick = jest.fn();

    mount(<ClickOutside {...props}>{children}</ClickOutside>);
    fireEvent.mousedown({ target: document.body });

    expect(props.actions.something).toHaveBeenCalledTimes(1);
  });

  it('should NOT call actions.something() when clicking inside', () => {
    const props = {
      actions: {
       something: jest.fn(),
     }
    };

    const wrapper = mount(
      <ClickOutside onClick={onClick}>{children}</ClickOutside>,
    );

    fireEvent.mousedown({
      target: wrapper.find('button').instance(),
    });

    expect(props.actions.something).not.toHaveBeenCalled();
  });
});

最简单的事情就是在身体上发送事件

mount();

window.document.body.dispatchEvent(新事件('click'))
据我所知,此测试已调用
handleClickOutside
,但不测试它是否包含在
wrapperRef
中的if条件?这不起作用。它的编写方式是在组件内部查找存在于组件外部的类。我想你可以导入一个在视图中的组件,该组件位于组件外部,以测试点击,但感觉应该有更好的方法。您可能希望尝试更改“外部单击”检测逻辑,以处理组件的某个根元素上的onBlur事件:虽然选择的答案是正确的,但我最终将此逻辑卸载到react onclickoutside库-是否问到相反的问题?在单元测试中,如何检测组件外部的点击?我认为只要将目标更改为类似于
document.body
的内容就可以完成这个答案。
import React from 'react';
import { shallow } from 'enzyme';

const initFireEvent = () => {
  const map = {};

  document.addEventListener = jest.fn((event, cb) => {
    map[event] = cb;
  });

  document.removeEventListener = jest.fn(event => {
    delete map[event];
  });

  return map;
};

describe('<ClickOutside />', () => {
  const fireEvent = initFireEvent();
  const children = <button type="button">Content</button>;

  it('should call actions.something() when clicking outside', () => {
    const props = {
      actions: {
       something: jest.fn(),
     }
    };

    const onClick = jest.fn();

    mount(<ClickOutside {...props}>{children}</ClickOutside>);
    fireEvent.mousedown({ target: document.body });

    expect(props.actions.something).toHaveBeenCalledTimes(1);
  });

  it('should NOT call actions.something() when clicking inside', () => {
    const props = {
      actions: {
       something: jest.fn(),
     }
    };

    const wrapper = mount(
      <ClickOutside onClick={onClick}>{children}</ClickOutside>,
    );

    fireEvent.mousedown({
      target: wrapper.find('button').instance(),
    });

    expect(props.actions.something).not.toHaveBeenCalled();
  });
});
"react": "^16.8.6",
"jest": "^25.1.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2"