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?
Step 1: You will start a new project using create-react-app so open your terminal and type. Step 2: Switch to the jest-testing folder using the following command. Step 6: Create a Button. js file and Button.
Both Jest and Enzyme are meant to test the react applications. Jest can be used with any other Javascript framework, but Enzyme is meant to run on react only. Jest can be used without Enzyme, and snapshots can be created and tested perfectly fine. But the Enzyme adds additional functionality to it.
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 the onClick
prop of the Button
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:
it("should navigate to the 'QuestionsScreen'", () => {
wrapper.find(Button).props().onPress({} as any);
expect(props.navigation.navigate).toHaveBeenCalledTimes(1); // SUCCESS
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With