I am trying to test a component that is accesing useRouter
from expo-router
My Component:
import { useRouter } from 'expo-router'
const CustomComponent: React.FC<Props> = () => {
const router = useRouter()
const onPress = () => {
router.replace(PATHS.DASHBOARD)
}
return <HCard pressAction={onPress} title={'title'} />
}
The test file:
describe('CustomComponent', () => {
it('should render CustomComponent correctly', () => {
const wrapper = renderWithProvider(<CustomComponent />)
expect(wrapper.getByText('title')).toBeOnTheScreen()
})
})
I am getting this error: Couldn't find a navigation object. Is your component inside NavigationContainer?
I understand what the error suggests, but I do not know how to provide that NavigationContainer, since it is not part of expo-router. Also, I have mocked the useRouter, but got the same error
Later edit Here is the renderWithProvider:
export const renderWithProvider = (children: JSX.Element): RenderResult => {
const inset = {
frame: { x: 0, y: 0, width: 0, height: 0 },
insets: { top: 0, left: 0, right: 0, bottom: 0 },
}
return render(<NativeBaseProvider initialWindowMetrics={inset}>{children}</NativeBaseProvider>)
}
I've built this util to help me with this error.
Basically when you are mounting your component inside a jest suite, it doesn't have the navigation stack necessary for useRouter
to work.
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
type NavigationMockProps = {
controller: ComponentType<any>;
params?: any;
};
export const NavigationMock = ({ controller, params }: NavigationMockProps) => {
const stack = createNativeStackNavigator<any>();
return (
<NavigationContainer independent>
<stack.Navigator initialRouteName="TestRoute">
<stack.Screen
name="TestRoute"
component={controller}
initialParams={params}
options={{ header: () => null }}
/>
</stack.Navigator>
</NavigationContainer>
);
};
Then, you can use it like this:
describe('CustomComponent', () => {
it('should render CustomComponent correctly', () => {
const wrapper = render(
<NavigationMock controller={CustomComponent} params={params} />
);
expect(wrapper.getByText('title')).toBeOnTheScreen();
})
})