From c779889cbdd69a93721cd544056bb25428bdd35c Mon Sep 17 00:00:00 2001 From: Sawyer Blatz Date: Mon, 15 Jul 2019 14:25:31 -0700 Subject: [PATCH] Closes #4027: Adds search fragment UI tests (#4033) --- .../java/org/mozilla/fenix/ui/SearchTest.kt | 82 +++++++++ .../fenix/ui/robots/HomeScreenRobot.kt | 11 +- .../mozilla/fenix/ui/robots/SearchRobot.kt | 157 ++++++++++++++++++ 3 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt create mode 100644 app/src/androidTest/java/org/mozilla/fenix/ui/robots/SearchRobot.kt diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt new file mode 100644 index 000000000..ee6221067 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt @@ -0,0 +1,82 @@ +/* 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 org.junit.Rule +import org.junit.Test +import org.mozilla.fenix.helpers.HomeActivityTestRule +import org.mozilla.fenix.ui.robots.homeScreen + +/** + * Tests for verifying the search fragment + * + * Including: + * - Verify the toolbar, awesomebar, and shortcut bar are displayed + * - Select shortcut button + * - Select scan button + * + */ + +class SearchTest { + /* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping. + @get:Rule + val activityTestRule = HomeActivityTestRule() + + @Test + fun searchScreenItemsTest() { + homeScreen { }.dismissOnboarding() + + homeScreen { + }.openSearch { + verifySearchView() + verifyBrowserToolbar() + verifyScanButton() + verifyShortcutsButton() + } + } + + @Test + fun scanButtonTest() { + homeScreen { }.dismissOnboarding() + + homeScreen { + }.openSearch { + clickScanButton() + verifyScanPrompt() + clickDenyPermission() + clickScanButton() + clickAllowPermission() + } + } + + @Test + fun shortcutButtonTest() { + homeScreen { }.dismissOnboarding() + + homeScreen { + }.openSearch { + clickShortcutsButton() + verifySearchWithText() + clickDuckDuckGoEngineButton() + typeSearch() + verifyDuckDuckGoResults() + clickDuckDuckGoResult() + verifyDuckDuckGoURL() + } + } + + @Test + fun shortcutSearchEngineSettingsTest() { + homeScreen { }.dismissOnboarding() + + homeScreen { + }.openSearch { + clickShortcutsButton() + scrollToSearchEngineSettings() + clickSearchEngineSettings() + verifySearchEngineSettings() + } + } +} diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt index 66c711e54..a433fce32 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt @@ -82,7 +82,6 @@ class HomeScreenRobot { val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) fun openThreeDotMenu(interact: ThreeDotMenuRobot.() -> Unit): ThreeDotMenuRobot.Transition { - mDevice.waitForIdle() threeDotButton().perform(click()) @@ -90,6 +89,14 @@ class HomeScreenRobot { return ThreeDotMenuRobot.Transition() } + fun openSearch(interact: SearchRobot.() -> Unit): SearchRobot.Transition { + mDevice.waitForIdle() + navigationToolbar().perform(click()) + + SearchRobot().interact() + return SearchRobot.Transition() + } + fun dismissOnboarding() { openThreeDotMenu { }.openSettings { }.goBack { } } @@ -103,6 +110,8 @@ fun homeScreen(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) +private fun navigationToolbar() = onView(CoreMatchers.allOf(ViewMatchers.withText("Search or enter address"))) + private fun assertNavigationToolbar() = onView(CoreMatchers.allOf(ViewMatchers.withText("Search or enter address"))) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun assertHomeScreen() = onView(ViewMatchers.withResourceName("homeLayout")) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SearchRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SearchRobot.kt new file mode 100644 index 000000000..22eaf9698 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SearchRobot.kt @@ -0,0 +1,157 @@ +/* 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.recyclerview.widget.RecyclerView +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.ViewInteraction +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.typeText +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.contrib.RecyclerViewActions +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.withContentDescription +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.uiautomator.UiDevice +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.By +import androidx.test.uiautomator.UiObject +import androidx.test.uiautomator.UiScrollable +import androidx.test.uiautomator.Until +import org.hamcrest.CoreMatchers.allOf +import org.hamcrest.Matchers +import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.TestAssetHelper +import androidx.test.uiautomator.UiSelector +import org.hamcrest.CoreMatchers.startsWith + +/** + * Implementation of Robot Pattern for the search fragment. + */ +class SearchRobot { + fun verifySearchView() = assertSearchView() + fun verifyBrowserToolbar() = assertBrowserToolbarEditView() + fun verifyScanButton() = assertScanButton() + fun verifyScanPrompt() = assertScanPrompt() + fun verifyShortcutsButton() = assertShortcutsButton() + fun verifySearchWithText() = assertSearchWithText() + fun verifyDuckDuckGoResults() = assertDuckDuckGoResults() + fun verifyDuckDuckGoURL() = assertDuckDuckGoURL() + fun verifySearchEngineSettings() = assertSearchEngineSettings() + + fun clickScanButton() { + scanButton().perform(click()) + } + + fun clickDenyPermission() { + denyPermissionButton().click() + } + + fun clickAllowPermission() { + allowPermissionButton().click() + } + + fun clickShortcutsButton() { + shortcutsButton().perform(click()) + } + + fun typeSearch() { + browserToolbarEditView().perform(typeText("Mozilla")) + } + + fun clickDuckDuckGoEngineButton() { + duckDuckGoEngineButton().perform(click()) + } + + fun clickDuckDuckGoResult() { + mDevice.wait(Until.findObjects(By.text("DuckDuckGo")), TestAssetHelper.waitingTime) + awesomeBar().perform(RecyclerViewActions.actionOnItemAtPosition(0, click())) + } + + fun scrollToSearchEngineSettings(): UiScrollable { + val appView = UiScrollable(UiSelector().scrollable(true)) + appView.scrollTextIntoView("Search engine settings") + return appView + } + + fun clickSearchEngineSettings() { + onView(withText("Search engine settings")).perform(click()) + } + + class Transition { + val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + } +} + +private fun awesomeBar() = onView(withId(R.id.awesomeBar)) + +private fun browserToolbarEditView() = onView(Matchers.allOf(withId(R.id.mozac_browser_toolbar_edit_url_view))) + +private fun duckDuckGoEngineButton(): ViewInteraction { + mDevice.wait(Until.findObject(By.text("DuckDuckGo")), TestAssetHelper.waitingTime) + return onView(Matchers.allOf(withText("DuckDuckGo"))) +} + +private fun denyPermissionButton(): UiObject { + mDevice.wait(Until.findObjects(By.text("Deny")), TestAssetHelper.waitingTime) + return mDevice.findObject(UiSelector().text("Deny")) +} + +private fun allowPermissionButton(): UiObject { + mDevice.wait(Until.findObjects(By.text("Allow")), TestAssetHelper.waitingTime) + return mDevice.findObject(UiSelector().text("Allow")) +} + +private fun scanButton() = onView(allOf(withId(R.id.search_scan_button))) + +private fun shortcutsButton() = onView(withId(R.id.search_shortcuts_button)) + +private fun assertDuckDuckGoURL() { + onView(allOf(withText(startsWith("https://duckduckgo.com")))) + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +} + +private fun assertDuckDuckGoResults() { + val count = mDevice.wait(Until.findObjects(By.text(("DuckDuckGo"))), TestAssetHelper.waitingTime) + assert(count.size > 1) +} + +private fun assertSearchView() { + onView(allOf(withId(R.id.search_layout))) +} + +private fun assertBrowserToolbarEditView() = + onView(Matchers.allOf(withId(R.id.mozac_browser_toolbar_edit_url_view))) + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + +private fun assertScanPrompt() = + onView(Matchers.allOf(withText("Allow Firefox Preview to take pictures and record video?"))) + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + +private fun assertScanButton() = + onView(allOf(withText("Scan"))) + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + +private fun assertShortcutsButton() = + onView(allOf(withText("Shortcuts"))) + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + +private fun assertSearchWithText() = + onView(allOf(withText("SEARCH WITH"))) + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + +private fun assertSearchEngineSettings() = + onView(allOf(withText("Search engine"))) + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + +fun searchScreen(interact: SearchRobot.() -> Unit): SearchRobot.Transition { + SearchRobot().interact() + return SearchRobot.Transition() +} + +private fun goBackButton() = onView(allOf(withContentDescription("Navigate up")))