From 35f136b14b34799522d8284b996fe9bd42015933 Mon Sep 17 00:00:00 2001 From: Aaron Train Date: Mon, 2 Dec 2019 17:15:00 -0500 Subject: [PATCH] Closes #6363 - Add Downloads UI tests (#6574) - Initiates a download - Verifies prompt - Verifies notification in notification shade --- .../androidTest/assets/pages/download.html | 5 + .../androidTest/assets/resources/Globe.svg | 4 + .../mozilla/fenix/helpers/TestAssetHelper.kt | 7 ++ .../java/org/mozilla/fenix/ui/DownloadTest.kt | 110 ++++++++++++++++++ .../mozilla/fenix/ui/robots/BrowserRobot.kt | 8 ++ .../mozilla/fenix/ui/robots/DownloadRobot.kt | 86 ++++++++++++++ 6 files changed, 220 insertions(+) create mode 100644 app/src/androidTest/assets/pages/download.html create mode 100644 app/src/androidTest/assets/resources/Globe.svg create mode 100644 app/src/androidTest/java/org/mozilla/fenix/ui/DownloadTest.kt create mode 100644 app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt diff --git a/app/src/androidTest/assets/pages/download.html b/app/src/androidTest/assets/pages/download.html new file mode 100644 index 000000000..f6dd187d5 --- /dev/null +++ b/app/src/androidTest/assets/pages/download.html @@ -0,0 +1,5 @@ + + + Page content: Globe.svg + + diff --git a/app/src/androidTest/assets/resources/Globe.svg b/app/src/androidTest/assets/resources/Globe.svg new file mode 100644 index 000000000..82d41832a --- /dev/null +++ b/app/src/androidTest/assets/resources/Globe.svg @@ -0,0 +1,4 @@ + + \ No newline at end of file diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestAssetHelper.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestAssetHelper.kt index 562569bf3..d864f53c9 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestAssetHelper.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestAssetHelper.kt @@ -63,4 +63,11 @@ object TestAssetHelper { return TestAsset(url, content) } + + fun getDownloadAsset(server: MockWebServer): TestAsset { + val url = server.url("pages/download.html").toString().toUri()!! + val content = "Page content: Globe.svg" + + return TestAsset(url, content) + } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/DownloadTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/DownloadTest.kt new file mode 100644 index 000000000..8c93f0a8c --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/DownloadTest.kt @@ -0,0 +1,110 @@ +/* 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 + +import android.os.Environment +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.rule.GrantPermissionRule +import androidx.test.uiautomator.UiDevice +import kotlinx.coroutines.runBlocking +import okhttp3.mockwebserver.MockWebServer +import org.junit.After +import org.junit.Before +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.ui.robots.downloadRobot +import org.mozilla.fenix.ui.robots.homeScreen +import org.mozilla.fenix.ui.robots.navigationToolbar +import java.io.File + +/** + * Tests for verifying basic functionality of download prompt UI + * + * - Initiates a download + * - Verifies download prompt + * - Verifies download notification + **/ + +class DownloadTest { + + private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + private lateinit var mockWebServer: MockWebServer + + /* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping. + @get:Rule + val activityTestRule = HomeActivityTestRule() + + @get:Rule + var mGrantPermissions = GrantPermissionRule.grant( + android.Manifest.permission.WRITE_EXTERNAL_STORAGE, + android.Manifest.permission.READ_EXTERNAL_STORAGE + ) + + @Before + fun setUp() { + mockWebServer = MockWebServer().apply { + setDispatcher(AndroidAssetDispatcher()) + start() + } + } + + @After + fun tearDown() { + mockWebServer.shutdown() + + // Clear Download + runBlocking { + val downloadedFile = File( + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), + "Globe.svg.html" + ) + + if (downloadedFile.exists()) { + downloadedFile.delete() + } + } + } + + @Test + fun testDownloadPrompt() { + homeScreen { }.dismissOnboarding() + + val defaultWebPage = TestAssetHelper.getDownloadAsset(mockWebServer) + + navigationToolbar { + }.openNewTabAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) + clickLinkMatchingText(defaultWebPage.content) + } + + downloadRobot { + verifyDownloadPrompt() + }.closePrompt {} + } + + @Test + fun testDownloadNotification() { + homeScreen { }.dismissOnboarding() + + val defaultWebPage = TestAssetHelper.getDownloadAsset(mockWebServer) + + navigationToolbar { + }.openNewTabAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) + clickLinkMatchingText(defaultWebPage.content) + } + + downloadRobot { + verifyDownloadPrompt() + }.clickDownload { + verifyDownloadNotificationPopup() + verifyDownloadNotificationShade() + } + } +} diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt index b28771f77..ff8f17b8b 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt @@ -76,6 +76,14 @@ class BrowserRobot { } } + fun clickLinkMatchingText(expectedText: String) { + val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + mDevice.waitNotNull(Until.findObject(By.text(expectedText)), TestAssetHelper.waitingTime) + + val element = mDevice.findObject(By.text(expectedText)) + element.click() + } + class Transition { private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) private fun threeDotButton() = onView( 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 new file mode 100644 index 000000000..531084fe1 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt @@ -0,0 +1,86 @@ +/* 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/. */ + +@file:Suppress("TooManyFunctions") + +package org.mozilla.fenix.ui.robots + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.RootMatchers.isDialog +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +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.UiDevice +import androidx.test.uiautomator.Until +import org.hamcrest.CoreMatchers +import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.TestAssetHelper +import org.mozilla.fenix.helpers.click +import org.mozilla.fenix.helpers.ext.waitNotNull + +/** + * Implementation of Robot Pattern for download UI handling. + */ + +class DownloadRobot { + + fun verifyDownloadPrompt() = assertDownloadPrompt() + + fun verifyDownloadNotificationPopup() = assertDownloadNotificationPopup() + + fun verifyDownloadNotificationShade() = assertDownloadNotificationShade() + + class Transition { + + fun clickDownload(interact: DownloadRobot.() -> Unit): DownloadRobot.Transition { + clickDownloadButton().click() + + DownloadRobot().interact() + return DownloadRobot.Transition() + } + + fun closePrompt(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + closePromptButton().click() + + BrowserRobot().interact() + return BrowserRobot.Transition() + } + } +} + +fun downloadRobot(interact: DownloadRobot.() -> Unit): DownloadRobot.Transition { + DownloadRobot().interact() + return DownloadRobot.Transition() +} + +private fun assertDownloadPrompt() { + mDevice.waitNotNull(Until.findObjects(By.res("org.mozilla.fenix.debug:id/download_button"))) +} + +private fun assertDownloadNotificationShade() { + val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + mDevice.openNotification() + mDevice.waitNotNull( + Until.findObjects(By.text("Download completed")), TestAssetHelper.waitingTime + ) + + // Go home (no UIDevice closeNotification) to close notification shade + mDevice.pressHome() +} + +private fun assertDownloadNotificationPopup() { + val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + mDevice.waitNotNull(Until.findObjects(By.text("Open")), TestAssetHelper.waitingTime) + onView(withId(R.id.download_notification_title)) + .check(matches(withText(CoreMatchers.containsString("Download completed")))) +} + +private fun closePromptButton() = + onView(withId(R.id.close_button)).inRoot(isDialog()).check(matches(isDisplayed())) + +private fun clickDownloadButton() = + onView(withText("Download")).inRoot(isDialog()).check(matches(isDisplayed()))