Reputation: 1572
I have a stateless component:
export default function TripReportFooter(props) {
const { tripReport, user, toggleFavorite, navigation } = props;
handleShare = async slug => {
try {
const result = await Share.share({
message: `Check out this Trip Report:\n/p/${slug}/`
});
if (result.action === Share.sharedAction) {
if (result.activityType) {
} else {
// shared
}
} else if (result.action === Share.dismissedAction) {
}
} catch (error) {
alert(error.message);
}
};
handleFavorite = async id => {
const token = await AsyncStorage.getItem("token");
toggleFavorite(id, token);
};
return (
... // handleFavorite and handleShare called with TouchableOpacities.
);
}
It has two functions inside, handleShare
and handleFavorite
. I want to test these functions are called, and also that handleFavorite
calls the prop function toggle favorite.
I tried wrapper.instance().handleFavorite()
, but since it is a stateless component, it returns null
.
Next someone on Stack Overflow suggested using a spy like so:
wrapper = shallow(<TripReportFooter {...props} handleFavorite={press} />);
wrapper
.find("TouchableOpacity")
.at(0)
.simulate("press");
expect(press.called).to.equal(true);
but this returned
'TypeError: Cannot read property 'equal' of undefined'.
What's the proper way to call these functions?
Upvotes: 13
Views: 6513
Reputation: 281626
Functions within a functional component aren't defined on the prototype or the functional component instance, you cannot directly spy on them
The solution here is to test out the internal implementation of the individual functions
For instance for handleFavourite
function you can mock AsynStorage and pass on a mock function for toggleFavourite and then asset it its called on TouchableOpacity onPress simulation
You can check how to mock AsyncStore in this post: How to test Async Storage with Jest?
const mocktToggleFavourite = jest.fn();
wrapper = shallow(<TripReportFooter {...props} toggleFavourite={mocktToggleFavourite} />);
wrapper
.find("TouchableOpacity")
.at(0)
.simulate("press");
expect(mockToggleFavourite).toHaveBeenCalled();
Similarly you can test the individual functionalities within handleShare
by first mocking Share.share
and then checking against each condition.For instance you can add an spy on window.alert and see if that is called
const windowSpy = jest.spyOn(window, 'alert');
wrapper = shallow(<TripReportFooter {...props} toggleFavourite={mocktToggleFavourite} />);
//Simulate event that calls handleShare
// Mock Share to give required result
expect(windowSpy).toBeCalledWith(expectedValue);
Upvotes: 1
Reputation: 1075
You first need to think about what you want to test. Is it implementation details or the interaction with your component? The latter is a much better mindset and standpoint so what I would do is to test the component from the interaction point of view.
I would (for handleShare
):
Now for the handleFavorite
:
AsyncStorage.getItem
;toggleFavorite
function that I would pass as props;toggleFavorite
function has been calledIf you want to test these functions individually you would have to extract them to the outside of the component and test them individually. But I would not advise this as it is not clean and extra work.
Hope it helps!
Upvotes: 1