mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-26 09:14:22 +08:00
refactor: migrate tests to typescript
This commit is contained in:
@@ -52,6 +52,7 @@
|
||||
"@types/jest": "^24.0.12",
|
||||
"@types/react": "^16.8.14",
|
||||
"@types/react-native": "^0.57.51",
|
||||
"@types/react-test-renderer": "^16.8.1",
|
||||
"commitlint": "^7.5.2",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-satya164": "^2.4.1",
|
||||
|
||||
@@ -7,7 +7,10 @@ import createStackNavigator from '../createStackNavigator';
|
||||
|
||||
import createAppContainer, {
|
||||
_TESTING_ONLY_reset_container_count,
|
||||
// @ts-ignore
|
||||
} from '@react-navigation/native/src/createAppContainer';
|
||||
import { NavigationProp } from '../../types';
|
||||
|
||||
const NavigationTestUtils = {
|
||||
resetInternalState: _TESTING_ONLY_reset_container_count,
|
||||
};
|
||||
@@ -19,7 +22,11 @@ const styles = StyleSheet.create({
|
||||
});
|
||||
|
||||
class HomeScreen extends Component {
|
||||
static navigationOptions = ({ navigation }) => ({
|
||||
static navigationOptions = ({
|
||||
navigation,
|
||||
}: {
|
||||
navigation: NavigationProp;
|
||||
}) => ({
|
||||
title: `Welcome ${
|
||||
navigation.state.params ? navigation.state.params.user : 'anonymous'
|
||||
}`,
|
||||
@@ -69,7 +76,10 @@ describe('StackNavigator', () => {
|
||||
it('passes navigation to headerRight when wrapped in withNavigation', () => {
|
||||
const spy = jest.fn();
|
||||
|
||||
class TestComponent extends React.Component {
|
||||
class TestComponent extends React.Component<{
|
||||
onPress: (navigation: NavigationProp) => undefined;
|
||||
navigation: NavigationProp;
|
||||
}> {
|
||||
render() {
|
||||
return <View>{this.props.onPress(this.props.navigation)}</View>;
|
||||
}
|
||||
@@ -26,6 +26,7 @@ export type NavigationState = {
|
||||
index: number;
|
||||
routes: Route[];
|
||||
isTransitioning?: boolean;
|
||||
params?: { [key: string]: unknown };
|
||||
};
|
||||
|
||||
export type NavigationProp<RouteName = string, Params = object> = {
|
||||
@@ -82,7 +83,7 @@ export type HeaderTransitionConfig = {
|
||||
|
||||
export type NavigationStackOptions = {
|
||||
title?: string;
|
||||
header?: (props: HeaderProps) => React.ReactNode | null;
|
||||
header?: (props: HeaderProps) => React.ReactNode;
|
||||
headerTitle?: string;
|
||||
headerTitleStyle?: StyleProp<TextStyle>;
|
||||
headerTitleContainerStyle?: StyleProp<ViewStyle>;
|
||||
@@ -92,11 +93,11 @@ export type NavigationStackOptions = {
|
||||
headerBackTitle?: string;
|
||||
headerBackTitleStyle?: StyleProp<TextStyle>;
|
||||
headerTruncatedBackTitle?: string;
|
||||
headerLeft?: React.ComponentType<HeaderBackbuttonProps>;
|
||||
headerLeft?: React.FunctionComponent<HeaderBackbuttonProps>;
|
||||
headerLeftContainerStyle?: StyleProp<ViewStyle>;
|
||||
headerRight?: React.ComponentType<{}>;
|
||||
headerRight?: (() => React.ReactNode) | React.ReactNode;
|
||||
headerRightContainerStyle?: StyleProp<ViewStyle>;
|
||||
headerBackImage?: React.ComponentType<{
|
||||
headerBackImage?: React.FunctionComponent<{
|
||||
tintColor: string;
|
||||
title?: string | null;
|
||||
}>;
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
} from '../../types';
|
||||
|
||||
type Props = {
|
||||
screenProps: unknown;
|
||||
navigation: NavigationProp;
|
||||
descriptors: { [key: string]: SceneDescriptor };
|
||||
navigationConfig: NavigationConfig;
|
||||
@@ -21,6 +20,7 @@ type Props = {
|
||||
onGestureBegin?: () => void;
|
||||
onGestureCanceled?: () => void;
|
||||
onGestureEnd?: () => void;
|
||||
screenProps?: unknown;
|
||||
};
|
||||
|
||||
const USE_NATIVE_DRIVER = true;
|
||||
|
||||
@@ -65,7 +65,7 @@ type Props = {
|
||||
onGestureBegin?: () => void;
|
||||
onGestureEnd?: () => void;
|
||||
onGestureCanceled?: () => void;
|
||||
screenProps: unknown;
|
||||
screenProps?: unknown;
|
||||
};
|
||||
|
||||
type State = {
|
||||
|
||||
@@ -37,7 +37,7 @@ type Props = {
|
||||
) => void | Promise<any>;
|
||||
navigation: NavigationProp;
|
||||
descriptors: { [key: string]: SceneDescriptor };
|
||||
screenProps: unknown;
|
||||
screenProps?: unknown;
|
||||
};
|
||||
|
||||
type State = {
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
import ScenesReducer from '../ScenesReducer';
|
||||
const MOCK_DESCRIPTOR = {};
|
||||
import { Scene, NavigationState, SceneDescriptor } from '../../types';
|
||||
|
||||
const MOCK_DESCRIPTOR: SceneDescriptor = {} as any;
|
||||
|
||||
/**
|
||||
* Simulate scenes transtion with changes of navigation states.
|
||||
*/
|
||||
function testTransition(states) {
|
||||
function testTransition(states: string[][]) {
|
||||
let descriptors = states
|
||||
.reduce((acc, state) => acc.concat(state), [])
|
||||
.reduce((acc, key) => {
|
||||
acc[key] = MOCK_DESCRIPTOR;
|
||||
return acc;
|
||||
}, {});
|
||||
const routes = states.map(keys => ({
|
||||
.reduce((acc, state) => acc.concat(state), [] as string[])
|
||||
.reduce(
|
||||
(acc, key) => {
|
||||
acc[key] = MOCK_DESCRIPTOR;
|
||||
return acc;
|
||||
},
|
||||
{} as { [key: string]: SceneDescriptor }
|
||||
);
|
||||
const routes = states.map((keys, i) => ({
|
||||
key: String(i),
|
||||
index: keys.length - 1,
|
||||
routes: keys.map(key => ({ key, routeName: '' })),
|
||||
isTransitioning: false,
|
||||
}));
|
||||
|
||||
let scenes = [];
|
||||
let prevState = null;
|
||||
routes.forEach(nextState => {
|
||||
let scenes: Scene[] = [];
|
||||
let prevState: NavigationState | null = null;
|
||||
routes.forEach((nextState: NavigationState) => {
|
||||
scenes = ScenesReducer(scenes, nextState, prevState, descriptors);
|
||||
prevState = nextState;
|
||||
});
|
||||
@@ -100,55 +106,61 @@ describe('ScenesReducer', () => {
|
||||
|
||||
it('gets active scene when index changes', () => {
|
||||
const state1 = {
|
||||
key: '0',
|
||||
index: 0,
|
||||
routes: [{ key: '1', routeName: '' }],
|
||||
isTransitioning: false,
|
||||
};
|
||||
|
||||
const state2 = {
|
||||
key: '0',
|
||||
index: 1,
|
||||
routes: [{ key: '1', routeName: '' }, { key: '2', routeName: '' }],
|
||||
isTransitioning: false,
|
||||
};
|
||||
|
||||
const scenes1 = ScenesReducer([], state1, null);
|
||||
const scenes2 = ScenesReducer(scenes1, state2, state1);
|
||||
const route = scenes2.find(scene => scene.isActive).route;
|
||||
const scenes1 = ScenesReducer([], state1, null, {});
|
||||
const scenes2 = ScenesReducer(scenes1, state2, state1, {});
|
||||
const route = scenes2.find(scene => scene.isActive)!.route;
|
||||
expect(route).toEqual({ key: '2', routeName: '' });
|
||||
});
|
||||
|
||||
it('gets same scenes', () => {
|
||||
const state1 = {
|
||||
key: '0',
|
||||
index: 1,
|
||||
routes: [{ key: '1', routeName: '' }, { key: '2', routeName: '' }],
|
||||
isTransitioning: false,
|
||||
};
|
||||
|
||||
const state2 = {
|
||||
key: '0',
|
||||
index: 1,
|
||||
routes: [{ key: '1', routeName: '' }, { key: '2', routeName: '' }],
|
||||
isTransitioning: false,
|
||||
};
|
||||
|
||||
const scenes1 = ScenesReducer([], state1, null);
|
||||
const scenes2 = ScenesReducer(scenes1, state2, state1);
|
||||
const scenes1 = ScenesReducer([], state1, null, {});
|
||||
const scenes2 = ScenesReducer(scenes1, state2, state1, {});
|
||||
expect(scenes1).toBe(scenes2);
|
||||
});
|
||||
|
||||
it('gets different scenes when keys are different', () => {
|
||||
const state1 = {
|
||||
key: '0',
|
||||
index: 1,
|
||||
routes: [{ key: '1', routeName: '' }, { key: '2', routeName: '' }],
|
||||
isTransitioning: false,
|
||||
};
|
||||
|
||||
const state2 = {
|
||||
key: '0',
|
||||
index: 1,
|
||||
routes: [{ key: '2', routeName: '' }, { key: '1', routeName: '' }],
|
||||
isTransitioning: false,
|
||||
};
|
||||
|
||||
const descriptors = { 1: jest.mock(), 2: jest.mock() };
|
||||
const descriptors = { 1: {}, 2: {} } as any;
|
||||
|
||||
const scenes1 = ScenesReducer([], state1, null, descriptors);
|
||||
const scenes2 = ScenesReducer(scenes1, state2, state1, descriptors);
|
||||
@@ -157,6 +169,7 @@ describe('ScenesReducer', () => {
|
||||
|
||||
it('gets different scenes when routes are different', () => {
|
||||
const state1 = {
|
||||
key: '0',
|
||||
index: 1,
|
||||
routes: [
|
||||
{ key: '1', x: 1, routeName: '' },
|
||||
@@ -166,6 +179,7 @@ describe('ScenesReducer', () => {
|
||||
};
|
||||
|
||||
const state2 = {
|
||||
key: '0',
|
||||
index: 1,
|
||||
routes: [
|
||||
{ key: '1', x: 3, routeName: '' },
|
||||
@@ -186,6 +200,7 @@ describe('ScenesReducer', () => {
|
||||
// anything except the last route in the array of routes.
|
||||
it('gets different scenes when state index changes', () => {
|
||||
const state1 = {
|
||||
key: '0',
|
||||
index: 1,
|
||||
routes: [
|
||||
{ key: '1', x: 1, routeName: '' },
|
||||
@@ -195,6 +210,7 @@ describe('ScenesReducer', () => {
|
||||
};
|
||||
|
||||
const state2 = {
|
||||
key: '0',
|
||||
index: 0,
|
||||
routes: [
|
||||
{ key: '1', x: 1, routeName: '' },
|
||||
@@ -13,6 +13,7 @@ describe('Transitioner', () => {
|
||||
configureTransition: () => ({}),
|
||||
navigation: {
|
||||
state: {
|
||||
key: '0',
|
||||
index: 0,
|
||||
routes: [
|
||||
{ key: '1', routeName: 'Foo' },
|
||||
@@ -23,6 +24,10 @@ describe('Transitioner', () => {
|
||||
dispatch: () => false,
|
||||
setParams: () => false,
|
||||
navigate: () => false,
|
||||
isFocused: () => false,
|
||||
dangerouslyGetParent: () => undefined,
|
||||
getParam: jest.fn(),
|
||||
addListener: jest.fn(),
|
||||
},
|
||||
render: () => <div />,
|
||||
onTransitionStart: onTransitionStartCallback,
|
||||
@@ -34,6 +39,7 @@ describe('Transitioner', () => {
|
||||
navigation: {
|
||||
...transitionerProps.navigation,
|
||||
state: {
|
||||
key: '0',
|
||||
index: 0,
|
||||
routes: [
|
||||
{ key: '1', routeName: 'Foo', params: { name: 'Zoom' } },
|
||||
@@ -42,8 +48,12 @@ describe('Transitioner', () => {
|
||||
},
|
||||
},
|
||||
};
|
||||
const component = renderer.create(<Transitioner {...transitionerProps} />);
|
||||
component.update(<Transitioner {...nextTransitionerProps} />);
|
||||
const component = renderer.create(
|
||||
<Transitioner descriptors={{}} {...transitionerProps} />
|
||||
);
|
||||
component.update(
|
||||
<Transitioner descriptors={{}} {...nextTransitionerProps} />
|
||||
);
|
||||
expect(onTransitionStartCallback).not.toBeCalled();
|
||||
expect(onTransitionEndCallback).not.toBeCalled();
|
||||
});
|
||||
@@ -27,5 +27,9 @@ declare module '@react-navigation/core' {
|
||||
stackConfig: object
|
||||
): React.ComponentType;
|
||||
|
||||
export function withNavigation<Props extends { navigation: object }>(
|
||||
Comp: React.ComponentType<Props>
|
||||
): React.ComponentType<Pick<Props, Exclude<keyof Props, 'navigation'>>>;
|
||||
|
||||
export function StackRouter(routeConfigMap: object, stackConfig: object);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@ declare module '@react-navigation/native' {
|
||||
import { ComponentType } from 'react';
|
||||
import { StyleProp, ViewStyle, ViewProps } from 'react-native';
|
||||
|
||||
export function createAppContainer<Props>(
|
||||
Comp: React.ComponentType<Props>
|
||||
): React.ComponentType<Props>;
|
||||
|
||||
export function withOrientation<Props extends { isLandscape: boolean }>(
|
||||
Comp: React.ComponentType<Props>
|
||||
): React.ComponentType<Pick<Props, Exclude<keyof Props, 'isLandscape'>>>;
|
||||
|
||||
@@ -1149,6 +1149,13 @@
|
||||
"@types/prop-types" "*"
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-test-renderer@^16.8.1":
|
||||
version "16.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-16.8.1.tgz#96f3ce45a3a41c94eca532a99103dd3042c9d055"
|
||||
integrity sha512-8gU69ELfJGxzVWVYj4MTtuHxz9nO+d175XeQ1XrXXxesUBsB4KK6OCfzVhEX6leZWWBDVtMJXp/rUjhClzL7gw==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^16.8.14":
|
||||
version "16.8.15"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.15.tgz#a76515fed5aa3e996603056f54427fec5f2a5122"
|
||||
|
||||
Reference in New Issue
Block a user