1

I have header component, written in react native. When onPress is triggered it should execute goBack function, but it just logs 'onPressCalled' and doesn't enter if statement. It looks like mock isn't applied properly and test is not using mocked version of navigation so it fails.

import {
    ArrowIcon,
    HeaderComponent,
    IconWrapper,
    PageTitle,
    PlaceholderView,
} from './Header.style';
import { Poppins_500Medium, useFonts } from '@expo-google-fonts/poppins';
import { useNavigation } from '@react-navigation/native';

const Header = () => {
    const navigation = useNavigation();
    const [loaded, error] = useFonts({
        Poppins_500Medium,
    });

    if (error || !loaded) {
        return <></>;
    }

    return (
        <HeaderComponent>
            <IconWrapper
                onPress={() => {
                    console.log('onPressCalled');
                    if (navigation.canGoBack()) {
                        console.log('usao1');
                        navigation.goBack();
                    }
                }}
            >
                <ArrowIcon
                    name='left'
                    color='#fff'
                    size={24}
                />
            </IconWrapper>
            <PageTitle>Create account</PageTitle>
            <PlaceholderView />
        </HeaderComponent>
    );
};

export default Header;

And test suite for it:

import { fireEvent, render, waitFor } from '../../../test-utils';
import Header from './Header.component';

describe('Header', () => {
    // Clicking the back button navigates to the previous screen
    it.only('should navigate to previous screen when back button is clicked', async () => {
        // Mock the necessary dependencies
        const navigation = {
            canGoBack: jest.fn().mockReturnValue(true),
            goBack: jest.fn(),
        };

        // Mock the required imports
        jest.doMock('@react-navigation/native', () => ({
            useNavigation: jest.fn().mockReturnValue(navigation),
        }));
        jest.doMock('@expo-google-fonts/poppins', () => ({
            Poppins_500Medium: 'Poppins_500Medium',
            useFonts: jest.fn().mockReturnValue([true, null]),
        }));

        // Render the component
        const { findByTestId } = render(<Header />);

        const iconWrapper = await findByTestId('IconWrapper');

        // Simulate click on the back button
        fireEvent.press(iconWrapper);

        // Assert that the navigation.goBack function is called
        await waitFor(() => {
            expect(navigation.goBack).toHaveBeenCalled();
        });
    });
})

1 Answer 1

1

I think this should work:

// Mock the useNavigation hook to return a navigation object
const mockNavigation = jest.fn();
const mockGoBack = jest.fn();
jest.mock('@react-navigation/native', () => {
  const actualNavigation = jest.requireActual('@react-navigation/native');
  return {
    ...actualNavigation,
    useNavigation: () => ({
      navigate: mockNavigation,
      goBack: mockGoBack,
    }),
  };
});

You mock the useNavigation to give back the mock functions you have defined. You can then check if they are called. You can put it in your test file or in your jest.setup, so that they are mocked globally.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.