From 80282c6df1e1c486b809306dc9a05330f4c54f4d Mon Sep 17 00:00:00 2001 From: Mattermost Build Date: Wed, 18 Sep 2019 19:04:29 +0200 Subject: [PATCH] Ensure onAppStateChange runs only after GlobalEventHandler is configured (#3271) --- app/init/global_event_handler.js | 15 +++++---- app/init/global_event_handler.test.js | 48 +++++++++++++++++++++++++++ test/setup.js | 3 ++ 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/app/init/global_event_handler.js b/app/init/global_event_handler.js index eed01a277..964351108 100644 --- a/app/init/global_event_handler.js +++ b/app/init/global_event_handler.js @@ -40,7 +40,6 @@ class GlobalEventHandler { EventEmitter.on(General.SERVER_VERSION_CHANGED, this.onServerVersionChanged); EventEmitter.on(General.CONFIG_CHANGED, this.onServerConfigChanged); EventEmitter.on(General.SWITCH_TO_DEFAULT_CHANNEL, this.onSwitchToDefaultChannel); - this.turnOnInAppNotificationHandling(); Dimensions.addEventListener('change', this.onOrientationChange); AppState.addEventListener('change', this.onAppStateChange); Linking.addEventListener('url', this.onDeepLink); @@ -77,6 +76,10 @@ class GlobalEventHandler { this.store = opts.store; this.launchApp = opts.launchApp; + // onAppStateChange may be called by the AppState listener before we + // configure the global event handler so we manually call it here + this.onAppStateChange('active'); + const window = Dimensions.get('window'); this.onOrientationChange({window}); @@ -113,12 +116,12 @@ class GlobalEventHandler { if (this.store) { this.store.dispatch(setAppState(isActive)); - } - if (isActive && emmProvider.previousAppState === 'background') { - this.appActive(); - } else if (isBackground) { - this.appInactive(); + if (isActive && (!emmProvider.enabled || emmProvider.previousAppState === 'background')) { + this.appActive(); + } else if (isBackground) { + this.appInactive(); + } } emmProvider.previousAppState = appState; diff --git a/app/init/global_event_handler.test.js b/app/init/global_event_handler.test.js index ec0fe40f0..7b22e9f5e 100644 --- a/app/init/global_event_handler.test.js +++ b/app/init/global_event_handler.test.js @@ -15,6 +15,12 @@ jest.mock('app/init/credentials', () => ({ removeAppCredentials: jest.fn(), })); +jest.mock('app/utils/error_handling', () => ({ + default: { + initializeErrorHandling: jest.fn(), + }, +})); + jest.mock('react-native-notifications', () => ({ addEventListener: jest.fn(), cancelAllLocalNotifications: jest.fn(), @@ -35,4 +41,46 @@ describe('GlobalEventHandler', () => { await GlobalEventHandler.onLogout(); expect(clearNotifications).toHaveBeenCalled(); }); + + it('should call onAppStateChange after configuration', () => { + const onAppStateChange = jest.spyOn(GlobalEventHandler, 'onAppStateChange'); + + GlobalEventHandler.configure({store}); + expect(GlobalEventHandler.store).not.toBeNull(); + expect(onAppStateChange).toHaveBeenCalledWith('active'); + }); + + it('should handle onAppStateChange to active if the store set', () => { + const appActive = jest.spyOn(GlobalEventHandler, 'appActive'); + const appInactive = jest.spyOn(GlobalEventHandler, 'appInactive'); + expect(GlobalEventHandler.store).not.toBeNull(); + + GlobalEventHandler.onAppStateChange('active'); + expect(appActive).toHaveBeenCalled(); + expect(appInactive).not.toHaveBeenCalled(); + }); + + it('should handle onAppStateChange to background if the store set', () => { + const appActive = jest.spyOn(GlobalEventHandler, 'appActive'); + const appInactive = jest.spyOn(GlobalEventHandler, 'appInactive'); + expect(GlobalEventHandler.store).not.toBeNull(); + + GlobalEventHandler.onAppStateChange('background'); + expect(appActive).not.toHaveBeenCalled(); + expect(appInactive).toHaveBeenCalled(); + }); + + it('should not handle onAppStateChange if the store is not set', () => { + const appActive = jest.spyOn(GlobalEventHandler, 'appActive'); + const appInactive = jest.spyOn(GlobalEventHandler, 'appInactive'); + GlobalEventHandler.store = null; + + GlobalEventHandler.onAppStateChange('active'); + expect(appActive).not.toHaveBeenCalled(); + expect(appInactive).not.toHaveBeenCalled(); + + GlobalEventHandler.onAppStateChange('background'); + expect(appActive).not.toHaveBeenCalled(); + expect(appInactive).not.toHaveBeenCalled(); + }); }); diff --git a/test/setup.js b/test/setup.js index 795986636..48a6ea4e4 100644 --- a/test/setup.js +++ b/test/setup.js @@ -46,6 +46,9 @@ jest.mock('NativeModules', () => { RNReactNativeHapticFeedback: { trigger: jest.fn(), }, + StatusBarManager: { + getHeight: jest.fn(), + }, }; }); jest.mock('NativeEventEmitter');