Skip to content

Commit 867bfc0

Browse files
Merge remote-tracking branch 'origin/feat/network-spans-feature-flags' into feat/network-spans-unit-testing
# Conflicts: # ios/RNInstabug/InstabugNetworkLoggerBridge.m # src/native/NativeNetworkLogger.ts
2 parents 1271f4d + 2af4bdd commit 867bfc0

23 files changed

+878
-180
lines changed

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

Lines changed: 2 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,12 @@
77

88
import androidx.annotation.NonNull;
99

10-
//import com.facebook.react.bridge.Arguments;
1110
import com.facebook.react.bridge.Promise;
1211
import com.facebook.react.bridge.ReactApplicationContext;
1312
import com.facebook.react.bridge.ReactMethod;
14-
//import com.facebook.react.bridge.WritableMap;
15-
//import com.instabug.apm.InternalAPM;
16-
//import com.instabug.apm.sanitization.OnCompleteCallback;
17-
//import com.instabug.apm.sanitization.VoidSanitizer;
18-
//import com.instabug.library.logging.listeners.networklogs.NetworkLogSnapshot;
1913
import com.instabug.apm.InternalAPM;
2014
import com.instabug.reactlibrary.utils.EventEmitterModule;
2115
import com.instabug.reactlibrary.utils.MainThreadHandler;
22-
//
23-
//import org.json.JSONException;
24-
//import org.json.JSONObject;
25-
//
26-
//import java.util.concurrent.ConcurrentHashMap;
2716

2817

