From 5185cb6d0ad55154b36434309952534189aaf3e0 Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Thu, 25 Apr 2024 23:59:08 +0200 Subject: [PATCH 01/20] add non fatal api --- android/src/main/AndroidManifest.xml | 2 +- .../instabug/reactlibrary/ArgsRegistry.java | 9 ++ .../RNInstabugCrashReportingModule.java | 84 ++++++++----- .../RNInstabugCrashReportingModuleTest.java | 25 +++- .../reactlibrary/util/MockReflected.java | 8 ++ .../InstabugExample.xcodeproj/project.pbxproj | 10 ++ .../ios/InstabugTests/InstabugAPMTests.m | 24 ---- .../InstabugCrashReportingTests.m | 24 ++++ examples/default/ios/Podfile | 2 + examples/default/ios/Podfile.lock | 14 ++- .../src/screens/CrashReportingScreen.tsx | 119 +++++++++++++++++- ios/RNInstabug/ArgsRegistry.h | 3 + ios/RNInstabug/ArgsRegistry.m | 12 ++ ios/RNInstabug/InstabugAPMBridge.m | 12 -- ios/RNInstabug/InstabugBugReportingBridge.m | 1 - ios/RNInstabug/InstabugCrashReportingBridge.h | 11 +- ios/RNInstabug/InstabugCrashReportingBridge.m | 18 +-- ios/RNInstabug/RCTConvert+InstabugEnums.m | 7 ++ ios/native.rb | 2 +- src/modules/CrashReporting.ts | 19 ++- src/native/NativeConstants.ts | 9 +- src/native/NativeCrashReporting.ts | 8 +- src/utils/Enums.ts | 10 ++ src/utils/InstabugUtils.ts | 62 ++++++++- src/utils/UnhandledRejectionTracking.ts | 2 +- test/mocks/mockInstabugUtils.ts | 1 + test/modules/CrashReporting.spec.ts | 13 +- test/utils/InstabugUtils.spec.ts | 2 +- 28 files changed, 411 insertions(+), 102 deletions(-) diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 44ad85bcd..9af27fbd3 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - diff --git a/android/src/main/java/com/instabug/reactlibrary/ArgsRegistry.java b/android/src/main/java/com/instabug/reactlibrary/ArgsRegistry.java index 522bd0dd0..afe829360 100644 --- a/android/src/main/java/com/instabug/reactlibrary/ArgsRegistry.java +++ b/android/src/main/java/com/instabug/reactlibrary/ArgsRegistry.java @@ -4,6 +4,7 @@ import com.instabug.bug.BugReporting; import com.instabug.bug.invocation.Option; +import com.instabug.crash.models.IBGNonFatalException; import com.instabug.featuresrequest.ActionType; import com.instabug.library.InstabugColorTheme; import com.instabug.library.InstabugCustomTextPlaceHolder.Key; @@ -54,11 +55,19 @@ static Map getAll() { putAll(extendedBugReportStates); putAll(reproModes); putAll(sdkLogLevels); + putAll(nonFatalExceptionLevel); putAll(locales); putAll(placeholders); }}; } + public static ArgsMap nonFatalExceptionLevel = new ArgsMap() {{ + put("nonFatalErrorTypeCritical", IBGNonFatalException.Level.CRITICAL); + put("nonFatalErrorTypeError", IBGNonFatalException.Level.ERROR); + put("nonFatalErrorTypeWarning", IBGNonFatalException.Level.WARNING); + put("nonFatalErrorTypeInfo", IBGNonFatalException.Level.INFO); + }}; + static ArgsMap invocationEvents = new ArgsMap() {{ put("invocationEventNone", InstabugInvocationEvent.NONE); put("invocationEventShake", InstabugInvocationEvent.SHAKE); diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugCrashReportingModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugCrashReportingModule.java index 4bd84c0bd..3137afc75 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugCrashReportingModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugCrashReportingModule.java @@ -2,11 +2,15 @@ import static com.instabug.reactlibrary.utils.InstabugUtil.getMethod; +import androidx.annotation.NonNull; + import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableMap; import com.instabug.crash.CrashReporting; +import com.instabug.crash.models.IBGNonFatalException; import com.instabug.library.Feature; import com.instabug.reactlibrary.utils.MainThreadHandler; @@ -14,6 +18,8 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -57,8 +63,8 @@ public void run() { * Send unhandled JS error object * * @param exceptionObject Exception object to be sent to Instabug's servers - * @param promise This makes sure that the RN side crashes the app only after the Android SDK - * finishes processing/handling the crash. + * @param promise This makes sure that the RN side crashes the app only after the Android SDK + * finishes processing/handling the crash. */ @ReactMethod public void sendJSCrash(final String exceptionObject, final Promise promise) { @@ -79,41 +85,61 @@ public void run() { * Send handled JS error object * * @param exceptionObject Exception object to be sent to Instabug's servers + * @param userAttributes (Optional) extra user attributes attached to the crash + * @param fingerprint (Optional) key used to customize how crashes are grouped together + * @param levelType different severity levels for errors */ @ReactMethod - public void sendHandledJSCrash(final String exceptionObject) { + public void sendHandledJSCrash(final String exceptionObject, @androidx.annotation.Nullable ReadableMap userAttributes, @androidx.annotation.Nullable String fingerprint, String levelType) { try { JSONObject jsonObject = new JSONObject(exceptionObject); - sendJSCrashByReflection(jsonObject, true, null); - } catch (Exception e) { + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + Method method = getMethod(Class.forName("com.instabug.crash.CrashReporting"), "reportException", JSONObject.class, boolean.class, + Map.class, JSONObject.class, IBGNonFatalException.Level.class); + if (method != null) { + IBGNonFatalException.Level nonFatalExceptionLevelType = ArgsRegistry.nonFatalExceptionLevel.getOrDefault(levelType, IBGNonFatalException.Level.ERROR); + method.invoke(null, jsonObject, true, userAttributes == null ? null : userAttributes.toHashMap(), fingerprint == null ? null : CrashReporting.getFingerprintObject(fingerprint), nonFatalExceptionLevelType); + + RNInstabugReactnativeModule.clearCurrentReport(); + } + } catch (ClassNotFoundException | IllegalAccessException | + InvocationTargetException e) { + e.printStackTrace(); + } + } + }); + } catch (Throwable e) { e.printStackTrace(); } } - private void sendJSCrashByReflection(final JSONObject exceptionObject, final boolean isHandled, @Nullable final Runnable onComplete) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - Method method = getMethod(Class.forName("com.instabug.crash.CrashReporting"), "reportException", JSONObject.class, boolean.class); - if (method != null) { - method.invoke(null, exceptionObject, isHandled); - RNInstabugReactnativeModule.clearCurrentReport(); - } - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } finally { - if (onComplete != null) { - onComplete.run(); - } - } - } - }); - } + private void sendJSCrashByReflection(final JSONObject exceptionObject, final boolean isHandled, @Nullable final Runnable onComplete) { + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + Method method = getMethod(Class.forName("com.instabug.crash.CrashReporting"), "reportException", JSONObject.class, boolean.class); + if (method != null) { + method.invoke(null, exceptionObject, isHandled); + RNInstabugReactnativeModule.clearCurrentReport(); + } + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } finally { + if (onComplete != null) { + onComplete.run(); + } + } + } + }); + } /** * Enables and disables capturing native C++ NDK crash reporting. diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugCrashReportingModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugCrashReportingModuleTest.java index fd2a9b58e..2f2fd50ff 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugCrashReportingModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugCrashReportingModuleTest.java @@ -1,16 +1,23 @@ package com.instabug.reactlibrary; +import static com.instabug.crash.CrashReporting.getFingerprintObject; +import static com.instabug.reactlibrary.util.GlobalMocks.reflected; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; import android.os.Looper; +import com.facebook.react.bridge.ReadableMap; import com.instabug.crash.CrashReporting; +import com.instabug.crash.models.IBGNonFatalException; import com.instabug.library.Feature; import com.instabug.reactlibrary.util.GlobalMocks; +import com.instabug.reactlibrary.util.MockReflected; import com.instabug.reactlibrary.utils.MainThreadHandler; +import org.json.JSONObject; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -19,6 +26,9 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import java.util.HashMap; +import java.util.Map; + public class RNInstabugCrashReportingModuleTest { private final RNInstabugCrashReportingModule rnModule = new RNInstabugCrashReportingModule(null); @@ -67,7 +77,7 @@ public void testSetNDKCrashesEnabledGivenTrue() { // when rnModule.setNDKCrashesEnabled(true); -//then + //then mockCrashReporting.verify(() -> CrashReporting.setNDKCrashesState(Feature.State.ENABLED)); } @@ -80,6 +90,19 @@ public void testSetNDKCrashesEnabledGivenFalse() { mockCrashReporting.verify(() -> CrashReporting.setNDKCrashesState(Feature.State.DISABLED)); } + @Test + public void testSendNonFatalError() { + String jsonCrash = "{}"; + boolean isHandled = true; + String fingerPrint = "test"; + String level = ArgsRegistry.nonFatalExceptionLevel.keySet().iterator().next(); + JSONObject finger = getFingerprintObject(fingerPrint); + IBGNonFatalException.Level lev = ArgsRegistry.nonFatalExceptionLevel.get(level); + rnModule.sendHandledJSCrash(jsonCrash, null, fingerPrint, level); + + mockCrashReporting.verify(() -> MockReflected.crashReportException(any(JSONObject.class), eq(isHandled), eq(null), eq(finger), eq(lev))); + } + @Test public void givenString$sendHandledJSCrash_whenQuery_thenShouldCallNativeApiWithArgs() throws Exception { // JSONObject json = mock(JSONObject.class); diff --git a/android/src/test/java/com/instabug/reactlibrary/util/MockReflected.java b/android/src/test/java/com/instabug/reactlibrary/util/MockReflected.java index bfe886b96..185f4bd76 100644 --- a/android/src/test/java/com/instabug/reactlibrary/util/MockReflected.java +++ b/android/src/test/java/com/instabug/reactlibrary/util/MockReflected.java @@ -1,5 +1,11 @@ package com.instabug.reactlibrary.util; +import com.instabug.crash.models.IBGNonFatalException; + +import org.json.JSONObject; + +import java.util.Map; + /** * Includes fake implementations of methods called by reflection. * Used to verify whether or not a private methods was called. @@ -16,4 +22,6 @@ public static void setCurrentPlatform(int platform) {} * Instabug.util.InstabugDeprecationLogger.setBaseUrl */ public static void setBaseUrl(String baseUrl) {} + public static void crashReportException(JSONObject exception, boolean isHandled, Map userAttributes, JSONObject fingerPrint, IBGNonFatalException.Level level) {} + } diff --git a/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj b/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj index 32dd9b905..1a855af4b 100644 --- a/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj +++ b/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj @@ -52,6 +52,7 @@ 9A3D962AB03F97E25566779F /* Pods-InstabugExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InstabugExample.debug.xcconfig"; path = "Target Support Files/Pods-InstabugExample/Pods-InstabugExample.debug.xcconfig"; sourceTree = ""; }; BAED0D0441A708AE2390E153 /* libPods-InstabugExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InstabugExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; BD54B44E2DF85672BB2D4DEE /* Pods-InstabugExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InstabugExample.release.xcconfig"; path = "Target Support Files/Pods-InstabugExample/Pods-InstabugExample.release.xcconfig"; sourceTree = ""; }; + BE3328762BDACE030078249A /* IBGCrashReporting+CP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IBGCrashReporting+CP.h"; sourceTree = ""; }; C3C8C24386310A3120006604 /* CrashReportingExampleModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CrashReportingExampleModule.m; sourceTree = ""; }; C3C8C784EADC037C5A752B94 /* CrashReportingExampleModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrashReportingExampleModule.h; sourceTree = ""; }; CC3DF8852A1DFC99003E9914 /* InstabugCrashReportingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InstabugCrashReportingTests.m; sourceTree = ""; }; @@ -91,6 +92,7 @@ 00E356EF1AD99517003FC87E /* InstabugTests */ = { isa = PBXGroup; children = ( + BE3328752BDACE030078249A /* Util */, CC3DF8892A1DFC99003E9914 /* IBGConstants.h */, CC3DF88D2A1DFC9A003E9914 /* IBGConstants.m */, CC3DF88C2A1DFC99003E9914 /* InstabugAPMTests.m */, @@ -181,6 +183,14 @@ path = Pods; sourceTree = ""; }; + BE3328752BDACE030078249A /* Util */ = { + isa = PBXGroup; + children = ( + BE3328762BDACE030078249A /* IBGCrashReporting+CP.h */, + ); + path = Util; + sourceTree = ""; + }; C3C8C1DDCEA91410F27A3683 /* native */ = { isa = PBXGroup; children = ( diff --git a/examples/default/ios/InstabugTests/InstabugAPMTests.m b/examples/default/ios/InstabugTests/InstabugAPMTests.m index dd96841de..b89df7a4d 100644 --- a/examples/default/ios/InstabugTests/InstabugAPMTests.m +++ b/examples/default/ios/InstabugTests/InstabugAPMTests.m @@ -133,31 +133,7 @@ - (void) testEndExecutionTrace { OCMVerify([traceMock end]); } -- (void) testStartFlow { - id mock = OCMClassMock([IBGAPM class]); - NSString* appFlowName = @"APP_Flow_1"; - - [self.instabugBridge startFlow:appFlowName]; - OCMVerify([mock startFlowWithName:appFlowName]); -} - -- (void) testEndFlow { - id mock = OCMClassMock([IBGAPM class]); - NSString* appFlowName = @"APP_Flow_1"; - [self.instabugBridge endFlow:appFlowName]; - OCMVerify([mock endFlowWithName:appFlowName]); -} - -- (void) testSetFlowAttribute { - id mock = OCMClassMock([IBGAPM class]); - NSString* appFlowName = @"APP_Flow_1"; - NSString* attributeKey = @"Attribute_Key_1"; - NSString* attributeValue = @"Attribute_Value_1"; - - [self.instabugBridge setFlowAttribute:appFlowName :attributeKey :attributeValue]; - OCMVerify([mock setAttributeForFlowWithName:appFlowName key:attributeKey value:attributeValue]); -} - (void) testStartUITrace { id mock = OCMClassMock([IBGAPM class]); diff --git a/examples/default/ios/InstabugTests/InstabugCrashReportingTests.m b/examples/default/ios/InstabugTests/InstabugCrashReportingTests.m index 83f682cd3..0d5ac7348 100644 --- a/examples/default/ios/InstabugTests/InstabugCrashReportingTests.m +++ b/examples/default/ios/InstabugTests/InstabugCrashReportingTests.m @@ -1,15 +1,21 @@ #import #import "Instabug/Instabug.h" #import "InstabugCrashReportingBridge.h" +#import "OCMock/OCMock.h" +#import "Util/IBGCrashReporting+CP.h" @interface InstabugCrashReportingTests : XCTestCase @property (nonatomic, retain) InstabugCrashReportingBridge *bridge; +@property (nonatomic, strong) id mCrashReporting; + @end @implementation InstabugCrashReportingTests - (void)setUp { self.bridge = [[InstabugCrashReportingBridge alloc] init]; + self.mCrashReporting = OCMClassMock([IBGCrashReporting class]); + } - (void)testSetEnabled { @@ -20,4 +26,22 @@ - (void)testSetEnabled { XCTAssertFalse(IBGCrashReporting.enabled); } +- (void)testSendNonFatalErrorJsonCrash { + NSDictionary *jsonCrash = @{}; + NSString *fingerPrint = @"fingerprint"; + RCTPromiseResolveBlock resolve = ^(id result) {}; + RCTPromiseRejectBlock reject = ^(NSString *code, NSString *message, NSError *error) {}; + NSDictionary *userAttributes = @{ @"key" : @"value", }; + IBGNonFatalLevel ibgNonFatalLevel = IBGNonFatalLevelInfo; + + + [self.bridge sendHandledJSCrash:jsonCrash userAttributes:userAttributes fingerprint:fingerPrint nonFatalExceptionLevel:ibgNonFatalLevel resolver:resolve rejecter:reject]; + + OCMVerify([self.mCrashReporting cp_reportNonFatalCrashWithStackTrace:jsonCrash + level:IBGNonFatalLevelInfo + groupingString:fingerPrint + userAttributes:userAttributes + ]); +} + @end diff --git a/examples/default/ios/Podfile b/examples/default/ios/Podfile index 7fa5129f9..b05580c35 100644 --- a/examples/default/ios/Podfile +++ b/examples/default/ios/Podfile @@ -48,6 +48,8 @@ target 'InstabugExample' do target 'InstabugTests' do inherit! :complete pod 'OCMock' + pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/feature-crash-reporting-support-non-fatal/12.7.1/Instabug.podspec' + # Pods for testing end diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index 04380a887..9234627f3 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -97,7 +97,7 @@ PODS: - hermes-engine (0.72.3): - hermes-engine/Pre-built (= 0.72.3) - hermes-engine/Pre-built (0.72.3) - - Instabug (13.0.0) + - Instabug (12.7.1) - instabug-reactnative-ndk (0.1.0): - RCT-Folly (= 2021.07.22.00) - React-Core @@ -532,7 +532,7 @@ PODS: - RCT-Folly (= 2021.07.22.00) - React-Core - RNInstabug (13.0.0): - - Instabug (= 13.0.0) + - Instabug (= 12.7.1) - React-Core - RNReanimated (3.5.4): - DoubleConversion @@ -602,6 +602,7 @@ DEPENDENCIES: - FlipperKit/SKIOSNetworkPlugin (= 0.182.0) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) + - Instabug (from `https://ios-releases.instabug.com/custom/feature-crash-reporting-support-non-fatal/12.7.1/Instabug.podspec`) - instabug-reactnative-ndk (from `../node_modules/instabug-reactnative-ndk`) - libevent (~> 2.1.12) - OCMock @@ -667,7 +668,6 @@ SPEC REPOS: - fmt - Google-Maps-iOS-Utils - GoogleMaps - - Instabug - libevent - OCMock - OpenSSL-Universal @@ -688,6 +688,8 @@ EXTERNAL SOURCES: hermes-engine: :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" :tag: hermes-2023-03-20-RNv0.72.0-49794cfc7c81fb8f69fd60c3bbf85a7480cc5a77 + Instabug: + :podspec: https://ios-releases.instabug.com/custom/feature-crash-reporting-support-non-fatal/12.7.1/Instabug.podspec instabug-reactnative-ndk: :path: "../node_modules/instabug-reactnative-ndk" RCT-Folly: @@ -798,7 +800,7 @@ SPEC CHECKSUMS: Google-Maps-iOS-Utils: f77eab4c4326d7e6a277f8e23a0232402731913a GoogleMaps: 032f676450ba0779bd8ce16840690915f84e57ac hermes-engine: 10fbd3f62405c41ea07e71973ea61e1878d07322 - Instabug: fa52de4a6cac26cde0a60ec5e0540f2461a06fe2 + Instabug: 30708b938e79c4cb5a748ca5a2fc6c2d1a8bcc4b instabug-reactnative-ndk: 960119a69380cf4cbe47ccd007c453f757927d17 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OCMock: 300b1b1b9155cb6378660b981c2557448830bdc6 @@ -841,7 +843,7 @@ SPEC CHECKSUMS: React-utils: bcb57da67eec2711f8b353f6e3d33bd8e4b2efa3 ReactCommon: 3ccb8fb14e6b3277e38c73b0ff5e4a1b8db017a9 RNGestureHandler: 6e46dde1f87e5f018a54fe5d40cd0e0b942b49ee - RNInstabug: 30d6f84029d964e88810910140218d497f6d99fe + RNInstabug: b140b0b014036c5687c94d2dd266c8965886566c RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87 RNScreens: b21dc57dfa2b710c30ec600786a3fc223b1b92e7 RNSVG: 80584470ff1ffc7994923ea135a3e5ad825546b9 @@ -850,6 +852,6 @@ SPEC CHECKSUMS: Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: ad82a989387dcdb1ce80667f16b998a2644cf0b2 +PODFILE CHECKSUM: 4614cd2944f8b5b72e85cf7a7df70a1ecc8872d2 COCOAPODS: 1.12.0 diff --git a/examples/default/src/screens/CrashReportingScreen.tsx b/examples/default/src/screens/CrashReportingScreen.tsx index 24eae5113..310029b42 100644 --- a/examples/default/src/screens/CrashReportingScreen.tsx +++ b/examples/default/src/screens/CrashReportingScreen.tsx @@ -1,13 +1,17 @@ -import React from 'react'; -import { Alert, Platform, ScrollView, Text, View } from 'react-native'; +import React, { useState } from 'react'; +import { Alert, Platform, ScrollView, StyleSheet, Text, View } from 'react-native'; -import { CrashReporting } from 'instabug-reactnative'; +import { CrashReporting, NonFatalErrorType } from 'instabug-reactnative'; import { ListTile } from '../components/ListTile'; import { Screen } from '../components/Screen'; import { Section } from '../components/Section'; import { PlatformListTile } from '../components/PlatformListTile'; import { NativeExampleCrashReporting } from '../native/NativeCrashReporting'; +import { VerticalListTile } from '../components/VerticalListTile'; +import { Button, VStack } from 'native-base'; +import { InputField } from '../components/InputField'; +import { Select } from '../components/Select'; export const CrashReportingScreen: React.FC = () => { function throwHandledException(error: Error) { @@ -19,7 +23,7 @@ export const CrashReportingScreen: React.FC = () => { throw error; } catch (err) { if (err instanceof Error) { - CrashReporting.reportError(err).then(() => + CrashReporting.reportError(err, null, null, NonFatalErrorType.critical).then(() => Alert.alert(`Crash report for ${error.name} is Sent!`), ); } @@ -46,6 +50,48 @@ export const CrashReportingScreen: React.FC = () => { } } + const styles = StyleSheet.create({ + inputWrapper: { + padding: 4, + flex: 1, + }, + + formContainer: { + flexDirection: 'row', + alignItems: 'stretch', + }, + }); + const [userAttributeKey, setUserAttributeKey] = useState(''); + const [userAttributeValue, setUserAttributeValue] = useState(''); + const [crashNameValue, setCrashNameValue] = useState(''); + const [crashFingerprint, setCrashFingerprint] = useState(''); + const [crashLevelValue, setCrashLevelValue] = useState( + NonFatalErrorType.error, + ); + + function sendCrash() { + try { + const error = Error(crashNameValue); + if (!error.message) { + const appName = 'Instabug Test App'; + error.message = `Handled ${crashNameValue} From ${appName}`; + } + throw error; + } catch (err) { + if (err instanceof Error) { + const attrMap: { [k: string]: string } = {}; + attrMap[userAttributeKey] = userAttributeValue; + + CrashReporting.reportError( + err, + userAttributeValue.length === 0 || userAttributeKey.length === 0 ? null : attrMap, + crashFingerprint.length === 0 ? null : crashFingerprint, + crashLevelValue, + ).then(() => Alert.alert(`Crash report for ${crashNameValue} is Sent!`)); + } + } + } + return ( @@ -119,6 +165,71 @@ export const CrashReportingScreen: React.FC = () => { title="Throw Unhandled Native OOM Exception" onPress={() => NativeExampleCrashReporting.sendOOM()} /> + + + + setCrashNameValue(key)} + value={crashNameValue} + /> + + + + setUserAttributeKey(key)} + value={userAttributeKey} + /> + + + setUserAttributeValue(value)} + value={userAttributeValue} + /> + + + +