如何在反应组件的孩子中模拟 e.preventDefault

Posted

技术标签:

【中文标题】如何在反应组件的孩子中模拟 e.preventDefault【英文标题】:How to mock e.preventDefault in react component's child 【发布时间】:2017-06-09 07:37:23 【问题描述】:

嘿,我不知道如何在 React 组件的子组件中模拟内联函数

我的堆栈:sinonchaienzyme

组件使用:

<ListItem onClick=() => someFn() />

组件的渲染:

render() 
    return (
      <li>
        <a href="#" onClick=e => 
            e.preventDefault();
            this.props.onClick();
          
        > whatever </a>
      </li>
    );
  

这里我们有调用e.preventDefault()onClick 函数。如何告诉&lt;a href&gt;(link) 不要打电话给e.preventDefault()?如何模拟onClick

以下是我在测试中尝试过的:

浅拷贝设置

function setup() 
  const someFn = sinon.stub();

  const component = shallow(
    <ListItem
      onClick=() => 
        someFn();
      
    />
  );

  return 
    component: component,
    actions: someFn,
    link: component.find('a'),
    listItem: component.find('li'),
  

还有测试

  it('simulates click events', () => 
    const  link, actions  = setup();
    link.simulate('click'); //Click on <a href>
    expect(actions).to.have.property('callCount', 1); //will be fine if we remove e.preventDefault()
  );

测试的输出错误:

TypeError: Cannot read property 'preventDefault' of undefined

【问题讨论】:

【参考方案1】:

对于那些使用 Jest 和 @testing-libraryreact-testing-librarys fireEvent 的人,您需要提供一个初始化的事件对象,否则无法通过您的元素调度事件。

然后可以通过将属性分配给该初始化事件来断言 e.preventDefault 被调用:

test('prevents default on click', () => 
  const getByText = render(<MyComponent />);
  const button = getByText(/click me/);

  // initialise an event, and assign your own preventDefault
  const clickEvent = new MouseEvent('click');
  Object.assign(clickEvent, preventDefault: jest.fn());

  fireEvent(button, clickEvent);

  expect(clickEvent.preventDefault).toHaveBeenCalledTimes(1);
);

stopPropagation 也是如此。

Anton Karpenko's answer for Jest 很有用。

【讨论】:

最后一行正确吗? event.preventDefaultexpect 怎么知道event 的上下文? @sidonaldson 感谢您接受这一点 - 修复了示例以引用 clickEvent【参考方案2】:

我正在使用 Web 组件,这对我有用 -

  const callback = jest.fn();
  MouseEvent.prototype.stopPropagation = callback;
  const element = createElement();
  element.shadowRoot.querySelector('ul').click();
  expect(callback).toHaveBeenCalledTimes(1);

【讨论】:

【参考方案3】:

您可以通过一些测试工具定义具有您将模拟的功能的对象,例如查看JestEnzyme

describe('Form component', () => 
  test('deos not reload page after submition', () => 
    const wrapper = shallow(<TodosForm />)
    // an object with some function
    const event =  preventDefault: () =>  
    // mocks for this function
    jest.spyOn(event, 'preventDefault')
    wrapper.find('form').simulate('submit', event)
    // how would you know that function is called
    expect(event.preventDefault).toBeCalled()
  )
)

【讨论】:

【参考方案4】:

我建议使用 jest.fn() 创建新对象

const event = Object.assign(jest.fn(), preventDefault: () => )

然后使用它:

element.simulate('click', event);

【讨论】:

【参考方案5】:

请注意,仅在使用shallow 酶渲染器时才会出现此问题。对于完整的 DOM 渲染器mount,事件对象包含preventDefault 方法,因此您不必模拟它。

【讨论】:

【参考方案6】:
 test('simulates click events', () => 
    const e =  stopPropagation: jest.fn() ;
    const component = shallow(<ListItem...props />);
    const li = component.find('li').at(0).childAt(0)
    li.props().onClick(e)

    expect();
  );

【讨论】:

【参考方案7】:

试试这个

link.simulate('click', 
  preventDefault: () => 
  
 );

【讨论】:

我有调用方法,这对我不起作用

以上是关于如何在反应组件的孩子中模拟 e.preventDefault的主要内容,如果未能解决你的问题,请参考以下文章

反应:你怎么能设置一个嵌套的孩子的状态

如何在本机反应中模拟上下文消费者反应元素

反应:警告列表中的每个孩子都应该有一个唯一的键[重复]

反应我必须重新渲染父母才能重新渲染孩子吗?

反应孩子与父母的沟通问题

如何将两个孩子喂给 React 组件并使用值?