How to mock e.preventDefault in react component's child

Unit TestingReactjsmocha.jsSinonEnzyme

Unit Testing Problem Overview


Hy, I don't know how to mock an 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 function that calls e.preventDefault(). How to tell to <a href>(link) to not to call e.preventDefault()? How can I mock an onClick?

Below is what I have tried 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); //will be fine if we remove e.preventDefault()
  });

Test's output error:

TypeError: Cannot read property 'preventDefault' of undefined

Unit Testing Solutions


Solution 1 - Unit Testing

Try this

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

Solution 2 - Unit Testing

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

Solution 3 - Unit Testing

For those using Jest and @testing-library or 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(clickEvent.preventDefault).toHaveBeenCalledTimes(1);
});

Similarly for stopPropagation.

Anton Karpenko's answer for Jest was useful.

Solution 4 - Unit Testing

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.

Solution 5 - Unit Testing

You can define an object with regarding function you will mock via some testing tool, for example look at Jest and Enzyme

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

Solution 6 - Unit Testing

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

Solution 7 - Unit Testing

I am using Web Components and this works for me -

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSergei PanfilovView Question on Stackoverflow
Solution 1 - Unit TestingWitVaultView Answer on Stackoverflow
Solution 2 - Unit TestingAnton KarpenkoView Answer on Stackoverflow
Solution 3 - Unit TestingLarryView Answer on Stackoverflow
Solution 4 - Unit TestingMatus DubravaView Answer on Stackoverflow
Solution 5 - Unit TestingPurkhalo AlexView Answer on Stackoverflow
Solution 6 - Unit TestingVonAxtView Answer on Stackoverflow
Solution 7 - Unit TestingIshankView Answer on Stackoverflow