I'm building a React Native app with TypeScript. I'm doing my component tests using Jest and Enzyme. I'm also using React Navigation
I'm struggling to write the unit test for clicking my button.
Here is the component's code (just the render function):
render() {
const { navigation } = this.props;
return (
<View style={styles.container}>
<Button
raised
title={strings.painButtonTitle}
buttonStyle={styles.painButton}
titleStyle={styles.title}
onPress={() => navigation.navigate("QuestionsScreen")}
/>
</View>
);
}
Now here is the unit test.
describe("interaction", () => {
let wrapper: ShallowWrapper;
let props: Props;
beforeEach(() => {
props = createTestProps({});
wrapper = shallow(<HomeScreen {...props} />);
});
describe("clicking the Pain Button", () => {
it("should navigate to the 'QuestionsScreen'", () => {
wrapper.find("Button").simulate("click");
expect(props.navigation.navigate).toHaveBeenCalledTimes(1);
});
});
});
This fails and claims the navigation.navigate
function - which is mocked using jest.fn() - is never called.
I assume it has something to do with providing an error function to the button. The problem is, I can't not do that, since I need to call with the argument "QuestionsScreen"
. So I can't do something like onPress={this.navigation.navigate)
and then miraculously call "QuestionsScreen"
, can I?
How can I get this test to pass?
I had a similar question with you. I tried
simulate("click")
but failed because there's noonClick
property of the component.My way was to change the test case to
wrapper.find("form").simulate("submit")
because my navigation function was defined in the submit property of the form.The "Common Gotchas" section for
simulate
says that "even though the name would imply this simulates an actual event, .simulate() will in fact target the component's prop based on the event you give it. For example, .simulate('click') will actually get the onClick prop and call it."That behavior can be seen in the
Enzyme
source code here and here.So the line
wrapper.find("Button").simulate("click");
ends up trying to call theonClick
prop of theButton
which doesn't exist so it essentially does nothing.This post from an Airbnb dev recommends invoking props directly and avoiding
simulate
.Here is a modified test that invokes the
onPress
prop directly: