From 2bbb4c29ffcb86fb13ba6b5a0677a39a526de231 Mon Sep 17 00:00:00 2001 From: Aaron Train Date: Tue, 27 Aug 2019 13:56:12 -0400 Subject: [PATCH] Closes #4926: Add basic UI test for regular/private tabs (#4928) --- .../org/mozilla/fenix/ui/HomeScreenTest.kt | 2 +- .../mozilla/fenix/ui/TabbedBrowsingTest.kt | 142 ++++++++++++++++++ .../mozilla/fenix/ui/robots/BrowserRobot.kt | 8 +- .../fenix/ui/robots/HomeScreenRobot.kt | 25 ++- .../fenix/ui/robots/NavigationToolbarRobot.kt | 11 +- .../org/mozilla/fenix/ui/robots/TabsRobot.kt | 23 --- .../fenix/ui/robots/ThreeDotMenuRobot.kt | 36 ++++- 7 files changed, 209 insertions(+), 38 deletions(-) create mode 100644 app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt delete mode 100644 app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabsRobot.kt diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/HomeScreenTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/HomeScreenTest.kt index 51099cbe1..593949571 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/HomeScreenTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/HomeScreenTest.kt @@ -95,7 +95,7 @@ class HomeScreenTest { @Test fun privateModeScreenItemsTest() { homeScreen { }.dismissOnboarding() - homeScreen { }.turnOnPrivateMode() + homeScreen { }.togglePrivateBrowsingMode() homeScreen { verifyHomeScreen() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt new file mode 100644 index 000000000..5ed6de4c5 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt @@ -0,0 +1,142 @@ +/* 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 + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import okhttp3.mockwebserver.MockWebServer +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.mozilla.fenix.helpers.AndroidAssetDispatcher +import org.mozilla.fenix.helpers.HomeActivityTestRule +import org.mozilla.fenix.helpers.TestAssetHelper +import org.mozilla.fenix.ui.robots.homeScreen +import org.mozilla.fenix.ui.robots.navigationToolbar + +/** + * Tests for verifying basic functionality of tabbed browsing + * + * Including: + * - Opening a tab + * - Opening a private tab + * - Verifying tab list + * - Closing all tabs + * + * TODO: Tab Collections + */ + +class TabbedBrowsingTest { + private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + private lateinit var mockWebServer: MockWebServer + + /* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping. + @get:Rule + val activityTestRule = HomeActivityTestRule() + + @Before + fun setUp() { + mockWebServer = MockWebServer().apply { + setDispatcher(AndroidAssetDispatcher()) + start() + } + } + + @After + fun tearDown() { + mockWebServer.shutdown() + } + + @Test + fun openNewTabTest() { + homeScreen { }.dismissOnboarding() + + val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + homeScreen { + verifyOpenTabsHeader() + verifyNoTabsOpenedText() + verifyNoTabsOpenedHeader() + verifyNoCollectionsText() + verifyNoCollectionsHeader() + verifyAddTabButton() + } + + navigationToolbar { + }.openNewTabAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) + verifyTabCounter("1") + }.openHomeScreen { } + + homeScreen { + verifyExistingTabList() + + }.openTabsListThreeDotMenu { + verifyCloseAllTabsButton() + verifyShareButton() + verifySaveCollection() + } + } + + @Test + fun openNewPrivateTabTest() { + homeScreen { }.dismissOnboarding() + + val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + homeScreen { }.togglePrivateBrowsingMode() + + homeScreen { + verifyPrivateSessionHeader() + verifyPrivateSessionMessage(true) + verifyAddTabButton() + } + + navigationToolbar { + }.openNewTabAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) + verifyTabCounter("1") + }.openHomeScreen { + verifyExistingTabList() + verifyShareTabsButton(true) + verifyCloseTabsButton(true) + }.togglePrivateBrowsingMode() + + // Verify private tabs remain in private browsing mode + + homeScreen { + verifyNoTabsOpenedHeader() + verifyNoTabsOpenedText() + }.togglePrivateBrowsingMode() + + homeScreen { + verifyExistingTabList() + } + } + + @Test + fun closeAllTabsTest() { + val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + navigationToolbar { + }.enterURLAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) + }.openHomeScreen { } + + homeScreen { + verifyExistingTabList() + }.openTabsListThreeDotMenu { + verifyCloseAllTabsButton() + verifyShareButton() + verifySaveCollection() + }.closeAllTabs { + verifyNoCollectionsHeader() + verifyNoCollectionsText() + verifyNoTabsOpenedHeader() + verifyNoTabsOpenedText() + } + } +} diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt index 64f93adc9..e50870c17 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt @@ -8,7 +8,6 @@ package org.mozilla.fenix.ui.robots import androidx.test.espresso.Espresso.onView import androidx.test.espresso.assertion.ViewAssertions.matches -import androidx.test.espresso.matcher.ViewMatchers.withContentDescription import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.platform.app.InstrumentationRegistry @@ -39,6 +38,11 @@ class BrowserRobot { mDevice.wait(Until.findObject(By.res(expectedText)), TestAssetHelper.waitingTime) } + fun verifyTabCounter(expectedText: String) { + onView(withId(R.id.counter_text)) + .check((matches(withText(containsString(expectedText))))) + } + class Transition { private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) @@ -68,4 +72,4 @@ fun browserScreen(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { fun navURLBar() = onView(withId(R.id.mozac_browser_toolbar_url_view)) -private fun tabsCounter() = onView(withContentDescription("Tabs")) +private fun tabsCounter() = onView(withId(R.id.counter_box)) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt index 38a194c62..9e9bcc2ad 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt @@ -12,6 +12,7 @@ import androidx.test.espresso.assertion.ViewAssertions.doesNotExist 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.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice @@ -72,6 +73,8 @@ class HomeScreenRobot { fun verifyShareTabsButton(visible: Boolean = true) = assertShareTabsButton(visible) fun verifyCloseTabsButton(visible: Boolean = true) = assertCloseTabsButton(visible) + fun verifyExistingTabList() = assertExistingTabList() + private fun scrollToElementByText(text: String): UiScrollable { val appView = UiScrollable(UiSelector().scrollable(true)) appView.scrollTextIntoView(text) @@ -109,10 +112,18 @@ class HomeScreenRobot { openSearch { }.openBrowser { }.openHomeScreen { } } - fun turnOnPrivateMode() { + fun togglePrivateBrowsingMode() { onView(ViewMatchers.withResourceName("privateBrowsingButton")) .perform(click()) } + + fun openTabsListThreeDotMenu(interact: ThreeDotMenuRobot.() -> Unit): ThreeDotMenuRobot.Transition { + mDevice.waitForIdle() + tabsListThreeDotButton().perform(click()) + + ThreeDotMenuRobot().interact() + return ThreeDotMenuRobot.Transition() + } } } @@ -151,7 +162,7 @@ private fun assertOpenTabsHeader() = .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun assertAddTabButton() = - onView(CoreMatchers.allOf(ViewMatchers.withResourceName("add_tab_button"))) + onView(CoreMatchers.allOf(ViewMatchers.withId(R.id.add_tab_button), isDisplayed())) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun assertNoTabsOpenedHeader() = @@ -296,11 +307,17 @@ private fun assertPrivateSessionMessage(visible: Boolean) = ) private fun assertShareTabsButton(visible: Boolean) = - onView(CoreMatchers.allOf(ViewMatchers.withResourceName("share_tabs_button"))) + onView(CoreMatchers.allOf(ViewMatchers.withId(R.id.share_tabs_button), isDisplayed())) .check(matches(withEffectiveVisibility(visibleOrGone(visible)))) private fun assertCloseTabsButton(visible: Boolean) = - onView(CoreMatchers.allOf(ViewMatchers.withResourceName("close_tabs_button"))) + onView(CoreMatchers.allOf(ViewMatchers.withId(R.id.close_tab_button), isDisplayed())) .check(matches(withEffectiveVisibility(visibleOrGone(visible)))) private fun visibleOrGone(visibility: Boolean) = if (visibility) Visibility.VISIBLE else Visibility.GONE + +private fun assertExistingTabList() = + onView(CoreMatchers.allOf(ViewMatchers.withId(R.id.item_tab))) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + +private fun tabsListThreeDotButton() = onView(allOf(ViewMatchers.withId(R.id.tabs_overflow_button))) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt index b47ed7963..9408c41ed 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt @@ -8,7 +8,6 @@ package org.mozilla.fenix.ui.robots import android.net.Uri import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.pressImeActionButton import androidx.test.espresso.action.ViewActions.replaceText import androidx.test.espresso.matcher.ViewMatchers @@ -44,6 +43,15 @@ class NavigationToolbarRobot { ThreeDotMenuRobot().interact() return ThreeDotMenuRobot.Transition() } + + fun openNewTabAndEnterToBrowser(url: Uri, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + mDevice.wait(Until.findObject(By.descContains("Add tab")), waitingTime) + newTab().click() + awesomeBar().perform(replaceText(url.toString()), pressImeActionButton()) + + BrowserRobot().interact() + return BrowserRobot.Transition() + } } } @@ -55,3 +63,4 @@ fun navigationToolbar(interact: NavigationToolbarRobot.() -> Unit): NavigationTo private fun urlBar() = onView(ViewMatchers.withId(R.id.toolbar)) private fun awesomeBar() = onView(ViewMatchers.withId(R.id.mozac_browser_toolbar_edit_url_view)) private fun threeDotButton() = onView(ViewMatchers.withContentDescription("Menu")) +private fun newTab() = onView(ViewMatchers.withContentDescription("Add tab")) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabsRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabsRobot.kt deleted file mode 100644 index 35dd43d10..000000000 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabsRobot.kt +++ /dev/null @@ -1,23 +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/. */ - -@file:Suppress("TooManyFunctions") - -package org.mozilla.fenix.ui.robots - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.uiautomator.UiDevice - -class TabsRobot { - - // Tabs functions here - - class Transition { - private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) - - // Transition functions here - } -} - -// Locaters here diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuRobot.kt index d91bdcab3..fb1d39e60 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuRobot.kt @@ -7,7 +7,6 @@ package org.mozilla.fenix.ui.robots import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.assertion.ViewAssertions import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.isDisplayed @@ -33,6 +32,9 @@ class ThreeDotMenuRobot { fun verifyForwardButton() = assertForwardButton() fun verifyBackButton() = assertBackButton() fun verifyRefreshButton() = assertRefreshButton() + fun verifyCloseAllTabsButton() = assertCloseAllTabsButton() + fun verifyShareButton() = assertShareButton() + fun verifySaveCollection() = assertSaveCollectionButton() class Transition { @@ -85,6 +87,14 @@ class ThreeDotMenuRobot { BrowserRobot().interact() return BrowserRobot.Transition() } + + fun closeAllTabs(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { + mDevice.wait(Until.findObject(By.text("Close all tabs")), waitingTime) + closeAllTabsButton().click() + + HomeScreenRobot().interact() + return HomeScreenRobot.Transition() + } } } private fun threeDotMenuRecyclerViewExists() { @@ -92,24 +102,36 @@ private fun threeDotMenuRecyclerViewExists() { } private fun settingsButton() = onView(allOf(withText(R.string.settings))) private fun assertSettingsButton() = settingsButton() - .check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun libraryButton() = onView(allOf(withText(R.string.browser_menu_your_library))) private fun assertLibraryButton() = libraryButton() - .check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun helpButton() = onView(allOf(withText(R.string.browser_menu_help))) private fun assertHelpButton() = helpButton() - .check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun forwardButton() = onView(ViewMatchers.withContentDescription("Forward")) private fun assertForwardButton() = forwardButton() - .check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun backButton() = onView(ViewMatchers.withContentDescription("Back")) private fun assertBackButton() = backButton() - .check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun refreshButton() = onView(ViewMatchers.withContentDescription("Refresh")) private fun assertRefreshButton() = refreshButton() - .check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + +private fun closeAllTabsButton() = onView(allOf(withText("Close all tabs"))) +private fun assertCloseAllTabsButton() = closeAllTabsButton() + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + +private fun shareButton() = onView(allOf(withText("Share tabs"))) +private fun assertShareButton() = shareButton() + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + +private fun saveCollectionButton() = onView(allOf(withText("Save to collection"))) +private fun assertSaveCollectionButton() = saveCollectionButton() + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))