diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/Constants.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/Constants.kt index 4e6e06509fa5..6e2829912c5d 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/helpers/Constants.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/Constants.kt @@ -5,6 +5,7 @@ object Constants { object PackageName { const val GOOGLE_PLAY_SERVICES = "com.android.vending" const val GOOGLE_APPS_PHOTOS = "com.google.android.apps.photos" + const val YOUTUBE_APP = "com.google.android.youtube" } const val LONG_CLICK_DURATION: Long = 5000 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 7df7d88cb43e..0f268e93222f 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt @@ -8,6 +8,7 @@ import android.app.PendingIntent import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent +import android.content.pm.PackageManager import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Color @@ -21,6 +22,8 @@ import androidx.test.espresso.Espresso.onView import androidx.test.espresso.IdlingRegistry import androidx.test.espresso.action.ViewActions.longClick import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.intent.Intents +import androidx.test.espresso.intent.matcher.IntentMatchers import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.platform.app.InstrumentationRegistry @@ -190,4 +193,35 @@ object TestHelper { canvas.drawColor(Color.GREEN) return bitmap } + + fun isPackageInstalled(packageName: String): Boolean { + return try { + val packageManager = InstrumentationRegistry.getInstrumentation().context.packageManager + packageManager.getApplicationInfo(packageName, 0).enabled + } catch (exception: PackageManager.NameNotFoundException) { + false + } + } + + fun assertExternalAppOpens(appPackageName: String) { + if (isPackageInstalled(appPackageName)) { + Intents.intended(IntentMatchers.toPackage(appPackageName)) + } else { + val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + mDevice.waitNotNull( + Until.findObject(By.text("Could not open file")), + waitingTime + ) + } + } + + fun returnToBrowser() { + val urlBar = + mDevice.findObject(UiSelector().resourceId("$packageName:id/mozac_browser_toolbar_url_view")) + do { + mDevice.pressBack() + } while ( + !urlBar.waitForExists(waitingTime) + ) + } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt index 062e3736242e..aa77308fe60e 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt @@ -25,14 +25,18 @@ import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.helpers.AndroidAssetDispatcher +import org.mozilla.fenix.helpers.Constants.PackageName.YOUTUBE_APP import org.mozilla.fenix.helpers.HomeActivityIntentTestRule import org.mozilla.fenix.helpers.RecyclerViewIdlingResource import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper import org.mozilla.fenix.helpers.TestHelper.appName +import org.mozilla.fenix.helpers.TestHelper.assertExternalAppOpens import org.mozilla.fenix.helpers.TestHelper.createCustomTabIntent import org.mozilla.fenix.helpers.TestHelper.deleteDownloadFromStorage +import org.mozilla.fenix.helpers.TestHelper.isPackageInstalled import org.mozilla.fenix.helpers.TestHelper.restartApp +import org.mozilla.fenix.helpers.TestHelper.returnToBrowser import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText import org.mozilla.fenix.helpers.ViewVisibilityIdlingResource import org.mozilla.fenix.ui.robots.browserScreen @@ -238,10 +242,13 @@ class SmokeTest { @Test // Verifies the History menu opens from a tab's 3 dot menu fun openMainMenuHistoryItemTest() { - homeScreen { + val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + navigationToolbar { + }.enterURLAndEnterToBrowser(defaultWebPage.url) { }.openThreeDotMenu { }.openHistory { - verifyHistoryMenuView() + verifyHistoryListExists() } } @@ -249,7 +256,10 @@ class SmokeTest { @Test // Verifies the Bookmarks menu opens from a tab's 3 dot menu fun openMainMenuBookmarksItemTest() { - homeScreen { + val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + navigationToolbar { + }.enterURLAndEnterToBrowser(defaultWebPage.url) { }.openThreeDotMenu { }.openBookmarks { verifyBookmarksMenuView() @@ -260,7 +270,10 @@ class SmokeTest { // Verifies the Synced tabs menu or Sync Sign In menu opens from a tab's 3 dot menu. // The test is assuming we are NOT signed in. fun openMainMenuSyncItemTest() { - homeScreen { + val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + navigationToolbar { + }.enterURLAndEnterToBrowser(defaultWebPage.url) { }.openThreeDotMenu { }.openSyncSignIn { verifySyncSignInMenuHeader() @@ -272,7 +285,10 @@ class SmokeTest { // caution when making changes to it, so they don't block the builds // Verifies the Settings menu opens from a tab's 3 dot menu fun openMainMenuSettingsItemTest() { - homeScreen { + val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + navigationToolbar { + }.enterURLAndEnterToBrowser(defaultWebPage.url) { }.openThreeDotMenu { }.openSettings { verifySettingsView() @@ -362,6 +378,37 @@ class SmokeTest { } } + @Test + // Verifies the Open in app button when an app is installed + fun mainMenuOpenInAppTest() { + val youtubeUrl = "m.youtube.com" + if (isPackageInstalled(YOUTUBE_APP)) { + navigationToolbar { + }.enterURLAndEnterToBrowser(youtubeUrl.toUri()) { + verifyNotificationDotOnMainMenu() + }.openThreeDotMenu { + }.clickOpenInApp { + assertExternalAppOpens(YOUTUBE_APP) + returnToBrowser() + verifyUrl(youtubeUrl) + } + } + } + + @Test + // Verifies the Desktop site toggle in a tab's 3 dot menu + fun mainMenuDesktopSiteTest() { + val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + navigationToolbar { + }.enterURLAndEnterToBrowser(defaultWebPage.url) { + }.openThreeDotMenu { + }.switchDesktopSiteMode { + }.openThreeDotMenu { + verifyDesktopSiteModeEnabled(true) + } + } + @Test // Verifies the Share button in a tab's 3 dot menu fun mainMenuShareButtonTest() { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt index b2fdff296c5f..2e769d4ab6e9 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt @@ -28,6 +28,7 @@ import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_APPS_PHOTOS import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime import org.mozilla.fenix.helpers.TestHelper +import org.mozilla.fenix.helpers.TestHelper.assertExternalAppOpens import org.mozilla.fenix.helpers.TestHelper.packageName import org.mozilla.fenix.helpers.click import org.mozilla.fenix.helpers.ext.waitNotNull @@ -42,7 +43,7 @@ class DownloadRobot { fun verifyDownloadNotificationPopup() = assertDownloadNotificationPopup() - fun verifyPhotosAppOpens() = assertPhotosOpens() + fun verifyPhotosAppOpens() = assertExternalAppOpens(GOOGLE_APPS_PHOTOS) fun verifyDownloadedFileName(fileName: String) { mDevice.findObject(UiSelector().text(fileName)).waitForExists(waitingTime) @@ -144,18 +145,6 @@ private fun clickOpenButton() = matches(isDisplayed()) ) -private fun assertPhotosOpens() { - if (isPackageInstalled(GOOGLE_APPS_PHOTOS)) { - Intents.intended(IntentMatchers.toPackage(GOOGLE_APPS_PHOTOS)) - } else { - val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) - mDevice.waitNotNull( - Until.findObject(By.text("Could not open file")), - TestAssetHelper.waitingTime - ) - } -} - private fun downloadedFile(fileName: String) = onView(withText(fileName)) private fun assertDownloadedFileIcon() = onView(withId(R.id.favicon)).check(matches(isDisplayed())) 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 411795c4af2f..31d13cd6f955 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 @@ -6,7 +6,6 @@ package org.mozilla.fenix.ui.robots -import android.content.pm.PackageManager import androidx.recyclerview.widget.RecyclerView import androidx.test.espresso.Espresso.onView import androidx.test.espresso.ViewInteraction @@ -34,6 +33,7 @@ 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.appName +import org.mozilla.fenix.helpers.TestHelper.isPackageInstalled import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText import org.mozilla.fenix.helpers.assertIsEnabled import org.mozilla.fenix.helpers.click @@ -493,15 +493,6 @@ private fun assertGooglePlayRedirect() { } } -fun isPackageInstalled(packageName: String): Boolean { - return try { - val packageManager = InstrumentationRegistry.getInstrumentation().context.packageManager - packageManager.getApplicationInfo(packageName, 0).enabled - } catch (exception: PackageManager.NameNotFoundException) { - false - } -} - private fun addonsManagerButton() = onView(withText(R.string.preferences_addons)) private fun goBackButton() = 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 05991877d992..ec2e70dfb59c 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 @@ -16,6 +16,7 @@ import androidx.test.espresso.matcher.RootMatchers 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.isChecked import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility @@ -28,6 +29,7 @@ import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until import org.hamcrest.Matchers.allOf +import org.hamcrest.Matchers.not import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.mozilla.fenix.R @@ -66,11 +68,6 @@ class ThreeDotMenuMainRobot { } fun clickShareButton() { - var maxSwipes = 3 - while (!shareButton().exists() && maxSwipes != 0) { - threeDotMenuRecyclerView().perform(swipeUp()) - maxSwipes-- - } shareButton().click() mDevice.waitNotNull(Until.findObject(By.text("ALL ACTIONS")), waitingTime) } @@ -93,6 +90,13 @@ class ThreeDotMenuMainRobot { fun verifyNewTabButton() = assertNewTabButton() fun verifyReportSiteIssueButton() = assertReportSiteIssueButton() + fun verifyDesktopSiteModeEnabled(state: Boolean) { + expandMenu() + if (state) { + desktopSiteButton().check(matches(isChecked())) + } else desktopSiteButton().check(matches(not(isChecked()))) + } + fun verifyPageThreeDotMainMenuItems() { verifyNewTabButton() verifyBookmarksButton() @@ -139,7 +143,7 @@ class ThreeDotMenuMainRobot { } fun openDownloadsManager(interact: DownloadRobot.() -> Unit): DownloadRobot.Transition { - onView(withId(R.id.mozac_browser_menu_recyclerView)).perform(swipeDown()) + threeDotMenuRecyclerView().perform(swipeDown()) downloadsButton().click() DownloadRobot().interact() @@ -147,7 +151,7 @@ class ThreeDotMenuMainRobot { } fun openSyncSignIn(interact: SyncSignInRobot.() -> Unit): SyncSignInRobot.Transition { - onView(withId(R.id.mozac_browser_menu_recyclerView)).perform(swipeDown()) + threeDotMenuRecyclerView().perform(swipeDown()) mDevice.waitNotNull(Until.findObject(By.text("Sign in to sync")), waitingTime) signInToSyncButton().click() @@ -156,7 +160,7 @@ class ThreeDotMenuMainRobot { } fun openBookmarks(interact: BookmarksRobot.() -> Unit): BookmarksRobot.Transition { - onView(withId(R.id.mozac_browser_menu_recyclerView)).perform(swipeDown()) + threeDotMenuRecyclerView().perform(swipeDown()) mDevice.waitNotNull(Until.findObject(By.text("Bookmarks")), waitingTime) bookmarksButton().click() @@ -167,7 +171,7 @@ class ThreeDotMenuMainRobot { } fun openHistory(interact: HistoryRobot.() -> Unit): HistoryRobot.Transition { - onView(withId(R.id.mozac_browser_menu_recyclerView)).perform(swipeDown()) + threeDotMenuRecyclerView().perform(swipeDown()) mDevice.waitNotNull(Until.findObject(By.text("History")), waitingTime) historyButton().click() @@ -185,6 +189,7 @@ class ThreeDotMenuMainRobot { fun sharePage(interact: LibrarySubMenusMultipleSelectionToolbarRobot.() -> Unit): LibrarySubMenusMultipleSelectionToolbarRobot.Transition { shareButton().click() + LibrarySubMenusMultipleSelectionToolbarRobot().interact() return LibrarySubMenusMultipleSelectionToolbarRobot.Transition() } @@ -205,10 +210,7 @@ class ThreeDotMenuMainRobot { } fun goBack(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { - // Close three dot - mDevice.pressBack() - // Nav back to previous page - mDevice.pressBack() + backButton().click() BrowserRobot().interact() return BrowserRobot.Transition() @@ -238,14 +240,6 @@ class ThreeDotMenuMainRobot { return BrowserRobot.Transition() } - fun stopPageLoad(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { - mDevice.waitNotNull(Until.findObject(By.desc("Stop")), waitingTime) - stopLoadingButton().click() - - BrowserRobot().interact() - return BrowserRobot.Transition() - } - fun closeAllTabs(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { closeAllTabsButton().click() @@ -254,6 +248,8 @@ class ThreeDotMenuMainRobot { } fun openReportSiteIssue(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + threeDotMenuRecyclerView().perform(swipeUp()) + threeDotMenuRecyclerView().perform(swipeUp()) reportSiteIssueButton().click() BrowserRobot().interact() @@ -261,7 +257,8 @@ class ThreeDotMenuMainRobot { } fun openFindInPage(interact: FindInPageRobot.() -> Unit): FindInPageRobot.Transition { - onView(withId(R.id.mozac_browser_menu_recyclerView)).perform(swipeDown()) + threeDotMenuRecyclerView().perform(swipeUp()) + threeDotMenuRecyclerView().perform(swipeUp()) mDevice.waitNotNull(Until.findObject(By.text("Find in page")), waitingTime) findInPageButton().click() @@ -278,11 +275,8 @@ class ThreeDotMenuMainRobot { } fun openReaderViewAppearance(interact: ReaderViewRobot.() -> Unit): ReaderViewRobot.Transition { - var maxSwipes = 3 - while (!readerViewAppearanceToggle().exists() && maxSwipes != 0) { - threeDotMenuRecyclerView().perform(swipeUp()) - maxSwipes-- - } + threeDotMenuRecyclerView().perform(swipeUp()) + threeDotMenuRecyclerView().perform(swipeUp()) readerViewAppearanceToggle().click() ReaderViewRobot().interact() @@ -305,11 +299,8 @@ class ThreeDotMenuMainRobot { } fun clickInstall(interact: AddToHomeScreenRobot.() -> Unit): AddToHomeScreenRobot.Transition { - var maxSwipes = 3 - while (!installPWAButton().exists() && maxSwipes != 0) { - threeDotMenuRecyclerView().perform(swipeUp()) - maxSwipes-- - } + threeDotMenuRecyclerView().perform(swipeUp()) + threeDotMenuRecyclerView().perform(swipeUp()) installPWAButton().click() AddToHomeScreenRobot().interact() @@ -318,9 +309,8 @@ class ThreeDotMenuMainRobot { fun openSaveToCollection(interact: CollectionRobot.() -> Unit): CollectionRobot.Transition { // Ensure the menu is expanded and fully scrolled to the bottom. - for (i in 0..3) { - threeDotMenuRecyclerView().perform(swipeUp()) - } + threeDotMenuRecyclerView().perform(swipeUp()) + threeDotMenuRecyclerView().perform(swipeUp()) mDevice.waitNotNull(Until.findObject(By.text("Save to collection")), waitingTime) saveCollectionButton().click() @@ -337,6 +327,24 @@ class ThreeDotMenuMainRobot { SettingsSubMenuAddonsManagerRobot().interact() return SettingsSubMenuAddonsManagerRobot.Transition() } + + fun clickOpenInApp(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + threeDotMenuRecyclerView().perform(swipeUp()) + threeDotMenuRecyclerView().perform(swipeUp()) + openInAppButton().click() + + BrowserRobot().interact() + return BrowserRobot.Transition() + } + + fun switchDesktopSiteMode(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + threeDotMenuRecyclerView().perform(swipeUp()) + threeDotMenuRecyclerView().perform(swipeUp()) + desktopSiteButton().click() + + BrowserRobot().interact() + return BrowserRobot.Transition() + } } } private fun threeDotMenuRecyclerView() = @@ -373,6 +381,8 @@ private fun assertHelpButton() = helpButton() private fun forwardButton() = mDevice.findObject(UiSelector().description("Forward")) private fun assertForwardButton() = assertTrue(forwardButton().waitForExists(waitingTime)) +private fun backButton() = mDevice.findObject(UiSelector().description("Back")) + private fun addBookmarkButton() = onView(allOf(withId(R.id.checkbox), withText("Add"))) private fun assertAddBookmarkButton() { onView(withId(R.id.mozac_browser_menu_menuView)).perform(swipeUp()) @@ -488,13 +498,20 @@ private fun assertAddToMobileHome() { private fun installPWAButton() = mDevice.findObject(UiSelector().text("Install")) -private fun desktopSiteButton() = - onView(allOf(withText(R.string.browser_menu_desktop_site))) +private fun desktopSiteButton() = onView(withId(R.id.switch_widget)) private fun assertDesktopSite() { - onView(withId(R.id.mozac_browser_menu_menuView)).perform(swipeUp()) + threeDotMenuRecyclerView().perform(swipeUp()) desktopSiteButton().check(matches(isDisplayed())) } +private fun openInAppButton() = + onView( + allOf( + withText("Open in app"), + withEffectiveVisibility(Visibility.VISIBLE) + ) + ) + private fun downloadsButton() = onView(withText(R.string.library_downloads)) private fun assertDownloadsButton() { onView(withId(R.id.mozac_browser_menu_menuView)).perform(swipeDown())