From 65105f285449b0cc8777d210e86becbd733ab7e0 Mon Sep 17 00:00:00 2001 From: Oana Horvath Date: Wed, 26 May 2021 16:25:42 +0300 Subject: [PATCH] [fenix] No issue: Added custom tab UI smoke test --- .../org/mozilla/fenix/helpers/TestHelper.kt | 33 ++++++++ .../java/org/mozilla/fenix/ui/SmokeTest.kt | 63 +++++++++++++- .../mozilla/fenix/ui/robots/CustomTabRobot.kt | 84 +++++++++++++++++++ 3 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt 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 ec9b3d70e3..30db0383c2 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt @@ -4,12 +4,17 @@ package org.mozilla.fenix.helpers +import android.app.PendingIntent import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Color import android.net.Uri import android.os.Build import android.os.Environment +import androidx.browser.customtabs.CustomTabsIntent import androidx.preference.PreferenceManager import androidx.test.espresso.Espresso import androidx.test.espresso.Espresso.onView @@ -153,4 +158,32 @@ object TestHelper { } } } + + fun createCustomTabIntent( + pageUrl: String, + customMenuItemLabel: String = "", + customActionButtonDescription: String = "" + ): Intent { + val appContext = InstrumentationRegistry.getInstrumentation() + .targetContext + .applicationContext + val pendingIntent = PendingIntent.getActivity(appContext, 0, Intent(), 0) + val customTabsIntent = CustomTabsIntent.Builder() + .addMenuItem(customMenuItemLabel, pendingIntent) + .setShareState(CustomTabsIntent.SHARE_STATE_ON) + .setActionButton( + createTestBitmap(), + customActionButtonDescription, pendingIntent, true + ) + .build() + customTabsIntent.intent.data = Uri.parse(pageUrl) + return customTabsIntent.intent + } + + private fun createTestBitmap(): Bitmap { + val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) + canvas.drawColor(Color.GREEN) + return bitmap + } } 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 0fe8b3f922..25b36c419b 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt @@ -9,6 +9,7 @@ import androidx.core.net.toUri import androidx.recyclerview.widget.RecyclerView import androidx.test.espresso.IdlingRegistry import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.rule.ActivityTestRule import androidx.test.rule.GrantPermissionRule import androidx.test.uiautomator.UiDevice import okhttp3.mockwebserver.MockWebServer @@ -18,6 +19,7 @@ import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.mozilla.fenix.FeatureFlags +import org.mozilla.fenix.IntentReceiverActivity import org.mozilla.fenix.R import org.mozilla.fenix.ext.settings import org.mozilla.fenix.helpers.AndroidAssetDispatcher @@ -25,11 +27,13 @@ import org.mozilla.fenix.helpers.HomeActivityTestRule import org.mozilla.fenix.helpers.RecyclerViewIdlingResource import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper +import org.mozilla.fenix.helpers.TestHelper.createCustomTabIntent import org.mozilla.fenix.helpers.TestHelper.deleteDownloadFromStorage import org.mozilla.fenix.helpers.ViewVisibilityIdlingResource import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.clickTabCrashedRestoreButton import org.mozilla.fenix.ui.robots.clickUrlbar +import org.mozilla.fenix.ui.robots.customTabScreen import org.mozilla.fenix.ui.robots.dismissTrackingOnboarding import org.mozilla.fenix.ui.robots.downloadRobot import org.mozilla.fenix.ui.robots.enhancedTrackingProtection @@ -52,8 +56,9 @@ class SmokeTest { private var recentlyClosedTabsListIdlingResource: RecyclerViewIdlingResource? = null private var readerViewNotification: ViewVisibilityIdlingResource? = null private val downloadFileName = "Globe.svg" - val collectionName = "First Collection" + private val collectionName = "First Collection" private var bookmarksListIdlingResource: RecyclerViewIdlingResource? = null + private val customMenuItem = "TestMenuItem" // This finds the dialog fragment child of the homeFragment, otherwise the awesomeBar would return null private fun getAwesomebarView(): View? { @@ -67,6 +72,11 @@ class SmokeTest { @get:Rule val activityTestRule = HomeActivityTestRule() + @get: Rule + val intentReceiverActivityTestRule = ActivityTestRule( + IntentReceiverActivity::class.java, true, false + ) + @get:Rule var mGrantPermissions = GrantPermissionRule.grant( android.Manifest.permission.WRITE_EXTERNAL_STORAGE, @@ -112,7 +122,7 @@ class SmokeTest { } } - // copied over from HomeScreenTest + // Verifies the first run onboarding screen @Test fun firstRunScreenTest() { homeScreen { @@ -1228,4 +1238,53 @@ class SmokeTest { verifyPageContent(website.content) } } + + @Test + // Verifies the main menu of a custom tab with a custom menu item + fun customTabMenuItemsTest() { + val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + intentReceiverActivityTestRule.launchActivity( + createCustomTabIntent( + customTabPage.url.toString(), + customMenuItem + ) + ) + + customTabScreen { + browserScreen { + verifyPageContent(customTabPage.content) + } + }.openMainMenu { + verifyPoweredByTextIsDisplayed() + verifyCustomMenuItem(customMenuItem) + verifyDesktopSiteButtonExists() + verifyFindInPageButtonExists() + verifyOpenInBrowserButtonExists() + verifyBackButtonExists() + verifyForwardButtonExists() + verifyRefreshButtonExists() + } + } + + @Test + // The test opens a link in a custom tab then sends it to the browser + fun openCustomTabInBrowserTest() { + val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + intentReceiverActivityTestRule.launchActivity( + createCustomTabIntent( + customTabPage.url.toString() + ) + ) + + customTabScreen { + browserScreen { + verifyPageContent(customTabPage.content) + } + }.openMainMenu { + }.clickOpenInBrowserButton { + verifyTabCounter("1") + } + } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt new file mode 100644 index 0000000000..90f05e96a8 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt @@ -0,0 +1,84 @@ +/* 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 androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.uiautomator.UiSelector +import junit.framework.TestCase.assertTrue +import mozilla.components.support.ktx.android.content.appName +import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime + +/** + * Implementation of the robot pattern for Custom tabs + */ +class CustomTabRobot { + + fun verifyDesktopSiteButtonExists() { + desktopSiteButton().check(matches(isDisplayed())) + } + + fun verifyFindInPageButtonExists() { + findInPageButton().check(matches(isDisplayed())) + } + + fun verifyPoweredByTextIsDisplayed() { + mDevice.findObject(UiSelector().textContains("POWERED BY ${appContext.appName}")) + } + + fun verifyOpenInBrowserButtonExists() { + openInBrowserButton().check(matches(isDisplayed())) + } + + fun verifyBackButtonExists() = assertTrue(backButton().waitForExists(waitingTime)) + + fun verifyForwardButtonExists() = assertTrue(forwardButton().waitForExists(waitingTime)) + + fun verifyRefreshButtonExists() = assertTrue(refreshButton().waitForExists(waitingTime)) + + fun verifyCustomMenuItem(label: String) { + assertTrue(mDevice.findObject(UiSelector().text(label)).exists()) + } + + class Transition { + fun openMainMenu(interact: CustomTabRobot.() -> Unit): Transition { + mainMenuButton().waitForExists(waitingTime) + mainMenuButton().click() + + CustomTabRobot().interact() + return Transition() + } + + fun clickOpenInBrowserButton(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + openInBrowserButton().perform(click()) + + BrowserRobot().interact() + return BrowserRobot.Transition() + } + } +} + +fun customTabScreen(interact: CustomTabRobot.() -> Unit): CustomTabRobot.Transition { + CustomTabRobot().interact() + return CustomTabRobot.Transition() +} + +private fun mainMenuButton() = mDevice.findObject(UiSelector().description("Menu")) + +private fun desktopSiteButton() = onView(withId(R.id.switch_widget)) + +private fun findInPageButton() = onView(withText("Find in page")) + +private fun openInBrowserButton() = onView(withText("Open in ${appContext.appName}")) + +private fun refreshButton() = mDevice.findObject(UiSelector().description("Refresh")) + +private fun forwardButton() = mDevice.findObject(UiSelector().description("Forward")) + +private fun backButton() = mDevice.findObject(UiSelector().description("Back"))