diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e23966167..e789b38208 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,10 +12,6 @@ - Bump Instabug iOS SDK to v14.3.0 ([#1367](https://github.com/Instabug/Instabug-React-Native/pull/1367)). [See release notes](https://github.com/Instabug/Instabug-iOS/releases/tag/14.3.0). -### Added - -- Add support for Network Spans in network logging module ([#1360](https://github.com/Instabug/Instabug-React-Native/pull/1360)). - ## [14.1.0](https://github.com/Instabug/Instabug-React-Native/compare/v14.0.0...v14.1.0) (January 2, 2025) ### Added diff --git a/RNInstabug.podspec b/RNInstabug.podspec index 03820e1800..843865b5b7 100644 --- a/RNInstabug.podspec +++ b/RNInstabug.podspec @@ -16,7 +16,6 @@ Pod::Spec.new do |s| s.source_files = "ios/**/*.{h,m,mm}" s.dependency 'React-Core' - # use_instabug!(s) - s.dependency 'Instabug' + use_instabug!(s) end diff --git a/android/src/main/java/com/instabug/reactlibrary/ArgsRegistry.java b/android/src/main/java/com/instabug/reactlibrary/ArgsRegistry.java index 428d989f62..b56db804d6 100644 --- a/android/src/main/java/com/instabug/reactlibrary/ArgsRegistry.java +++ b/android/src/main/java/com/instabug/reactlibrary/ArgsRegistry.java @@ -17,7 +17,6 @@ import com.instabug.library.invocation.util.InstabugVideoRecordingButtonPosition; import com.instabug.library.sessionreplay.model.SessionMetadata; import com.instabug.library.ui.onboarding.WelcomeMessage; -import com.instabug.library.MaskingType; import java.util.ArrayList; import java.util.HashMap; @@ -61,7 +60,6 @@ static Map getAll() { putAll(locales); putAll(placeholders); putAll(launchType); - putAll(autoMaskingTypes); }}; } @@ -255,10 +253,5 @@ static Map getAll() { put(SessionMetadata.LaunchType.COLD,"cold"); put(SessionMetadata.LaunchType.WARM,"warm" ); }}; - public static final ArgsMap autoMaskingTypes = new ArgsMap() {{ - put("labels", MaskingType.LABELS); - put("textInputs", MaskingType.TEXT_INPUTS); - put("media", MaskingType.MEDIA); - put("none", MaskingType.MASK_NOTHING); - }}; + } diff --git a/android/src/main/java/com/instabug/reactlibrary/Constants.java b/android/src/main/java/com/instabug/reactlibrary/Constants.java index 9f1a0cf355..f6986200d3 100644 --- a/android/src/main/java/com/instabug/reactlibrary/Constants.java +++ b/android/src/main/java/com/instabug/reactlibrary/Constants.java @@ -10,9 +10,6 @@ final class Constants { final static String IBG_ON_NEW_MESSAGE_HANDLER = "IBGonNewMessageHandler"; final static String IBG_ON_NEW_REPLY_RECEIVED_CALLBACK = "IBGOnNewReplyReceivedCallback"; - final static String IBG_ON_FEATURES_UPDATED_CALLBACK = "IBGOnFeatureUpdatedCallback"; - final static String IBG_NETWORK_LOGGER_HANDLER = "IBGNetworkLoggerHandler"; - final static String IBG_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK = "IBGOnNewW3CFlagsUpdateReceivedCallback"; final static String IBG_SESSION_REPLAY_ON_SYNC_CALLBACK_INVOCATION = "IBGSessionReplayOnSyncCallback"; diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugNetworkLoggerModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugNetworkLoggerModule.java deleted file mode 100644 index a47cc7e212..0000000000 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugNetworkLoggerModule.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.instabug.reactlibrary; - - -import static com.instabug.apm.configuration.cp.APMFeature.APM_NETWORK_PLUGIN_INSTALLED; -import static com.instabug.apm.configuration.cp.APMFeature.CP_NATIVE_INTERCEPTION_ENABLED; - -import android.util.Log; - -import androidx.annotation.NonNull; - -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.ReadableMapKeySetIterator; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.WritableNativeMap; -import com.instabug.apm.InternalAPM; -import com.instabug.apm.sanitization.OnCompleteCallback; -import com.instabug.library.logging.listeners.networklogs.NetworkLogSnapshot; -import com.instabug.reactlibrary.utils.EventEmitterModule; -import com.instabug.reactlibrary.utils.MainThreadHandler; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - - -public class RNInstabugNetworkLoggerModule extends EventEmitterModule { - - public final ConcurrentHashMap> callbackMap = new ConcurrentHashMap>(); - - public RNInstabugNetworkLoggerModule(ReactApplicationContext reactContext) { - super(reactContext); - } - - - @NonNull - @Override - public String getName() { - return "IBGNetworkLogger"; - } - - - @ReactMethod - public void addListener(String event) { - super.addListener(event); - } - - @ReactMethod - public void removeListeners(Integer count) { - super.removeListeners(count); - } - - private boolean getFlagValue(String key) { - return InternalAPM._isFeatureEnabledCP(key, ""); - } - - private WritableMap convertFromMapToWritableMap(Map map) { - WritableMap writableMap = new WritableNativeMap(); - for (String key : map.keySet()) { - Object value = map.get(key); - writableMap.putString(key, (String) value); - } - return writableMap; - } - - private Map convertReadableMapToMap(ReadableMap readableMap) { - Map map = new HashMap<>(); - if (readableMap != null) { - ReadableMapKeySetIterator iterator = readableMap.keySetIterator(); - while (iterator.hasNextKey()) { - String key = iterator.nextKey(); - map.put(key, readableMap.getString(key)); - } - } - return map; - } - - /** - * Get first time Value of [cp_native_interception_enabled] flag - */ - @ReactMethod - public void isNativeInterceptionEnabled(Promise promise) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - promise.resolve(getFlagValue(CP_NATIVE_INTERCEPTION_ENABLED)); - } catch (Exception e) { - e.printStackTrace(); - promise.resolve(false); // Will rollback to JS interceptor - } - - } - }); - } - - /** - * Indicate if user added APM Network plugin or not - * [true] means user added the APM plugin - * [false] means not - */ - @ReactMethod - public void hasAPMNetworkPlugin(Promise promise) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - promise.resolve(getFlagValue(APM_NETWORK_PLUGIN_INSTALLED)); - } catch (Exception e) { - e.printStackTrace(); - promise.resolve(false); // Will rollback to JS interceptor - } - - } - }); - } - - - @ReactMethod - public void registerNetworkLogsListener() { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - InternalAPM._registerNetworkLogSanitizer((networkLogSnapshot, onCompleteCallback) -> { - final String id = String.valueOf(onCompleteCallback.hashCode()); - callbackMap.put(id, onCompleteCallback); - - WritableMap networkSnapshotParams = Arguments.createMap(); - networkSnapshotParams.putString("id", id); - networkSnapshotParams.putString("url", networkLogSnapshot.getUrl()); - networkSnapshotParams.putInt("responseCode", networkLogSnapshot.getResponseCode()); - networkSnapshotParams.putString("requestBody", networkLogSnapshot.getRequestBody()); - networkSnapshotParams.putString("response", networkLogSnapshot.getResponse()); - final Map requestHeaders = networkLogSnapshot.getRequestHeaders(); - if (requestHeaders != null) { - networkSnapshotParams.putMap("requestHeader", convertFromMapToWritableMap(requestHeaders)); - } - final Map responseHeaders = networkLogSnapshot.getResponseHeaders(); - if (responseHeaders != null) { - networkSnapshotParams.putMap("responseHeader", convertFromMapToWritableMap(responseHeaders)); - } - - sendEvent(Constants.IBG_NETWORK_LOGGER_HANDLER, networkSnapshotParams); - }); - } - }); - } - - @ReactMethod - public void resetNetworkLogsListener() { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - InternalAPM._registerNetworkLogSanitizer(null); - } - }); - } - - @ReactMethod - public void updateNetworkLogSnapshot( - String url, - String callbackID, - String requestBody, - String responseBody, - int responseCode, - ReadableMap requestHeaders, - ReadableMap responseHeaders - ) { - try { - // Convert ReadableMap to a Java Map for easier handling - Map requestHeadersMap = convertReadableMapToMap(requestHeaders); - Map responseHeadersMap = convertReadableMapToMap(responseHeaders); - - NetworkLogSnapshot modifiedSnapshot = null; - if (!url.isEmpty()) { - modifiedSnapshot = new NetworkLogSnapshot(url, requestHeadersMap, requestBody, responseHeadersMap, responseBody, responseCode); - } - - final OnCompleteCallback callback = callbackMap.get(callbackID); - if (callback != null) { - callback.onComplete(modifiedSnapshot); - callbackMap.remove(callbackID); - } - } catch (Exception e) { - // Reject the promise to indicate an error occurred - Log.e("IB-CP-Bridge", "InstabugNetworkLogger.updateNetworkLogSnapshot failed to parse the network snapshot object."); - } - } -} diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index 04a07eaade..72872fac8b 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -1,7 +1,5 @@ package com.instabug.reactlibrary; -import static com.instabug.apm.configuration.cp.APMFeature.APM_NETWORK_PLUGIN_INSTALLED; -import static com.instabug.apm.configuration.cp.APMFeature.CP_NATIVE_INTERCEPTION_ENABLED; import static com.instabug.reactlibrary.utils.InstabugUtil.getMethod; import android.app.Application; @@ -40,8 +38,7 @@ import com.instabug.library.internal.crossplatform.FeaturesStateListener; import com.instabug.library.internal.crossplatform.InternalCore; import com.instabug.library.featuresflags.model.IBGFeatureFlag; -import com.instabug.library.internal.crossplatform.InternalCore; -import com.instabug.library.internal.crossplatform.OnFeaturesUpdatedListener; +import com.instabug.library.featuresflags.model.IBGFeatureFlag; import com.instabug.library.internal.module.InstabugLocale; import com.instabug.library.invocation.InstabugInvocationEvent; import com.instabug.library.logging.InstabugLog; @@ -123,7 +120,7 @@ public void setEnabled(final boolean isEnabled) { @Override public void run() { try { - if (isEnabled) + if(isEnabled) Instabug.enable(); else Instabug.disable(); @@ -136,11 +133,10 @@ public void run() { /** * Initializes the SDK. - * - * @param token The token that identifies the app. You can find it on your dashboard. + * @param token The token that identifies the app. You can find it on your dashboard. * @param invocationEventValues The events that invoke the SDK's UI. - * @param logLevel The level of detail in logs that you want to print. - * @param codePushVersion The Code Push version to be used for all reports. + * @param logLevel The level of detail in logs that you want to print. + * @param codePushVersion The Code Push version to be used for all reports. */ @ReactMethod public void init( @@ -166,8 +162,8 @@ public void run() { .setInvocationEvents(invocationEvents) .setLogLevel(parsedLogLevel); - if (codePushVersion != null) { - if (Instabug.isBuilt()) { + if(codePushVersion != null) { + if(Instabug.isBuilt()) { Instabug.setCodePushVersion(codePushVersion); } else { builder.setCodePushVersion(codePushVersion); @@ -333,7 +329,7 @@ public void run() { * * @param userEmail User's default email * @param userName Username. - * @param userId User's ID + * @param userId User's ID */ @ReactMethod public void identifyUser( @@ -753,15 +749,15 @@ public void addFileAttachmentWithDataToReport(String data, String fileName) { private WritableMap convertFromHashMapToWriteableMap(HashMap hashMap) { WritableMap writableMap = new WritableNativeMap(); - for (int i = 0; i < hashMap.size(); i++) { + for(int i = 0; i < hashMap.size(); i++) { Object key = hashMap.keySet().toArray()[i]; Object value = hashMap.get(key); - writableMap.putString((String) key, (String) value); + writableMap.putString((String) key,(String) value); } return writableMap; } - private static JSONObject objectToJSONObject(Object object) { + private static JSONObject objectToJSONObject(Object object){ Object json = null; JSONObject jsonObject = null; try { @@ -778,12 +774,13 @@ private static JSONObject objectToJSONObject(Object object) { private WritableArray convertArrayListToWritableArray(List arrayList) { WritableArray writableArray = new WritableNativeArray(); - for (int i = 0; i < arrayList.size(); i++) { + for(int i = 0; i < arrayList.size(); i++) { Object object = arrayList.get(i); - if (object instanceof String) { + if(object instanceof String) { writableArray.pushString((String) object); - } else { + } + else { JSONObject jsonObject = objectToJSONObject(object); writableArray.pushMap((WritableMap) jsonObject); } @@ -839,7 +836,7 @@ public void run() { * Shows the welcome message in a specific mode. * * @param welcomeMessageMode An enum to set the welcome message mode to - * live, or beta. + * live, or beta. */ @ReactMethod public void showWelcomeMessageWithMode(final String welcomeMessageMode) { @@ -861,7 +858,7 @@ public void run() { * Sets the welcome message mode to live, beta or disabled. * * @param welcomeMessageMode An enum to set the welcome message mode to - * live, beta or disabled. + * live, beta or disabled. */ @ReactMethod public void setWelcomeMessageMode(final String welcomeMessageMode) { @@ -996,6 +993,7 @@ public void run() { * Reports that the screen name been changed (Current View). * * @param screenName string containing the screen name + * */ @ReactMethod public void reportCurrentViewChange(final String screenName) { @@ -1018,6 +1016,7 @@ public void run() { * Reports that the screen has been changed (Repro Steps) the screen sent to this method will be the 'current view' on the dashboard * * @param screenName string containing the screen name + * */ @ReactMethod public void reportScreenChange(final String screenName) { @@ -1027,7 +1026,7 @@ public void run() { try { Method method = getMethod(Class.forName("com.instabug.library.Instabug"), "reportScreenChange", Bitmap.class, String.class); if (method != null) { - method.invoke(null, null, screenName); + method.invoke(null , null, screenName); } } catch (Exception e) { e.printStackTrace(); @@ -1121,7 +1120,7 @@ public void removeFeatureFlags(final ReadableArray featureFlags) { @Override public void run() { try { - ArrayList stringArray = ArrayUtil.parseReadableArrayOfStrings(featureFlags); + ArrayList stringArray = ArrayUtil.parseReadableArrayOfStrings(featureFlags); Instabug.removeFeatureFlag(stringArray); } catch (Exception e) { e.printStackTrace(); @@ -1157,12 +1156,11 @@ public void run() { } }); } - /** * Register a listener for W3C flags value change */ @ReactMethod - public void registerW3CFlagsChangeListener() { + public void registerW3CFlagsChangeListener(){ MainThreadHandler.runOnMainThread(new Runnable() { @Override @@ -1179,7 +1177,8 @@ public void invoke(@NonNull CoreFeaturesState featuresState) { sendEvent(Constants.IBG_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params); } }); - } catch (Exception e) { + } + catch (Exception e) { e.printStackTrace(); } @@ -1190,17 +1189,18 @@ public void invoke(@NonNull CoreFeaturesState featuresState) { /** - * Get first time Value of W3ExternalTraceID flag + * Get first time Value of W3ExternalTraceID flag */ @ReactMethod - public void isW3ExternalTraceIDEnabled(Promise promise) { + public void isW3ExternalTraceIDEnabled(Promise promise){ MainThreadHandler.runOnMainThread(new Runnable() { @Override public void run() { try { promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID)); - } catch (Exception e) { + } + catch (Exception e) { e.printStackTrace(); promise.resolve(false); } @@ -1212,17 +1212,18 @@ public void run() { /** - * Get first time Value of W3ExternalGeneratedHeader flag + * Get first time Value of W3ExternalGeneratedHeader flag */ @ReactMethod - public void isW3ExternalGeneratedHeaderEnabled(Promise promise) { + public void isW3ExternalGeneratedHeaderEnabled(Promise promise){ MainThreadHandler.runOnMainThread(new Runnable() { @Override public void run() { try { promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER)); - } catch (Exception e) { + } + catch (Exception e) { e.printStackTrace(); promise.resolve(false); } @@ -1233,17 +1234,18 @@ public void run() { } /** - * Get first time Value of W3CaughtHeader flag + * Get first time Value of W3CaughtHeader flag */ @ReactMethod - public void isW3CaughtHeaderEnabled(Promise promise) { + public void isW3CaughtHeaderEnabled(Promise promise){ MainThreadHandler.runOnMainThread(new Runnable() { @Override public void run() { try { promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER)); - } catch (Exception e) { + } + catch (Exception e) { e.printStackTrace(); promise.resolve(false); } @@ -1273,47 +1275,7 @@ public Map getConstants() { return constants; } - /** - * Sets the auto mask screenshots types. - * - * @param autoMaskingTypes The masking type to be applied. - */ - @ReactMethod - public void enableAutoMasking(@NonNull ReadableArray autoMaskingTypes) { - MainThreadHandler.runOnMainThread(new Runnable() { - - @Override - public void run() { - int[] autoMassingTypesArray = new int[autoMaskingTypes.size()]; - for (int i = 0; i < autoMaskingTypes.size(); i++) { - String key = autoMaskingTypes.getString(i); - - autoMassingTypesArray[i] = ArgsRegistry.autoMaskingTypes.get(key); - - } - - Instabug.setAutoMaskScreenshotsTypes(autoMassingTypesArray); - } - - }); - } - - @ReactMethod - public void setOnFeaturesUpdatedListener() { - InternalCore.INSTANCE._setOnFeaturesUpdatedListener(new OnFeaturesUpdatedListener() { - @Override - public void invoke() { - final boolean cpNativeInterceptionEnabled = InternalAPM._isFeatureEnabledCP(CP_NATIVE_INTERCEPTION_ENABLED, ""); - final boolean hasAPMPlugin = InternalAPM._isFeatureEnabledCP(APM_NETWORK_PLUGIN_INSTALLED, ""); - - WritableMap params = Arguments.createMap(); - params.putBoolean("cpNativeInterceptionEnabled", cpNativeInterceptionEnabled); - params.putBoolean("hasAPMPlugin", hasAPMPlugin); - sendEvent(Constants.IBG_ON_FEATURES_UPDATED_CALLBACK, params); - } - }); - } - /** + /** * Enables or disables capturing network body. * @param isEnabled A boolean to enable/disable capturing network body. */ diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativePackage.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativePackage.java index 0cabd1bcfa..1d38287252 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativePackage.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativePackage.java @@ -29,7 +29,6 @@ public List createNativeModules(@NonNull ReactApplicationContext r modules.add(new RNInstabugRepliesModule(reactContext)); modules.add(new RNInstabugAPMModule(reactContext)); modules.add(new RNInstabugSessionReplayModule(reactContext)); - modules.add(new RNInstabugNetworkLoggerModule(reactContext)); return modules; } diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugNetworkLoggerModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugNetworkLoggerModuleTest.java deleted file mode 100644 index 30cec00abe..0000000000 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugNetworkLoggerModuleTest.java +++ /dev/null @@ -1,207 +0,0 @@ -package com.instabug.reactlibrary; - -import static com.instabug.apm.configuration.cp.APMFeature.APM_NETWORK_PLUGIN_INSTALLED; -import static com.instabug.apm.configuration.cp.APMFeature.CP_NATIVE_INTERCEPTION_ENABLED; -import static org.mockito.Mockito.*; -import static org.junit.Assert.*; - -import android.os.Looper; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.mockito.stubbing.Answer; - -import com.instabug.apm.InternalAPM; -import com.instabug.reactlibrary.utils.MainThreadHandler; - -public class RNInstabugNetworkLoggerModuleTest { - - // Mock Objects - private MockedStatic mockLooper; - private MockedStatic mockMainThreadHandler; - private RNInstabugNetworkLoggerModule rnInstabugNetworkLoggerModule; - private Promise mockPromise; - - @Before - public void mockMainThreadHandler() { - // Mock Object - ReactApplicationContext mockReactApplicationContext = mock(ReactApplicationContext.class); - mockPromise = mock(Promise.class); - rnInstabugNetworkLoggerModule = new RNInstabugNetworkLoggerModule(mockReactApplicationContext); - - // Mock static functions - mockLooper = mockStatic(Looper.class); - mockMainThreadHandler = mockStatic(MainThreadHandler.class); - // Mock Looper class - Looper mockMainThreadLooper = mock(Looper.class); - when(Looper.getMainLooper()).thenReturn(mockMainThreadLooper); - - // Override runOnMainThread - Answer handlerPostAnswer = invocation -> { - invocation.getArgument(0, Runnable.class).run(); - return true; - }; - Mockito.doAnswer(handlerPostAnswer).when(MainThreadHandler.class); - MainThreadHandler.runOnMainThread(any(Runnable.class)); - } - - @After - public void tearDown() { - // Remove static mocks - mockLooper.close(); - mockMainThreadHandler.close(); - } - - - @Test - public void testGetName() { - // Test the getName method - String name = rnInstabugNetworkLoggerModule.getName(); - assertEquals("IBGNetworkLogger", name); - } - - @Test - public void testAddListener() { - // Test addListener method - rnInstabugNetworkLoggerModule.addListener("event_name"); - // Nothing to assert, but check no exceptions are thrown - } - - @Test - public void testRemoveListeners() { - // Test removeListeners method - rnInstabugNetworkLoggerModule.removeListeners(1); - // Nothing to assert, but check no exceptions are thrown - } - - @Test - public void testIsNativeInterceptionEnabled_True() { - - // Mock InternalAPM behavior within the scope of this test - try (MockedStatic internalAPMMock = mockStatic(InternalAPM.class)) { - internalAPMMock.when(() -> InternalAPM._isFeatureEnabledCP(CP_NATIVE_INTERCEPTION_ENABLED, "")).thenReturn(true); - - // Execute the method - rnInstabugNetworkLoggerModule.isNativeInterceptionEnabled(mockPromise); - - // Capture the Promise.resolve() call - ArgumentCaptor captor = ArgumentCaptor.forClass(Boolean.class); - verify(mockPromise).resolve(captor.capture()); - - // Assert that true was passed to resolve - internalAPMMock.verify(() -> InternalAPM._isFeatureEnabledCP(CP_NATIVE_INTERCEPTION_ENABLED, "")); - assertTrue(captor.getValue()); - } - } - - @Test - public void testIsNativeInterceptionEnabled_False() { - - try (MockedStatic internalAPMMock = mockStatic(InternalAPM.class)) { - internalAPMMock.when(() -> InternalAPM._isFeatureEnabledCP(CP_NATIVE_INTERCEPTION_ENABLED, "")).thenReturn(false); - - // Execute the method - rnInstabugNetworkLoggerModule.isNativeInterceptionEnabled(mockPromise); - - // Capture the Promise.resolve() call - ArgumentCaptor captor = ArgumentCaptor.forClass(Boolean.class); - verify(mockPromise).resolve(captor.capture()); - - // Assert that false was passed to resolve - assertFalse(captor.getValue()); - } - } - - @Test - public void testIsNativeInterceptionEnabled_Exception() { - - // Simulate an exception in InternalAPM - try (MockedStatic internalAPMMock = mockStatic(InternalAPM.class)) { - internalAPMMock.when(() -> InternalAPM._isFeatureEnabledCP(anyString(), anyString())).thenThrow(new RuntimeException("Error")); - - // Execute the method - rnInstabugNetworkLoggerModule.isNativeInterceptionEnabled(mockPromise); - - // Capture the Promise.resolve() call in case of an exception - ArgumentCaptor captor = ArgumentCaptor.forClass(Boolean.class); - verify(mockPromise).resolve(captor.capture()); - - // Assert that false was passed to resolve when exception occurs - assertFalse(captor.getValue()); - } - } - - @Test - public void testHasAPMNetworkPlugin_True() { - - try (MockedStatic internalAPMMock = mockStatic(InternalAPM.class)) { - internalAPMMock.when(() -> InternalAPM._isFeatureEnabledCP(APM_NETWORK_PLUGIN_INSTALLED, "")).thenReturn(true); - - // Execute the method - rnInstabugNetworkLoggerModule.hasAPMNetworkPlugin(mockPromise); - - // Capture the Promise.resolve() call - ArgumentCaptor captor = ArgumentCaptor.forClass(Boolean.class); - verify(mockPromise).resolve(captor.capture()); - - // Assert that true was passed to resolve - internalAPMMock.verify(() -> InternalAPM._isFeatureEnabledCP(APM_NETWORK_PLUGIN_INSTALLED, "")); - assertTrue(captor.getValue()); - } - } - - @Test - public void testHasAPMNetworkPlugin_False() { - - try (MockedStatic internalAPMMock = mockStatic(InternalAPM.class)) { - internalAPMMock.when(() -> InternalAPM._isFeatureEnabledCP(APM_NETWORK_PLUGIN_INSTALLED, "")).thenReturn(false); - - // Execute the method - rnInstabugNetworkLoggerModule.hasAPMNetworkPlugin(mockPromise); - - // Capture the Promise.resolve() call - ArgumentCaptor captor = ArgumentCaptor.forClass(Boolean.class); - verify(mockPromise).resolve(captor.capture()); - - // Assert that false was passed to resolve - assertFalse(captor.getValue()); - } - } - - @Test - public void testHasAPMNetworkPlugin_Exception() { - - // Simulate an exception in InternalAPM - try (MockedStatic internalAPMMock = mockStatic(InternalAPM.class)) { - internalAPMMock.when(() -> InternalAPM._isFeatureEnabledCP(anyString(), anyString())).thenThrow(new RuntimeException("Error")); - - // Execute the method - rnInstabugNetworkLoggerModule.hasAPMNetworkPlugin(mockPromise); - - // Capture the Promise.resolve() call in case of an exception - ArgumentCaptor captor = ArgumentCaptor.forClass(Boolean.class); - verify(mockPromise).resolve(captor.capture()); - - // Assert that false was passed to resolve when exception occurs - assertFalse(captor.getValue()); - } - } - - @Test - public void testRegisterNetworkLogsListenerCalled() { - try (MockedStatic internalAPMMock = mockStatic(InternalAPM.class)) { - // Run the method - rnInstabugNetworkLoggerModule.registerNetworkLogsListener(); - - // Verify the sanitizer was registered - internalAPMMock.verify(() -> InternalAPM._registerNetworkLogSanitizer(any())); - } - } -} diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java index c9cb92a9a6..ef507bb780 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java @@ -25,7 +25,6 @@ import com.instabug.library.internal.module.InstabugLocale; import com.instabug.library.ui.onboarding.WelcomeMessage; import com.instabug.reactlibrary.utils.MainThreadHandler; -import com.instabug.library.MaskingType; import org.junit.After; import org.junit.Assert; @@ -664,19 +663,7 @@ public void testW3CCaughtHeaderFlag(){ verify(promise).resolve(expected); } - @Test - public void testEnableAutoMasking(){ - - String maskLabel = "labels"; - String maskTextInputs = "textInputs"; - String maskMedia = "media"; - String maskNone = "none"; - - rnModule.enableAutoMasking(JavaOnlyArray.of(maskLabel, maskMedia, maskTextInputs,maskNone)); - - mockInstabug.verify(() -> Instabug.setAutoMaskScreenshotsTypes(MaskingType.LABELS,MaskingType.MEDIA,MaskingType.TEXT_INPUTS,MaskingType.MASK_NOTHING)); - } - + @Test public void testSetNetworkLogBodyEnabled() { rnModule.setNetworkLogBodyEnabled(true); diff --git a/examples/default/android/app/build.gradle b/examples/default/android/app/build.gradle index b039dd1901..b017ddb2f9 100644 --- a/examples/default/android/app/build.gradle +++ b/examples/default/android/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: "com.android.application" apply plugin: "org.jetbrains.kotlin.android" apply plugin: "com.facebook.react" apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" -apply plugin: 'instabug-apm' + /** * This is the configuration block to customize your React Native Android app. * By default you don't need to apply any configuration, just uncomment the lines you need. @@ -124,12 +124,6 @@ android { } } -instabug { - apm { - networkEnabled = true - } -} - dependencies { // The version of react-native is set by the React Native Gradle Plugin implementation("com.facebook.react:react-android") diff --git a/examples/default/android/build.gradle b/examples/default/android/build.gradle index 5729e78c9e..72cc6f93ba 100644 --- a/examples/default/android/build.gradle +++ b/examples/default/android/build.gradle @@ -12,19 +12,11 @@ buildscript { repositories { google() mavenCentral() - maven { - url "https://mvn.instabug.com/nexus/repository/instabug-internal/" - credentials { - username "instabug" - password System.getenv("INSTABUG_REPOSITORY_PASSWORD") - } - } } dependencies { classpath("com.android.tools.build:gradle:8.1.0") classpath("com.facebook.react:react-native-gradle-plugin") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") - classpath("com.instabug.library:instabug-plugin:14.1.0.6273967-SNAPSHOT") } } @@ -34,13 +26,6 @@ allprojects { url("$rootDir/../node_modules/detox/Detox-android") } - maven { - url "https://mvn.instabug.com/nexus/repository/instabug-internal/" - credentials { - username "instabug" - password System.getenv("INSTABUG_REPOSITORY_PASSWORD") - } - } maven { credentials { username System.getenv("DREAM11_MAVEN_USERNAME") diff --git a/examples/default/ios/InstabugTests/InstabugNetworkLoggerTests.m b/examples/default/ios/InstabugTests/InstabugNetworkLoggerTests.m deleted file mode 100644 index 693c2c01cb..0000000000 --- a/examples/default/ios/InstabugTests/InstabugNetworkLoggerTests.m +++ /dev/null @@ -1,124 +0,0 @@ -#import -#import "InstabugNetworkLoggerBridge.h" - -@interface InstabugNetworkLoggerBridgeTests : XCTestCase - -@property (nonatomic, strong) InstabugNetworkLoggerBridge *networkLoggerBridge; - -@end - -@implementation InstabugNetworkLoggerBridgeTests - -- (void)setUp { - [super setUp]; - self.networkLoggerBridge = [[InstabugNetworkLoggerBridge alloc] init]; -} - -- (void)tearDown { - self.networkLoggerBridge = nil; - [super tearDown]; -} - -- (void)testInitialization { - XCTAssertNotNil(self.networkLoggerBridge.requestObfuscationCompletionDictionary); - XCTAssertNotNil(self.networkLoggerBridge.responseObfuscationCompletionDictionary); - XCTAssertNotNil(self.networkLoggerBridge.requestFilteringCompletionDictionary); - XCTAssertNotNil(self.networkLoggerBridge.responseFilteringCompletionDictionary); -} - -- (void)testRequiresMainQueueSetup { - XCTAssertFalse([InstabugNetworkLoggerBridge requiresMainQueueSetup]); -} - -- (void)testSupportedEvents { - NSArray *events = [self.networkLoggerBridge supportedEvents]; - NSArray *expectedEvents = @[@"IBGpreInvocationHandler", @"IBGNetworkLoggerHandler"]; - XCTAssertEqualObjects(events, expectedEvents); -} - -- (void)testMethodQueue { - dispatch_queue_t queue = [self.networkLoggerBridge methodQueue]; - XCTAssertEqual(queue, dispatch_get_main_queue()); -} - -- (void)testStartObserving { - [self.networkLoggerBridge startObserving]; - // Since `hasListeners` is private, we will assume it is true based on no errors or behavior issues - XCTAssertTrue(YES); // Expect no crashes -} - -- (void)testStopObserving { - [self.networkLoggerBridge stopObserving]; - XCTAssertTrue(YES); // Ensure the method doesn't cause issues -} - -- (void)testIsNativeInterceptionEnabled { - XCTestExpectation *expectation = [self expectationWithDescription:@"isNativeInterceptionEnabled"]; - - [self.networkLoggerBridge isNativeInterceptionEnabled:^(id result) { - XCTAssertNotNil(result); - XCTAssertTrue([result isKindOfClass:[NSNumber class]]); - [expectation fulfill]; - } :^(NSString *code, NSString *message, NSError *error) { - XCTFail(@"Promise rejection not expected."); - }]; - - [self waitForExpectationsWithTimeout:1.0 handler:nil]; -} - -- (void)testRegisterNetworkLogsListenerFiltering { - [self.networkLoggerBridge registerNetworkLogsListener:NetworkListenerTypeFiltering]; - // Expect no crashes and check that filtering handler was set - XCTAssertTrue(YES); // Could add additional assertions if more visibility into handler setup is possible -} - -- (void)testRegisterNetworkLogsListenerObfuscation { - [self.networkLoggerBridge registerNetworkLogsListener:NetworkListenerTypeObfuscation]; - XCTAssertTrue(YES); // Expect no crashes, similar reasoning -} - -- (void)testRegisterNetworkLogsListenerBoth { - [self.networkLoggerBridge registerNetworkLogsListener:NetworkListenerTypeBoth]; - XCTAssertTrue(YES); // Same reason, ensuring no crash -} - -- (void)testUpdateNetworkLogSnapshotValidJson { - NSString *jsonString = @"{\"url\":\"https://example.com\",\"requestBody\":\"bodyData\",\"requestHeader\":{\"key\":\"value\"},\"id\":\"12345\"}"; - - [self.networkLoggerBridge updateNetworkLogSnapshot:jsonString]; - - // Expect no errors or logs regarding completion issues - XCTAssertTrue(YES); -} - -- (void)testUpdateNetworkLogSnapshotInvalidJson { - NSString *invalidJsonString = @"invalid json string"; - - // This should fail gracefully and log an error - [self.networkLoggerBridge updateNetworkLogSnapshot:invalidJsonString]; - XCTAssertTrue(YES); // No crash, expect graceful handling -} - -- (void)testSetNetworkLoggingRequestFilterPredicateIOS { - NSString *callbackID = @"12345"; - - // Mock a completion handler - self.networkLoggerBridge.requestFilteringCompletionDictionary[callbackID] = ^(BOOL shouldSave) { - XCTAssertTrue(shouldSave); - }; - - [self.networkLoggerBridge setNetworkLoggingRequestFilterPredicateIOS:callbackID :YES]; - - XCTAssertTrue(YES); // Ensure that the handler is invoked correctly -} - -- (void)testSetNetworkLoggingRequestFilterPredicateIOSInvalidCallback { - NSString *invalidCallbackID = @"invalidID"; - - // This should fail gracefully and log an error - [self.networkLoggerBridge setNetworkLoggingRequestFilterPredicateIOS:invalidCallbackID :YES]; - - XCTAssertTrue(YES); // No crash, expect graceful handling -} - -@end diff --git a/examples/default/ios/InstabugTests/InstabugSampleTests.m b/examples/default/ios/InstabugTests/InstabugSampleTests.m index df61d21f3b..281fc35d69 100644 --- a/examples/default/ios/InstabugTests/InstabugSampleTests.m +++ b/examples/default/ios/InstabugTests/InstabugSampleTests.m @@ -608,22 +608,6 @@ - (void) testIsW3CaughtHeaderEnabled { OCMVerify([mock w3CaughtHeaderEnabled]); } -- (void)testEnableAutoMasking { - id mock = OCMClassMock([Instabug class]); - - NSArray *autoMaskingTypes = [NSArray arrayWithObjects: - [NSNumber numberWithInteger:IBGAutoMaskScreenshotOptionLabels], - [NSNumber numberWithInteger:IBGAutoMaskScreenshotOptionTextInputs], - [NSNumber numberWithInteger:IBGAutoMaskScreenshotOptionMedia], - [NSNumber numberWithInteger:IBGAutoMaskScreenshotOptionMaskNothing], - nil]; - - OCMStub([mock setAutoMaskScreenshots:IBGAutoMaskScreenshotOptionLabels | IBGAutoMaskScreenshotOptionTextInputs | IBGAutoMaskScreenshotOptionMedia | IBGAutoMaskScreenshotOptionMaskNothing]); - - [self.instabugBridge enableAutoMasking:autoMaskingTypes]; - - OCMVerify([mock setAutoMaskScreenshots:IBGAutoMaskScreenshotOptionLabels | IBGAutoMaskScreenshotOptionTextInputs | IBGAutoMaskScreenshotOptionMedia | IBGAutoMaskScreenshotOptionMaskNothing]); -} - (void)testSetNetworkLogBodyEnabled { id mock = OCMClassMock([IBGNetworkLogger class]); diff --git a/examples/default/ios/Podfile b/examples/default/ios/Podfile index 1bb16073b8..3526171cd4 100644 --- a/examples/default/ios/Podfile +++ b/examples/default/ios/Podfile @@ -15,7 +15,6 @@ target 'InstabugExample' do config = use_native_modules! rn_maps_path = '../node_modules/react-native-maps' pod 'react-native-google-maps', :path => rn_maps_path - pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/feature-support_cp_network_filtering_obfuscation-base/14.3.0/Instabug.podspec' # Flags change depending on the env values. flags = get_default_flags() diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock index 3dca873b20..6f53229e8f 100644 --- a/examples/default/ios/Podfile.lock +++ b/examples/default/ios/Podfile.lock @@ -1624,7 +1624,7 @@ PODS: - ReactCommon/turbomodule/core - Yoga - RNInstabug (14.1.0): - - Instabug + - Instabug (= 14.3.0) - React-Core - RNReanimated (3.16.1): - DoubleConversion @@ -1768,7 +1768,6 @@ DEPENDENCIES: - fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`) - 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-support_cp_network_filtering_obfuscation-base/14.3.0/Instabug.podspec`) - instabug-reactnative-ndk (from `../node_modules/instabug-reactnative-ndk`) - OCMock - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) @@ -1848,6 +1847,7 @@ SPEC REPOS: trunk: - Google-Maps-iOS-Utils - GoogleMaps + - Instabug - OCMock - SocketRocket @@ -1865,8 +1865,6 @@ EXTERNAL SOURCES: hermes-engine: :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" :tag: hermes-2024-08-15-RNv0.75.1-4b3bf912cc0f705b51b71ce1a5b8bd79b93a451b - Instabug: - :podspec: https://ios-releases.instabug.com/custom/feature-support_cp_network_filtering_obfuscation-base/14.3.0/Instabug.podspec instabug-reactnative-ndk: :path: "../node_modules/instabug-reactnative-ndk" RCT-Folly: @@ -2019,7 +2017,7 @@ SPEC CHECKSUMS: Google-Maps-iOS-Utils: f77eab4c4326d7e6a277f8e23a0232402731913a GoogleMaps: 032f676450ba0779bd8ce16840690915f84e57ac hermes-engine: ea92f60f37dba025e293cbe4b4a548fd26b610a0 - Instabug: 56c200f9af7772dd57b30b8d1aad605980cc4c71 + Instabug: 97a4e694731f46bbc02dbe49ab29cc552c5e2f41 instabug-reactnative-ndk: d765ac289d56e8896398d02760d9abf2562fc641 OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74 RCT-Folly: 4464f4d875961fce86008d45f4ecf6cef6de0740 @@ -2086,7 +2084,7 @@ SPEC CHECKSUMS: ReactCommon: 6a952e50c2a4b694731d7682aaa6c79bc156e4ad RNCClipboard: 2821ac938ef46f736a8de0c8814845dde2dcbdfb RNGestureHandler: 511250b190a284388f9dd0d2e56c1df76f14cfb8 - RNInstabug: b77a5561ccf3806073944bc085a4e4b31f91d31d + RNInstabug: 4e49b8da38b1f6a0fdeca226cec844d553c8d785 RNReanimated: f42a5044d121d68e91680caacb0293f4274228eb RNScreens: c7ceced6a8384cb9be5e7a5e88e9e714401fd958 RNSVG: 8b1a777d54096b8c2a0fd38fc9d5a454332bbb4d @@ -2094,6 +2092,6 @@ SPEC CHECKSUMS: SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d Yoga: 055f92ad73f8c8600a93f0e25ac0b2344c3b07e6 -PODFILE CHECKSUM: 7d44257b7d13c9b09806f318160658af940e8e2a +PODFILE CHECKSUM: 63bf073bef3872df95ea45e7c9c023a331ebb3c3 COCOAPODS: 1.14.0 diff --git a/examples/default/src/App.tsx b/examples/default/src/App.tsx index aaf08037dd..abdab11111 100644 --- a/examples/default/src/App.tsx +++ b/examples/default/src/App.tsx @@ -1,19 +1,17 @@ -import React, { useEffect, useState } from 'react'; -import { ActivityIndicator, StyleSheet } from 'react-native'; +import React, { useEffect } from 'react'; +import { StyleSheet } from 'react-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native'; -import type { SessionMetadata } from 'instabug-reactnative'; import Instabug, { CrashReporting, InvocationEvent, - LaunchType, LogLevel, - NetworkInterceptionMode, - NetworkLogger, ReproStepsMode, SessionReplay, + LaunchType, } from 'instabug-reactnative'; +import type { SessionMetadata } from 'instabug-reactnative'; import { NativeBaseProvider } from 'native-base'; import { RootTabNavigator } from './navigation/RootTab'; @@ -40,38 +38,20 @@ export const App: React.FC = () => { const navigationRef = useNavigationContainerRef(); - const [isInstabugInitialized, setIsInstabugInitialized] = useState(false); - - const initializeInstabug = async () => { - try { - SessionReplay.setSyncCallback((data) => shouldSyncSession(data)); - - await Instabug.init({ - token: 'deb1910a7342814af4e4c9210c786f35', - invocationEvents: [InvocationEvent.floatingButton], - debugLogsLevel: LogLevel.verbose, - networkInterceptionMode: NetworkInterceptionMode.native, - }); - - CrashReporting.setNDKCrashesEnabled(true); - Instabug.setReproStepsConfig({ all: ReproStepsMode.enabled }); + useEffect(() => { + SessionReplay.setSyncCallback((data) => shouldSyncSession(data)); - setIsInstabugInitialized(true); // Set to true after initialization - } catch (error) { - console.error('Instabug initialization failed:', error); - setIsInstabugInitialized(true); // Proceed even if initialization fails - } - }; + Instabug.init({ + token: 'deb1910a7342814af4e4c9210c786f35', + invocationEvents: [InvocationEvent.floatingButton], + debugLogsLevel: LogLevel.verbose, + }); + CrashReporting.setNDKCrashesEnabled(true); - useEffect(() => { - initializeInstabug().then(() => { - NetworkLogger.setNetworkDataObfuscationHandler(async (networkData) => { - networkData.url = `${networkData.url}/JS/Obfuscated`; - return networkData; - }); - // NetworkLogger.setRequestFilterExpression('false'); + Instabug.setReproStepsConfig({ + all: ReproStepsMode.enabled, }); - }); + }, []); useEffect(() => { const unregisterListener = Instabug.setNavigationListener(navigationRef); @@ -79,15 +59,11 @@ export const App: React.FC = () => { return unregisterListener; }, [navigationRef]); - if (!isInstabugInitialized) { - return ; - } - return ( - + @@ -100,9 +76,4 @@ const styles = StyleSheet.create({ root: { flex: 1, }, - loading: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - }, }); diff --git a/examples/default/src/screens/apm/NetworkScreen.tsx b/examples/default/src/screens/apm/NetworkScreen.tsx index 14398d0f58..f9f057f612 100644 --- a/examples/default/src/screens/apm/NetworkScreen.tsx +++ b/examples/default/src/screens/apm/NetworkScreen.tsx @@ -5,28 +5,26 @@ import { Screen } from '../../components/Screen'; import { ClipboardTextInput } from '../../components/ClipboardTextInput'; import { useQuery } from 'react-query'; import { HStack, VStack } from 'native-base'; -import { gql, GraphQLClient } from 'graphql-request'; +import { gql, request } from 'graphql-request'; import { CustomButton } from '../../components/CustomButton'; import axios from 'axios'; import type { HomeStackParamList } from '../../navigation/HomeStack'; import type { NativeStackScreenProps } from '@react-navigation/native-stack'; +import { ListTile } from '../../components/ListTile'; export const NetworkScreen: React.FC< NativeStackScreenProps > = ({ navigation }) => { const [endpointUrl, setEndpointUrl] = useState(''); const { width, height } = useWindowDimensions(); - const defaultRequestBaseUrl = 'https://jsonplaceholder.typicode.com/posts/'; - const shortenLink = 'https://shorturl.at/3Ufj3'; - const defaultRequestUrl = `${defaultRequestBaseUrl}1`; - + const defaultRequestUrl = 'https://jsonplaceholder.typicode.com/posts/1'; const imageUrls = [ 'https://fastly.picsum.photos/id/57/200/300.jpg?hmac=l908G1qVr4r7dP947-tak2mY8Vvic_vEYzCXUCKKskY', 'https://fastly.picsum.photos/id/619/200/300.jpg?hmac=WqBGwlGjuY9RCdpzRaG9G-rc9Fi7TGUINX_-klAL2kA', ]; async function sendRequestToUrl() { - let urlToSend: string; + let urlToSend = ''; if (endpointUrl.trim() !== '') { urlToSend = endpointUrl; @@ -54,7 +52,7 @@ export const NetworkScreen: React.FC< } async function sendRequestToUrlUsingAxios() { - let urlToSend: string; + let urlToSend = ''; if (endpointUrl.trim() !== '') { urlToSend = endpointUrl; @@ -79,33 +77,7 @@ export const NetworkScreen: React.FC< } } - async function sendRedirectRequestToUrl() { - try { - console.log('Sending request to: ', shortenLink); - const response = await fetch(shortenLink); - console.log('Received from: ', response.url); - - // Format the JSON response for better logging - const data = await response.json(); - - // Format the JSON response for better logging - const formattedData = JSON.stringify(data, null, 2); - - // Log the formatted response - console.log('Response:', formattedData); - } catch (error) { - // Handle errors appropriately - console.error('Error:', error); - } - } - const fetchGraphQlData = async () => { - const client = new GraphQLClient('https://countries.trevorblades.com/graphql', { - headers: { - 'ibg-graphql-header': 'AndrewQL', // change Query Name here - }, - }); - const document = gql` query { country(code: "EG") { @@ -115,7 +87,10 @@ export const NetworkScreen: React.FC< } `; - return client.request<{ country: { emoji: string; name: string } }>(document); + return request<{ country: { emoji: string; name: string } }>( + 'https://countries.trevorblades.com/graphql', + document, + ); }; const { data, isError, isSuccess, isLoading, refetch } = useQuery('helloQuery', fetchGraphQlData); @@ -128,39 +103,6 @@ export const NetworkScreen: React.FC< axios.get('https://httpbin.org/anything'); }; - function generateUrls(count: number = 10) { - const urls = []; - for (let i = 1; i <= count; i++) { - urls.push(defaultRequestBaseUrl + i); - } - return urls; - } - - async function makeSequentialApiCalls(urls: string[]): Promise { - const results: any[] = []; - - try { - for (let i = 0; i < urls.length; i++) { - await fetch(urls[i]); - results.push(results[i]); - } - return results; - } catch (error) { - console.error('Error making parallel API calls:', error); - throw error; - } - } - async function makeParallelApiCalls(urls: string[]): Promise { - const fetchPromises = urls.map((url) => fetch(url).then((response) => response.json())); - - try { - return await Promise.all(fetchPromises); - } catch (error) { - console.error('Error making parallel API calls:', error); - throw error; - } - } - return ( @@ -173,35 +115,15 @@ export const NetworkScreen: React.FC< value={endpointUrl} /> - - - makeParallelApiCalls(generateUrls())} - title="Send Parallel Requests" - /> - makeSequentialApiCalls(generateUrls())} - title="Send Sequantail Requests" - /> - - refetch()} title="Reload GraphQL" /> - navigation.navigate('HttpScreen')} - title="Go HTTP Screen" - /> - - simulateNetworkRequest()} /> - simulateNetworkRequestWithoutHeader()} /> @@ -226,6 +148,7 @@ export const NetworkScreen: React.FC< ))} + navigation.navigate('HttpScreen')} /> ); diff --git a/ios/RNInstabug/ArgsRegistry.h b/ios/RNInstabug/ArgsRegistry.h index 52c1562f78..c7720e38fb 100644 --- a/ios/RNInstabug/ArgsRegistry.h +++ b/ios/RNInstabug/ArgsRegistry.h @@ -25,6 +25,5 @@ typedef NSDictionary ArgsDictionary; + (ArgsDictionary *) launchType; + (NSDictionary *) placeholders; -+ (ArgsDictionary *)autoMaskingTypes; @end diff --git a/ios/RNInstabug/ArgsRegistry.m b/ios/RNInstabug/ArgsRegistry.m index 08494b1ddf..bc14302ac1 100644 --- a/ios/RNInstabug/ArgsRegistry.m +++ b/ios/RNInstabug/ArgsRegistry.m @@ -21,8 +21,6 @@ + (NSMutableDictionary *) getAll { [all addEntriesFromDictionary:ArgsRegistry.nonFatalExceptionLevel]; [all addEntriesFromDictionary:ArgsRegistry.placeholders]; [all addEntriesFromDictionary:ArgsRegistry.launchType]; - [all addEntriesFromDictionary:ArgsRegistry.autoMaskingTypes]; - return all; } @@ -251,12 +249,4 @@ + (ArgsDictionary *) launchType { }; } -+ (ArgsDictionary *)autoMaskingTypes { - return @{ - @"labels" : @(IBGAutoMaskScreenshotOptionLabels), - @"textInputs" : @(IBGAutoMaskScreenshotOptionTextInputs), - @"media" : @(IBGAutoMaskScreenshotOptionMedia), - @"none" : @(IBGAutoMaskScreenshotOptionMaskNothing) - }; -} @end diff --git a/ios/RNInstabug/InstabugNetworkLoggerBridge.h b/ios/RNInstabug/InstabugNetworkLoggerBridge.h deleted file mode 100644 index 888b9dc5f0..0000000000 --- a/ios/RNInstabug/InstabugNetworkLoggerBridge.h +++ /dev/null @@ -1,44 +0,0 @@ -#import -#import -#import - -typedef void (^ IBGURLRequestAsyncObfuscationCompletedHandler)(NSURLRequest * _Nonnull request); -typedef void (^IBGURLRequestResponseAsyncFilteringCompletedHandler)(BOOL keep); - -typedef NS_ENUM(NSInteger, NetworkListenerType) { - NetworkListenerTypeFiltering, - NetworkListenerTypeObfuscation, - NetworkListenerTypeBoth -}; - -@interface InstabugNetworkLoggerBridge : RCTEventEmitter - -@property NSMutableDictionary * _Nonnull requestObfuscationCompletionDictionary; -@property NSMutableDictionary * _Nonnull responseObfuscationCompletionDictionary; -@property NSMutableDictionary * _Nonnull requestFilteringCompletionDictionary; -@property NSMutableDictionary * _Nonnull responseFilteringCompletionDictionary; - -/* - +------------------------------------------------------------------------+ - | NetworkLogger Module | - +------------------------------------------------------------------------+ - */ - -- (void)isNativeInterceptionEnabled:(RCTPromiseResolveBlock _Nullable )resolve :(RCTPromiseRejectBlock _Nullable )reject; - -- (void) registerNetworkLogsListener:(NetworkListenerType)listenerType; - -- (void)updateNetworkLogSnapshot:(NSString * _Nonnull)url - callbackID:(NSString * _Nonnull)callbackID - requestBody:(NSString * _Nullable)requestBody - responseBody:(NSString * _Nullable)responseBody - responseCode:(double)responseCode - requestHeaders:(NSDictionary * _Nullable)requestHeaders - responseHeaders:(NSDictionary * _Nullable)responseHeaders; - -- (void) setNetworkLoggingRequestFilterPredicateIOS:(NSString * _Nonnull) callbackID : (BOOL)value; - -- (void)forceStartNetworkLoggingIOS; - -- (void)forceStopNetworkLoggingIOS; -@end diff --git a/ios/RNInstabug/InstabugNetworkLoggerBridge.m b/ios/RNInstabug/InstabugNetworkLoggerBridge.m deleted file mode 100644 index 16d71c8144..0000000000 --- a/ios/RNInstabug/InstabugNetworkLoggerBridge.m +++ /dev/null @@ -1,204 +0,0 @@ -// -// InstabugNetworkLoggerBridge.m -// RNInstabug -// -// Created by Andrew Amin on 01/10/2024. -// -#import "InstabugNetworkLoggerBridge.h" -#import "Util/IBGNetworkLogger+CP.h" - -#import -#import - -// Extend RCTConvert to handle NetworkListenerType enum conversion -@implementation RCTConvert (NetworkListenerType) - -// The RCT_ENUM_CONVERTER macro handles the conversion between JS values (Int) and Objective-C enum values -RCT_ENUM_CONVERTER(NetworkListenerType, (@{ - @"filtering": @(NetworkListenerTypeFiltering), - @"obfuscation": @(NetworkListenerTypeObfuscation), - @"both": @(NetworkListenerTypeBoth) -}), NetworkListenerTypeFiltering, integerValue) - -@end - -@implementation InstabugNetworkLoggerBridge - - -- (instancetype)init { - self = [super init]; - if (self) { - _requestObfuscationCompletionDictionary = [[NSMutableDictionary alloc] init]; - _responseObfuscationCompletionDictionary = [[NSMutableDictionary alloc] init]; - _requestFilteringCompletionDictionary = [[NSMutableDictionary alloc] init]; - _responseFilteringCompletionDictionary = [[NSMutableDictionary alloc] init]; - } - return self; -} - -- (dispatch_queue_t)methodQueue { - return dispatch_get_main_queue(); -} - -+ (BOOL)requiresMainQueueSetup -{ - return NO; -} - -- (NSArray *)supportedEvents { - return @[ - @"IBGpreInvocationHandler", - @"IBGNetworkLoggerHandler" - ]; -} -RCT_EXPORT_MODULE(IBGNetworkLogger) - -bool hasListeners = NO; - - - -// Will be called when this module's first listener is added. --(void)startObserving { - hasListeners = YES; - // Set up any upstream listeners or background tasks as necessary -} - -// Will be called when this module's last listener is removed, or on dealloc. --(void)stopObserving { - hasListeners = NO; - // Remove upstream listeners, stop unnecessary background tasks -} - -RCT_EXPORT_METHOD(isNativeInterceptionEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) { - resolve(@(IBGNetworkLogger.isNativeNetworkInterceptionFeatureEnabled)); -} - -RCT_EXPORT_METHOD(registerNetworkLogsListener: (NetworkListenerType) listenerType) { - switch (listenerType) { - case NetworkListenerTypeFiltering: - [self setupRequestFilteringHandler]; - break; - - case NetworkListenerTypeObfuscation: - [self setupRequestObfuscationHandler]; - break; - - case NetworkListenerTypeBoth: - // The obfuscation handler sends additional data to the JavaScript side. If filtering is applied, the request will be ignored; otherwise, it will be obfuscated and saved in the database. - [self setupRequestObfuscationHandler]; - break; - - default: - NSLog(@"Unknown NetworkListenerType"); - break; - } -} - - -RCT_EXPORT_METHOD(updateNetworkLogSnapshot:(NSString * _Nonnull)url - callbackID:(NSString * _Nonnull)callbackID - requestBody:(NSString * _Nullable)requestBody - responseBody:(NSString * _Nullable)responseBody - responseCode:(double)responseCode - requestHeaders:(NSDictionary * _Nullable)requestHeaders - responseHeaders:(NSDictionary * _Nullable)responseHeaders) -{ - // Validate and construct the URL - NSURL *requestURL = [NSURL URLWithString:url]; - if (!requestURL) { - NSLog(@"Invalid URL: %@", url); - return; - } - - // Initialize the NSMutableURLRequest - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:requestURL]; - - // Set the HTTP body if provided - if (requestBody && [requestBody isKindOfClass:[NSString class]]) { - request.HTTPBody = [requestBody dataUsingEncoding:NSUTF8StringEncoding]; - } - - // Ensure requestHeaders is a valid dictionary before setting it - if (requestHeaders && [requestHeaders isKindOfClass:[NSDictionary class]]) { - request.allHTTPHeaderFields = requestHeaders; - } else { - NSLog(@"Invalid requestHeaders format, expected NSDictionary."); - } - - // Ensure callbackID is valid and the completion handler exists - IBGURLRequestAsyncObfuscationCompletedHandler completionHandler = self.requestObfuscationCompletionDictionary[callbackID]; - if (callbackID && [callbackID isKindOfClass:[NSString class]] && completionHandler) { - // Call the completion handler with the constructed request - completionHandler(request); - } else { - NSLog(@"CallbackID not found or completion handler is unavailable for CallbackID: %@", callbackID); - } -} - -RCT_EXPORT_METHOD(setNetworkLoggingRequestFilterPredicateIOS: (NSString * _Nonnull) callbackID : (BOOL)value ){ - - if (self.requestFilteringCompletionDictionary[callbackID] != nil) { - // ⬇️ YES == Request will be saved, NO == will be ignored - ((IBGURLRequestResponseAsyncFilteringCompletedHandler)self.requestFilteringCompletionDictionary[callbackID])(value); - } else { - NSLog(@"Not Available Completion"); - } -} - - -#pragma mark - Helper Methods - -// Set up the filtering handler -- (void)setupRequestFilteringHandler { - [IBGNetworkLogger setCPRequestFilteringHandler:^(NSURLRequest * _Nonnull request, void (^ _Nonnull completion)(BOOL)) { - NSString *callbackID = [[[NSUUID alloc] init] UUIDString]; - self.requestFilteringCompletionDictionary[callbackID] = completion; - - NSDictionary *dict = [self createNetworkRequestDictForRequest:request callbackID:callbackID]; - if(hasListeners){ - [self sendEventWithName:@"IBGNetworkLoggerHandler" body:dict]; - } - - }]; -} - -// Set up the obfuscation handler -- (void)setupRequestObfuscationHandler { - [IBGNetworkLogger setCPRequestAsyncObfuscationHandler:^(NSURLRequest * _Nonnull request, void (^ _Nonnull completion)(NSURLRequest * _Nonnull)) { - NSString *callbackID = [[[NSUUID alloc] init] UUIDString]; - self.requestObfuscationCompletionDictionary[callbackID] = completion; - - - NSDictionary *dict = [self createNetworkRequestDictForRequest:request callbackID:callbackID]; - if (hasListeners) { - [self sendEventWithName:@"IBGNetworkLoggerHandler" body:dict]; - } - - }]; -} - -// Helper to create a dictionary from the request and callbackID -- (NSDictionary *)createNetworkRequestDictForRequest:(NSURLRequest *)request callbackID:(NSString *)callbackID { - NSString *urlString = request.URL.absoluteString ?: @""; - NSString *bodyString = [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding] ?: @""; - NSDictionary *headerDict = request.allHTTPHeaderFields ?: @{}; - - return @{ - @"id": callbackID, - @"url": urlString, - @"requestBody": bodyString, - @"requestHeader": headerDict - }; -} - -RCT_EXPORT_METHOD(forceStartNetworkLoggingIOS) { - [IBGNetworkLogger forceStartNetworkLogging]; -} - -RCT_EXPORT_METHOD(forceStopNetworkLoggingIOS) { - [IBGNetworkLogger forceStopNetworkLogging]; -} - - - -@end diff --git a/ios/RNInstabug/InstabugReactBridge.h b/ios/RNInstabug/InstabugReactBridge.h index bd28cecd7a..1498da336d 100644 --- a/ios/RNInstabug/InstabugReactBridge.h +++ b/ios/RNInstabug/InstabugReactBridge.h @@ -138,7 +138,6 @@ w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes; - (void)addFeatureFlags:(NSDictionary *)featureFlagsMap; - (void)removeFeatureFlags:(NSArray *)featureFlags; - (void)removeAllFeatureFlags; -- (void)enableAutoMasking:(NSArray *)autoMaskingTypes; - (void)setNetworkLogBodyEnabled:(BOOL)isEnabled; @end diff --git a/ios/RNInstabug/InstabugReactBridge.m b/ios/RNInstabug/InstabugReactBridge.m index b936f2a9cc..f5237e1b7e 100644 --- a/ios/RNInstabug/InstabugReactBridge.m +++ b/ios/RNInstabug/InstabugReactBridge.m @@ -23,7 +23,7 @@ + (void)setWillSendReportHandler_private:(void(^)(IBGReport *report, void(^repor @implementation InstabugReactBridge - (NSArray *)supportedEvents { - return @[@"IBGpreSendingHandler" , @"IBGNetworkLoggerHandler"]; + return @[@"IBGpreSendingHandler"]; } RCT_EXPORT_MODULE(Instabug) @@ -439,18 +439,7 @@ + (BOOL)requiresMainQueueSetup + (BOOL)iOSVersionIsLessThan:(NSString *)iOSVersion { return [iOSVersion compare:[UIDevice currentDevice].systemVersion options:NSNumericSearch] == NSOrderedDescending; }; -RCT_EXPORT_METHOD(enableAutoMasking:(NSArray *)autoMaskingTypes) { - IBGAutoMaskScreenshotOption autoMaskingOptions = 0; - - for (NSNumber *event in autoMaskingTypes) { - - autoMaskingOptions |= [event intValue]; - } - - [Instabug setAutoMaskScreenshots: autoMaskingOptions]; - -}; RCT_EXPORT_METHOD(setNetworkLogBodyEnabled:(BOOL)isEnabled) { IBGNetworkLogger.logBodyEnabled = isEnabled; } diff --git a/ios/RNInstabug/RCTConvert+InstabugEnums.m b/ios/RNInstabug/RCTConvert+InstabugEnums.m index 4cf497c595..3e675ca2fa 100644 --- a/ios/RNInstabug/RCTConvert+InstabugEnums.m +++ b/ios/RNInstabug/RCTConvert+InstabugEnums.m @@ -109,10 +109,4 @@ @implementation RCTConvert (InstabugEnums) integerValue ); -RCT_ENUM_CONVERTER( - IBGAutoMaskScreenshotOption, - ArgsRegistry.autoMaskingTypes, - IBGAutoMaskScreenshotOptionMaskNothing, - integerValue -); @end diff --git a/ios/RNInstabug/Util/IBGNetworkLogger+CP.h b/ios/RNInstabug/Util/IBGNetworkLogger+CP.h index 1ef677c23e..805591d0ce 100644 --- a/ios/RNInstabug/Util/IBGNetworkLogger+CP.h +++ b/ios/RNInstabug/Util/IBGNetworkLogger+CP.h @@ -8,7 +8,6 @@ NS_ASSUME_NONNULL_BEGIN @property (class, atomic, assign) BOOL w3ExternalGeneratedHeaderEnabled; @property (class, atomic, assign) BOOL w3CaughtHeaderEnabled; -@property (class, atomic, assign) BOOL isNativeNetworkInterceptionFeatureEnabled; + (void)disableAutomaticCapturingOfNetworkLogs; + (void)addNetworkLogWithUrl:(NSString *_Nonnull)url @@ -55,13 +54,6 @@ NS_ASSUME_NONNULL_BEGIN generatedW3CTraceparent:(NSString * _Nullable)generatedW3CTraceparent caughtedW3CTraceparent:(NSString * _Nullable)caughtedW3CTraceparent; -+ (void)forceStartNetworkLogging; -+ (void)forceStopNetworkLogging; - -+ (void)setCPRequestAsyncObfuscationHandler:(void (^)(NSURLRequest * requestToBeObfuscated, void (^ completion)(NSURLRequest * obfuscatedRequest)))asyncObfuscationHandler; -+ (void)setCPRequestFilteringHandler:(void (^)(NSURLRequest * request, void (^completion)(BOOL keep)))requestFilteringHandler; -+ (void)setCPResponseFilteringHandler:(void (^)(NSURLResponse * response, void (^comppletion)(BOOL keep)))responseFilteringHandler; - @end NS_ASSUME_NONNULL_END diff --git a/src/modules/Instabug.ts b/src/modules/Instabug.ts index 1bcd5bf8b5..91f6c5c127 100644 --- a/src/modules/Instabug.ts +++ b/src/modules/Instabug.ts @@ -1,10 +1,5 @@ -import { - AppState, - type AppStateStatus, - findNodeHandle, - Platform, - processColor, -} from 'react-native'; +import type React from 'react'; +import { Platform, findNodeHandle, processColor } from 'react-native'; import type { NavigationContainerRefWithCurrent, @@ -18,7 +13,6 @@ import Report from '../models/Report'; import { emitter, NativeEvents, NativeInstabug } from '../native/NativeInstabug'; import { registerW3CFlagsListener } from '../utils/FeatureFlags'; import { - AutoMaskingType, ColorTheme, Locale, LogLevel, @@ -27,18 +21,11 @@ import { StringKey, WelcomeMessageMode, } from '../utils/Enums'; -import InstabugUtils, { - checkNetworkRequestHandlers, - resetNativeObfuscationListener, - setApmNetworkFlagsIfChanged, - stringifyIfNotString, -} from '../utils/InstabugUtils'; +import InstabugUtils, { stringifyIfNotString } from '../utils/InstabugUtils'; import * as NetworkLogger from './NetworkLogger'; import { captureUnhandledRejections } from '../utils/UnhandledRejectionTracking'; import type { ReproConfig } from '../models/ReproConfig'; import type { FeatureFlag } from '../models/FeatureFlag'; -import { addAppStateListener } from '../utils/AppStatesHandler'; -import { NativeNetworkLogger } from '../native/NativeNetworkLogger'; import InstabugConstants from '../utils/InstabugConstants'; import { InstabugRNConfig } from '../utils/config'; import { Logger } from '../utils/logger'; @@ -47,10 +34,6 @@ let _currentScreen: string | null = null; let _lastScreen: string | null = null; let _isFirstScreen = false; const firstScreen = 'Initial Screen'; -let _currentAppState = AppState.currentState; -let isNativeInterceptionFeatureEnabled = false; // Checks the value of "cp_native_interception_enabled" backend flag. -let hasAPMNetworkPlugin = false; // Android only: checks if the APM plugin is installed. -let shouldEnableNativeInterception = false; // For Android: used to disable APM logging inside reportNetworkLog() -> NativeAPM.networkLogAndroid(), For iOS: used to control native interception (true == enabled , false == disabled) /** * Enables or disables Instabug functionality. @@ -84,235 +67,44 @@ function reportCurrentViewForAndroid(screenName: string | null) { * Should be called in constructor of the AppRegistry component * @param config SDK configurations. See {@link InstabugConfig} for more info. */ -export const init = async (config: InstabugConfig) => { - if (Platform.OS === 'android') { - // Add android feature flags listener for android - registerW3CFlagsListener(); - addOnFeatureUpdatedListener(config); - } else { - isNativeInterceptionFeatureEnabled = await NativeNetworkLogger.isNativeInterceptionEnabled(); - - // Add app state listener to handle background/foreground transitions - addAppStateListener(async (nextAppState) => handleAppStateChange(nextAppState, config)); - - handleNetworkInterceptionMode(config); - - //Set APM networking flags for the first time - setApmNetworkFlagsIfChanged({ - isNativeInterceptionFeatureEnabled: isNativeInterceptionFeatureEnabled, - hasAPMNetworkPlugin: hasAPMNetworkPlugin, - shouldEnableNativeInterception: shouldEnableNativeInterception, - }); - } - - // call Instabug native init method - initializeNativeInstabug(config); - - // Set up error capturing and rejection handling +export const init = (config: InstabugConfig) => { InstabugUtils.captureJsErrors(); captureUnhandledRejections(); - _isFirstScreen = true; - _currentScreen = firstScreen; - - InstabugRNConfig.debugLogsLevel = config.debugLogsLevel ?? LogLevel.error; - - reportCurrentViewForAndroid(firstScreen); - setTimeout(() => { - if (_currentScreen === firstScreen) { - NativeInstabug.reportScreenChange(firstScreen); - _currentScreen = null; - } - }, 1000); -}; - -/** - * Handles app state changes and updates APM network flags if necessary. - */ -const handleAppStateChange = async (nextAppState: AppStateStatus, config: InstabugConfig) => { - // Checks if the app has come to the foreground - if (['inactive', 'background'].includes(_currentAppState) && nextAppState === 'active') { - const isUpdated = await fetchApmNetworkFlags(); - - if (isUpdated) { - refreshAPMNetworkConfigs(config); - } - } - - _currentAppState = nextAppState; -}; - -/** - * Fetches the current APM network flags. - */ -const fetchApmNetworkFlags = async () => { - let isUpdated = false; - const newNativeInterceptionFeatureEnabled = - await NativeNetworkLogger.isNativeInterceptionEnabled(); - if (isNativeInterceptionFeatureEnabled !== newNativeInterceptionFeatureEnabled) { - isNativeInterceptionFeatureEnabled = newNativeInterceptionFeatureEnabled; - isUpdated = true; - } if (Platform.OS === 'android') { - const newHasAPMNetworkPlugin = await NativeNetworkLogger.hasAPMNetworkPlugin(); - if (hasAPMNetworkPlugin !== newHasAPMNetworkPlugin) { - hasAPMNetworkPlugin = newHasAPMNetworkPlugin; - isUpdated = true; - } + registerW3CFlagsListener(); } - return isUpdated; -}; -/** - * Handles platform-specific checks and updates the network interception mode. - */ -const handleNetworkInterceptionMode = (config: InstabugConfig) => { - // Default networkInterceptionMode to JavaScript if not set + // Default networkInterceptionMode to JavaScript if (config.networkInterceptionMode == null) { config.networkInterceptionMode = NetworkInterceptionMode.javascript; } - if (Platform.OS === 'android') { - handleInterceptionModeForAndroid(config); - config.networkInterceptionMode = NetworkInterceptionMode.javascript; // Need to enable JS interceptor in all scenarios for Bugs & Crashes network logs - } else if (Platform.OS === 'ios') { - handleInterceptionModeForIOS(config); - //enable | disable native obfuscation and filtering synchronously - NetworkLogger.setNativeInterceptionEnabled(shouldEnableNativeInterception); - } - if (config.networkInterceptionMode === NetworkInterceptionMode.javascript) { NetworkLogger.setEnabled(true); } -}; -/** - * Handles the network interception logic for Android if the user set - * network interception mode with [NetworkInterceptionMode.javascript]. - */ -function handleAndroidJSInterception() { - if (isNativeInterceptionFeatureEnabled && hasAPMNetworkPlugin) { - shouldEnableNativeInterception = true; - Logger.warn( - InstabugConstants.IBG_APM_TAG + InstabugConstants.SWITCHED_TO_NATIVE_INTERCEPTION_MESSAGE, - ); - } -} - -/** - * Handles the network interception logic for Android if the user set - * network interception mode with [NetworkInterceptionMode.native]. - */ -function handleAndroidNativeInterception() { - if (isNativeInterceptionFeatureEnabled) { - shouldEnableNativeInterception = hasAPMNetworkPlugin; - if (!hasAPMNetworkPlugin) { - Logger.error(InstabugConstants.IBG_APM_TAG + InstabugConstants.PLUGIN_NOT_INSTALLED_MESSAGE); - } - } else { - shouldEnableNativeInterception = false; // rollback to use JS interceptor for APM & Core. - Logger.error( - InstabugConstants.IBG_APM_TAG + InstabugConstants.NATIVE_INTERCEPTION_DISABLED_MESSAGE, - ); - } -} - -/** - * Control either to enable or disable the native interception for iOS after the init method is called. - */ -function handleIOSNativeInterception(config: InstabugConfig) { - if ( - shouldEnableNativeInterception && - config.networkInterceptionMode === NetworkInterceptionMode.native - ) { - NativeNetworkLogger.forceStartNetworkLoggingIOS(); // Enable native iOS automatic network logging. - } else { - NativeNetworkLogger.forceStopNetworkLoggingIOS(); // Disable native iOS automatic network logging. - } -} - -/** - * Handles the network interception mode logic for Android. - * By deciding which interception mode should be enabled (Native or JavaScript). - */ -const handleInterceptionModeForAndroid = (config: InstabugConfig) => { - const { networkInterceptionMode } = config; - - if (networkInterceptionMode === NetworkInterceptionMode.javascript) { - handleAndroidJSInterception(); - } else { - handleAndroidNativeInterception(); - } -}; - -/** - * Handles the interception mode logic for iOS. - * By deciding which interception mode should be enabled (Native or JavaScript). - */ -const handleInterceptionModeForIOS = (config: InstabugConfig) => { - if (config.networkInterceptionMode === NetworkInterceptionMode.native) { - if (isNativeInterceptionFeatureEnabled) { - shouldEnableNativeInterception = true; - NetworkLogger.setEnabled(false); // insure JS interceptor is disabled - } else { - shouldEnableNativeInterception = false; - NetworkLogger.setEnabled(true); // rollback to JS interceptor - Logger.error( - InstabugConstants.IBG_APM_TAG + InstabugConstants.NATIVE_INTERCEPTION_DISABLED_MESSAGE, - ); - } - } -}; - -/** - * Initializes Instabug with the given configuration. - */ -const initializeNativeInstabug = (config: InstabugConfig) => { NativeInstabug.init( config.token, config.invocationEvents, config.debugLogsLevel ?? LogLevel.error, - shouldEnableNativeInterception && - config.networkInterceptionMode === NetworkInterceptionMode.native, + config.networkInterceptionMode === NetworkInterceptionMode.native, config.codePushVersion, ); -}; -/** - * Refresh the APM network configurations. - */ -function refreshAPMNetworkConfigs(config: InstabugConfig, forceRefreshIOS: boolean = true) { - handleNetworkInterceptionMode(config); - if (Platform.OS === 'ios' && forceRefreshIOS) { - handleIOSNativeInterception(config); - } - setApmNetworkFlagsIfChanged({ - isNativeInterceptionFeatureEnabled, - hasAPMNetworkPlugin, - shouldEnableNativeInterception, - }); - if (shouldEnableNativeInterception) { - checkNetworkRequestHandlers(); - } else { - // remove any attached [NativeNetworkLogger] Listeners if exists, to avoid memory leaks. - resetNativeObfuscationListener(); - } -} + _isFirstScreen = true; + _currentScreen = firstScreen; -/** - * Add Android Listener for native feature flags changes. - */ -function addOnFeatureUpdatedListener(config: InstabugConfig) { - emitter.addListener(NativeEvents.IBG_ON_FEATURES_UPDATED_CALLBACK, (flags) => { - const { cpNativeInterceptionEnabled, hasAPMPlugin } = flags; - isNativeInterceptionFeatureEnabled = cpNativeInterceptionEnabled; - hasAPMNetworkPlugin = hasAPMPlugin; - shouldEnableNativeInterception = - config.networkInterceptionMode === NetworkInterceptionMode.native; - refreshAPMNetworkConfigs(config); - }); - NativeInstabug.setOnFeaturesUpdatedListener(); -} + InstabugRNConfig.debugLogsLevel = config.debugLogsLevel ?? LogLevel.error; + + reportCurrentViewForAndroid(firstScreen); + setTimeout(() => { + if (_currentScreen === firstScreen) { + NativeInstabug.reportScreenChange(firstScreen); + _currentScreen = null; + } + }, 1000); +}; /** * Sets the Code Push version to be sent with each report. @@ -886,11 +678,3 @@ export const _registerW3CFlagsChangeListener = ( }); NativeInstabug.registerW3CFlagsChangeListener(); }; - -/** - * Sets the auto mask screenshots types. - * @param autoMaskingTypes The masking type to be applied. - */ -export const enableAutoMasking = (autoMaskingTypes: AutoMaskingType[]) => { - NativeInstabug.enableAutoMasking(autoMaskingTypes); -}; diff --git a/src/modules/NetworkLogger.ts b/src/modules/NetworkLogger.ts index 8de927c663..4e6b6d3794 100644 --- a/src/modules/NetworkLogger.ts +++ b/src/modules/NetworkLogger.ts @@ -2,32 +2,16 @@ import type { RequestHandler } from '@apollo/client'; import InstabugConstants from '../utils/InstabugConstants'; import xhr, { NetworkData, ProgressCallback } from '../utils/XhrNetworkInterceptor'; +import { isContentTypeNotAllowed, reportNetworkLog } from '../utils/InstabugUtils'; import { InstabugRNConfig } from '../utils/config'; import { Logger } from '../utils/logger'; import { NativeInstabug } from '../native/NativeInstabug'; -import { - isContentTypeNotAllowed, - registerFilteringAndObfuscationListener, - registerFilteringListener, - registerObfuscationListener, - reportNetworkLog, -} from '../utils/InstabugUtils'; -import { - NativeNetworkLogger, - NativeNetworkLoggerEvent, - NetworkListenerType, - NetworkLoggerEmitter, -} from '../native/NativeNetworkLogger'; -import { Platform } from 'react-native'; export type { NetworkData }; export type NetworkDataObfuscationHandler = (data: NetworkData) => Promise; let _networkDataObfuscationHandler: NetworkDataObfuscationHandler | null | undefined; let _requestFilterExpression = 'false'; -let _isNativeInterceptionEnabled = false; -let _networkListener: NetworkListenerType | null = null; -let hasFilterExpression = false; function getPortFromUrl(url: string) { const portMatch = url.match(/:(\d+)(?=\/|$)/); @@ -92,22 +76,6 @@ export const setEnabled = (isEnabled: boolean) => { } }; -/** - * @internal - * Sets whether enabling or disabling native network interception. - * It is disabled by default. - * @param isEnabled - */ -export const setNativeInterceptionEnabled = (isEnabled: boolean) => { - _isNativeInterceptionEnabled = isEnabled; -}; - -export const getNetworkDataObfuscationHandler = () => _networkDataObfuscationHandler; - -export const getRequestFilterExpression = () => _requestFilterExpression; - -export const hasRequestFilterExpression = () => hasFilterExpression; - /** * Obfuscates any response data. * @param handler @@ -116,13 +84,6 @@ export const setNetworkDataObfuscationHandler = ( handler?: NetworkDataObfuscationHandler | null | undefined, ) => { _networkDataObfuscationHandler = handler; - if (_isNativeInterceptionEnabled && Platform.OS === 'ios') { - if (hasFilterExpression) { - registerFilteringAndObfuscationListener(_requestFilterExpression); - } else { - registerObfuscationListener(); - } - } }; /** @@ -131,15 +92,6 @@ export const setNetworkDataObfuscationHandler = ( */ export const setRequestFilterExpression = (expression: string) => { _requestFilterExpression = expression; - hasFilterExpression = true; - - if (_isNativeInterceptionEnabled && Platform.OS === 'ios') { - if (_networkDataObfuscationHandler) { - registerFilteringAndObfuscationListener(_requestFilterExpression); - } else { - registerFilteringListener(_requestFilterExpression); - } - } }; /** @@ -171,84 +123,3 @@ export const apolloLinkRequestHandler: RequestHandler = (operation, forward) => export const setNetworkLogBodyEnabled = (isEnabled: boolean) => { NativeInstabug.setNetworkLogBodyEnabled(isEnabled); }; - -/** - * @internal - * Exported for internal/testing purposes only. - */ -export const resetNetworkListener = () => { - if (process.env.NODE_ENV === 'test') { - _networkListener = null; - NativeNetworkLogger.resetNetworkLogsListener(); - } else { - Logger.error( - `${InstabugConstants.IBG_APM_TAG}: The \`resetNetworkListener()\` method is intended solely for testing purposes.`, - ); - } -}; - -/** - * @internal - * Exported for internal/testing purposes only. - */ -export const registerNetworkLogsListener = ( - type: NetworkListenerType, - handler?: (networkSnapshot: NetworkData) => void, -) => { - if (Platform.OS === 'ios') { - // remove old listeners - if (NetworkLoggerEmitter.listenerCount(NativeNetworkLoggerEvent.NETWORK_LOGGER_HANDLER) > 0) { - NetworkLoggerEmitter.removeAllListeners(NativeNetworkLoggerEvent.NETWORK_LOGGER_HANDLER); - } - - if (_networkListener == null) { - // set new listener. - _networkListener = type; - } else { - // attach a new listener to the existing one. - _networkListener = NetworkListenerType.both; - } - } - - NetworkLoggerEmitter.addListener( - NativeNetworkLoggerEvent.NETWORK_LOGGER_HANDLER, - (networkSnapshot) => { - // Mapping the data [Native -> React-Native]. - const { id, url, requestHeader, requestBody, responseHeader, response, responseCode } = - networkSnapshot; - - const networkSnapshotObj: NetworkData = { - id: id, - url: url, - requestBody: requestBody, - requestHeaders: requestHeader, - method: '', - responseBody: response, - responseCode: responseCode, - responseHeaders: responseHeader, - contentType: '', - duration: 0, - requestBodySize: 0, - responseBodySize: 0, - errorDomain: '', - errorCode: 0, - startTime: 0, - serverErrorMessage: '', - requestContentType: '', - isW3cHeaderFound: true, - networkStartTimeInSeconds: 0, - partialId: 0, - w3cCaughtHeader: '', - w3cGeneratedHeader: '', - }; - if (handler) { - handler(networkSnapshotObj); - } - }, - ); - if (Platform.OS === 'ios') { - NativeNetworkLogger.registerNetworkLogsListener(_networkListener ?? NetworkListenerType.both); - } else { - NativeNetworkLogger.registerNetworkLogsListener(); - } -}; diff --git a/src/native/NativeConstants.ts b/src/native/NativeConstants.ts index 4d93e84ff4..a4e98e2c86 100644 --- a/src/native/NativeConstants.ts +++ b/src/native/NativeConstants.ts @@ -13,8 +13,8 @@ export type NativeConstants = NativeSdkDebugLogsLevel & NativeLocale & NativeNonFatalErrorLevel & NativeStringKey & - NativeLaunchType & - NativeAutoMaskingType; + NativeLaunchType; + interface NativeSdkDebugLogsLevel { sdkDebugLogsLevelVerbose: any; sdkDebugLogsLevelDebug: any; @@ -195,10 +195,3 @@ interface NativeLaunchType { warm: any; unknown: any; } - -interface NativeAutoMaskingType { - labels: any; - textInputs: any; - media: any; - none: any; -} diff --git a/src/native/NativeInstabug.ts b/src/native/NativeInstabug.ts index 257c2dbf1d..7fca0bea26 100644 --- a/src/native/NativeInstabug.ts +++ b/src/native/NativeInstabug.ts @@ -2,7 +2,6 @@ import { NativeEventEmitter, NativeModule, ProcessedColorValue } from 'react-nat import type Report from '../models/Report'; import type { - AutoMaskingType, ColorTheme, InvocationEvent, Locale, @@ -154,16 +153,12 @@ export interface InstabugNativeModule extends NativeModule { // W3C Feature Flags Listener for Android registerW3CFlagsChangeListener(): void; - enableAutoMasking(autoMaskingTypes: AutoMaskingType[]): void; - - setOnFeaturesUpdatedListener(handler?: (params: any) => void): void; // android only } export const NativeInstabug = NativeModules.Instabug; export enum NativeEvents { PRESENDING_HANDLER = 'IBGpreSendingHandler', - IBG_ON_FEATURES_UPDATED_CALLBACK = 'IBGOnFeatureUpdatedCallback', ON_W3C_FLAGS_CHANGE = 'IBGOnNewW3CFlagsUpdateReceivedCallback', } diff --git a/src/native/NativeNetworkLogger.ts b/src/native/NativeNetworkLogger.ts deleted file mode 100644 index 4162a0fbff..0000000000 --- a/src/native/NativeNetworkLogger.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { NativeModules } from './NativePackage'; -import { NativeEventEmitter, type NativeModule } from 'react-native'; - -export enum NetworkListenerType { - filtering = 'filtering', - obfuscation = 'obfuscation', - both = 'both', -} - -export interface NetworkLoggerNativeModule extends NativeModule { - isNativeInterceptionEnabled(): Promise; - - registerNetworkLogsListener(type?: NetworkListenerType): void; - - updateNetworkLogSnapshot( - url: string, - callbackID: string, - requestBody: string | null, - responseBody: string | null, - responseCode: number, - requestHeaders: Record, - responseHeaders: Record, - ): void; - - hasAPMNetworkPlugin(): Promise; // Android only - - resetNetworkLogsListener(): void; //Android only - - setNetworkLoggingRequestFilterPredicateIOS(id: string, value: boolean): void; // iOS only - - forceStartNetworkLoggingIOS(): void; // iOS only; - - forceStopNetworkLoggingIOS(): void; // iOS only; -} - -export const NativeNetworkLogger = NativeModules.IBGNetworkLogger; - -export enum NativeNetworkLoggerEvent { - NETWORK_LOGGER_HANDLER = 'IBGNetworkLoggerHandler', -} - -export const NetworkLoggerEmitter = new NativeEventEmitter(NativeNetworkLogger); diff --git a/src/native/NativePackage.ts b/src/native/NativePackage.ts index 51ac6fd0c7..9c31789bd4 100644 --- a/src/native/NativePackage.ts +++ b/src/native/NativePackage.ts @@ -8,7 +8,6 @@ import type { InstabugNativeModule } from './NativeInstabug'; import type { RepliesNativeModule } from './NativeReplies'; import type { SurveysNativeModule } from './NativeSurveys'; import type { SessionReplayNativeModule } from './NativeSessionReplay'; -import type { NetworkLoggerNativeModule } from './NativeNetworkLogger'; export interface InstabugNativePackage { IBGAPM: ApmNativeModule; @@ -19,7 +18,6 @@ export interface InstabugNativePackage { IBGReplies: RepliesNativeModule; IBGSurveys: SurveysNativeModule; IBGSessionReplay: SessionReplayNativeModule; - IBGNetworkLogger: NetworkLoggerNativeModule; } export const NativeModules = ReactNativeModules as InstabugNativePackage; diff --git a/src/utils/AppStatesHandler.ts b/src/utils/AppStatesHandler.ts deleted file mode 100644 index ac71f50b91..0000000000 --- a/src/utils/AppStatesHandler.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { AppState, type AppStateStatus } from 'react-native'; - -let subscription: any = null; - -// Register the event listener manually -export const addAppStateListener = (handleAppStateChange: (state: AppStateStatus) => void) => { - if (!subscription) { - subscription = AppState.addEventListener('change', handleAppStateChange); - } -}; - -// Unregister the event listener manually -//todo: find where to Unregister appState listener -export const removeAppStateListener = () => { - if (subscription) { - subscription.remove(); - subscription = null; - } -}; diff --git a/src/utils/Enums.ts b/src/utils/Enums.ts index 14864351ba..37ffa33ce3 100644 --- a/src/utils/Enums.ts +++ b/src/utils/Enums.ts @@ -241,9 +241,3 @@ export enum LaunchType { */ warm = constants.warm, } -export enum AutoMaskingType { - labels = constants.labels, - textInputs = constants.textInputs, - media = constants.media, - none = constants.none, -} diff --git a/src/utils/InstabugConstants.ts b/src/utils/InstabugConstants.ts index 5d576c15b1..aedc840701 100644 --- a/src/utils/InstabugConstants.ts +++ b/src/utils/InstabugConstants.ts @@ -12,13 +12,6 @@ const InstabugConstants = { REMOVE_USER_ATTRIBUTES_ERROR_TYPE_MESSAGE: 'IBG-RN: Expected key and value passed to removeUserAttribute to be of type string', DEFAULT_METRO_PORT: '8081', - IBG_APM_TAG: 'IBG-APM: ', - SWITCHED_TO_NATIVE_INTERCEPTION_MESSAGE: - 'Android Plugin Detected. Switched to Native Interception.', - PLUGIN_NOT_INSTALLED_MESSAGE: - 'Network Spans will not be captured as Android Plugin is not installed. Disabling Native Interception to minimize data loss.', - NATIVE_INTERCEPTION_DISABLED_MESSAGE: - 'Network Spans capture is disabled by Instabug. Disabling native interception to avoid data loss.', }; export default InstabugConstants; diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index b70153a7dd..df19f0d42a 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -8,41 +8,10 @@ import type { NavigationState as NavigationStateV5, PartialState } from '@react- import type { NavigationState as NavigationStateV4 } from 'react-navigation'; import type { CrashData } from '../native/NativeCrashReporting'; -import { NativeCrashReporting } from '../native/NativeCrashReporting'; import type { NetworkData } from './XhrNetworkInterceptor'; +import { NativeCrashReporting } from '../native/NativeCrashReporting'; import { NativeInstabug } from '../native/NativeInstabug'; import { NativeAPM } from '../native/NativeAPM'; -import * as NetworkLogger from '../modules/NetworkLogger'; -import { - NativeNetworkLogger, - NativeNetworkLoggerEvent, - NetworkListenerType, - NetworkLoggerEmitter, -} from '../native/NativeNetworkLogger'; - -type ApmNetworkFlags = { - isNativeInterceptionFeatureEnabled: boolean; - hasAPMNetworkPlugin: boolean; - shouldEnableNativeInterception: boolean; -}; - -let apmFlags: ApmNetworkFlags = { - isNativeInterceptionFeatureEnabled: false, - hasAPMNetworkPlugin: false, - shouldEnableNativeInterception: false, -}; - -export function setApmNetworkFlagsIfChanged(flags: ApmNetworkFlags): boolean { - if ( - flags.hasAPMNetworkPlugin === apmFlags.hasAPMNetworkPlugin && - flags.isNativeInterceptionFeatureEnabled === apmFlags.isNativeInterceptionFeatureEnabled && - flags.shouldEnableNativeInterception === apmFlags.shouldEnableNativeInterception - ) { - return false; - } - apmFlags = flags; - return true; -} export const parseErrorStack = (error: ExtendedError): StackFrame[] => { return parseErrorStackLib(error); @@ -209,7 +178,7 @@ export function isContentTypeNotAllowed(contentType: string) { return allowed.every((type) => !contentType.includes(type)); } -export const reportNetworkLog = (network: NetworkData) => { +export function reportNetworkLog(network: NetworkData) { if (Platform.OS === 'android') { const requestHeaders = JSON.stringify(network.requestHeaders); const responseHeaders = JSON.stringify(network.responseHeaders); @@ -224,37 +193,32 @@ export const reportNetworkLog = (network: NetworkData) => { responseHeaders, network.duration, ); - if ( - !apmFlags.isNativeInterceptionFeatureEnabled || - !apmFlags.hasAPMNetworkPlugin || - !apmFlags.shouldEnableNativeInterception - ) { - NativeAPM.networkLogAndroid( - network.startTime, - network.duration, - requestHeaders, - network.requestBody, - network.requestBodySize, - network.method, - network.url, - network.requestContentType, - responseHeaders, - network.responseBody, - network.responseBodySize, - network.responseCode, - network.contentType, - network.errorDomain, - { - isW3cHeaderFound: network.isW3cHeaderFound, - partialId: network.partialId, - networkStartTimeInSeconds: network.networkStartTimeInSeconds, - w3cGeneratedHeader: network.w3cGeneratedHeader, - w3cCaughtHeader: network.w3cCaughtHeader, - }, - network.gqlQueryName, - network.serverErrorMessage, - ); - } + + NativeAPM.networkLogAndroid( + network.startTime, + network.duration, + requestHeaders, + network.requestBody, + network.requestBodySize, + network.method, + network.url, + network.requestContentType, + responseHeaders, + network.responseBody, + network.responseBodySize, + network.responseCode, + network.contentType, + network.errorDomain, + { + isW3cHeaderFound: network.isW3cHeaderFound, + partialId: network.partialId, + networkStartTimeInSeconds: network.networkStartTimeInSeconds, + w3cGeneratedHeader: network.w3cGeneratedHeader, + w3cCaughtHeader: network.w3cCaughtHeader, + }, + network.gqlQueryName, + network.serverErrorMessage, + ); } else { NativeInstabug.networkLogIOS( network.url, @@ -282,125 +246,6 @@ export const reportNetworkLog = (network: NetworkData) => { }, ); } -}; - -/** - * @internal - * This method is for internal use only. - */ -export function registerObfuscationListener() { - NetworkLogger.registerNetworkLogsListener( - NetworkListenerType.obfuscation, - async (networkSnapshot) => { - const _networkDataObfuscationHandler = NetworkLogger.getNetworkDataObfuscationHandler(); - if (_networkDataObfuscationHandler) { - networkSnapshot = await _networkDataObfuscationHandler(networkSnapshot); - } - updateNetworkLogSnapshot(networkSnapshot); - }, - ); -} - -/** - * @internal - * This method is for internal use only. - */ -export function registerFilteringListener(filterExpression: string) { - NetworkLogger.registerNetworkLogsListener( - NetworkListenerType.filtering, - async (networkSnapshot) => { - // eslint-disable-next-line no-new-func - const predicate = Function('network', 'return ' + filterExpression); - const value = predicate(networkSnapshot); - if (Platform.OS === 'ios') { - // For iOS True == Request will be saved, False == will be ignored - NativeNetworkLogger.setNetworkLoggingRequestFilterPredicateIOS(networkSnapshot.id, !value); - } else { - // For Android Setting the [url] to an empty string will ignore the request; - if (value) { - networkSnapshot.url = ''; - updateNetworkLogSnapshot(networkSnapshot); - } - } - }, - ); -} - -/** - * @internal - * This method is for internal use only. - */ -export function registerFilteringAndObfuscationListener(filterExpression: string) { - NetworkLogger.registerNetworkLogsListener(NetworkListenerType.both, async (networkSnapshot) => { - // eslint-disable-next-line no-new-func - const predicate = Function('network', 'return ' + filterExpression); - const value = predicate(networkSnapshot); - if (Platform.OS === 'ios') { - // For iOS True == Request will be saved, False == will be ignored - NativeNetworkLogger.setNetworkLoggingRequestFilterPredicateIOS(networkSnapshot.id, !value); - } else { - // For Android Setting the [url] to an empty string will ignore the request; - if (value) { - networkSnapshot.url = ''; - updateNetworkLogSnapshot(networkSnapshot); - } - } - if (!value) { - const _networkDataObfuscationHandler = NetworkLogger.getNetworkDataObfuscationHandler(); - if (_networkDataObfuscationHandler) { - networkSnapshot = await _networkDataObfuscationHandler(networkSnapshot); - } - updateNetworkLogSnapshot(networkSnapshot); - } - }); -} - -/** - * @internal - * This method is for internal use only. - */ -export function checkNetworkRequestHandlers() { - const obfuscationHandler = NetworkLogger.getNetworkDataObfuscationHandler(); - const hasFilterExpression = NetworkLogger.hasRequestFilterExpression(); - - if (hasFilterExpression && obfuscationHandler) { - // Register listener that handles both (Filtering & Obfuscation) - registerFilteringAndObfuscationListener(NetworkLogger.getRequestFilterExpression()); - return; - } - if (obfuscationHandler) { - // Register listener that handles only (Obfuscation) - registerObfuscationListener(); - return; - } - - if (hasFilterExpression) { - // Register listener that handles only (Filtering) - registerFilteringListener(NetworkLogger.getRequestFilterExpression()); - return; - } -} -export function resetNativeObfuscationListener() { - if (Platform.OS === 'android') { - NativeNetworkLogger.resetNetworkLogsListener(); - } - NetworkLoggerEmitter.removeAllListeners(NativeNetworkLoggerEvent.NETWORK_LOGGER_HANDLER); -} - -/** - * @internal - * This method is for internal use only. - */ -export function updateNetworkLogSnapshot(networkSnapshot: NetworkData) { - NativeNetworkLogger.updateNetworkLogSnapshot( - networkSnapshot.url, - networkSnapshot.id, - networkSnapshot.requestBody, - networkSnapshot.responseBody, - networkSnapshot.responseCode ?? 200, - networkSnapshot.requestHeaders, - networkSnapshot.responseHeaders, - ); } export default { @@ -411,7 +256,6 @@ export default { getStackTrace, stringifyIfNotString, sendCrashReport, - reportNetworkLog, generateTracePartialId, generateW3CHeader, }; diff --git a/src/utils/XhrNetworkInterceptor.ts b/src/utils/XhrNetworkInterceptor.ts index 682adc2181..4443940362 100644 --- a/src/utils/XhrNetworkInterceptor.ts +++ b/src/utils/XhrNetworkInterceptor.ts @@ -7,7 +7,6 @@ export type ProgressCallback = (totalBytesSent: number, totalBytesExpectedToSend export type NetworkDataCallback = (data: NetworkData) => void; export interface NetworkData { - readonly id: string; url: string; method: string; requestBody: string; @@ -44,7 +43,6 @@ let network: NetworkData; const _reset = () => { network = { - id: '', url: '', method: '', requestBody: '', diff --git a/test/mocks/mockInstabug.ts b/test/mocks/mockInstabug.ts index fc0f8917f7..eb02f16f18 100644 --- a/test/mocks/mockInstabug.ts +++ b/test/mocks/mockInstabug.ts @@ -73,9 +73,7 @@ const mockInstabug: InstabugNativeModule = { isW3ExternalGeneratedHeaderEnabled: jest.fn(), isW3CaughtHeaderEnabled: jest.fn(), registerW3CFlagsChangeListener: jest.fn(), - enableAutoMasking: jest.fn(), setNetworkLogBodyEnabled: jest.fn(), - setOnFeaturesUpdatedListener: jest.fn(), }; export default mockInstabug; diff --git a/test/mocks/mockNativeModules.ts b/test/mocks/mockNativeModules.ts index 6d4c19face..5618930e83 100644 --- a/test/mocks/mockNativeModules.ts +++ b/test/mocks/mockNativeModules.ts @@ -7,12 +7,10 @@ import mockSessionReplay from './mockSessionReplay'; import mockInstabug from './mockInstabug'; import mockReplies from './mockReplies'; import mockSurveys from './mockSurveys'; -import mockNetworkLogger from './mockNetworkLogger'; jest.mock('react-native', () => { const RN = jest.requireActual('react-native'); const mockNativeModules: InstabugNativePackage = { - IBGNetworkLogger: mockNetworkLogger, IBGAPM: mockAPM, IBGBugReporting: mockBugReporting, IBGCrashReporting: mockCrashReporting, diff --git a/test/mocks/mockNetworkLogger.ts b/test/mocks/mockNetworkLogger.ts index 88608016ce..0eaed26e0d 100644 --- a/test/mocks/mockNetworkLogger.ts +++ b/test/mocks/mockNetworkLogger.ts @@ -1,16 +1 @@ -import type { NetworkLoggerNativeModule } from '../../src/native/NativeNetworkLogger'; - -const mockNetworkLogger: NetworkLoggerNativeModule = { - addListener: jest.fn(), - removeListeners: jest.fn(), - hasAPMNetworkPlugin: jest.fn(), - isNativeInterceptionEnabled: jest.fn(), - forceStartNetworkLoggingIOS: jest.fn(), - forceStopNetworkLoggingIOS: jest.fn(), - registerNetworkLogsListener: jest.fn(), - updateNetworkLogSnapshot: jest.fn(), - setNetworkLoggingRequestFilterPredicateIOS: jest.fn(), - resetNetworkLogsListener: jest.fn(), -}; - -export default mockNetworkLogger; +jest.mock('../../src/modules/NetworkLogger'); diff --git a/test/modules/Instabug.spec.ts b/test/modules/Instabug.spec.ts index 6e0f738277..d1bca25c90 100644 --- a/test/modules/Instabug.spec.ts +++ b/test/modules/Instabug.spec.ts @@ -1,18 +1,18 @@ import '../mocks/mockInstabugUtils'; import '../mocks/mockNetworkLogger'; -import { findNodeHandle, Platform, processColor } from 'react-native'; +import { Platform, findNodeHandle, processColor } from 'react-native'; import type { NavigationContainerRefWithCurrent } from '@react-navigation/native'; // Import the hook + import { mocked } from 'jest-mock'; import waitForExpect from 'wait-for-expect'; import Report from '../../src/models/Report'; import * as Instabug from '../../src/modules/Instabug'; import * as NetworkLogger from '../../src/modules/NetworkLogger'; -import { emitter, NativeEvents, NativeInstabug } from '../../src/native/NativeInstabug'; +import { NativeEvents, NativeInstabug, emitter } from '../../src/native/NativeInstabug'; import { ColorTheme, - type InstabugConfig, InvocationEvent, Locale, LogLevel, @@ -20,18 +20,11 @@ import { ReproStepsMode, StringKey, WelcomeMessageMode, -} from '../../src'; +} from '../../src/utils/Enums'; import InstabugUtils from '../../src/utils/InstabugUtils'; import type { FeatureFlag } from '../../src/models/FeatureFlag'; -import { Logger } from '../../src/utils/logger'; -import { NativeNetworkLogger } from '../../src/native/NativeNetworkLogger'; import InstabugConstants from '../../src/utils/InstabugConstants'; - -jest.mock('../../src/modules/NetworkLogger'); - -function fakeTimer(callback: () => void) { - setTimeout(callback, 100); -} +import { Logger } from '../../src/utils/logger'; describe('Instabug Module', () => { beforeEach(() => { @@ -69,7 +62,7 @@ describe('Instabug Module', () => { }); it("componentDidAppearListener shouldn't call the native method reportScreenChange if first screen", async () => { - await Instabug.init({ + Instabug.init({ token: 'some-token', invocationEvents: [InvocationEvent.none], }); @@ -282,7 +275,7 @@ describe('Instabug Module', () => { expect(onStateChangeMock).toHaveBeenCalledWith(mockNavigationContainerRef.getRootState()); }); - it('should call the native method init', async () => { + it('should call the native method init', () => { const instabugConfig = { token: 'some-token', invocationEvents: [InvocationEvent.floatingButton, InvocationEvent.shake], @@ -291,7 +284,7 @@ describe('Instabug Module', () => { }; const usesNativeNetworkInterception = false; - await Instabug.init(instabugConfig); + Instabug.init(instabugConfig); expect(NetworkLogger.setEnabled).toBeCalledWith(true); expect(NativeInstabug.init).toBeCalledTimes(1); @@ -313,7 +306,7 @@ describe('Instabug Module', () => { expect(NativeInstabug.setCodePushVersion).toBeCalledWith(codePushVersion); }); - it('init should disable JavaScript interceptor when using native interception mode', async () => { + it('init should disable JavaScript interceptor when using native interception mode', () => { const instabugConfig = { token: 'some-token', invocationEvents: [InvocationEvent.floatingButton, InvocationEvent.shake], @@ -322,38 +315,18 @@ describe('Instabug Module', () => { codePushVersion: '1.1.0', }; - // Stubbing Network feature flags - jest - .spyOn(NativeNetworkLogger, 'isNativeInterceptionEnabled') - .mockReturnValue(Promise.resolve(true)); - jest.spyOn(NativeNetworkLogger, 'hasAPMNetworkPlugin').mockReturnValue(Promise.resolve(true)); - - await Instabug.init(instabugConfig); - - if (Platform.OS === 'android') { - expect(NetworkLogger.setEnabled).not.toBeCalled(); - expect(NativeInstabug.init).toBeCalledTimes(1); - - expect(NativeInstabug.init).toBeCalledWith( - instabugConfig.token, - instabugConfig.invocationEvents, - instabugConfig.debugLogsLevel, - // usesNativeNetworkInterception should be false when using native interception mode with Android - false, - instabugConfig.codePushVersion, - ); - } else { - expect(NativeInstabug.init).toBeCalledTimes(1); - - expect(NativeInstabug.init).toBeCalledWith( - instabugConfig.token, - instabugConfig.invocationEvents, - instabugConfig.debugLogsLevel, - // usesNativeNetworkInterception should be true when using native interception mode with iOS - true, - instabugConfig.codePushVersion, - ); - } + Instabug.init(instabugConfig); + + expect(NetworkLogger.setEnabled).not.toBeCalled(); + expect(NativeInstabug.init).toBeCalledTimes(1); + expect(NativeInstabug.init).toBeCalledWith( + instabugConfig.token, + instabugConfig.invocationEvents, + instabugConfig.debugLogsLevel, + // usesNativeNetworkInterception should be true when using native interception mode + true, + instabugConfig.codePushVersion, + ); }); it('should report the first screen on SDK initialization', async () => { @@ -915,188 +888,3 @@ describe('Instabug Module', () => { expect(callback).toHaveBeenCalled(); }); }); - -describe('Instabug iOS initialization tests', () => { - let config: InstabugConfig; - beforeEach(() => { - Platform.OS = 'ios'; - config = { - token: 'some-token', - invocationEvents: [InvocationEvent.floatingButton, InvocationEvent.shake], - debugLogsLevel: LogLevel.debug, - networkInterceptionMode: NetworkInterceptionMode.native, - codePushVersion: '1.1.0', - }; - // Fast-forward until all timers have been executed - jest.advanceTimersByTime(1000); - }); - - it('should initialize correctly with javascript interception mode', async () => { - config.networkInterceptionMode = NetworkInterceptionMode.javascript; - - await Instabug.init(config); - - expect(NativeNetworkLogger.isNativeInterceptionEnabled).toHaveBeenCalled(); - expect(NetworkLogger.setEnabled).toHaveBeenCalledWith(true); - expect(NativeInstabug.init).toHaveBeenCalledWith( - config.token, - config.invocationEvents, - config.debugLogsLevel, - false, // Disable native interception - config.codePushVersion, - ); - }); - - it('should initialize correctly with native interception mode when [isNativeInterceptionEnabled] == ture', async () => { - jest - .spyOn(NativeNetworkLogger, 'isNativeInterceptionEnabled') - .mockReturnValue(Promise.resolve(true)); - - await Instabug.init(config); - - expect(NativeNetworkLogger.isNativeInterceptionEnabled).toHaveBeenCalled(); - expect(NetworkLogger.setEnabled).toHaveBeenCalledWith(false); - expect(NativeInstabug.init).toHaveBeenCalledWith( - config.token, - config.invocationEvents, - config.debugLogsLevel, - true, // Enable native interception - config.codePushVersion, - ); - }); - - it('should disable native interception mode when user sets networkInterceptionMode to native and [isNativeInterceptionEnabled] == false', async () => { - jest - .spyOn(NativeNetworkLogger, 'isNativeInterceptionEnabled') - .mockReturnValue(Promise.resolve(false)); - - await Instabug.init(config); - - expect(NativeNetworkLogger.isNativeInterceptionEnabled).toHaveBeenCalled(); - expect(NetworkLogger.setEnabled).toHaveBeenCalled(); - expect(NativeInstabug.init).toHaveBeenCalledWith( - config.token, - config.invocationEvents, - config.debugLogsLevel, - false, // Disable native interception - config.codePushVersion, - ); - }); - - it('should display error message when user sets networkInterceptionMode to native and [isNativeInterceptionEnabled] == false', async () => { - jest - .spyOn(NativeNetworkLogger, 'isNativeInterceptionEnabled') - .mockReturnValue(Promise.resolve(false)); - const logSpy = jest.spyOn(global.console, 'error'); - - await Instabug.init(config); - - expect(logSpy).toBeCalledTimes(1); - expect(logSpy).toBeCalledWith( - InstabugConstants.IBG_APM_TAG + InstabugConstants.NATIVE_INTERCEPTION_DISABLED_MESSAGE, - ); - }); -}); - -describe('Instabug Android initialization tests', () => { - let config: InstabugConfig; - - beforeEach(() => { - Platform.OS = 'android'; - config = { - token: 'some-token', - invocationEvents: [InvocationEvent.floatingButton, InvocationEvent.shake], - debugLogsLevel: LogLevel.debug, - networkInterceptionMode: NetworkInterceptionMode.javascript, - codePushVersion: '1.1.0', - }; - }); - - it('should initialize correctly with native interception enabled', async () => { - config.networkInterceptionMode = NetworkInterceptionMode.native; - await Instabug.init(config); - fakeTimer(() => { - expect(NativeInstabug.setOnFeaturesUpdatedListener).toHaveBeenCalled(); - expect(NetworkLogger.setEnabled).toHaveBeenCalledWith(true); - expect(NativeInstabug.init).toHaveBeenCalledWith( - config.token, - config.invocationEvents, - config.debugLogsLevel, - false, // always disable native interception to insure sending network logs to core (Bugs & Crashes). - config.codePushVersion, - ); - }); - }); - - it('should show warning message when networkInterceptionMode == javascript and user added APM plugin', async () => { - jest - .spyOn(NativeNetworkLogger, 'isNativeInterceptionEnabled') - .mockReturnValue(Promise.resolve(true)); - jest.spyOn(NativeNetworkLogger, 'hasAPMNetworkPlugin').mockReturnValue(Promise.resolve(true)); - const logSpy = jest.spyOn(global.console, 'warn'); - - await Instabug.init(config); - fakeTimer(() => { - expect(logSpy).toBeCalledTimes(1); - expect(logSpy).toBeCalledWith( - InstabugConstants.IBG_APM_TAG + InstabugConstants.SWITCHED_TO_NATIVE_INTERCEPTION_MESSAGE, - ); - }); - }); - - it('should show error message when networkInterceptionMode == native and user did not add APM plugin', async () => { - config.networkInterceptionMode = NetworkInterceptionMode.native; - - jest - .spyOn(NativeNetworkLogger, 'isNativeInterceptionEnabled') - .mockReturnValue(Promise.resolve(true)); - jest.spyOn(NativeNetworkLogger, 'hasAPMNetworkPlugin').mockReturnValue(Promise.resolve(false)); - const logSpy = jest.spyOn(global.console, 'error'); - - await Instabug.init(config); - - fakeTimer(() => { - expect(logSpy).toBeCalledTimes(1); - expect(logSpy).toBeCalledWith( - InstabugConstants.IBG_APM_TAG + InstabugConstants.PLUGIN_NOT_INSTALLED_MESSAGE, - ); - }); - }); - - it('should show error message when networkInterceptionMode == native and user did not add APM plugin and the isNativeInterceptionEnabled is disabled', async () => { - config.networkInterceptionMode = NetworkInterceptionMode.native; - - jest - .spyOn(NativeNetworkLogger, 'isNativeInterceptionEnabled') - .mockReturnValue(Promise.resolve(false)); - jest.spyOn(NativeNetworkLogger, 'hasAPMNetworkPlugin').mockReturnValue(Promise.resolve(false)); - const logSpy = jest.spyOn(global.console, 'error'); - - await Instabug.init(config); - - fakeTimer(() => { - expect(logSpy).toBeCalledTimes(1); - expect(logSpy).toBeCalledWith( - InstabugConstants.IBG_APM_TAG + InstabugConstants.NATIVE_INTERCEPTION_DISABLED_MESSAGE, - ); - }); - }); - - it('should show error message when networkInterceptionMode == native and the isNativeInterceptionEnabled is disabled', async () => { - config.networkInterceptionMode = NetworkInterceptionMode.native; - jest - .spyOn(NativeNetworkLogger, 'isNativeInterceptionEnabled') - .mockReturnValue(Promise.resolve(false)); - jest.spyOn(NativeNetworkLogger, 'hasAPMNetworkPlugin').mockReturnValue(Promise.resolve(true)); - const logSpy = jest.spyOn(global.console, 'error'); - - await Instabug.init(config); - - fakeTimer(() => { - expect(logSpy).toBeCalledTimes(1); - expect(logSpy).toBeCalledWith( - InstabugConstants.IBG_APM_TAG + InstabugConstants.NATIVE_INTERCEPTION_DISABLED_MESSAGE, - ); - }); - }); -}); diff --git a/test/modules/NetworkLogger.spec.ts b/test/modules/NetworkLogger.spec.ts index be567b8d1f..d46b10aff5 100644 --- a/test/modules/NetworkLogger.spec.ts +++ b/test/modules/NetworkLogger.spec.ts @@ -7,15 +7,6 @@ import * as NetworkLogger from '../../src/modules/NetworkLogger'; import Interceptor from '../../src/utils/XhrNetworkInterceptor'; import { isContentTypeNotAllowed, reportNetworkLog } from '../../src/utils/InstabugUtils'; import InstabugConstants from '../../src/utils/InstabugConstants'; -import * as Instabug from '../../src/modules/Instabug'; -import { - NativeNetworkLogger, - NativeNetworkLoggerEvent, - NetworkListenerType, - NetworkLoggerEmitter, -} from '../../src/native/NativeNetworkLogger'; -import { InvocationEvent, LogLevel, NetworkInterceptionMode } from '../../src'; -import { Platform } from 'react-native'; import { Logger } from '../../src/utils/logger'; import { NativeInstabug } from '../../src/native/NativeInstabug'; @@ -23,11 +14,8 @@ const clone = (obj: T): T => { return JSON.parse(JSON.stringify(obj)); }; -jest.mock('../../src/native/NativeNetworkLogger'); - describe('NetworkLogger Module', () => { const network: NetworkLogger.NetworkData = { - id: '', url: 'https://api.instabug.com', requestBody: '', requestHeaders: { 'content-type': 'application/json' }, @@ -302,118 +290,4 @@ describe('NetworkLogger Module', () => { expect(NativeInstabug.setNetworkLogBodyEnabled).toBeCalledTimes(1); expect(NativeInstabug.setNetworkLogBodyEnabled).toBeCalledWith(true); }); - - it('Instabug.init should call NativeNetworkLogger.isNativeInterceptionEnabled and not call NativeNetworkLogger.hasAPMNetworkPlugin with iOS', async () => { - Platform.OS = 'ios'; - const config = { - token: 'some-token', - invocationEvents: [InvocationEvent.floatingButton, InvocationEvent.shake], - debugLogsLevel: LogLevel.debug, - networkInterceptionMode: NetworkInterceptionMode.native, - codePushVersion: '1.1.0', - }; - await Instabug.init(config); - - expect(NativeNetworkLogger.isNativeInterceptionEnabled).toHaveBeenCalled(); - expect(NativeNetworkLogger.hasAPMNetworkPlugin).not.toHaveBeenCalled(); - }); -}); - -describe('_registerNetworkLogsListener', () => { - let handlerMock: jest.Mock; - let type: NetworkListenerType; - - beforeEach(() => { - handlerMock = jest.fn(); - type = NetworkListenerType.both; - jest.resetAllMocks(); // Reset mock implementation and calls - NetworkLogger.resetNetworkListener(); // Clear only calls, keeping implementation intact - }); - - it('should remove old listeners if they exist', () => { - Platform.OS = 'ios'; - - // Simulate that there are existing listeners - jest.spyOn(NetworkLoggerEmitter, 'listenerCount').mockReturnValue(2); - - NetworkLogger.registerNetworkLogsListener(type, handlerMock); - - expect(NetworkLoggerEmitter.removeAllListeners).toHaveBeenCalledWith( - NativeNetworkLoggerEvent.NETWORK_LOGGER_HANDLER, - ); - }); - - it('should set the new listener if _networkListener is null', () => { - Platform.OS = 'ios'; - // No existing listener - jest.spyOn(NetworkLoggerEmitter, 'listenerCount').mockReturnValue(0); - - NetworkLogger.registerNetworkLogsListener(type, handlerMock); - - expect(NetworkLoggerEmitter.addListener).toHaveBeenCalled(); - expect(NativeNetworkLogger.registerNetworkLogsListener).toHaveBeenCalledWith(type); - }); - - it('should attach a new listener to the existing one if _networkListener is set', () => { - Platform.OS = 'ios'; - - type = NetworkListenerType.filtering; - const newType = NetworkListenerType.both; - - // First call to set the listener - NetworkLogger.registerNetworkLogsListener(type, handlerMock); - - // Second call with a different type to trigger setting to `both` - NetworkLogger.registerNetworkLogsListener(newType, handlerMock); - - expect(NetworkLoggerEmitter.addListener).toHaveBeenCalledTimes(2); - expect(NativeNetworkLogger.registerNetworkLogsListener).toHaveBeenCalledWith( - NetworkListenerType.both, - ); - }); - - it('should map networkSnapshot data correctly and call handler', () => { - const mockNetworkSnapshot = { - id: '123', - url: 'http://example.com', - requestHeader: {}, - requestBody: 'test request body', - responseHeader: {}, - response: 'test response', - responseCode: 200, - }; - - (NetworkLoggerEmitter.addListener as jest.Mock).mockImplementation((_, callback) => { - callback(mockNetworkSnapshot); - }); - - NetworkLogger.registerNetworkLogsListener(type, handlerMock); - - const expectedNetworkData: NetworkLogger.NetworkData = { - id: '123', - url: 'http://example.com', - requestBody: 'test request body', - requestHeaders: {}, - method: '', - responseBody: 'test response', - responseCode: 200, - responseHeaders: {}, - contentType: '', - duration: 0, - requestBodySize: 0, - responseBodySize: 0, - errorDomain: '', - errorCode: 0, - startTime: 0, - serverErrorMessage: '', - requestContentType: '', - isW3cHeaderFound: true, - networkStartTimeInSeconds: 0, - partialId: 0, - w3cCaughtHeader: '', - w3cGeneratedHeader: '', - }; - - expect(handlerMock).toHaveBeenCalledWith(expectedNetworkData); - }); }); diff --git a/test/utils/AppStatesHandler.spec.ts b/test/utils/AppStatesHandler.spec.ts deleted file mode 100644 index c784da86a5..0000000000 --- a/test/utils/AppStatesHandler.spec.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { AppState } from 'react-native'; -import { addAppStateListener, removeAppStateListener } from '../../src/utils/AppStatesHandler'; - -jest.mock('react-native', () => ({ - AppState: { - addEventListener: jest.fn(), - }, -})); - -describe('AppState Listener', () => { - const mockHandleAppStateChange = jest.fn(); - const mockRemove = jest.fn(); - - beforeEach(() => { - jest.clearAllMocks(); - (AppState.addEventListener as jest.Mock).mockReturnValue({ remove: mockRemove }); - }); - - afterEach(() => { - removeAppStateListener(); // Ensure no leftover subscriptions between tests - }); - - it('should add an AppState listener if none exists', () => { - addAppStateListener(mockHandleAppStateChange); - - expect(AppState.addEventListener).toHaveBeenCalledTimes(1); - expect(AppState.addEventListener).toHaveBeenCalledWith('change', mockHandleAppStateChange); - }); - - it('should not add another listener if one already exists', () => { - addAppStateListener(mockHandleAppStateChange); - addAppStateListener(mockHandleAppStateChange); - - expect(AppState.addEventListener).toHaveBeenCalledTimes(1); // Only called once - }); - - it('should remove the AppState listener if one exists', () => { - addAppStateListener(mockHandleAppStateChange); - removeAppStateListener(); - - expect(mockRemove).toHaveBeenCalledTimes(1); // The remove function is called - }); - - it('should do nothing if removeAppStateListener is called without an existing subscription', () => { - removeAppStateListener(); - - expect(mockRemove).not.toHaveBeenCalled(); // No remove is called - }); - - it('should handle multiple add/remove calls properly', () => { - addAppStateListener(mockHandleAppStateChange); - removeAppStateListener(); - - addAppStateListener(mockHandleAppStateChange); - removeAppStateListener(); - - expect(AppState.addEventListener).toHaveBeenCalledTimes(2); // Listener is added twice - expect(mockRemove).toHaveBeenCalledTimes(2); // Listener is removed twice - }); -}); diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index deb2eebd0f..fd389d7f0b 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -4,30 +4,16 @@ import { Platform } from 'react-native'; import parseErrorStackLib from 'react-native/Libraries/Core/Devtools/parseErrorStack'; import * as Instabug from '../../src/modules/Instabug'; -import * as NetworkLogger from '../../src/modules/NetworkLogger'; import { NativeCrashReporting } from '../../src/native/NativeCrashReporting'; import { InvocationEvent, NetworkData, NonFatalErrorLevel } from '../../src'; import InstabugUtils, { getStackTrace, - registerFilteringAndObfuscationListener, - registerFilteringListener, - registerObfuscationListener, reportNetworkLog, - resetNativeObfuscationListener, sendCrashReport, - updateNetworkLogSnapshot, } from '../../src/utils/InstabugUtils'; - -import { - NativeNetworkLogger, - NetworkListenerType, - NetworkLoggerEmitter, -} from '../../src/native/NativeNetworkLogger'; import { NativeInstabug } from '../../src/native/NativeInstabug'; import { NativeAPM } from '../../src/native/NativeAPM'; -jest.mock('../../src/modules/NetworkLogger'); - describe('Test global error handler', () => { beforeEach(() => { Instabug.init({ token: '', invocationEvents: [InvocationEvent.none] }); @@ -256,7 +242,6 @@ describe('Instabug Utils', () => { describe('reportNetworkLog', () => { const network: NetworkData = { - id: 'id', url: 'https://api.instabug.com', method: 'GET', requestBody: 'requestBody', @@ -280,16 +265,12 @@ describe('reportNetworkLog', () => { w3cCaughtHeader: null, }; - it('reportNetworkLog should send network logs to native with the correct parameters on Android', async () => { + it('reportNetworkLog should send network logs to native with the correct parameters on Android', () => { Platform.OS = 'android'; - jest - .spyOn(NativeNetworkLogger, 'isNativeInterceptionEnabled') - .mockReturnValue(Promise.resolve(false)); - jest.spyOn(NativeNetworkLogger, 'hasAPMNetworkPlugin').mockReturnValue(Promise.resolve(false)); - await Instabug.init({ token: '', invocationEvents: [InvocationEvent.none] }); const requestHeaders = JSON.stringify(network.requestHeaders); const responseHeaders = JSON.stringify(network.responseHeaders); + reportNetworkLog(network); expect(NativeInstabug.networkLogAndroid).toHaveBeenCalledTimes(1); @@ -365,96 +346,3 @@ describe('reportNetworkLog', () => { ); }); }); - -describe('test registerNetworkLogsListener usage', () => { - beforeEach(() => { - jest.clearAllMocks(); // Clear all mocks before each test - }); - - const network: NetworkLogger.NetworkData = { - id: '', - url: 'https://api.instabug.com', - requestBody: '', - requestHeaders: { 'content-type': 'application/json' }, - method: 'GET', - responseBody: '', - responseCode: 200, - responseHeaders: { 'content-type': 'application/json' }, - contentType: 'application/json', - duration: 0, - requestBodySize: 0, - responseBodySize: 0, - errorDomain: '', - errorCode: 0, - startTime: 0, - serverErrorMessage: '', - requestContentType: 'application/json', - isW3cHeaderFound: true, - networkStartTimeInSeconds: 0, - partialId: 0, - w3cCaughtHeader: '', - w3cGeneratedHeader: '', - }; - - it('registerObfuscationListener should call NetworkLogger.registerNetworkLogsListener() with NetworkListenerType = NetworkListenerType.obfuscation', () => { - registerObfuscationListener(); - expect(NetworkLogger.registerNetworkLogsListener).toBeCalledTimes(1); - expect(NetworkLogger.registerNetworkLogsListener).toBeCalledWith( - NetworkListenerType.obfuscation, - expect.any(Function), - ); - }); - - it('registerFilteringListener should call NetworkLogger.registerNetworkLogsListener() with NetworkListenerType = NetworkListenerType.filtering', () => { - const testText = 'true'; - registerFilteringListener(testText); - - expect(NetworkLogger.registerNetworkLogsListener).toBeCalledTimes(1); - expect(NetworkLogger.registerNetworkLogsListener).toBeCalledWith( - NetworkListenerType.filtering, - expect.any(Function), - ); - }); - - it('registerFilteringAndObfuscationListener should call NetworkLogger.registerNetworkLogsListener() with NetworkListenerType = NetworkListenerType.both', () => { - const testText = 'true'; - registerFilteringAndObfuscationListener(testText); - - expect(NetworkLogger.registerNetworkLogsListener).toBeCalledTimes(1); - expect(NetworkLogger.registerNetworkLogsListener).toBeCalledWith( - NetworkListenerType.both, - expect.any(Function), - ); - }); - - it('should call NetworkLoggerEmitter.removeAllListeners when call resetNativeObfuscationListener', () => { - jest.spyOn(NetworkLoggerEmitter, 'removeAllListeners').mockImplementation(); - resetNativeObfuscationListener(); - expect(NetworkLoggerEmitter.removeAllListeners).toBeCalledTimes(1); - }); - - it('should call NativeNetworkLogger.resetNetworkLogsListener when call resetNativeObfuscationListener on android platform', () => { - Platform.OS = 'android'; - jest.spyOn(NativeNetworkLogger, 'resetNetworkLogsListener').mockImplementation(); - jest.spyOn(NetworkLoggerEmitter, 'removeAllListeners').mockImplementation(); - resetNativeObfuscationListener(); - expect(NativeNetworkLogger.resetNetworkLogsListener).toBeCalledTimes(1); - expect(NetworkLoggerEmitter.removeAllListeners).toBeCalledTimes(1); - }); - - it('should call NativeNetworkLogger.updateNetworkLogSnapshot when call updateNetworkLogSnapshot with correct parameters', () => { - jest.spyOn(NativeNetworkLogger, 'updateNetworkLogSnapshot').mockImplementation(); - - updateNetworkLogSnapshot(network); - expect(NativeNetworkLogger.updateNetworkLogSnapshot).toBeCalledTimes(1); - expect(NativeNetworkLogger.updateNetworkLogSnapshot).toHaveBeenCalledWith( - network.url, - network.id, - network.requestBody, - network.responseBody, - network.responseCode ?? 200, - network.requestHeaders, - network.responseHeaders, - ); - }); -});