How to mock e.preventDefault in react component

2019-04-03 06:40发布

I don't really know how to mock inline function in react component's child

My stack: sinon, chai, enzyme;

Component usage:

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

Component's render:

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

Here we have onClick that calls e.preventDefault(). How to tell for <a href>(link) to not call e.preventDefault()? How can I mock that onClick?

Below what I have try in tests:

Shallow copy setup

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'),
  }
}

And the test

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

Test's output error:

TypeError: Cannot read property 'preventDefault' of undefined

5条回答
一夜七次
2楼-- · 2019-04-03 07:10

Just to note that this is an issue only when using shallow enzyme renderer. In case of full DOM renderer mount, the event object contains the preventDefault method, therefore you don't have to mock it.

查看更多
对你真心纯属浪费
3楼-- · 2019-04-03 07:16

Try this

link.simulate('click', {
  preventDefault: () => {
  }
 });
查看更多
一夜七次
4楼-- · 2019-04-03 07:20

For those using Jest and react-testing-librarys fireEvent, you need to provide an initialised event object, otherwise the event can't be dispatched via your element.

One can then assert on e.preventDefault being called by assigning a property to that initialised event:

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(event.preventDefault).toHaveBeenCalledTimes(1);
});

Similarly for stopPropagation.

Anton Karpenko's answer for Jest was useful.

查看更多
不美不萌又怎样
5楼-- · 2019-04-03 07:25
 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();
  });
查看更多
趁早两清
6楼-- · 2019-04-03 07:28

I would suggest to create new object based on jest.fn() with

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

then use it:

element.simulate('click', event);
查看更多
登录 后发表回答