diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e8f5941ef..55f6beeb0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Uses Process.startUptimeMillis to calculate app-start timings - To enable this feature set `options.isEnablePerformanceV2 = true` - Move slow+frozen frame calculation, as well as frame delay inside SentryFrameMetricsCollector ([#3100](https://github.com/getsentry/sentry-java/pull/3100)) +- Extract Activity Breadcrumbs generation into own Integration ([#3064](https://github.com/getsentry/sentry-java/pull/3064)) ### Fixes diff --git a/sentry-android-core/api/sentry-android-core.api b/sentry-android-core/api/sentry-android-core.api index e6f49c5904..360364d59d 100644 --- a/sentry-android-core/api/sentry-android-core.api +++ b/sentry-android-core/api/sentry-android-core.api @@ -1,3 +1,16 @@ +public final class io/sentry/android/core/ActivityBreadcrumbsIntegration : android/app/Application$ActivityLifecycleCallbacks, io/sentry/Integration, java/io/Closeable { + public fun (Landroid/app/Application;)V + public fun close ()V + public fun onActivityCreated (Landroid/app/Activity;Landroid/os/Bundle;)V + public fun onActivityDestroyed (Landroid/app/Activity;)V + public fun onActivityPaused (Landroid/app/Activity;)V + public fun onActivityResumed (Landroid/app/Activity;)V + public fun onActivitySaveInstanceState (Landroid/app/Activity;Landroid/os/Bundle;)V + public fun onActivityStarted (Landroid/app/Activity;)V + public fun onActivityStopped (Landroid/app/Activity;)V + public fun register (Lio/sentry/IHub;Lio/sentry/SentryOptions;)V +} + public final class io/sentry/android/core/ActivityFramesTracker { public fun (Lio/sentry/android/core/LoadClass;Lio/sentry/android/core/SentryAndroidOptions;)V public fun (Lio/sentry/android/core/LoadClass;Lio/sentry/android/core/SentryAndroidOptions;Lio/sentry/android/core/MainLooperHandler;)V diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/ActivityBreadcrumbsIntegration.java b/sentry-android-core/src/main/java/io/sentry/android/core/ActivityBreadcrumbsIntegration.java new file mode 100644 index 0000000000..dc03abe808 --- /dev/null +++ b/sentry-android-core/src/main/java/io/sentry/android/core/ActivityBreadcrumbsIntegration.java @@ -0,0 +1,123 @@ +package io.sentry.android.core; + +import static io.sentry.TypeCheckHint.ANDROID_ACTIVITY; +import static io.sentry.util.IntegrationUtils.addIntegrationToSdkVersion; + +import android.app.Activity; +import android.app.Application; +import android.os.Bundle; +import io.sentry.Breadcrumb; +import io.sentry.Hint; +import io.sentry.IHub; +import io.sentry.Integration; +import io.sentry.SentryLevel; +import io.sentry.SentryOptions; +import io.sentry.util.Objects; +import java.io.Closeable; +import java.io.IOException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** Automatically adds breadcrumbs for Activity Lifecycle Events. */ +public final class ActivityBreadcrumbsIntegration + implements Integration, Closeable, Application.ActivityLifecycleCallbacks { + + private final @NotNull Application application; + private @Nullable IHub hub; + private boolean enabled; + + public ActivityBreadcrumbsIntegration(final @NotNull Application application) { + this.application = Objects.requireNonNull(application, "Application is required"); + } + + @Override + public void register(final @NotNull IHub hub, final @NotNull SentryOptions options) { + final SentryAndroidOptions androidOptions = + Objects.requireNonNull( + (options instanceof SentryAndroidOptions) ? (SentryAndroidOptions) options : null, + "SentryAndroidOptions is required"); + + this.hub = Objects.requireNonNull(hub, "Hub is required"); + this.enabled = androidOptions.isEnableActivityLifecycleBreadcrumbs(); + options + .getLogger() + .log(SentryLevel.DEBUG, "ActivityBreadcrumbsIntegration enabled: %s", enabled); + + if (enabled) { + application.registerActivityLifecycleCallbacks(this); + options.getLogger().log(SentryLevel.DEBUG, "ActivityBreadcrumbIntegration installed."); + addIntegrationToSdkVersion(getClass()); + } + } + + @Override + public void close() throws IOException { + if (enabled) { + application.unregisterActivityLifecycleCallbacks(this); + if (hub != null) { + hub.getOptions() + .getLogger() + .log(SentryLevel.DEBUG, "ActivityBreadcrumbsIntegration removed."); + } + } + } + + @Override + public synchronized void onActivityCreated( + final @NotNull Activity activity, final @Nullable Bundle savedInstanceState) { + addBreadcrumb(activity, "created"); + } + + @Override + public synchronized void onActivityStarted(final @NotNull Activity activity) { + addBreadcrumb(activity, "started"); + } + + @Override + public synchronized void onActivityResumed(final @NotNull Activity activity) { + addBreadcrumb(activity, "resumed"); + } + + @Override + public synchronized void onActivityPaused(final @NotNull Activity activity) { + addBreadcrumb(activity, "paused"); + } + + @Override + public synchronized void onActivityStopped(final @NotNull Activity activity) { + addBreadcrumb(activity, "stopped"); + } + + @Override + public synchronized void onActivitySaveInstanceState( + final @NotNull Activity activity, final @NotNull Bundle outState) { + addBreadcrumb(activity, "saveInstanceState"); + } + + @Override + public synchronized void onActivityDestroyed(final @NotNull Activity activity) { + addBreadcrumb(activity, "destroyed"); + } + + private void addBreadcrumb(final @NotNull Activity activity, final @NotNull String state) { + if (hub == null) { + return; + } + + final Breadcrumb breadcrumb = new Breadcrumb(); + breadcrumb.setType("navigation"); + breadcrumb.setData("state", state); + breadcrumb.setData("screen", getActivityName(activity)); + breadcrumb.setCategory("ui.lifecycle"); + breadcrumb.setLevel(SentryLevel.INFO); + + final Hint hint = new Hint(); + hint.set(ANDROID_ACTIVITY, activity); + + hub.addBreadcrumb(breadcrumb, hint); + } + + private @NotNull String getActivityName(final @NotNull Activity activity) { + return activity.getClass().getSimpleName(); + } +} diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java b/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java index 87771da8e0..11dcc0d160 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java @@ -1,7 +1,6 @@ package io.sentry.android.core; import static io.sentry.MeasurementUnit.Duration.MILLISECOND; -import static io.sentry.TypeCheckHint.ANDROID_ACTIVITY; import static io.sentry.util.IntegrationUtils.addIntegrationToSdkVersion; import android.app.Activity; @@ -12,9 +11,7 @@ import android.os.Looper; import android.view.View; import androidx.annotation.NonNull; -import io.sentry.Breadcrumb; import io.sentry.FullyDisplayedReporter; -import io.sentry.Hint; import io.sentry.IHub; import io.sentry.IScope; import io.sentry.ISpan; @@ -112,13 +109,6 @@ public void register(final @NotNull IHub hub, final @NotNull SentryOptions optio this.hub = Objects.requireNonNull(hub, "Hub is required"); - this.options - .getLogger() - .log( - SentryLevel.DEBUG, - "ActivityLifecycleIntegration enabled: %s", - this.options.isEnableActivityLifecycleBreadcrumbs()); - performanceEnabled = isPerformanceEnabled(this.options); fullyDisplayedReporter = this.options.getFullyDisplayedReporter(); timeToFullDisplaySpanEnabled = this.options.isEnableTimeToFullDisplayTracing(); @@ -143,22 +133,6 @@ public void close() throws IOException { activityFramesTracker.stop(); } - private void addBreadcrumb(final @NotNull Activity activity, final @NotNull String state) { - if (options != null && hub != null && options.isEnableActivityLifecycleBreadcrumbs()) { - final Breadcrumb breadcrumb = new Breadcrumb(); - breadcrumb.setType("navigation"); - breadcrumb.setData("state", state); - breadcrumb.setData("screen", getActivityName(activity)); - breadcrumb.setCategory("ui.lifecycle"); - breadcrumb.setLevel(SentryLevel.INFO); - - final Hint hint = new Hint(); - hint.set(ANDROID_ACTIVITY, activity); - - hub.addBreadcrumb(breadcrumb, hint); - } - } - private @NotNull String getActivityName(final @NotNull Activity activity) { return activity.getClass().getSimpleName(); } @@ -385,7 +359,6 @@ private void finishTransaction( public synchronized void onActivityCreated( final @NotNull Activity activity, final @Nullable Bundle savedInstanceState) { setColdStart(savedInstanceState); - addBreadcrumb(activity, "created"); if (hub != null) { final @Nullable String activityClassName = ClassUtil.getClassName(activity); hub.configureScope(scope -> scope.setScreen(activityClassName)); @@ -411,7 +384,6 @@ public synchronized void onActivityStarted(final @NotNull Activity activity) { // working. Moving this to onActivityStarted fixes the problem. activityFramesTracker.addActivity(activity); } - addBreadcrumb(activity, "started"); } @Override @@ -430,7 +402,6 @@ public synchronized void onActivityResumed(final @NotNull Activity activity) { mainHandler.post(() -> onFirstFrameDrawn(ttfdSpan, ttidSpan)); } } - addBreadcrumb(activity, "resumed"); } @Override @@ -460,24 +431,22 @@ public synchronized void onActivityPaused(final @NotNull Activity activity) { lastPausedTime = hub.getOptions().getDateProvider().now(); } } - addBreadcrumb(activity, "paused"); } @Override public synchronized void onActivityStopped(final @NotNull Activity activity) { - addBreadcrumb(activity, "stopped"); + // no-op } @Override public synchronized void onActivitySaveInstanceState( final @NotNull Activity activity, final @NotNull Bundle outState) { - addBreadcrumb(activity, "saveInstanceState"); + // no-op } @Override public synchronized void onActivityDestroyed(final @NotNull Activity activity) { - if (performanceEnabled || options.isEnableActivityLifecycleBreadcrumbs()) { - addBreadcrumb(activity, "destroyed"); + if (performanceEnabled) { // in case the appStartSpan isn't completed yet, we finish it as cancelled to avoid // memory leak diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java b/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java index e014d1ac40..9d4fd8900f 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java @@ -244,6 +244,7 @@ static void installDefaultIntegrations( options.addIntegration( new ActivityLifecycleIntegration( (Application) context, buildInfoProvider, activityFramesTracker)); + options.addIntegration(new ActivityBreadcrumbsIntegration((Application) context)); options.addIntegration(new CurrentActivityIntegration((Application) context)); options.addIntegration(new UserInteractionIntegration((Application) context, loadClass)); if (isFragmentAvailable) { diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/ActivityBreadcrumbsIntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/ActivityBreadcrumbsIntegrationTest.kt new file mode 100644 index 0000000000..f104acebfa --- /dev/null +++ b/sentry-android-core/src/test/java/io/sentry/android/core/ActivityBreadcrumbsIntegrationTest.kt @@ -0,0 +1,157 @@ +package io.sentry.android.core + +import android.app.Activity +import android.app.Application +import android.os.Bundle +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.sentry.Breadcrumb +import io.sentry.Hub +import io.sentry.SentryLevel +import org.junit.runner.RunWith +import org.mockito.kotlin.any +import org.mockito.kotlin.anyOrNull +import org.mockito.kotlin.check +import org.mockito.kotlin.mock +import org.mockito.kotlin.never +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever +import kotlin.test.Test +import kotlin.test.assertEquals + +@RunWith(AndroidJUnit4::class) +class ActivityBreadcrumbsIntegrationTest { + + private class Fixture { + val application = mock() + val hub = mock() + val options = SentryAndroidOptions().apply { + dsn = "https://key@sentry.io/proj" + } + val bundle = mock() + + fun getSut(enabled: Boolean = true): ActivityBreadcrumbsIntegration { + options.isEnableActivityLifecycleBreadcrumbs = enabled + whenever(hub.options).thenReturn(options) + return ActivityBreadcrumbsIntegration( + application + ) + } + } + + private val fixture = Fixture() + + @Test + fun `When ActivityBreadcrumbsIntegration is disabled, it should not register the activity callback`() { + val sut = fixture.getSut(false) + sut.register(fixture.hub, fixture.options) + + verify(fixture.application, never()).registerActivityLifecycleCallbacks(any()) + } + + @Test + fun `When ActivityBreadcrumbsIntegration is enabled, it should register the activity callback`() { + val sut = fixture.getSut() + sut.register(fixture.hub, fixture.options) + + verify(fixture.application).registerActivityLifecycleCallbacks(any()) + + sut.close() + verify(fixture.application).unregisterActivityLifecycleCallbacks(any()) + } + + @Test + fun `When breadcrumb is added, type and category should be set`() { + val sut = fixture.getSut() + sut.register(fixture.hub, fixture.options) + + val activity = mock() + sut.onActivityCreated(activity, fixture.bundle) + + verify(fixture.hub).addBreadcrumb( + check { + assertEquals("ui.lifecycle", it.category) + assertEquals("navigation", it.type) + assertEquals(SentryLevel.INFO, it.level) + // cant assert data, its not a public API + }, + anyOrNull() + ) + } + + @Test + fun `When activity is created, it should add a breadcrumb`() { + val sut = fixture.getSut() + sut.register(fixture.hub, fixture.options) + + val activity = mock() + sut.onActivityCreated(activity, fixture.bundle) + + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) + } + + @Test + fun `When activity is started, it should add a breadcrumb`() { + val sut = fixture.getSut() + sut.register(fixture.hub, fixture.options) + + val activity = mock() + sut.onActivityStarted(activity) + + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) + } + + @Test + fun `When activity is resumed, it should add a breadcrumb`() { + val sut = fixture.getSut() + sut.register(fixture.hub, fixture.options) + + val activity = mock() + sut.onActivityResumed(activity) + + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) + } + + @Test + fun `When activity is paused, it should add a breadcrumb`() { + val sut = fixture.getSut() + sut.register(fixture.hub, fixture.options) + + val activity = mock() + sut.onActivityPaused(activity) + + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) + } + + @Test + fun `When activity is stopped, it should add a breadcrumb`() { + val sut = fixture.getSut() + sut.register(fixture.hub, fixture.options) + + val activity = mock() + sut.onActivityStopped(activity) + + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) + } + + @Test + fun `When activity is save instance, it should add a breadcrumb`() { + val sut = fixture.getSut() + sut.register(fixture.hub, fixture.options) + + val activity = mock() + sut.onActivitySaveInstanceState(activity, fixture.bundle) + + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) + } + + @Test + fun `When activity is destroyed, it should add a breadcrumb`() { + val sut = fixture.getSut() + sut.register(fixture.hub, fixture.options) + + val activity = mock() + sut.onActivityDestroyed(activity) + + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) + } +} diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt index f5f482ad43..0fb9d1f05f 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt @@ -12,7 +12,6 @@ import android.view.View import android.view.ViewTreeObserver import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.sentry.Breadcrumb import io.sentry.DateUtils import io.sentry.FullyDisplayedReporter import io.sentry.Hub @@ -21,9 +20,7 @@ import io.sentry.Scope import io.sentry.ScopeCallback import io.sentry.Sentry import io.sentry.SentryDate -import io.sentry.SentryLevel import io.sentry.SentryNanotimeDate -import io.sentry.SentryOptions import io.sentry.SentryTracer import io.sentry.Span import io.sentry.SpanStatus @@ -145,7 +142,7 @@ class ActivityLifecycleIntegrationTest { } @Test - fun `When activity lifecycle breadcrumb is enabled, it registers callback`() { + fun `When ActivityLifecycleIntegration is registered, it registers activity callback`() { val sut = fixture.getSut() sut.register(fixture.hub, fixture.options) @@ -153,75 +150,7 @@ class ActivityLifecycleIntegrationTest { } @Test - fun `When activity lifecycle breadcrumb and tracing are disabled, it still registers callback`() { - val sut = fixture.getSut() - fixture.options.isEnableActivityLifecycleBreadcrumbs = false - - sut.register(fixture.hub, fixture.options) - - verify(fixture.application).registerActivityLifecycleCallbacks(any()) - } - - @Test - fun `When activity lifecycle breadcrumb is disabled but tracing is enabled, it registers callback`() { - val sut = fixture.getSut() - fixture.options.isEnableActivityLifecycleBreadcrumbs = false - fixture.options.enableTracing = true - - sut.register(fixture.hub, fixture.options) - - verify(fixture.application).registerActivityLifecycleCallbacks(any()) - } - - @Test - fun `When activity lifecycle breadcrumb is disabled and tracesSampleRate is set but tracing is disabled, it still registers callback`() { - val sut = fixture.getSut() - fixture.options.isEnableActivityLifecycleBreadcrumbs = false - fixture.options.tracesSampleRate = 1.0 - fixture.options.enableTracing = false - - sut.register(fixture.hub, fixture.options) - - verify(fixture.application).registerActivityLifecycleCallbacks(any()) - } - - @Test - fun `When activity lifecycle breadcrumb is disabled but tracing sample rate is enabled, it registers callback`() { - val sut = fixture.getSut() - fixture.options.isEnableActivityLifecycleBreadcrumbs = false - fixture.options.tracesSampleRate = 1.0 - - sut.register(fixture.hub, fixture.options) - - verify(fixture.application).registerActivityLifecycleCallbacks(any()) - } - - @Test - fun `When activity lifecycle breadcrumb is disabled but tracing sample callback is enabled, it registers callback`() { - val sut = fixture.getSut() - fixture.options.isEnableActivityLifecycleBreadcrumbs = false - fixture.options.tracesSampler = SentryOptions.TracesSamplerCallback { 1.0 } - - sut.register(fixture.hub, fixture.options) - - verify(fixture.application).registerActivityLifecycleCallbacks(any()) - } - - @Test - fun `When activity lifecycle breadcrumb and tracing activity flag are disabled, its still registers callback`() { - val sut = fixture.getSut() - fixture.options.isEnableActivityLifecycleBreadcrumbs = false - fixture.options.tracesSampleRate = 1.0 - fixture.options.tracesSampler = SentryOptions.TracesSamplerCallback { 1.0 } - fixture.options.isEnableAutoActivityLifecycleTracing = false - - sut.register(fixture.hub, fixture.options) - - verify(fixture.application).registerActivityLifecycleCallbacks(any()) - } - - @Test - fun `When ActivityBreadcrumbsIntegration is closed, it should unregister the callback`() { + fun `When ActivityLifecycleIntegration is closed, it should unregister the callback`() { val sut = fixture.getSut() sut.register(fixture.hub, fixture.options) @@ -231,7 +160,7 @@ class ActivityLifecycleIntegrationTest { } @Test - fun `When ActivityBreadcrumbsIntegration is closed, it should close the ActivityFramesTracker`() { + fun `When ActivityLifecycleIntegration is closed, it should close the ActivityFramesTracker`() { val sut = fixture.getSut() sut.register(fixture.hub, fixture.options) @@ -240,102 +169,6 @@ class ActivityLifecycleIntegrationTest { verify(fixture.activityFramesTracker).stop() } - @Test - fun `When breadcrumb is added, type and category should be set`() { - val sut = fixture.getSut() - sut.register(fixture.hub, fixture.options) - - val activity = mock() - sut.onActivityCreated(activity, fixture.bundle) - - verify(fixture.hub).addBreadcrumb( - check { - assertEquals("ui.lifecycle", it.category) - assertEquals("navigation", it.type) - assertEquals(SentryLevel.INFO, it.level) - // cant assert data, its not a public API - }, - anyOrNull() - ) - } - - @Test - fun `When activity is created, it should add a breadcrumb`() { - val sut = fixture.getSut() - sut.register(fixture.hub, fixture.options) - - val activity = mock() - sut.onActivityCreated(activity, fixture.bundle) - - verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) - } - - @Test - fun `When activity is started, it should add a breadcrumb`() { - val sut = fixture.getSut() - sut.register(fixture.hub, fixture.options) - - val activity = mock() - sut.onActivityStarted(activity) - - verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) - } - - @Test - fun `When activity is resumed, it should add a breadcrumb`() { - val sut = fixture.getSut() - sut.register(fixture.hub, fixture.options) - - val activity = mock() - sut.onActivityResumed(activity) - - verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) - } - - @Test - fun `When activity is paused, it should add a breadcrumb`() { - val sut = fixture.getSut() - sut.register(fixture.hub, fixture.options) - - val activity = mock() - sut.onActivityPaused(activity) - - verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) - } - - @Test - fun `When activity is stopped, it should add a breadcrumb`() { - val sut = fixture.getSut() - sut.register(fixture.hub, fixture.options) - - val activity = mock() - sut.onActivityStopped(activity) - - verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) - } - - @Test - fun `When activity is save instance, it should add a breadcrumb`() { - val sut = fixture.getSut() - sut.register(fixture.hub, fixture.options) - - val activity = mock() - sut.onActivitySaveInstanceState(activity, fixture.bundle) - - verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) - } - - @Test - fun `When activity is destroyed, it should add a breadcrumb`() { - val sut = fixture.getSut() - sut.register(fixture.hub, fixture.options) - - val activity = mock() - sut.onActivityDestroyed(activity) - - verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) - } - @Test fun `When tracing is disabled, do not start tracing`() { val sut = fixture.getSut() diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt index 3b9c012c38..2f34b2a066 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt @@ -418,6 +418,15 @@ class AndroidOptionsInitializerTest { assertNull(actual) } + @Test + fun `When given Context is not an Application class, do not add ActivityBreadcrumbsIntegration`() { + fixture.initSut(hasAppContext = false) + + val actual = fixture.sentryOptions.integrations + .firstOrNull { it is ActivityBreadcrumbsIntegration } + assertNull(actual) + } + @Test fun `When given Context is not an Application class, do not add UserInteractionIntegration`() { fixture.initSut(hasAppContext = false) diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidTest.kt index f48868ad72..4c431e8bc9 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidTest.kt @@ -409,7 +409,7 @@ class SentryAndroidTest { fixture.initSut(context = mock()) { options -> optionsRef = options options.dsn = "https://key@sentry.io/123" - assertEquals(18, options.integrations.size) + assertEquals(19, options.integrations.size) options.integrations.removeAll { it is UncaughtExceptionHandlerIntegration || it is ShutdownHookIntegration || @@ -419,6 +419,7 @@ class SentryAndroidTest { it is AppLifecycleIntegration || it is AnrIntegration || it is ActivityLifecycleIntegration || + it is ActivityBreadcrumbsIntegration || it is CurrentActivityIntegration || it is UserInteractionIntegration || it is FragmentLifecycleIntegration ||