Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,13 @@ class ContextMenusTest {
.enterUrlAndEnterToBrowser(pageLinks.url) {
longClickMatchingText("Link 1")
clickContextOpenLinkInNewTab()
verifySnackbarIsAnchoredAboveToolbar()
focusToolbarWithSnackbarShown()
verifySnackbarIsAnchoredAboveToolbar()
dismissKeyboardWithSnackbarShown()
verifySnackbarIsAnchoredAboveToolbar()
clickSnackbarSwitchButton()
verifyUrl(genericURL.url.toString())
}
navigationToolbar {}
.openTabTrayMenu {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

package org.mozilla.reference.browser.ui.robots

import android.graphics.Rect
import android.view.View
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers
Expand All @@ -20,9 +22,12 @@ import org.mozilla.reference.browser.helpers.Constants.LONG_CLICK_DURATION
import org.mozilla.reference.browser.helpers.TestAssetHelper.waitingTime
import org.mozilla.reference.browser.helpers.TestHelper.packageName
import org.mozilla.reference.browser.helpers.TestHelper.waitForObjects
import kotlin.math.abs

/** Implementation of Robot Pattern for browser action. */
class BrowserRobot {
private var snackbarToolbarGap: Int? = null

/* Asserts that the text within DOM element with ID="testContent" has the given text, i.e.
* document.querySelector('#testContent').innerText == expectedText
*/
Expand Down Expand Up @@ -208,6 +213,54 @@ class BrowserRobot {
it.click()
}

fun verifySnackbarIsAnchoredAboveToolbar() {
mDevice.findObject(UiSelector().resourceId("$packageName:id/snackbar_text")).waitForExists(waitingTime)
onView(withId(com.google.android.material.R.id.snackbar_text)).check { snackbarText, exception ->
if (exception != null) {
throw exception
}

val snackbarContent = snackbarText.parent as View
val snackbar = snackbarContent.parent as View
val toolbar = snackbar.rootView.findViewById<View>(org.mozilla.reference.browser.R.id.toolbar)
val snackbarBounds = Rect().also(snackbar::getGlobalVisibleRect)
val toolbarBounds = Rect().also(toolbar::getGlobalVisibleRect)
val visibleScreenBounds = Rect().also(snackbar.rootView::getWindowVisibleDisplayFrame)
val gap = toolbarBounds.top - snackbarBounds.bottom
val maximumGap = (snackbar.resources.displayMetrics.density * MAXIMUM_SNACKBAR_GAP_DP).toInt()
val positionTolerance = (snackbar.resources.displayMetrics.density * POSITION_TOLERANCE_DP).toInt()

assertTrue("Snackbar overlaps toolbar: snackbar=$snackbarBounds toolbar=$toolbarBounds", gap >= 0)
assertTrue("Snackbar is too far above toolbar: gap=$gap", gap <= maximumGap)
assertTrue(
"Toolbar is not aligned with the visible screen: toolbar=$toolbarBounds screen=$visibleScreenBounds",
abs(toolbarBounds.bottom - visibleScreenBounds.bottom) <= positionTolerance,
)

snackbarToolbarGap?.let { initialGap ->
assertTrue(
"Snackbar gap changed from $initialGap to $gap",
abs(initialGap - gap) <= positionTolerance,
)
} ?: run {
snackbarToolbarGap = gap
}
}
}

fun focusToolbarWithSnackbarShown() {
mDevice
.findObject(UiSelector().resourceId("$packageName:id/mozac_browser_toolbar_url_view"))
.click()
mDevice.findObject(UiSelector().textContains("Search or enter address")).waitForExists(waitingTime)
mDevice.waitForIdle()
}

fun dismissKeyboardWithSnackbarShown() {
mDevice.pressBack()
mDevice.waitForIdle()
}

class Transition {
fun checkExternalApps(interact: ExternalAppsRobot.() -> Unit): ExternalAppsRobot.Transition {
mDevice.waitForWindowUpdate(packageName, waitingTime)
Expand Down Expand Up @@ -237,6 +290,9 @@ class BrowserRobot {
}
}

private const val MAXIMUM_SNACKBAR_GAP_DP = 32
private const val POSITION_TOLERANCE_DP = 1

fun browser(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
BrowserRobot().interact()
return BrowserRobot.Transition()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
requireComponents.useCases.contextMenuUseCases,
engineView,
view,
toolbar,
sessionId,
),
owner = this,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,14 @@ class ContextMenuIntegration(
contextMenuUseCases: ContextMenuUseCases,
engineView: EngineView,
parentView: View,
toolbar: View,
sessionId: String? = null,
) : LifecycleAwareFeature {
private val candidates = run {
if (sessionId != null) {
val snackbarDelegate = DefaultSnackbarDelegate()
val snackbarDelegate = DefaultSnackbarDelegate { snackbar ->
snackbar.anchorView = toolbar
}
listOf(
createCopyLinkCandidate(context, parentView, snackbarDelegate),
createShareLinkCandidate(context),
Expand Down