Skip to content

Commit

Permalink
Use appLaunchedInForeground to determine invalid app start data on An…
Browse files Browse the repository at this point in the history
…droid (#4146)

* Check if appLaunchedInForeground and launch duration for native app start

---------

Co-authored-by: LucasZF <[email protected]>
  • Loading branch information
antonis and lucas-zimerman authored Oct 9, 2024
1 parent f31859f commit b95b8af
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Fixes

- Use `appLaunchedInForeground` to determine invalid app start data on Android ([#4146](https://github.com/getsentry/sentry-react-native/pull/4146))
- Upload source maps for all release variants on Android (not only the last found) ([#4125](https://github.com/getsentry/sentry-react-native/pull/4125))

### Dependencies
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package io.sentry.react

import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.WritableMap
import io.sentry.ILogger
import io.sentry.SentryLevel
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mockito.*
import org.mockito.MockitoAnnotations
import org.mockito.MockedStatic
import org.mockito.Mockito.mockStatic
import org.mockito.kotlin.whenever

@RunWith(JUnit4::class)
class RNSentryModuleImplTest {

private lateinit var module: RNSentryModuleImpl
private lateinit var promise: Promise
private lateinit var logger: ILogger
private var argumentsMock: MockedStatic<Arguments>? = null

@Captor
private lateinit var writableMapCaptor: ArgumentCaptor<WritableMap>

@Before
fun setUp() {
MockitoAnnotations.openMocks(this)
val reactContext = mock(ReactApplicationContext::class.java)
promise = mock(Promise::class.java)
logger = mock(ILogger::class.java)
val packageManager = mock(PackageManager::class.java)
val packageInfo = mock(PackageInfo::class.java)

whenever(reactContext.packageManager).thenReturn(packageManager)
whenever(packageManager.getPackageInfo(anyString(), anyInt())).thenReturn(packageInfo)

module = RNSentryModuleImpl(reactContext)

// Mock the Arguments class
argumentsMock = mockStatic(Arguments::class.java)
val writableMap = mock(WritableMap::class.java)
whenever(Arguments.createMap()).thenReturn(writableMap)
}

@After
fun tearDown() {
argumentsMock?.close()
}

@Test
fun `fetchNativeAppStart resolves promise with null when app is not launched in the foreground`() {
// Mock the app start measurement
val appStartMeasurement = mapOf<String, Any>()

// Call the method
module.fetchNativeAppStart(promise, appStartMeasurement, logger, false)

// Verify a warning log is emitted
verify(logger, org.mockito.kotlin.times(1)).log(
SentryLevel.WARNING,
"Invalid app start data: app not launched in foreground."
)

// Verify the promise is resolved with null
verify(promise).resolve(null)
}

@Test
fun `fetchNativeAppStart resolves promise with app start data when app is launched in the foreground`() {
// Mock the app start measurement
val appStartMeasurement = mapOf<String, Any>()

// Call the method
module.fetchNativeAppStart(promise, appStartMeasurement, logger, true)

// Verify no logs are emitted
verify(logger, org.mockito.kotlin.times(0)).log(any(), any())

// Verify the promise is resolved with the expected data
verify(promise).resolve(any(WritableMap::class.java))
verify(promise).resolve(writableMapCaptor.capture())
val capturedMap = writableMapCaptor.value
assertEquals(false, capturedMap.getBoolean("has_fetched"))
}
}
12 changes: 10 additions & 2 deletions android/src/main/java/io/sentry/react/RNSentryModuleImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,17 @@ public void fetchNativeRelease(Promise promise) {
}

public void fetchNativeAppStart(Promise promise) {
final Map<String, Object> measurement = InternalSentrySdk.getAppStartMeasurement();
fetchNativeAppStart(promise, InternalSentrySdk.getAppStartMeasurement(), logger, AppStartMetrics.getInstance().isAppLaunchedInForeground());
}

protected void fetchNativeAppStart(Promise promise, final Map<String, Object> appStartMeasurement, ILogger logger, boolean isAppLaunchedInForeground) {
if (!isAppLaunchedInForeground) {
logger.log(SentryLevel.WARNING, "Invalid app start data: app not launched in foreground.");
promise.resolve(null);
return;
}

WritableMap mutableMeasurement = (WritableMap) RNSentryMapConverter.convertToWritable(measurement);
WritableMap mutableMeasurement = (WritableMap) RNSentryMapConverter.convertToWritable(appStartMeasurement);
mutableMeasurement.putBoolean("has_fetched", hasFetchedAppStart);

// This is always set to true, as we would only allow an app start fetch to only
Expand Down

0 comments on commit b95b8af

Please sign in to comment.