Skip to content

Commit ca93121

Browse files
chore: add unit tests and extract log messages
1 parent e0c7f28 commit ca93121

File tree

6 files changed

+456
-16
lines changed

6 files changed

+456
-16
lines changed
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+
}

src/modules/Instabug.ts

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import type { ReproConfig } from '../models/ReproConfig';
3636
import type { FeatureFlag } from '../models/FeatureFlag';
3737
import { addAppStateListener } from '../utils/AppStatesHandler';
3838
import InstabugConstants from '../utils/InstabugConstants';
39+
import instabugConstants from '../utils/InstabugConstants';
3940
import { NativeNetworkLogger } from '../native/NativeNetworkLogger';
4041

4142
let _currentScreen: string | null = null;
@@ -101,26 +102,26 @@ export const init = async (config: InstabugConfig) => {
101102
// Add app state listener to handle background/foreground transitions
102103
addAppStateListener(async (nextAppState) => handleAppStateChange(nextAppState, config));
103104

104-
// Set up error capturing and rejection handling
105-
InstabugUtils.captureJsErrors();
106-
captureUnhandledRejections();
107-
108-
// Perform platform-specific checks and update interception mode
109-
handleNetworkInterceptionMode(config);
110-
111-
// Log the current APM network flags and initialize Instabug
112-
_logFlags();
113-
114105
//Set APM networking flags for the first time
115106
setApmNetworkFlagsIfChanged({
116107
isNativeInterceptionFeatureEnabled: isNativeInterceptionFeatureEnabled,
117108
hasAPMNetworkPlugin: hasAPMNetworkPlugin,
118109
shouldEnableNativeInterception: shouldEnableNativeInterception,
119110
});
120111

112+
// Perform platform-specific checks and update interception mode
113+
handleNetworkInterceptionMode(config);
114+
115+
// Log the current APM network flags and initialize Instabug
116+
_logFlags();
117+
121118
// call Instabug native init method
122119
initializeNativeInstabug(config);
123120

121+
// Set up error capturing and rejection handling
122+
InstabugUtils.captureJsErrors();
123+
captureUnhandledRejections();
124+
124125
_isFirstScreen = true;
125126
_currentScreen = firstScreen;
126127

@@ -202,26 +203,27 @@ const checkNativeInterceptionForAndroid = (config: InstabugConfig) => {
202203
if (isNativeInterceptionFeatureEnabled && hasAPMNetworkPlugin) {
203204
shouldEnableNativeInterception = true;
204205
console.warn(
205-
InstabugConstants.IBG_APM_TAG + 'Switched to Native Interception: Android Plugin Detected',
206+
InstabugConstants.IBG_APM_TAG + InstabugConstants.SWITCHED_TO_NATIVE_INTERCEPTION_MESSAGE,
206207
);
207208
}
208209
} else {
209210
if (isNativeInterceptionFeatureEnabled) {
210211
shouldEnableNativeInterception = hasAPMNetworkPlugin;
211212
if (!hasAPMNetworkPlugin) {
212213
console.error(
213-
InstabugConstants.IBG_APM_TAG +
214-
'Network traces won’t get captured as plugin is not installed',
214+
InstabugConstants.IBG_APM_TAG + InstabugConstants.PLUGIN_NOT_INSTALLED_MESSAGE,
215215
);
216216
}
217217
} else {
218218
if (hasAPMNetworkPlugin) {
219-
console.error(InstabugConstants.IBG_APM_TAG + 'Native interception is disabled');
219+
console.error(
220+
InstabugConstants.IBG_APM_TAG + InstabugConstants.NATIVE_INTERCEPTION_DISABLED_MESSAGE,
221+
);
220222
} else {
221223
shouldEnableNativeInterception = false; // rollback to use JS interceptor for APM & Core.
222224
console.error(
223225
InstabugConstants.IBG_APM_TAG +
224-
'Native interception is disabled and plugin is not installed',
226+
InstabugConstants.PLUGIN_NOT_INSTALLED_AND_NATIVE_INTERCEPTION_DISABLED_MESSAGE,
225227
);
226228
}
227229
}
@@ -238,7 +240,9 @@ const checkNativeInterceptionForIOS = (config: InstabugConfig) => {
238240
} else {
239241
shouldEnableNativeInterception = false;
240242
NetworkLogger.setEnabled(true); // rollback to JS interceptor
241-
console.error(InstabugConstants.IBG_APM_TAG + 'Native interception is disabled');
243+
console.error(
244+
InstabugConstants.IBG_APM_TAG + instabugConstants.NATIVE_INTERCEPTION_DISABLED_MESSAGE,
245+
);
242246
}
243247
}
244248
};

src/utils/InstabugConstants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ const InstabugConstants = {
88
MAX_REQUEST_BODY_SIZE_EXCEEDED_MESSAGE:
99
'The request body has not been logged because it exceeds the maximum size of 10 Kb',
1010
IBG_APM_TAG: 'IBG-APM: ',
11+
SWITCHED_TO_NATIVE_INTERCEPTION_MESSAGE:
12+
'Switched to Native Interception: Android Plugin Detected',
13+
PLUGIN_NOT_INSTALLED_MESSAGE: 'Network traces won’t get captured as plugin is not installed',
14+
PLUGIN_NOT_INSTALLED_AND_NATIVE_INTERCEPTION_DISABLED_MESSAGE:
15+
'Network traces won’t get captured as plugin is not installed and native interception is disabled from BE',
16+
NATIVE_INTERCEPTION_DISABLED_MESSAGE: 'Native interception is disabled',
1117
};
1218

1319
export default InstabugConstants;

src/utils/InstabugUtils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,4 +245,5 @@ export default {
245245
getStackTrace,
246246
stringifyIfNotString,
247247
sendCrashReport,
248+
reportNetworkLog,
248249
};

0 commit comments

Comments
 (0)