From cd3b6181b3292f8a96376c843ae1214e52633eb3 Mon Sep 17 00:00:00 2001 From: Jeff Boek Date: Wed, 10 Jun 2020 15:34:26 -0700 Subject: [PATCH] For #10374 - Adds quick contextual menu to tab switcher Co-authored-by: person808 --- .../fenix/browser/BaseBrowserFragment.kt | 27 ++++++++ .../components/toolbar/BrowserInteractor.kt | 4 ++ .../toolbar/BrowserToolbarController.kt | 35 +++++++++- .../components/toolbar/BrowserToolbarView.kt | 1 + .../components/toolbar/TabCounterMenuItem.kt | 6 ++ .../toolbar/TabCounterToolbarButton.kt | 45 ++++++++++++ .../components/toolbar/ToolbarIntegration.kt | 5 +- .../org/mozilla/fenix/home/HomeFragment.kt | 69 +++++++++++++++++++ .../org/mozilla/fenix/tabtray/TabTrayView.kt | 1 + app/src/main/res/navigation/nav_graph.xml | 5 ++ app/src/main/res/values/dimens.xml | 1 + .../toolbar/BrowserInteractorTest.kt | 8 +++ .../DefaultBrowserToolbarControllerTest.kt | 56 +++++++++++++-- 13 files changed, 255 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/components/toolbar/TabCounterMenuItem.kt diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index d4c953759..2aebee3eb 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -96,6 +96,7 @@ import org.mozilla.fenix.ext.settings import org.mozilla.fenix.home.SharedViewModel import org.mozilla.fenix.tabtray.TabTrayDialogFragment import org.mozilla.fenix.theme.ThemeManager +import org.mozilla.fenix.utils.allowUndo import org.mozilla.fenix.wifi.SitePermissionsWifiIntegration import java.lang.ref.WeakReference @@ -218,6 +219,32 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session sharedViewModel = sharedViewModel, onTabCounterClicked = { TabTrayDialogFragment.show(parentFragmentManager) + }, + onCloseTab = { + val snapshot = sessionManager.createSessionSnapshot(it) + val state = snapshot.engineSession?.saveState() + val isSelected = + it.id == context.components.core.store.state.selectedTabId ?: false + + val snackbarMessage = if (snapshot.session.private) { + requireContext().getString(R.string.snackbar_private_tab_closed) + } else { + requireContext().getString(R.string.snackbar_tab_closed) + } + + viewLifecycleOwner.lifecycleScope.allowUndo( + requireView(), + snackbarMessage, + requireContext().getString(R.string.snackbar_deleted_undo), + { + sessionManager.add( + snapshot.session, + isSelected, + engineSessionState = state + ) + }, + operation = { } + ) } ) diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserInteractor.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserInteractor.kt index ab4e93a98..4707a0830 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserInteractor.kt @@ -12,6 +12,10 @@ open class BrowserInteractor( browserToolbarController.handleTabCounterClick() } + override fun onTabCounterMenuItemTapped(item: TabCounterMenuItem) { + browserToolbarController.handleTabCounterItemInteraction(item) + } + override fun onBrowserToolbarPaste(text: String) { browserToolbarController.handleToolbarPaste(text) } diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt index 44c57f6f4..9d36bd094 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt @@ -22,11 +22,13 @@ import mozilla.components.browser.state.selector.findTab import mozilla.components.concept.engine.EngineView import mozilla.components.concept.engine.prompt.ShareData import mozilla.components.support.ktx.kotlin.isUrl +import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.NavGraphDirections import org.mozilla.fenix.R import org.mozilla.fenix.browser.BrowserAnimator import org.mozilla.fenix.browser.BrowserAnimator.Companion.getToolbarNavOptions import org.mozilla.fenix.browser.BrowserFragmentDirections +import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.browser.readermode.ReaderModeController import org.mozilla.fenix.collections.SaveCollectionStep import org.mozilla.fenix.components.FenixSnackbar @@ -37,6 +39,7 @@ import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.getRootView import org.mozilla.fenix.ext.nav import org.mozilla.fenix.ext.navigateSafe +import org.mozilla.fenix.ext.sessionsOfType import org.mozilla.fenix.ext.settings import org.mozilla.fenix.home.SharedViewModel import org.mozilla.fenix.settings.deletebrowsingdata.deleteAndQuit @@ -52,11 +55,12 @@ interface BrowserToolbarController { fun handleToolbarItemInteraction(item: ToolbarMenu.Item) fun handleToolbarClick() fun handleTabCounterClick() + fun handleTabCounterItemInteraction(item: TabCounterMenuItem) fun handleBrowserMenuDismissed(lowPrioHighlightItems: List) fun handleReaderModePressed(enabled: Boolean) } -@Suppress("LargeClass", "TooManyFunctions") +@SuppressWarnings("LargeClass", "TooManyFunctions") class DefaultBrowserToolbarController( private val activity: Activity, private val navController: NavController, @@ -73,7 +77,8 @@ class DefaultBrowserToolbarController( private val tabCollectionStorage: TabCollectionStorage, private val topSiteStorage: TopSiteStorage, private val sharedViewModel: SharedViewModel, - private val onTabCounterClicked: () -> Unit + private val onTabCounterClicked: () -> Unit, + private val onCloseTab: (Session) -> Unit ) : BrowserToolbarController { private val currentSession @@ -133,6 +138,32 @@ class DefaultBrowserToolbarController( } } + override fun handleTabCounterItemInteraction(item: TabCounterMenuItem) { + val tabUseCases = activity.components.useCases.tabsUseCases + when (item) { + is TabCounterMenuItem.CloseTab -> { + activity.components.core.sessionManager.selectedSession?.let { + // When closing the last tab we must show the undo snackbar in the home fragment + if (activity.components.core.sessionManager.sessionsOfType(it.private) + .count() == 1 + ) { + // The tab tray always returns to normal mode so do that here too + (activity as HomeActivity).browsingModeManager.mode = BrowsingMode.Normal + navController.navigate(BrowserFragmentDirections.actionGlobalHome(it.id)) + } else { + onCloseTab.invoke(it) + tabUseCases.removeTab.invoke(it) + } + } + } + is TabCounterMenuItem.NewTab -> { + (activity as HomeActivity).browsingModeManager.mode = + BrowsingMode.fromBoolean(item.isPrivate) + navController.popBackStack(R.id.homeFragment, false) + } + } + } + override fun handleBrowserMenuDismissed(lowPrioHighlightItems: List) { lowPrioHighlightItems.forEach { when (it) { diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt index ed0a4a4e3..130172300 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt @@ -49,6 +49,7 @@ interface BrowserToolbarViewInteractor { fun onBrowserToolbarClicked() fun onBrowserToolbarMenuItemTapped(item: ToolbarMenu.Item) fun onTabCounterClicked() + fun onTabCounterMenuItemTapped(item: TabCounterMenuItem) fun onBrowserMenuDismissed(lowPrioHighlightItems: List) fun onScrolled(offset: Int) fun onReaderModePressed(enabled: Boolean) diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/TabCounterMenuItem.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/TabCounterMenuItem.kt new file mode 100644 index 000000000..89d5c5b99 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/TabCounterMenuItem.kt @@ -0,0 +1,6 @@ +package org.mozilla.fenix.components.toolbar + +sealed class TabCounterMenuItem { + object CloseTab : TabCounterMenuItem() + class NewTab(val isPrivate: Boolean) : TabCounterMenuItem() +} diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/TabCounterToolbarButton.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/TabCounterToolbarButton.kt index 1889a1e27..a9745894c 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/TabCounterToolbarButton.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/TabCounterToolbarButton.kt @@ -4,13 +4,20 @@ package org.mozilla.fenix.components.toolbar +import android.content.Context import android.util.TypedValue import android.view.View import android.view.ViewGroup +import mozilla.components.browser.menu.BrowserMenu +import mozilla.components.browser.menu.BrowserMenuBuilder +import mozilla.components.browser.menu.item.BrowserMenuDivider +import mozilla.components.browser.menu.item.BrowserMenuImageText import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager import mozilla.components.concept.toolbar.Toolbar +import org.mozilla.fenix.R import org.mozilla.fenix.ext.sessionsOfType +import org.mozilla.fenix.theme.ThemeManager import java.lang.ref.WeakReference /** @@ -19,6 +26,7 @@ import java.lang.ref.WeakReference class TabCounterToolbarButton( private val sessionManager: SessionManager, private val isPrivate: Boolean, + private val onItemTapped: (TabCounterMenuItem) -> Unit = {}, private val showTabs: () -> Unit ) : Toolbar.Action { private var reference: WeakReference = WeakReference(null) @@ -32,6 +40,11 @@ class TabCounterToolbarButton( showTabs.invoke() } + setOnLongClickListener { + getTabContextMenu(it.context).show(it) + true + } + addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View?) { setCount(sessionManager.sessionsOfType(private = isPrivate).count()) @@ -62,6 +75,38 @@ class TabCounterToolbarButton( } } + private fun getTabContextMenu(context: Context): BrowserMenu { + val primaryTextColor = ThemeManager.resolveAttribute(R.attr.primaryText, context) + val menuItems = listOf( + BrowserMenuImageText( + label = context.getString(R.string.close_tab), + imageResource = R.drawable.ic_close, + iconTintColorResource = primaryTextColor, + textColorResource = primaryTextColor + ) { + onItemTapped(TabCounterMenuItem.CloseTab) + }, + BrowserMenuDivider(), + BrowserMenuImageText( + label = context.getString(R.string.browser_menu_new_tab), + imageResource = R.drawable.ic_new, + iconTintColorResource = primaryTextColor, + textColorResource = primaryTextColor + ) { + onItemTapped(TabCounterMenuItem.NewTab(false)) + }, + BrowserMenuImageText( + label = context.getString(R.string.home_screen_shortcut_open_new_private_tab_2), + imageResource = R.drawable.ic_private_browsing, + iconTintColorResource = primaryTextColor, + textColorResource = primaryTextColor + ) { + onItemTapped(TabCounterMenuItem.NewTab(true)) + } + ) + return BrowserMenuBuilder(menuItems).build(context) + } + private val sessionManagerObserver = object : SessionManager.Observer { override fun onSessionAdded(session: Session) { updateCount() diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarIntegration.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarIntegration.kt index c8ac9d62a..fa183a89a 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarIntegration.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarIntegration.kt @@ -132,7 +132,10 @@ class DefaultToolbarIntegration( ) } - val tabsAction = TabCounterToolbarButton(sessionManager, isPrivate) { + val onTabCounterMenuItemTapped = { item: TabCounterMenuItem -> + interactor.onTabCounterMenuItemTapped(item) + } + val tabsAction = TabCounterToolbarButton(sessionManager, isPrivate, onTabCounterMenuItemTapped) { toolbar.hideKeyboard() interactor.onTabCounterClicked() } diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 108f44d37..bbb8e53c5 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -36,6 +36,7 @@ import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE @@ -49,6 +50,9 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import mozilla.appservices.places.BookmarkRoot +import mozilla.components.browser.menu.BrowserMenu +import mozilla.components.browser.menu.BrowserMenuBuilder +import mozilla.components.browser.menu.item.BrowserMenuImageText import mozilla.components.browser.menu.view.MenuButton import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager @@ -95,6 +99,7 @@ import org.mozilla.fenix.settings.deletebrowsingdata.deleteAndQuit import org.mozilla.fenix.tabtray.TabTrayDialogFragment import org.mozilla.fenix.theme.ThemeManager import org.mozilla.fenix.utils.FragmentPreDrawManager +import org.mozilla.fenix.utils.allowUndo import org.mozilla.fenix.whatsnew.WhatsNew import java.lang.ref.WeakReference import kotlin.math.abs @@ -106,6 +111,8 @@ class HomeFragment : Fragment() { ViewModelProvider.AndroidViewModelFactory(requireActivity().application) } + private val args by navArgs() + private val snackbarAnchorView: View? get() { return if (requireContext().settings().shouldUseBottomToolbar) { @@ -306,6 +313,10 @@ class HomeFragment : Fragment() { } createHomeMenu(requireContext(), WeakReference(view.menuButton)) + view.tab_button.setOnLongClickListener { + createTabCounterMenu(requireContext()).show(view.tab_button) + true + } view.menuButton.setColorFilter( ContextCompat.getColor( @@ -453,7 +464,40 @@ class HomeFragment : Fragment() { if (browsingModeManager.mode == BrowsingMode.Private) { activity?.window?.setBackgroundDrawableResource(R.drawable.private_home_background_gradient) } + hideToolbar() + + args.sessionToDelete?.also { + sessionManager.findSessionById(it)?.let { session -> + val snapshot = sessionManager.createSessionSnapshot(session) + val state = snapshot.engineSession?.saveState() + val isSelected = + session.id == requireComponents.core.store.state.selectedTabId ?: false + + val snackbarMessage = if (snapshot.session.private) { + requireContext().getString(R.string.snackbar_private_tab_closed) + } else { + requireContext().getString(R.string.snackbar_tab_closed) + } + + viewLifecycleOwner.lifecycleScope.allowUndo( + requireView(), + snackbarMessage, + requireContext().getString(R.string.snackbar_deleted_undo), + { + sessionManager.add( + snapshot.session, + isSelected, + engineSessionState = state + ) + findNavController().navigate(HomeFragmentDirections.actionHomeFragmentToBrowserFragment(null)) + }, + operation = { }, + anchorView = snackbarAnchorView + ) + requireComponents.useCases.tabsUseCases.removeTab.invoke(session) + } + } } override fun onPause() { @@ -545,6 +589,31 @@ class HomeFragment : Fragment() { ) } + private fun createTabCounterMenu(context: Context): BrowserMenu { + val primaryTextColor = ThemeManager.resolveAttribute(R.attr.primaryText, context) + val isPrivate = (activity as HomeActivity).browsingModeManager.mode == BrowsingMode.Private + val menuItems = listOf( + BrowserMenuImageText( + label = context.getString(if (isPrivate) { + R.string.browser_menu_new_tab + } else { + R.string.home_screen_shortcut_open_new_private_tab_2 + }), + imageResource = if (isPrivate) { + R.drawable.ic_new + } else { + R.drawable.ic_private_browsing + }, + iconTintColorResource = primaryTextColor, + textColorResource = primaryTextColor + ) { + (activity as HomeActivity).browsingModeManager.mode = + BrowsingMode.fromBoolean(!isPrivate) + } + ) + return BrowserMenuBuilder(menuItems).build(context) + } + @SuppressWarnings("ComplexMethod", "LongMethod") private fun createHomeMenu(context: Context, menuButtonView: WeakReference) = HomeMenu( diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt index 5f87c3fc2..7eb9f42c9 100644 --- a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt +++ b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt @@ -163,6 +163,7 @@ class TabTrayView( updateState(view.context.components.core.store.state) } + override fun onTabReselected(tab: TabLayout.Tab?) { /*noop*/ } override fun onTabUnselected(tab: TabLayout.Tab?) { /*noop*/ } diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 597223d5e..0e40a8dfc 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -66,6 +66,11 @@ app:destination="@id/browserFragment" app:exitAnim="@anim/zoom_in_fade" app:popEnterAnim="@anim/zoom_out_fade" /> + 5dp 16dp + diff --git a/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserInteractorTest.kt b/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserInteractorTest.kt index dd33672eb..04cab6f8b 100644 --- a/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserInteractorTest.kt +++ b/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserInteractorTest.kt @@ -24,6 +24,14 @@ class BrowserInteractorTest { verify { browserToolbarController.handleTabCounterClick() } } + @Test + fun onTabCounterMenuItemTapped() { + val item: TabCounterMenuItem = mockk() + + interactor.onTabCounterMenuItemTapped(item) + verify { browserToolbarController.handleTabCounterItemInteraction(item) } + } + @Test fun onBrowserToolbarPaste() { val pastedText = "Mozilla" diff --git a/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarControllerTest.kt b/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarControllerTest.kt index c18200998..34086bdb3 100644 --- a/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarControllerTest.kt @@ -36,6 +36,7 @@ import mozilla.components.concept.engine.EngineView import mozilla.components.feature.search.SearchUseCases import mozilla.components.feature.session.SessionUseCases import mozilla.components.feature.tab.collections.TabCollection +import mozilla.components.feature.tabs.TabsUseCases import org.junit.After import org.junit.Assert.assertEquals import org.junit.Before @@ -45,6 +46,9 @@ import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.browser.BrowserAnimator import org.mozilla.fenix.browser.BrowserFragmentDirections +import org.mozilla.fenix.browser.browsingmode.BrowsingMode +import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager +import org.mozilla.fenix.browser.browsingmode.DefaultBrowsingModeManager import org.mozilla.fenix.browser.readermode.ReaderModeController import org.mozilla.fenix.collections.SaveCollectionStep import org.mozilla.fenix.components.Analytics @@ -113,7 +117,8 @@ class DefaultBrowserToolbarControllerTest { readerModeController = readerModeController, sessionManager = mockk(), sharedViewModel = mockk(), - onTabCounterClicked = { } + onTabCounterClicked = { }, + onCloseTab = {} ) mockkStatic( @@ -207,7 +212,8 @@ class DefaultBrowserToolbarControllerTest { readerModeController = mockk(), sessionManager = mockk(), sharedViewModel = mockk(), - onTabCounterClicked = { } + onTabCounterClicked = { }, + onCloseTab = { } ) controller.handleBrowserMenuDismissed(itemList) @@ -371,7 +377,8 @@ class DefaultBrowserToolbarControllerTest { readerModeController = mockk(), sessionManager = mockk(), sharedViewModel = mockk(), - onTabCounterClicked = { } + onTabCounterClicked = { }, + onCloseTab = { } ) controller.ioScope = this @@ -496,7 +503,8 @@ class DefaultBrowserToolbarControllerTest { readerModeController = mockk(), sessionManager = mockk(), sharedViewModel = mockk(), - onTabCounterClicked = { } + onTabCounterClicked = { }, + onCloseTab = { } ) val sessionManager: SessionManager = mockk(relaxed = true) @@ -536,7 +544,8 @@ class DefaultBrowserToolbarControllerTest { readerModeController = mockk(), sessionManager = mockk(), sharedViewModel = mockk(), - onTabCounterClicked = { } + onTabCounterClicked = { }, + onCloseTab = { } ) controller.handleToolbarItemInteraction(item) @@ -556,4 +565,41 @@ class DefaultBrowserToolbarControllerTest { controller.handleToolbarItemInteraction(item) verify { readerModeController.hideReaderView() } } + + @Test + fun handleToolbarCloseTabPress() { + val tabsUseCases: TabsUseCases = mockk(relaxed = true) + val removeTabUseCase: TabsUseCases.RemoveTabUseCase = mockk(relaxed = true) + val item = TabCounterMenuItem.CloseTab + + every { activity.components.useCases.tabsUseCases } returns tabsUseCases + every { tabsUseCases.removeTab } returns removeTabUseCase + + controller.handleTabCounterItemInteraction(item) + verify { removeTabUseCase.invoke(currentSession) } + } + + @Test + fun handleToolbarNewTabPress() { + val browsingModeManager: BrowsingModeManager = DefaultBrowsingModeManager(BrowsingMode.Private) {} + val item = TabCounterMenuItem.NewTab(false) + + every { activity.browsingModeManager } returns browsingModeManager + + controller.handleTabCounterItemInteraction(item) + assertEquals(BrowsingMode.Normal, activity.browsingModeManager.mode) + verify { navController.popBackStack(R.id.homeFragment, false) } + } + + @Test + fun handleToolbarNewPrivateTabPress() { + val browsingModeManager: BrowsingModeManager = DefaultBrowsingModeManager(BrowsingMode.Normal) {} + val item = TabCounterMenuItem.NewTab(true) + + every { activity.browsingModeManager } returns browsingModeManager + + controller.handleTabCounterItemInteraction(item) + assertEquals(BrowsingMode.Private, activity.browsingModeManager.mode) + verify { navController.popBackStack(R.id.homeFragment, false) } + } }