2918
public class RNInstabugNetworkLoggerModule extends EventEmitterModule {
@@ -32,8 +21,6 @@ public RNInstabugNetworkLoggerModule(ReactApplicationContext reactContext) {
3221
super(reactContext);
3322
}
3423

35-
// private final ConcurrentHashMap<Integer, OnCompleteCallback<NetworkLogSnapshot>> callbackMap = new ConcurrentHashMap<Integer, OnCompleteCallback<NetworkLogSnapshot>>();
36-
3724
@NonNull
3825
@Override
3926
public String getName() {
@@ -67,7 +54,7 @@ public void run() {
6754
promise.resolve(getFlagValue(CP_NATIVE_INTERCEPTION_ENABLED));
6855
} catch (Exception e) {
6956
e.printStackTrace();
70-
promise.resolve(false);
57+
promise.resolve(false); // Will rollback to JS interceptor
7158
}
7259

7360
}
@@ -88,83 +75,10 @@ public void run() {
8875
promise.resolve(getFlagValue(APM_NETWORK_PLUGIN_INSTALLED));
8976
} catch (Exception e) {
9077
e.printStackTrace();
91-
promise.resolve(false);
92-
}
93-
94-
}
95-
});
96-
}
97-
98-
/**
99-
* Indicate APM is enabled & Network logging is enabled
100-
* [true] ApmEnabled && NetworkEnabled
101-
* [false] otherwise
102-
*/
103-
@ReactMethod
104-
public void isAPMNetworkEnabled(Promise promise) {
105-
MainThreadHandler.runOnMainThread(new Runnable() {
106-
@Override
107-
public void run() {
108-
try {
109-
promise.resolve(getFlagValue(NETWORK_INTERCEPTION_ENABLED));
110-
} catch (Exception e) {
111-
e.printStackTrace();
112-
promise.resolve(false);
78+
promise.resolve(false); // Will rollback to JS interceptor
11379
}
11480

11581
}
11682
});
11783
}
118-
119-
120-
// @ReactMethod
121-
// public void registerNetworkLogsListener() {
122-
// MainThreadHandler.runOnMainThread(new Runnable() {
123-
// @Override
124-
// public void run() {
125-
// InternalAPM._registerNetworkLogSanitizer(new VoidSanitizer<NetworkLogSnapshot>() {
126-
// @Override
127-
// public void sanitize(NetworkLogSnapshot networkLogSnapshot, @NonNull OnCompleteCallback<NetworkLogSnapshot> onCompleteCallback) {
128-
// final int id = onCompleteCallback.hashCode();
129-
// callbackMap.put(id, onCompleteCallback);
130-
//
131-
// WritableMap networkSnapshotParams = Arguments.createMap();
132-
// networkSnapshotParams.putInt("id", id);
133-
// networkSnapshotParams.putString("url", networkLogSnapshot.getUrl());
134-
// networkSnapshotParams.putInt("responseCode", networkLogSnapshot.getResponseCode());
135-
//
136-
// sendEvent("IBGNetworkLoggerHandler", networkSnapshotParams);
137-
//
138-
// }
139-
// });
140-
// }
141-
// });
142-
// }
143-
//
144-
// @ReactMethod
145-
// protected void updateNetworkLogSnapshot(String jsonString) {
146-
//
147-
// JSONObject newJSONObject = null;
148-
// try {
149-
// newJSONObject = new JSONObject(jsonString);
150-
// } catch (JSONException e) {
151-
// throw new RuntimeException(e);
152-
// }
153-
// final Integer ID = newJSONObject.optInt("id");
154-
// final NetworkLogSnapshot modifiedSnapshot = new NetworkLogSnapshot(
155-
// newJSONObject.optString("url"),
156-
// null,
157-
// null,
158-
// null,
159-
// null,
160-
// newJSONObject.optInt("responseCode")
161-
// );
162-
//
163-
// final OnCompleteCallback<NetworkLogSnapshot> callback = callbackMap.get(ID);
164-
// if (callback != null) {
165-
// callback.onComplete(null);
166-
// }
167-
// callbackMap.remove(ID);
168-
//
169-
// }
17084
}
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
package com.instabug.reactlibrary;
2+
3+
import static com.instabug.apm.configuration.cp.APMFeature.APM_NETWORK_PLUGIN_INSTALLED;
4+
import static com.instabug.apm.configuration.cp.APMFeature.CP_NATIVE_INTERCEPTION_ENABLED;
5+
import static org.mockito.Mockito.*;
6+
import static org.junit.Assert.*;
7+
8+
import android.os.Looper;
9+
10+
import com.facebook.react.bridge.Promise;
11+
import com.facebook.react.bridge.ReactApplicationContext;
12+
13+
import org.junit.After;
14+
import org.junit.Before;
15+
import org.junit.Test;
16+
import org.mockito.ArgumentCaptor;
17+
import org.mockito.MockedStatic;
18+
import org.mockito.Mockito;
19+
import org.mockito.invocation.InvocationOnMock;
20+
import org.mockito.stubbing.Answer;
21+
22+
import com.instabug.apm.InternalAPM;
23+
import com.instabug.reactlibrary.utils.MainThreadHandler;
24+
25+
import java.util.concurrent.Executors;
26+
import java.util.concurrent.ScheduledExecutorService;
27+
28+
public class RNInstabugNetworkLoggerModuleTest {
29+
30+
// Mock MainThread
31+
private final static ScheduledExecutorService mainThread = Executors.newSingleThreadScheduledExecutor();
32+
33+
// Mock Objects
34+
private MockedStatic<Looper> mockLooper;
35+
private MockedStatic<MainThreadHandler> mockMainThreadHandler;
36+
private RNInstabugNetworkLoggerModule networkLoggerModule;
37+
private Promise mockPromise;
38+
39+
@Before
40+
public void mockMainThreadHandler() throws Exception {
41+
// Mock Object
42+
ReactApplicationContext mockReactApplicationContext = mock(ReactApplicationContext.class);
43+
mockPromise = mock(Promise.class);
44+
networkLoggerModule = new RNInstabugNetworkLoggerModule(mockReactApplicationContext);
45+
46+
// Mock static functions
47+
mockLooper = mockStatic(Looper.class);
48+
mockMainThreadHandler = mockStatic(MainThreadHandler.class);
49+
// Mock Looper class
50+
Looper mockMainThreadLooper = mock(Looper.class);
51+
when(Looper.getMainLooper()).thenReturn(mockMainThreadLooper);
52+
53+
// Override runOnMainThread
54+
Answer<Boolean> handlerPostAnswer = new Answer<Boolean>() {
55+
@Override
56+
public Boolean answer(InvocationOnMock invocation) throws Throwable {
57+
invocation.getArgument(0, Runnable.class).run();
58+
return true;
59+
}
60+
};
61+
Mockito.doAnswer(handlerPostAnswer).when(MainThreadHandler.class);
62+
MainThreadHandler.runOnMainThread(any(Runnable.class));
63+
}
64+
65+
@After
66+
public void tearDown() {
67+
// Remove static mocks
68+
mockLooper.close();
69+
mockMainThreadHandler.close();
70+
}
71+
72+
73+
@Test
74+
public void testGetName() {
75+
// Test the getName method
76+
String name = networkLoggerModule.getName();
77+
assertEquals("IBGNetworkLogger", name);
78+
}
79+
80+
@Test
81+
public void testAddListener() {
82+
// Test addListener method
83+
networkLoggerModule.addListener("event_name");
84+
// Nothing to assert, but check no exceptions are thrown
85+
}
86+
87+
@Test
88+
public void testRemoveListeners() {
89+
// Test removeListeners method
90+
networkLoggerModule.removeListeners(1);
91+
// Nothing to assert, but check no exceptions are thrown
92+
}
93+
94+
@Test
95+
public void testIsNativeInterceptionEnabled_True() {
96+
97+
98+
// Mock InternalAPM behavior within the scope of this test
99+
try (MockedStatic<InternalAPM> internalAPMMock = mockStatic(InternalAPM.class)) {
100+
internalAPMMock.when(() -> InternalAPM._isFeatureEnabledCP(CP_NATIVE_INTERCEPTION_ENABLED, ""))
101+
.thenReturn(true);
102+
103+
// Execute the method
104+
networkLoggerModule.isNativeInterceptionEnabled(mockPromise);
105+
106+
// Capture the Promise.resolve() call
107+
ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
108+
verify(mockPromise).resolve(captor.capture());
109+
110+
// Assert that true was passed to resolve
111+
assertTrue(captor.getValue());
112+
}
113+
}
114+
115+
@Test
116+
public void testIsNativeInterceptionEnabled_False() {
117+
118+
119+
try (MockedStatic<InternalAPM> internalAPMMock = mockStatic(InternalAPM.class)) {
120+
internalAPMMock.when(() -> InternalAPM._isFeatureEnabledCP(CP_NATIVE_INTERCEPTION_ENABLED, ""))
121+
.thenReturn(false);
122+
123+
// Execute the method
124+
networkLoggerModule.isNativeInterceptionEnabled(mockPromise);
125+
126+
// Capture the Promise.resolve() call
127+
ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
128+
verify(mockPromise).resolve(captor.capture());
129+
130+
// Assert that false was passed to resolve
131+
assertFalse(captor.getValue());
132+
}
133+
}
134+
135+
@Test
136+
public void testIsNativeInterceptionEnabled_Exception() {
137+
138+
139+
// Simulate an exception in InternalAPM
140+
try (MockedStatic<InternalAPM> internalAPMMock = mockStatic(InternalAPM.class)) {
141+
internalAPMMock.when(() -> InternalAPM._isFeatureEnabledCP(anyString(), anyString()))
142+
.thenThrow(new RuntimeException("Error"));
143+
144+
// Execute the method
145+
networkLoggerModule.isNativeInterceptionEnabled(mockPromise);
146+
147+
// Capture the Promise.resolve() call in case of an exception
148+
ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
149+
verify(mockPromise).resolve(captor.capture());
150+
151+
// Assert that false was passed to resolve when exception occurs
152+
assertFalse(captor.getValue());
153+
}
154+
}
155+
156+
@Test
157+
public void testHasAPMNetworkPlugin_True() {
158+
159+
160+
try (MockedStatic<InternalAPM> internalAPMMock = mockStatic(InternalAPM.class)) {
161+
internalAPMMock.when(() -> InternalAPM._isFeatureEnabledCP(APM_NETWORK_PLUGIN_INSTALLED, ""))
162+
.thenReturn(true);
163+
164+
// Execute the method
165+
networkLoggerModule.hasAPMNetworkPlugin(mockPromise);
166+
167+
// Capture the Promise.resolve() call
168+
ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
169+
verify(mockPromise).resolve(captor.capture());
170+
171+
// Assert that true was passed to resolve
172+
assertTrue(captor.getValue());
173+
}
174+
}
175+
176+
@Test
177+
public void testHasAPMNetworkPlugin_False() {
178+
179+
180+
try (MockedStatic<InternalAPM> internalAPMMock = mockStatic(InternalAPM.class)) {
181+
internalAPMMock.when(() -> InternalAPM._isFeatureEnabledCP(APM_NETWORK_PLUGIN_INSTALLED, ""))
182+
.thenReturn(false);
183+
184+
// Execute the method
185+
networkLoggerModule.hasAPMNetworkPlugin(mockPromise);
186+
187+
// Capture the Promise.resolve() call
188+
ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
189+
verify(mockPromise).resolve(captor.capture());
190+
191+
// Assert that false was passed to resolve
192+
assertFalse(captor.getValue());
193+
}
194+
}
195+
196+
@Test
197+
public void testHasAPMNetworkPlugin_Exception() {
198+
199+
200+
// Simulate an exception in InternalAPM
201+
try (MockedStatic<InternalAPM> internalAPMMock = mockStatic(InternalAPM.class)) {
202+
internalAPMMock.when(() -> InternalAPM._isFeatureEnabledCP(anyString(), anyString()))
203+
.thenThrow(new RuntimeException("Error"));
204+
205+
// Execute the method
206+
networkLoggerModule.hasAPMNetworkPlugin(mockPromise);
207+
208+
// Capture the Promise.resolve() call in case of an exception
209+
ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
210+
verify(mockPromise).resolve(captor.capture());
211+
212+
// Assert that false was passed to resolve when exception occurs
213+
assertFalse(captor.getValue());
214+
}
215+
}
216+
}

