Reputation: 4887
How can I write a jest unit test for a react native component which contains a NavigationEvents
subcomponent.
I've tried the solutions offered in questions here and here without success.
The error I am getting is
console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9215
The above error occurred in the <Context.Consumer> component:
in withNavigation(NavigationEvents) (created by MyComponent)
in View (created by View)
in View (created by MyComponent)
in MyComponent
Consider adding an error boundary to your tree to customize error handling behavior.
● MyComponent test › renders
Invariant Violation: withNavigation can only be used on a view hierarchy of a navigator. The wrapped component is unable to get access to navigation from props or context.
Below is a minimal example that causes the error.
import 'react-native';
import { View } from 'react-native';
import { NavigationEvents } from 'react-navigation';
import React from 'react';
import renderer from 'react-test-renderer';
class MyComponent extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<View>
<NavigationEvents/>
</View>
);}
}
describe('MyComponent test', () => {
it('renders', () => {
jest.mock('react-navigation', () =>({
NavigationEvents: 'mockNavigationEvents',
withNavigation: component => component
}));
const navigation = { navigate: jest.fn() };
renderer.create(<MyComponent navigation={navigation}/>);
});
});
As requested in comments added package.json
below:
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"eject": "expo eject",
"test": "node ./node_modules/jest/bin/jest.js --watchAll"
},
"jest": {
"preset": "jest-expo"
},
"dependencies": {
"@expo/samples": "2.1.1",
"@expo/vector-icons": "^10.0.0",
"expo": "^35.0.0",
"expo-camera": "~7.0.0",
"expo-sqlite": "^7.0.0",
"moment": "^2.24.0",
"react": "16.8.3",
"react-native": "https://github.com/expo/react-native/archive/sdk-35.0.0.tar.gz",
"react-native-action-button": "^2.8.5",
"react-native-calendar-picker": "^6.0.0",
"react-native-dialog": "^5.6.0",
"react-native-dotenv": "^0.2.0",
"react-native-dynamic-search-bar": "^0.1.11",
"react-native-elements": "^1.1.0",
"react-native-gesture-handler": "~1.3.0",
"react-native-keyboard-aware-scroll-view": "^0.9.1",
"react-native-modal-datetime-picker": "^7.4.0",
"react-native-paper": "^2.15.2",
"react-native-progress-circle": "^2.1.0",
"react-native-search-bar": "^3.4.2",
"react-native-vector-icons": "^6.4.2",
"react-navigation": "^3.0.9",
"expo-constants": "~7.0.0",
"expo-file-system": "~7.0.0"
},
"devDependencies": {
"babel-preset-expo": "^7.0.0",
"jest-expo": "^35.0.0"
},
"private": true
}
$ expo-cli -V
3.13.1
Upvotes: 1
Views: 2804
Reputation: 37318
The problem is that jest.mock
has to be outside of describe
and it
functions. You don't need to manually mock navigation
object since you're mocking the withNavigation
HOC function:
// Setup mocks outside describe and it functions
jest.mock('react-navigation', () =>({
NavigationEvents: 'mockNavigationEvents',
withNavigation: component => component
}));
class MyComponent extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<View>
<NavigationEvents/>
</View>
);
}
}
describe('MyComponent test', () => {
it('renders', () => {
renderer.create(<MyComponent/>);
});
});
And the renders
test passes:
I suggest you have all those mocks inside a file and set setupFilesAfterEnv
in package.json
:
package.json
> jest
:"jest": {
"preset": "jest-expo"
"setupFilesAfterEnv": ["./path/to/jestInit.js"]
},
jestInit.js
:jest.mock('react-navigation', () =>({
NavigationEvents: 'mockNavigationEvents',
withNavigation: component => component
}));
This way, you'll have those mocks for every Jest test file without having to include the mocks inside each test file.
Upvotes: 4