diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e27d7641..f6fb6ab8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ - Bump Instabug iOS SDK to v12.5.0 ([#1085](https://github.com/Instabug/Instabug-React-Native/pull/1085)). [See release notes](https://github.com/instabug/instabug-ios/releases/tag/12.5.0). - Bump Instabug Android SDK to v12.5.1 ([#1088](https://github.com/Instabug/Instabug-React-Native/pull/1085)). See release notes for [v12.5.0](https://github.com/Instabug/android/releases/tag/v12.5.0) and [v12.5.1](https://github.com/Instabug/android/releases/tag/v12.5.1). +### Fixed + +- Fix a delay issue in reporting the 'Current View' that resulted in displaying outdated values ([#1080](https://github.com/Instabug/Instabug-React-Native/pull/1080)). + ## [12.4.0](https://github.com/Instabug/Instabug-React-Native/compare/v12.2.0...v12.4.0) (December 7, 2023) ### Changed diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index d412c62a6..46814e53e 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -916,6 +916,29 @@ public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) { }); } + /** + * Reports that the screen name been changed (Current View). + * + * @param screenName string containing the screen name + * + */ + @ReactMethod + public void reportCurrentViewChange(final String screenName) { + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + Method method = getMethod(Class.forName("com.instabug.library.Instabug"), "reportCurrentViewChange", String.class); + if (method != null) { + method.invoke(null, screenName); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + /** * Reports that the screen has been changed (Repro Steps) the screen sent to this method will be the 'current view' on the dashboard * diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java index 1426f9a1f..148d71d51 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java @@ -482,6 +482,18 @@ public void tearDown() { } } + @Test + public void givenString$reportCurrentViewChange_whenQuery_thenShouldCallNativeApiWithString() throws Exception { + // when + rnModule.reportCurrentViewChange("screen"); + Method privateStringMethod = getMethod(Class.forName("com.instabug.library.Instabug"), "reportCurrentViewChange", String.class); + privateStringMethod.setAccessible(true); + + // then + verify(Instabug.class, VerificationModeFactory.times(1)); + privateStringMethod.invoke("reportCurrentViewChange","screen"); + } + @Test public void givenString$reportScreenChange_whenQuery_thenShouldCallNativeApiWithString() throws Exception { // when diff --git a/src/modules/Instabug.ts b/src/modules/Instabug.ts index 0d1c4092a..399464f0d 100644 --- a/src/modules/Instabug.ts +++ b/src/modules/Instabug.ts @@ -34,6 +34,23 @@ export const setEnabled = (isEnabled: boolean) => { NativeInstabug.setEnabled(isEnabled); }; +/** + * Reports that the screen name been changed (Current View field on dashboard). + * only for android. + * + * Normally reportScreenChange handles taking a screenshot for reproduction + * steps and the Current View field on the dashboard. But we've faced issues + * in android where we needed to separate them, that's why we only call it + * for android. + * + * @param screenName string containing the screen name + */ +function reportCurrentViewForAndroid(screenName: string | null) { + if (Platform.OS === 'android' && screenName != null) { + NativeInstabug.reportCurrentViewChange(screenName); + } +} + /** * Initializes the SDK. * This is the main SDK method that does all the magic. This is the only @@ -55,6 +72,7 @@ export const init = (config: InstabugConfig) => { _isFirstScreen = true; _currentScreen = firstScreen; + reportCurrentViewForAndroid(firstScreen); setTimeout(() => { if (_currentScreen === firstScreen) { NativeInstabug.reportScreenChange(firstScreen); @@ -458,6 +476,7 @@ export const onNavigationStateChange = ( const prevScreen = InstabugUtils.getActiveRouteName(prevState); if (prevScreen !== currentScreen) { + reportCurrentViewForAndroid(currentScreen); if (_currentScreen != null && _currentScreen !== firstScreen) { NativeInstabug.reportScreenChange(_currentScreen); _currentScreen = null; @@ -478,6 +497,7 @@ export const onStateChange = (state?: NavigationStateV5) => { } const currentScreen = InstabugUtils.getFullRoute(state); + reportCurrentViewForAndroid(currentScreen); if (_currentScreen !== null && _currentScreen !== firstScreen) { NativeInstabug.reportScreenChange(_currentScreen); _currentScreen = null; diff --git a/src/native/NativeInstabug.ts b/src/native/NativeInstabug.ts index 23d41e342..14b306554 100644 --- a/src/native/NativeInstabug.ts +++ b/src/native/NativeInstabug.ts @@ -44,6 +44,7 @@ export interface InstabugNativeModule extends NativeModule { ): void; setTrackUserSteps(isEnabled: boolean): void; reportScreenChange(firstScreen: string): void; + reportCurrentViewChange(screenName: string): void; addPrivateView(nativeTag: number | null): void; removePrivateView(nativeTag: number | null): void; diff --git a/test/mocks/mockInstabug.ts b/test/mocks/mockInstabug.ts index f7d975eee..6353cf64c 100644 --- a/test/mocks/mockInstabug.ts +++ b/test/mocks/mockInstabug.ts @@ -47,6 +47,7 @@ const mockInstabug: InstabugNativeModule = { show: jest.fn(), setPreSendingHandler: jest.fn(), reportScreenChange: jest.fn(), + reportCurrentViewChange: jest.fn(), addExperiments: jest.fn(), removeExperiments: jest.fn(), clearAllExperiments: jest.fn(), diff --git a/test/modules/Instabug.spec.ts b/test/modules/Instabug.spec.ts index 2d928253a..06f0e770a 100644 --- a/test/modules/Instabug.spec.ts +++ b/test/modules/Instabug.spec.ts @@ -109,6 +109,33 @@ describe('Instabug Module', () => { }); }); + // eslint-disable-next-line jest/no-disabled-tests + it.skip('onNavigationStateChange should call the native method reportCurrentViewChange on Android Platform', async () => { + Platform.OS = 'android'; + InstabugUtils.getActiveRouteName = jest.fn().mockImplementation((screenName) => screenName); + + // @ts-ignore + Instabug.onNavigationStateChange('home', 'settings'); + + await waitForExpect(() => { + expect(NativeInstabug.reportCurrentViewChange).toBeCalledTimes(1); + expect(NativeInstabug.reportCurrentViewChange).toBeCalledWith('settings'); + }); + }); + + // eslint-disable-next-line jest/no-disabled-tests + it.skip('onNavigationStateChange should not call the native method reportCurrentViewChange on iOS Platform', async () => { + Platform.OS = 'ios'; + InstabugUtils.getActiveRouteName = jest.fn().mockImplementation((screenName) => screenName); + + // @ts-ignore + Instabug.onNavigationStateChange('home', 'settings'); + + await waitForExpect(() => { + expect(NativeInstabug.reportCurrentViewChange).not.toBeCalled(); + }); + }); + it('onNavigationStateChange should not call the native method reportScreenChange if screen is the same', (done) => { InstabugUtils.getActiveRouteName = jest.fn().mockImplementation((screenName) => screenName); @@ -122,7 +149,20 @@ describe('Instabug Module', () => { }, 1500); }); - it('onNavigationStateChange should call the native method reportScreenChange immediatly if _currentScreen is set', async () => { + it('onNavigationStateChange should not call the native method reportCurrentViewChange if screen is the same', (done) => { + InstabugUtils.getActiveRouteName = jest.fn().mockImplementation((screenName) => screenName); + + // @ts-ignore + Instabug.onNavigationStateChange('home', 'home'); + + // Wait for 1.5s as reportScreenChange is delayed by 1s + setTimeout(() => { + expect(NativeInstabug.reportCurrentViewChange).not.toBeCalled(); + done(); + }, 1500); + }); + + it('onNavigationStateChange should call the native method reportScreenChange immediately if _currentScreen is set', async () => { InstabugUtils.getActiveRouteName = jest.fn().mockImplementation((screenName) => screenName); // sets _currentScreen and waits for 1s as _currentScreen is null @@ -150,6 +190,31 @@ describe('Instabug Module', () => { }); }); + // eslint-disable-next-line jest/no-disabled-tests + it.skip('onStateChange should call the native method reportCurrentViewChange on Android Platform', async () => { + Platform.OS = 'android'; + const state = { routes: [{ name: 'ScreenName' }], index: 0 }; + // @ts-ignore + Instabug.onStateChange(state); + + await waitForExpect(() => { + expect(NativeInstabug.reportCurrentViewChange).toBeCalledTimes(1); + expect(NativeInstabug.reportCurrentViewChange).toBeCalledWith('ScreenName'); + }); + }); + + // eslint-disable-next-line jest/no-disabled-tests + it.skip('onStateChange should not call the native method reportCurrentViewChange on iOS Platform', async () => { + Platform.OS = 'ios'; + const state = { routes: [{ name: 'ScreenName' }], index: 0 }; + // @ts-ignore + Instabug.onStateChange(state); + + await waitForExpect(() => { + expect(NativeInstabug.reportCurrentViewChange).not.toBeCalled(); + }); + }); + it('onStateChange should call the native method reportScreenChange immediately if _currentScreen is set', async () => { // sets _currentScreen and waits for 1s as _currentScreen is null const state = { routes: [{ name: 'ScreenName' }], index: 0 }; @@ -195,6 +260,31 @@ describe('Instabug Module', () => { }); }); + it('init should call reportCurrentViewChange on Android Platform', async () => { + Platform.OS = 'android'; + Instabug.init({ + token: 'some-token', + invocationEvents: [InvocationEvent.none], + }); + + await waitForExpect(() => { + expect(NativeInstabug.reportCurrentViewChange).toBeCalledTimes(1); + expect(NativeInstabug.reportCurrentViewChange).toBeCalledWith('Initial Screen'); + }); + }); + + it('init should not call reportCurrentViewChange on ios Platform', async () => { + Platform.OS = 'ios'; + Instabug.init({ + token: 'some-token', + invocationEvents: [InvocationEvent.none], + }); + + await waitForExpect(() => { + expect(NativeInstabug.reportCurrentViewChange).not.toBeCalled(); + }); + }); + it('should call the native method setUserData', () => { const userData = 'userData'; Instabug.setUserData(userData);