Refactor collections UI tests for Compose

pull/543/head
sv-ohorvath 2 years ago committed by mergify[bot]
parent 9b35c6fd45
commit 24fd376707

@ -16,6 +16,7 @@ class FeatureSettingsHelper {
private var isPocketEnabled: Boolean = settings.showPocketRecommendationsFeature
private var isJumpBackInCFREnabled: Boolean = settings.shouldShowJumpBackInCFR
private var isRecentTabsFeatureEnabled: Boolean = settings.showRecentTabsFeature
private var isRecentlyVisitedFeatureEnabled: Boolean = settings.historyMetadataUIFeature
private var isUserKnowsAboutPwasTrue: Boolean = settings.userKnowsAboutPwas
fun setPocketEnabled(enabled: Boolean) {
@ -30,6 +31,10 @@ class FeatureSettingsHelper {
settings.showRecentTabsFeature = enabled
}
fun setRecentlyVisitedFeatureEnabled(enabled: Boolean) {
settings.historyMetadataUIFeature = enabled
}
fun setStrictETPEnabled() {
settings.setStrictETP()
}
@ -49,6 +54,7 @@ class FeatureSettingsHelper {
settings.showPocketRecommendationsFeature = isPocketEnabled
settings.shouldShowJumpBackInCFR = isJumpBackInCFREnabled
settings.showRecentTabsFeature = isRecentTabsFeatureEnabled
settings.historyMetadataUIFeature = isRecentlyVisitedFeatureEnabled
settings.userKnowsAboutPwas = isUserKnowsAboutPwasTrue
}
}

@ -15,6 +15,7 @@ import org.mozilla.fenix.helpers.ext.toUri
object TestAssetHelper {
@Suppress("MagicNumber")
val waitingTime: Long = TimeUnit.SECONDS.toMillis(15)
val waitingTimeLong = TimeUnit.SECONDS.toMillis(25)
val waitingTimeShort: Long = TimeUnit.SECONDS.toMillis(3)
data class TestAsset(val url: Uri, val content: String, val title: String)

@ -4,19 +4,24 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
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.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.collectionRobot
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.tabDrawer
/**
* Tests for verifying basic functionality of tab collections
@ -24,24 +29,27 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
*/
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
private val firstCollectionName = "testcollection_1"
private val secondCollectionName = "testcollection_2"
private val collectionName = "First Collection"
private val featureSettingsHelper = FeatureSettingsHelper()
@get:Rule
val activityTestRule = HomeActivityTestRule()
val composeTestRule = AndroidComposeTestRule(
HomeActivityIntentTestRule(),
{ it.activity }
)
@Before
fun setUp() {
// disabling these features to have better visibility of Collections
// disabling these features to have better visibility of Collections,
// and to avoid multiple matches on tab items
featureSettingsHelper.setRecentTabsFeatureEnabled(false)
featureSettingsHelper.setPocketEnabled(false)
featureSettingsHelper.setJumpBackCFREnabled(false)
featureSettingsHelper.setRecentlyVisitedFeatureEnabled(false)
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
@ -57,6 +65,171 @@ class CollectionTest {
featureSettingsHelper.resetAllFeatureFlags()
}
@SmokeTest
@Test
fun createFirstCollectionTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
val secondWebPage = getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
mDevice.waitForIdle()
}.openTabDrawer {
}.openNewTab {
}.submitQuery(secondWebPage.url.toString()) {
mDevice.waitForIdle()
}.goToHomescreen {
swipeToBottom()
}.clickSaveTabsToCollectionButton {
longClickTab(firstWebPage.title)
selectTab(secondWebPage.title, numOfTabs = 2)
}.clickSaveCollection {
typeCollectionNameAndSave(collectionName)
}
tabDrawer {
verifySnackBarText("Collection saved!")
snackBarButtonClick("VIEW")
}
homeScreen {
verifyCollectionIsDisplayed(collectionName)
}
}
@SmokeTest
@Test
fun verifyExpandedCollectionItemsTest() {
val webPage = getGenericAsset(mockWebServer, 1)
val webPageUrl = webPage.url.host.toString()
navigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openTabDrawer {
createCollection(webPage.title, collectionName = collectionName)
snackBarButtonClick("VIEW")
}
homeScreen {
verifyCollectionIsDisplayed(collectionName)
}.expandCollection(collectionName, composeTestRule) {
verifyTabSavedInCollection(webPage.title)
verifyCollectionTabUrl(true, webPageUrl)
verifyShareCollectionButtonIsVisible(true)
verifyCollectionMenuIsVisible(true, composeTestRule)
verifyCollectionItemRemoveButtonIsVisible(webPage.title, true)
}.collapseCollection(collectionName) {}
collectionRobot {
verifyTabSavedInCollection(webPage.title, false)
verifyShareCollectionButtonIsVisible(false)
verifyCollectionMenuIsVisible(false, composeTestRule)
verifyCollectionTabUrl(false, webPageUrl)
verifyCollectionItemRemoveButtonIsVisible(webPage.title, false)
}
homeScreen {
}.expandCollection(collectionName, composeTestRule) {
verifyTabSavedInCollection(webPage.title)
verifyCollectionTabUrl(true, webPageUrl)
verifyShareCollectionButtonIsVisible(true)
verifyCollectionMenuIsVisible(true, composeTestRule)
verifyCollectionItemRemoveButtonIsVisible(webPage.title, true)
}.collapseCollection(collectionName) {}
collectionRobot {
verifyTabSavedInCollection(webPage.title, false)
verifyShareCollectionButtonIsVisible(false)
verifyCollectionMenuIsVisible(false, composeTestRule)
verifyCollectionTabUrl(false, webPageUrl)
verifyCollectionItemRemoveButtonIsVisible(webPage.title, false)
}
}
@SmokeTest
@Test
fun openAllTabsInCollectionTest() {
val firstTestPage = getGenericAsset(mockWebServer, 1)
val secondTestPage = getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstTestPage.url) {
waitForPageToLoad()
}.openTabDrawer {
}.openNewTab {
}.submitQuery(secondTestPage.url.toString()) {
waitForPageToLoad()
}.openTabDrawer {
createCollection(
firstTestPage.title,
secondTestPage.title,
collectionName = collectionName
)
closeTab()
}
homeScreen {
}.expandCollection(collectionName, composeTestRule) {
clickCollectionThreeDotButton(composeTestRule)
selectOpenTabs(composeTestRule)
}
tabDrawer {
verifyExistingOpenTabs(firstTestPage.title, secondTestPage.title)
}
}
@SmokeTest
@Test
fun shareCollectionTest() {
val firstWebsite = getGenericAsset(mockWebServer, 1)
val secondWebsite = getGenericAsset(mockWebServer, 2)
val sharingApp = "Gmail"
val urlString = "${secondWebsite.url}\n\n${firstWebsite.url}"
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebsite.url) {
}.openTabDrawer {
}.openNewTab {
}.submitQuery(secondWebsite.url.toString()) {
waitForPageToLoad()
}.openTabDrawer {
createCollection(firstWebsite.title, secondWebsite.title, collectionName = collectionName)
verifySnackBarText("Collection saved!")
}.openTabsListThreeDotMenu {
}.closeAllTabs {
}.expandCollection(collectionName, composeTestRule) {
}.clickShareCollectionButton {
verifyShareTabsOverlay(firstWebsite.title, secondWebsite.title)
verifySharingWithSelectedApp(sharingApp, urlString, collectionName)
}
}
@SmokeTest
@Test
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
fun deleteCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openTabDrawer {
createCollection(webPage.title, collectionName = collectionName)
snackBarButtonClick("VIEW")
}
homeScreen {
}.expandCollection(collectionName, composeTestRule) {
clickCollectionThreeDotButton(composeTestRule)
selectDeleteCollection(composeTestRule)
}
homeScreen {
verifySnackBarText("Collection deleted")
verifyNoCollectionsText()
}
}
@Test
// open a webpage, and add currently opened tab to existing collection
fun mainMenuSaveToExistingCollection() {
@ -66,7 +239,7 @@ class CollectionTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
}.openTabDrawer {
createCollection(firstWebPage.title, firstCollectionName)
createCollection(firstWebPage.title, collectionName = collectionName)
verifySnackBarText("Collection saved!")
}.closeTabDrawer {}
@ -75,12 +248,12 @@ class CollectionTest {
verifyPageContent(secondWebPage.content)
}.openThreeDotMenu {
}.openSaveToCollection {
}.selectExistingCollection(firstCollectionName) {
}.selectExistingCollection(collectionName) {
verifySnackBarText("Tab saved!")
// }.goToHomescreen {
// }.expandCollection(firstCollectionName) {
// verifyTabSavedInCollection(firstWebPage.title)
// verifyTabSavedInCollection(secondWebPage.title)
}.goToHomescreen {
}.expandCollection(collectionName, composeTestRule) {
verifyTabSavedInCollection(firstWebPage.title)
verifyTabSavedInCollection(secondWebPage.title)
}
}
@ -92,7 +265,7 @@ class CollectionTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
}.openTabDrawer {
createCollection(firstWebPage.title, firstCollectionName)
createCollection(firstWebPage.title, collectionName = collectionName)
verifySnackBarText("Collection saved!")
closeTab()
}
@ -100,117 +273,131 @@ class CollectionTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(secondWebPage.url) {
}.goToHomescreen {
// }.expandCollection(firstCollectionName) {
// clickCollectionThreeDotButton()
// selectAddTabToCollection()
// verifyTabsSelectedCounterText(1)
// saveTabsSelectedForCollection()
// verifySnackBarText("Tab saved!")
// verifyTabSavedInCollection(secondWebPage.title)
}.expandCollection(collectionName, composeTestRule) {
clickCollectionThreeDotButton(composeTestRule)
selectAddTabToCollection(composeTestRule)
verifyTabsSelectedCounterText(1)
saveTabsSelectedForCollection()
verifySnackBarText("Tab saved!")
verifyTabSavedInCollection(secondWebPage.title)
}
}
@Test
fun renameCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openTabDrawer {
createCollection(webPage.title, collectionName = firstCollectionName)
verifySnackBarText("Collection saved!")
}.closeTabDrawer {
}.goToHomescreen {
}.expandCollection(firstCollectionName, composeTestRule) {
clickCollectionThreeDotButton(composeTestRule)
selectRenameCollection(composeTestRule)
}.typeCollectionNameAndSave(secondCollectionName) {}
homeScreen {
verifyCollectionIsDisplayed(secondCollectionName)
}
}
@Test
fun createSecondCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openTabDrawer {
createCollection(webPage.title, collectionName = firstCollectionName)
verifySnackBarText("Collection saved!")
createCollection(
webPage.title, collectionName = secondCollectionName,
firstCollection = false
)
verifySnackBarText("Collection saved!")
}.closeTabDrawer {
}.goToHomescreen {
verifyCollectionIsDisplayed(firstCollectionName)
verifyCollectionIsDisplayed(secondCollectionName)
}
}
@Test
fun removeTabFromCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openTabDrawer {
createCollection(webPage.title, collectionName = collectionName)
closeTab()
}
homeScreen {
}.expandCollection(collectionName, composeTestRule) {
verifyTabSavedInCollection(webPage.title, true)
removeTabFromCollection(webPage.title)
verifyTabSavedInCollection(webPage.title, false)
}
homeScreen {
verifyCollectionIsDisplayed(collectionName, false)
}
}
@Test
fun swipeLeftToRemoveTabFromCollectionTest() {
val testPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.url) {
waitForPageToLoad()
}.openTabDrawer {
createCollection(
testPage.title,
collectionName = collectionName
)
closeTab()
}
homeScreen {
}.expandCollection(collectionName, composeTestRule) {
swipeToBottom()
swipeTabLeft(testPage.title, composeTestRule)
verifyTabSavedInCollection(testPage.title, false)
}
homeScreen {
verifyCollectionIsDisplayed(collectionName, false)
}
}
@Test
fun swipeRightToRemoveTabFromCollectionTest() {
val testPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.url) {
waitForPageToLoad()
}.openTabDrawer {
createCollection(
testPage.title,
collectionName = collectionName
)
closeTab()
}
homeScreen {
}.expandCollection(collectionName, composeTestRule) {
swipeToBottom()
swipeTabRight(testPage.title, composeTestRule)
verifyTabSavedInCollection(testPage.title, false)
}
homeScreen {
verifyCollectionIsDisplayed(collectionName, false)
}
}
// @Test
// fun renameCollectionTest() {
// val webPage = getGenericAsset(mockWebServer, 1)
//
// navigationToolbar {
// }.enterURLAndEnterToBrowser(webPage.url) {
// }.openTabDrawer {
// createCollection(webPage.title, firstCollectionName)
// verifySnackBarText("Collection saved!")
// }.closeTabDrawer {
// }.goToHomescreen {
// }.expandCollection(firstCollectionName) {
// clickCollectionThreeDotButton()
// selectRenameCollection()
// }.typeCollectionNameAndSave("renamed_collection") {}
//
// homeScreen {
// verifyCollectionIsDisplayed("renamed_collection")
// }
// }
// @Test
// fun createSecondCollectionTest() {
// val webPage = getGenericAsset(mockWebServer, 1)
//
// navigationToolbar {
// }.enterURLAndEnterToBrowser(webPage.url) {
// }.openTabDrawer {
// createCollection(webPage.title, firstCollectionName)
// verifySnackBarText("Collection saved!")
// createCollection(webPage.title, secondCollectionName, false)
// verifySnackBarText("Collection saved!")
// }.closeTabDrawer {
// }.goToHomescreen {}
//
// homeScreen {
// verifyCollectionIsDisplayed(firstCollectionName)
// verifyCollectionIsDisplayed(secondCollectionName)
// }
// }
// @Test
// fun removeTabFromCollectionTest() {
// val webPage = getGenericAsset(mockWebServer, 1)
//
// navigationToolbar {
// }.enterURLAndEnterToBrowser(webPage.url) {
// }.openTabDrawer {
// createCollection(webPage.title, firstCollectionName)
// verifySnackBarText("Collection saved!")
// closeTab()
// }
//
// homeScreen {
// }.expandCollection(firstCollectionName) {
// removeTabFromCollection(webPage.title)
// verifyTabSavedInCollection(webPage.title, false)
// }
// // To add this step when https://github.com/mozilla-mobile/fenix/issues/13177 is fixed
// // homeScreen {
// // verifyCollectionIsDisplayed(firstCollectionName, false)
// // }
// }
// @Test
// fun swipeToRemoveTabFromCollectionTest() {
// val firstWebPage = getGenericAsset(mockWebServer, 1)
// val secondWebPage = getGenericAsset(mockWebServer, 2)
//
// navigationToolbar {
// }.enterURLAndEnterToBrowser(firstWebPage.url) {
// }.openTabDrawer {
// createCollection(firstWebPage.title, firstCollectionName)
// verifySnackBarText("Collection saved!")
// closeTab()
// }
//
// navigationToolbar {
// }.enterURLAndEnterToBrowser(secondWebPage.url) {
// }.openThreeDotMenu {
// }.openSaveToCollection {
// }.selectExistingCollection(firstCollectionName) {
// }.openTabDrawer {
// closeTab()
// }
//
// homeScreen {
// }.expandCollection(firstCollectionName) {
// swipeToBottom()
// swipeCollectionItemLeft(firstWebPage.title)
// verifyTabSavedInCollection(firstWebPage.title, false)
// swipeCollectionItemRight(secondWebPage.title)
// verifyTabSavedInCollection(secondWebPage.title, false)
// }
// To add this step when https://github.com/mozilla-mobile/fenix/issues/13177 is fixed
// homeScreen {
// verifyCollectionIsDisplayed(firstCollectionName, false)
// }
// }
@Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/24997")
@Test
fun selectTabOnLongTapTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
@ -218,83 +405,84 @@ class CollectionTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
waitForPageToLoad()
}.openTabDrawer {
}.openNewTab {
}.submitQuery(secondWebPage.url.toString()) {
mDevice.waitForIdle()
waitForPageToLoad()
}.openTabDrawer {
verifyExistingOpenTabs(firstWebPage.title, secondWebPage.title)
longClickTab(firstWebPage.title)
verifyTabsMultiSelectionCounter(1)
selectTab(secondWebPage.title)
verifyTabsMultiSelectionCounter(2)
selectTab(secondWebPage.title, numOfTabs = 2)
}.clickSaveCollection {
typeCollectionNameAndSave(firstCollectionName)
typeCollectionNameAndSave(collectionName)
verifySnackBarText("Tabs saved!")
}
// tabDrawer {
// }.closeTabDrawer {
// }.goToHomescreen {
// }.expandCollection(firstCollectionName) {
// verifyTabSavedInCollection(firstWebPage.title)
// verifyTabSavedInCollection(secondWebPage.title)
// }
tabDrawer {
}.closeTabDrawer {
}.goToHomescreen {
}.expandCollection(collectionName, composeTestRule) {
verifyTabSavedInCollection(firstWebPage.title)
verifyTabSavedInCollection(secondWebPage.title)
}
}
@Test
fun navigateBackInCollectionFlowTest() {
val webPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openTabDrawer {
createCollection(webPage.title, collectionName = collectionName)
verifySnackBarText("Collection saved!")
}.closeTabDrawer {
}.openThreeDotMenu {
}.openSaveToCollection {
verifySelectCollectionScreen()
goBackInCollectionFlow()
}
browserScreen {
}.openThreeDotMenu {
}.openSaveToCollection {
verifySelectCollectionScreen()
clickAddNewCollection()
verifyCollectionNameTextField()
goBackInCollectionFlow()
verifySelectCollectionScreen()
goBackInCollectionFlow()
}
// verify the browser layout is visible
browserScreen {
verifyMenuButton()
}
}
// @Test
// fun navigateBackInCollectionFlowTest() {
// val webPage = getGenericAsset(mockWebServer, 1)
//
// navigationToolbar {
// }.enterURLAndEnterToBrowser(webPage.url) {
// }.openTabDrawer {
// createCollection(webPage.title, firstCollectionName)
// verifySnackBarText("Collection saved!")
// }.closeTabDrawer {
// }.openThreeDotMenu {
// }.openSaveToCollection {
// verifySelectCollectionScreen()
// goBackInCollectionFlow()
// }
//
// browserScreen {
// }.openThreeDotMenu {
// }.openSaveToCollection {
// verifySelectCollectionScreen()
// clickAddNewCollection()
// verifyCollectionNameTextField()
// goBackInCollectionFlow()
// verifySelectCollectionScreen()
// goBackInCollectionFlow()
// }
// // verify the browser layout is visible
// browserScreen {
// verifyMenuButton()
// }
// }
// @SmokeTest
// @Test
// fun undoDeleteCollectionTest() {
// val webPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
//
// navigationToolbar {
// }.enterURLAndEnterToBrowser(webPage.url) {
// }.openTabDrawer {
// createCollection(webPage.title, firstCollectionName)
// snackBarButtonClick("VIEW")
// }
//
// homeScreen {
// }.expandCollection(firstCollectionName) {
// clickCollectionThreeDotButton()
// selectDeleteCollection()
// }
//
// homeScreen {
// verifySnackBarText("Collection deleted")
// clickUndoCollectionDeletion("UNDO")
// verifyCollectionIsDisplayed(firstCollectionName, true)
// }
// }
@SmokeTest
@Test
fun undoDeleteCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openTabDrawer {
createCollection(webPage.title, collectionName = collectionName)
snackBarButtonClick("VIEW")
}
homeScreen {
}.expandCollection(collectionName, composeTestRule) {
clickCollectionThreeDotButton(composeTestRule)
selectDeleteCollection(composeTestRule)
}
homeScreen {
verifySnackBarText("Collection deleted")
clickUndoCollectionDeletion("UNDO")
verifyCollectionIsDisplayed(collectionName, true)
}
}
}

