Skip to content

Commit 3e9797c

Browse files
feat: enhance non-fatals support (#461)
* feat: add non fatal api * feat:add-non-fatal-api * feat:add-non-fatal-api * fix: conflict issue * fix: conflict issue * fix: conflict issue * add example app * add example app * add example app * fix: PR comments * Update CHANGELOG.md Co-authored-by: Ahmed Mahmoud <[email protected]> * fix: PR comments * fix: syntax error * fix: syntax error * docs: fix changeLog * docs: fix changeLog * resolve conflict issues * fix:ios * fix:ios * fix:ios * fix:ios --------- Co-authored-by: Ahmed Mahmoud <[email protected]>
1 parent 876f6b6 commit 3e9797c

File tree

28 files changed

+395
-38
lines changed

28 files changed

+395
-38
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ commands:
4747
steps:
4848
- run:
4949
name: Install XCUITest Driver
50-
command: appium driver install xcuitest@7.14.0
50+
command: appium driver install xcuitest@4.35.0
5151
- when:
5252
condition:
5353
equal:

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## [Unreleased](https://github.com/Instabug/Instabug-Flutter/compare/v13.0.0...dev)
44

5+
### Added
6+
- Add support for passing a grouping fingerprint, error level, and user attributes to the `CrashReporting.reportHandledCrash` non-fatals API ([#461](https://github.com/Instabug/Instabug-Flutter/pull/461)).
7+
58
### Changed
69

710
- Bump Instabug iOS SDK to v13.1.0 ([#1227](https://github.com/Instabug/Instabug-Flutter/pull/1227)). [See release notes](https://github.com/Instabug/Instabug-iOS/releases/tag/13.1.0).

android/src/main/java/com/instabug/flutter/modules/CrashReportingApi.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
package com.instabug.flutter.modules;
22

3-
import android.util.Log;
3+
import static com.instabug.crash.CrashReporting.getFingerprintObject;
44

55
import androidx.annotation.NonNull;
6+
import androidx.annotation.Nullable;
67

78
import com.instabug.crash.CrashReporting;
9+
import com.instabug.crash.models.IBGNonFatalException;
810
import com.instabug.flutter.generated.CrashReportingPigeon;
11+
import com.instabug.flutter.util.ArgsRegistry;
912
import com.instabug.flutter.util.Reflection;
1013
import com.instabug.library.Feature;
1114

1215
import org.json.JSONObject;
1316

1417
import java.lang.reflect.Method;
18+
import java.util.Map;
1519

1620
import io.flutter.plugin.common.BinaryMessenger;
1721

@@ -46,4 +50,24 @@ public void send(@NonNull String jsonCrash, @NonNull Boolean isHandled) {
4650
}
4751
}
4852

53+
@Override
54+
public void sendNonFatalError(@NonNull String jsonCrash, @Nullable Map<String, String> userAttributes, @Nullable String fingerprint, @NonNull String nonFatalExceptionLevel) {
55+
try {
56+
Method method = Reflection.getMethod(Class.forName("com.instabug.crash.CrashReporting"), "reportException", JSONObject.class, boolean.class,
57+
Map.class, JSONObject.class, IBGNonFatalException.Level.class);
58+
final JSONObject exceptionObject = new JSONObject(jsonCrash);
59+
60+
JSONObject fingerprintObj = null;
61+
if (fingerprint != null) {
62+
fingerprintObj = getFingerprintObject(fingerprint);
63+
}
64+
IBGNonFatalException.Level nonFatalExceptionLevelType = ArgsRegistry.nonFatalExceptionLevel.get(nonFatalExceptionLevel);
65+
if (method != null) {
66+
method.invoke(null, exceptionObject, true, userAttributes, fingerprintObj, nonFatalExceptionLevelType);
67+
}
68+
} catch (Exception e) {
69+
e.printStackTrace();
70+
}
71+
}
72+
4973
}

android/src/main/java/com/instabug/flutter/util/ArgsRegistry.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import androidx.annotation.NonNull;
44

5+
import com.instabug.crash.models.IBGNonFatalException;
56
import com.instabug.library.LogLevel;
67
import com.instabug.bug.BugReporting;
78
import com.instabug.bug.invocation.Option;
@@ -56,7 +57,12 @@ public T get(Object key) {
5657
put("ColorTheme.light", InstabugColorTheme.InstabugColorThemeLight);
5758
put("ColorTheme.dark", InstabugColorTheme.InstabugColorThemeDark);
5859
}};
59-
60+
public static ArgsMap<IBGNonFatalException.Level> nonFatalExceptionLevel = new ArgsMap<IBGNonFatalException.Level>() {{
61+
put("NonFatalExceptionLevel.critical", IBGNonFatalException.Level.CRITICAL);
62+
put("NonFatalExceptionLevel.error", IBGNonFatalException.Level.ERROR);
63+
put("NonFatalExceptionLevel.warning", IBGNonFatalException.Level.WARNING);
64+
put("NonFatalExceptionLevel.info", IBGNonFatalException.Level.INFO);
65+
}};
6066
public static final ArgsMap<InstabugFloatingButtonEdge> floatingButtonEdges = new ArgsMap<InstabugFloatingButtonEdge>() {{
6167
put("FloatingButtonEdge.left", InstabugFloatingButtonEdge.LEFT);
6268
put("FloatingButtonEdge.right", InstabugFloatingButtonEdge.RIGHT);

android/src/test/java/com/instabug/flutter/CrashReportingApiTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package com.instabug.flutter;
22

3+
import static com.instabug.crash.CrashReporting.getFingerprintObject;
34
import static com.instabug.flutter.util.GlobalMocks.reflected;
45
import static org.mockito.ArgumentMatchers.any;
56
import static org.mockito.ArgumentMatchers.eq;
67
import static org.mockito.Mockito.mock;
78
import static org.mockito.Mockito.mockStatic;
89

910
import com.instabug.crash.CrashReporting;
11+
import com.instabug.crash.models.IBGNonFatalException;
1012
import com.instabug.flutter.generated.CrashReportingPigeon;
1113
import com.instabug.flutter.modules.CrashReportingApi;
14+
import com.instabug.flutter.util.ArgsRegistry;
1215
import com.instabug.flutter.util.GlobalMocks;
1316
import com.instabug.flutter.util.MockReflected;
1417
import com.instabug.library.Feature;
@@ -19,6 +22,9 @@
1922
import org.junit.Test;
2023
import org.mockito.MockedStatic;
2124

25+
import java.util.HashMap;
26+
import java.util.Map;
27+
2228
import io.flutter.plugin.common.BinaryMessenger;
2329

2430

@@ -77,4 +83,19 @@ public void testSend() {
7783

7884
reflected.verify(() -> MockReflected.crashReportException(any(JSONObject.class), eq(isHandled)));
7985
}
86+
87+
@Test
88+
public void testSendNonFatalError() {
89+
String jsonCrash = "{}";
90+
boolean isHandled = true;
91+
String fingerPrint = "test";
92+
93+
Map<String, String> expectedUserAttributes = new HashMap<>();
94+
String level = ArgsRegistry.nonFatalExceptionLevel.keySet().iterator().next();
95+
JSONObject expectedFingerprint = getFingerprintObject(fingerPrint);
96+
IBGNonFatalException.Level expectedLevel = ArgsRegistry.nonFatalExceptionLevel.get(level);
97+
api.sendNonFatalError(jsonCrash, expectedUserAttributes, fingerPrint, level);
98+
99+
reflected.verify(() -> MockReflected.crashReportException(any(JSONObject.class), eq(isHandled), eq(expectedUserAttributes), eq(expectedFingerprint), eq(expectedLevel)));
100+
}
80101
}

android/src/test/java/com/instabug/flutter/util/GlobalMocks.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@
88
import android.net.Uri;
99
import android.util.Log;
1010

11+
import com.instabug.crash.models.IBGNonFatalException;
12+
1113
import org.json.JSONObject;
1214
import org.mockito.MockedStatic;
1315
import org.mockito.invocation.InvocationOnMock;
1416
import org.mockito.stubbing.Answer;
1517

1618
import java.lang.reflect.Method;
19+
import java.util.Map;
1720

1821
public class GlobalMocks {
1922
public static MockedStatic<ThreadManager> threadManager;
@@ -75,6 +78,15 @@ public static void setUp() throws NoSuchMethodException {
7578
JSONObject.class, boolean.class))
7679
.thenReturn(mCrashReportException);
7780

81+
Method mCrashReportNonFatalException = MockReflected.class.getDeclaredMethod("crashReportException", JSONObject.class, boolean.class,
82+
Map.class, JSONObject.class, IBGNonFatalException.Level.class);
83+
mCrashReportNonFatalException.setAccessible(true);
84+
reflection
85+
.when(() -> Reflection.getMethod(Class.forName("com.instabug.crash.CrashReporting"), "reportException",
86+
JSONObject.class, boolean.class,
87+
Map.class, JSONObject.class, IBGNonFatalException.Level.class))
88+
.thenReturn(mCrashReportNonFatalException);
89+
7890
uri = mockStatic(Uri.class);
7991
uri.when(() -> Uri.fromFile(any())).thenReturn(mock(Uri.class));
8092
}

android/src/test/java/com/instabug/flutter/util/MockReflected.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44

55
import androidx.annotation.Nullable;
66

7+
import com.instabug.crash.models.IBGNonFatalException;
8+
79
import org.json.JSONObject;
810

11+
import java.util.Map;
12+
913
/**
1014
* Includes fake implementations of methods called by reflection.
1115
* Used to verify whether or not a private methods was called.
@@ -36,4 +40,6 @@ public static void apmNetworkLog(long requestStartTime, long requestDuration, St
3640
* CrashReporting.reportException
3741
*/
3842
public static void crashReportException(JSONObject exception, boolean isHandled) {}
43+
public static void crashReportException(JSONObject exception, boolean isHandled, Map<String,String> userAttributes, JSONObject fingerPrint, IBGNonFatalException.Level level) {}
44+
3945
}

e2e/BugReportingTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public void ManualInvocation()
113113
[Fact]
114114
public void MultipleScreenshotsInReproSteps()
115115
{
116-
ScrollDown();
116+
ScrollDownLittle();
117117

118118
captain.FindByText("Enter screen name").Tap();
119119
captain.Type("My Screen");

example/ios/Flutter/AppFrameworkInfo.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@
2121
<key>CFBundleVersion</key>
2222
<string>1.0</string>
2323
<key>MinimumOSVersion</key>
24-
<string>11.0</string>
24+
<string>12.0</string>
2525
</dict>
2626
</plist>

example/ios/InstabugTests/CrashReportingApiTests.m

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
#import "Instabug/IBGCrashReporting.h"
55
#import "Instabug/Instabug.h"
66
#import "Util/Instabug+Test.h"
7+
#import "Util/IBGCrashReporting+CP.h"
78

89
@interface CrashReportingApiTests : XCTestCase
910

10-
@property (nonatomic, strong) id mCrashReporting;
11-
@property (nonatomic, strong) id mInstabug;
12-
@property (nonatomic, strong) CrashReportingApi *api;
11+
@property(nonatomic, strong) id mCrashReporting;
12+
@property(nonatomic, strong) id mInstabug;
13+
@property(nonatomic, strong) CrashReportingApi *api;
1314

1415
@end
1516

@@ -24,20 +25,42 @@ - (void)setUp {
2425
- (void)testSetEnabled {
2526
NSNumber *isEnabled = @1;
2627
FlutterError *error;
27-
28+
2829
[self.api setEnabledIsEnabled:isEnabled error:&error];
29-
30+
3031
OCMVerify([self.mCrashReporting setEnabled:YES]);
3132
}
3233

3334
- (void)testSend {
3435
NSString *jsonCrash = @"{}";
3536
NSNumber *isHandled = @0;
3637
FlutterError *error;
37-
38+
3839
[self.api sendJsonCrash:jsonCrash isHandled:isHandled error:&error];
40+
41+
OCMVerify([self.mCrashReporting cp_reportFatalCrashWithStackTrace:@{}]);
42+
}
3943

40-
OCMVerify([self.mInstabug reportCrashWithStackTrace:@{} handled:isHandled]);
44+
45+
- (void)testSendNonFatalErrorJsonCrash {
46+
NSString *jsonCrash = @"{}";
47+
NSString *fingerPrint = @"fingerprint";
48+
NSDictionary *userAttributes = @{@"key": @"value",};
49+
NSString *ibgNonFatalLevel = @"NonFatalExceptionLevel.error";
50+
51+
FlutterError *error;
52+
53+
[self.api sendNonFatalErrorJsonCrash:jsonCrash
54+
userAttributes:userAttributes
55+
fingerprint:fingerPrint
56+
nonFatalExceptionLevel:ibgNonFatalLevel
57+
error:&error];
58+
59+
OCMVerify([self.mCrashReporting cp_reportNonFatalCrashWithStackTrace:@{}
60+
level:IBGNonFatalLevelError
61+
groupingString:fingerPrint
62+
userAttributes:userAttributes
63+
]);
4164
}
4265

4366
@end

0 commit comments

Comments
 (0)