Reputation: 53
The simplified setup of my code is as follows:
App.js
class App extends React.Component {
componentDidMount() {
const { thirdPartyAPI } = this.props;
thirdPartyAPI.field.onValueChanged(this.handleValueChange);
}
handleValueChange = (value) => {
// callback to do complex validation stuff and suchlike
// update state
}
render() {
// display stuff
}
}
App.test.js
each([...]).
.test('App is rendered according to...',
async (...) => {
const mockApi = {
field: {
onValueChanged: ????
}
}
const AppComponent = await shallow(
<App thirdPartyAPI={mockApi} />,
);
});
OnValueChanged detects when a user altered the value outside the react-app. From a user-perspective this works, but the jest-test is giving me trouble.
Simply put: how do I test this?
I need to mock the API function, but I need to use the callback function handleValueChange as defined in App.js. I have lost track of the jest-tutorials I've read and watched, many of them very detailed, but none of them seem to apply to this particular situation.
Is it even possible to test this code? If so, how? And if not, how should I restructure my code so that I can test it?
If anyone can point me in the right direction, I would appreciate it.
Upvotes: 4
Views: 1094
Reputation: 45840
If you pass a mock function to your component as thirdPartyAPI.field.onValueChanged
then it will get called with this.handleValueChange
.
Mock functions record everything they get called with, so you can then use the mock function to get this.handleValueChange
using mockFn.mock.calls
.
Once you have retrieved this.handleValueChange
in your test, you can call it directly and verify that it works as expected.
Here is a simple working example:
import * as React from 'react';
import { shallow } from 'enzyme';
class App extends React.Component {
constructor(...args) {
super(...args);
this.state = { val: 'original' };
}
componentDidMount() {
const { thirdPartyAPI } = this.props;
thirdPartyAPI.field.onValueChanged(this.handleValueChange);
}
handleValueChange = (value) => {
this.setState({ val: value });
}
render() { return null; }
}
test('App', () => {
const onValueChangedMock = jest.fn();
const thirdPartyAPIMock = { field: { onValueChanged: onValueChangedMock } };
const wrapper = shallow(<App thirdPartyAPI={thirdPartyAPIMock} />);
expect(wrapper.state('val')).toBe('original'); // Success!
const handleValueChange = onValueChangedMock.mock.calls[0][0]; // <= get handleValueChange...
handleValueChange('updated'); // <= ...now call it directly
expect(wrapper.state('val')).toBe('updated'); // Success!
})
Upvotes: 2