I'm new at React Native and Typescript. I have been implementing a small project with Stack Navigation and Drawer Navigation. The project has been working well but now I have to make some unit tests. I started with a very simple one but is failing :/
This is the code for the navigation of the app:
Navigator.tsx
import App from "../../App";
import React from 'react';
import { Image, StyleSheet, TouchableHighlight } from 'react-native';
import { createAppContainer, NavigationScreenProp, NavigationState, NavigationParams } from 'react-navigation';
import { createDrawerNavigator } from 'react-navigation-drawer';
import { createStackNavigator } from 'react-navigation-stack';
import LoginScreen from "./LoginScreen";
import RegisterScreen from "./RegisterScreen";
import MapScreen from "./MapScreen";
import BikesScreen from "./BikesScreen";
import TheftScreen from "./TheftScreen";
import RentBikeScreen from "./RentBikeScreen";
import RouteListScreen from "./RouteListScreen";
import CouponScreen from "./CouponScreen";
import strings from "../config/strings";
interface Props {
navigation: NavigationScreenProp<NavigationState,NavigationParams>;
}
interface State {}
export default class NavigatorContainer extends React.Component<Props, State> {
render() {
const DrawerStack =
createDrawerNavigator({
Map: MapScreen,
Bikes: BikesScreen,
Theft: TheftScreen,
RouteList: RouteListScreen,
Coupon: CouponScreen
})
DrawerStack.navigationOptions = ({ navigation }) => {
const { routeName } = navigation.state.routes[navigation.state.index];
const headerTitle =
routeName == "Map" ? strings.CONSULT_ROUTE :
routeName == "Bikes" ? strings.BIKES_TITLE :
routeName == "Theft" ? strings.THEFT_REPORT_TITLE :
routeName == "Register" ? strings.REGISTER_SCREEN_TITLE :
routeName == "RouteList" ? strings.ROUTE_LIST_TITLE :
routeName == "Coupon" ? strings.COUPON_TITLE : "";
return {
headerTitle,
headerLeft: ({ tintColor }: {tintColor: any}) => (
<TouchableHighlight onPress={() => navigation.toggleDrawer()}><Image
source={require('../assets/images/drawer.png')}
style={[styles.icon, { tintColor: tintColor }]}
/></TouchableHighlight>)
};
};
const AppNavigator = createStackNavigator(
{
Login: {
screen: LoginScreen,
navigationOptions: {
header: null
}
},
Register: {
screen: RegisterScreen
},
DrawerStack: DrawerStack
},
{
initialRouteName: 'Login',
}
);
const AppContainer = createAppContainer(AppNavigator);
return <AppContainer />;
}
}
const styles = StyleSheet.create({
icon: {
width: 24,
height: 24,
},
});
This is the test:
App-test.tsx
/**
* @format
*/
import 'react-native';
import React from 'react';
import App from '../App';
import * as renderer from 'react-test-renderer';
jest.mock('react-native', () => {
return {
StyleSheet: {
create: () => {
}
},
Platform: {}
}
});
it('renders correctly', () => {
renderer.create(<App />);
});
When executing the tests with "yarn test" I get this:
src/screens/Navigator.tsx:50:38 - error TS7031: Binding element 'navigation' implicitly has an 'any' type
So I changed 'navigation' with 'navigation : NavigationScreenProp':
DrawerStack.navigationOptions = (navigation : NavigationScreenProp<NavigationState,NavigationParams>) => {....
And the test pass!... but now when I try to go to one of the screens of the DrawerNavigator for instance MapScreen, using 'this.props.navigation.navigate('Map')' I get the error:
TypeError: undefined is not an object (evaluating 'navigation.state.routes')
I see that the problem is in this line:
const { routeName } = navigation.state.routes[navigation.state.index];
but I don't know how to solve it and don't understand why it worked only with '({ navigation })'
Any ideas?