Skip to content

Commit d5c32e3

Browse files
antoniskrystofwoldrichKrystof Woldrichgetsentry-botgetsentry-bot
authored
feat: v8: Capture app start errors before JS (#5582)
* ref(ios): Extract Cocoa SDK init into standalone file (#4442) * ref(android): Extracts Android native initialization to standalone structures (#4445) * Extract Android SDK Init * Update tests * Adds changelog * Fix lint issues * Rename RNSentryStart instance for clarity * Converts RNSentryStart to utility class * Update CHANGELOG.md --------- Co-authored-by: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> * feat(experimental): Add native `startWithConfigureOptions` for Apple platforms (#4444) * feat: Read `sentry.options.json` during cocoa init (#4447) * Adds utility class for converting `JsonObject` to `WritableMap` (#4479) * Convert json object to writable map * Make class/methods package-private(default) * feat: Automatically load `sentry.options.json` file (#4476) * feat(experimental): Initialize Android SDK from json configuration (#4451) * misc: Add `sentry.options.json` example to the changelog (#4509) * feat(init): Load options from `sentry.options.json` in JS (#4510) * release: 6.7.0-alpha.0 * misc(sample): Change RN Sample to use native file init by default (#4522) * chore(sample-rn): Remove duplicate init options from code (#4532) * chore(sample-rn): Always use fhe file option (including auto init) (#4533) * internal(sample-rn): Add Detox for integration/e2e tests of the rn sample (#4535) * internal(sample-rn): Add header and message envelope tests (#4536) * fix(sample-e2e): Fix type errors missing sentry/core and afterAll (#4564) * chore(samples): Add package scripts for native builds, dsn and testing (#4561) * test(e2e): Verify captured Errors Screen transaction (#4584) * test(e2e): Add auto init from JS tests (#4588) * test(e2e): Add app start crash test for iOS (#4593) * test(e2e): Avoid race conditions when waiting for captured message (#4595) * chore(sample-e2e): Move Detox related files to e2e-detox dir * fix: remove unused SentryPackage import Removed unused import that was causing CI lint failure * fix: update RNSentryStartTest for Sentry Android SDK v7 API changes - Removed assertions for packages getter (not available in v7) - Removed assertion for enableTracing property (removed in v7) - Added comments explaining the API changes * fix: remove unused addPackages method to fix PMD lint error The method was a no-op after v7 API changes, so removing it entirely to avoid unused parameter warnings from PMD. * fix: update RNSentrySDKTest for Sentry Android SDK v7 API changes - Removed assertions for enableTracing property (removed in v7) - Removed assertions for packages getter (not available in v7) - Added comments explaining the API changes * fix: use relative path for RNSentrySDK+Test.h import in bridging header The file is in the parent directory, so use ../ prefix to fix the import path * fix: remove deprecated enableTracing property in iOS RNSentryStart The property is deprecated in v7. Tracing is already disabled by setting tracesSampleRate and tracesSampler to nil. * fix: remove enableTracing assertions from iOS tests The enableTracing property is deprecated in Sentry Cocoa SDK v7. Tracing is already verified to be disabled by checking that tracesSampleRate and tracesSampler are nil. * Update Podspec * Fix lint issue * ref(sample-e2e): v7: Migrate from Detox to Maestro (#5473) * chore(sample-e2e): Migrate from Detox to Maestro * fix set dsn script path * fix: Update script paths after detox-to-maestro migration The set-dsn scripts were moved from scripts/detox/ to scripts/ during the migration * Update script paths * Fix tests * Fix test failure * Fix idle issue * fix(e2e): Fix Maestro flows for captureMessage and captureSpaceflightNewsScreen - Add scrollUntilVisible for 'Capture message' button (might be off-screen) - Add proper waiting and scrolling for SpaceflightNewsScreen to trigger auto-load - Wait for 'Load More Articles' button to appear after autoLoadCount threshold * chore(e2e-sample): Increase Maestro driver startup timeout (cherry picked from commit ee429b5) * increase timeout * Increase timeouts on Android too --------- Co-authored-by: Krystof Woldrich <krystof.woldrich@sentry.io> * chore: Merge Android UI profiling on the capture startup crashes branch (#5544) * chore: Merge Android UI profiling on the capture startup crashes branch * Fix logger compilation issue * Properly check logging values * fix SR iOS issue (#5560) * Remove duplicate changelog entry * feat(expo): Add RNSentrySDK APIs support to @sentry/react-native/expo plugin (#4633) * useNativeInit Android implementation * Adds changelog * useNativeInit iOS implementation * Fix indentation * Extend test cases with realistic data * Adds code sample in the changelog * Fix CHANGELOG.md Co-authored-by: LucasZF <lucas-zimerman1@hotmail.com> * Warn if RESentySDK.init/start wasn't injected * Make useNativeInit opt-in * Make Android failure warning more clear Co-authored-by: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> * Make Android no update warning more clear Co-authored-by: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> * Use path.basename to get last path component * Update tests to account for the new warnings * Explicitly check for kotlin * Add filename in the warning message * Import only if init injection succeeds * Explicitly check for Objective-C * Add filename in the warning * Make iOS file not found warning more clear * Import only if init injection succeeds * Reset test mock config in a function * Lint issue * Add missing quote Co-authored-by: LucasZF <lucas-zimerman1@hotmail.com> * Remove unneeded async Co-authored-by: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> * Set useNativeInit = false by default * dynamically fill white spaces * Add unsupported language in warning message * Add objcpp in detected languages Co-authored-by: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> * Update tests for objcpp * ref(expo-plugin): Split utils to logger, version and utils (#4906) Co-authored-by: Antonis Lilis <antonis.lilis@gmail.com> * Update changelog * fix(ios): Add Swift module support for RNSentrySDK native init Fixes Swift compilation errors when using the useNativeInit Expo plugin feature. Changes: - Updated RNSentry.h to use angle bracket import for RNSentrySDK, properly exposing it through the module system - Added DEFINES_MODULE to RNSentry.podspec to enable Swift module generation - Fixed Expo plugin to insert import after first import statement (supports modern Expo AppDelegate structure without UIKit import) This enables Swift code to successfully import RNSentry and call RNSentrySDK.start() when using native initialization. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * Fix test * Update changelog * Fix native tests * Fix lint issue * Fix native tests * Revert unneeded changes * Fix sample app build --------- Co-authored-by: LucasZF <lucas-zimerman1@hotmail.com> Co-authored-by: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> * Fix native ios tests * Mark area Co-authored-by: LucasZF <lucas-zimerman1@hotmail.com> * fix(android): Fix ConcurrentModificationException (#5588) * fix(android): Fix ConcurrentModificationException when disabling native crash handling When enableNativeCrashHandling is set to false, the code was iterating over the integrations list with a for-each loop while calling remove() directly, which causes a ConcurrentModificationException at runtime. Fixed by using Java 8's removeIf() method which safely handles iteration and removal in a single operation. This is more concise and follows modern Java best practices. Added unit tests to verify the fix and ensure integrations are properly removed without throwing exceptions. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * Lint fix --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> * fix(android): Fix crash when spotlight is enabled without defaultSidecarUrl The code attempted to read defaultSidecarUrl without checking if the key exists in the options map. This caused a NoSuchKeyException crash during startup when spotlight was set to true in sentry.options.json without providing defaultSidecarUrl. Added key existence check to match iOS implementation behavior and prevent the crash while maintaining backward compatibility. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * test(e2e): Add auto init from JS tests for Android (#5583) * test(e2e): Add auto init from JS tests for Android Implements Android E2E testing infrastructure to verify both manual native initialization and auto initialization from JavaScript, matching the iOS implementation and resolving issue #4912. Key additions: - Jest configs for android.auto and android.manual test modes - Build scripts that toggle SENTRY_DISABLE_NATIVE_START at compile time - Test scripts to run auto and manual test suites separately - App start crash testing via flag file mechanism - TestControlModule to enable/disable crash-on-start from JS - Comprehensive E2E test documentation Unlike iOS which uses launch arguments at runtime, Android requires separate builds with different build configurations to control native initialization. Closes #4912 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix(e2e): Add scrolling to find crash control buttons in Android test The crash control buttons are off-screen, so the Maestro flow needs to scroll to find them before tapping. This matches the pattern used in other Android E2E tests. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix(e2e): Make Android crash flag auto-expire after one crash The crash flag file was persisting across app launches, causing the app to crash indefinitely. Now the flag auto-deletes when read, allowing: 1. First launch: Enable flag 2. Second launch: Read flag, delete it, then crash 3. Third launch: Start normally and send crash report This solves the chicken-and-egg problem where the app couldn't reach JavaScript to clear the flag because it kept crashing before JS loaded. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix(e2e): Handle wrapped exceptions in Android crash test Android wraps exceptions thrown in Application.onCreate() with: "Unable to create application... RuntimeException: <original message>" Updated the test to check if ANY exception in the chain contains our intentional crash message, rather than expecting an exact match on the first exception. Test now passes locally and should pass in CI. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * Clean up notes for now --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> * fix(android): Fix crash when dsn or devServerUrl are missing from options Fixes a crash on Android startup when initializing from sentry.options.json without dsn or devServerUrl fields. The code was calling getString() on ReadableMap without checking if the keys exist first, which throws NoSuchKeyException for missing keys. Both fields are optional in configuration files, so the code now checks for key existence before accessing values, returning null when keys are missing. This matches the pattern used throughout the rest of the file and is already handled correctly by the null-checks in the breadcrumb filter logic. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> --------- Co-authored-by: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> Co-authored-by: Krystof Woldrich <krystof.woldrich@sentry.io> Co-authored-by: getsentry-bot <bot@sentry.io> Co-authored-by: getsentry-bot <bot@getsentry.com> Co-authored-by: LucasZF <lucas-zimerman1@hotmail.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent db9c1a8 commit d5c32e3

File tree

132 files changed

+5863
-1082
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

132 files changed

+5863
-1082
lines changed

.github/workflows/sample-application.yml

Lines changed: 24 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ jobs:
8282
- uses: ruby/setup-ruby@v1
8383
if: ${{ matrix.platform == 'ios' || matrix.platform == 'macos' }}
8484
with:
85-
working-directory: ${{ matrix.platform == 'ios' && env.REACT_NATIVE_SAMPLE_PATH || ' samples/react-native-macos' }}
85+
working-directory: ${{ matrix.platform == 'ios' && env.REACT_NATIVE_SAMPLE_PATH || 'samples/react-native-macos' }}
8686
ruby-version: '3.3.0' # based on what is used in the sample
8787
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
8888
cache-version: 1 # cache the installed gems
@@ -112,62 +112,39 @@ jobs:
112112
if: ${{ matrix.platform == 'ios' || matrix.platform == 'macos' }}
113113
working-directory: samples
114114
run: |
115-
[[ "${{ matrix.platform }}" == "ios" ]] && cd react-native/ios
116-
[[ "${{ matrix.platform }}" == "macos" ]] && cd react-native-macos/macos
115+
[[ "${{ matrix.platform }}" == "ios" ]] && cd react-native
116+
[[ "${{ matrix.platform }}" == "macos" ]] && cd react-native-macos
117117
118-
[[ "${{ matrix.build-type }}" == "production" ]] && ENABLE_PROD=1 || ENABLE_PROD=0
119-
[[ "${{ matrix.rn-architecture }}" == "new" ]] && ENABLE_NEW_ARCH=1 || ENABLE_NEW_ARCH=0
118+
[[ "${{ matrix.build-type }}" == "production" ]] && export ENABLE_PROD=1 || export ENABLE_PROD=0
119+
[[ "${{ matrix.rn-architecture }}" == "new" ]] && export ENABLE_NEW_ARCH=1 || export ENABLE_NEW_ARCH=0
120120
[[ "${{ matrix.ios-use-frameworks }}" == "dynamic-frameworks" ]] && export USE_FRAMEWORKS=dynamic
121-
echo "ENABLE_PROD=$ENABLE_PROD"
122-
echo "ENABLE_NEW_ARCH=$ENABLE_NEW_ARCH"
123-
PRODUCTION=$ENABLE_PROD RCT_NEW_ARCH_ENABLED=$ENABLE_NEW_ARCH bundle exec pod install
124-
cat Podfile.lock | grep $RN_SENTRY_POD_NAME
121+
122+
./scripts/pod-install.sh
125123
126124
- name: Build Android App
127125
if: ${{ matrix.platform == 'android' }}
128-
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}/android
126+
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
129127
run: |
130-
if [[ ${{ matrix.rn-architecture }} == 'new' ]]; then
131-
perl -i -pe's/newArchEnabled=false/newArchEnabled=true/g' gradle.properties
132-
echo 'New Architecture enabled'
133-
elif [[ ${{ matrix.rn-architecture }} == 'legacy' ]]; then
134-
perl -i -pe's/newArchEnabled=true/newArchEnabled=false/g' gradle.properties
135-
echo 'Legacy Architecture enabled'
136-
else
137-
echo 'No changes for architecture: ${{ matrix.rn-architecture }}'
138-
fi
139-
[[ "${{ matrix.build-type }}" == "production" ]] && CONFIG='Release' || CONFIG='Debug'
140-
echo "Building $CONFIG"
141-
[[ "${{ matrix.build-type }}" == "production" ]] && TEST_TYPE='release' || TEST_TYPE='debug'
142-
echo "Building $TEST_TYPE"
128+
export RN_ARCHITECTURE="${{ matrix.rn-architecture }}"
129+
[[ "${{ matrix.build-type }}" == "production" ]] && export CONFIG='release' || export CONFIG='debug'
143130
144-
./gradlew ":app:assemble$CONFIG" -PreactNativeArchitectures=x86
131+
./scripts/set-dsn-aos.mjs
132+
./scripts/build-android.sh -PreactNativeArchitectures=x86
145133
146134
- name: Build iOS App
147135
if: ${{ matrix.platform == 'ios' }}
148-
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}/ios
136+
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
149137
run: |
150-
[[ "${{ matrix.build-type }}" == "production" ]] && CONFIG='Release' || CONFIG='Debug'
151-
echo "Building $CONFIG"
152-
mkdir -p "DerivedData"
153-
derivedData="$(cd "DerivedData" ; pwd -P)"
154-
set -o pipefail && xcodebuild \
155-
-workspace sentryreactnativesample.xcworkspace \
156-
-configuration "$CONFIG" \
157-
-scheme sentryreactnativesample \
158-
-sdk 'iphonesimulator' \
159-
-destination 'generic/platform=iOS Simulator' \
160-
ONLY_ACTIVE_ARCH=yes \
161-
-derivedDataPath "$derivedData" \
162-
build \
163-
| tee xcodebuild.log \
164-
| xcbeautify --quieter --is-ci --disable-colored-output
138+
[[ "${{ matrix.build-type }}" == "production" ]] && export CONFIG='Release' || export CONFIG='Debug'
139+
140+
./scripts/set-dsn-ios.mjs
141+
./scripts/build-ios.sh
165142
166143
- name: Build macOS App
167144
if: ${{ matrix.platform == 'macos' }}
168145
working-directory: samples/react-native-macos/macos
169146
run: |
170-
[[ "${{ matrix.build-type }}" == "production" ]] && CONFIG='Release' || CONFIG='Debug'
147+
[[ "${{ matrix.build-type }}" == "production" ]] && export CONFIG='Release' || export CONFIG='Debug'
171148
echo "Building $CONFIG"
172149
mkdir -p "DerivedData"
173150
derivedData="$(cd "DerivedData" ; pwd -P)"
@@ -184,19 +161,19 @@ jobs:
184161
185162
- name: Archive iOS App
186163
if: ${{ matrix.platform == 'ios' && matrix.rn-architecture == 'new' && matrix.build-type == 'production' && matrix.ios-use-frameworks == 'no-frameworks' }}
164+
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
187165
run: |
188-
cd ${{ env.REACT_NATIVE_SAMPLE_PATH }}/ios/DerivedData/Build/Products/Release-iphonesimulator
189166
zip -r \
190167
${{ github.workspace }}/${{ env.IOS_APP_ARCHIVE_PATH }} \
191168
sentryreactnativesample.app
192169
193170
- name: Archive Android App
194171
if: ${{ matrix.platform == 'android' && matrix.rn-architecture == 'new' && matrix.build-type == 'production' }}
195172
run: |
196-
mv ${{ env.REACT_NATIVE_SAMPLE_PATH }}/android/app/build/outputs/apk/release/app-release.apk app.apk
197173
zip -j \
198174
${{ env.ANDROID_APP_ARCHIVE_PATH }} \
199-
app.apk
175+
${{ env.REACT_NATIVE_SAMPLE_PATH }}/app.apk \
176+
${{ env.REACT_NATIVE_SAMPLE_PATH }}/app-androidTest.apk
200177
201178
- name: Upload iOS APP
202179
if: ${{ matrix.platform == 'ios' && matrix.rn-architecture == 'new' && matrix.build-type == 'production' && matrix.ios-use-frameworks == 'no-frameworks' }}
@@ -272,7 +249,9 @@ jobs:
272249
- name: Unzip Android APK
273250
if: ${{ matrix.platform == 'android' }}
274251
working-directory: ${{ env.REACT_NATIVE_SAMPLE_PATH }}
275-
run: unzip ${{ env.ANDROID_APP_ARCHIVE_PATH }}
252+
run: |
253+
unzip ${{ env.ANDROID_APP_ARCHIVE_PATH }}
254+
rm app-androidTest.apk
276255
277256
- name: Enable Corepack
278257
run: npm i -g corepack

