I am having trouble using Enzyme's contains method when it comes to a button's onClick handler where the provided action method requires an argument. I ran into this while passing redux actions to a component, but I'll use simplified examples here.
Say you have two methods:
const logClick = () => console.log('button was clicked');
const logClickWithArg = (message) => console.log('button was clicked: ', message);
You pass them to a component, and in that component you have two buttons:
<button
onClick={logClick}
>
Click
</button>
<button
onClick={() => logClickWithArg('hello')}
>
Click With Arg
</button>
When I test the first button, there's no problem:
expect(wrapper.contains(
<button
onClick={logClick}
>
Click
</button>)).toBe(true);
it passes. However, the second:
expect(wrapper.contains(
<button
onClick={() => logClickWithArg('hello')}
>
Click
</button>)).toBe(true);
fails with the unhelpful output:
expect(received).toBe(expected)
Expected value to be (using ===):
true
Received:
false
at Object.<anonymous>.it (src/App.test.js:42:3)
at process._tickCallback (internal/process/next_tick.js:103:7)
I've tried to find out more by trying all kinds of comparisons, like:
console.log('first ', wrapper.find('button').first().props().onClick);
console.log('last ', wrapper.find('button').last().props().onClick);
expect(wrapper.find('button').first().props().onClick).toEqual(logClick);
expect(wrapper.find('button').last().props().onClick).toEqual(logClickWithArg);
which results in:
console.log src/App.test.js:29
first () => console.log('button was clicked')
console.log src/App.test.js:30
last () => logClickWithArg('hello')
expect(received).toEqual(expected)
Expected value to equal:
[Function logClickWithArg]
Received:
[Function onClick]
I am using Jest as a test-runner, and encountered this in both the create-react-app and react-boilerplate set-up. Any idea what I am doing wrong?
EDIT
I'll give my own workaround in an answer below. I'll use my actual code there instead of these examples. However, I am still curious why the test here fails ....
I would suggest to revise testing strategy.
You can test HTML rendering this way (using enzyme
):
// GIVEN
const expectedNode = shallow(
<div>
<button className="simple-button">Click</button>
<button>Click With Arg</button>
</div>
);
// WHEN
const actualNode = shallow(<YourComponentName />);
// THEN
expect(actualNode.html()).to.equal(expectedNode.html());
and component interactivity this way (using enzyme
and sinon
):
// GIVEN
const clickCallback = sinon.spy();
const actualNode = shallow(<YourComponentName onClick={clickCallback}/>);
// WHEN
actualNode.find(".simple-button").simulate("click");
// THEN
sinon.assert.called(clickCallback);
As you are using Jest, you may consider using Jest Snapshots for HTML verification.