Here is my code I'm testing:
const CardWarsComponent = props => {
const onSubmitCardMove = () => {
props.floopThePig()
}
return <Button id="FloopButtonId" onClick={onSubmitCardMove}>FLOOP IT</Button>
};
When I test I do this:
const floopStub = sinon.stub();
const wrapper = shallow(<CardWarsComponent floopThePig={floopStub}></CardWarsComponent>)
const button = wrapper.find('#FloopButtonId').dive();
const onClick = button.prop('onClick');
onClick();
wrapper.update();
expect(floopStub).to.have.been.calledOnce();
I find that I get this response:
TypeError: (0, _chai.expect)(...).to.have.been.calledOnce is not a function
BUT, if I call it once already:
const floopStub = sinon.stub();
floopStub()
const wrapper = shallow(<CardWarsComponent floopThePig={floopMock}></CardWarsComponent>)
Then I get:
expected floopThePig to have been called exactly once, but was called twice
floopThePig at Context.floopThePig
floopThePig at floopThePig
So why can I not get it called once, but after calling it once...I get the second (actual test) call?
The initial error message you got is exactly correct - looking at the Sinon docs, .calledOnce
is a not a function, it's a javascript get
that runs code. In general, Chai expectations only seem to be functions if they need parameters.
I find this a bit annoying because get
overloading isn't very nice and breaks our ability to reason about the code, and it sets off a bunch of lint errors, but hey ho.
Changing your expect to
expect(floopStub).to.have.been.calledOnce;
fixes the test (at least on my machine!)
The reason the code seems to "work" in your second example is because the test resolves the calledOnce
get operation, which checks the condition and throws a test failure assertion, so there's never a chance to throw the original error by trying to call the get
result as if it were a function.
Incidentally, it's easier to trigger the click event with enzyme's built-in .simulate()
call. This code works fine:
const floopStub = sinon.stub();
const wrapper = shallow(<CardWarsComponent floopThePig={floopMock}></CardWarsComponent>);
wrapper.find('#FloopButtonId').dive().simulate('click');
expect(floopStub).to.have.been.calledOnce;
More info on testing React events with sinon/enzyme can be found here: https://www.leighhalliday.com/testing-react-jest-enzyme-sinon