@ -4,52 +4,58 @@
package org.mozilla.fenix.ui.robots
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.hasContentDescription
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.ComposeTestRule
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTouchInput
import androidx.compose.ui.test.swipeLeft
import androidx.compose.ui.test.swipeRight
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.replaceText
import androidx.test.espresso.action.ViewActions.swipeLeft
import androidx.test.espresso.action.ViewActions.swipeRight
import androidx.test.espresso.action.ViewActions.swipeUp
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.hasSibling
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
import androidx.test.espresso.NoMatchingViewException
import androidx.test.espresso.action.ViewActions.pressImeActionButton
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiScrollable
import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import org.hamcrest.Matchers.allOf
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText
import org.mozilla.fenix.helpers.click
import org.mozilla.fenix.helpers.ext.waitNotNull
class CollectionRobot {
fun verifySelectCollectionScreen() {
onView(withText("Select collection"))
.check(matches(isDisplayed()))
onView(withId(R.id.collections_list))
.check(matches(isDisplayed()))
onView(withText("Add new collection"))
.check(matches(isDisplayed()))
assertTrue(
mDevice.findObject(UiSelector().text("Select collection"))
.exists()
)
assertTrue(
mDevice.findObject(UiSelector().resourceId("$packageName:id/collections_list"))
.exists()
)
assertTrue(
mDevice.findObject(UiSelector().text("Add new collection"))
.exists()
)
}
fun clickAddNewCollection() = addNewCollectionButton().click()
fun verifyCollectionNameTextField() {
mainMenuEditCollectionNameField().check(matches(isDisplayed()))
assertTrue(
mainMenuEditCollectionNameField().waitForExists(waitingTime)
)
}
// names a collection saved from tab drawer
fun typeCollectionNameAndSave(collectionName: String) {
collectionNameTextField().perform(replaceText(collectionName))
collectionNameTextField().text = collectionName
mDevice.findObject(UiSelector().textContains("OK")).click()
}
@ -57,141 +63,115 @@ class CollectionRobot {
mDevice.findObject(UiSelector().text("Select tabs to save"))
.waitUntilGone(waitingTime)
val tabsCounter = onView(withId(R.id.bottom_bar_text))
val tabsCounter = mDevice.findObject(UiSelector().resourceId("$packageName:id/bottom_bar_text"))
when (numOfTabs) {
1 -> tabsCounter.check(matches(withText("$numOfTabs tab selected")))
2 -> tabsCounter.check(matches(withText("$numOfTabs tabs selected")))
1 -> assertTrue(tabsCounter.text.equals("$numOfTabs tab selected"))
2 -> assertTrue(tabsCounter.text.equals("$numOfTabs tabs selected"))
}
}
fun saveTabsSelectedForCollection() {
onView(withId(R.id.save_button)).click()
mDevice.findObject(UiSelector().resourceId("$packageName:id/save_button")).click()
}
fun verifyTabSavedInCollection(title: String, visible: Boolean = true) {
if (visible) {
scrollToElementByText(title)
collectionItem(title)
.check(
matches(isDisplayed())
)
assertTrue(
collectionListItem(title).waitForExists(waitingTime)
)
} else
collectionItem(title)
.check(doesNotExist())
assertTrue(
collectionListItem(title).waitUntilGone(waitingTime)
)
}
fun verifyCollectionTabUrl(visible: Boolean) {
onView(withId(R.id.caption))
.check(
if (visible) matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))
else doesNotExist()
)
fun verifyCollectionTabUrl(visible: Boolean, url: String) {
val tabUrl = mDevice.findObject(UiSelector().text(url))
if (visible) {
assertTrue(tabUrl.exists())
} else {
assertFalse(tabUrl.exists())
}
}
fun verifyCollectionTabLogo(visible: Boolean) {
onView(withId(R.id.favicon))
.check(
if (visible) matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))
else doesNotExist()
)
fun verifyShareCollectionButtonIsVisible(visible: Boolean) {
if (visible) {
assertTrue(shareCollectionButton().exists())
} else {
assertFalse(shareCollectionButton().exists())
}
}
// fun verifyShareCollectionButtonIsVisible(visible: Boolean) {
// shareCollectionButton()
// .check(
// if (visible) matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))
// else matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))
// )
// }
// fun verifyCollectionMenuIsVisible(visible: Boolean) {
// collectionThreeDotButton()
// .check(
// if (visible) matches(
// withEffectiveVisibility(
// ViewMatchers.Visibility.VISIBLE
// )
// )
// else matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))
// )
// }
// fun clickCollectionThreeDotButton() {
// collectionThreeDotButton().click()
// mDevice.waitNotNull(
// Until.findObject(By.text("Delete collection")),
// waitingTime
// )
// }
fun selectOpenTabs() {
onView(withText("Open tabs")).click()
fun verifyCollectionMenuIsVisible(visible: Boolean, rule: ComposeTestRule) {
if (visible) {
collectionThreeDotButton(rule)
.assertExists()
.assertIsDisplayed()
} else {
collectionThreeDotButton(rule)
.assertDoesNotExist()
}
}
fun selectRenameCollection() {
onView(withText("Rename collection")).click()
mDevice.waitNotNull(Until.findObject(By.text("Rename collection")))
fun clickCollectionThreeDotButton(rule: ComposeTestRule) {
collectionThreeDotButton(rule)
.assertIsDisplayed()
.performClick()
}
fun selectAddTabToCollection() {
onView(withText("Add tab")).click()
mDevice.waitNotNull(Until.findObject(By.text("Select Tabs")))
fun selectOpenTabs(rule: ComposeTestRule) {
rule.onNode(hasText("Open tabs"))
.assertIsDisplayed()
.performClick()
}
fun selectDeleteCollection() {
onView(withText("Delete collection")).click()
fun selectRenameCollection(rule: ComposeTestRule) {
rule.onNode(hasText("Rename collection"))
.assertIsDisplayed()
.performClick()
mainMenuEditCollectionNameField().waitForExists(waitingTime)
}
fun confirmDeleteCollection() {
onView(withText("DELETE")).click()
mDevice.waitNotNull(
Until.findObject(By.res("$packageName:id/no_collections_header")),
waitingTime
)
fun selectAddTabToCollection(rule: ComposeTestRule) {
rule.onNode(hasText("Add tab"))
.assertIsDisplayed()
.performClick()
mDevice.waitNotNull(Until.findObject(By.text("Select Tabs")))
}
fun selectDeleteCollection(rule: ComposeTestRule) {
rule.onNode(hasText("Delete collection"))
.assertIsDisplayed()
.performClick()
}
fun verifyCollectionItemRemoveButtonIsVisible(title: String, visible: Boolean) {
removeTabFromCollectionButton(title)
.check(
if (visible) matches(
withEffectiveVisibility(
ViewMatchers.Visibility.VISIBLE
)
)
else doesNotExist()
if (visible) {
assertTrue(
removeTabFromCollectionButton(title).exists()
)
} else {
assertFalse(
removeTabFromCollectionButton(title).exists()
)
}
}
fun removeTabFromCollection(title: String) = removeTabFromCollectionButton(title).click()
fun swipeCollectionItemRight(title: String) {
scrollToElementByText(title)
// Swipping can sometimes fail to remove the tab, so if the tab still exists, we need to repeat it
var retries = 0 // number of retries before failing, will stop at 2
while (mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/label")
.text(title)
).exists() && retries < 2
) {
collectionItem(title).perform(swipeRight())
retries++
}
fun swipeTabLeft(title: String, rule: ComposeTestRule) {
rule.onNode(hasText(title), useUnmergedTree = true)
.performTouchInput { swipeLeft() }
rule.waitForIdle()
}
fun swipeCollectionItemLeft(title: String) {
scrollToElementByText(title)
// Swipping can sometimes fail to remove the tab, so if the tab still exists, we need to repeat it
var retries = 0 // number of retries before failing, will stop at 2
while (mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/label")
.text(title)
).exists() && retries < 2
) {
collectionItem(title).perform(swipeLeft())
retries++
}
fun swipeTabRight(title: String, rule: ComposeTestRule) {
rule.onNode(hasText(title), useUnmergedTree = true)
.performTouchInput { swipeRight() }
rule.waitForIdle()
}
fun verifySnackBarText(expectedText: String) {
@ -200,61 +180,62 @@ class CollectionRobot {
fun goBackInCollectionFlow() = backButton().click()
fun swipeToBottom() = onView(withId(R.id.sessionControlRecyclerView)).perform(swipeUp())
fun swipeToBottom() =
UiScrollable(
UiSelector().resourceId("$packageName:id/sessionControlRecyclerView")
).scrollToEnd(3)
class Transition {
// fun collapseCollection(
// title: String,
// interact: HomeScreenRobot.() -> Unit
// ): HomeScreenRobot.Transition {
// try {
// mDevice.waitNotNull(Until.findObject(By.text(title)), waitingTime)
// onView(allOf(withId(R.id.chevron), hasSibling(withText(title)))).click()
// } catch (e: NoMatchingViewException) {
// scrollToElementByText(title)
// }
//
// HomeScreenRobot().interact()
// return HomeScreenRobot.Transition()
// }
//
// // names a collection saved from the 3dot menu
// fun typeCollectionNameAndSave(
// name: String,
// interact: BrowserRobot.() -> Unit
// ): BrowserRobot.Transition {
// mDevice.findObject(UiSelector().resourceId("$packageName:id/name_collection_edittext"))
// .waitForExists(waitingTime)
//
// mainMenuEditCollectionNameField().perform(
// replaceText(name),
// pressImeActionButton()
// )
//
// // wait for the collection creation wrapper to be dismissed
// mDevice.waitNotNull(Until.gone(By.res("$packageName:id/createCollectionWrapper")))
//
// BrowserRobot().interact()
// return BrowserRobot.Transition()
// }
fun collapseCollection(
title: String,
interact: HomeScreenRobot.() -> Unit
): HomeScreenRobot.Transition {
try {
collectionTitle(title).waitForExists(waitingTime)
collectionTitle(title).click()
} catch (e: NoMatchingViewException) {
scrollToElementByText(title)
collectionTitle(title).click()
}
HomeScreenRobot().interact()
return HomeScreenRobot.Transition()
}
// names a collection saved from the 3dot menu
fun typeCollectionNameAndSave(
name: String,
interact: BrowserRobot.() -> Unit
): BrowserRobot.Transition {
mainMenuEditCollectionNameField().waitForExists(waitingTime)
mainMenuEditCollectionNameField().text = name
onView(withId(R.id.name_collection_edittext)).perform(pressImeActionButton())
// wait for the collection creation wrapper to be dismissed
mDevice.waitNotNull(Until.gone(By.res("$packageName:id/createCollectionWrapper")))
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun selectExistingCollection(
title: String,
interact: BrowserRobot.() -> Unit
): BrowserRobot.Transition {
mDevice.waitNotNull(Until.findObject(By.text(title)), waitingTime)
onView(withText(title)).click()
collectionTitle(title).waitForExists(waitingTime)
collectionTitle(title).click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
// fun clickShareCollectionButton(interact: ShareOverlayRobot.() -> Unit): ShareOverlayRobot.Transition {
// shareCollectionButton().click()
//
// ShareOverlayRobot().interact()
// return ShareOverlayRobot.Transition()
// }
fun clickShareCollectionButton(interact: ShareOverlayRobot.() -> Unit): ShareOverlayRobot.Transition {
shareCollectionButton().waitForExists(waitingTime)
shareCollectionButton().click()
ShareOverlayRobot().interact()
return ShareOverlayRobot.Transition()
}
}
}
@ -263,30 +244,46 @@ fun collectionRobot(interact: CollectionRobot.() -> Unit): CollectionRobot.Trans
return CollectionRobot.Transition()
}
// private fun collectionThreeDotButton() =
// onView(withId(R.id.collection_overflow_button))
private fun collectionTitle(title: String) =
mDevice.findObject(
UiSelector()
.text(title)
)
private fun collectionItem(title: String) =
onView(allOf(withId(R.id.label), withText(title)))
private fun collectionThreeDotButton(rule: ComposeTestRule) =
rule.onNode(hasContentDescription("Collection menu"))
// private fun shareCollectionButton() = onView(withId(R.id.collection_share_button))
private fun collectionListItem(title: String) = mDevice.findObject(UiSelector().text(title))
private fun shareCollectionButton() =
mDevice.findObject(
UiSelector().description("Share")
)
private fun removeTabFromCollectionButton(title: String) =
onView(
allOf(
withId(R.id.secondary_button),
hasSibling(withText(title))
)
mDevice.findObject(
UiSelector().text(title)
).getFromParent(
UiSelector()
.description("Remove tab from collection")
)
// collection name text field, opened from tab drawer
private fun collectionNameTextField() = onView(withId(R.id.collection_name))
private fun collectionNameTextField() =
mDevice.findObject(
UiSelector().resourceId("$packageName:id/collection_name")
)
// collection name text field, opened from main menu
// collection name text field, when saving from the main menu option
private fun mainMenuEditCollectionNameField() =
onView(withId(R.id.name_collection_edittext))
mDevice.findObject(
UiSelector().resourceId("$packageName:id/name_collection_edittext")
)
private fun addNewCollectionButton() = onView(withText("Add new collection"))
private fun addNewCollectionButton() =
mDevice.findObject(UiSelector().text("Add new collection"))
private fun backButton() =
onView(withId(R.id.back_button))
mDevice.findObject(
UiSelector().resourceId("$packageName:id/back_button")
)

@ -8,6 +8,10 @@ package org.mozilla.fenix.ui.robots
import android.graphics.Bitmap
import android.widget.EditText
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.ComposeTestRule
import androidx.compose.ui.test.performClick
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions
@ -42,6 +46,7 @@ import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.Constants.LISTS_MAXSWIPES
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.appContext
@ -189,8 +194,6 @@ class HomeScreenRobot {
}
}
fun verifyCollectionIcon() = onView(withId(R.id.collection_icon)).check(matches(isDisplayed()))
fun togglePrivateBrowsingModeOnOff() {
onView(ViewMatchers.withResourceName("privateBrowsingButton"))
.perform(click())
@ -392,21 +395,15 @@ class HomeScreenRobot {
return TabDrawerRobot.Transition()
}
// fun expandCollection(
// title: String,
// interact: CollectionRobot.() -> Unit
// ): CollectionRobot.Transition {
// // Depending on the screen dimensions collections might report as visible on screen
// // but actually have the bottom toolbar above so interactions with collections might fail.
// // As a quick solution we'll try scrolling to the element below collection on the homescreen
// // so that they are displayed above in their entirety.
// scrollToElementByText(appContext.getString(R.string.pocket_stories_header_1))
//
// collectionTitle(title).click()
//
// CollectionRobot().interact()
// return CollectionRobot.Transition()
// }
fun expandCollection(title: String, rule: ComposeTestRule, interact: CollectionRobot.() -> Unit): CollectionRobot.Transition {
homeScreenList().scrollToEnd(LISTS_MAXSWIPES)
collectionTitle(title, rule)
.assertIsDisplayed()
.performClick()
CollectionRobot().interact()
return CollectionRobot.Transition()
}
fun openRecentlyVisitedSearchGroupHistoryList(title: String, interact: HistoryRobot.() -> Unit): HistoryRobot.Transition {
val searchGroup = recentlyVisitedList.getChildByText(UiSelector().text(title), title, true)
@ -649,6 +646,9 @@ private fun assertPrivateSessionMessage() =
).waitForExists(waitingTime)
)
private fun collectionTitle(title: String, rule: ComposeTestRule) =
rule.onNode(hasText(title))
private fun assertExistingTopSitesList() =
onView(allOf(withId(R.id.top_sites_list)))
.check((matches(withEffectiveVisibility(Visibility.VISIBLE))))

@ -49,8 +49,13 @@ class ShareOverlayRobot {
mDevice.waitNotNull(Until.findObject(By.res("android:id/resolver_list")))
}
fun selectAppToShareWith(appName: String) =
mDevice.findObject(UiSelector().text(appName)).clickAndWaitForNewWindow()
fun verifySharingWithSelectedApp(appName: String, content: String, subject: String) {
val sharingApp = mDevice.findObject(UiSelector().text(appName))
if (sharingApp.exists()) {
sharingApp.clickAndWaitForNewWindow()
verifySharedTabsIntent(content, subject)
}
}
fun verifySendToDeviceTitle() = assertSendToDeviceTitle()

@ -7,6 +7,7 @@
package org.mozilla.fenix.ui.robots
import android.content.Context
import android.text.TextUtils.indexOf
import android.view.View
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso
@ -41,9 +42,9 @@ import org.hamcrest.CoreMatchers.anyOf
import org.hamcrest.CoreMatchers.containsString
import org.hamcrest.Matcher
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeLong
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText
import org.mozilla.fenix.helpers.click
@ -77,7 +78,7 @@ class TabDrawerRobot {
assertPrivateBrowsingButtonIsSelected(isSelected)
fun verifySyncedTabsButtonIsSelected(isSelected: Boolean) =
assertSyncedTabsButtonIsSelected(isSelected)
fun verifyExistingOpenTabs(title: String) = assertExistingOpenTabs(title)
fun verifyExistingOpenTabs(vararg titles: String) = assertExistingOpenTabs(*titles)
fun verifyCloseTabsButton(title: String) = assertCloseTabsButton(title)
fun verifyExistingTabList() = assertExistingTabList()
@ -229,28 +230,28 @@ class TabDrawerRobot {
tabMediaControlButton().click()
}
private fun clickSelectTabs() {
fun clickSelectTabsOption() {
threeDotMenu().click()
mDevice.waitNotNull(
findObject(
text(getStringResource(R.string.tabs_tray_select_tabs))
),
waitingTime
)
val selectTabsButton = mDevice.findObject(text(getStringResource(R.string.tabs_tray_select_tabs)))
val selectTabsButton = mDevice.findObject(UiSelector().text("Select tabs"))
selectTabsButton.waitForExists(waitingTime)
selectTabsButton.click()
}
fun selectTab(title: String) {
mDevice.waitNotNull(
findObject(text(title)),
waitingTime
fun selectTab(title: String, tabsSelected: Int) {
val tab = mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/tab_item")
.childSelector(UiSelector().text(title))
)
val tab = mDevice.findObject(text(title))
tab.waitForExists(waitingTime)
tab.click()
try {
verifyTabsMultiSelectionCounter(tabsSelected)
} catch (e: AssertionError) {
tab.click()
verifyTabsMultiSelectionCounter(tabsSelected)
}
}
fun longClickTab(title: String) {
@ -264,13 +265,15 @@ class TabDrawerRobot {
}
fun createCollection(
tabTitle: String,
vararg tabTitle: String,
collectionName: String,
firstCollection: Boolean = true
) {
clickSelectTabs()
selectTab(tabTitle)
tabDrawer {
clickSelectTabsOption()
for (tab in tabTitle) {
selectTab(tab, tabTitle.indexOf(tab) + 1)
}
}.clickSaveCollection {
if (!firstCollection)
clickAddNewCollection()
@ -489,32 +492,27 @@ private fun syncedTabsButton() = onView(withContentDescription("Synced tabs"))
private fun newTabButton() = mDevice.findObject(UiSelector().resourceId("$packageName:id/new_tab_button"))
private fun threeDotMenu() = onView(withId(R.id.tab_tray_overflow))
private fun assertExistingOpenTabs(title: String) {
try {
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/mozac_browser_tabstray_title")
.textContains(title)
)
.waitForExists(waitingTime)
assertTrue(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/mozac_browser_tabstray_title")
.textContains(title)
).waitForExists(waitingTime)
)
} catch (e: AssertionError) {
println("The tab wasn't found")
mDevice.findObject(UiSelector().resourceId("$packageName:id/tabsTray")).swipeUp(2)
assertTrue(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/mozac_browser_tabstray_title")
.textContains(title)
).waitForExists(waitingTime)
)
private fun assertExistingOpenTabs(vararg tabTitles: String) {
for (title in tabTitles) {
try {
assertTrue(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/mozac_browser_tabstray_title")
.textContains(title)
).waitForExists(waitingTimeLong)
)
} catch (e: AssertionError) {
println("The tab wasn't found")
mDevice.findObject(UiSelector().resourceId("$packageName:id/tabsTray")).swipeUp(2)
assertTrue(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/mozac_browser_tabstray_title")
.textContains(title)
).waitForExists(waitingTime)
)
}
}
}

Loading…
Cancel
Save