examples/default/android/app/build.gradle

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ def reactNativeArchitectures() {
9898

9999
instabug {
100100
apm {
101-
// networkEnabled = true
102-
// debugEnabled = true
101+
networkEnabled = true
103102
}
104103
}
105104
android {

examples/default/android/app/src/main/res/xml/network_security_config.xml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,4 @@
1212
<certificates src="user" />
1313
</trust-anchors>
1414
</base-config>
15-
16-
<debug-overrides>
17-
<trust-anchors>
18-
<!-- Trust user added CAs while debuggable only -->
19-
<certificates src="user" />
20-
<certificates src="system" />
21-
</trust-anchors>
22-
</debug-overrides>
2315
</network-security-config>

examples/default/src/App.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { RootTabNavigator } from './navigation/RootTab';
1717
import { nativeBaseTheme } from './theme/nativeBaseTheme';
1818
import { navigationTheme } from './theme/navigationTheme';
1919

20-
// import { QueryClient } from 'react-query';
2120
import { QueryClient, QueryClientProvider } from 'react-query';
2221

2322
const queryClient = new QueryClient();
@@ -27,7 +26,6 @@ const queryClient = new QueryClient();
2726
export const App: React.FC = () => {
2827
useEffect(() => {
2928
Instabug.init({
30-
// token: 'deb1910a7342814af4e4c9210c786f35',
3129
token: '0fcc87b8bf731164828cc411eccc802a',
3230
invocationEvents: [InvocationEvent.floatingButton],
3331
debugLogsLevel: LogLevel.verbose,

0 commit comments

Comments
 (0)