1
0
Fork 0

For #4451: Adds tests for DefaultBrowserToolbarController (#4493)

* For #4451: Adds tests for DefaultBrowserToolbarController

* Continue working

* Large refactoring of test

* Mock analytics

* Fix merge conflicts
master
Sawyer Blatz 2019-08-08 09:02:42 -07:00 committed by GitHub
parent 0ea595743d
commit ff6e9bccb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 364 additions and 25 deletions

View File

@ -18,6 +18,7 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.component_search.*
import kotlinx.android.synthetic.main.fragment_browser.*
@ -46,6 +47,7 @@ import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import mozilla.components.support.ktx.android.view.exitImmersiveModeIfNeeded
import org.mozilla.fenix.FeatureFlags
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.IntentReceiverActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.ThemeManager
import org.mozilla.fenix.collections.CreateCollectionViewModel
@ -65,6 +67,8 @@ import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.enterToImmersiveMode
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.toTab
import org.mozilla.fenix.settings.SupportUtils
import org.mozilla.fenix.utils.Settings
/**
@ -142,7 +146,14 @@ abstract class BaseBrowserFragment : Fragment(), BackHandler {
nestedScrollQuickActionView = nestedScrollQuickAction,
engineView = engineView,
currentSession = session,
viewModel = viewModel
viewModel = viewModel,
getSupportUrl = { SupportUtils.getSumoURLForTopic(context!!, SupportUtils.SumoTopic.HELP) },
openInFenixIntent = Intent(context, IntentReceiverActivity::class.java).also {
it.action = Intent.ACTION_VIEW
it.flags = Intent.FLAG_ACTIVITY_NEW_TASK
},
currentSessionAsTab = session.toTab(context!!),
bottomSheetBehavior = BottomSheetBehavior.from(nestedScrollQuickAction)
)
browserInteractor = createBrowserToolbarViewInteractor(browserToolbarController, session)

View File

@ -19,6 +19,7 @@ import androidx.navigation.fragment.findNavController
import androidx.transition.TransitionInflater
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.component_search.*
import kotlinx.android.synthetic.main.fragment_browser.*
import kotlinx.android.synthetic.main.fragment_browser.view.*
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main

View File

@ -14,7 +14,6 @@ import mozilla.components.browser.session.Session
import mozilla.components.concept.engine.EngineView
import org.mozilla.fenix.BrowsingModeManager
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.IntentReceiverActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.BrowserFragment
import org.mozilla.fenix.browser.BrowserFragmentDirections
@ -23,10 +22,8 @@ import org.mozilla.fenix.collections.getStepForCollectionsSize
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.toTab
import org.mozilla.fenix.home.sessioncontrol.Tab
import org.mozilla.fenix.lib.Do
import org.mozilla.fenix.quickactionsheet.QuickActionSheetBehavior
import org.mozilla.fenix.settings.SupportUtils
/**
* An interface that handles the view manipulation of the BrowserToolbar, triggered by the Interactor
@ -43,7 +40,11 @@ class DefaultBrowserToolbarController(
private val nestedScrollQuickActionView: NestedScrollView,
private val engineView: EngineView,
private val currentSession: Session,
private val viewModel: CreateCollectionViewModel
private val viewModel: CreateCollectionViewModel,
private val getSupportUrl: () -> String,
private val openInFenixIntent: Intent,
private val currentSessionAsTab: Tab,
private val bottomSheetBehavior: BottomSheetBehavior<NestedScrollView>
) : BrowserToolbarController {
override fun handleToolbarClick() {
@ -93,9 +94,7 @@ class DefaultBrowserToolbarController(
(context as HomeActivity).browsingModeManager.mode = BrowsingModeManager.Mode.Private
}
ToolbarMenu.Item.FindInPage -> {
(BottomSheetBehavior.from(nestedScrollQuickActionView) as QuickActionSheetBehavior).apply {
state = BottomSheetBehavior.STATE_COLLAPSED
}
bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
findInPageLauncher()
context.components.analytics.metrics.track(Event.FindInPageOpened)
}
@ -106,12 +105,7 @@ class DefaultBrowserToolbarController(
}
}
ToolbarMenu.Item.Help -> {
context.components.useCases.tabsUseCases.addTab.invoke(
SupportUtils.getSumoURLForTopic(
context,
SupportUtils.SumoTopic.HELP
)
)
context.components.useCases.tabsUseCases.addTab.invoke(getSupportUrl())
}
ToolbarMenu.Item.NewTab -> {
val directions = BrowserFragmentDirections
@ -123,10 +117,9 @@ class DefaultBrowserToolbarController(
ToolbarMenu.Item.SaveToCollection -> {
context.components.analytics.metrics
.track(Event.CollectionSaveButtonPressed(TELEMETRY_BROWSER_IDENTIFIER))
currentSession.let {
val tab = it.toTab(context)
viewModel.tabs = listOf(tab)
val selectedSet = mutableSetOf(tab)
viewModel.tabs = listOf(currentSessionAsTab)
val selectedSet = mutableSetOf(currentSessionAsTab)
viewModel.selectedTabs = selectedSet
viewModel.tabCollections =
context.components.core.tabCollectionStorage.cachedTabCollections.reversed()
@ -136,7 +129,6 @@ class DefaultBrowserToolbarController(
val directions = BrowserFragmentDirections.actionBrowserFragmentToCreateCollectionFragment()
navController.nav(R.id.browserFragment, directions)
}
}
ToolbarMenu.Item.OpenInFenix -> {
// Release the session from this view so that it can immediately be rendered by a different view
@ -147,10 +139,7 @@ class DefaultBrowserToolbarController(
context.components.core.sessionManager.select(currentSession)
// Switch to the actual browser which should now display our new selected session
context.startActivity(Intent(context, IntentReceiverActivity::class.java).also {
it.action = Intent.ACTION_VIEW
it.flags = Intent.FLAG_ACTIVITY_NEW_TASK
})
context.startActivity(openInFenixIntent)
// Close this activity since it is no longer displaying any session
(context as Activity).finish()
@ -188,6 +177,6 @@ class DefaultBrowserToolbarController(
}
companion object {
private const val TELEMETRY_BROWSER_IDENTIFIER = "browserMenu"
internal const val TELEMETRY_BROWSER_IDENTIFIER = "browserMenu"
}
}

View File

@ -0,0 +1,338 @@
/* 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.components.toolbar
import android.content.Intent
import androidx.core.widget.NestedScrollView
import androidx.navigation.NavController
import com.google.android.material.bottomsheet.BottomSheetBehavior
import io.mockk.Runs
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.verify
import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager
import mozilla.components.concept.engine.EngineView
import mozilla.components.feature.session.SessionUseCases
import mozilla.components.feature.tabs.TabsUseCases
import org.junit.Before
import org.junit.Test
import org.mozilla.fenix.BrowsingModeManager
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.BrowserFragment
import org.mozilla.fenix.browser.BrowserFragmentDirections
import org.mozilla.fenix.collections.CreateCollectionViewModel
import org.mozilla.fenix.collections.SaveCollectionStep
import org.mozilla.fenix.components.Analytics
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.metrics
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.home.sessioncontrol.Tab
import org.mozilla.fenix.home.sessioncontrol.TabCollection
class DefaultBrowserToolbarControllerTest {
private var context: HomeActivity = mockk(relaxed = true)
private var analytics: Analytics = mockk(relaxed = true)
private var navController: NavController = mockk(relaxed = true)
private var findInPageLauncher: () -> Unit = mockk(relaxed = true)
private val nestedScrollQuickActionView: NestedScrollView = mockk(relaxed = true)
private val engineView: EngineView = mockk(relaxed = true)
private val currentSession: Session = mockk(relaxed = true)
private val viewModel: CreateCollectionViewModel = mockk(relaxed = true)
private val getSupportUrl: () -> String = { "https://supportUrl.org" }
private val openInFenixIntent: Intent = mockk(relaxed = true)
private val currentSessionAsTab: Tab = mockk(relaxed = true)
private val bottomSheetBehavior: BottomSheetBehavior<NestedScrollView> = mockk(relaxed = true)
private val metrics: MetricController = mockk(relaxed = true)
private val sessionUseCases: SessionUseCases = mockk(relaxed = true)
private lateinit var controller: DefaultBrowserToolbarController
@Before
fun setUp() {
controller = DefaultBrowserToolbarController(
context = context,
navController = navController,
findInPageLauncher = findInPageLauncher,
nestedScrollQuickActionView = nestedScrollQuickActionView,
engineView = engineView,
currentSession = currentSession,
viewModel = viewModel,
getSupportUrl = getSupportUrl,
openInFenixIntent = openInFenixIntent,
currentSessionAsTab = currentSessionAsTab,
bottomSheetBehavior = bottomSheetBehavior
)
every { context.components.analytics } returns analytics
every { analytics.metrics } returns metrics
every { context.components.useCases.sessionUseCases } returns sessionUseCases
}
@Test
fun handleToolbarClick() {
every { currentSession.id } returns "1"
controller.handleToolbarClick()
verify { metrics.track(Event.SearchBarTapped(Event.SearchBarTapped.Source.BROWSER)) }
verify { navController.nav(
R.id.browserFragment,
BrowserFragmentDirections.actionBrowserFragmentToSearchFragment(currentSession.id)
) }
}
@Test
fun handleToolbarBackPress() {
val item = ToolbarMenu.Item.Back
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.BACK)) }
verify { sessionUseCases.goBack }
}
@Test
fun handleToolbarForwardPress() {
val item = ToolbarMenu.Item.Forward
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.FORWARD)) }
verify { sessionUseCases.goForward }
}
@Test
fun handleToolbarReloadPress() {
val item = ToolbarMenu.Item.Reload
every { context.components.useCases.sessionUseCases } returns sessionUseCases
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.RELOAD)) }
verify { sessionUseCases.reload }
}
@Test
fun handleToolbarStopPress() {
val item = ToolbarMenu.Item.Stop
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.STOP)) }
verify { sessionUseCases.stopLoading }
}
@Test
fun handleToolbarSettingsPress() {
val item = ToolbarMenu.Item.Settings
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.SETTINGS)) }
verify { navController.nav(
R.id.settingsFragment,
BrowserFragmentDirections.actionBrowserFragmentToSettingsFragment()
) }
}
@Test
fun handleToolbarLibraryPress() {
val item = ToolbarMenu.Item.Library
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.LIBRARY)) }
verify { navController.nav(
R.id.libraryFragment,
BrowserFragmentDirections.actionBrowserFragmentToSettingsFragment()
) }
}
@Test
fun handleToolbarRequestDesktopOnPress() {
val requestDesktopSiteUseCase: SessionUseCases.RequestDesktopSiteUseCase = mockk(relaxed = true)
val item = ToolbarMenu.Item.RequestDesktop(true)
every { sessionUseCases.requestDesktopSite } returns requestDesktopSiteUseCase
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.DESKTOP_VIEW_ON)) }
verify {
requestDesktopSiteUseCase.invoke(
true,
currentSession
)
}
}
@Test
fun handleToolbarRequestDesktopOffPress() {
val requestDesktopSiteUseCase: SessionUseCases.RequestDesktopSiteUseCase = mockk(relaxed = true)
val item = ToolbarMenu.Item.RequestDesktop(false)
every { sessionUseCases.requestDesktopSite } returns requestDesktopSiteUseCase
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.DESKTOP_VIEW_OFF)) }
verify {
requestDesktopSiteUseCase.invoke(
false,
currentSession
)
}
}
@Test
fun handleToolbarSharePress() {
val item = ToolbarMenu.Item.Share
every { currentSession.url } returns "https://mozilla.org"
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.SHARE)) }
verify {
val directions = BrowserFragmentDirections.actionBrowserFragmentToShareFragment(currentSession.url)
navController.nav(R.id.browserFragment, directions)
}
}
@Test
fun handleToolbarNewPrivateTabPress() {
val browsingModeManager: BrowsingModeManager = mockk(relaxed = true)
val item = ToolbarMenu.Item.NewPrivateTab
every { context.browsingModeManager } returns browsingModeManager
every { browsingModeManager.mode } returns BrowsingModeManager.Mode.Normal
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.NEW_PRIVATE_TAB)) }
verify {
val directions = BrowserFragmentDirections
.actionBrowserFragmentToSearchFragment(null)
navController.nav(R.id.browserFragment, directions)
}
verify { browsingModeManager.mode = BrowsingModeManager.Mode.Private }
}
@Test
fun handleToolbarFindInPagePress() {
val item = ToolbarMenu.Item.FindInPage
controller.handleToolbarItemInteraction(item)
verify { bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED }
verify { findInPageLauncher() }
verify { metrics.track(Event.FindInPageOpened) }
}
@Test
fun handleToolbarReportIssuePress() {
val tabsUseCases: TabsUseCases = mockk(relaxed = true)
val addTabUseCase: TabsUseCases.AddNewTabUseCase = mockk(relaxed = true)
val item = ToolbarMenu.Item.ReportIssue
every { currentSession.url } returns "https://mozilla.org"
every { context.components.useCases.tabsUseCases } returns tabsUseCases
every { tabsUseCases.addTab } returns addTabUseCase
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.REPORT_SITE_ISSUE)) }
verify {
// Hardcoded URL because this function modifies the URL with an apply
addTabUseCase.invoke(String.format(BrowserFragment.REPORT_SITE_ISSUE_URL, "https://mozilla.org"))
}
}
@Test
fun handleToolbarHelpPress() {
val tabsUseCases: TabsUseCases = mockk(relaxed = true)
val addTabUseCase: TabsUseCases.AddNewTabUseCase = mockk(relaxed = true)
val item = ToolbarMenu.Item.Help
every { context.components.useCases.tabsUseCases } returns tabsUseCases
every { tabsUseCases.addTab } returns addTabUseCase
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.HELP)) }
verify {
addTabUseCase.invoke(getSupportUrl())
}
}
@Test
fun handleToolbarNewTabPress() {
val browsingModeManager: BrowsingModeManager = mockk(relaxed = true)
val item = ToolbarMenu.Item.NewTab
every { context.browsingModeManager } returns browsingModeManager
every { browsingModeManager.mode } returns BrowsingModeManager.Mode.Private
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.NEW_TAB)) }
verify {
val directions = BrowserFragmentDirections
.actionBrowserFragmentToSearchFragment(null)
navController.nav(R.id.browserFragment, directions)
}
verify { browsingModeManager.mode = BrowsingModeManager.Mode.Normal }
}
@Test
fun handleToolbarSaveToCollectionPress() {
val item = ToolbarMenu.Item.SaveToCollection
val cachedTabCollections: List<TabCollection> = mockk(relaxed = true)
every { context.components.useCases.sessionUseCases } returns sessionUseCases
every { context.components.core.tabCollectionStorage.cachedTabCollections } returns cachedTabCollections
controller.handleToolbarItemInteraction(item)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.SAVE_TO_COLLECTION)) }
verify { metrics.track(Event.CollectionSaveButtonPressed(DefaultBrowserToolbarController.TELEMETRY_BROWSER_IDENTIFIER)) }
verify { viewModel.tabs = listOf(currentSessionAsTab) }
verify { viewModel.selectedTabs = mutableSetOf(currentSessionAsTab) }
verify { viewModel.tabCollections = cachedTabCollections.reversed() }
verify { viewModel.saveCollectionStep = SaveCollectionStep.SelectCollection }
verify { viewModel.snackbarAnchorView = nestedScrollQuickActionView }
verify { viewModel.previousFragmentId = R.id.browserFragment }
verify {
val directions = BrowserFragmentDirections
.actionBrowserFragmentToSearchFragment(null)
navController.nav(R.id.browserFragment, directions)
}
}
@Test
fun handleToolbarOpenInFenixPress() {
val sessionManager: SessionManager = mockk(relaxed = true)
val item = ToolbarMenu.Item.OpenInFenix
every { context.components.core.sessionManager } returns sessionManager
every { currentSession.customTabConfig } returns mockk()
every { context.startActivity(any()) } just Runs
controller.handleToolbarItemInteraction(item)
verify { engineView.release() }
verify { currentSession.customTabConfig = null }
verify { sessionManager.select(currentSession) }
verify { context.startActivity(openInFenixIntent) }
verify { context.finish() }
}
}