mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-02-09 17:23:18 +08:00
tests: refactor SwitchRouter tests (#34)
* add test:dev for dev test workflow, which should rather not lint/build and trigger pretest * refactor tests to use closure based helper instead of class * refactor SwitchRouter tests with router stateful helpers to improve tests readability * simplify matcher * better initialRoute backBehavior test by using a non-default routeName * minor fix * Update src/routers/__tests__/routerTestHelper.js Co-Authored-By: slorber <slorber@users.noreply.github.com> * Update src/routers/__tests__/routerTestHelper.js Co-Authored-By: slorber <slorber@users.noreply.github.com> * Update src/routers/__tests__/routerTestHelper.js Co-Authored-By: slorber <slorber@users.noreply.github.com> * revert bad merge stuff * revert bad merge stuff * fix tests
This commit is contained in:
@@ -3,186 +3,148 @@
|
||||
import React from 'react';
|
||||
import SwitchRouter from '../SwitchRouter';
|
||||
import StackRouter from '../StackRouter';
|
||||
import * as SwitchActions from '../SwitchActions';
|
||||
import * as NavigationActions from '../../NavigationActions';
|
||||
import { getRouterTestHelper } from './routerTestHelper';
|
||||
|
||||
describe('SwitchRouter', () => {
|
||||
it('resets the route when unfocusing a tab by default', () => {
|
||||
const router = getExampleRouter();
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
const state2 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'A2' },
|
||||
state
|
||||
);
|
||||
expect(state2.routes[0].index).toEqual(1);
|
||||
expect(state2.routes[0].routes.length).toEqual(2);
|
||||
const { navigateTo, getState } = getRouterTestHelper(getExampleRouter());
|
||||
|
||||
const state3 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'B' },
|
||||
state2
|
||||
);
|
||||
navigateTo('A2');
|
||||
expect(getState().routes[0].index).toEqual(1);
|
||||
expect(getState().routes[0].routes.length).toEqual(2);
|
||||
|
||||
expect(state3.routes[0].index).toEqual(0);
|
||||
expect(state3.routes[0].routes.length).toEqual(1);
|
||||
navigateTo('B');
|
||||
expect(getState().routes[0].index).toEqual(0);
|
||||
expect(getState().routes[0].routes.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('does not reset the route on unfocus if resetOnBlur is false', () => {
|
||||
const router = getExampleRouter({ resetOnBlur: false });
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
const state2 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'A2' },
|
||||
state
|
||||
);
|
||||
expect(state2.routes[0].index).toEqual(1);
|
||||
expect(state2.routes[0].routes.length).toEqual(2);
|
||||
|
||||
const state3 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'B' },
|
||||
state2
|
||||
const { navigateTo, getState } = getRouterTestHelper(
|
||||
getExampleRouter({ resetOnBlur: false })
|
||||
);
|
||||
|
||||
expect(state3.routes[0].index).toEqual(1);
|
||||
expect(state3.routes[0].routes.length).toEqual(2);
|
||||
navigateTo('A2');
|
||||
expect(getState().routes[0].index).toEqual(1);
|
||||
expect(getState().routes[0].routes.length).toEqual(2);
|
||||
|
||||
navigateTo('B');
|
||||
expect(getState().routes[0].index).toEqual(1);
|
||||
expect(getState().routes[0].routes.length).toEqual(2);
|
||||
});
|
||||
|
||||
it('ignores back by default', () => {
|
||||
const router = getExampleRouter();
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
const state2 = router.getStateForAction(
|
||||
{ type: SwitchActions.JUMP_TO, routeName: 'B' },
|
||||
state
|
||||
);
|
||||
expect(state2.index).toEqual(1);
|
||||
const { jumpTo, back, getState } = getRouterTestHelper(getExampleRouter());
|
||||
|
||||
const state3 = router.getStateForAction(
|
||||
{ type: NavigationActions.BACK },
|
||||
state2
|
||||
);
|
||||
jumpTo('B');
|
||||
expect(getState().index).toEqual(1);
|
||||
|
||||
expect(state3.index).toEqual(1);
|
||||
back();
|
||||
expect(getState().index).toEqual(1);
|
||||
});
|
||||
|
||||
it('handles initialRoute backBehavior', () => {
|
||||
const router = getExampleRouter({ backBehavior: 'initialRoute' });
|
||||
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
expect(state.routeKeyHistory).toBeUndefined();
|
||||
|
||||
const state2 = router.getStateForAction(
|
||||
{ type: SwitchActions.JUMP_TO, routeName: 'B' },
|
||||
state
|
||||
const { jumpTo, back, getState } = getRouterTestHelper(
|
||||
getExampleRouter({ backBehavior: 'initialRoute', initialRouteName: 'B' })
|
||||
);
|
||||
expect(state2.index).toEqual(1);
|
||||
expect(getState().routeKeyHistory).toBeUndefined();
|
||||
expect(getState().index).toEqual(1);
|
||||
|
||||
const state3 = router.getStateForAction(
|
||||
{ type: NavigationActions.BACK },
|
||||
state2
|
||||
);
|
||||
jumpTo('C');
|
||||
expect(getState().index).toEqual(2);
|
||||
|
||||
expect(state3.index).toEqual(0);
|
||||
jumpTo('A');
|
||||
expect(getState().index).toEqual(0);
|
||||
|
||||
back();
|
||||
expect(getState().index).toEqual(1);
|
||||
|
||||
back();
|
||||
expect(getState().index).toEqual(1);
|
||||
});
|
||||
|
||||
it('handles order backBehavior', () => {
|
||||
const routerHelper = new ExampleRouterHelper({ backBehavior: 'order' });
|
||||
expect(routerHelper.getCurrentState().routeKeyHistory).toBeUndefined();
|
||||
const { navigateTo, back, getState } = getRouterTestHelper(
|
||||
getExampleRouter({ backBehavior: 'order' })
|
||||
);
|
||||
expect(getState().routeKeyHistory).toBeUndefined();
|
||||
|
||||
expect(
|
||||
routerHelper.applyAction({
|
||||
type: SwitchActions.JUMP_TO,
|
||||
routeName: 'C',
|
||||
})
|
||||
).toMatchObject({ index: 2 });
|
||||
navigateTo('C');
|
||||
expect(getState().index).toEqual(2);
|
||||
|
||||
expect(
|
||||
routerHelper.applyAction({ type: NavigationActions.BACK })
|
||||
).toMatchObject({ index: 1 });
|
||||
back();
|
||||
expect(getState().index).toEqual(1);
|
||||
|
||||
expect(
|
||||
routerHelper.applyAction({ type: NavigationActions.BACK })
|
||||
).toMatchObject({ index: 0 });
|
||||
back();
|
||||
expect(getState().index).toEqual(0);
|
||||
|
||||
expect(
|
||||
routerHelper.applyAction({ type: NavigationActions.BACK })
|
||||
).toMatchObject({ index: 0 });
|
||||
back();
|
||||
expect(getState().index).toEqual(0);
|
||||
});
|
||||
|
||||
it('handles history backBehavior', () => {
|
||||
const routerHelper = new ExampleRouterHelper({ backBehavior: 'history' });
|
||||
expect(routerHelper.getCurrentState().routeKeyHistory).toMatchObject(['A']);
|
||||
const { navigateTo, back, getState } = getRouterTestHelper(
|
||||
getExampleRouter({ backBehavior: 'history' })
|
||||
);
|
||||
expect(getState().routeKeyHistory).toEqual(['A']);
|
||||
|
||||
expect(
|
||||
routerHelper.applyAction({
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'B',
|
||||
})
|
||||
).toMatchObject({ index: 1, routeKeyHistory: ['A', 'B'] });
|
||||
navigateTo('B');
|
||||
expect(getState().index).toEqual(1);
|
||||
expect(getState().routeKeyHistory).toEqual(['A', 'B']);
|
||||
|
||||
expect(
|
||||
routerHelper.applyAction({
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'A',
|
||||
})
|
||||
).toMatchObject({ index: 0, routeKeyHistory: ['B', 'A'] });
|
||||
navigateTo('A');
|
||||
expect(getState().index).toEqual(0);
|
||||
expect(getState().routeKeyHistory).toEqual(['B', 'A']);
|
||||
|
||||
expect(
|
||||
routerHelper.applyAction({
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'C',
|
||||
})
|
||||
).toMatchObject({ index: 2, routeKeyHistory: ['B', 'A', 'C'] });
|
||||
navigateTo('C');
|
||||
expect(getState().index).toEqual(2);
|
||||
expect(getState().routeKeyHistory).toEqual(['B', 'A', 'C']);
|
||||
|
||||
expect(
|
||||
routerHelper.applyAction({
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'A',
|
||||
})
|
||||
).toMatchObject({ index: 0, routeKeyHistory: ['B', 'C', 'A'] });
|
||||
navigateTo('A');
|
||||
expect(getState().index).toEqual(0);
|
||||
expect(getState().routeKeyHistory).toEqual(['B', 'C', 'A']);
|
||||
|
||||
expect(
|
||||
routerHelper.applyAction({ type: NavigationActions.BACK })
|
||||
).toMatchObject({ index: 2, routeKeyHistory: ['B', 'C'] });
|
||||
back();
|
||||
expect(getState().index).toEqual(2);
|
||||
expect(getState().routeKeyHistory).toEqual(['B', 'C']);
|
||||
|
||||
expect(
|
||||
routerHelper.applyAction({ type: NavigationActions.BACK })
|
||||
).toMatchObject({ index: 1, routeKeyHistory: ['B'] });
|
||||
back();
|
||||
expect(getState().index).toEqual(1);
|
||||
expect(getState().routeKeyHistory).toEqual(['B']);
|
||||
|
||||
expect(
|
||||
routerHelper.applyAction({ type: NavigationActions.BACK })
|
||||
).toMatchObject({ index: 1, routeKeyHistory: ['B'] });
|
||||
back();
|
||||
expect(getState().index).toEqual(1);
|
||||
expect(getState().routeKeyHistory).toEqual(['B']);
|
||||
});
|
||||
|
||||
it('handles nested actions', () => {
|
||||
const router = getExampleRouter();
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
const state2 = router.getStateForAction(
|
||||
{
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'B',
|
||||
action: { type: NavigationActions.NAVIGATE, routeName: 'B2' },
|
||||
},
|
||||
state
|
||||
);
|
||||
const subState = state2.routes[state2.index];
|
||||
const activeGrandChildRoute = subState.routes[subState.index];
|
||||
expect(activeGrandChildRoute.routeName).toEqual('B2');
|
||||
const { navigateTo, getSubState } = getRouterTestHelper(getExampleRouter());
|
||||
|
||||
navigateTo('B', {
|
||||
action: { type: NavigationActions.NAVIGATE, routeName: 'B2' },
|
||||
});
|
||||
expect(getSubState(1).routeName).toEqual('B');
|
||||
expect(getSubState(2).routeName).toEqual('B2');
|
||||
});
|
||||
|
||||
it('handles nested actions and params simultaneously', () => {
|
||||
const router = getExampleRouter();
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
const state2 = router.getStateForAction(
|
||||
{
|
||||
const { navigateTo, getSubState } = getRouterTestHelper(getExampleRouter());
|
||||
|
||||
const params1 = { foo: 'bar' };
|
||||
const params2 = { bar: 'baz' };
|
||||
|
||||
navigateTo('B', {
|
||||
params: params1,
|
||||
action: {
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'B',
|
||||
params: { foo: 'bar' },
|
||||
action: { type: NavigationActions.NAVIGATE, routeName: 'B2' },
|
||||
routeName: 'B2',
|
||||
params: params2,
|
||||
},
|
||||
state
|
||||
);
|
||||
const subState = state2.routes[state2.index];
|
||||
const activeGrandChildRoute = subState.routes[subState.index];
|
||||
expect(subState.params.foo).toEqual('bar');
|
||||
expect(activeGrandChildRoute.routeName).toEqual('B2');
|
||||
});
|
||||
expect(getSubState(1).routeName).toEqual('B');
|
||||
expect(getSubState(1).params).toEqual(params1);
|
||||
expect(getSubState(2).routeName).toEqual('B2');
|
||||
expect(getSubState(2).params).toEqual(params2);
|
||||
});
|
||||
|
||||
it('order of handling navigate action is correct for nested switchrouters', () => {
|
||||
@@ -209,35 +171,17 @@ describe('SwitchRouter', () => {
|
||||
}
|
||||
);
|
||||
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
expect(state.routes[state.index].routeName).toEqual('OtherNestedSwitch');
|
||||
const { navigateTo, getSubState } = getRouterTestHelper(router);
|
||||
expect(getSubState(1).routeName).toEqual('OtherNestedSwitch');
|
||||
|
||||
const state2 = router.getStateForAction(
|
||||
{
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'Bar',
|
||||
},
|
||||
state
|
||||
);
|
||||
expect(state2.routes[state2.index].routeName).toEqual('Bar');
|
||||
navigateTo('Bar');
|
||||
expect(getSubState(1).routeName).toEqual('Bar');
|
||||
|
||||
const state3 = router.getStateForAction(
|
||||
{
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'NestedSwitch',
|
||||
},
|
||||
state2
|
||||
);
|
||||
const state4 = router.getStateForAction(
|
||||
{
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'Bar',
|
||||
},
|
||||
state3
|
||||
);
|
||||
let activeState4 = state4.routes[state4.index];
|
||||
expect(activeState4.routeName).toEqual('NestedSwitch');
|
||||
expect(activeState4.routes[activeState4.index].routeName).toEqual('Bar');
|
||||
navigateTo('NestedSwitch');
|
||||
navigateTo('Bar');
|
||||
|
||||
expect(getSubState(1).routeName).toEqual('NestedSwitch');
|
||||
expect(getSubState(2).routeName).toEqual('Bar');
|
||||
});
|
||||
|
||||
// https://github.com/react-navigation/react-navigation.github.io/issues/117#issuecomment-385597628
|
||||
@@ -259,42 +203,14 @@ describe('SwitchRouter', () => {
|
||||
}
|
||||
);
|
||||
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
expect(state.routes[state.index].routeName).toEqual('Login');
|
||||
const { navigateTo, getSubState } = getRouterTestHelper(router);
|
||||
expect(getSubState(1).routeName).toEqual('Login');
|
||||
|
||||
const state2 = router.getStateForAction(
|
||||
{
|
||||
type: SwitchActions.JUMP_TO,
|
||||
routeName: 'Home',
|
||||
},
|
||||
state
|
||||
);
|
||||
expect(state2.routes[state2.index].routeName).toEqual('Home');
|
||||
navigateTo('Home');
|
||||
expect(getSubState(1).routeName).toEqual('Home');
|
||||
});
|
||||
});
|
||||
|
||||
// A simple helper that makes it easier to write basic routing tests
|
||||
// As we generally want to apply one action after the other,
|
||||
// it's often convenient to manipulate a structure that keeps the router state
|
||||
class ExampleRouterHelper {
|
||||
constructor(config) {
|
||||
this._router = getExampleRouter(config);
|
||||
this._currentState = this._router.getStateForAction({
|
||||
type: NavigationActions.INIT,
|
||||
});
|
||||
}
|
||||
|
||||
applyAction = action => {
|
||||
this._currentState = this._router.getStateForAction(
|
||||
action,
|
||||
this._currentState
|
||||
);
|
||||
return this._currentState;
|
||||
};
|
||||
|
||||
getCurrentState = () => this._currentState;
|
||||
}
|
||||
|
||||
const getExampleRouter = (config = {}) => {
|
||||
const PlainScreen = () => <div />;
|
||||
const StackA = () => <div />;
|
||||
|
||||
55
packages/core/src/routers/__tests__/routerTestHelper.js
Normal file
55
packages/core/src/routers/__tests__/routerTestHelper.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import * as NavigationActions from '../../NavigationActions';
|
||||
import * as SwitchActions from '../../routers/SwitchActions';
|
||||
|
||||
// A simple helper that makes it easier to write basic routing tests
|
||||
// We generally want to apply one action after the other and check router returns correct state
|
||||
// it's often convenient to manipulate a structure that keeps the router state to avoid
|
||||
// creating many state1, state2, state3 local variables which are prone to typos...
|
||||
|
||||
const defaultInitAction = {
|
||||
type: NavigationActions.INIT,
|
||||
};
|
||||
|
||||
export const getRouterTestHelper = (router, initAction = defaultInitAction) => {
|
||||
let state = router.getStateForAction(initAction);
|
||||
|
||||
const applyAction = action => {
|
||||
state = router.getStateForAction(action, state);
|
||||
};
|
||||
|
||||
const navigateTo = (routeName, otherActionAttributes) =>
|
||||
applyAction({
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName,
|
||||
...otherActionAttributes,
|
||||
});
|
||||
|
||||
const jumpTo = (routeName, otherActionAttributes) =>
|
||||
applyAction({
|
||||
type: SwitchActions.JUMP_TO,
|
||||
routeName,
|
||||
...otherActionAttributes,
|
||||
});
|
||||
|
||||
const back = () =>
|
||||
applyAction({
|
||||
type: NavigationActions.BACK,
|
||||
});
|
||||
|
||||
const getState = () => state;
|
||||
|
||||
const getSubState = (level = 1) => {
|
||||
return getSubStateRecursive(state, level);
|
||||
};
|
||||
|
||||
return { applyAction, navigateTo, jumpTo, back, getState, getSubState };
|
||||
};
|
||||
|
||||
const getSubStateRecursive = (state, level = 1) => {
|
||||
if (level === 0) {
|
||||
return state;
|
||||
} else {
|
||||
const directSubState = state.routes[state.index];
|
||||
return getSubStateRecursive(directSubState, level - 1);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user