You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iceraven-browser/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt

596 lines
24 KiB
Kotlin

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/* 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/. */
@file:Suppress("TooManyFunctions")
package org.mozilla.fenix.ui.robots
import android.util.Log
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.swipeDown
import androidx.test.espresso.action.ViewActions.swipeUp
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.matcher.RootMatchers
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.Visibility
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiObjectNotFoundException
import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import org.hamcrest.Matchers.allOf
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.Constants.LONG_CLICK_DURATION
import org.mozilla.fenix.helpers.Constants.RETRY_COUNT
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.checkedItemWithResIdAndText
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithDescription
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeLong
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.click
import org.mozilla.fenix.helpers.ext.waitNotNull
import org.mozilla.fenix.nimbus.FxNimbus
/**
* Implementation of Robot Pattern for the three dot (main) menu.
*/
@Suppress("ForbiddenComment")
class ThreeDotMenuMainRobot {
fun verifyShareAllTabsButton() = shareAllTabsButton().check(matches(isDisplayed()))
fun verifySettingsButton() = assertUIObjectExists(settingsButton())
fun verifyHistoryButton() = assertUIObjectExists(historyButton())
fun verifyThreeDotMenuExists() = threeDotMenuRecyclerView().check(matches(isDisplayed()))
fun verifyAddBookmarkButton() = assertUIObjectExists(addBookmarkButton())
fun verifyEditBookmarkButton() =
editBookmarkButton().check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
fun verifyCloseAllTabsButton() =
closeAllTabsButton().check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
fun verifyReaderViewAppearance(visible: Boolean) {
var maxSwipes = 3
if (visible) {
while (!readerViewAppearanceToggle().exists() && maxSwipes != 0) {
threeDotMenuRecyclerView().perform(swipeUp())
maxSwipes--
}
assertUIObjectExists(readerViewAppearanceToggle())
} else {
while (!readerViewAppearanceToggle().exists() && maxSwipes != 0) {
threeDotMenuRecyclerView().perform(swipeUp())
maxSwipes--
}
assertUIObjectExists(readerViewAppearanceToggle(), exists = false)
}
}
fun verifyQuitButtonExists() {
// Need to double swipe the menu, to make this button visible.
// In case it reaches the end, the second swipe is no-op.
expandMenu()
expandMenu()
assertUIObjectExists(itemWithText("Quit"))
}
fun expandMenu() {
onView(withId(R.id.mozac_browser_menu_menuView)).perform(swipeUp())
}
fun verifyShareTabButton() = shareTabButton().check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
fun verifySelectTabs() = selectTabsButton().check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
fun verifyFindInPageButton() = assertUIObjectExists(findInPageButton())
fun verifyAddToShortcutsButton(shouldExist: Boolean) =
assertUIObjectExists(addToShortcutsButton(), exists = shouldExist)
fun verifyRemoveFromShortcutsButton() =
onView(withId(R.id.mozac_browser_menu_recyclerView))
.perform(
RecyclerViewActions.scrollTo<RecyclerView.ViewHolder>(
hasDescendant(withText(R.string.browser_menu_settings)),
),
).check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
fun verifyShareTabsOverlay() {
onView(withId(R.id.shared_site_list)).check(matches(isDisplayed()))
onView(withId(R.id.share_tab_title)).check(matches(isDisplayed()))
onView(withId(R.id.share_tab_favicon)).check(matches(isDisplayed()))
onView(withId(R.id.share_tab_url)).check(matches(isDisplayed()))
}
fun verifyDesktopSiteModeEnabled(isRequestDesktopSiteEnabled: Boolean) {
expandMenu()
assertUIObjectExists(desktopSiteToggle(isRequestDesktopSiteEnabled))
}
fun verifyPageThreeDotMainMenuItems(isRequestDesktopSiteEnabled: Boolean) {
expandMenu()
assertUIObjectExists(
normalBrowsingNewTabButton(),
bookmarksButton(),
historyButton(),
downloadsButton(),
addOnsButton(),
syncAndSaveDataButton(),
findInPageButton(),
desktopSiteButton(),
reportSiteIssueButton(),
addToHomeScreenButton(),
addToShortcutsButton(),
saveToCollectionButton(),
addBookmarkButton(),
desktopSiteToggle(isRequestDesktopSiteEnabled),
translateButton(),
)
// Swipe to second part of menu
expandMenu()
assertUIObjectExists(
settingsButton(),
)
if (FxNimbus.features.print.value().browserPrintEnabled) {
assertUIObjectExists(printContentButton())
}
assertUIObjectExists(
backButton(),
forwardButton(),
shareButton(),
refreshButton(),
)
}
fun verifyHomeThreeDotMainMenuItems(isRequestDesktopSiteEnabled: Boolean) {
assertUIObjectExists(
bookmarksButton(),
historyButton(),
downloadsButton(),
addOnsButton(),
// Disabled step due to https://github.com/mozilla-mobile/fenix/issues/26788
// syncAndSaveDataButton,
desktopSiteButton(),
whatsNewButton(),
helpButton(),
customizeHomeButton(),
settingsButton(),
desktopSiteToggle(isRequestDesktopSiteEnabled),
)
}
fun openAddonsSubList() {
// when there are add-ons installed, there is an overflow Add-ons sub-menu
// in that case we use this method instead or before openAddonsManagerMenu()
clickAddonsManagerButton()
}
fun verifyAddonAvailableInMainMenu(addonName: String) {
for (i in 1..RETRY_COUNT) {
try {
assertUIObjectExists(itemContainingText(addonName))
break
} catch (e: AssertionError) {
if (i == RETRY_COUNT) {
throw e
} else {
mDevice.pressBack()
browserScreen {
}.openThreeDotMenu {
openAddonsSubList()
}
}
}
}
}
fun verifyTrackersBlockedByUblock() {
assertUIObjectExists(itemWithResId("$packageName:id/badge_text"))
assertTrue(itemWithResId("$packageName:id/badge_text").text.toInt() > 0)
}
fun clickQuit() {
expandMenu()
onView(withText("Quit")).click()
}
class Transition {
fun openSettings(
localizedText: String = getStringResource(R.string.browser_menu_settings),
interact: SettingsRobot.() -> Unit,
): SettingsRobot.Transition {
// We require one swipe to display the full size 3-dot menu. On smaller devices
// such as the Pixel 2, we require two swipes to display the "Settings" menu item
// at the bottom. On larger devices, the second swipe is a no-op.
threeDotMenuRecyclerView().perform(swipeUp())
Log.i(TAG, "openSettings: Swiped up the main menu once")
threeDotMenuRecyclerView().perform(swipeUp())
Log.i(TAG, "openSettings: Swiped up the main menu twice")
settingsButton(localizedText).click()
Log.i(TAG, "openSettings: Clicked main menu $localizedText button")
SettingsRobot().interact()
return SettingsRobot.Transition()
}
fun openDownloadsManager(interact: DownloadRobot.() -> Unit): DownloadRobot.Transition {
threeDotMenuRecyclerView().perform(swipeDown())
Log.i(TAG, "openDownloadsManager: Swiped up main menu")
downloadsButton().click()
Log.i(TAG, "openDownloadsManager: Clicked main menu \"DOWNLOADS\" button")
DownloadRobot().interact()
return DownloadRobot.Transition()
}
fun openSyncSignIn(interact: SyncSignInRobot.() -> Unit): SyncSignInRobot.Transition {
threeDotMenuRecyclerView().perform(swipeDown())
mDevice.waitNotNull(Until.findObject(By.text("Sync and save data")), waitingTime)
syncAndSaveDataButton().click()
SyncSignInRobot().interact()
return SyncSignInRobot.Transition()
}
fun openBookmarks(interact: BookmarksRobot.() -> Unit): BookmarksRobot.Transition {
threeDotMenuRecyclerView().perform(swipeDown())
mDevice.waitNotNull(Until.findObject(By.text("Bookmarks")), waitingTime)
bookmarksButton().click()
assertUIObjectExists(itemWithResId("$packageName:id/bookmark_list"))
BookmarksRobot().interact()
return BookmarksRobot.Transition()
}
fun clickNewTabButton(interact: SearchRobot.() -> Unit): SearchRobot.Transition {
normalBrowsingNewTabButton().click()
SearchRobot().interact()
return SearchRobot.Transition()
}
fun openHistory(interact: HistoryRobot.() -> Unit): HistoryRobot.Transition {
threeDotMenuRecyclerView().perform(swipeDown())
mDevice.waitNotNull(Until.findObject(By.text("History")), waitingTime)
historyButton().click()
HistoryRobot().interact()
return HistoryRobot.Transition()
}
fun bookmarkPage(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
mDevice.waitNotNull(Until.findObject(By.text("Bookmarks")), waitingTime)
addBookmarkButton().click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun editBookmarkPage(interact: BookmarksRobot.() -> Unit): BookmarksRobot.Transition {
mDevice.waitNotNull(Until.findObject(By.text("Bookmarks")), waitingTime)
editBookmarkButton().click()
BookmarksRobot().interact()
return BookmarksRobot.Transition()
}
fun openHelp(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
mDevice.waitNotNull(Until.findObject(By.text("Help")), waitingTime)
helpButton().click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun openCustomizeHome(interact: SettingsSubMenuHomepageRobot.() -> Unit): SettingsSubMenuHomepageRobot.Transition {
mDevice.wait(
Until
.findObject(
By.textContains("$packageName:id/browser_menu_customize_home_1"),
),
waitingTime,
)
customizeHomeButton().click()
mDevice.findObject(
UiSelector().resourceId("$packageName:id/recycler_view"),
).waitForExists(waitingTime)
SettingsSubMenuHomepageRobot().interact()
return SettingsSubMenuHomepageRobot.Transition()
}
fun goForward(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
forwardButton().click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun goToPreviousPage(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
backButton().click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun clickShareButton(interact: ShareOverlayRobot.() -> Unit): ShareOverlayRobot.Transition {
shareButton().click()
Log.i(TAG, "clickShareButton: Clicked main menu share button")
mDevice.waitNotNull(Until.findObject(By.text("ALL ACTIONS")), waitingTime)
ShareOverlayRobot().interact()
return ShareOverlayRobot.Transition()
}
fun closeBrowserMenuToBrowser(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
// Close three dot
mDevice.pressBack()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun refreshPage(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
refreshButton().also {
Log.i(TAG, "refreshPage: Looking for refresh button")
it.waitForExists(waitingTime)
it.click()
Log.i(TAG, "refreshPage: Clicked the refresh button")
}
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun forceRefreshPage(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
mDevice.findObject(By.desc(getStringResource(R.string.browser_menu_refresh)))
.click(LONG_CLICK_DURATION)
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun closeAllTabs(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
closeAllTabsButton().click()
HomeScreenRobot().interact()
return HomeScreenRobot.Transition()
}
fun openReportSiteIssue(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
threeDotMenuRecyclerView().perform(swipeUp())
threeDotMenuRecyclerView().perform(swipeUp())
reportSiteIssueButton().click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun openFindInPage(interact: FindInPageRobot.() -> Unit): FindInPageRobot.Transition {
threeDotMenuRecyclerView().perform(swipeUp())
threeDotMenuRecyclerView().perform(swipeUp())
mDevice.waitNotNull(Until.findObject(By.text("Find in page")), waitingTime)
findInPageButton().click()
FindInPageRobot().interact()
return FindInPageRobot.Transition()
}
fun openWhatsNew(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
mDevice.waitNotNull(Until.findObject(By.text("Whats new")), waitingTime)
whatsNewButton().click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun openReaderViewAppearance(interact: ReaderViewRobot.() -> Unit): ReaderViewRobot.Transition {
threeDotMenuRecyclerView().perform(swipeUp())
threeDotMenuRecyclerView().perform(swipeUp())
readerViewAppearanceToggle().click()
ReaderViewRobot().interact()
return ReaderViewRobot.Transition()
}
fun addToFirefoxHome(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
for (i in 1..RETRY_COUNT) {
try {
addToShortcutsButton().also {
it.waitForExists(waitingTime)
it.click()
}
break
} catch (e: UiObjectNotFoundException) {
if (i == RETRY_COUNT) {
throw e
} else {
mDevice.pressBack()
navigationToolbar {
}.openThreeDotMenu {
expandMenu()
}
}
}
}
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun clickRemoveFromShortcuts(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
removeFromShortcutsButton().click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun openAddToHomeScreen(interact: AddToHomeScreenRobot.() -> Unit): AddToHomeScreenRobot.Transition {
addToHomeScreenButton().clickAndWaitForNewWindow(waitingTime)
AddToHomeScreenRobot().interact()
return AddToHomeScreenRobot.Transition()
}
fun clickInstall(interact: AddToHomeScreenRobot.() -> Unit): AddToHomeScreenRobot.Transition {
threeDotMenuRecyclerView().perform(swipeUp())
threeDotMenuRecyclerView().perform(swipeUp())
installPWAButton().click()
AddToHomeScreenRobot().interact()
return AddToHomeScreenRobot.Transition()
}
fun openSaveToCollection(interact: CollectionRobot.() -> Unit): CollectionRobot.Transition {
// Ensure the menu is expanded and fully scrolled to the bottom.
threeDotMenuRecyclerView().perform(swipeUp())
threeDotMenuRecyclerView().perform(swipeUp())
mDevice.waitNotNull(Until.findObject(By.text("Save to collection")), waitingTime)
saveToCollectionButton().click()
CollectionRobot().interact()
return CollectionRobot.Transition()
}
fun openAddonsManagerMenu(interact: SettingsSubMenuAddonsManagerRobot.() -> Unit): SettingsSubMenuAddonsManagerRobot.Transition {
clickAddonsManagerButton()
mDevice.findObject(UiSelector().resourceId("$packageName:id/add_ons_list"))
.waitForExists(waitingTimeLong)
SettingsSubMenuAddonsManagerRobot().interact()
return SettingsSubMenuAddonsManagerRobot.Transition()
}
fun clickOpenInApp(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
threeDotMenuRecyclerView().perform(swipeUp())
threeDotMenuRecyclerView().perform(swipeUp())
openInAppButton().click()
mDevice.waitForIdle()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun switchDesktopSiteMode(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
threeDotMenuRecyclerView().perform(swipeUp())
threeDotMenuRecyclerView().perform(swipeUp())
desktopSiteButton().click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun clickShareAllTabsButton(interact: ShareOverlayRobot.() -> Unit): ShareOverlayRobot.Transition {
shareAllTabsButton().click()
ShareOverlayRobot().interact()
return ShareOverlayRobot.Transition()
}
fun clickPrintButton(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
threeDotMenuRecyclerView().perform(swipeUp())
threeDotMenuRecyclerView().perform(swipeUp())
printButton().waitForExists(waitingTime)
printButton().click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
}
}
private fun threeDotMenuRecyclerView() =
onView(withId(R.id.mozac_browser_menu_recyclerView))
private fun editBookmarkButton() = onView(withText("Edit"))
private fun stopLoadingButton() = onView(ViewMatchers.withContentDescription("Stop"))
private fun closeAllTabsButton() = onView(allOf(withText("Close all tabs"))).inRoot(RootMatchers.isPlatformPopup())
private fun shareTabButton() = onView(allOf(withText("Share all tabs"))).inRoot(RootMatchers.isPlatformPopup())
private fun selectTabsButton() = onView(allOf(withText("Select tabs"))).inRoot(RootMatchers.isPlatformPopup())
private fun readerViewAppearanceToggle() =
mDevice.findObject(UiSelector().text("Customize reader view"))
private fun removeFromShortcutsButton() =
onView(allOf(withText(R.string.browser_menu_remove_from_shortcuts)))
private fun installPWAButton() = mDevice.findObject(UiSelector().text("Install"))
private fun openInAppButton() =
onView(
allOf(
withText("Open in app"),
withEffectiveVisibility(Visibility.VISIBLE),
),
)
private fun clickAddonsManagerButton() {
onView(withId(R.id.mozac_browser_menu_menuView)).perform(swipeDown())
addOnsButton().click()
}
private fun shareAllTabsButton() =
onView(allOf(withText("Share all tabs"))).inRoot(RootMatchers.isPlatformPopup())
private fun bookmarksButton() =
itemContainingText(getStringResource(R.string.library_bookmarks))
private fun historyButton() =
itemContainingText(getStringResource(R.string.library_history))
private fun downloadsButton() =
itemContainingText(getStringResource(R.string.library_downloads))
private fun addOnsButton() =
itemContainingText(getStringResource(R.string.browser_menu_add_ons))
private fun desktopSiteButton() =
itemContainingText(getStringResource(R.string.browser_menu_desktop_site))
private fun desktopSiteToggle(state: Boolean) =
checkedItemWithResIdAndText(
"$packageName:id/switch_widget",
getStringResource(R.string.browser_menu_desktop_site),
state,
)
private fun whatsNewButton() =
itemContainingText(getStringResource(R.string.browser_menu_whats_new))
private fun helpButton() =
itemContainingText(getStringResource(R.string.browser_menu_help))
private fun customizeHomeButton() =
itemContainingText(getStringResource(R.string.browser_menu_customize_home_1))
private fun settingsButton(localizedText: String = getStringResource(R.string.browser_menu_settings)) =
itemContainingText(localizedText)
private fun syncAndSaveDataButton() =
itemContainingText(getStringResource(R.string.sync_menu_sync_and_save_data))
private fun normalBrowsingNewTabButton() =
itemContainingText(getStringResource(R.string.library_new_tab))
private fun addBookmarkButton() =
itemWithResIdAndText(
"$packageName:id/checkbox",
getStringResource(R.string.browser_menu_add),
)
private fun findInPageButton() = itemContainingText(getStringResource(R.string.browser_menu_find_in_page))
private fun translateButton() = itemContainingText(getStringResource(R.string.browser_menu_translations))
private fun reportSiteIssueButton() = itemContainingText("Report Site Issue")
private fun addToHomeScreenButton() = itemContainingText(getStringResource(R.string.browser_menu_add_to_homescreen))
private fun addToShortcutsButton() = itemContainingText(getStringResource(R.string.browser_menu_add_to_shortcuts))
private fun saveToCollectionButton() = itemContainingText(getStringResource(R.string.browser_menu_save_to_collection_2))
private fun printContentButton() = itemContainingText(getStringResource(R.string.menu_print))
private fun backButton() = itemWithDescription(getStringResource(R.string.browser_menu_back))
private fun forwardButton() = itemWithDescription(getStringResource(R.string.browser_menu_forward))
private fun shareButton() = itemWithDescription(getStringResource(R.string.share_button_content_description))
private fun refreshButton() = itemWithDescription(getStringResource(R.string.browser_menu_refresh))
private fun printButton() = itemWithText("Print")