Search code examples
typescriptreact-nativereact-testing-libraryreact-native-testing-libraryreact-navigation-v6

Testing React Native app: How to fix: navigation.setOptions is not a function?


Here is the test:


describe('<HomeScreen />', () => {
  it('Renders correctly', () => {

// const setOptions = jest.fn(); // 1
// const setOptions = (navigation: any, route: any) => { } // 2
//   const setOptions = (props: HomeProps) => { } // 3
//  const setOptions = (options: Partial<NativeStackNavigationOptions>) => void // 4

    render(
      <Provider store={store}>
        <PersistGate loading={null} persistor={persistor}>
          <HomeScreen navigation={{ setOptions: setOptions }} route={undefined} />
        </PersistGate>
      </Provider>,
    );
  });
});

I've tried the solutions that are given here and here but they do not work for me.

I think the problem is that I'm using TypeScript and React Navigation v6, because:

  1. const setOptions = jest.fn(); I get:

    Type '{ setOptions: jest.Mock<any, any>; }' is not assignable to type 'NativeStackNavigationProp<RootStackParamList, "Home">'.
    

    NativeStackNavigationProp<RootStackParamList, "Home"> is the type I have for the component.

    It's this one: export type HomeProps = NativeStackScreenProps<RootStackParamList, 'Home'>;

    Which later I import as HomeProps

  2. const setOptions = (navigation: any, route: any) => { }

    I get:

    Type '(navigation: any, route: any) => void' is not assignable to type '(options: Partial<NativeStackNavigationOptions>) => void'.
    
  3. const setOptions = (props: HomeProps) => { }

    I get:

    Type '(props: HomeProps) => void' is not assignable to type '(options: Partial<NativeStackNavigationOptions>) => void'.
    
  4. const setOptions = (options: Partial<NativeStackNavigationOptions>) => void (suggestion of @captain-yossarian)

I get:

Type '{ setOptions: (options: Partial<NativeStackNavigationOptions>) => any; }' is not assignable to type 'NativeStackNavigationProp<RootStackParamList, "Home">'.

How can I solve this?


Solution

  • Consider this example:

    import React, { FC, useEffect } from "react";
    import { View } from "react-native";
    import "react-native";
    import { render } from "@testing-library/react-native";
    import { NativeStackScreenProps, NativeStackNavigationProp } from "@react-navigation/native-stack";
    
    type RootStackParamList = {
      App: undefined;
    };
    
    export type AppProps = NativeStackScreenProps<RootStackParamList, "App">;
    
    const App: FC<AppProps> = ({ navigation }) => {
      useEffect(() => {
        navigation.setOptions({
          headerRight: () => <View>hello</View>,
          gestureEnabled: false
        });
      });
    
      return <View>Hello</View>;
    };
    
    export default App;
    
    
    const setOptions = (options: NativeStackNavigationProp<RootStackParamList, "App">) =>
      void (
        // 4
    
        render(
          <App navigation={options} route={{ key: 'hello', name: "App", }} />
        )
      );
    

    Playground

    We need to use NativeStackNavigationProp<RootStackParamList, "App"> type for options