CHANGELOG.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,75 @@ See our [migration docs](https://docs.sentry.io/platforms/react-native/migration
3131
- **Sentry Self-Hosted**: ([#5523](https://github.com/getsentry/sentry-react-native/pull/5523))
3232
- Sentry CLI v3 requires self-hosted **25.11.1+** (previously 25.2.0)
3333

34+
### Features
35+
36+
- Capture App Start errors and crashes by initializing Sentry from `sentry.options.json` ([#4472](https://github.com/getsentry/sentry-react-native/pull/4472))
37+
38+
Create `sentry.options.json` in the React Native project root and set options the same as you currently have in `Sentry.init` in JS.
39+
40+
```json
41+
{
42+
"dsn": "https://key@example.io/value",
43+
}
44+
```
45+
46+
Initialize Sentry on the native layers by newly provided native methods.
47+
48+
```kotlin
49+
import io.sentry.react.RNSentrySDK
50+
51+
class MainApplication : Application(), ReactApplication {
52+
override fun onCreate() {
53+
super.onCreate()
54+
RNSentrySDK.init(this)
55+
}
56+
}
57+
```
58+
59+
```obj-c
60+
#import <RNSentry/RNSentry.h>
61+
62+
@implementation AppDelegate
63+
- (BOOL)application:(UIApplication *)application
64+
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
65+
{
66+
[RNSentrySDK start];
67+
return [super application:application didFinishLaunchingWithOptions:launchOptions];
68+
}
69+
@end
70+
```
71+
72+
- Add RNSentrySDK APIs support to @sentry/react-native/expo plugin ([#4633](https://github.com/getsentry/sentry-react-native/pull/4633))
73+
- Adds `useNativeInit` option to automatically initialize Sentry natively before JavaScript loads, enabling capture of app start errors
74+
```json
75+
{
76+
"expo": {
77+
"plugins": [
78+
[
79+
"@sentry/react-native/expo",
80+
{
81+
"useNativeInit": true
82+
}
83+
]
84+
]
85+
}
86+
}
87+
```
88+
89+
### Changes
90+
91+
- Load `optionsFile` into the JS bundle during Metro bundle process ([#4476](https://github.com/getsentry/sentry-react-native/pull/4476))
92+
- Add experimental version of `startWithConfigureOptions` for Apple platforms ([#4444](https://github.com/getsentry/sentry-react-native/pull/4444))
93+
- Add experimental version of `init` with optional `OptionsConfiguration<SentryAndroidOptions>` for Android ([#4451](https://github.com/getsentry/sentry-react-native/pull/4451))
94+
- Add initialization using `sentry.options.json` for Apple platforms ([#4447](https://github.com/getsentry/sentry-react-native/pull/4447))
95+
- Add initialization using `sentry.options.json` for Android ([#4451](https://github.com/getsentry/sentry-react-native/pull/4451))
96+
- Merge options from file with `Sentry.init` options in JS ([#4510](https://github.com/getsentry/sentry-react-native/pull/4510))
97+
98+
### Internal
99+
100+
- Extract iOS native initialization to standalone structures ([#4442](https://github.com/getsentry/sentry-react-native/pull/4442))
101+
- Extract Android native initialization to standalone structures ([#4445](https://github.com/getsentry/sentry-react-native/pull/4445))
102+
34103
### Dependencies
35104

36105
- Bump Cocoa SDK from v8.58.0 to v9.1.0 ([#5356](https://github.com/getsentry/sentry-react-native/pull/5356))

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
"performance-tests/*"
99
],
1010
"npmClient": "yarn"
11-
}
11+
}

packages/core/RNSentry.podspec

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,14 @@ Pod::Spec.new do |s|
4242
s.preserve_paths = '*.js'
4343

4444
s.source_files = 'ios/**/*.{h,m,mm}'
45-
s.public_header_files = 'ios/RNSentry.h'
45+
s.public_header_files = 'ios/RNSentry.h', 'ios/RNSentrySDK.h', 'ios/RNSentryStart.h', 'ios/RNSentryVersion.h', 'ios/RNSentryBreadcrumb.h', 'ios/RNSentryReplay.h', 'ios/RNSentryReplayBreadcrumbConverter.h', 'ios/Replay/RNSentryReplayMask.h', 'ios/Replay/RNSentryReplayUnmask.h', 'ios/RNSentryTimeToDisplay.h'
4646

4747
s.compiler_flags = other_cflags
4848

49+
s.pod_target_xcconfig = {
50+
'DEFINES_MODULE' => 'YES'
51+
}
52+
4953
s.dependency 'Sentry/HybridSDK', '9.1.0'
5054

5155
if defined? install_modules_dependencies
@@ -56,10 +60,10 @@ Pod::Spec.new do |s|
5660

5761
if is_new_arch_enabled then
5862
# New Architecture on React Native 0.70 and older
59-
s.pod_target_xcconfig = {
63+
s.pod_target_xcconfig.merge!({
6064
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
6165
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
62-
}
66+
})
6367

6468
s.dependency "React-RCTFabric" # Required for Fabric Components (like RCTViewComponentView)
6569
s.dependency "React-Codegen"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"dsn": "invalid-dsn"
3+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
invalid-options
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"dsn": "https://abcd@efgh.ingest.sentry.io/123456",
3+
"enableTracing": true,
4+
"tracesSampleRate": 1.0
5+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package io.sentry.react
2+
3+
import androidx.test.ext.junit.runners.AndroidJUnit4
4+
import com.facebook.react.bridge.WritableArray
5+
import com.facebook.react.bridge.WritableMap
6+
import io.sentry.react.RNSentryJsonConverter.convertToWritable
7+
import org.json.JSONArray
8+
import org.json.JSONObject
9+
import org.junit.Assert.assertEquals
10+
import org.junit.Assert.assertNotNull
11+
import org.junit.Assert.assertNull
12+
import org.junit.Test
13+
import org.junit.runner.RunWith
14+
15+
@RunWith(AndroidJUnit4::class)
16+
class RNSentryJsonConverterTest {
17+
@Test
18+
fun testConvertToWritableWithSimpleJsonObject() {
19+
val jsonObject =
20+
JSONObject().apply {
21+
put("floatKey", 12.3f)
22+
put("doubleKey", 12.3)
23+
put("intKey", 123)
24+
put("stringKey", "test")
25+
put("nullKey", JSONObject.NULL)
26+
}
27+
28+
val result: WritableMap? = convertToWritable(jsonObject)
29+
30+
assertNotNull(result)
31+
assertEquals(12.3, result!!.getDouble("floatKey"), 0.0001)
32+
assertEquals(12.3, result.getDouble("doubleKey"), 0.0)
33+
assertEquals(123, result.getInt("intKey"))
34+
assertEquals("test", result.getString("stringKey"))
35+
assertNull(result.getString("nullKey"))
36+
}
37+
38+
@Test
39+
fun testConvertToWritableWithNestedJsonObject() {
40+
val jsonObject =
41+
JSONObject().apply {
42+
put(
43+
"nested",
44+
JSONObject().apply {
45+
put("key", "value")
46+
},
47+
)
48+
}
49+
50+
val result: WritableMap? = convertToWritable(jsonObject)
51+
52+
assertNotNull(result)
53+
val nestedMap = result!!.getMap("nested")
54+
assertNotNull(nestedMap)
55+
assertEquals("value", nestedMap!!.getString("key"))
56+
}
57+
58+
@Test
59+
fun testConvertToWritableWithJsonArray() {
60+
val jsonArray =
61+
JSONArray().apply {
62+
put(1)
63+
put(2.5)
64+
put("string")
65+
put(JSONObject.NULL)
66+
}
67+
68+
val result: WritableArray = convertToWritable(jsonArray)
69+
70+
assertEquals(1, result.getInt(0))
71+
assertEquals(2.5, result.getDouble(1), 0.0)
72+
assertEquals("string", result.getString(2))
73+
assertNull(result.getString(3))
74+
}
75+
76+
@Test
77+
fun testConvertToWritableWithNestedJsonArray() {
78+
val jsonObject =
79+
JSONObject().apply {
80+
put(
81+
"array",
82+
JSONArray().apply {
83+
put(
84+
JSONObject().apply {
85+
put("key1", "value1")
86+
},
87+
)
88+
put(
89+
JSONObject().apply {
90+
put("key2", "value2")
91+
},
92+
)
93+
},
94+
)
95+
}
96+
97+
val result: WritableMap? = convertToWritable(jsonObject)
98+
99+
val array = result?.getArray("array")
100+
assertEquals("value1", array?.getMap(0)?.getString("key1"))
101+
assertEquals("value2", array?.getMap(1)?.getString("key2"))
102+
}
103+
}

0 commit comments

Comments
 (0)