diff --git a/app/src/androidTest/assets/pages/generic1.html b/app/src/androidTest/assets/pages/generic1.html index bb10f49d9..778816fa6 100644 --- a/app/src/androidTest/assets/pages/generic1.html +++ b/app/src/androidTest/assets/pages/generic1.html @@ -1,4 +1,7 @@ + +Test_Page_1 +

Page content: 1

diff --git a/app/src/androidTest/assets/pages/generic2.html b/app/src/androidTest/assets/pages/generic2.html index d797672fc..975f1aec1 100644 --- a/app/src/androidTest/assets/pages/generic2.html +++ b/app/src/androidTest/assets/pages/generic2.html @@ -1,4 +1,7 @@ + + Test_Page_2 +

Page content: 2

diff --git a/app/src/androidTest/assets/pages/generic3.html b/app/src/androidTest/assets/pages/generic3.html index 1ac11415c..06eb5f36c 100644 --- a/app/src/androidTest/assets/pages/generic3.html +++ b/app/src/androidTest/assets/pages/generic3.html @@ -1,4 +1,7 @@ + + Test_Page_3 +

Page content: 3

diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt index c9773d020..0e4d9cf27 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt @@ -4,25 +4,37 @@ package org.mozilla.fenix.ui +import android.net.Uri +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.NoMatchingViewException +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.matcher.ViewMatchers import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice +import androidx.test.uiautomator.Until import okhttp3.mockwebserver.MockWebServer -import org.junit.Rule +import org.junit.Ignore import org.junit.Before import org.junit.After -import org.junit.Ignore import org.junit.Test +import org.junit.Rule +import org.mozilla.fenix.R import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.HomeActivityTestRule +import org.mozilla.fenix.helpers.TestAssetHelper +import org.mozilla.fenix.helpers.click +import org.mozilla.fenix.ui.robots.browserScreen +import org.mozilla.fenix.ui.robots.homeScreen +import org.mozilla.fenix.ui.robots.navigationToolbar /** - * Tests for verifying basic functionality of history + * Tests for verifying basic functionality of tab collection * */ class CollectionTest { /* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping. - private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) private lateinit var mockWebServer: MockWebServer @@ -42,31 +54,162 @@ class CollectionTest { mockWebServer.shutdown() } - @Ignore("not implemented") @Test - fun AddTabToCollectionTest() { - // open a webpage, and add currently opened tab to existing collection + @Ignore("Temp disable test - see: https://github.com/mozilla-mobile/fenix/issues/5793") + // open a webpage, and add currently opened tab to existing collection + fun addTabToCollectionTest() { + val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2) + + createCollection(firstWebPage.url, "testcollection_1") + + // Close the open tab + homeScreen { + verifyHomeScreen() + } + onView(ViewMatchers.withId(R.id.close_tab_button)).click() + + // On homeview, open another webpage + navigationToolbar { + }.enterURLAndEnterToBrowser(secondWebPage.url) { + verifyPageContent(secondWebPage.content) + } + + // Save the current page to the testcollection_1 + navigationToolbar { + }.openThreeDotMenu { + // click save to collection menu item, type collection name + clickBrowserViewSaveCollectionButton() + org.mozilla.fenix.ui.robots.mDevice.wait( + Until.findObject(By.text("testcollection_1")), + TestAssetHelper.waitingTime) + onView(ViewMatchers.withText("testcollection_1")).click() + mDevice.pressBack() // go to main page + } + + // close currently opened tab + homeScreen { + verifyHomeScreen() + onView(ViewMatchers.withId(R.id.close_tab_button)).click() + org.mozilla.fenix.ui.robots.mDevice.wait( + Until.findObject(By.text("testcollection_1")), + TestAssetHelper.waitingTime) + // On homeview, expand the collection and open the first saved page + onView(ViewMatchers.withText("testcollection_1")).click() + onView(ViewMatchers.withText("Test_Page_1")).click() + } + // Page content: 1 + browserScreen { + verifyPageContent("Page content: 1") + mDevice.pressBack() // go to main page + } + + // tab_in_collection_item + homeScreen { + verifyHomeScreen() + onView(ViewMatchers.withId(R.id.close_tab_button)).click() + // On homeview, expand the collection and open the first saved page + org.mozilla.fenix.ui.robots.mDevice.wait( + Until.findObject(By.text("Test_Page_2")), + TestAssetHelper.waitingTime) + onView(ViewMatchers.withText("Test_Page_2")).click() + } + + // Page content: 2 + browserScreen { + verifyPageContent("Page content: 2") + } } - @Ignore("not implemented") @Test - fun OpenTabFromCollectionTest() { - // Open one tab from Collection in the Homescreen view + @Ignore("Temp disable test - see: https://github.com/mozilla-mobile/fenix/issues/5793") + // Rename Collection from the Homescreen + fun renameCollectionTest() { + + val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + createCollection(firstWebPage.url, "testcollection_1") + + homeScreen { + // On homeview, tap the 3-dot button to expand, select rename, rename collection + clickCollectionThreeDotButton() + selectRenameCollection() + typeCollectionName("renamed_collection") + mDevice.wait(Until.findObject(By.text("renamed_collection")), TestAssetHelper.waitingTime) + // Verify the new name is displayed on homeview + onView(ViewMatchers.withText("renamed_collection")) + .check(ViewAssertions + .matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + } } - @Ignore("not implemented") @Test - fun RenameCollectionTest() { - // Rename Collection from the Homescreen + @Ignore("Temp disable test - see: https://github.com/mozilla-mobile/fenix/issues/5793") + // Delete Collection from the Homescreen + fun deleteCollectionTest() { + + val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + createCollection(firstWebPage.url, "testcollection_1") + + homeScreen { + // Choose delete collection from homeview, and confirm + clickCollectionThreeDotButton() + selectDeleteCollection() + confirmDeleteCollection() + + // Check for No collections caption + onView(ViewMatchers.withText("No collections")) + .check(ViewAssertions + .matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + } } - @Ignore("not implemented") @Test - fun DeleteCollectionTest() { - // Delete Collection from the Homescreen + @Ignore("Temp disable test - see: https://github.com/mozilla-mobile/fenix/issues/5793") + fun createCollectionTest() { + val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2) + + createCollection(firstWebPage.url, "testcollection_1") + createCollection(secondWebPage.url, "testcollection_2", false) + + // On the main screen, swipe to bottom until the collections are shown + homeScreen { + // swipe to bottom until the collections are shown + verifyHomeScreen() + try { + onView(ViewMatchers.withText("testcollection_1")) + .check(ViewAssertions + .matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + } catch (e: NoMatchingViewException) { + scrollToElementByText("testcollection_1") + } + onView(ViewMatchers.withText("testcollection_2")).check(ViewAssertions + .matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + } } - fun CreateCollection() { - // Open 3 webpages, and save each of them to a single collection + private fun createCollection(url: Uri, collectionName: String, firstCollection: Boolean = true) { + val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + // Open a webpage and save to collection "testcollection_1" + navigationToolbar { + }.enterURLAndEnterToBrowser(url) { + verifyPageContent(firstWebPage.content) + } + navigationToolbar { + }.openThreeDotMenu { + // click save to collection menu item, type collection name + clickBrowserViewSaveCollectionButton() + if (!firstCollection) + clickAddNewCollection() + + }.typeCollectionName(collectionName) {} + + mDevice.pressBack() // go to main page + org.mozilla.fenix.ui.robots.mDevice.wait( + Until.findObject(By.text(collectionName)), + TestAssetHelper.waitingTime) } } 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 dc1714910..5dc780875 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 @@ -51,6 +51,11 @@ class BrowserRobot { .check((matches(withText(containsString(expectedText))))) } + fun waitForCollectionSavedPopup() { + mDevice.wait(Until.findObject(By.text("Tab saved!")), + TestAssetHelper.waitingTime) + } + class Transition { private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) @@ -94,6 +99,10 @@ fun browserScreen(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { } private fun dismissOnboardingButton() = onView(withId(R.id.close_onboarding)) +fun dismissTrackingOnboarding() { + mDevice.wait(Until.findObject(By.res("close_onboarding")), TestAssetHelper.waitingTime) + dismissOnboardingButton().click() +} fun navURLBar() = onView(withId(R.id.mozac_browser_toolbar_url_view)) 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 939f48b29..a82cedd66 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 @@ -7,6 +7,7 @@ package org.mozilla.fenix.ui.robots import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.assertion.ViewAssertions.doesNotExist import androidx.test.espresso.assertion.ViewAssertions.matches @@ -14,7 +15,10 @@ 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.espresso.matcher.ViewMatchers.hasFocus import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.Until +import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.UiScrollable import androidx.test.uiautomator.UiSelector @@ -22,6 +26,8 @@ import org.hamcrest.CoreMatchers import org.hamcrest.Matchers.allOf import org.hamcrest.Matchers.containsString import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime +import org.mozilla.fenix.helpers.click /** * Implementation of Robot Pattern for the home screen menu. @@ -75,12 +81,34 @@ class HomeScreenRobot { fun verifyExistingTabList() = assertExistingTabList() - private fun scrollToElementByText(text: String): UiScrollable { + // Collections element + fun clickCollectionThreeDotButton() { + collectionThreeDotButton().click() + mDevice.wait(Until.findObject(By.text("Delete collection")), waitingTime) + } + fun selectRenameCollection() { + onView(allOf(ViewMatchers.withText("Rename collection"))).click() + mDevice.wait(Until.findObject(By.res("org.mozilla.fenix.debug:id/name_collection_edittext")), waitingTime) + } + fun selectDeleteCollection() { + onView(allOf(ViewMatchers.withText("Delete collection"))).click() + mDevice.wait(Until.findObject(By.res("message")), waitingTime) + } + fun confirmDeleteCollection() { + onView(allOf(ViewMatchers.withText("DELETE"))).click() + mDevice.wait(Until.findObject(By.res("org.mozilla.fenix.debug:id/collections_header")), waitingTime) + } + fun typeCollectionName(name: String) { + mDevice.wait(Until.findObject(By.res("org.mozilla.fenix.debug:id/name_collection_edittext")), waitingTime) + collectionNameTextField().check(matches(hasFocus())) + collectionNameTextField().perform(ViewActions.replaceText(name)) + collectionNameTextField().perform(ViewActions.pressImeActionButton()) + } + fun scrollToElementByText(text: String): UiScrollable { val appView = UiScrollable(UiSelector().scrollable(true)) appView.scrollTextIntoView(text) return appView } - fun swipeUpToDismissFirstRun() { scrollToElementByText("Start browsing") } @@ -321,3 +349,7 @@ private fun assertExistingTabList() = .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun tabsListThreeDotButton() = onView(allOf(ViewMatchers.withId(R.id.tabs_overflow_button))) + +private fun collectionThreeDotButton() = onView(allOf(ViewMatchers.withId(R.id.collection_overflow_button))) + +private fun collectionNameTextField() = onView(allOf(ViewMatchers.withResourceName("name_collection_edittext"), hasFocus())) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt index 2bfe630e8..88e5cafa7 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt @@ -7,11 +7,14 @@ package org.mozilla.fenix.ui.robots import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers -import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.espresso.matcher.ViewMatchers.hasFocus import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility import androidx.test.espresso.matcher.ViewMatchers.withResourceName import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.By @@ -44,6 +47,13 @@ class ThreeDotMenuMainRobot { fun verifyShareTabButton() = assertShareTabButton() fun verifySaveCollection() = assertSaveCollectionButton() + fun clickBrowserViewSaveCollectionButton() { + browserViewSaveCollectionButton().click() + } + fun clickAddNewCollection() { + addNewCollectionButton().click() + } + fun verifyCollectionNameTextField() = assertCollectionNameTextField() fun verifyFindInPageButton() = assertFindInPageButton() fun verifyShareScrim() = assertShareScrim() fun verifySendToDeviceTitle() = assertSendToDeviceTitle() @@ -125,6 +135,16 @@ class ThreeDotMenuMainRobot { BrowserRobot().interact() return BrowserRobot.Transition() } + + fun typeCollectionName(name: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + mDevice.wait(Until.findObject(By.res("org.mozilla.fenix.debug:id/name_collection_edittext")), waitingTime) + + collectionNameTextField().check(matches(hasFocus())) + collectionNameTextField().perform(ViewActions.replaceText(name), ViewActions.pressImeActionButton()) + + BrowserRobot().interact() + return BrowserRobot.Transition() + } } } @@ -134,43 +154,54 @@ private fun threeDotMenuRecyclerViewExists() { private fun settingsButton() = onView(allOf(withText(R.string.settings))) private fun assertSettingsButton() = settingsButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun libraryButton() = onView(allOf(withText(R.string.browser_menu_your_library))) private fun assertLibraryButton() = libraryButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun helpButton() = onView(allOf(withText(R.string.browser_menu_help))) private fun assertHelpButton() = helpButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun forwardButton() = onView(ViewMatchers.withContentDescription("Forward")) private fun assertForwardButton() = forwardButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun backButton() = onView(ViewMatchers.withContentDescription("Back")) private fun assertBackButton() = backButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun refreshButton() = onView(ViewMatchers.withContentDescription("Refresh")) private fun assertRefreshButton() = refreshButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun closeAllTabsButton() = onView(allOf(withText("Close all tabs"))) private fun assertCloseAllTabsButton() = closeAllTabsButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun shareTabButton() = onView(allOf(withText("Share tabs"))) private fun assertShareTabButton() = shareTabButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun shareButton() = onView(allOf(withText("Share"))) private fun assertShareButton() = shareButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + +private fun browserViewSaveCollectionButton() = onView(allOf(withText("Save to Collection"), + withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun saveCollectionButton() = onView(allOf(withText("Save to collection"))) private fun assertSaveCollectionButton() = saveCollectionButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + +private fun addNewCollectionButton() = onView(allOf(withText("Add new collection"))) +private fun assertaddNewCollectionButton() = addNewCollectionButton() + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + +private fun collectionNameTextField() = onView(allOf(withResourceName("name_collection_edittext"))) +private fun assertCollectionNameTextField() = collectionNameTextField() + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun findInPageButton() = onView(allOf(withText("Find in page"))) private fun assertFindInPageButton() = findInPageButton() @@ -183,7 +214,7 @@ private fun SendToDeviceTitle() = onView(allOf(withText("SEND TO DEVICE"), withResourceName("accountHeaderText"))) private fun assertSendToDeviceTitle() = SendToDeviceTitle() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun ShareALinkTitle() = onView(allOf(withText("SHARE A LINK"), withResourceName("link_header"))) @@ -192,4 +223,4 @@ private fun assertShareALinkTitle() = ShareALinkTitle() private fun whatsNewButton() = onView(allOf(withText("What's New"))) private fun assertWhatsNewButton() = whatsNewButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))