For #10686 - Use the AC custom behavior for both the top and bottom toolbars

This comes to unify the experience (with improvements but also specific issues)
for the url toolbar irrespective of it being placed at the bottom or at the top
Going further this will ease development and ensure the best UX for users.
upstream-sync
Mugurell 3 years ago committed by Sebastian Kaspari
parent a3d401a3b7
commit 8bf1cae2ca

@ -70,7 +70,6 @@ import mozilla.components.feature.session.FullScreenFeature
import mozilla.components.feature.session.PictureInPictureFeature
import mozilla.components.feature.session.SessionFeature
import mozilla.components.feature.session.SwipeRefreshFeature
import mozilla.components.feature.session.behavior.EngineViewBottomBehavior
import mozilla.components.feature.sitepermissions.SitePermissions
import mozilla.components.feature.sitepermissions.SitePermissionsFeature
import mozilla.components.lib.state.ext.consumeFlow
@ -103,9 +102,7 @@ import org.mozilla.fenix.components.toolbar.BrowserToolbarView
import org.mozilla.fenix.components.toolbar.BrowserToolbarViewInteractor
import org.mozilla.fenix.components.toolbar.DefaultBrowserToolbarController
import org.mozilla.fenix.components.toolbar.DefaultBrowserToolbarMenuController
import org.mozilla.fenix.components.toolbar.SwipeRefreshScrollingViewBehavior
import org.mozilla.fenix.components.toolbar.ToolbarIntegration
import org.mozilla.fenix.components.toolbar.ToolbarPosition
import org.mozilla.fenix.downloads.DownloadService
import org.mozilla.fenix.downloads.DynamicDownloadDialog
import org.mozilla.fenix.ext.accessibilityManager
@ -128,9 +125,11 @@ import org.mozilla.fenix.utils.allowUndo
import org.mozilla.fenix.wifi.SitePermissionsWifiIntegration
import java.lang.ref.WeakReference
import mozilla.components.feature.media.fullscreen.MediaFullscreenOrientationFeature
import mozilla.components.feature.session.behavior.EngineViewBrowserToolbarBehavior
import mozilla.components.feature.webauthn.WebAuthnFeature
import mozilla.components.support.base.feature.ActivityResultHandler
import org.mozilla.fenix.FeatureFlags.newMediaSessionApi
import mozilla.components.feature.session.behavior.ToolbarPosition as MozacToolbarPosition
/**
* Base fragment extended by [BrowserFragment].
@ -838,34 +837,42 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
!inFullScreen
}
private fun initializeEngineView(toolbarHeight: Int) {
@VisibleForTesting
internal fun initializeEngineView(toolbarHeight: Int) {
val context = requireContext()
if (context.settings().isDynamicToolbarEnabled) {
engineView.setDynamicToolbarMaxHeight(toolbarHeight)
// If there is an a11y service enabled and the user hasn't explicitly set bottom toolbar
val isTopToolbarForced =
!context.settings().shouldUseBottomToolbar &&
context.settings().shouldUseFixedTopToolbar
if (!isTopToolbarForced && context.settings().isDynamicToolbarEnabled) {
getEngineView().setDynamicToolbarMaxHeight(toolbarHeight)
val behavior = when (context.settings().toolbarPosition) {
// Set engineView dynamic vertical clipping depending on the toolbar position.
ToolbarPosition.BOTTOM -> EngineViewBottomBehavior(context, null)
// Set scroll flags depending on if if the browser or the website is doing the scroll.
ToolbarPosition.TOP -> SwipeRefreshScrollingViewBehavior(
val toolbarPosition = if (context.settings().shouldUseBottomToolbar) {
MozacToolbarPosition.BOTTOM
} else {
MozacToolbarPosition.TOP
}
(getSwipeRefreshLayout().layoutParams as CoordinatorLayout.LayoutParams).behavior =
EngineViewBrowserToolbarBehavior(
context,
null,
engineView,
browserToolbarView
getSwipeRefreshLayout(),
toolbarHeight,
toolbarPosition
)
}
(swipeRefresh.layoutParams as CoordinatorLayout.LayoutParams).behavior = behavior
} else {
// Ensure webpage's bottom elements are aligned to the very bottom of the engineView.
engineView.setDynamicToolbarMaxHeight(0)
getEngineView().setDynamicToolbarMaxHeight(0)
// Effectively place the engineView on top of the toolbar if that is not dynamic.
// Effectively place the engineView on top/below of the toolbar if that is not dynamic.
val swipeRefreshParams =
getSwipeRefreshLayout().layoutParams as CoordinatorLayout.LayoutParams
if (context.settings().shouldUseBottomToolbar) {
val browserEngine = swipeRefresh.layoutParams as CoordinatorLayout.LayoutParams
browserEngine.bottomMargin =
requireContext().resources.getDimensionPixelSize(R.dimen.browser_toolbar_height)
swipeRefreshParams.bottomMargin = toolbarHeight
} else {
swipeRefreshParams.topMargin = toolbarHeight
}
}
}
@ -1251,6 +1258,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
browserToolbarView.view.isVisible = false
val browserEngine = swipeRefresh.layoutParams as CoordinatorLayout.LayoutParams
browserEngine.bottomMargin = 0
browserEngine.topMargin = 0
swipeRefresh.translationY = 0f
engineView.setDynamicToolbarMaxHeight(0)
browserToolbarView.expand()
@ -1330,7 +1339,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
override fun onAccessibilityStateChanged(enabled: Boolean) {
if (_browserToolbarView != null) {
browserToolbarView.setScrollFlags(enabled)
browserToolbarView.setToolbarBehavior(enabled)
}
}
@ -1352,4 +1361,16 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
}
}
}
/**
* Convenience method for replacing EngineView (id/engineView) in unit tests.
*/
@VisibleForTesting
internal fun getEngineView() = engineView
/**
* Convenience method for replacing SwipeRefreshLayout (id/swipeRefresh) in unit tests.
*/
@VisibleForTesting
internal fun getSwipeRefreshLayout() = swipeRefresh
}

