From cb2e744dcebf7f71ddaa5462d393a6dbfd971fcd Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Wed, 4 Nov 2020 21:48:26 +0100 Subject: [PATCH] fix: always respect key in the route object when generating action --- .../src/__tests__/getActionFromState.test.tsx | 228 +++++++++++++++--- packages/core/src/getActionFromState.tsx | 24 +- 2 files changed, 209 insertions(+), 43 deletions(-) diff --git a/packages/core/src/__tests__/getActionFromState.test.tsx b/packages/core/src/__tests__/getActionFromState.test.tsx index 733d7790..3772f4cb 100644 --- a/packages/core/src/__tests__/getActionFromState.test.tsx +++ b/packages/core/src/__tests__/getActionFromState.test.tsx @@ -64,7 +64,58 @@ it('gets navigate action from state for top-level screen', () => { }); }); -it('gets navigate action from state for top-level screen with 2 screens', () => { +it('gets reset action from state with 1 route with key at root', () => { + const state = { + routes: [ + { + name: 'foo', + key: 'test', + state: { + routes: [ + { + name: 'bar', + state: { + routes: [ + { + key: 'test', + name: 'qux', + params: { author: 'jane' }, + }, + ], + }, + }, + ], + }, + }, + ], + }; + + expect(getActionFromState(state)).toEqual({ + payload: { + routes: [ + { + key: 'test', + name: 'foo', + state: { + routes: [ + { + name: 'bar', + state: { + routes: [ + { key: 'test', name: 'qux', params: { author: 'jane' } }, + ], + }, + }, + ], + }, + }, + ], + }, + type: 'RESET', + }); +}); + +it('gets reset action from state for top-level screen with 2 screens', () => { const state = { routes: [ { @@ -95,37 +146,7 @@ it('gets navigate action from state for top-level screen with 2 screens', () => }); }); -it('gets navigate action from state for top-level screen with 2 screens with config', () => { - const state = { - routes: [ - { - name: 'foo', - params: { answer: 42 }, - }, - { - name: 'bar', - params: { author: 'jane' }, - }, - ], - }; - - const config = { - initialRouteName: 'foo', - screens: { - bar: 'bar', - }, - }; - - expect(getActionFromState(state, config)).toEqual({ - payload: { - name: 'bar', - params: { author: 'jane' }, - }, - type: 'NAVIGATE', - }); -}); - -it('gets navigate action from state for top-level screen with more than 2 screens with config', () => { +it('gets reset action from state for top-level screen with more than 2 screens with config', () => { const state = { routes: [ { @@ -165,6 +186,76 @@ it('gets navigate action from state for top-level screen with more than 2 screen }); }); +it('gets reset action from state for top-level screen with 2 screens with config', () => { + const state = { + routes: [ + { + name: 'foo', + params: { answer: 42 }, + }, + { + name: 'bar', + key: 'test', + params: { author: 'jane' }, + }, + ], + }; + + const config = { + initialRouteName: 'foo', + screens: { + bar: 'bar', + }, + }; + + expect(getActionFromState(state, config)).toEqual({ + payload: { + routes: [ + { + name: 'foo', + params: { answer: 42 }, + }, + { + name: 'bar', + key: 'test', + params: { author: 'jane' }, + }, + ], + }, + type: 'RESET', + }); +}); + +it('gets navigate action from state for top-level screen with 2 screens with config', () => { + const state = { + routes: [ + { + name: 'foo', + params: { answer: 42 }, + }, + { + name: 'bar', + params: { author: 'jane' }, + }, + ], + }; + + const config = { + initialRouteName: 'foo', + screens: { + bar: 'bar', + }, + }; + + expect(getActionFromState(state, config)).toEqual({ + payload: { + name: 'bar', + params: { author: 'jane' }, + }, + type: 'NAVIGATE', + }); +}); + it('gets navigate action from state for top-level screen with more than 2 screens with config with lower index', () => { const state = { index: 1, @@ -550,7 +641,7 @@ it('gets navigate action from state with 2 screens without initial route and wit }); }); -it('gets navigate action from state with 2 screens including route with key and with config', () => { +it('gets navigate action from state with 2 screens including route with key on initial route and with config', () => { const state = { routes: [ { @@ -615,6 +706,75 @@ it('gets navigate action from state with 2 screens including route with key and }); }); +it('gets navigate action from state with 2 screens including route with key on 2nd route and with config', () => { + const state = { + routes: [ + { + name: 'foo', + state: { + routes: [ + { + name: 'bar', + state: { + routes: [ + { + name: 'qux', + params: { author: 'jane' }, + }, + { + key: 'test', + name: 'quz', + }, + ], + }, + }, + ], + }, + }, + ], + }; + + const config = { + screens: { + foo: { + initialRouteName: 'bar', + screens: { + bar: { + initialRouteName: 'qux', + }, + }, + }, + }, + }; + + expect(getActionFromState(state, config)).toEqual({ + payload: { + name: 'foo', + params: { + initial: true, + screen: 'bar', + params: { + state: { + routes: [ + { + name: 'qux', + params: { + author: 'jane', + }, + }, + { + key: 'test', + name: 'quz', + }, + ], + }, + }, + }, + }, + type: 'NAVIGATE', + }); +}); + it('gets navigate action from state with more than 2 screens and with config', () => { const state = { routes: [ @@ -743,7 +903,7 @@ it("doesn't return action if no routes are provided'", () => { expect(getActionFromState({ routes: [] })).toBe(undefined); }); -it('gets reset action from state', () => { +it('gets undefined action from state', () => { const state = { routes: [ { diff --git a/packages/core/src/getActionFromState.tsx b/packages/core/src/getActionFromState.tsx index 01a079dc..a142a08f 100644 --- a/packages/core/src/getActionFromState.tsx +++ b/packages/core/src/getActionFromState.tsx @@ -38,9 +38,11 @@ export default function getActionFromState( if ( !( - routes.length === 1 || + (routes.length === 1 && routes[0].key === undefined) || (routes.length === 2 && - routes[0].name === normalizedConfig?.initialRouteName) + routes[0].key === undefined && + routes[0].name === normalizedConfig?.initialRouteName && + routes[1].key === undefined) ) ) { return { @@ -70,22 +72,26 @@ export default function getActionFromState( const route: Route | PartialRoute> = routes[routes.length - 1]; - if (routes.length === 1) { + // Explicitly set to override existing value when merging params + Object.assign(params, { + initial: undefined, + screen: undefined, + params: undefined, + state: undefined, + }); + + if (routes.length === 1 && routes[0].key === undefined) { params.initial = true; params.screen = route.name; - params.state = undefined; // Explicitly set to override existing value when merging params } else if ( routes.length === 2 && routes[0].key === undefined && - routes[0].name === config?.initialRouteName + routes[0].name === config?.initialRouteName && + routes[1].key === undefined ) { params.initial = false; params.screen = route.name; - params.state = undefined; } else { - params.initial = undefined; - params.screen = undefined; - params.params = undefined; params.state = current; break; }