Skip to content

Commit 52e3365

Browse files
alyezzAli AbdelfattahAliAbdelfattah
authored
Feature - Repro Steps (#411)
* Adding navigation listener * repro steps apis * iOS APIs * changed to avoid duplicate screens * Add initial screen * Chaning repro steps state api to new implementation * Adds unit tests * danger changelog * updates Readme * Adds RN tests * Update build.gradle * Update RNInstabugReactnativeModule.java * Revert "Update RNInstabugReactnativeModule.java" This reverts commit 323a8cf. * Revert "Update build.gradle" This reverts commit a179528. * Update build.gradle * Call setCrossPlatform Also remove the repro steps disabling statement * Update build.gradle * Fix android repro steps issues * Add iOS spanshot * Adds new iOS platform API * remove old platform API * Revert "Add iOS spanshot" This reverts commit 4eaa2f0. * Revert "Adds new iOS platform API" This reverts commit b1e57d0. * Revert "remove old platform API" This reverts commit dd47150. * Adds new iOS snapshot * Adds new iOS APIs * Adds duplicate initial screen fix * Adding android snapshot * Add native snapshots * rename variable to be more descriptive * Adjusting tests Co-authored-by: Ali Abdelfattah <[email protected]> Co-authored-by: Ali Abdelfattah <[email protected]>
1 parent 359f7ca commit 52e3365

File tree

62 files changed

+415
-186
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+415
-186
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
* Updates native iOS SDK to v8.7.2
5151
* Fixes `Warning: Require cycle` warnings.
5252

53+
5354
## v8.7.0 (2019-09-19)
5455

5556
* Updates native SDKs to v8.7

README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,36 @@ import { NetworkLogger } from 'instabug-reactnative';
197197
NetworkLogger.setEnabled(false);
198198
```
199199
200+
## Repro Steps
201+
202+
Instabug Repro Steps are enabled by default. It captures a screenshot of each screen the user navigates to. These screens are attached to the BugReport when sent.
203+
204+
We support the 2 most popular React Native navigation libraries:
205+
206+
* **react-navigation**
207+
1) Set the `onNavigationStateChange` to `Instabug.onNavigationStateChange` in your App wrapper as follows:
208+
209+
```javascript
210+
export default () => (
211+
<App
212+
onNavigationStateChange={ Instabug.onNavigationStateChange } />
213+
);
214+
```
215+
216+
* **react-native-navigation**
217+
1) Register `Instabug.componentDidAppearListener` listener using:
218+
219+
```javascript
220+
Navigation.events().registerComponentDidAppearListener( Instabug.componentDidAppearListener );
221+
```
222+
223+
You can disable Repro Steps using the following API:
224+
```javascript
225+
Instabug.setReproStepsMode(Instabug.reproStepsMode.disabled);
226+
```
227+
200228
## Features that are not supported yet
201-
- Repro Steps
229+
202230
- Push Notification Support for In-App Messaging
203231
204232
## Documentation

__tests__/index.spec.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ describe('Instabug Module', () => {
6767
const callPrivateApi = sinon.spy(NativeModules.Instabug, 'callPrivateApi');
6868
const sendHandledJSCrash = sinon.spy(NativeModules.Instabug, 'sendHandledJSCrash');
6969
const sendJSCrash = sinon.spy(NativeModules.Instabug, 'sendJSCrash');
70+
const reportScreenChange = sinon.spy(NativeModules.Instabug, 'reportScreenChange');
7071

7172
beforeEach(() => {
7273
startWithToken.resetHistory();
@@ -86,6 +87,22 @@ describe('Instabug Module', () => {
8687

8788
});
8889

90+
it('componentDidAppearListener should call the native method reportScreenChange', () => {
91+
const screenName = "some-screen";
92+
var obj = {componentId: "1",
93+
componentName: screenName,
94+
"passProps": "screenName"};
95+
Instabug.componentDidAppearListener(obj);
96+
expect(reportScreenChange.calledOnceWithExactly(screenName)).toBe(true);
97+
});
98+
99+
it('onNavigationStateChange should call the native method reportScreenChange', () => {
100+
const screenName = "some-screen";
101+
InstabugUtils.getActiveRouteName.mockImplementation((screenName) => screenName);
102+
Instabug.onNavigationStateChange(screenName, screenName, screenName);
103+
expect(reportScreenChange.calledOnceWithExactly(screenName)).toBe(true);
104+
});
105+
89106
it('should call the native method startWithToken', () => {
90107

91108
Platform.OS = 'ios';

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ android {
2929
dependencies {
3030
implementation 'com.android.support:multidex:1.0.3'
3131
implementation 'com.facebook.react:react-native:+'
32-
api('com.instabug.library:instabug:9.1.0.0') {
32+
api('com.instabug.library:instabug:9.1.6.0') {
3333
exclude group: 'com.android.support:appcompat-v7'
3434
}
3535
testImplementation 'org.mockito:mockito-core:1.10.19'

android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import android.annotation.SuppressLint;
44
import android.app.Application;
5+
import android.graphics.Bitmap;
56
import android.net.Uri;
67
import android.os.Handler;
78
import android.os.Looper;
@@ -1682,7 +1683,7 @@ public void run() {
16821683
});
16831684
}
16841685

1685-
/**
1686+
/**
16861687
* Sets whether user steps tracking is visual, non visual or disabled.
16871688
*
16881689
* @param reproStepsMode A string to set user steps tracking to be
@@ -1694,17 +1695,7 @@ public void setReproStepsMode(final String reproStepsMode) {
16941695
@Override
16951696
public void run() {
16961697
try {
1697-
switch (reproStepsMode) {
1698-
case ENABLED_WITH_NO_SCREENSHOTS:
1699-
Instabug.setReproStepsState(State.ENABLED_WITH_NO_SCREENSHOTS);
1700-
break;
1701-
case DISABLED:
1702-
Instabug.setReproStepsState(State.DISABLED);
1703-
break;
1704-
default:
1705-
Instabug.setReproStepsState(State.ENABLED);
1706-
}
1707-
1698+
Instabug.setReproStepsState( ArgsRegistry.getDeserializedValue(reproStepsMode, State.class));
17081699
} catch (Exception e) {
17091700
e.printStackTrace();
17101701
}
@@ -2247,6 +2238,29 @@ public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
22472238
});
22482239
}
22492240

2241+
/**
2242+
* Reports that the screen has been changed (Repro Steps) the screen sent to this method will be the 'current view' on the dashboard
2243+
*
2244+
* @param screenName string containing the screen name
2245+
*
2246+
*/
2247+
@ReactMethod
2248+
public void reportScreenChange(final String screenName) {
2249+
MainThreadHandler.runOnMainThread(new Runnable() {
2250+
@Override
2251+
public void run() {
2252+
try {
2253+
Method method = getMethod(Class.forName("com.instabug.library.Instabug"), "reportScreenChange", Bitmap.class, String.class);
2254+
if (method != null) {
2255+
method.invoke(null , null, screenName);
2256+
}
2257+
} catch (Exception e) {
2258+
e.printStackTrace();
2259+
}
2260+
}
2261+
});
2262+
}
2263+
22502264
private InstabugCustomTextPlaceHolder.Key getStringToKeyConstant(String key) {
22512265
switch (key) {
22522266
case SHAKE_HINT:

android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativePackage.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
package com.instabug.reactlibrary;
22

33
import android.app.Application;
4+
import android.util.Log;
45

56
import com.facebook.react.ReactPackage;
67
import com.facebook.react.bridge.NativeModule;
78
import com.facebook.react.bridge.ReactApplicationContext;
89
import com.facebook.react.uimanager.ViewManager;
910
import com.instabug.bug.BugReporting;
1011
import com.instabug.crash.CrashReporting;
12+
import com.instabug.library.Platform;
1113
import com.instabug.library.Feature;
1214
import com.instabug.library.Instabug;
1315
import com.instabug.library.InstabugColorTheme;
1416
import com.instabug.library.invocation.InstabugInvocationEvent;
1517
import com.instabug.library.invocation.util.InstabugFloatingButtonEdge;
1618
import com.instabug.library.visualusersteps.State;
1719
import com.instabug.reactlibrary.utils.InstabugUtil;
20+
import com.instabug.reactlibrary.utils.MainThreadHandler;
1821

1922
import android.graphics.Color;
2023

@@ -47,10 +50,10 @@ public RNInstabugReactnativePackage(String androidApplicationToken, Application
4750
this.parseInvocationEvent(invocationEventValues);
4851

4952
setBaseUrlForDeprecationLogs();
50-
53+
setCrossPlatform();
54+
5155
new Instabug.Builder(this.androidApplication, this.mAndroidApplicationToken)
5256
.setInvocationEvents(this.invocationEvents.toArray(new InstabugInvocationEvent[0]))
53-
.setReproStepsState(State.DISABLED)
5457
.build();
5558
if (crashReportingEnabled)
5659
CrashReporting.setState(Feature.State.ENABLED);
@@ -96,6 +99,20 @@ private void parseInvocationEvent(String[] invocationEventValues) {
9699
}
97100
}
98101

102+
private void setCrossPlatform() {
103+
try {
104+
Method method = InstabugUtil.getMethod(Class.forName("com.instabug.library.Instabug"), "setCrossPlatform", int.class);
105+
if (method != null) {
106+
Log.i("IB-CP-Bridge", "invoking setCrossPlatform with platform: " + Platform.RN);
107+
method.invoke(null, Platform.RN);
108+
} else {
109+
Log.e("IB-CP-Bridge", "setCrossPlatform was not found by reflection");
110+
}
111+
} catch (Exception e) {
112+
e.printStackTrace();
113+
}
114+
}
115+
99116
private void setBaseUrlForDeprecationLogs() {
100117
try {
101118
Method method = InstabugUtil.getMethod(Class.forName("com.instabug.library.util.InstabugDeprecationLogger"), "setBaseUrl", String.class);

android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ public Boolean answer(InvocationOnMock invocation) throws Throwable {
339339
}
340340

341341
@Test
342-
public void givenArg$setReproStepsMode_whenQuery_thenShouldCallNativeApiWithArg() {
342+
public void givenArg$setReproStepsMode_whenQuery_thenShouldCallNativeApiWithArg() throws Exception {
343343
// given
344344
PowerMockito.mockStatic(Instabug.class);
345345
Map<String, Object> args = new HashMap<>();
@@ -350,9 +350,9 @@ public Boolean answer(InvocationOnMock invocation) throws Throwable {
350350
rnModule.setReproStepsMode(key);
351351
}
352352
// then
353-
PowerMockito.verifyStatic(VerificationModeFactory.times(1));
354353
for (String key : keysArray) {
355354
State mode = (State) args.get(key);
355+
PowerMockito.verifyStatic(VerificationModeFactory.times(1));
356356
Instabug.setReproStepsState(mode);
357357
}
358358

@@ -547,4 +547,15 @@ public Boolean answer(InvocationOnMock invocation) throws Throwable {
547547
}
548548
}
549549

550+
@Test
551+
public void givenString$reportScreenChange_whenQuery_thenShouldCallNativeApiWithString() throws Exception {
552+
// given
553+
PowerMockito.mockStatic(Instabug.class);
554+
rnModule.reportScreenChange("screen");
555+
556+
// then
557+
PowerMockito.verifyPrivate(Instabug.class, VerificationModeFactory.times(1)).invoke("reportScreenChange", null,"screen");
558+
559+
}
560+
550561
}

index.js

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ import NetworkLogger from './modules/NetworkLogger';
2020
InstabugUtils.captureJsErrors();
2121
NetworkLogger.setEnabled(true);
2222

23+
var _currentScreen = null;
24+
var _lastScreen = null;
25+
var _isFirstScreen = false;
26+
const firstScreen = "Initial Screen";
2327
/**
2428
* Instabug
2529
* @exports Instabug
@@ -53,7 +57,17 @@ const InstabugModule = {
5357
* the SDK's UI.
5458
*/
5559
start: function(token, invocationEvent) {
56-
if (Platform.OS === 'ios') Instabug.startWithToken(token, invocationEvent);
60+
if (Platform.OS === 'ios') {
61+
Instabug.startWithToken(token, invocationEvent);
62+
}
63+
_isFirstScreen = true;
64+
_currentScreen = firstScreen;
65+
setTimeout(function() {
66+
if (_currentScreen == firstScreen) {
67+
Instabug.reportScreenChange(firstScreen);
68+
_currentScreen = null;
69+
}
70+
}, 1000);
5771
},
5872

5973
/**
@@ -774,6 +788,38 @@ const InstabugModule = {
774788
Instabug.callPrivateApi(apiName, param);
775789
},
776790

791+
onNavigationStateChange(prevState, currentState, action) {
792+
const currentScreen = InstabugUtils.getActiveRouteName(currentState);
793+
const prevScreen = InstabugUtils.getActiveRouteName(prevState);
794+
795+
if (prevScreen !== currentScreen) {
796+
if (_currentScreen != null && _currentScreen != firstScreen) {
797+
Instabug.reportScreenChange(_currentScreen);
798+
_currentScreen = null;
799+
}
800+
_currentScreen = currentScreen;
801+
setTimeout(function() {
802+
if (_currentScreen == currentScreen) {
803+
Instabug.reportScreenChange(currentScreen);
804+
_currentScreen = null;
805+
}
806+
}, 1000);
807+
}
808+
},
809+
810+
componentDidAppearListener({componentId, componentName, passProps}) {
811+
if (_isFirstScreen) {
812+
_lastScreen = componentName;
813+
_isFirstScreen = false;
814+
return;
815+
}
816+
if (_lastScreen != componentName) {
817+
Instabug.reportScreenChange(componentName);
818+
_lastScreen = componentName;
819+
}
820+
},
821+
822+
777823
/**
778824
* The event used to invoke the feedback form
779825
* @readonly

ios/Instabug.framework/Headers/IBGBugReporting.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
Copyright: (c) 2013-2019 by Instabug, Inc., all rights reserved.
77
8-
Version: 9.1
8+
Version: 9.1.6
99
*/
1010

1111
#import <Foundation/Foundation.h>

ios/Instabug.framework/Headers/IBGChats.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
Copyright: (c) 2013-2019 by Instabug, Inc., all rights reserved.
77
8-
Version: 9.1
8+
Version: 9.1.6
99
*/
1010

1111
#import <Foundation/Foundation.h>

0 commit comments

Comments
 (0)