Skip to content

Commit d69e49a

Browse files
authored
Merge b7adc29 into 1b0b11d
2 parents 1b0b11d + b7adc29 commit d69e49a

File tree

3 files changed

+170
-3
lines changed

3 files changed

+170
-3
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package io.sentry.react
2+
3+
import android.content.Context
4+
import com.facebook.react.bridge.JavaOnlyMap
5+
import com.facebook.react.bridge.ReadableMap
6+
import io.sentry.ILogger
7+
import io.sentry.Sentry.OptionsConfiguration
8+
import io.sentry.SentryLevel
9+
import io.sentry.android.core.SentryAndroidOptions
10+
import org.json.JSONObject
11+
import org.junit.After
12+
import org.junit.Assert.assertEquals
13+
import org.junit.Assert.assertThrows
14+
import org.junit.Before
15+
import org.junit.Test
16+
import org.junit.runner.RunWith
17+
import org.junit.runners.JUnit4
18+
import org.mockito.ArgumentMatchers.contains
19+
import org.mockito.ArgumentMatchers.eq
20+
import org.mockito.MockedStatic
21+
import org.mockito.Mockito.mock
22+
import org.mockito.Mockito.mockStatic
23+
import org.mockito.Mockito.verify
24+
import org.mockito.MockitoAnnotations
25+
26+
@RunWith(JUnit4::class)
27+
class RNSentrySDKTest {
28+
private val configurationFile = "sentry.options.json"
29+
30+
private lateinit var mockLogger: ILogger
31+
private lateinit var mockContext: Context
32+
private lateinit var mockConfiguration: OptionsConfiguration<SentryAndroidOptions>
33+
private lateinit var mockedRNSentryStart: MockedStatic<RNSentryStart>
34+
private lateinit var mockedRNSentryJsonUtils: MockedStatic<RNSentryJsonUtils>
35+
36+
@Before
37+
fun setUp() {
38+
MockitoAnnotations.openMocks(this)
39+
mockLogger = mock(ILogger::class.java)
40+
mockContext = mock(Context::class.java)
41+
mockConfiguration = mock(OptionsConfiguration::class.java) as OptionsConfiguration<SentryAndroidOptions>
42+
mockedRNSentryStart = mockStatic(RNSentryStart::class.java)
43+
mockedRNSentryJsonUtils = mockStatic(RNSentryJsonUtils::class.java)
44+
}
45+
46+
@After
47+
fun tearDown() {
48+
mockedRNSentryStart.close()
49+
mockedRNSentryJsonUtils.close()
50+
}
51+
52+
@Test
53+
fun `init with passed configuration callback when no valid json file is provided`() {
54+
val mockJsonObject = null
55+
mockedRNSentryJsonUtils
56+
.`when`<JSONObject> {
57+
RNSentryJsonUtils.getOptionsFromConfigurationFile(mockContext, configurationFile, mockLogger)
58+
}.thenReturn(mockJsonObject)
59+
RNSentrySDK.init(mockContext, mockConfiguration, mockLogger)
60+
61+
verify(mockLogger).log(
62+
eq(SentryLevel.WARNING),
63+
contains("Failed to load configuration file(sentry.options.json), starting with configuration callback."),
64+
)
65+
66+
mockedRNSentryStart.verify {
67+
RNSentryStart.startWithConfiguration(mockContext, mockConfiguration)
68+
}
69+
}
70+
71+
@Test
72+
fun `init with passed configuration callback when no valid readable map is created`() {
73+
val mockJsonObject = JSONObject()
74+
mockedRNSentryJsonUtils
75+
.`when`<JSONObject> {
76+
RNSentryJsonUtils.getOptionsFromConfigurationFile(mockContext, configurationFile, mockLogger)
77+
}.thenReturn(mockJsonObject)
78+
val mockReadableMap = null
79+
mockedRNSentryJsonUtils
80+
.`when`<ReadableMap> {
81+
RNSentryJsonUtils.jsonObjectToReadableMap(
82+
mockJsonObject,
83+
)
84+
}.thenReturn(mockReadableMap)
85+
86+
RNSentrySDK.init(mockContext, mockConfiguration, mockLogger)
87+
88+
verify(mockLogger).log(
89+
eq(SentryLevel.WARNING),
90+
contains("Failed to load configuration file(sentry.options.json), starting with configuration callback."),
91+
)
92+
mockedRNSentryStart.verify {
93+
RNSentryStart.startWithConfiguration(mockContext, mockConfiguration)
94+
}
95+
}
96+
97+
@Test
98+
fun `init with the json file and the passed configuration when a valid json is provided`() {
99+
val mockJsonObject = JSONObject()
100+
mockedRNSentryJsonUtils
101+
.`when`<JSONObject> {
102+
RNSentryJsonUtils.getOptionsFromConfigurationFile(mockContext, configurationFile, mockLogger)
103+
}.thenReturn(mockJsonObject)
104+
val mockReadableMap =
105+
JavaOnlyMap.of(
106+
"dsn",
107+
"https://[email protected]/1234567",
108+
)
109+
110+
mockedRNSentryJsonUtils
111+
.`when`<ReadableMap> {
112+
RNSentryJsonUtils.jsonObjectToReadableMap(
113+
mockJsonObject,
114+
)
115+
}.thenReturn(mockReadableMap)
116+
117+
RNSentrySDK.init(mockContext, mockConfiguration, mockLogger)
118+
119+
mockedRNSentryStart.verify {
120+
RNSentryStart.startWithOptions(mockContext, mockReadableMap, mockConfiguration, null, mockLogger)
121+
}
122+
}
123+
124+
@Test
125+
fun `fails with an error when there is an unhandled exception in initialisation`() {
126+
mockedRNSentryJsonUtils
127+
.`when`<JSONObject> {
128+
RNSentryJsonUtils.getOptionsFromConfigurationFile(mockContext, configurationFile, mockLogger)
129+
}.thenThrow(RuntimeException("Test exception"))
130+
131+
val exception =
132+
assertThrows(RuntimeException::class.java) {
133+
RNSentrySDK.init(mockContext, mockConfiguration, mockLogger)
134+
}
135+
136+
assertEquals("Failed to initialize Sentry's React Native SDK", exception.message)
137+
}
138+
}

