diff --git a/lib/src/commands/Commands.test.ts b/lib/src/commands/Commands.test.ts index f1be4567865..0c7a6328f23 100644 --- a/lib/src/commands/Commands.test.ts +++ b/lib/src/commands/Commands.test.ts @@ -22,6 +22,7 @@ import { IWrappedComponent } from 'react-native-navigation/components/ComponentW describe('Commands', () => { let uut: Commands; let mockedNativeCommandsSender: NativeCommandsSender; + let mockedOptionsProcessor: OptionsProcessor; let mockedStore: Store; let commandsObserver: CommandsObserver; let mockedUniqueIdProvider: UniqueIdProvider; @@ -36,7 +37,7 @@ describe('Commands', () => { commandsObserver = new CommandsObserver(uniqueIdProvider); const layoutProcessorsStore = new LayoutProcessorsStore(); - const mockedOptionsProcessor = mock(OptionsProcessor); + mockedOptionsProcessor = mock(OptionsProcessor); const optionsProcessor = instance(mockedOptionsProcessor) as OptionsProcessor; layoutProcessor = new LayoutProcessor(layoutProcessorsStore); @@ -317,6 +318,19 @@ describe('Commands', () => { const result = await uut.dismissModal('myUniqueId'); expect(result).toEqual('the id'); }); + + it('processes mergeOptions', async () => { + const options = { + animations: { + dismissModal: { + enabled: false, + }, + }, + }; + + uut.dismissModal('myUniqueId', options); + verify(mockedOptionsProcessor.processOptions(CommandName.DismissModal, options)).called(); + }); }); describe('dismissAllModals', () => { @@ -334,6 +348,19 @@ describe('Commands', () => { const result = await uut.dismissAllModals(); expect(result).toEqual('the id'); }); + + it('processes mergeOptions', async () => { + const options: Options = { + animations: { + dismissModal: { + enabled: false, + }, + }, + }; + + uut.dismissAllModals(options); + verify(mockedOptionsProcessor.processOptions(CommandName.DismissAllModals, options)).called(); + }); }); describe('push', () => { @@ -405,6 +432,19 @@ describe('Commands', () => { const result = await uut.pop('theComponentId', {}); expect(result).toEqual('theComponentId'); }); + + it('processes mergeOptions', async () => { + const options: Options = { + animations: { + pop: { + enabled: false, + }, + }, + }; + + uut.pop('theComponentId', options); + verify(mockedOptionsProcessor.processOptions(CommandName.Pop, options)).called(); + }); }); describe('popTo', () => { @@ -422,6 +462,19 @@ describe('Commands', () => { const result = await uut.popTo('theComponentId'); expect(result).toEqual('theComponentId'); }); + + it('processes mergeOptions', async () => { + const options: Options = { + animations: { + pop: { + enabled: false, + }, + }, + }; + + uut.popTo('theComponentId', options); + verify(mockedOptionsProcessor.processOptions(CommandName.PopTo, options)).called(); + }); }); describe('popToRoot', () => { @@ -439,6 +492,19 @@ describe('Commands', () => { const result = await uut.popToRoot('theComponentId'); expect(result).toEqual('theComponentId'); }); + + it('processes mergeOptions', async () => { + const options: Options = { + animations: { + pop: { + enabled: false, + }, + }, + }; + + uut.popToRoot('theComponentId', options); + verify(mockedOptionsProcessor.processOptions(CommandName.PopToRoot, options)).called(); + }); }); describe('setStackRoot', () => { diff --git a/lib/src/commands/Commands.ts b/lib/src/commands/Commands.ts index 3defb11c912..cca3e2b697f 100644 --- a/lib/src/commands/Commands.ts +++ b/lib/src/commands/Commands.ts @@ -73,7 +73,7 @@ export class Commands { public mergeOptions(componentId: string, options: Options) { const input = cloneDeep(options); - this.optionsProcessor.processOptions(input, CommandName.MergeOptions); + this.optionsProcessor.processOptions(CommandName.MergeOptions, input); const component = this.store.getComponentInstance(componentId); if (component && !component.isMounted) @@ -106,6 +106,7 @@ export class Commands { public dismissModal(componentId: string, mergeOptions?: Options) { const commandId = this.uniqueIdProvider.generate(CommandName.DismissModal); + this.optionsProcessor.processOptions(CommandName.DismissModal, mergeOptions); const result = this.nativeCommandsSender.dismissModal(commandId, componentId, mergeOptions); this.commandsObserver.notify(CommandName.DismissModal, { commandId, @@ -117,6 +118,7 @@ export class Commands { public dismissAllModals(mergeOptions?: Options) { const commandId = this.uniqueIdProvider.generate(CommandName.DismissAllModals); + this.optionsProcessor.processOptions(CommandName.DismissAllModals, mergeOptions); const result = this.nativeCommandsSender.dismissAllModals(commandId, mergeOptions); this.commandsObserver.notify(CommandName.DismissAllModals, { commandId, mergeOptions }); return result; @@ -138,6 +140,7 @@ export class Commands { public pop(componentId: string, mergeOptions?: Options) { const commandId = this.uniqueIdProvider.generate(CommandName.Pop); + this.optionsProcessor.processOptions(CommandName.Pop, mergeOptions); const result = this.nativeCommandsSender.pop(commandId, componentId, mergeOptions); this.commandsObserver.notify(CommandName.Pop, { commandId, componentId, mergeOptions }); return result; @@ -145,6 +148,7 @@ export class Commands { public popTo(componentId: string, mergeOptions?: Options) { const commandId = this.uniqueIdProvider.generate(CommandName.PopTo); + this.optionsProcessor.processOptions(CommandName.PopTo, mergeOptions); const result = this.nativeCommandsSender.popTo(commandId, componentId, mergeOptions); this.commandsObserver.notify(CommandName.PopTo, { commandId, componentId, mergeOptions }); return result; @@ -152,6 +156,7 @@ export class Commands { public popToRoot(componentId: string, mergeOptions?: Options) { const commandId = this.uniqueIdProvider.generate(CommandName.PopToRoot); + this.optionsProcessor.processOptions(CommandName.PopToRoot, mergeOptions); const result = this.nativeCommandsSender.popToRoot(commandId, componentId, mergeOptions); this.commandsObserver.notify(CommandName.PopToRoot, { commandId, componentId, mergeOptions }); return result; diff --git a/lib/src/commands/LayoutTreeCrawler.ts b/lib/src/commands/LayoutTreeCrawler.ts index 3aa60a026a7..d2fbf1109ba 100644 --- a/lib/src/commands/LayoutTreeCrawler.ts +++ b/lib/src/commands/LayoutTreeCrawler.ts @@ -24,7 +24,7 @@ export class LayoutTreeCrawler { if (node.type === LayoutType.Component) { this.handleComponent(node); } - this.optionsProcessor.processOptions(node.data.options, commandName); + this.optionsProcessor.processOptions(commandName, node.data.options); node.children.forEach((value: LayoutNode) => this.crawl(value, commandName)); } diff --git a/lib/src/commands/OptionsProcessor.test.ts b/lib/src/commands/OptionsProcessor.test.ts index 55fd667113b..754256d66cf 100644 --- a/lib/src/commands/OptionsProcessor.test.ts +++ b/lib/src/commands/OptionsProcessor.test.ts @@ -83,7 +83,7 @@ describe('navigation options', () => { }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual(expectedOptions); }); @@ -135,7 +135,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.ShowModal); + uut.processOptions(CommandName.ShowModal, options); expect(options).toEqual(expected); }); @@ -165,7 +165,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.ShowModal); + uut.processOptions(CommandName.ShowModal, options); expect(options).toEqual(expected); }); @@ -195,7 +195,7 @@ describe('navigation options', () => { }, }; const expected: Options = { ...options }; - uut.processOptions(options, CommandName.ShowModal); + uut.processOptions(CommandName.ShowModal, options); expect(options).toEqual(expected); }); }); @@ -247,7 +247,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.DismissModal); + uut.processOptions(CommandName.DismissModal, options); expect(options).toEqual(expected); }); @@ -277,7 +277,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.DismissModal); + uut.processOptions(CommandName.DismissModal, options); expect(options).toEqual(expected); }); @@ -307,7 +307,7 @@ describe('navigation options', () => { }, }; const expected: Options = { ...options }; - uut.processOptions(options, CommandName.DismissModal); + uut.processOptions(CommandName.DismissModal, options); expect(options).toEqual(expected); }); }); @@ -319,7 +319,7 @@ describe('navigation options', () => { popGesture: false, modalPresentationStyle: OptionsModalPresentationStyle.fullScreen, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ blurOnUnmount: false, popGesture: false, @@ -338,7 +338,7 @@ describe('navigation options', () => { return !value; }); - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { visible: false, @@ -364,7 +364,7 @@ describe('navigation options', () => { return !value; }); - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { visible: false, @@ -386,7 +386,7 @@ describe('navigation options', () => { expect(commandName).toEqual(CommandName.SetRoot); }); - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); }); it('passes props to registered processor', () => { @@ -404,7 +404,7 @@ describe('navigation options', () => { }; optionProcessorsRegistry.addProcessor('topBar.visible', processor); - uut.processOptions(options, CommandName.SetRoot, props); + uut.processOptions(CommandName.SetRoot, options, props); }); it('supports multiple registered processors', () => { @@ -417,7 +417,7 @@ describe('navigation options', () => { optionProcessorsRegistry.addProcessor('topBar.visible', () => false); optionProcessorsRegistry.addProcessor('topBar.visible', () => true); - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { visible: true, @@ -442,7 +442,7 @@ describe('navigation options', () => { optionProcessorsRegistry.addProcessor('bottomTabs.visible', () => true); optionProcessorsRegistry.addProcessor('topBar.background.translucent', () => true); - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { visible: true, @@ -467,7 +467,7 @@ describe('navigation options', () => { topBar: { background: { color: undefined } }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { background: { color: undefined } }, }); @@ -484,7 +484,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { background: { color: { resource_paths: ['@color/textColor'] } } }, }); @@ -496,7 +496,7 @@ describe('navigation options', () => { topBar: { background: { color: 'blue' } }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ statusBar: { backgroundColor: { light: 0xffff0000, dark: 0xffff0000 } }, topBar: { background: { color: { light: 0xff0000ff, dark: 0xff0000ff } } }, @@ -508,7 +508,7 @@ describe('navigation options', () => { topBar: { background: { color: null } }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { background: { color: { light: 'NoColor', dark: 'NoColor' } } }, }); @@ -520,7 +520,7 @@ describe('navigation options', () => { background: { color: { light: 'blue', dark: 'red' } }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { background: { color: { light: 0xff0000ff, dark: 0xffff0000 } }, @@ -540,7 +540,7 @@ describe('navigation options', () => { topBar: { background: { color: 'blue' } }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ statusBar: { backgroundColor: 0xffff0000 }, topBar: { background: { color: 0xff0000ff } }, @@ -552,7 +552,7 @@ describe('navigation options', () => { topBar: { background: { color: undefined } }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { background: { color: undefined } }, }); @@ -563,7 +563,7 @@ describe('navigation options', () => { topBar: { background: { color: null } }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { background: { color: 'NoColor' } }, }); @@ -579,7 +579,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ statusBar: { backgroundColor: 0xffff0000 }, topBar: { @@ -596,7 +596,7 @@ describe('navigation options', () => { topBar: { background: { color: DynamicColorIOS({ light: 'red', dark: 'blue' }) } }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { background: { color: { dynamic: { light: 0xffff0000, dark: 0xff0000ff } } } }, }); @@ -607,7 +607,7 @@ describe('navigation options', () => { topBar: { background: { color: undefined } }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { background: { color: undefined } }, }); @@ -621,7 +621,7 @@ describe('navigation options', () => { rootBackgroundImage: 234, bottomTab: { icon: 345, selectedIcon: 345 }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ backgroundImage: { height: 100, scale: 1, uri: 'lol', width: 100 }, rootBackgroundImage: { height: 100, scale: 1, uri: 'lol', width: 100 }, @@ -636,7 +636,7 @@ describe('navigation options', () => { const passProps = { some: 'thing' }; const options = { topBar: { title: { component: { passProps, name: 'a' } } } }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); verify(mockedStore.setPendingProps('CustomComponent1', passProps)).called(); }); @@ -644,7 +644,7 @@ describe('navigation options', () => { it('generates componentId for component id was not passed', () => { const options = { topBar: { title: { component: { name: 'a' } } } }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { title: { component: { name: 'a', componentId: 'CustomComponent1' } } }, @@ -654,7 +654,7 @@ describe('navigation options', () => { it('copies passed id to componentId key', () => { const options = { topBar: { title: { component: { name: 'a', id: 'Component1' } } } }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { title: { component: { name: 'a', id: 'Component1', componentId: 'Component1' } } }, @@ -665,7 +665,7 @@ describe('navigation options', () => { const passProps = { prop: 'prop' }; const options = { topBar: { rightButtons: [{ passProps, id: '1' }] } }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); verify(mockedStore.setPendingProps('1', passProps)).called(); }); @@ -674,7 +674,7 @@ describe('navigation options', () => { const passProps = { prop: 'prop' }; const options = { topBar: { rightButtons: [{ passProps } as any] } }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options).toEqual({ topBar: { rightButtons: [{ passProps }] } }); }); @@ -688,7 +688,7 @@ describe('navigation options', () => { background: { component: { name: 'helloThere2', passProps: {} } }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.topBar.rightButtons[0].passProps).toBeUndefined(); expect(options.topBar.leftButtons[0].passProps).toBeUndefined(); expect(options.topBar.title.component.passProps).toBeUndefined(); @@ -702,14 +702,14 @@ describe('navigation options', () => { background: { component: { name: 'helloThere2', passProps: {} } }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); verify(mockedStore.ensureClassForName('helloThere1')).called(); verify(mockedStore.ensureClassForName('helloThere2')).called(); }); it('show warning on iOS when toggling bottomTabs visibility through mergeOptions', () => { jest.spyOn(console, 'warn'); - uut.processOptions({ bottomTabs: { visible: false } }, CommandName.MergeOptions); + uut.processOptions(CommandName.MergeOptions, { bottomTabs: { visible: false } }); expect(console.warn).toBeCalledWith( 'toggling bottomTabs visibility is deprecated on iOS. For more information see https://github.com/wix/react-native-navigation/issues/6416', { @@ -726,7 +726,7 @@ describe('navigation options', () => { it('transform searchBar bool to object', () => { const options = { topBar: { searchBar: true as any } }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.topBar.searchBar).toStrictEqual({ visible: true, hideOnScroll: false, @@ -749,7 +749,7 @@ describe('navigation options', () => { searchBarPlaceholder: 'foo', }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.topBar.searchBar).toStrictEqual({ visible: true, hideOnScroll: true, @@ -769,7 +769,7 @@ describe('navigation options', () => { it('transform searchBar bool to object', () => { const options = { topBar: { searchBar: true as any } }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.topBar.searchBar).toStrictEqual({ visible: true, hideOnScroll: false, @@ -792,7 +792,7 @@ describe('navigation options', () => { searchBarPlaceholder: 'foo', }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.topBar.searchBar).toStrictEqual({ visible: true, hideOnScroll: true, @@ -825,7 +825,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.animations!!.push).toStrictEqual({ [view]: { enter: { @@ -861,7 +861,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.animations!!.push).toStrictEqual({ [view]: { exit: { @@ -893,7 +893,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.animations!!.push).toStrictEqual({ enabled: false, waitForRender: true, @@ -919,7 +919,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.animations!!.pop).toStrictEqual({ [view]: { exit: { @@ -955,7 +955,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.animations!!.pop).toStrictEqual({ [view]: { exit: { @@ -987,7 +987,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.animations!!.pop).toStrictEqual({ enabled: false, waitForRender: true, @@ -1010,7 +1010,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.animations!!.setStackRoot).toStrictEqual({ content: { enter: { @@ -1032,7 +1032,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.animations!!.setStackRoot as StackAnimationOptions).toStrictEqual({ enabled: false, waitForRender: true, @@ -1061,7 +1061,7 @@ describe('navigation options', () => { }, }, }; - uut.processOptions(options, CommandName.SetRoot); + uut.processOptions(CommandName.SetRoot, options); expect(options.animations!!.setStackRoot).toStrictEqual({ [view]: { enter: { diff --git a/lib/src/commands/OptionsProcessor.ts b/lib/src/commands/OptionsProcessor.ts index c66dcc01e0b..4dca5df88ba 100644 --- a/lib/src/commands/OptionsProcessor.ts +++ b/lib/src/commands/OptionsProcessor.ts @@ -37,17 +37,19 @@ export class OptionsProcessor { private deprecations: Deprecations ) {} - public processOptions(options: Options, commandName: CommandName, props?: any) { - this.processObject( - options, - clone(options), - (key, parentOptions) => { - this.deprecations.onProcessOptions(key, parentOptions, commandName); - this.deprecations.checkForDeprecatedOptions(parentOptions); - }, - commandName, - props - ); + public processOptions(commandName: CommandName, options?: Options, props?: any) { + if (options) { + this.processObject( + options, + clone(options), + (key, parentOptions) => { + this.deprecations.onProcessOptions(key, parentOptions, commandName); + this.deprecations.checkForDeprecatedOptions(parentOptions); + }, + commandName, + props + ); + } } public processDefaultOptions(options: Options, commandName: CommandName) {