(This is somewhat related to this three year-old post. I have tried to to follow the answers but they did not resolve my problem.)
I want to build a general mock (spy) navigator that I can pass in like I do here with spyNavigation
:
it('shows an error if the request fails', async () => {
const spyNavigation = {
replace: jest.fn(),
push: jest.fn(),
}
mockServer.use(
rest.get('*/users/current-user', (req, res, ctx) => {
return res(ctx.status(200), ctx.json({ id: 1 }))
})
)
mockServer.use(
rest.get('*/some-data', (req, res, ctx) => {
return res(ctx.status(500))
})
)
// @ts-ignore
TestHelper.renderWithReactQueryClient(<OverviewScreen navigation={spyNavigation} />)
await TestHelper.waitForWithExtendedTimeOut(() => {
expect(spyNavigation.push).toHaveBeenCalledWith('Error', {
error: new Error('Request failed with status code 500'),
})
})
})
I would like to abstract the spyNavigation
to a test helper and have TypeScript help me out to Partial typing it. So it will code-complete methods like 'replace', 'push' etc.
The TypeScript of react-navigation
is just so complex for me to understand. It would be fine if the spy does not know about the names Screens/Navigators - just to be a general "navigation" object.
import { BottomTabScreenProps } from '@react-navigation/bottom-tabs'
import { CompositeScreenProps, NavigatorScreenParams } from '@react-navigation/native'
import { NativeStackScreenProps } from '@react-navigation/native-stack'
import { AxiosError } from 'axios'
declare global {
namespace ReactNavigation {
interface RootParamList extends RootStackParamList {}
}
}
export type RootStackParamList = {
SignInOrCreateUser: undefined
SignIn: undefined
Root: NavigatorScreenParams<RootTabParamList> | undefined
Modal: undefined
Error: { error: AxiosError | null } | undefined
}
export type RootTabParamList = {
Overview: undefined
Returns: undefined
Portfolio: undefined
More: undefined
}
export type RouteName = keyof RootStackParamList | keyof RootTabParamList
export const routeTypeGuard = (route: RouteName) => route
export type RootStackScreenProps<Screen extends keyof RootStackParamList> = NativeStackScreenProps<
RootStackParamList,
Screen
>
export type RootTabScreenProps<Screen extends keyof RootTabParamList> = CompositeScreenProps<
BottomTabScreenProps<RootTabParamList, Screen>,
NativeStackScreenProps<RootStackParamList>
>
this does not work
import { NativeStackNavigatorProps } from '@react-navigation/native-stack/lib/typescript/src/types'
export const mockNavigation: NativeStackNavigatorProps = {
navigate: jest.fn(),
push: jest.fn(),
replace: jest.fn(),
pop: jest.fn(),
}
Type '{ navigate: jest.Mock<any, any>; push: jest.Mock<any, any>; replace: jest.Mock<any, any>; pop: jest.Mock<any, any>; }' is not assignable to type 'NativeStackNavigatorProps'.
Object literal may only specify known properties, and 'navigate' does not exist in type 'NativeStackNavigatorProps'.ts(2322)
I have a guess that it should be something like
export const mockNavigation: Record<keyof ???, () => ReturnType<typeof jest.fn>> = {
navigate: jest.fn(),
push: jest.fn(),
replace: jest.fn(),
pop: jest.fn(),
}