问题
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 an onClick function that calls e.preventDefault(). How to tell to <a href>(link) 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); //would be good if we'll remove e.preventDefault()
});
Test's output error:
TypeError: Cannot read property 'preventDefault' of undefined
回答1:
Try this
link.simulate('click', {
preventDefault: () => {
}
});
回答2:
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();
});
回答3:
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.
回答4:
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(event.preventDefault).toHaveBeenCalledTimes(1);
});
Similarly for stopPropagation.
Anton Karpenko's answer for Jest was useful.
回答5:
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()
})
})
回答6:
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);
来源:https://stackoverflow.com/questions/41829301/how-to-mock-e-preventdefault-in-react-components-child