diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt new file mode 100644 index 000000000..841e41eaa --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt @@ -0,0 +1,16 @@ +/* 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.helpers + +import androidx.test.uiautomator.UiScrollable +import androidx.test.uiautomator.UiSelector + +object TestHelper { + fun scrollToElementByText(text: String): UiScrollable { + val appView = UiScrollable(UiSelector().scrollable(true)) + appView.scrollTextIntoView(text) + return appView + } +} diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAboutTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAboutTest.kt new file mode 100644 index 000000000..223d4c543 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAboutTest.kt @@ -0,0 +1,93 @@ +/* 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 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.Ignore +import org.junit.Test +import org.mozilla.fenix.helpers.AndroidAssetDispatcher +import org.mozilla.fenix.helpers.HomeActivityTestRule +import org.mozilla.fenix.ui.robots.homeScreen + +/** + * Tests for verifying the main three dot menu options + * + */ + +class SettingsAboutTest { + /* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping. + + private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + private lateinit var mockWebServer: MockWebServer + + @get:Rule + val activityTestRule = HomeActivityTestRule() + + @Before + fun setUp() { + mockWebServer = MockWebServer().apply { + setDispatcher(AndroidAssetDispatcher()) + start() + } + } + + @After + fun tearDown() { + mockWebServer.shutdown() + } + + @Test + // Walks through settings menu and sub-menus to ensure all items are present + fun settingsAboutItemsTest() { + // ABOUT + homeScreen { + }.openThreeDotMenu { + }.openSettings { + // ABOUT + verifyAboutHeading() + verifyHelp() + verifyRateOnGooglePlay() + verifyAboutFirefoxPreview() + } + } + + // ABOUT + @Ignore("This is a stub test, ignore for now") + @Test + fun verifyHelpRedirect() { + // Open 3dot (main) menu + // Select settings + // Click on "Help" + // Verify redirect to: https://support.mozilla.org/ + } + + @Ignore("This is a stub test, ignore for now") + @Test + fun verifyRateOnGooglePlayRedirect() { + // Open 3dot (main) menu + // Select settings + // Click on "Rate on Google Play" + // Verify Android "Open with Google Play Store" sub menu + } + + @Ignore("This is a stub test, ignore for now") + @Test + fun verifyAboutFirefoxPreview() { + // Open 3dot (main) menu + // Select settings + // Click on "Verify About Firefox Preview" + // Verify about page contains.... + // Build # + // Version # + // "Firefox Preview is produced by Mozilla" + // Day, Date, timestamp + // "Open source libraries we use" + } +} diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsBasicsTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsBasicsTest.kt index af601b61c..d45eabad9 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsBasicsTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsBasicsTest.kt @@ -14,6 +14,7 @@ import org.junit.Ignore import org.junit.Test import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.HomeActivityTestRule +import org.mozilla.fenix.ui.robots.homeScreen /** * Tests for verifying the main three dot menu options @@ -42,29 +43,35 @@ class SettingsBasicsTest { mockWebServer.shutdown() } - @Ignore("This is a stub test, ignore for now") @Test + // Walks through settings menu and sub-menus to ensure all items are present fun settingsMenuBasicsItemsTests() { - // Open 3dot (main) menu - // Select settings - - // Verify header: "Basics" - - // Verify item: "Search Engine" and default value: "Google" - // Open 3dot (main) menu - // Select settings - // Verify default search engine (Google) - // Select "Search engine" to change - // Verify menu choices: Google, Amazon.com, Bing, DuckDuckGo, Twitter, Wikipedia - // Verify label: "Show search suggestions" - // Verify search suggestions toggle, set to 'on' by default - // Verify label: "Show visited sites and bookmarks" - // Verify visited sites and bookmarks toggle, set to 'on' by default - - // Verify item: "Theme" and default value: "Light" - // Verify item: "Accessibility" - // Verify item: "Set as default browser" and default toggle value: "off" - // Verify item: "Search Engine" and default value: "Google" + homeScreen { + }.openThreeDotMenu { + }.openSettings { + verifyBasicsHeading() + verifySearchEngineButton() + // drill down to submenu + }.openSearchSubMenu { + verifyDefaultSearchEngineHeader() + verifySearchEngineList() + verifyShowSearchSuggestions() + verifyShowClipboardSuggestions() + verifySearchBrowsingHistory() + verifySearchBookmarks() + }.goBack { + }.openThemeSubMenu { + verifyThemes() + }.goBack { + }.openAccessibilitySubMenu { + verifyAutomaticFontSizing() + }.goBack { + // drill down to submenu + }.openDefaultBrowserSubMenu { + // verify item: set as default browser (duplicates, verify child of recyclerview) + // Verify label: Open links in private tab + }.goBack { + } } @Ignore("This is a stub test, ignore for now") diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsDeveloperToolsTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsDeveloperToolsTest.kt new file mode 100644 index 000000000..f60e50915 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsDeveloperToolsTest.kt @@ -0,0 +1,102 @@ +/* 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 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.Ignore +import org.junit.Test +import org.mozilla.fenix.helpers.AndroidAssetDispatcher +import org.mozilla.fenix.helpers.HomeActivityTestRule +import org.mozilla.fenix.ui.robots.homeScreen + +/** + * Tests for verifying the main three dot menu options + * + */ + +class SettingsDeveloperToolsTest { + /* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping. + + private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + private lateinit var mockWebServer: MockWebServer + + @get:Rule + val activityTestRule = HomeActivityTestRule() + + @Before + fun setUp() { + mockWebServer = MockWebServer().apply { + setDispatcher(AndroidAssetDispatcher()) + start() + } + } + + @After + fun tearDown() { + mockWebServer.shutdown() + } + + @Test + // Walks through settings developer tools menu and sub-menus to ensure all items are present + fun settingsDeveloperToolsItemsTest() { + homeScreen { + }.openThreeDotMenu { + }.openSettings { + verifyDeveloperToolsHeading() + verifyRemoteDebug() + } + } + + // DEVELOPER TOOLS + @Ignore("This is a stub test, ignore for now") + @Test + fun turnOnRemoteDebuggingViaUsb() { + // Open terminal + // Verify USB debugging is off + // Open 3dot (main) menu + // Select settings + // Toggle Remote debugging via USB to 'on' + // Open terminal + // Verify USB debugging is on + } + + // ABOUT + @Ignore("This is a stub test, ignore for now") + @Test + fun verifyHelpRedirect() { + // Open 3dot (main) menu + // Select settings + // Click on "Help" + // Verify redirect to: https://support.mozilla.org/ + } + + @Ignore("This is a stub test, ignore for now") + @Test + fun verifyRateOnGooglePlayRedirect() { + // Open 3dot (main) menu + // Select settings + // Click on "Rate on Google Play" + // Verify Android "Open with Google Play Store" sub menu + } + + @Ignore("This is a stub test, ignore for now") + @Test + fun verifyAboutFirefoxPreview() { + // Open 3dot (main) menu + // Select settings + // Click on "Verify About Firefox Preview" + // Verify about page contains.... + // Build # + // Version # + // "Firefox Preview is produced by Mozilla" + // Day, Date, timestamp + // "Open source libraries we use" + } +} 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 fb84b26db..b8b7c86fb 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt @@ -14,6 +14,7 @@ import org.junit.Ignore import org.junit.Test import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.HomeActivityTestRule +import org.mozilla.fenix.ui.robots.homeScreen /** * Tests for verifying the main three dot menu options @@ -42,8 +43,8 @@ class SettingsPrivacyTest { mockWebServer.shutdown() } - @Ignore("This is a stub test, ignore for now") @Test + // Walks through settings privacy menu and sub-menus to ensure all items are present fun settingsPrivacyItemsTest() { // Open 3dot (main) menu // Select settings @@ -83,6 +84,24 @@ class SettingsPrivacyTest { // Verify item: "Privacy notice" // Verify item: "Leak Canary" and default toggle value: "Off" + homeScreen { + }.openThreeDotMenu { + }.openSettings { + + // PRIVACY + verifyPrivacyHeading() + verifyEnhancedTrackingProtectionButton() + verifyEnhancedTrackingProtectionValue() + // drill down to submenu + verifyAddPrivateBrowsingShortcutButton() + verifySitePermissionsButton() + // drill down on search + verifyDeleteBrowsingDataButton() + verifyDeleteBrowsingDataOnQuitButton() + verifyDataCollectionButton() + verifyPrivacyNoticeButton() + verifyLeakCanaryButton() + } } @Ignore("This is a stub test, ignore for now") diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsSyncTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsSyncTest.kt index 1eeea63a8..21ce9cf77 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsSyncTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsSyncTest.kt @@ -44,15 +44,14 @@ class SettingsSyncTest { @Ignore("This is a stub test, ignore for now") @Test - // Walks through settings menu and sub-menus to ensure all items are present - fun settingsSyncMenusItemsTest() { + // Walks through settings sync menu and sub-menus to ensure all items are present + fun settingsSyncItemsTest() { // SYNC // Open 3dot (main) menu // Select settings // Verify header: "Turn on Sync" // Verify description: "Sync bookmarks, history, and more with your Firefox Account" - } // SYNC 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 94fec1194..0920c8dee 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 @@ -77,11 +77,11 @@ class BookmarksRobot { return LibraryRobot.Transition() } - fun openThreeDotMenu(interact: ThreeDotMenuBookmarks.() -> Unit): ThreeDotMenuBookmarks.Transition { + fun openThreeDotMenu(interact: ThreeDotMenuBookmarksRobot.() -> Unit): ThreeDotMenuBookmarksRobot.Transition { threeDotMenu().click() - ThreeDotMenuBookmarks().interact() - return ThreeDotMenuBookmarks.Transition() + ThreeDotMenuBookmarksRobot().interact() + return ThreeDotMenuBookmarksRobot.Transition() } } } 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 012ddec33..939f48b29 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 @@ -88,12 +88,12 @@ class HomeScreenRobot { class Transition { val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) - fun openThreeDotMenu(interact: ThreeDotMenuRobot.() -> Unit): ThreeDotMenuRobot.Transition { + fun openThreeDotMenu(interact: ThreeDotMenuMainRobot.() -> Unit): ThreeDotMenuMainRobot.Transition { mDevice.waitForIdle() threeDotButton().perform(click()) - ThreeDotMenuRobot().interact() - return ThreeDotMenuRobot.Transition() + ThreeDotMenuMainRobot().interact() + return ThreeDotMenuMainRobot.Transition() } fun openSearch(interact: SearchRobot.() -> Unit): SearchRobot.Transition { @@ -117,12 +117,12 @@ class HomeScreenRobot { .perform(click()) } - fun openTabsListThreeDotMenu(interact: ThreeDotMenuRobot.() -> Unit): ThreeDotMenuRobot.Transition { + fun openTabsListThreeDotMenu(interact: ThreeDotMenuMainRobot.() -> Unit): ThreeDotMenuMainRobot.Transition { mDevice.waitForIdle() tabsListThreeDotButton().perform(click()) - ThreeDotMenuRobot().interact() - return ThreeDotMenuRobot.Transition() + ThreeDotMenuMainRobot().interact() + return ThreeDotMenuMainRobot.Transition() } } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt index e6b8a7875..48939ba16 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt @@ -36,12 +36,12 @@ class NavigationToolbarRobot { return BrowserRobot.Transition() } - fun openThreeDotMenu(interact: ThreeDotMenuRobot.() -> Unit): ThreeDotMenuRobot.Transition { + fun openThreeDotMenu(interact: ThreeDotMenuMainRobot.() -> Unit): ThreeDotMenuMainRobot.Transition { mDevice.wait(Until.findObject(By.text("Menu")), waitingTime) threeDotButton().click() - ThreeDotMenuRobot().interact() - return ThreeDotMenuRobot.Transition() + ThreeDotMenuMainRobot().interact() + return ThreeDotMenuMainRobot.Transition() } fun openNewTabAndEnterToBrowser(url: Uri, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { 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 acdf7badb..e4b62e573 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 @@ -10,32 +10,100 @@ 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.withContentDescription import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import androidx.test.espresso.matcher.ViewMatchers.Visibility +import androidx.test.uiautomator.By +import androidx.test.uiautomator.Until import org.hamcrest.CoreMatchers -import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime +import org.mozilla.fenix.helpers.TestHelper +import org.mozilla.fenix.helpers.click /** * Implementation of Robot Pattern for the settings menu. */ class SettingsRobot { + // BASICS SECTION + fun verifyBasicsHeading() = assertBasicsHeading() + fun verifySearchEngineButton() = assertSearchEngineButton() + fun verifyThemeButton() = assertThemeButton() + fun verifyThemeSelected() = assertThemeSelected() + fun verifyAccessibilityButton() = assertAccessibilityButton() + fun verifySetAsDefaultBrowserButton() = assertSetAsDefaultBrowserButton() + + // PRIVACY SECTION + fun verifyPrivacyHeading() = assertPrivacyHeading() + fun verifyEnhancedTrackingProtectionButton() = assertEnhancedTrackingProtectionButton() + fun verifyEnhancedTrackingProtectionValue() = assertEnhancedTrackingProtectionValue() + fun verifyAddPrivateBrowsingShortcutButton() = assertAddPrivateBrowsingShortcutButton() + fun verifySitePermissionsButton() = assertSitePermissionsButton() + fun verifyDeleteBrowsingDataButton() = assertDeleteBrowsingDataButton() + fun verifyDeleteBrowsingDataOnQuitButton() = assertDeleteBrowsingDataOnQuitButton() + fun verifyDataCollectionButton() = assertDataCollectionButton() + fun verifyPrivacyNoticeButton() = assertPrivacyNoticeButton() + fun verifyLeakCanaryButton() = assertLeakCanaryButton() fun verifySettingsView() = assertSettingsView() + + // DEVELOPER TOOLS SECTION + fun verifyDeveloperToolsHeading() = assertDeveloperToolsHeading() + fun verifyRemoteDebug() = assertRemoteDebug() + + // ABOUT SECTION + fun verifyAboutHeading() = assertAboutHeading() + fun verifyHelp() = assertHelp() + fun verifyRateOnGooglePlay() = assertRateOnGooglePlay() + fun verifyAboutFirefoxPreview() = assertAboutFirefoxPreview() + class Transition { val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) fun goBack(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { - mDevice.waitForIdle() goBackButton().perform(ViewActions.click()) HomeScreenRobot().interact() return HomeScreenRobot.Transition() } + + fun openSearchSubMenu(interact: SettingsSubMenuSearchRobot.() -> Unit): SettingsSubMenuSearchRobot.Transition { + mDevice.waitForIdle() + fun searchEngineButton() = onView(ViewMatchers.withText("Search")) + searchEngineButton().click() + + SettingsSubMenuSearchRobot().interact() + return SettingsSubMenuSearchRobot.Transition() + } + + fun openThemeSubMenu(interact: SettingsSubMenuThemeRobot.() -> Unit): SettingsSubMenuThemeRobot.Transition { + mDevice.waitForIdle() + fun themeButton() = onView(ViewMatchers.withText("Theme")) + themeButton().click() + + SettingsSubMenuThemeRobot().interact() + return SettingsSubMenuThemeRobot.Transition() + } + + fun openAccessibilitySubMenu(interact: SettingsSubMenuAccessibilityRobot.() -> Unit): SettingsSubMenuAccessibilityRobot.Transition { + mDevice.waitForIdle() + fun accessibilityButton() = onView(ViewMatchers.withText("Accessibility")) + accessibilityButton().click() + + SettingsSubMenuAccessibilityRobot().interact() + return SettingsSubMenuAccessibilityRobot.Transition() + } + + fun openDefaultBrowserSubMenu(interact: SettingsSubMenuDefaultBrowserRobot.() -> Unit): SettingsSubMenuDefaultBrowserRobot.Transition { + mDevice.waitForIdle() + fun defaultBrowserButton() = onView(ViewMatchers.withText("Set as default browser")) + defaultBrowserButton().click() + + SettingsSubMenuDefaultBrowserRobot().interact() + return SettingsSubMenuDefaultBrowserRobot.Transition() + } } } @@ -43,13 +111,86 @@ private fun assertSettingsView() { // verify that we are in the correct library view assertBasicsHeading() assertPrivacyHeading() + assertDeveloperToolsHeading() + assertAboutHeading() } +// BASICS SECTION private fun assertBasicsHeading() = onView(ViewMatchers.withText("Basics")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -private fun assertPrivacyHeading() = onView(ViewMatchers.withText("Privacy")) +private fun assertSearchEngineButton() { + mDevice.wait(Until.findObject(By.text("Search")), waitingTime) + onView(ViewMatchers.withText("Search")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +} +private fun assertThemeButton() = onView(ViewMatchers.withText("Theme")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +private fun assertThemeSelected() = onView(ViewMatchers.withText("Light")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +private fun assertAccessibilityButton() = onView(ViewMatchers.withText("Accessibility")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +private fun assertSetAsDefaultBrowserButton() = onView(ViewMatchers.withText("Set as default browser")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -private fun goBackButton() = onView(CoreMatchers.allOf(withContentDescription("Navigate up"))) +// PRIVACY SECTION +private fun assertPrivacyHeading() { + onView(ViewMatchers.withText("Privacy")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +} +private fun assertEnhancedTrackingProtectionButton() = onView(ViewMatchers.withText("Enhanced Tracking Protection")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +private fun assertEnhancedTrackingProtectionValue() = onView(ViewMatchers.withText("On")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +private fun assertAddPrivateBrowsingShortcutButton() { + mDevice.wait(Until.findObject(By.text("Add private browsing shortcut")), waitingTime) + onView(ViewMatchers.withText("Add private browsing shortcut")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +} +private fun assertSitePermissionsButton() { + TestHelper.scrollToElementByText("Site permissions") + onView(ViewMatchers.withText("Site permissions")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +} +private fun assertDeleteBrowsingDataButton() = onView(ViewMatchers.withText("Delete browsing data")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +private fun assertDeleteBrowsingDataOnQuitButton() = onView(ViewMatchers.withText("Delete browsing data on quit")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +private fun assertDataCollectionButton() = onView(ViewMatchers.withText("Data collection")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +private fun assertPrivacyNoticeButton() = onView(ViewMatchers.withText("Privacy notice")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +private fun assertLeakCanaryButton() = onView(ViewMatchers.withText("LeakCanary")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -fun swipeToBottom() = onView(ViewMatchers.withId(R.id.recycler_view)).perform(ViewActions.swipeUp()) +// DEVELOPER TOOLS SECTION +private fun assertDeveloperToolsHeading() { + TestHelper.scrollToElementByText("Developer tools") + onView(ViewMatchers.withText("Developer tools")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +} +private fun assertRemoteDebug() = onView(ViewMatchers.withText("Remote debugging via USB")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + +// ABOUT SECTION +private fun assertAboutHeading() { + TestHelper.scrollToElementByText("About") + onView(ViewMatchers.withText("About")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +} +private fun assertHelp() { + TestHelper.scrollToElementByText("About Firefox Preview") + onView(ViewMatchers.withText("Help")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +} +private fun assertRateOnGooglePlay() { + TestHelper.scrollToElementByText("About Firefox Preview") + onView(ViewMatchers.withText("Rate on Google Play")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +} +private fun assertAboutFirefoxPreview() { + TestHelper.scrollToElementByText("About Firefox Preview") + onView(ViewMatchers.withText("About Firefox Preview")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +} + +private fun goBackButton() = onView(CoreMatchers.allOf(ViewMatchers.withContentDescription("Navigate up"))) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt new file mode 100644 index 000000000..5076c048b --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt @@ -0,0 +1,35 @@ +/* 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 +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import org.hamcrest.CoreMatchers + +/** + * Implementation of Robot Pattern for the settings search sub menu. + */ +class SettingsSubMenuAboutRobot { + + 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() + } + } +} + +private fun goBackButton() = + Espresso.onView(CoreMatchers.allOf(ViewMatchers.withContentDescription("Navigate up"))) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAccessibilityRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAccessibilityRobot.kt new file mode 100644 index 000000000..3bee4db8c --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAccessibilityRobot.kt @@ -0,0 +1,46 @@ +/* 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 +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import org.hamcrest.CoreMatchers + +/** + * Implementation of Robot Pattern for the settings Accessibility sub menu. + */ +class SettingsSubMenuAccessibilityRobot { + + fun verifyAutomaticFontSizing() = assertAutomaticFontSizing() + + 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() + } + } +} + +private fun assertAutomaticFontSizing() { + Espresso.onView(ViewMatchers.withText("Automatic Font Sizing")) + .check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + val strFont = "Font size will match your Android settings. Disable to manage font size here." + Espresso.onView(ViewMatchers.withText(strFont)) + .check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +} + +private fun goBackButton() = + Espresso.onView(CoreMatchers.allOf(ViewMatchers.withContentDescription("Navigate up"))) 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 new file mode 100644 index 000000000..97f34186e --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDefaultBrowserRobot.kt @@ -0,0 +1,43 @@ +/* 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.action.ViewActions +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import org.hamcrest.CoreMatchers + +/** + * Implementation of Robot Pattern for the settings DefaultBrowser sub menu. + */ +class SettingsSubMenuDefaultBrowserRobot { + + fun verifyOpenLinksInPrivateTab() = assertOpenLinksInPrivateTab() + + 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() + } + } +} + +private fun assertOpenLinksInPrivateTab() { + onView(ViewMatchers.withText("Open links in private tab")) + .check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +} + +private fun goBackButton() = + onView(CoreMatchers.allOf(ViewMatchers.withContentDescription("Navigate up"))) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt new file mode 100644 index 000000000..66c7105bc --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt @@ -0,0 +1,69 @@ +/* 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.action.ViewActions +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import org.hamcrest.CoreMatchers + +/** + * Implementation of Robot Pattern for the settings search sub menu. + */ +class SettingsSubMenuSearchRobot { + fun verifyDefaultSearchEngineHeader() = assertDefaultSearchEngineHeader() + fun verifySearchEngineList() = assertSearchEngineList() + fun verifyShowSearchSuggestions() = assertShowSearchSuggestions() + fun verifyShowClipboardSuggestions() = assertShowClipboardSuggestions() + fun verifySearchBrowsingHistory() = assertSearchBrowsingHistory() + fun verifySearchBookmarks() = assertSearchBookmarks() + + 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() + } + } +} + +private fun assertDefaultSearchEngineHeader() = onView(ViewMatchers.withText("Default search engine")) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +private fun assertSearchEngineList() { + onView(ViewMatchers.withText("Google")) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + onView(ViewMatchers.withText("Amazon.com")) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + onView(ViewMatchers.withText("Bing")) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + onView(ViewMatchers.withText("DuckDuckGo")) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + onView(ViewMatchers.withText("Twitter")) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + onView(ViewMatchers.withText("Wikipedia")) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +} + +private fun assertShowSearchSuggestions() = onView(ViewMatchers.withText("Show search suggestions")) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +private fun assertShowClipboardSuggestions() = onView(ViewMatchers.withText("Show clipboard suggestions")) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +private fun assertSearchBrowsingHistory() = onView(ViewMatchers.withText("Search browsing history")) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +private fun assertSearchBookmarks() = onView(ViewMatchers.withText("Search bookmarks")) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + +private fun goBackButton() = + onView(CoreMatchers.allOf(ViewMatchers.withContentDescription("Navigate up"))) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuThemeRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuThemeRobot.kt new file mode 100644 index 000000000..1f5b3e28a --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuThemeRobot.kt @@ -0,0 +1,49 @@ +/* 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 +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import org.hamcrest.CoreMatchers + +/** + * Implementation of Robot Pattern for the settings Theme sub menu. + */ +class SettingsSubMenuThemeRobot { + + fun verifyThemes() = assertThemes() + + 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() + } + } +} + +private fun assertThemes() { + onView(ViewMatchers.withText("Light")) + .check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + onView(ViewMatchers.withText("Dark")) + .check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + // Conditionally unavailable on API 25 + // onView(ViewMatchers.withText("Follow device theme")) + // .check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +} + +private fun goBackButton() = + Espresso.onView(CoreMatchers.allOf(ViewMatchers.withContentDescription("Navigate up"))) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuBookmarks.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuBookmarksRobot.kt similarity index 98% rename from app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuBookmarks.kt rename to app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuBookmarksRobot.kt index 78076dcda..f59a2845e 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuBookmarks.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuBookmarksRobot.kt @@ -13,7 +13,7 @@ import org.mozilla.fenix.helpers.click /** * Implementation of Robot Pattern for the Bookmarks three dot menu. */ -class ThreeDotMenuBookmarks { +class ThreeDotMenuBookmarksRobot { class Transition { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt similarity index 99% rename from app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuRobot.kt rename to app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt index 8a1a0101b..552894522 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt @@ -26,7 +26,7 @@ import org.mozilla.fenix.share.ShareFragment /** * Implementation of Robot Pattern for the three dot (main) menu. */ -class ThreeDotMenuRobot { +class ThreeDotMenuMainRobot { fun verifySettingsButton() = assertSettingsButton() fun verifyLibraryButton() = assertLibraryButton() fun verifyHelpButton() = assertHelpButton() diff --git a/automation/taskcluster/androidTest/ui-test.sh b/automation/taskcluster/androidTest/ui-test.sh index f840cf456..05435ad5a 100755 --- a/automation/taskcluster/androidTest/ui-test.sh +++ b/automation/taskcluster/androidTest/ui-test.sh @@ -89,6 +89,13 @@ function failure_check() { exit $exitcode } +echo +echo "FLANK VERSION" +echo +$JAVA_BIN -jar $FLANK_BIN --version +echo +echo + echo echo "EXECUTE TEST(S)" echo diff --git a/taskcluster/docker/ui-tests/Dockerfile b/taskcluster/docker/ui-tests/Dockerfile index babaad64a..d3d216e3b 100644 --- a/taskcluster/docker/ui-tests/Dockerfile +++ b/taskcluster/docker/ui-tests/Dockerfile @@ -10,6 +10,7 @@ USER worker:worker ENV GOOGLE_SDK_DOWNLOAD ./gcloud.tar.gz ENV GOOGLE_SDK_VERSION 233 +ENV FLANK_VERSION v8.0.1 ENV TEST_TOOLS /builds/worker/test-tools ENV PATH ${PATH}:${TEST_TOOLS}:${TEST_TOOLS}/google-cloud-sdk/bin @@ -23,7 +24,7 @@ RUN curl https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud && ${TEST_TOOLS}/google-cloud-sdk/install.sh --quiet \ && ${TEST_TOOLS}/google-cloud-sdk/bin/gcloud --quiet components update -RUN URL_FLANK_BIN=$(curl -s "https://api.github.com/repos/TestArmada/flank/releases/latest" | grep "browser_download_url*" | sed -r "s/\"//g" | cut -d ":" -f3) \ +RUN URL_FLANK_BIN=$(curl -s "https://api.github.com/repos/TestArmada/flank/releases" | grep "browser_download_url*" | grep "${FLANK_VERSION}" | sed -r "s/\"//g" | cut -d ":" -f3) \ && wget "https:${URL_FLANK_BIN}" -O ${TEST_TOOLS}/flank.jar \ && chmod +x ${TEST_TOOLS}/flank.jar