commit a44e6ff6ffc043f664d03812775b7cb00ff7ff68
parent 95e4c34b2164a01edcf582eb662da439ec7eea9b
Author: mcarare <48995920+mcarare@users.noreply.github.com>
Date: Tue, 4 Nov 2025 15:15:10 +0000
Bug 1997939 - Extract DownloadCancelDialogFragment creation in BrowserScreenMiddleware r=android-reviewers,avirvara
This patch refactors the `BrowserScreenMiddleware` to extract the creation and styling of the `DownloadCancelDialogFragment` into new, testable methods.
Differential Revision: https://phabricator.services.mozilla.com/D271190
Diffstat:
2 files changed, 65 insertions(+), 88 deletions(-)
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/store/BrowserScreenMiddleware.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/store/BrowserScreenMiddleware.kt
@@ -4,6 +4,7 @@
package org.mozilla.fenix.browser.store
+import android.content.Context
import android.view.Gravity
import androidx.annotation.VisibleForTesting
import mozilla.components.concept.base.crash.Breadcrumb
@@ -74,31 +75,51 @@ class BrowserScreenMiddleware(
crashReporter.recordCrashBreadcrumb(
Breadcrumb("DownloadCancelDialogFragment shown in browser screen"),
)
- val dialog = DownloadCancelDialogFragment.newInstance(
+ val dialog = createDownloadCancelDialog(environment.context, store, downloadCount, tabId)
+
+ dialog.show(environment.fragmentManager, CANCEL_PRIVATE_DOWNLOADS_DIALOG_FRAGMENT_TAG)
+ }
+
+ /**
+ * Creates and configures a new instance of [DownloadCancelDialogFragment].
+ */
+ @VisibleForTesting
+ internal fun createDownloadCancelDialog(
+ context: Context,
+ store: Store<BrowserScreenState, BrowserScreenAction>,
+ downloadCount: Int,
+ tabId: String?,
+ ): DownloadCancelDialogFragment {
+ return DownloadCancelDialogFragment.newInstance(
downloadCount = downloadCount,
tabId = tabId,
source = null,
- promptStyling = DownloadCancelDialogFragment.PromptStyling(
- gravity = Gravity.BOTTOM,
- shouldWidthMatchParent = true,
- positiveButtonBackgroundColor = ThemeManager.resolveAttribute(
- R.attr.accent,
- environment.context,
- ),
- positiveButtonTextColor = ThemeManager.resolveAttribute(
- R.attr.textOnColorPrimary,
- environment.context,
- ),
- positiveButtonRadius = environment.context.pixelSizeFor(
- R.dimen.tab_corner_radius,
- ).toFloat(),
- ),
-
+ promptStyling = createDialogPromptStyling(context),
onPositiveButtonClicked = { _, _ ->
store.dispatch(CancelPrivateDownloadsOnPrivateTabsClosedAccepted)
},
)
- dialog.show(environment.fragmentManager, CANCEL_PRIVATE_DOWNLOADS_DIALOG_FRAGMENT_TAG)
+ }
+
+ /**
+ * Creates the specific styling configuration for the download cancellation prompt.
+ */
+ fun createDialogPromptStyling(context: Context): DownloadCancelDialogFragment.PromptStyling {
+ return DownloadCancelDialogFragment.PromptStyling(
+ gravity = Gravity.BOTTOM,
+ shouldWidthMatchParent = true,
+ positiveButtonBackgroundColor = ThemeManager.resolveAttribute(
+ R.attr.accent,
+ context,
+ ),
+ positiveButtonTextColor = ThemeManager.resolveAttribute(
+ R.attr.textOnColorPrimary,
+ context,
+ ),
+ positiveButtonRadius = context.pixelSizeFor(
+ R.dimen.tab_corner_radius,
+ ).toFloat(),
+ )
}
/**
diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/browser/store/BrowserScreenMiddlewareTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/browser/store/BrowserScreenMiddlewareTest.kt
@@ -5,122 +5,78 @@
package org.mozilla.fenix.browser.store
import android.content.Context
-import android.view.Gravity
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.test.ext.junit.runners.AndroidJUnit4
-import io.mockk.Runs
import io.mockk.every
-import io.mockk.just
import io.mockk.mockk
-import io.mockk.mockkObject
-import io.mockk.slot
+import io.mockk.spyk
import io.mockk.verify
import mozilla.components.feature.downloads.ui.DownloadCancelDialogFragment
import mozilla.components.lib.crash.CrashReporter
import mozilla.components.lib.state.Middleware
import mozilla.components.support.test.middleware.CaptureActionsMiddleware
import mozilla.components.support.test.robolectric.testContext
-import mozilla.components.support.test.rule.MainCoroutineRule
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
-import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
-import org.mozilla.fenix.R
import org.mozilla.fenix.browser.store.BrowserScreenAction.CancelPrivateDownloadsOnPrivateTabsClosedAccepted
import org.mozilla.fenix.browser.store.BrowserScreenAction.EnvironmentCleared
import org.mozilla.fenix.browser.store.BrowserScreenAction.EnvironmentRehydrated
import org.mozilla.fenix.browser.store.BrowserScreenMiddleware.Companion.CANCEL_PRIVATE_DOWNLOADS_DIALOG_FRAGMENT_TAG
import org.mozilla.fenix.browser.store.BrowserScreenStore.Environment
import org.mozilla.fenix.helpers.lifecycle.TestLifecycleOwner
-import org.mozilla.fenix.theme.ThemeManager
@RunWith(AndroidJUnit4::class)
class BrowserScreenMiddlewareTest {
- @get:Rule
- private val coroutinesTestRule = MainCoroutineRule()
+
private val lifecycleOwner = TestLifecycleOwner(Lifecycle.State.RESUMED)
private val fragmentManager: FragmentManager = mockk(relaxed = true)
+ private val crashReporter: CrashReporter = mockk(relaxed = true)
@Test
fun `WHEN the last private tab is closing THEN record a breadcrumb and show a warning dialog`() {
- val crashReporter: CrashReporter = mockk(relaxed = true)
- val middleware = BrowserScreenMiddleware(crashReporter)
+ val middleware = spyk(BrowserScreenMiddleware(crashReporter))
val store = buildStore(listOf(middleware))
- val warningDialog: DownloadCancelDialogFragment = mockk {
- every { show(any<FragmentManager>(), any<String>()) } just Runs
- }
+ val warningDialog: DownloadCancelDialogFragment = mockk(relaxed = true)
+
+ every { middleware.createDownloadCancelDialog(any(), any(), any(), any()) } returns warningDialog
+
+ store.dispatch(BrowserScreenAction.ClosingLastPrivateTab(tabId = "tabId", inProgressPrivateDownloads = 3))
- mockkObject(DownloadCancelDialogFragment.Companion) {
- every { DownloadCancelDialogFragment.Companion.newInstance(any(), any(), any(), any(), any(), any(), any()) } returns warningDialog
-
- store.dispatch(BrowserScreenAction.ClosingLastPrivateTab("tabId", 3))
-
- verify { crashReporter.recordCrashBreadcrumb(any()) }
- verify {
- DownloadCancelDialogFragment.Companion.newInstance(
- downloadCount = 3,
- tabId = "tabId",
- source = null,
- promptStyling = DownloadCancelDialogFragment.PromptStyling(
- gravity = Gravity.BOTTOM,
- shouldWidthMatchParent = true,
- positiveButtonBackgroundColor = ThemeManager.resolveAttribute(
- R.attr.accent,
- testContext,
- ),
- positiveButtonTextColor = ThemeManager.resolveAttribute(
- R.attr.textOnColorPrimary,
- testContext,
- ),
- positiveButtonRadius = testContext.resources.getDimensionPixelSize(
- R.dimen.tab_corner_radius,
- ).toFloat(),
- ),
- onPositiveButtonClicked = any(),
- onNegativeButtonClicked = null,
- )
- }
- verify { warningDialog.show(fragmentManager, CANCEL_PRIVATE_DOWNLOADS_DIALOG_FRAGMENT_TAG) }
+ verify { crashReporter.recordCrashBreadcrumb(any()) }
+ verify {
+ middleware.createDownloadCancelDialog(
+ context = testContext,
+ store = store,
+ downloadCount = 3,
+ tabId = "tabId",
+ )
}
+ verify { warningDialog.show(fragmentManager, CANCEL_PRIVATE_DOWNLOADS_DIALOG_FRAGMENT_TAG) }
}
@Test
fun `GIVEN a warning dialog for closing private tabs is shown WHEN the warning is accepted THEN inform about this`() {
- val middleware = BrowserScreenMiddleware(mockk(relaxed = true))
+ val middleware = spyk(BrowserScreenMiddleware(crashReporter))
val captureActionsMiddleware = CaptureActionsMiddleware<BrowserScreenState, BrowserScreenAction>()
val store = buildStore(listOf(middleware, captureActionsMiddleware))
- val warningDialog: DownloadCancelDialogFragment = mockk {
- every { show(any<FragmentManager>(), any<String>()) } just Runs
- }
- val positiveActionCaptor = slot<((tabId: String?, source: String?) -> Unit)>()
-
- mockkObject(DownloadCancelDialogFragment.Companion) {
- every { DownloadCancelDialogFragment.Companion.newInstance(any()) } returns warningDialog
-
- store.dispatch(BrowserScreenAction.ClosingLastPrivateTab("tabId", 3))
- verify {
- DownloadCancelDialogFragment.Companion.newInstance(
- downloadCount = any(),
- tabId = any(),
- source = any(),
- promptStyling = any(),
- onPositiveButtonClicked = capture(positiveActionCaptor),
- onNegativeButtonClicked = any(),
- )
- }
- }
+ val warningDialog: DownloadCancelDialogFragment = mockk(relaxed = true)
+
+ every { middleware.createDownloadCancelDialog(any(), any(), any(), any()) } returns warningDialog
- positiveActionCaptor.captured.invoke("test", "source")
+ store.dispatch(BrowserScreenAction.ClosingLastPrivateTab("tabId", 3))
+
+ store.dispatch(CancelPrivateDownloadsOnPrivateTabsClosedAccepted)
captureActionsMiddleware.assertLastAction(CancelPrivateDownloadsOnPrivateTabsClosedAccepted::class) {}
}
@Test
fun `GIVEN an environment was already set WHEN it is cleared THEN reset it to null`() {
- val middleware = BrowserScreenMiddleware(mockk())
+ val middleware = BrowserScreenMiddleware(crashReporter)
val store = buildStore(listOf(middleware))
assertNotNull(middleware.environment)