packages/core/android/src/main/java/io/sentry/react/RNSentrySDK.java

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,51 @@ private RNSentrySDK() {
2525
*
2626
* @param context Android Context
2727
* @param configuration configuration options
28+
* @param logger logger
2829
*/
2930
public static void init(
3031
@NotNull final Context context,
31-
@NotNull Sentry.OptionsConfiguration<SentryAndroidOptions> configuration) {
32+
@NotNull Sentry.OptionsConfiguration<SentryAndroidOptions> configuration,
33+
@NotNull ILogger logger) {
3234
try {
3335
JSONObject jsonObject =
3436
RNSentryJsonUtils.getOptionsFromConfigurationFile(context, CONFIGURATION_FILE, logger);
3537
ReadableMap rnOptions = RNSentryJsonUtils.jsonObjectToReadableMap(jsonObject);
38+
if (rnOptions == null) {
39+
logger.log(
40+
SentryLevel.WARNING,
41+
"Failed to load configuration file("
42+
+ CONFIGURATION_FILE
43+
+ "), starting with configuration callback.");
44+
RNSentryStart.startWithConfiguration(context, configuration);
45+
return;
46+
}
3647
RNSentryStart.startWithOptions(context, rnOptions, configuration, null, logger);
3748
} catch (Exception e) {
3849
logger.log(
3950
SentryLevel.ERROR, "Failed to start Sentry with options from configuration file.", e);
40-
throw new RuntimeException(e);
51+
throw new RuntimeException("Failed to initialize Sentry's React Native SDK", e);
4152
}
4253
}
4354

55+
/**
56+
* Start the Native Android SDK with the provided options
57+
*
58+
* @param context Android Context
59+
* @param configuration configuration options
60+
*/
61+
public static void init(
62+
@NotNull final Context context,
63+
@NotNull Sentry.OptionsConfiguration<SentryAndroidOptions> configuration) {
64+
init(context, configuration, logger);
65+
}
66+
4467
/**
4568
* Start the Native Android SDK with options from `sentry.options.json` configuration file
4669
*
4770
* @param context Android Context
4871
*/
4972
public static void init(@NotNull final Context context) {
50-
init(context, options -> {});
73+
init(context, options -> {}, logger);
5174
}
5275
}

packages/core/android/src/main/java/io/sentry/react/RNSentryStart.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ private RNSentryStart() {
3434
throw new AssertionError("Utility class should not be instantiated");
3535
}
3636

37+
public static void startWithConfiguration(
38+
@NotNull final Context context,
39+
@NotNull Sentry.OptionsConfiguration<SentryAndroidOptions> configuration) {
40+
SentryAndroid.init(context, configuration);
41+
}
42+
3743
public static void startWithOptions(
3844
@NotNull final Context context,
3945
@NotNull final ReadableMap rnOptions,

0 commit comments

Comments
 (0)