Skip to content

Commit 3fae0be

Browse files
ahmedAlaaInstabugabdelhamid-f-nassera7medev
authored
feat: add setNDKCrashesEnabled API (#1132)
* feat_add_setNDKCrashesEnabled * fix android_testing issue * rename_test_cases * fix_pr_comments * feat/add-ndk-demo-crash-buttons * chore: add ChangeLog changes * Update CHANGELOG.md Co-authored-by: Abdelhamid Nasser <[email protected]> * feat: add more crash scenarios to example app (#1131) * feat(example): add nested complex views (#1111) Jira ID: MOB-13737 * fix hybrid mode code push version init (#1108) * chore(android): ignore jetbrains ide run configurations (#1110) Jira ID: MOB-13736 * ci: migrate macos machines to m1 (#1114) * feat: support identify user by id (#1115) Jira ID: MOB-13746 * ci: replace d11 cluster url in UploadSourcemaps (#1122) * fix(android): resolve private views through UI manager directly (#1121) * feat: support switching to native network interception (#1120) * feat(example): Add more sdk crashes buttons * chore(android): ignore jetbrains ide run configurations (#1110) Jira ID: MOB-13736 * feat(example): Add more sdk crashes buttons * fix dev merge issue * feat_add_crash_buttons * feat_add_crash_buttons * feat_add_crash_buttons * fix: PlatformListTile typo name --------- Co-authored-by: Abdelhamid Nasser <[email protected]> Co-authored-by: Ahmed Mahmoud <[email protected]> Co-authored-by: AbdElHamid Nasser <[email protected]> * feat_add_setNDKCrashesEnabled * fix android_testing issue * rename_test_cases * fix_pr_comments * feat/add-ndk-demo-crash-buttons * chore: add ChangeLog changes * Update CHANGELOG.md Co-authored-by: Abdelhamid Nasser <[email protected]> * fix:lint issue * fix: CHANGELOG typo issue Co-authored-by: Abdelhamid Nasser <[email protected]> --------- Co-authored-by: Abdelhamid Nasser <[email protected]> Co-authored-by: Ahmed Mahmoud <[email protected]> Co-authored-by: AbdElHamid Nasser <[email protected]>
1 parent 3ab63ab commit 3fae0be

File tree

8 files changed

+137
-0
lines changed

8 files changed

+137
-0
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## [Unreleased](https://github.com/Instabug/Instabug-React-Native/compare/v12.7.1...dev)
4+
5+
### Added
6+
7+
- Support enabling NDK crash capturing on Android ([#1132](https://github.com/Instabug/Instabug-React-Native/pull/1132)).
8+
39
## [12.7.1](https://github.com/Instabug/Instabug-React-Native/compare/v12.7.0...v12.7.1) (February 15, 2024)
410

511
### Changed

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,28 @@ public void run() {
113113
}
114114
}
115115
});
116+
}
116117

118+
/**
119+
* Enables and disables capturing native C++ NDK crash reporting.
120+
*
121+
* @param isEnabled boolean indicating enabled or disabled.
122+
*/
123+
@ReactMethod
124+
public void setNDKCrashesEnabled(final boolean isEnabled) {
125+
MainThreadHandler.runOnMainThread(new Runnable() {
126+
@Override
127+
public void run() {
128+
try {
129+
if (isEnabled) {
130+
CrashReporting.setNDKCrashesState(Feature.State.ENABLED);
131+
} else {
132+
CrashReporting.setNDKCrashesState(Feature.State.DISABLED);
133+
}
134+
} catch (Exception e) {
135+
e.printStackTrace();
136+
}
137+
}
138+
});
117139
}
118140
}

android/src/test/java/com/instabug/reactlibrary/RNInstabugCrashReportingModuleTest.java

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,85 @@
11
package com.instabug.reactlibrary;
22

