From b8f819b12c5082ca3848ac854769cb6d9a37d5ce Mon Sep 17 00:00:00 2001 From: AndiAJ Date: Fri, 8 Jan 2021 16:31:57 +0200 Subject: [PATCH] [fenix] For https://github.com/mozilla-mobile/fenix/issues/16615: UI Smoke Tests for Recently Closed Tabs --- .../java/org/mozilla/fenix/ui/SmokeTest.kt | 194 +++++++++++++++ .../ui/robots/RecentlyClosedTabsRobot.kt | 222 ++++++++++++++++++ .../mozilla/fenix/ui/robots/TabDrawerRobot.kt | 22 +- 3 files changed, 437 insertions(+), 1 deletion(-) create mode 100644 app/src/androidTest/java/org/mozilla/fenix/ui/robots/RecentlyClosedTabsRobot.kt diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt index 362b6a2deb..d948c3b4ae 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt @@ -42,6 +42,7 @@ class SmokeTest { private var awesomeBar: ViewVisibilityIdlingResource? = null private var searchSuggestionsIdlingResource: RecyclerViewIdlingResource? = null private var addonsListIdlingResource: RecyclerViewIdlingResource? = null + private var recentlyClosedTabsListIdlingResource: RecyclerViewIdlingResource? = null private val downloadFileName = "Globe.svg" // This finds the dialog fragment child of the homeFragment, otherwise the awesomeBar would return null @@ -85,6 +86,10 @@ class SmokeTest { IdlingRegistry.getInstance().unregister(addonsListIdlingResource!!) } + if (recentlyClosedTabsListIdlingResource != null) { + IdlingRegistry.getInstance().unregister(recentlyClosedTabsListIdlingResource!!) + } + deleteDownloadFromStorage(downloadFileName) } @@ -580,6 +585,195 @@ class SmokeTest { } } + @Test + // This test verifies the Recently Closed Tabs List and items + fun verifyRecentlyClosedTabsListTest() { + val website = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + homeScreen { + }.openNavigationToolbar { + }.enterURLAndEnterToBrowser(website.url) { + mDevice.waitForIdle() + }.openTabDrawer { + closeTab() + }.openTabDrawer { + }.openRecentlyClosedTabs { + waitForListToExist() + recentlyClosedTabsListIdlingResource = + RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1) + IdlingRegistry.getInstance().register(recentlyClosedTabsListIdlingResource!!) + verifyRecentlyClosedTabsMenuView() + IdlingRegistry.getInstance().unregister(recentlyClosedTabsListIdlingResource!!) + verifyRecentlyClosedTabsPageTitle("Test_Page_1") + verifyRecentlyClosedTabsUrl(website.url) + } + } + + @Test + // Verifies the items from the overflow menu of Recently Closed Tabs + fun recentlyClosedTabsMenuItemsTest() { + val website = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + homeScreen { + }.openNavigationToolbar { + }.enterURLAndEnterToBrowser(website.url) { + mDevice.waitForIdle() + }.openTabDrawer { + closeTab() + }.openTabDrawer { + }.openRecentlyClosedTabs { + waitForListToExist() + recentlyClosedTabsListIdlingResource = + RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1) + IdlingRegistry.getInstance().register(recentlyClosedTabsListIdlingResource!!) + verifyRecentlyClosedTabsMenuView() + IdlingRegistry.getInstance().unregister(recentlyClosedTabsListIdlingResource!!) + openRecentlyClosedTabsThreeDotMenu() + verifyRecentlyClosedTabsMenuCopy() + verifyRecentlyClosedTabsMenuShare() + verifyRecentlyClosedTabsMenuNewTab() + verifyRecentlyClosedTabsMenuPrivateTab() + verifyRecentlyClosedTabsMenuDelete() + } + } + + @Test + // Verifies the Copy option from the Recently Closed Tabs overflow menu + fun copyRecentlyClosedTabsItemTest() { + val website = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + homeScreen { + }.openNavigationToolbar { + }.enterURLAndEnterToBrowser(website.url) { + mDevice.waitForIdle() + }.openTabDrawer { + closeTab() + }.openTabDrawer { + }.openRecentlyClosedTabs { + waitForListToExist() + recentlyClosedTabsListIdlingResource = + RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1) + IdlingRegistry.getInstance().register(recentlyClosedTabsListIdlingResource!!) + verifyRecentlyClosedTabsMenuView() + IdlingRegistry.getInstance().unregister(recentlyClosedTabsListIdlingResource!!) + openRecentlyClosedTabsThreeDotMenu() + verifyRecentlyClosedTabsMenuCopy() + clickCopyRecentlyClosedTabs() + verifyCopyRecentlyClosedTabsSnackBarText() + } + } + + @Test + // Verifies the Share option from the Recently Closed Tabs overflow menu + fun shareRecentlyClosedTabsItemTest() { + val website = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + homeScreen { + }.openNavigationToolbar { + }.enterURLAndEnterToBrowser(website.url) { + mDevice.waitForIdle() + }.openTabDrawer { + closeTab() + }.openTabDrawer { + }.openRecentlyClosedTabs { + waitForListToExist() + recentlyClosedTabsListIdlingResource = + RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1) + IdlingRegistry.getInstance().register(recentlyClosedTabsListIdlingResource!!) + verifyRecentlyClosedTabsMenuView() + IdlingRegistry.getInstance().unregister(recentlyClosedTabsListIdlingResource!!) + openRecentlyClosedTabsThreeDotMenu() + verifyRecentlyClosedTabsMenuShare() + clickShareRecentlyClosedTabs() + verifyShareOverlay() + verifyShareTabTitle("Test_Page_1") + verifyShareTabUrl(website.url) + verifyShareTabFavicon() + } + } + + @Test + // Verifies the Open in a new tab option from the Recently Closed Tabs overflow menu + fun openRecentlyClosedTabsInNewTabTest() { + val website = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + homeScreen { + }.openNavigationToolbar { + }.enterURLAndEnterToBrowser(website.url) { + mDevice.waitForIdle() + }.openTabDrawer { + closeTab() + }.openTabDrawer { + }.openRecentlyClosedTabs { + waitForListToExist() + recentlyClosedTabsListIdlingResource = + RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1) + IdlingRegistry.getInstance().register(recentlyClosedTabsListIdlingResource!!) + verifyRecentlyClosedTabsMenuView() + IdlingRegistry.getInstance().unregister(recentlyClosedTabsListIdlingResource!!) + openRecentlyClosedTabsThreeDotMenu() + verifyRecentlyClosedTabsMenuNewTab() + }.clickOpenInNewTab { + verifyUrl(website.url.toString()) + }.openTabDrawer { + verifyNormalModeSelected() + } + } + + @Test + // Verifies the Open in a private tab option from the Recently Closed Tabs overflow menu + fun openRecentlyClosedTabsInNewPrivateTabTest() { + val website = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + homeScreen { + }.openNavigationToolbar { + }.enterURLAndEnterToBrowser(website.url) { + mDevice.waitForIdle() + }.openTabDrawer { + closeTab() + }.openTabDrawer { + }.openRecentlyClosedTabs { + waitForListToExist() + recentlyClosedTabsListIdlingResource = + RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1) + IdlingRegistry.getInstance().register(recentlyClosedTabsListIdlingResource!!) + verifyRecentlyClosedTabsMenuView() + IdlingRegistry.getInstance().unregister(recentlyClosedTabsListIdlingResource!!) + openRecentlyClosedTabsThreeDotMenu() + verifyRecentlyClosedTabsMenuPrivateTab() + }.clickOpenInPrivateTab { + verifyUrl(website.url.toString()) + }.openTabDrawer { + verifyPrivateModeSelected() + } + } + + @Test + // Verifies the delete option from the Recently Closed Tabs overflow menu + fun deleteRecentlyClosedTabsItemTest() { + val website = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + homeScreen { + }.openNavigationToolbar { + }.enterURLAndEnterToBrowser(website.url) { + mDevice.waitForIdle() + }.openTabDrawer { + closeTab() + }.openTabDrawer { + }.openRecentlyClosedTabs { + waitForListToExist() + recentlyClosedTabsListIdlingResource = + RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1) + IdlingRegistry.getInstance().register(recentlyClosedTabsListIdlingResource!!) + verifyRecentlyClosedTabsMenuView() + IdlingRegistry.getInstance().unregister(recentlyClosedTabsListIdlingResource!!) + openRecentlyClosedTabsThreeDotMenu() + verifyRecentlyClosedTabsMenuDelete() + clickDeleteCopyRecentlyClosedTabs() + verifyEmptyRecentlyClosedTabsList() + } + } + @Test /* Verifies downloads in the Downloads Menu: - downloads appear in the list diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/RecentlyClosedTabsRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/RecentlyClosedTabsRobot.kt new file mode 100644 index 0000000000..c2bbd5cad5 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/RecentlyClosedTabsRobot.kt @@ -0,0 +1,222 @@ +/* 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.ui.robots + +import android.net.Uri +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.Visibility +import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withParent +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.uiautomator.UiSelector +import org.hamcrest.Matchers +import org.hamcrest.Matchers.allOf +import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.TestAssetHelper +import org.mozilla.fenix.helpers.click + +/** + * Implementation of Robot Pattern for the recently closed tabs menu. + */ + +class RecentlyClosedTabsRobot { + + fun waitForListToExist() = + mDevice.findObject(UiSelector().resourceId("org.mozilla.fenix.debug:id/recently_closed_list")) + .waitForExists( + TestAssetHelper.waitingTime + ) + + fun verifyRecentlyClosedTabsMenuView() = assertRecentlyClosedTabsMenuView() + + fun verifyEmptyRecentlyClosedTabsList() = assertEmptyRecentlyClosedTabsList() + + fun verifyRecentlyClosedTabsPageTitle(title: String) = assertRecentlyClosedTabsPageTitle(title) + + fun verifyRecentlyClosedTabsUrl(expectedUrl: Uri) = assertPageUrl(expectedUrl) + + fun openRecentlyClosedTabsThreeDotMenu() = recentlyClosedTabsThreeDotButton().click() + + fun verifyRecentlyClosedTabsMenuCopy() = assertRecentlyClosedTabsMenuCopy() + + fun verifyRecentlyClosedTabsMenuShare() = assertRecentlyClosedTabsMenuShare() + + fun verifyRecentlyClosedTabsMenuNewTab() = assertRecentlyClosedTabsOverlayNewTab() + + fun verifyRecentlyClosedTabsMenuPrivateTab() = assertRecentlyClosedTabsMenuPrivateTab() + + fun verifyRecentlyClosedTabsMenuDelete() = assertRecentlyClosedTabsMenuDelete() + + fun clickCopyRecentlyClosedTabs() = recentlyClosedTabsCopyButton().click() + + fun clickShareRecentlyClosedTabs() = recentlyClosedTabsShareButton().click() + + fun clickDeleteCopyRecentlyClosedTabs() = recentlyClosedTabsDeleteButton().click() + + fun verifyCopyRecentlyClosedTabsSnackBarText() = assertCopySnackBarText() + + fun verifyShareOverlay() = assertRecentlyClosedShareOverlay() + + fun verifyShareTabFavicon() = assertRecentlyClosedShareFavicon() + + fun verifyShareTabTitle(title: String) = assetRecentlyClosedShareTitle(title) + + fun verifyShareTabUrl(expectedUrl: Uri) = assertRecentlyClosedShareUrl(expectedUrl) + + class Transition { + fun clickOpenInNewTab(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + recentlyClosedTabsNewTabButton().click() + + BrowserRobot().interact() + return BrowserRobot.Transition() + } + + fun clickOpenInPrivateTab(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + recentlyClosedTabsNewPrivateTabButton().click() + + BrowserRobot().interact() + return BrowserRobot.Transition() + } + } +} + +private fun assertRecentlyClosedTabsMenuView() { + onView( + allOf( + withText("Recently closed tabs"), + withParent(withId(R.id.navigationToolbar)) + ) + ) + .check( + matches(withEffectiveVisibility(Visibility.VISIBLE))) +} + +private fun assertEmptyRecentlyClosedTabsList() = + onView( + allOf( + withId(R.id.recently_closed_empty_view), + withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE) + ) + ) + .check( + matches(withText("No recently closed tabs here"))) + +private fun assertPageUrl(expectedUrl: Uri) = onView( + allOf( + withId(R.id.url), + withEffectiveVisibility( + Visibility.VISIBLE + ) + ) +) + .check( + matches(withText(Matchers.containsString(expectedUrl.toString())))) + +private fun recentlyClosedTabsPageTitle() = onView( + allOf( + withId(R.id.title), + withText("Test_Page_1") + ) +) + +private fun assertRecentlyClosedTabsPageTitle(title: String) { + recentlyClosedTabsPageTitle() + .check( + matches(withEffectiveVisibility(Visibility.VISIBLE))) + .check( + matches(withText(title))) +} + +private fun recentlyClosedTabsThreeDotButton() = + onView( + allOf( + withId(R.id.overflow_menu), + withEffectiveVisibility( + Visibility.VISIBLE + ) + ) +) + +private fun assertRecentlyClosedTabsMenuCopy() = + onView(withText("Copy")) + .check( + matches( + withEffectiveVisibility(Visibility.VISIBLE))) + +private fun assertRecentlyClosedTabsMenuShare() = + onView(withText("Share")) + .check( + matches( + withEffectiveVisibility(Visibility.VISIBLE))) + +private fun assertRecentlyClosedTabsOverlayNewTab() = + onView(withText("Open in new tab")) + .check( + matches( + withEffectiveVisibility(Visibility.VISIBLE)) +) + +private fun assertRecentlyClosedTabsMenuPrivateTab() = + onView(withText("Open in private tab")) + .check( + matches( + withEffectiveVisibility(Visibility.VISIBLE) + ) + ) + +private fun assertRecentlyClosedTabsMenuDelete() = + onView(withText("Delete")) + .check( + matches( + withEffectiveVisibility(Visibility.VISIBLE) + ) +) + +private fun recentlyClosedTabsCopyButton() = onView(withText("Copy")) + +private fun copySnackBarText() = onView(withId(R.id.snackbar_text)) + +private fun assertCopySnackBarText() = copySnackBarText() + .check( + matches + (withText("URL copied"))) + +private fun recentlyClosedTabsShareButton() = onView(withText("Share")) + +private fun assertRecentlyClosedShareOverlay() = + onView(withId(R.id.shareWrapper)) + .check( + matches(ViewMatchers.isDisplayed())) + +private fun assetRecentlyClosedShareTitle(title: String) = + onView(withId(R.id.share_tab_title)) + .check( + matches(ViewMatchers.isDisplayed())) + .check( + matches(withText(title))) + +private fun assertRecentlyClosedShareFavicon() = + onView(withId(R.id.share_tab_favicon)) + .check( + matches(ViewMatchers.isDisplayed())) + +private fun assertRecentlyClosedShareUrl(expectedUrl: Uri) = + onView( + allOf( + withId(R.id.share_tab_url), + withEffectiveVisibility(Visibility.VISIBLE) + ) + ) + .check( + matches(withText(Matchers.containsString(expectedUrl.toString())))) + +private fun recentlyClosedTabsNewTabButton() = onView(withText("Open in new tab")) + +private fun recentlyClosedTabsNewPrivateTabButton() = onView(withText("Open in private tab")) + +private fun recentlyClosedTabsDeleteButton() = onView(withText("Delete")) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt index a14b0e539f..f926a1ed2f 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt @@ -30,6 +30,7 @@ import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.By import androidx.test.uiautomator.By.text import androidx.test.uiautomator.UiDevice +import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until import androidx.test.uiautomator.Until.findObject import com.google.android.material.bottomsheet.BottomSheetBehavior @@ -123,7 +124,8 @@ class TabDrawerRobot { } fun openTabDrawer(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition { - org.mozilla.fenix.ui.robots.mDevice.waitForIdle() + mDevice.findObject(UiSelector().resourceId("org.mozilla.fenix.debug:id/tab_button")) + .waitForExists(waitingTime) tabsCounter().click() @@ -226,6 +228,24 @@ class TabDrawerRobot { } return Transition() } + + fun openRecentlyClosedTabs(interact: RecentlyClosedTabsRobot.() -> Unit): + RecentlyClosedTabsRobot.Transition { + + threeDotMenu().click() + + val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + mDevice.waitNotNull( + Until.findObject(text("Recently closed tabs")), + waitingTime + ) + + val menuRecentlyClosedTabs = mDevice.findObject(text("Recently closed tabs")) + menuRecentlyClosedTabs.click() + + RecentlyClosedTabsRobot().interact() + return RecentlyClosedTabsRobot.Transition() + } } }