TypeError: navigation.navigate is not a function in jest

1.8k Views Asked by At

Here is touchable element with navigation.navigate (react navigation 6.x),

    export default Home = ({ navigation }) => {
     ....
       return (
            <TouchableOpacity testID={"home.myhelp"} onPress={()=>{navigation.navigate("MyHelp")}} >
                <View style={{flex:2, alignContent:"flex-start", justifyContent:"center",alignItems:"center"}}>
                    <Icon  name="help-outline" color="black" size={hp("4.4%")}/> 
                </View>  
            </TouchableOpacity> 
     )

Here is the jest code which uses fireEvent to simulate the click of the touchable element:

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { render, cleanup, screen, fireEvent, waitFor } from "@testing-library/react-native";
import { authContext, stateContext, propsContext } from '../app/GlobalContext';
import Home from './Home';

describe ('Home page view', () => {

    test ('home page link', async () => {
        jest.mock('react-native-easy-grid', () => jest.fn());
        //jest.mock('react-native-device-info', () => () => jest.fn());
        const navigation = jest.fn();
        const propcontext = {device_id:"a device id", result:"fdkfjdsl;fjdsafkl", myself:{id:1,name:"me"}};
        const contextval = jest.fn().mockImplementation(() => {
            let temp = {}
        });
        const propsVal = {device_id:"a device id"};
        const authVal = {result:"fdkfjdsl;fjdsafkl", myself:{id:1,name:"me"}};
        const stateVal = {name:"me", alias:"akkus", aka:"aka"};
        //const spy = jest.spyOn(jest.fn(), "submit");
        const submit = jest.fn();
         //= jest.fn().mockImplementation();
        const component = (<NavigationContainer>
                                <propsContext.Provider value={propsVal}>
                                    <authContext.Provider value={authVal}>
                                        <stateContext.Provider value={stateVal}>
                                            <Home navigation={navigation}  />
                                        </stateContext.Provider>
                                    </authContext.Provider>
                                </propsContext.Provider>                                 
                            </NavigationContainer>);

        const wrapper = render(component);

        expect(screen.getByTestId('home.myhelp')).toBeTruthy();
        fireEvent.press(screen.getByTestId('home.myhelp')); //this line cause the error
       
    })
    
})

However the fireEvent causes error about navigation.navigate:

TypeError: navigation.navigate is not a function

  121 |                     <TextInput  style={{fontSize:hp("3%")}} placeholder={plcholder} onChangeText={strChg}></TextInput>
  122 |                 </View>
> 123 |                 <TouchableOpacity testID={"home.myhelp"} onPress={()=>{navigation.navigate("MyHelp")}} >
      |                                                                                   ^
  124 |                     <View style={{flex:2, alignContent:"flex-start", justifyContent:"center",alignItems:"center"}}>
  125 |                         <Icon  name="help-outline" color="black" size={hp("4.4%")}/> 
  126 |                     </View>  

  at navigate (src/components/home/Home.js:123:83)
  at handler (node_modules/@testing-library/react-native/src/fireEvent.ts:124:19)
  at act (node_modules/react/cjs/react.development.js:2510:16)
  at invokeEvent (node_modules/@testing-library/react-native/src/fireEvent.ts:123:3)
  at Function.invokeEvent [as press] (node_modules/@testing-library/react-native/src/fireEvent.ts:134:3)
  at Object.press (src/components/home/Home.test.js:56:23)
  at asyncGeneratorStep (node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24)
  at _next (node_modules/@babel/runtime/helpers/asyncToGenerator.js:25:9)
  at tryCallOne (node_modules/promise/lib/core.js:37:12)
  at node_modules/promise/lib/core.js:123:15
  at flush (node_modules/asap/raw.js:50:29)     

How to mock navigation.navigate to calm the error?

2

There are 2 best solutions below

0
On

Try this:

  1. const mockCallback = jest.fn((val) => val);

  2. Pass it to the component:

<Component navigation={{push: mockCallback} /> (Don't forget wrapping it with NavigationContainer)

  1. Click and expect the mock function to run:
const toClick = await screen.findByText('Products');
fireEvent(toClick, 'press');

expect(mockCallback).toHaveBeenCalled();
0
On

Solved the error after defining navigation as below:

const navigation = {navigate:jest.fn()};

or

const navigation = {navigate:()=>jest.fn()};