3+
import static org.mockito.ArgumentMatchers.any;
4+
import static org.mockito.Mockito.mock;
5+
import static org.mockito.Mockito.mockStatic;
6+
7+
import android.os.Looper;
8+
9+
import com.instabug.crash.CrashReporting;
10+
import com.instabug.library.Feature;
11+
import com.instabug.reactlibrary.util.GlobalMocks;
12+
import com.instabug.reactlibrary.utils.MainThreadHandler;
13+
14+
import org.junit.After;
15+
import org.junit.Before;
316
import org.junit.Test;
17+
import org.mockito.MockedStatic;
18+
import org.mockito.Mockito;
19+
import org.mockito.invocation.InvocationOnMock;
20+
import org.mockito.stubbing.Answer;
421

522

623
public class RNInstabugCrashReportingModuleTest {
24+
private final RNInstabugCrashReportingModule rnModule = new RNInstabugCrashReportingModule(null);
25+
26+
// Mock Objects
27+
private MockedStatic<Looper> mockLooper;
28+
private MockedStatic<MainThreadHandler> mockMainThreadHandler;
29+
private MockedStatic<CrashReporting> mockCrashReporting;
30+
31+
32+
@Before
33+
public void mockMainThreadHandler() throws Exception {
34+
// Mock static functions
35+
mockLooper = mockStatic(Looper.class);
36+
mockMainThreadHandler = mockStatic(MainThreadHandler.class);
37+
mockCrashReporting = mockStatic(CrashReporting.class);
38+
// Mock Looper class
39+
Looper mockMainThreadLooper = mock(Looper.class);
40+
Mockito.when(Looper.getMainLooper()).thenReturn(mockMainThreadLooper);
41+
42+
43+
// Override runOnMainThread
44+
Answer<Boolean> handlerPostAnswer = new Answer<Boolean>() {
45+
@Override
46+
public Boolean answer(InvocationOnMock invocation) throws Throwable {
47+
invocation.getArgument(0, Runnable.class).run();
48+
return true;
49+
}
50+
};
51+
Mockito.doAnswer(handlerPostAnswer).when(MainThreadHandler.class);
52+
MainThreadHandler.runOnMainThread(any(Runnable.class));
53+
}
54+
55+
@After
56+
public void tearDown() {
57+
// Remove static mocks
58+
mockLooper.close();
59+
mockMainThreadHandler.close();
60+
mockCrashReporting.close();
61+
}
62+
63+
/********Crashes*********/
64+
65+
@Test
66+
public void testSetNDKCrashesEnabledGivenTrue() {
67+
// when
68+
rnModule.setNDKCrashesEnabled(true);
69+
70+
//then
71+
mockCrashReporting.verify(() -> CrashReporting.setNDKCrashesState(Feature.State.ENABLED));
72+
}
73+
74+
@Test
75+
public void testSetNDKCrashesEnabledGivenFalse() {
76+
// when
77+
rnModule.setNDKCrashesEnabled(false);
78+
79+
//then
80+
mockCrashReporting.verify(() -> CrashReporting.setNDKCrashesState(Feature.State.DISABLED));
81+
}
82+
783
@Test
884
public void givenString$sendHandledJSCrash_whenQuery_thenShouldCallNativeApiWithArgs() throws Exception {
985
// JSONObject json = mock(JSONObject.class);

android/src/test/java/com/instabug/reactlibrary/RNInstabugRepliesModuleTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.facebook.react.bridge.WritableMap;
1111
import com.instabug.chat.Replies;
1212
import com.instabug.library.Feature;
13+
import com.instabug.reactlibrary.utils.InstabugUtil;
1314
import com.instabug.reactlibrary.utils.MapUtil;
1415
import com.instabug.reactlibrary.utils.MainThreadHandler;
1516

@@ -42,13 +43,15 @@ public class RNInstabugRepliesModuleTest {
4243
private MockedStatic<Looper> mockLooper;
4344
private MockedStatic <MainThreadHandler> mockMainThreadHandler;
4445
private MockedStatic <Replies> mockReplies;
46+
private MockedStatic <InstabugUtil> mockInstabugUtil;
4547

4648
@Before
4749
public void mockMainThreadHandler() throws Exception {
4850
// Mock static functions
4951
mockReplies = mockStatic(Replies.class);
5052
mockLooper = mockStatic(Looper.class);
5153
mockMainThreadHandler = mockStatic(MainThreadHandler.class);
54+
mockInstabugUtil = mockStatic(InstabugUtil.class);
5255

5356
// Mock Looper class
5457
Looper mockMainThreadLooper = mock(Looper.class);
@@ -71,6 +74,7 @@ public void tearDown() {
7174
mockLooper.close();
7275
mockMainThreadHandler.close();
7376
mockReplies.close();
77+
mockInstabugUtil.close();
7478
}
7579

7680
/********Replies*********/

src/modules/CrashReporting.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { ExtendedError } from 'react-native/Libraries/Core/Devtools/parseEr
22

33
import { NativeCrashReporting } from '../native/NativeCrashReporting';
44
import InstabugUtils from '../utils/InstabugUtils';
5+
import { Platform } from 'react-native';
56

67
/**
78
* Enables and disables everything related to crash reporting including intercepting
@@ -19,3 +20,13 @@ export const setEnabled = (isEnabled: boolean) => {
1920
export const reportError = (error: ExtendedError) => {
2021
return InstabugUtils.sendCrashReport(error, NativeCrashReporting.sendHandledJSCrash);
2122
};
23+
24+
/**
25+
* Enables and disables capturing native C++ NDK crashes.
26+
* @param isEnabled
27+
*/
28+
export const setNDKCrashesEnabled = (isEnabled: boolean) => {
29+
if (Platform.OS === 'android') {
30+
NativeCrashReporting.setNDKCrashesEnabled(isEnabled);
31+
}
32+
};

src/native/NativeCrashReporting.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface CrashReportingNativeModule extends NativeModule {
1616
setEnabled(isEnabled: boolean): void;
1717
sendJSCrash(data: CrashData | string): Promise<void>;
1818
sendHandledJSCrash(data: CrashData | string): Promise<void>;
19+
setNDKCrashesEnabled(isEnabled: boolean): Promise<void>;
1920
}
2021

2122
export const NativeCrashReporting = NativeModules.IBGCrashReporting;

test/mocks/mockCrashReporting.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const mockCrashReporting: CrashReportingNativeModule = {
66
setEnabled: jest.fn(),
77
sendHandledJSCrash: jest.fn(),
88
sendJSCrash: jest.fn(),
9+
setNDKCrashesEnabled: jest.fn(),
910
};
1011

1112
export default mockCrashReporting;

test/modules/CrashReporting.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import '../mocks/mockInstabugUtils';
33
import * as CrashReporting from '../../src/modules/CrashReporting';
44
import { NativeCrashReporting } from '../../src/native/NativeCrashReporting';
55
import InstabugUtils from '../../src/utils/InstabugUtils';
6+
import { Platform } from 'react-native';
67

78
describe('CrashReporting Module', () => {
89
it('should call the native method setEnabled', () => {
@@ -22,4 +23,19 @@ describe('CrashReporting Module', () => {
2223
NativeCrashReporting.sendHandledJSCrash,
2324
);
2425
});
26+
27+
it('should call the native method setNDKCrashesEnabled for Android platform', () => {
28+
Platform.OS = 'android';
29+
CrashReporting.setNDKCrashesEnabled(true);
30+
31+
expect(NativeCrashReporting.setNDKCrashesEnabled).toBeCalledTimes(1);
32+
expect(NativeCrashReporting.setNDKCrashesEnabled).toBeCalledWith(true);
33+
});
34+
35+
it('should not call the native method setNDKCrashesEnabled for ios platform', () => {
36+
Platform.OS = 'ios';
37+
CrashReporting.setNDKCrashesEnabled(true);
38+
39+
expect(NativeCrashReporting.setNDKCrashesEnabled).not.toBeCalled();
40+
});
2541
});

0 commit comments

Comments
 (0)