diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt index 074a5fd99..71f745669 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt @@ -4,7 +4,9 @@ package org.mozilla.fenix.helpers +import android.content.ActivityNotFoundException import android.content.Context +import android.content.Intent import android.net.Uri import android.os.Build import android.preference.PreferenceManager @@ -12,6 +14,7 @@ import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.longClick import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.By import androidx.test.uiautomator.UiScrollable import androidx.test.uiautomator.UiSelector @@ -48,6 +51,14 @@ object TestHelper { editor.apply() } + fun restartApp(activity: HomeActivityTestRule) { + with(activity) { + finishActivity() + mDevice.waitForIdle() + launchActivity(null) + } + } + fun getPermissionAllowID(): String { return when (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { @@ -62,4 +73,20 @@ object TestHelper { TestAssetHelper.waitingTime ) } + + fun openAppFromExternalLink(url: String) { + val context = InstrumentationRegistry.getInstrumentation().getTargetContext() + val intent = Intent().apply { + action = Intent.ACTION_VIEW + data = Uri.parse(url) + `package` = "org.mozilla.fenix.debug" + flags = Intent.FLAG_ACTIVITY_NEW_TASK + } + try { + context.startActivity(intent) + } catch (ex: ActivityNotFoundException) { + intent.setPackage(null) + context.startActivity(intent) + } + } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt index 0a7566a57..3cda0f882 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt @@ -7,15 +7,19 @@ package org.mozilla.fenix.ui import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import okhttp3.mockwebserver.MockWebServer -import org.junit.Rule -import org.junit.Before import org.junit.After +import org.junit.Before import org.junit.Ignore +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.helpers.TestHelper +import org.mozilla.fenix.helpers.TestHelper.openAppFromExternalLink +import org.mozilla.fenix.helpers.TestHelper.restartApp +import org.mozilla.fenix.ui.robots.addToHomeScreen +import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.homeScreen import org.mozilla.fenix.ui.robots.navigationToolbar @@ -29,6 +33,7 @@ class SettingsPrivacyTest { private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) private lateinit var mockWebServer: MockWebServer + private val pageShortcutName = "TestShortcut" @get:Rule val activityTestRule = HomeActivityTestRule() @@ -100,7 +105,7 @@ class SettingsPrivacyTest { // Logins verifyLoginsButton() // drill down to submenu - verifyAddPrivateBrowsingShortcutButton() + verifyPrivateBrowsingButton() verifySitePermissionsButton() // drill down on search verifyDeleteBrowsingDataButton() @@ -138,21 +143,21 @@ class SettingsPrivacyTest { @Test fun saveLoginFromPromptTest() { val saveLoginTest = - TestAssetHelper.getSaveLoginAsset(mockWebServer) + TestAssetHelper.getSaveLoginAsset(mockWebServer) - navigationToolbar { - }.enterURLAndEnterToBrowser(saveLoginTest.url) { - verifySaveLoginPromptIsShown() - // Click save to save the login - saveLoginFromPrompt("Save") - }.openHomeScreen { - }.openThreeDotMenu { - }.openSettings { - TestHelper.scrollToElementByText("Logins and passwords") - }.openLoginsAndPasswordSubMenu { - verifyDefaultView() - verifyDefaultValueSyncLogins() - }.openSavedLogins { + navigationToolbar { + }.enterURLAndEnterToBrowser(saveLoginTest.url) { + verifySaveLoginPromptIsShown() + // Click save to save the login + saveLoginFromPrompt("Save") + }.openHomeScreen { + }.openThreeDotMenu { + }.openSettings { + TestHelper.scrollToElementByText("Logins and passwords") + }.openLoginsAndPasswordSubMenu { + verifyDefaultView() + verifyDefaultValueSyncLogins() + }.openSavedLogins { verifySavedLoginsView() tapSetupLater() // Verify that the login appears correctly @@ -194,6 +199,110 @@ class SettingsPrivacyTest { } } + @Test + fun verifyPrivateBrowsingMenuItemsTest() { + homeScreen { + }.openThreeDotMenu { + }.openSettings { + }.openPrivateBrowsingSubMenu { + verifyAddPrivateBrowsingShortcutButton() + verifyOpenLinksInPrivateTab() + verifyOpenLinksInPrivateTabOff() + }.goBack { + verifySettingsView() + } + } + + @Test + fun openExternalLinksInPrivateTest() { + val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + setOpenLinksInPrivateOn() + + openAppFromExternalLink(defaultWebPage.url.toString()) + + browserScreen { + }.openHomeScreen { + verifyPrivateSessionHeader() + } + + setOpenLinksInPrivateOff() + + openAppFromExternalLink(defaultWebPage.url.toString()) + + browserScreen { + }.openHomeScreen { + verifyOpenTabsHeader() + } + } + + @Test + fun launchPageShortcutInPrivateModeTest() { + val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + setOpenLinksInPrivateOn() + + navigationToolbar { + }.enterURLAndEnterToBrowser(defaultWebPage.url) { + }.openThreeDotMenu { + }.openAddToHomeScreen { + addShortcutName(pageShortcutName) + clickAddShortcutButton() + clickAddAutomaticallyButton() + }.openHomeScreenShortcut(pageShortcutName) { + }.openHomeScreen { + verifyPrivateSessionHeader() + } + } + + @Test + fun launchLinksInPrivateToggleOffStateDoesntChangeTest() { + val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + setOpenLinksInPrivateOn() + + navigationToolbar { + }.enterURLAndEnterToBrowser(defaultWebPage.url) { + }.openThreeDotMenu { + }.openAddToHomeScreen { + addShortcutName(pageShortcutName) + clickAddShortcutButton() + clickAddAutomaticallyButton() + }.openHomeScreenShortcut(pageShortcutName) { + }.openHomeScreen {} + + setOpenLinksInPrivateOff() + restartApp(activityTestRule) + mDevice.waitForIdle() + + addToHomeScreen { + }.searchAndOpenHomeScreenShortcut(pageShortcutName) { + }.openHomeScreen { + verifyOpenTabsHeader() + }.openThreeDotMenu { + }.openSettings { + }.openPrivateBrowsingSubMenu { + verifyOpenLinksInPrivateTabOff() + } + + } + + @Test + fun addPrivateBrowsingShortcut() { + homeScreen { + }.openThreeDotMenu { + }.openSettings { + }.openPrivateBrowsingSubMenu { + addPrivateShortcutToHomescreen() + verifyPrivateBrowsingShortcutIcon() + }.openPrivateBrowsingShortcut { + verifySearchView() + }.openBrowser { + }.openHomeScreen { + verifyPrivateSessionHeader() + } + } + @Ignore("This is a stub test, ignore for now") @Test fun toggleTrackingProtection() { @@ -365,3 +474,29 @@ class SettingsPrivacyTest { // Verify 'dump' message } } + +private fun setOpenLinksInPrivateOn() { + homeScreen { + }.openThreeDotMenu { + }.openSettings { + }.openPrivateBrowsingSubMenu { + verifyOpenLinksInPrivateTabEnabled() + clickOpenLinksInPrivateTabSwitch() + }.goBack { + }.goBack { + verifyHomeComponent() + } +} + +private fun setOpenLinksInPrivateOff() { + homeScreen { + }.openThreeDotMenu { + }.openSettings { + }.openPrivateBrowsingSubMenu { + clickOpenLinksInPrivateTabSwitch() + verifyOpenLinksInPrivateTabOff() + }.goBack { + }.goBack { + verifyHomeComponent() + } +} diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/AddToHomeScreenRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/AddToHomeScreenRobot.kt new file mode 100644 index 000000000..14c0ffaf7 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/AddToHomeScreenRobot.kt @@ -0,0 +1,83 @@ +/* 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.os.Build +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.clearText +import androidx.test.espresso.action.ViewActions.typeText +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.uiautomator.By +import androidx.test.uiautomator.By.textContains +import androidx.test.uiautomator.UiScrollable +import androidx.test.uiautomator.UiSelector +import androidx.test.uiautomator.Until +import org.hamcrest.CoreMatchers.anyOf +import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime +import org.mozilla.fenix.helpers.click +import org.mozilla.fenix.helpers.ext.waitNotNull + +/** + * Implementation of Robot Pattern for the Add to homescreen feature. + */ +class AddToHomeScreenRobot { + + fun addShortcutName(title: String) { + mDevice.waitNotNull(Until.findObject(By.text("Add to Home screen")), waitingTime) + shortcutNameField() + .perform(clearText()) + .perform(typeText(title)) + } + + fun clickAddShortcutButton() = addButton().click() + + fun clickAddAutomaticallyButton() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + mDevice.wait(Until.findObject(textContains("add automatically")), waitingTime) + addAutomaticallyButton().click() + } + } + + class Transition { + fun openHomeScreenShortcut(title: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + mDevice.wait( + Until.findObject(By.text(title)), + waitingTime + ) + mDevice.findObject((UiSelector().text(title))).clickAndWaitForNewWindow(waitingTime) + + BrowserRobot().interact() + return BrowserRobot.Transition() + } + + fun searchAndOpenHomeScreenShortcut(title: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + mDevice.pressHome() + + fun homeScreenView() = UiScrollable(UiSelector().scrollable(true)) + homeScreenView().setAsHorizontalList() + + fun shortcut() = + homeScreenView().getChildByText(UiSelector().textContains(title), title) + shortcut().clickAndWaitForNewWindow() + + BrowserRobot().interact() + return BrowserRobot.Transition() + } + } +} + +fun addToHomeScreen(interact: AddToHomeScreenRobot.() -> Unit): AddToHomeScreenRobot.Transition { + AddToHomeScreenRobot().interact() + return AddToHomeScreenRobot.Transition() +} + +private fun shortcutNameField() = onView(withId(R.id.shortcut_text)) + +private fun addButton() = onView(anyOf(withText("ADD"))) + +private fun addAutomaticallyButton() = + mDevice.findObject(UiSelector().textContains("add automatically")) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BookmarksRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BookmarksRobot.kt index 43f301465..c26e995ac 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BookmarksRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BookmarksRobot.kt @@ -73,6 +73,10 @@ class BookmarksRobot { } fun clickAddFolderButton() { + mDevice.waitNotNull( + Until.findObject(By.res("org.mozilla.fenix.debug:id/add_bookmark_folder")), + TestAssetHelper.waitingTime + ) addFolderButton().click() } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt index 05ce3e73f..2c1718708 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt @@ -17,17 +17,21 @@ import androidx.test.espresso.intent.Intents.intended import androidx.test.espresso.intent.matcher.IntentMatchers.toPackage import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.Visibility +import androidx.test.espresso.matcher.ViewMatchers.hasDescendant import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.By +import androidx.test.uiautomator.By.textContains import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.Until import org.hamcrest.CoreMatchers import org.mozilla.fenix.R import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_PLAY_SERVICES import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime -import org.mozilla.fenix.helpers.TestHelper +import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText import org.mozilla.fenix.helpers.click /** @@ -52,7 +56,7 @@ class SettingsRobot { fun verifyEnhancedTrackingProtectionValue(state: String) = assertEnhancedTrackingProtectionValue(state) - fun verifyAddPrivateBrowsingShortcutButton() = assertPrivateBrowsingButton() + fun verifyPrivateBrowsingButton() = assertPrivateBrowsingButton() fun verifySitePermissionsButton() = assertSitePermissionsButton() fun verifyDeleteBrowsingDataButton() = assertDeleteBrowsingDataButton() fun verifyDeleteBrowsingDataOnQuitButton() = assertDeleteBrowsingDataOnQuitButton() @@ -95,7 +99,7 @@ class SettingsRobot { fun openSearchSubMenu(interact: SettingsSubMenuSearchRobot.() -> Unit): SettingsSubMenuSearchRobot.Transition { - fun searchEngineButton() = onView(ViewMatchers.withText("Search")) + fun searchEngineButton() = onView(withText("Search")) searchEngineButton().click() SettingsSubMenuSearchRobot().interact() @@ -104,7 +108,7 @@ class SettingsRobot { fun openCustomizeSubMenu(interact: SettingsSubMenuThemeRobot.() -> Unit): SettingsSubMenuThemeRobot.Transition { - fun customizeButton() = onView(ViewMatchers.withText("Customize")) + fun customizeButton() = onView(withText("Customize")) customizeButton().click() SettingsSubMenuThemeRobot().interact() @@ -113,7 +117,7 @@ class SettingsRobot { fun openAccessibilitySubMenu(interact: SettingsSubMenuAccessibilityRobot.() -> Unit): SettingsSubMenuAccessibilityRobot.Transition { - fun accessibilityButton() = onView(ViewMatchers.withText("Accessibility")) + fun accessibilityButton() = onView(withText("Accessibility")) accessibilityButton().click() SettingsSubMenuAccessibilityRobot().interact() @@ -122,7 +126,7 @@ class SettingsRobot { fun openDefaultBrowserSubMenu(interact: SettingsSubMenuDefaultBrowserRobot.() -> Unit): SettingsSubMenuDefaultBrowserRobot.Transition { - fun defaultBrowserButton() = onView(ViewMatchers.withText("Set as default browser")) + fun defaultBrowserButton() = onView(withText("Set as default browser")) defaultBrowserButton().click() SettingsSubMenuDefaultBrowserRobot().interact() @@ -131,7 +135,7 @@ class SettingsRobot { fun openEnhancedTrackingProtectionSubMenu(interact: SettingsSubMenuEnhancedTrackingProtectionRobot.() -> Unit): SettingsSubMenuEnhancedTrackingProtectionRobot.Transition { fun enhancedTrackingProtectionButton() = - onView(ViewMatchers.withText("Enhanced Tracking Protection")) + onView(withText("Enhanced Tracking Protection")) enhancedTrackingProtectionButton().click() SettingsSubMenuEnhancedTrackingProtectionRobot().interact() @@ -139,8 +143,8 @@ class SettingsRobot { } fun openLoginsAndPasswordSubMenu(interact: SettingsSubMenuLoginsAndPasswordRobot.() -> Unit): SettingsSubMenuLoginsAndPasswordRobot.Transition { - TestHelper.scrollToElementByText("Logins and passwords") - fun loginsAndPasswordsButton() = onView(ViewMatchers.withText("Logins and passwords")) + scrollToElementByText("Logins and passwords") + fun loginsAndPasswordsButton() = onView(withText("Logins and passwords")) loginsAndPasswordsButton().click() SettingsSubMenuLoginsAndPasswordRobot().interact() @@ -148,12 +152,21 @@ class SettingsRobot { } fun openTurnOnSyncMenu(interact: SettingsTurnOnSyncRobot.() -> Unit): SettingsTurnOnSyncRobot.Transition { - fun turnOnSyncButton() = onView(ViewMatchers.withText("Turn on Sync")) + fun turnOnSyncButton() = onView(withText("Turn on Sync")) turnOnSyncButton().click() SettingsTurnOnSyncRobot().interact() return SettingsTurnOnSyncRobot.Transition() } + + fun openPrivateBrowsingSubMenu(interact: SettingsSubMenuPrivateBrowsingRobot.() -> Unit): SettingsSubMenuPrivateBrowsingRobot.Transition { + scrollToElementByText("Private browsing") + fun privateBrowsingButton() = mDevice.findObject(textContains("Private browsing")) + privateBrowsingButton().click() + + SettingsSubMenuPrivateBrowsingRobot().interact() + return SettingsSubMenuPrivateBrowsingRobot.Transition() + } } } @@ -166,114 +179,114 @@ private fun assertSettingsView() { } // GENERAL SECTION -private fun assertGeneralHeading() = onView(ViewMatchers.withText("General")) +private fun assertGeneralHeading() = onView(withText("General")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun assertSearchEngineButton() { mDevice.wait(Until.findObject(By.text("Search")), waitingTime) - onView(ViewMatchers.withText("Search")) + onView(withText("Search")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } -private fun assertCustomizeButton() = onView(ViewMatchers.withText("Customize")) +private fun assertCustomizeButton() = onView(withText("Customize")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -private fun assertThemeSelected() = onView(ViewMatchers.withText("Light")) +private fun assertThemeSelected() = onView(withText("Light")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -private fun assertAccessibilityButton() = onView(ViewMatchers.withText("Accessibility")) +private fun assertAccessibilityButton() = onView(withText("Accessibility")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun assertSetAsDefaultBrowserButton() = - onView(ViewMatchers.withText("Set as default browser")) + onView(withText("Set as default browser")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) // PRIVACY SECTION private fun assertPrivacyHeading() { - onView(ViewMatchers.withText("Privacy and security")) + onView(withText("Privacy and security")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } private fun assertEnhancedTrackingProtectionButton() { mDevice.wait(Until.findObject(By.text("Privacy and Security")), waitingTime) - onView(ViewMatchers.withId(R.id.recycler_view)).perform( + onView(withId(R.id.recycler_view)).perform( RecyclerViewActions.scrollTo( - ViewMatchers.hasDescendant(ViewMatchers.withText("Enhanced Tracking Protection")) + hasDescendant(withText("Enhanced Tracking Protection")) ) ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } private fun assertEnhancedTrackingProtectionValue(state: String) { mDevice.wait(Until.findObject(By.text("Enhanced Tracking Protection")), waitingTime) - onView(ViewMatchers.withText(state)).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + onView(withText(state)).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } private fun assertLoginsButton() { - TestHelper.scrollToElementByText("Logins and passwords") - onView(ViewMatchers.withText("Logins and passwords")) + scrollToElementByText("Logins and passwords") + onView(withText("Logins and passwords")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } private fun assertPrivateBrowsingButton() { - TestHelper.scrollToElementByText("Private browsing") + scrollToElementByText("Private browsing") mDevice.wait(Until.findObject(By.text("Private browsing")), waitingTime) - onView(ViewMatchers.withText("Private browsing")) + onView(withText("Private browsing")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } private fun assertSitePermissionsButton() { - TestHelper.scrollToElementByText("Site permissions") - onView(ViewMatchers.withText("Site permissions")) + scrollToElementByText("Site permissions") + onView(withText("Site permissions")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } private fun assertDeleteBrowsingDataButton() { - TestHelper.scrollToElementByText("Delete browsing data") - onView(ViewMatchers.withText("Delete browsing data")) + scrollToElementByText("Delete browsing data") + onView(withText("Delete browsing data")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } private fun assertDeleteBrowsingDataOnQuitButton() { - TestHelper.scrollToElementByText("Delete browsing data on quit") - onView(ViewMatchers.withText("Delete browsing data on quit")) + scrollToElementByText("Delete browsing data on quit") + onView(withText("Delete browsing data on quit")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } -private fun assertDataCollectionButton() = onView(ViewMatchers.withText("Data collection")) +private fun assertDataCollectionButton() = onView(withText("Data collection")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -private fun assertLeakCanaryButton() = onView(ViewMatchers.withText("LeakCanary")) +private fun assertLeakCanaryButton() = onView(withText("LeakCanary")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) // DEVELOPER TOOLS SECTION private fun assertDeveloperToolsHeading() { - TestHelper.scrollToElementByText("Developer tools") - onView(ViewMatchers.withText("Developer tools")) + scrollToElementByText("Developer tools") + onView(withText("Developer tools")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } private fun assertRemoteDebug() { - TestHelper.scrollToElementByText("Remote debugging via USB") - onView(ViewMatchers.withText("Remote debugging via USB")) + scrollToElementByText("Remote debugging via USB") + onView(withText("Remote debugging via USB")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } // ABOUT SECTION private fun assertAboutHeading(): ViewInteraction { - TestHelper.scrollToElementByText("About") - return onView(ViewMatchers.withText("About")) + scrollToElementByText("About") + return onView(withText("About")) .check(matches(isCompletelyDisplayed())) } private fun assertRateOnGooglePlay(): ViewInteraction { - TestHelper.scrollToElementByText("About Firefox Preview") - return onView(ViewMatchers.withText("Rate on Google Play")) + scrollToElementByText("About Firefox Preview") + return onView(withText("Rate on Google Play")) .check(matches(isCompletelyDisplayed())) } private fun assertAboutFirefoxPreview(): ViewInteraction { - TestHelper.scrollToElementByText("About Firefox Preview") - return onView(ViewMatchers.withText("About Firefox Preview")) + scrollToElementByText("About Firefox Preview") + return onView(withText("About Firefox Preview")) .check(matches(isCompletelyDisplayed())) } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDefaultBrowserRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDefaultBrowserRobot.kt index 87697d0ae..9ba16af96 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDefaultBrowserRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDefaultBrowserRobot.kt @@ -7,18 +7,15 @@ 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.matches import androidx.test.espresso.intent.Intents.intended import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction -import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.isNotChecked +import androidx.test.espresso.matcher.ViewMatchers.withContentDescription +import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withParent import androidx.test.espresso.matcher.ViewMatchers.withText -import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility -import androidx.test.espresso.matcher.ViewMatchers.Visibility -import androidx.test.espresso.matcher.ViewMatchers.withContentDescription import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import org.hamcrest.CoreMatchers.allOf @@ -35,7 +32,6 @@ class SettingsSubMenuDefaultBrowserRobot { const val DEFAULT_APPS_SETTINGS_ACTION = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS" } - fun verifyOpenLinksInPrivateTab() = assertOpenLinksInPrivateTab() fun verifyDefaultBrowserIsDisabled() = assertDefaultBrowserIsDisabled() fun clickDefaultBrowserSwitch() = toggleDefaultBrowserSwitch() fun verifyAndroidDefaultAppsMenuAppears() = assertAndroidDefaultAppsMenuAppears() @@ -45,7 +41,7 @@ class SettingsSubMenuDefaultBrowserRobot { fun goBack(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition { mDevice.waitForIdle() - goBackButton().perform(ViewActions.click()) + goBackButton().perform(click()) SettingsRobot().interact() return SettingsRobot.Transition() @@ -72,10 +68,5 @@ private fun assertAndroidDefaultAppsMenuAppears() { intended(hasAction(DEFAULT_APPS_SETTINGS_ACTION)) } -private fun assertOpenLinksInPrivateTab() { - onView(withText("Open links in private tab")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - private fun goBackButton() = onView(allOf(withContentDescription("Navigate up"))) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuPrivateBrowsingRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuPrivateBrowsingRobot.kt new file mode 100644 index 000000000..dfd0d9959 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuPrivateBrowsingRobot.kt @@ -0,0 +1,114 @@ +package org.mozilla.fenix.ui.robots + +import android.os.Build +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.isEnabled +import androidx.test.espresso.matcher.ViewMatchers.withContentDescription +import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility +import androidx.test.espresso.matcher.ViewMatchers.withText +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 org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime +import org.mozilla.fenix.helpers.click + +/** + * Implementation of Robot Pattern for the settings PrivateBrowsing sub menu. + */ + +class SettingsSubMenuPrivateBrowsingRobot { + + fun verifyOpenLinksInPrivateTab() = assertOpenLinksInPrivateTab() + + fun verifyAddPrivateBrowsingShortcutButton() = assertAddPrivateBrowsingShortcutButton() + + fun verifyOpenLinksInPrivateTabEnabled() = assertOpenLinksInPrivateTabEnabled() + + fun verifyOpenLinksInPrivateTabOff() = assertOpenLinksInPrivateTabOff() + + fun verifyPrivateBrowsingShortcutIcon() = assertPrivateBrowsingShortcutIcon() + + fun clickOpenLinksInPrivateTabSwitch() = openLinksInPrivateTabSwitch().click() + + fun addPrivateShortcutToHomescreen() { + mDevice.wait( + Until.findObject(text("Add private browsing shortcut")), + waitingTime + ) + addPrivateBrowsingShortcutButton().click() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + mDevice.wait(Until.findObject(By.textContains("add automatically")), waitingTime) + addAutomaticallyButton().click() + } + } + + class Transition { + val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + fun goBack(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition { + mDevice.waitForIdle() + goBackButton().perform(ViewActions.click()) + + SettingsRobot().interact() + return SettingsRobot.Transition() + } + + fun openPrivateBrowsingShortcut(interact: SearchRobot.() -> Unit): SearchRobot.Transition { + privateBrowsingShortcutIcon().click() + + SearchRobot().interact() + return SearchRobot.Transition() + } + } +} + +private fun openLinksInPrivateTabSwitch() = + onView(withText("Open links in a private tab")) + +private fun addPrivateBrowsingShortcutButton() = onView(withText("Add private browsing shortcut")) + +private fun goBackButton() = onView(withContentDescription("Navigate up")) + +private fun addAutomaticallyButton() = + mDevice.findObject(UiSelector().textStartsWith("add automatically")) + +private fun privateBrowsingShortcutIcon() = mDevice.findObject(text("Private Firefox Preview")) + +private fun assertAddPrivateBrowsingShortcutButton() { + mDevice.wait( + Until.findObject(text("Add private browsing shortcut")), + waitingTime + ) + addPrivateBrowsingShortcutButton() + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +} + +private fun assertOpenLinksInPrivateTab() { + openLinksInPrivateTabSwitch() + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +} + +private fun assertOpenLinksInPrivateTabEnabled() = + openLinksInPrivateTabSwitch().check(matches(isEnabled())) + +private fun assertOpenLinksInPrivateTabOff() { + assertFalse(mDevice.findObject(UiSelector().resourceId("android:id/switch_widget")).isChecked()) + openLinksInPrivateTabSwitch() + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +} + +private fun assertPrivateBrowsingShortcutIcon() { + mDevice.wait( + Until.findObject(text("Private Firefox Preview")), + waitingTime + ) + assertTrue(mDevice.hasObject(text("Private Firefox Preview"))) +} 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 179b635e8..4e43377e2 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 @@ -233,6 +233,14 @@ class ThreeDotMenuMainRobot { BrowserRobot().interact() return BrowserRobot.Transition() } + + fun openAddToHomeScreen(interact: AddToHomeScreenRobot.() -> Unit): AddToHomeScreenRobot.Transition { + mDevice.waitNotNull(Until.findObject(By.text("Add to Home screen")), waitingTime) + addToHomeScreenButton().click() + + AddToHomeScreenRobot().interact() + return AddToHomeScreenRobot.Transition() + } } } @@ -336,6 +344,8 @@ private fun whatsNewButton() = onView( private fun assertWhatsNewButton() = whatsNewButton() .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +private fun addToHomeScreenButton() = onView(withText("Add to Home screen")) + private fun readerViewToggle() = onView(allOf(withText(R.string.browser_menu_read))) private fun assertReaderViewToggle(visible: Boolean) = readerViewToggle() .check(