commit 6cefde734b2ab549bdaee1f05d45ba5ef29f1d8c
parent 8328c2006d5e572d684f62fb447d09974227f486
Author: Julie De Lorenzo <jdelorenzo@mozilla.com>
Date: Fri, 31 Oct 2025 22:26:09 +0000
Bug 1977667: Remove `NavigationInteractor` and move logic into TabManagerController r=android-reviewers,007
Differential Revision: https://phabricator.services.mozilla.com/D270352
Diffstat:
5 files changed, 266 insertions(+), 317 deletions(-)
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/controller/NavigationInteractor.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/controller/NavigationInteractor.kt
@@ -1,125 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.fenix.tabstray.controller
-
-import androidx.navigation.NavController
-import mozilla.components.browser.state.store.BrowserStore
-import mozilla.components.service.fxa.manager.FxaAccountManager
-import mozilla.telemetry.glean.private.NoExtras
-import org.mozilla.fenix.GleanMetrics.Events
-import org.mozilla.fenix.GleanMetrics.TabsTray
-import org.mozilla.fenix.components.accounts.FenixFxAEntryPoint
-import org.mozilla.fenix.home.HomeScreenViewModel.Companion.ALL_NORMAL_TABS
-import org.mozilla.fenix.home.HomeScreenViewModel.Companion.ALL_PRIVATE_TABS
-import org.mozilla.fenix.tabstray.ext.isActiveDownload
-import org.mozilla.fenix.tabstray.ui.TabManagementFragmentDirections
-
-/**
- * An interactor that helps with navigating to different parts of the app from the tab manager.
- */
-interface NavigationInteractor {
-
- /**
- * Called when tab manager should be dismissed.
- */
- fun onTabManagerDismissed()
-
- /**
- * Called when clicking the account settings button.
- */
- fun onAccountSettingsClicked()
-
- /**
- * Called when clicking the tab settings button.
- */
- fun onTabSettingsClicked()
-
- /**
- * Called when clicking the close all tabs button.
- */
- fun onCloseAllTabsClicked(private: Boolean)
-
- /**
- * Called when cancelling private downloads confirmed.
- */
- fun onCloseAllPrivateTabsWarningConfirmed(private: Boolean)
-
- /**
- * Called when opening the recently closed tabs menu button.
- */
- fun onOpenRecentlyClosedClicked()
-}
-
-/**
- * A default implementation of [NavigationInteractor].
- *
- * This is slated to get refactored in:
- * https://bugzilla.mozilla.org/show_bug.cgi?id=1977667
- */
-class DefaultNavigationInteractor(
- private val browserStore: BrowserStore,
- private val navController: NavController,
- private val dismissTabManagerAndNavigateHome: (sessionId: String) -> Unit,
- private val showCancelledDownloadWarning: (downloadCount: Int, tabId: String?, source: String?) -> Unit,
- private val accountManager: FxaAccountManager,
-) : NavigationInteractor {
-
- override fun onTabManagerDismissed() {
- TabsTray.closed.record(NoExtras())
- }
-
- override fun onAccountSettingsClicked() {
- val isSignedIn = accountManager.authenticatedAccount() != null
-
- val direction = if (isSignedIn) {
- TabManagementFragmentDirections.actionGlobalAccountSettingsFragment()
- } else {
- TabManagementFragmentDirections.actionGlobalTurnOnSync(
- entrypoint = FenixFxAEntryPoint.NavigationInteraction,
- )
- }
- navController.navigate(direction)
- }
-
- override fun onTabSettingsClicked() {
- navController.navigate(
- TabManagementFragmentDirections.actionGlobalTabSettingsFragment(),
- )
- }
-
- override fun onOpenRecentlyClosedClicked() {
- navController.navigate(
- TabManagementFragmentDirections.actionGlobalRecentlyClosed(),
- )
- Events.recentlyClosedTabsOpened.record(NoExtras())
- }
-
- override fun onCloseAllTabsClicked(private: Boolean) {
- closeAllTabs(private, isConfirmed = false)
- }
-
- override fun onCloseAllPrivateTabsWarningConfirmed(private: Boolean) {
- closeAllTabs(private, isConfirmed = true)
- }
-
- private fun closeAllTabs(private: Boolean, isConfirmed: Boolean) {
- val sessionsToClose = if (private) {
- ALL_PRIVATE_TABS
- } else {
- ALL_NORMAL_TABS
- }
-
- if (private && !isConfirmed) {
- val privateDownloads = browserStore.state.downloads.filter {
- it.value.private && it.value.isActiveDownload()
- }
- if (privateDownloads.isNotEmpty()) {
- showCancelledDownloadWarning(privateDownloads.size, null, null)
- return
- }
- }
- dismissTabManagerAndNavigateHome(sessionsToClose)
- }
-}
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/controller/TabManagerController.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/controller/TabManagerController.kt
@@ -28,6 +28,7 @@ import mozilla.components.feature.accounts.push.CloseTabsUseCases
import mozilla.components.feature.downloads.ui.DownloadCancelDialogFragment
import mozilla.components.feature.tabs.TabsUseCases
import mozilla.components.lib.state.DelicateAction
+import mozilla.components.service.fxa.manager.FxaAccountManager
import mozilla.telemetry.glean.private.NoExtras
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.GleanMetrics.Collections
@@ -179,11 +180,37 @@ interface TabManagerController : SyncedTabsController, InactiveTabsController, T
* Navigates to the sign into Sync flow
*/
fun handleSignInClicked()
+
+ /**
+ * Called when clicking the account settings button.
+ */
+ fun onAccountSettingsClicked()
+
+ /**
+ * Called when clicking the tab settings button.
+ */
+ fun onTabSettingsClicked()
+
+ /**
+ * Called when clicking the close all tabs button.
+ */
+ fun onCloseAllTabsClicked(private: Boolean)
+
+ /**
+ * Called when cancelling private downloads confirmed.
+ */
+ fun onCloseAllPrivateTabsWarningConfirmed(private: Boolean)
+
+ /**
+ * Called when opening the recently closed tabs menu button.
+ */
+ fun onOpenRecentlyClosedClicked()
}
/**
* Default implementation of [TabManagerController].
*
+ * @param accountManager [FxaAccountManager] used to determine signed in status.
* @param activity [HomeActivity] used to perform top-level app actions.
* @param appStore [AppStore] used to dispatch any [AppAction].
* @param tabsTrayStore [TabsTrayStore] used to read/update the [TabsTrayState].
@@ -193,7 +220,6 @@ interface TabManagerController : SyncedTabsController, InactiveTabsController, T
* @param navController [NavController] used to navigate away from the tab manager.
* @param navigateToHomeAndDeleteSession Lambda used to return to the Homescreen and delete the current session.
* @param profiler [Profiler] used to add profiler markers.
- * @param navigationInteractor [NavigationInteractor] used to perform navigation actions with side effects.
* @param tabsUseCases Use case wrapper for interacting with tabs.
* @param fenixBrowserUseCases [FenixBrowserUseCases] used for adding new homepage tabs.
* @param bookmarksStorage Storage layer for retrieving and saving bookmarks.
@@ -210,6 +236,7 @@ interface TabManagerController : SyncedTabsController, InactiveTabsController, T
*/
@Suppress("TooManyFunctions", "LongParameterList")
class DefaultTabManagerController(
+ private val accountManager: FxaAccountManager,
private val activity: HomeActivity,
private val appStore: AppStore,
private val tabsTrayStore: TabsTrayStore,
@@ -219,7 +246,6 @@ class DefaultTabManagerController(
private val navController: NavController,
private val navigateToHomeAndDeleteSession: (String) -> Unit,
private val profiler: Profiler?,
- private val navigationInteractor: NavigationInteractor,
private val tabsUseCases: TabsUseCases,
private val fenixBrowserUseCases: FenixBrowserUseCases,
private val bookmarksStorage: BookmarksStorage,
@@ -271,7 +297,7 @@ class DefaultTabManagerController(
)
}
- navigationInteractor.onTabManagerDismissed()
+ TabsTray.closed.record(NoExtras())
profiler?.addMarker(
"DefaultTabManagerController.onNewTabTapped",
startTime,
@@ -627,10 +653,69 @@ class DefaultTabManagerController(
)
}
+ override fun onAccountSettingsClicked() {
+ val isSignedIn = accountManager.authenticatedAccount() != null
+
+ val direction = if (isSignedIn) {
+ TabManagementFragmentDirections.actionGlobalAccountSettingsFragment()
+ } else {
+ TabManagementFragmentDirections.actionGlobalTurnOnSync(
+ entrypoint = FenixFxAEntryPoint.NavigationInteraction,
+ )
+ }
+ navController.navigate(direction)
+ }
+
+ override fun onTabSettingsClicked() {
+ navController.navigate(
+ TabManagementFragmentDirections.actionGlobalTabSettingsFragment(),
+ )
+ }
+
+ override fun onCloseAllTabsClicked(private: Boolean) {
+ closeAllTabs(private = private, isConfirmed = false)
+ }
+
+ override fun onCloseAllPrivateTabsWarningConfirmed(private: Boolean) {
+ closeAllTabs(private = private, isConfirmed = true)
+ }
+
+ override fun onOpenRecentlyClosedClicked() {
+ navController.navigate(
+ TabManagementFragmentDirections.actionGlobalRecentlyClosed(),
+ )
+ Events.recentlyClosedTabsOpened.record(NoExtras())
+ }
+
/**
* Marks the inactive tabs auto close dialog as shown and to not be displayed again.
*/
private fun markDialogAsShown() {
settings.hasInactiveTabsAutoCloseDialogBeenDismissed = true
}
+
+ /**
+ * Close all tabs.
+ *
+ * @param private Whether to close all of the Private tabs or all of the Normal tabs.
+ * @param isConfirmed: whether the user has confirmed the warning message
+ */
+ private fun closeAllTabs(private: Boolean, isConfirmed: Boolean) {
+ val sessionsToClose = if (private) {
+ ALL_PRIVATE_TABS
+ } else {
+ ALL_NORMAL_TABS
+ }
+
+ if (private && !isConfirmed) {
+ val privateDownloads = browserStore.state.downloads.filter {
+ it.value.private && it.value.isActiveDownload()
+ }
+ if (privateDownloads.isNotEmpty()) {
+ showCancelledDownloadWarning(privateDownloads.size, null, null)
+ return
+ }
+ }
+ dismissTabManagerAndNavigateHome(sessionsToClose)
+ }
}
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/ui/TabManagementFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/ui/TabManagementFragment.kt
@@ -82,10 +82,8 @@ import org.mozilla.fenix.tabstray.TabsTrayStore
import org.mozilla.fenix.tabstray.TabsTrayTelemetryMiddleware
import org.mozilla.fenix.tabstray.binding.SecureTabManagerBinding
import org.mozilla.fenix.tabstray.browser.TabSorter
-import org.mozilla.fenix.tabstray.controller.DefaultNavigationInteractor
import org.mozilla.fenix.tabstray.controller.DefaultTabManagerController
import org.mozilla.fenix.tabstray.controller.DefaultTabManagerInteractor
-import org.mozilla.fenix.tabstray.controller.NavigationInteractor
import org.mozilla.fenix.tabstray.controller.TabManagerController
import org.mozilla.fenix.tabstray.controller.TabManagerInteractor
import org.mozilla.fenix.tabstray.syncedtabs.SyncedTabsIntegration
@@ -105,7 +103,6 @@ class TabManagementFragment : DialogFragment() {
private lateinit var tabManagerInteractor: TabManagerInteractor
private lateinit var tabManagerController: TabManagerController
- private lateinit var navigationInteractor: NavigationInteractor
private lateinit var enablePbmPinLauncher: ActivityResultLauncher<Intent>
@VisibleForTesting
@@ -168,16 +165,8 @@ class TabManagementFragment : DialogFragment() {
)
}
- navigationInteractor =
- DefaultNavigationInteractor(
- browserStore = requireComponents.core.store,
- navController = findNavController(),
- dismissTabManagerAndNavigateHome = ::navigateToHomeAndDeleteSession,
- showCancelledDownloadWarning = ::showCancelledDownloadWarning,
- accountManager = requireComponents.backgroundServices.accountManager,
- )
-
tabManagerController = DefaultTabManagerController(
+ accountManager = requireComponents.backgroundServices.accountManager,
activity = activity,
appStore = requireComponents.appStore,
tabsTrayStore = tabsTrayStore,
@@ -186,7 +175,6 @@ class TabManagementFragment : DialogFragment() {
browsingModeManager = activity.browsingModeManager,
navController = findNavController(),
navigateToHomeAndDeleteSession = ::navigateToHomeAndDeleteSession,
- navigationInteractor = navigationInteractor,
profiler = requireComponents.core.engine.profiler,
tabsUseCases = requireComponents.useCases.tabsUseCases,
fenixBrowserUseCases = requireComponents.useCases.fenixBrowserUseCases,
@@ -337,9 +325,9 @@ class TabManagementFragment : DialogFragment() {
onSaveToCollectionClick = tabManagerInteractor::onAddSelectedTabsToCollectionClicked,
onShareSelectedTabsClick = tabManagerInteractor::onShareSelectedTabs,
- onTabSettingsClick = navigationInteractor::onTabSettingsClicked,
- onRecentlyClosedClick = navigationInteractor::onOpenRecentlyClosedClicked,
- onAccountSettingsClick = navigationInteractor::onAccountSettingsClicked,
+ onTabSettingsClick = tabManagerController::onTabSettingsClicked,
+ onRecentlyClosedClick = tabManagerController::onOpenRecentlyClosedClicked,
+ onAccountSettingsClick = tabManagerController::onAccountSettingsClicked,
onDeleteAllTabsClick = {
if (tabsTrayStore.state.selectedPage == Page.NormalTabs) {
tabsTrayStore.dispatch(TabsTrayAction.CloseAllNormalTabs)
@@ -347,7 +335,7 @@ class TabManagementFragment : DialogFragment() {
tabsTrayStore.dispatch(TabsTrayAction.CloseAllPrivateTabs)
}
- navigationInteractor.onCloseAllTabsClicked(
+ tabManagerController.onCloseAllTabsClicked(
private = tabsTrayStore.state.selectedPage == Page.PrivateTabs,
)
},
@@ -361,7 +349,7 @@ class TabManagementFragment : DialogFragment() {
PrivateBrowsingLocked.bannerNegativeClicked.record()
},
onTabAutoCloseBannerViewOptionsClick = {
- navigationInteractor.onTabSettingsClicked()
+ tabManagerController.onTabSettingsClicked()
requireContext().settings().shouldShowAutoCloseTabsBanner =
false
requireContext().settings().lastCfrShownTimeInMillis =
@@ -387,7 +375,7 @@ class TabManagementFragment : DialogFragment() {
false
requireContext().settings().lastCfrShownTimeInMillis =
System.currentTimeMillis()
- navigationInteractor.onTabSettingsClicked()
+ tabManagerController.onTabSettingsClicked()
TabsTray.inactiveTabsCfrSettings.record(NoExtras())
},
onInactiveTabsCFRDismiss = {
@@ -516,7 +504,7 @@ class TabManagementFragment : DialogFragment() {
if (tabId != null) {
tabManagerInteractor.onDeletePrivateTabWarningAccepted(tabId, source)
} else {
- navigationInteractor.onCloseAllPrivateTabsWarningConfirmed(private = true)
+ tabManagerController.onCloseAllPrivateTabsWarningConfirmed(private = true)
}
}
diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/tabstray/controller/DefaultTabManagerControllerTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/tabstray/controller/DefaultTabManagerControllerTest.kt
@@ -35,12 +35,14 @@ import mozilla.components.concept.storage.BookmarkNodeType
import mozilla.components.concept.storage.BookmarksStorage
import mozilla.components.feature.accounts.push.CloseTabsUseCases
import mozilla.components.feature.tabs.TabsUseCases
+import mozilla.components.service.fxa.manager.FxaAccountManager
import mozilla.components.support.test.ext.joinBlocking
import mozilla.components.support.test.libstate.ext.waitUntilIdle
import mozilla.components.support.test.middleware.CaptureActionsMiddleware
import mozilla.components.support.test.robolectric.testContext
import mozilla.components.support.test.rule.MainCoroutineRule
import mozilla.components.support.test.rule.runTestOnMain
+import mozilla.telemetry.glean.private.NoExtras
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotEquals
@@ -96,9 +98,6 @@ class DefaultTabManagerControllerTest {
private lateinit var profiler: Profiler
@MockK(relaxed = true)
- private lateinit var navigationInteractor: NavigationInteractor
-
- @MockK(relaxed = true)
private lateinit var tabsUseCases: TabsUseCases
@MockK(relaxed = true)
@@ -107,6 +106,9 @@ class DefaultTabManagerControllerTest {
@MockK(relaxed = true)
private lateinit var activity: HomeActivity
+ @MockK(relaxed = true)
+ private lateinit var accountManager: FxaAccountManager
+
private val appStore: AppStore = mockk(relaxed = true)
private val settings: Settings = mockk(relaxed = true)
@@ -143,7 +145,8 @@ class DefaultTabManagerControllerTest {
assertNull(TabsTray.newPrivateTabTapped.testGetValue())
- createController().handlePrivateTabsFabClick()
+ val target = createController()
+ target.handlePrivateTabsFabClick()
assertNotNull(TabsTray.newPrivateTabTapped.testGetValue())
@@ -153,7 +156,7 @@ class DefaultTabManagerControllerTest {
navController.navigate(
TabManagementFragmentDirections.actionGlobalHome(focusOnAddressBar = true),
)
- navigationInteractor.onTabManagerDismissed()
+ TabsTray.closed.record(NoExtras())
profiler.addMarker(
"DefaultTabManagerController.onNewTabTapped",
Double.MAX_VALUE,
@@ -171,7 +174,8 @@ class DefaultTabManagerControllerTest {
assertNull(TabsTray.newPrivateTabTapped.testGetValue())
- createController().handlePrivateTabsFabClick()
+ val target = createController()
+ target.handlePrivateTabsFabClick()
assertNotNull(TabsTray.newPrivateTabTapped.testGetValue())
@@ -180,7 +184,7 @@ class DefaultTabManagerControllerTest {
fenixBrowserUseCases.addNewHomepageTab(
private = true,
)
- navigationInteractor.onTabManagerDismissed()
+ TabsTray.closed.record(NoExtras())
profiler.addMarker(
"DefaultTabManagerController.onNewTabTapped",
Double.MAX_VALUE,
@@ -194,7 +198,8 @@ class DefaultTabManagerControllerTest {
every { getProfilerTime() } returns Double.MAX_VALUE
}
- createController().handleNormalTabsFabClick()
+ val target = createController()
+ target.handleNormalTabsFabClick()
verifyOrder {
profiler.getProfilerTime()
@@ -202,7 +207,7 @@ class DefaultTabManagerControllerTest {
navController.navigate(
TabManagementFragmentDirections.actionGlobalHome(focusOnAddressBar = true),
)
- navigationInteractor.onTabManagerDismissed()
+ TabsTray.closed.record(NoExtras())
profiler.addMarker(
"DefaultTabManagerController.onNewTabTapped",
Double.MAX_VALUE,
@@ -218,14 +223,15 @@ class DefaultTabManagerControllerTest {
every { getProfilerTime() } returns Double.MAX_VALUE
}
- createController().handleNormalTabsFabClick()
+ val target = createController()
+ target.handleNormalTabsFabClick()
verifyOrder {
profiler.getProfilerTime()
fenixBrowserUseCases.addNewHomepageTab(
private = false,
)
- navigationInteractor.onTabManagerDismissed()
+ TabsTray.closed.record(NoExtras())
profiler.addMarker(
"DefaultTabManagerController.onNewTabTapped",
Double.MAX_VALUE,
@@ -1354,6 +1360,158 @@ class DefaultTabManagerControllerTest {
}
}
+ @Test
+ fun `GIVEN logged in state WHEN account settings is clicked THEN navigate to account settings`() {
+ every { accountManager.authenticatedAccount() }.answers { mockk(relaxed = true) }
+
+ createController().onAccountSettingsClicked()
+
+ verify(exactly = 1) { navController.navigate(TabManagementFragmentDirections.actionGlobalAccountSettingsFragment()) }
+ }
+
+ @Test
+ fun `GIVEN logged out state WHEN account settings is clicked THEN navigate to turn on sync`() {
+ every { accountManager.authenticatedAccount() }.answers { null }
+
+ createController().onAccountSettingsClicked()
+
+ verify(exactly = 1) {
+ navController.navigate(
+ TabManagementFragmentDirections.actionGlobalTurnOnSync(
+ entrypoint = FenixFxAEntryPoint.NavigationInteraction,
+ ),
+ )
+ }
+ }
+
+ @Test
+ fun `WHEN tab settings is clicked THEN navigate to global tab settings`() {
+ createController().onTabSettingsClicked()
+ verify(exactly = 1) { navController.navigate(TabManagementFragmentDirections.actionGlobalTabSettingsFragment()) }
+ }
+
+ @Test
+ fun `GIVEN no open recently closed tabs WHEN open recently closed tabs clicked THEN navigate to recently closed tabs`() {
+ assertNull(Events.recentlyClosedTabsOpened.testGetValue())
+
+ createController().onOpenRecentlyClosedClicked()
+
+ verify(exactly = 1) { navController.navigate(TabManagementFragmentDirections.actionGlobalRecentlyClosed()) }
+ assertNotNull(Events.recentlyClosedTabsOpened.testGetValue())
+ }
+
+ @Test
+ fun `GIVEN public tabs and one download in progress WHEN close all tabs clicked THEN dismiss tab manager and navigate to home`() {
+ val tab: TabSessionState = mockk { every { content.private } returns false }
+ every { browserStore.state } returns mockk {
+ every { tabs } returns listOf(tab)
+ }
+ every { browserStore.state.downloads } returns mapOf(
+ "1" to DownloadState(
+ "https://mozilla.org/download",
+ private = false,
+ destinationDirectory = "Download",
+ status = DownloadState.Status.DOWNLOADING,
+ ),
+ )
+
+ val controller = spyk(createController())
+ controller.onCloseAllTabsClicked(private = false)
+
+ verify { controller.dismissTabManagerAndNavigateHome(any()) }
+ }
+
+ @Test
+ fun `GIVEN private tabs and 1 download in progress WHEN close all tabs clicked THEN dismiss tab manager and navigate to home`() {
+ val tab: TabSessionState = mockk { every { content.private } returns true }
+ every { browserStore.state } returns mockk {
+ every { tabs } returns listOf(tab)
+ }
+ every { browserStore.state.downloads } returns mapOf(
+ "1" to DownloadState(
+ "https://mozilla.org/download",
+ private = true,
+ destinationDirectory = "Download",
+ status = DownloadState.Status.DOWNLOADING,
+ ),
+ )
+
+ val controller = spyk(createController())
+ controller.onCloseAllTabsClicked(private = false)
+
+ verify { controller.dismissTabManagerAndNavigateHome(any()) }
+ }
+
+ @Test
+ fun `GIVEN active private download WHEN onCloseAllTabsClicked is called for private tabs THEN showCancelledDownloadWarning is called`() {
+ var showCancelledDownloadWarningInvoked = false
+ val tab: TabSessionState = mockk { every { content.private } returns true }
+ every { browserStore.state } returns mockk {
+ every { tabs } returns listOf(tab)
+ }
+ every { browserStore.state.downloads } returns mapOf(
+ "1" to DownloadState(
+ "https://mozilla.org/download",
+ private = true,
+ destinationDirectory = "Download",
+ status = DownloadState.Status.DOWNLOADING,
+ ),
+ )
+
+ createController(showCancelledDownloadWarning = { _, _, _ -> showCancelledDownloadWarningInvoked = true }).onCloseAllTabsClicked(true)
+
+ assertTrue(showCancelledDownloadWarningInvoked)
+ }
+
+ @Test
+ fun `GIVEN no active private download WHEN onCloseAllTabsClicked is called for private tabs THEN showCancelledDownloadWarning is not called`() {
+ var showCancelledDownloadWarningInvoked = false
+ val tab: TabSessionState = mockk { every { content.private } returns true }
+ every { browserStore.state } returns mockk {
+ every { tabs } returns listOf(tab)
+ }
+ every { browserStore.state.downloads } returns emptyMap()
+
+ createController(showCancelledDownloadWarning = { _, _, _ -> showCancelledDownloadWarningInvoked = true }).onCloseAllTabsClicked(true)
+
+ assertFalse(showCancelledDownloadWarningInvoked)
+ }
+
+ @Test
+ fun `GIVEN no active download WHEN onCloseAllTabsClicked is called for public tabs THEN showCancelledDownloadWarning is not called`() {
+ var showCancelledDownloadWarningInvoked = false
+ val tab: TabSessionState = mockk { every { content.private } returns false }
+ every { browserStore.state } returns mockk {
+ every { tabs } returns listOf(tab)
+ }
+ every { browserStore.state.downloads } returns mapOf(
+ "1" to DownloadState(
+ "https://mozilla.org/download",
+ private = false,
+ destinationDirectory = "Download",
+ status = DownloadState.Status.DOWNLOADING,
+ ),
+ )
+
+ createController(showCancelledDownloadWarning = { _, _, _ -> showCancelledDownloadWarningInvoked = true }).onCloseAllTabsClicked(true)
+
+ assertFalse(showCancelledDownloadWarningInvoked)
+ }
+
+ @Test
+ fun `GIVEN active download WHEN onCloseAllTabsClicked is called for public tabs THEN showCancelledDownloadWarning is not called`() {
+ var showCancelledDownloadWarningInvoked = false
+ val tab: TabSessionState = mockk { every { content.private } returns false }
+ every { browserStore.state } returns mockk {
+ every { tabs } returns listOf(tab)
+ }
+ every { browserStore.state.downloads } returns emptyMap()
+
+ createController(showCancelledDownloadWarning = { _, _, _ -> showCancelledDownloadWarningInvoked = true }).onCloseAllTabsClicked(true)
+
+ assertFalse(showCancelledDownloadWarningInvoked)
+ }
+
private fun makeBookmarkFolder(guid: String) = BookmarkNode(
type = BookmarkNodeType.FOLDER,
parentGuid = BookmarkRoot.Mobile.id,
@@ -1376,6 +1534,7 @@ class DefaultTabManagerControllerTest {
showBookmarkSnackbar: (Int, String?) -> Unit = { _, _ -> },
): DefaultTabManagerController {
return DefaultTabManagerController(
+ accountManager = accountManager,
activity = activity,
appStore = appStore,
tabsTrayStore = trayStore,
@@ -1385,7 +1544,6 @@ class DefaultTabManagerControllerTest {
navController = navController,
navigateToHomeAndDeleteSession = navigateToHomeAndDeleteSession,
profiler = profiler,
- navigationInteractor = navigationInteractor,
tabsUseCases = tabsUseCases,
fenixBrowserUseCases = fenixBrowserUseCases,
bookmarksStorage = bookmarksStorage,
diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/tabstray/controller/NavigationInteractorTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/tabstray/controller/NavigationInteractorTest.kt
@@ -1,157 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.fenix.tabstray.controller
-
-import androidx.navigation.NavController
-import io.mockk.every
-import io.mockk.mockk
-import io.mockk.spyk
-import io.mockk.verify
-import mozilla.components.browser.state.state.BrowserState
-import mozilla.components.browser.state.state.TabSessionState
-import mozilla.components.browser.state.state.content.DownloadState
-import mozilla.components.browser.state.store.BrowserStore
-import mozilla.components.service.fxa.manager.FxaAccountManager
-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.Assert.assertTrue
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.RuleChain
-import org.junit.runner.RunWith
-import org.mozilla.fenix.GleanMetrics.Events
-import org.mozilla.fenix.GleanMetrics.TabsTray
-import org.mozilla.fenix.components.accounts.FenixFxAEntryPoint
-import org.mozilla.fenix.helpers.FenixGleanTestRule
-import org.mozilla.fenix.tabstray.ui.TabManagementFragmentDirections
-import org.robolectric.RobolectricTestRunner
-import mozilla.components.browser.state.state.createTab as createStateTab
-
-@RunWith(RobolectricTestRunner::class) // for gleanTestRule
-class NavigationInteractorTest {
- private lateinit var store: BrowserStore
- private val testTab: TabSessionState = createStateTab(url = "https://mozilla.org")
- private val navController: NavController = mockk(relaxed = true)
- private val accountManager: FxaAccountManager = mockk(relaxed = true)
-
- val coroutinesTestRule: MainCoroutineRule = MainCoroutineRule()
- val gleanTestRule = FenixGleanTestRule(testContext)
-
- @get:Rule
- val chain: RuleChain = RuleChain.outerRule(gleanTestRule).around(coroutinesTestRule)
-
- @Before
- fun setup() {
- store = BrowserStore(initialState = BrowserState(tabs = listOf(testTab)))
- }
-
- @Test
- fun `WHEN the tab manager is dismissed THEN the metric is reported`() {
- assertNull(TabsTray.closed.testGetValue())
-
- createInteractor().onTabManagerDismissed()
-
- assertNotNull(TabsTray.closed.testGetValue())
- }
-
- @Test
- fun `onAccountSettingsClicked calls navigation on DefaultNavigationInteractor`() {
- every { accountManager.authenticatedAccount() }.answers { mockk(relaxed = true) }
-
- createInteractor().onAccountSettingsClicked()
-
- verify(exactly = 1) { navController.navigate(TabManagementFragmentDirections.actionGlobalAccountSettingsFragment()) }
- }
-
- @Test
- fun `onAccountSettingsClicked when not logged in calls navigation to turn on sync`() {
- every { accountManager.authenticatedAccount() }.answers { null }
-
- createInteractor().onAccountSettingsClicked()
-
- verify(exactly = 1) {
- navController.navigate(
- TabManagementFragmentDirections.actionGlobalTurnOnSync(
- entrypoint = FenixFxAEntryPoint.NavigationInteraction,
- ),
- )
- }
- }
-
- @Test
- fun `onTabSettingsClicked calls navigation on DefaultNavigationInteractor`() {
- createInteractor().onTabSettingsClicked()
- verify(exactly = 1) { navController.navigate(TabManagementFragmentDirections.actionGlobalTabSettingsFragment()) }
- }
-
- @Test
- fun `onOpenRecentlyClosedClicked calls navigation on DefaultNavigationInteractor`() {
- assertNull(Events.recentlyClosedTabsOpened.testGetValue())
-
- createInteractor().onOpenRecentlyClosedClicked()
-
- verify(exactly = 1) { navController.navigate(TabManagementFragmentDirections.actionGlobalRecentlyClosed()) }
- assertNotNull(Events.recentlyClosedTabsOpened.testGetValue())
- }
-
- @Test
- fun `onCloseAllTabsClicked calls navigation on DefaultNavigationInteractor`() {
- var dismissTabManagerAndNavigateHomeInvoked = false
- createInteractor(
- dismissTabManagerAndNavigateHome = {
- dismissTabManagerAndNavigateHomeInvoked = true
- },
- ).onCloseAllTabsClicked(false)
-
- assertTrue(dismissTabManagerAndNavigateHomeInvoked)
- }
-
- @Test
- fun `GIVEN active private download WHEN onCloseAllTabsClicked is called for private tabs THEN showCancelledDownloadWarning is called`() {
- var showCancelledDownloadWarningInvoked = false
- val mockedStore: BrowserStore = mockk()
- val controller = spyk(
- createInteractor(
- browserStore = mockedStore,
- showCancelledDownloadWarning = { _, _, _ ->
- showCancelledDownloadWarningInvoked = true
- },
- ),
- )
- val tab: TabSessionState = mockk { every { content.private } returns true }
- every { mockedStore.state } returns mockk {
- every { tabs } returns listOf(tab)
- }
- every { mockedStore.state.downloads } returns mapOf(
- "1" to DownloadState(
- "https://mozilla.org/download",
- private = true,
- destinationDirectory = "Download",
- status = DownloadState.Status.DOWNLOADING,
- ),
- )
-
- controller.onCloseAllTabsClicked(true)
-
- assertTrue(showCancelledDownloadWarningInvoked)
- }
-
- private fun createInteractor(
- browserStore: BrowserStore = store,
- dismissTabManagerAndNavigateHome: (String) -> Unit = { _ -> },
- showCancelledDownloadWarning: (Int, String?, String?) -> Unit = { _, _, _ -> },
- ): NavigationInteractor {
- return DefaultNavigationInteractor(
- browserStore = browserStore,
- navController = navController,
- dismissTabManagerAndNavigateHome = dismissTabManagerAndNavigateHome,
- showCancelledDownloadWarning = showCancelledDownloadWarning,
- accountManager = accountManager,
- )
- }
-}