@ -9,25 +9,18 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.annotation.VisibleForTesting
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.LifecycleOwner
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP
import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.component_browser_top_toolbar.*
import kotlinx.android.synthetic.main.component_browser_top_toolbar.view.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.browser.domains.autocomplete.ShippedDomainsProvider
import mozilla.components.browser.session.Session
import mozilla.components.browser.state.selector.selectedTab
import mozilla.components.browser.state.state.ExternalAppType
import mozilla.components.browser.toolbar.BrowserToolbar
import mozilla.components.browser.toolbar.behavior.BrowserToolbarBottomBehavior
import mozilla.components.browser.toolbar.behavior.BrowserToolbarBehavior
import mozilla.components.browser.toolbar.display.DisplayToolbar
import mozilla.components.support.utils.URLStringUtils
import mozilla.components.ui.tabcounter.TabCounterMenu
@ -40,6 +33,7 @@ import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.theme.ThemeManager
import org.mozilla.fenix.utils.ToolbarPopupWindow
import java.lang.ref.WeakReference
import mozilla.components.browser.toolbar.behavior.ToolbarPosition as MozacToolbarPosition
interface BrowserToolbarViewInteractor {
fun onBrowserToolbarPaste(text: String)
@ -76,12 +70,14 @@ class BrowserToolbarView(
private val layout = LayoutInflater.from(container.context)
.inflate(toolbarLayout, container, true)
val view: BrowserToolbar = layout
@VisibleForTesting
internal var view: BrowserToolbar = layout
.findViewById(R.id.toolbar)
val toolbarIntegration: ToolbarIntegration
private val isPwaTabOrTwaTab: Boolean
@VisibleForTesting
internal val isPwaTabOrTwaTab: Boolean
get() = customTabSession?.customTabConfig?.externalAppType == ExternalAppType.PROGRESSIVE_WEB_APP ||
customTabSession?.customTabConfig?.externalAppType == ExternalAppType.TRUSTED_WEB_ACTIVITY
@ -101,17 +97,8 @@ class BrowserToolbarView(
with(container.context) {
val isPinningSupported = components.useCases.webAppUseCases.isPinningSupported()
if (toolbarPosition == ToolbarPosition.TOP) {
val offsetChangedListener =
AppBarLayout.OnOffsetChangedListener { _: AppBarLayout?, verticalOffset: Int ->
interactor.onScrolled(verticalOffset)
}
app_bar.addOnOffsetChangedListener(offsetChangedListener)
}
view.apply {
setScrollFlags()
setToolbarBehavior()
elevation = resources.getDimension(R.dimen.browser_fragment_toolbar_elevation)
@ -222,16 +209,9 @@ class BrowserToolbarView(
if (isPwaTabOrTwaTab) {
return
}
when (settings.toolbarPosition) {
ToolbarPosition.BOTTOM -> {
(view.layoutParams as? CoordinatorLayout.LayoutParams)?.apply {
// behavior can be null if the "Scroll to hide toolbar" setting is toggled off.
(behavior as? BrowserToolbarBottomBehavior)?.forceExpand(view)
}
}
ToolbarPosition.TOP -> {
layout.app_bar?.setExpanded(true)
}
(view.layoutParams as? CoordinatorLayout.LayoutParams)?.apply {
(behavior as? BrowserToolbarBehavior)?.forceExpand(view)
}
}
@ -240,41 +220,54 @@ class BrowserToolbarView(
}
/**
* Dynamically sets scroll flags for the toolbar when the user does not have a screen reader enabled
* Note that the toolbar will have the flags set and be able to be hidden
* only if the user didn't disabled this behavior in app's settings.
* Sets whether the toolbar will have a dynamic behavior (to be scrolled) or not.
*
* This will intrinsically check and disable the dynamic behavior if
* - this is disabled in app settings
* - toolbar is placed at the bottom and tab shows a PWA or TWA
*
* Also if the user has not explicitly set a toolbar position and has a screen reader enabled
* the toolbar will be placed at the top and in a fixed position.
*
* @param shouldDisableScroll force disable of the dynamic behavior irrespective of the intrinsic checks.
*/
fun setScrollFlags(shouldDisableScroll: Boolean = false) {
fun setToolbarBehavior(shouldDisableScroll: Boolean = false) {
when (settings.toolbarPosition) {
ToolbarPosition.BOTTOM -> {
if (settings.isDynamicToolbarEnabled && !isPwaTabOrTwaTab) {
(view.layoutParams as? CoordinatorLayout.LayoutParams)?.apply {
behavior = BrowserToolbarBottomBehavior(view.context, null)
}
setDynamicToolbarBehavior(MozacToolbarPosition.BOTTOM)
} else {
expand()
expandToolbarAndMakeItFixed()
}
}
ToolbarPosition.TOP -> {
view.updateLayoutParams<AppBarLayout.LayoutParams> {
scrollFlags =
if (settings.shouldUseFixedTopToolbar ||
!settings.isDynamicToolbarEnabled ||
shouldDisableScroll) {
// Force expand the toolbar so the user is not stuck with a hidden toolbar
expand()
0
} else {
SCROLL_FLAG_SCROLL or
SCROLL_FLAG_ENTER_ALWAYS or
SCROLL_FLAG_SNAP or
SCROLL_FLAG_EXIT_UNTIL_COLLAPSED
}
if (settings.shouldUseFixedTopToolbar ||
!settings.isDynamicToolbarEnabled ||
shouldDisableScroll
) {
expandToolbarAndMakeItFixed()
} else {
setDynamicToolbarBehavior(MozacToolbarPosition.TOP)
}
}
}
}
@VisibleForTesting
internal fun expandToolbarAndMakeItFixed() {
expand()
(view.layoutParams as? CoordinatorLayout.LayoutParams)?.apply {
behavior = null
}
}
@VisibleForTesting
internal fun setDynamicToolbarBehavior(toolbarPosition: MozacToolbarPosition) {
(view.layoutParams as? CoordinatorLayout.LayoutParams)?.apply {
behavior = BrowserToolbarBehavior(view.context, null, toolbarPosition)
}
}
@Suppress("ComplexCondition")
private fun ToolbarMenu.Item.performHapticIfNeeded(view: View) {
if (this is ToolbarMenu.Item.Reload && this.bypassCache ||

@ -1,50 +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.components.toolbar
import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.google.android.material.appbar.AppBarLayout
import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.concept.engine.EngineView
import mozilla.components.concept.engine.EngineView.InputResult.INPUT_RESULT_UNHANDLED
import org.mozilla.fenix.ext.settings
/**
* ScrollingViewBehavior that will setScrollFlags on BrowserToolbar based on EngineView touch handling
*/
@ExperimentalCoroutinesApi
class SwipeRefreshScrollingViewBehavior(
context: Context,
attrs: AttributeSet?,
private val engineView: EngineView,
private val browserToolbarView: BrowserToolbarView
) : AppBarLayout.ScrollingViewBehavior(context, attrs) {
override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: View,
directTargetChild: View,
target: View,
axes: Int,
type: Int
): Boolean {
if (!browserToolbarView.view.context.settings().shouldUseBottomToolbar) {
val shouldDisable = engineView.getInputResult() == INPUT_RESULT_UNHANDLED
browserToolbarView.setScrollFlags(shouldDisable)
}
return super.onStartNestedScroll(
coordinatorLayout,
child,
directTargetChild,
target,
axes,
type
)
}
}

@ -2,12 +2,9 @@
<!-- 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/. -->
<com.google.android.material.appbar.AppBarLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<mozilla.components.browser.toolbar.BrowserToolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
@ -17,13 +14,10 @@
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
app:layout_scrollFlags="scroll|enterAlways|snap|exitUntilCollapsed"
app:browserToolbarClearColor="?primaryText"
app:browserToolbarInsecureColor="?primaryText"
app:browserToolbarMenuColor="?primaryText"
app:browserToolbarProgressBarGravity="bottom"
app:browserToolbarSecureColor="?primaryText"
app:browserToolbarTrackingProtectionAndSecurityIndicatorSeparatorColor="?toolbarDivider" />
</com.google.android.material.appbar.AppBarLayout>
<!-- NOTE: Scroll flags set dynamically with `setScrollFlagsForTopToolbar` -->

@ -25,8 +25,7 @@
<mozilla.components.ui.widgets.VerticalSwipeRefreshLayout
android:id="@+id/swipeRefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
android:layout_height="match_parent">
<mozilla.components.concept.engine.EngineView
tools:ignore="Instantiatable"

@ -0,0 +1,133 @@
/* 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.browser
import android.content.Context
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import io.mockk.every
import io.mockk.mockk
import io.mockk.slot
import io.mockk.spyk
import io.mockk.verify
import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.browser.state.state.SessionState
import mozilla.components.concept.engine.EngineView
import mozilla.components.feature.contextmenu.ContextMenuCandidate
import mozilla.components.feature.session.behavior.EngineViewBrowserToolbarBehavior
import mozilla.components.feature.sitepermissions.SitePermissions
import mozilla.components.support.test.robolectric.testContext
import mozilla.components.ui.widgets.VerticalSwipeRefreshLayout
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
@ExperimentalCoroutinesApi
@RunWith(FenixRobolectricTestRunner::class)
class BaseBrowserFragmentTest {
private lateinit var fragment: TestBaseBrowserFragment
private lateinit var swipeRefreshLayout: VerticalSwipeRefreshLayout
private lateinit var engineView: EngineView
@Before
fun setup() {
fragment = spyk(TestBaseBrowserFragment())
swipeRefreshLayout = mockk(relaxed = true)
engineView = mockk(relaxed = true)
every { fragment.isAdded } returns true
every { fragment.activity } returns mockk()
every { fragment.requireContext() } returns testContext
every { fragment.getEngineView() } returns engineView
every { fragment.getSwipeRefreshLayout() } returns swipeRefreshLayout
every { swipeRefreshLayout.layoutParams } returns mockk<CoordinatorLayout.LayoutParams>(relaxed = true)
}
@Test
fun `initializeEngineView should setDynamicToolbarMaxHeight to 0 if top toolbar is forced for a11y`() {
every { testContext.settings().shouldUseBottomToolbar } returns false
every { testContext.settings().shouldUseFixedTopToolbar } returns true
fragment.initializeEngineView(13)
verify { engineView.setDynamicToolbarMaxHeight(0) }
}
@Test
fun `initializeEngineView should setDynamicToolbarMaxHeight to toolbar height if dynamic toolbar is enabled`() {
every { testContext.settings().shouldUseFixedTopToolbar } returns false
every { testContext.settings().isDynamicToolbarEnabled } returns true
fragment.initializeEngineView(13)
verify { engineView.setDynamicToolbarMaxHeight(13) }
}
@Test
fun `initializeEngineView should setDynamicToolbarMaxHeight to 0 if dynamic toolbar is disabled`() {
every { testContext.settings().shouldUseFixedTopToolbar } returns false
every { testContext.settings().isDynamicToolbarEnabled } returns false
fragment.initializeEngineView(13)
verify { engineView.setDynamicToolbarMaxHeight(0) }
}
@Test
fun `initializeEngineView should set EngineViewBrowserToolbarBehavior when dynamic toolbar is enabled`() {
every { testContext.settings().shouldUseFixedTopToolbar } returns false
every { testContext.settings().isDynamicToolbarEnabled } returns true
val params: CoordinatorLayout.LayoutParams = mockk(relaxed = true)
every { params.behavior } returns mockk(relaxed = true)
every { swipeRefreshLayout.layoutParams } returns params
val behavior = slot<EngineViewBrowserToolbarBehavior>()
fragment.initializeEngineView(13)
// EngineViewBrowserToolbarBehavior constructor parameters are not properties, we cannot check them.
// Ensure just that the right behavior is set.
verify { params.behavior = capture(behavior) }
}
@Test
fun `initializeEngineView should set toolbar height as EngineView parent's bottom margin when using bottom toolbar`() {
every { testContext.settings().isDynamicToolbarEnabled } returns false
every { testContext.settings().shouldUseBottomToolbar } returns true
fragment.initializeEngineView(13)
verify { (swipeRefreshLayout.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = 13 }
}
@Test
fun `initializeEngineView should set toolbar height as EngineView parent's bottom margin if top toolbar is forced for a11y`() {
every { testContext.settings().shouldUseBottomToolbar } returns false
every { testContext.settings().shouldUseFixedTopToolbar } returns true
fragment.initializeEngineView(13)
verify { (swipeRefreshLayout.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = 13 }
}
}
@ExperimentalCoroutinesApi
private class TestBaseBrowserFragment : BaseBrowserFragment() {
override fun getContextMenuCandidates(
context: Context,
view: View
): List<ContextMenuCandidate> {
// no-op
return emptyList()
}
override fun navToQuickSettingsSheet(tab: SessionState, sitePermissions: SitePermissions?) {
// no-op
}
override fun navToTrackingProtectionPanel(tab: SessionState) {
// no-op
}
}

@ -0,0 +1,196 @@
/* 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 androidx.coordinatorlayout.widget.CoordinatorLayout
import io.mockk.every
import io.mockk.mockk
import io.mockk.spyk
import io.mockk.verify
import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.support.test.robolectric.testContext
import org.junit.Test
import org.junit.runner.RunWith
import mozilla.components.browser.toolbar.BrowserToolbar
import mozilla.components.browser.toolbar.behavior.BrowserToolbarBehavior
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Before
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import mozilla.components.browser.toolbar.behavior.ToolbarPosition as MozacToolbarPosition
@ExperimentalCoroutinesApi
@RunWith(FenixRobolectricTestRunner::class)
class BrowserToolbarViewTest {
private lateinit var toolbarView: BrowserToolbarView
private lateinit var toolbar: BrowserToolbar
private lateinit var behavior: BrowserToolbarBehavior
@Before
fun `setup`() {
toolbar = BrowserToolbar(testContext)
toolbar.layoutParams = CoordinatorLayout.LayoutParams(100, 100)
behavior = spyk(BrowserToolbarBehavior(testContext, null, MozacToolbarPosition.BOTTOM))
(toolbar.layoutParams as CoordinatorLayout.LayoutParams).behavior = behavior
toolbarView = BrowserToolbarView(
container = CoordinatorLayout(testContext),
toolbarPosition = ToolbarPosition.BOTTOM,
interactor = mockk(),
customTabSession = mockk(relaxed = true),
lifecycleOwner = mockk()
)
toolbarView.view = toolbar
}
@Test
fun `setToolbarBehavior(false) should setDynamicToolbarBehavior if bottom toolbar is dynamic and the tab is not for a PWA or TWA`() {
val toolbarViewSpy = spyk(toolbarView)
every { testContext.settings().toolbarPosition } returns ToolbarPosition.BOTTOM
every { testContext.settings().isDynamicToolbarEnabled } returns true
every { toolbarViewSpy.isPwaTabOrTwaTab } returns false
toolbarViewSpy.setToolbarBehavior(false)
verify { toolbarViewSpy.setDynamicToolbarBehavior(MozacToolbarPosition.BOTTOM) }
}
@Test
fun `setToolbarBehavior(false) should expandToolbarAndMakeItFixed if bottom toolbar is not set as dynamic`() {
val toolbarViewSpy = spyk(toolbarView)
every { testContext.settings().toolbarPosition } returns ToolbarPosition.BOTTOM
every { testContext.settings().isDynamicToolbarEnabled } returns false
toolbarViewSpy.setToolbarBehavior(false)
verify { toolbarViewSpy.expandToolbarAndMakeItFixed() }
}
@Test
fun `setToolbarBehavior(false) should expandToolbarAndMakeItFixed if bottom toolbar is dynamic but the tab is for a PWA or TWA`() {
val toolbarViewSpy = spyk(toolbarView)
every { testContext.settings().toolbarPosition } returns ToolbarPosition.BOTTOM
every { testContext.settings().isDynamicToolbarEnabled } returns true
every { toolbarViewSpy.isPwaTabOrTwaTab } returns true
toolbarViewSpy.setToolbarBehavior(false)
verify { toolbarViewSpy.expandToolbarAndMakeItFixed() }
}
@Test
fun `setToolbarBehavior(true) should setDynamicToolbarBehavior if bottom toolbar is dynamic and the tab is not for a PWA or TWA`() {
val toolbarViewSpy = spyk(toolbarView)
every { testContext.settings().toolbarPosition } returns ToolbarPosition.BOTTOM
every { testContext.settings().isDynamicToolbarEnabled } returns true
every { toolbarViewSpy.isPwaTabOrTwaTab } returns false
toolbarViewSpy.setToolbarBehavior(false)
verify { toolbarViewSpy.setDynamicToolbarBehavior(MozacToolbarPosition.BOTTOM) }
}
@Test
fun `setToolbarBehavior(true) should expandToolbarAndMakeItFixed if bottom toolbar is not set as dynamic`() {
val toolbarViewSpy = spyk(toolbarView)
every { testContext.settings().toolbarPosition } returns ToolbarPosition.BOTTOM
every { testContext.settings().isDynamicToolbarEnabled } returns false
toolbarViewSpy.setToolbarBehavior(false)
verify { toolbarViewSpy.expandToolbarAndMakeItFixed() }
}
@Test
fun `setToolbarBehavior(true) should expandToolbarAndMakeItFixed if bottom toolbar is dynamic but the tab is for a PWA or TWA`() {
val toolbarViewSpy = spyk(toolbarView)
every { testContext.settings().toolbarPosition } returns ToolbarPosition.BOTTOM
every { testContext.settings().isDynamicToolbarEnabled } returns true
every { toolbarViewSpy.isPwaTabOrTwaTab } returns true
toolbarViewSpy.setToolbarBehavior(false)
verify { toolbarViewSpy.expandToolbarAndMakeItFixed() }
}
@Test
fun `setToolbarBehavior(true) should expandToolbarAndMakeItFixed for top toolbar if shouldUseFixedTopToolbar`() {
val toolbarViewSpy = spyk(toolbarView)
every { testContext.settings().toolbarPosition } returns ToolbarPosition.TOP
every { testContext.settings().shouldUseFixedTopToolbar } returns true
toolbarViewSpy.setToolbarBehavior(true)
verify { toolbarViewSpy.expandToolbarAndMakeItFixed() }
}
@Test
fun `setToolbarBehavior(true) should expandToolbarAndMakeItFixed for top toolbar if it is not dynamic`() {
val toolbarViewSpy = spyk(toolbarView)
every { testContext.settings().toolbarPosition } returns ToolbarPosition.TOP
every { testContext.settings().isDynamicToolbarEnabled } returns false
toolbarViewSpy.setToolbarBehavior(true)
verify { toolbarViewSpy.expandToolbarAndMakeItFixed() }
}
@Test
fun `setToolbarBehavior(true) should expandToolbarAndMakeItFixed for top toolbar if shouldDisableScroll`() {
val toolbarViewSpy = spyk(toolbarView)
every { testContext.settings().toolbarPosition } returns ToolbarPosition.TOP
toolbarViewSpy.setToolbarBehavior(true)
verify { toolbarViewSpy.expandToolbarAndMakeItFixed() }
}
@Test
fun `setToolbarBehavior(false) should setDynamicToolbarBehavior for top toolbar`() {
val toolbarViewSpy = spyk(toolbarView)
every { testContext.settings().toolbarPosition } returns ToolbarPosition.TOP
every { testContext.settings().shouldUseFixedTopToolbar } returns true
every { testContext.settings().isDynamicToolbarEnabled } returns true
toolbarViewSpy.setToolbarBehavior(true)
verify { toolbarViewSpy.expandToolbarAndMakeItFixed() }
}
@Test
fun `expandToolbarAndMakeItFixed should expand the toolbar and and disable the dynamic behavior`() {
val toolbarViewSpy = spyk(toolbarView)
assertNotNull((toolbar.layoutParams as CoordinatorLayout.LayoutParams).behavior)
toolbarViewSpy.expandToolbarAndMakeItFixed()
verify { toolbarViewSpy.expand() }
assertNull((toolbar.layoutParams as CoordinatorLayout.LayoutParams).behavior)
}
@Test
fun `setDynamicToolbarBehavior should set a BrowserToolbarBehavior for the bottom toolbar`() {
val toolbarViewSpy = spyk(toolbarView)
(toolbar.layoutParams as CoordinatorLayout.LayoutParams).behavior = null
toolbarViewSpy.setDynamicToolbarBehavior(MozacToolbarPosition.BOTTOM)
assertNotNull((toolbar.layoutParams as CoordinatorLayout.LayoutParams).behavior)
}
@Test
fun `setDynamicToolbarBehavior should set a BrowserToolbarBehavior for the top toolbar`() {
val toolbarViewSpy = spyk(toolbarView)
(toolbar.layoutParams as CoordinatorLayout.LayoutParams).behavior = null
toolbarViewSpy.setDynamicToolbarBehavior(MozacToolbarPosition.TOP)
assertNotNull((toolbar.layoutParams as CoordinatorLayout.LayoutParams).behavior)
}
}
Loading…
Cancel
Save