Unverified Commit 095477e0 authored by Kadeem M's avatar Kadeem M Committed by GitHub
Browse files

Adding UI tests for the Basic Menu settings. 馃幉 !!!! (#6346)

* Added UI tests for the basic settings menu

* Disabled toggleSearchSuggestions test
parent 6019adaf
......@@ -4,9 +4,11 @@
package org.mozilla.fenix.helpers
import android.graphics.Bitmap
import android.view.View
import org.hamcrest.CoreMatchers.not
import org.hamcrest.Matcher
import org.mozilla.fenix.helpers.matchers.BitmapDrawableMatcher
import androidx.test.espresso.matcher.ViewMatchers.isChecked as espressoIsChecked
import androidx.test.espresso.matcher.ViewMatchers.isEnabled as espressoIsEnabled
import androidx.test.espresso.matcher.ViewMatchers.isSelected as espressoIsSelected
......@@ -30,3 +32,5 @@ private fun maybeInvertMatcher(matcher: Matcher<View>, useUnmodifiedMatcher: Boo
useUnmodifiedMatcher -> matcher
else -> not(matcher)
}
fun withBitmapDrawable(bitmap: Bitmap, name: String): Matcher<View>? = BitmapDrawableMatcher(bitmap, name)
package org.mozilla.fenix.helpers.assertions
import android.view.View
import androidx.test.espresso.ViewAssertion
import mozilla.components.browser.awesomebar.BrowserAwesomeBar
class AwesomeBarAssertion {
companion object {
fun suggestionsAreGreaterThan(minimumSuggestions: Int): ViewAssertion {
return ViewAssertion { view, noViewFoundException ->
if (noViewFoundException != null) throw noViewFoundException
val suggestionsCount = getSuggestionCountFromView(view)
if (suggestionsCount <= minimumSuggestions)
throw AssertionError("The suggestion count is less than or equal to the minimum suggestions")
}
}
fun suggestionsAreEqualTo(expectedItemCount: Int): ViewAssertion {
return ViewAssertion { view, noViewFoundException ->
if (noViewFoundException != null) throw noViewFoundException
val suggestionsCount = getSuggestionCountFromView(view)
if (suggestionsCount != expectedItemCount)
throw AssertionError("The expected item count is $expectedItemCount, and the suggestions count within the AwesomeBar is $suggestionsCount")
}
}
private fun getSuggestionCountFromView(view: View): Int {
return (view as BrowserAwesomeBar).adapter?.itemCount
?: throw AssertionError("This view is not of type BrowserAwesomeBar")
}
}
}
package org.mozilla.fenix.helpers.matchers
import android.graphics.Bitmap
import android.view.View
import android.widget.ImageView
import androidx.test.espresso.matcher.BoundedMatcher
import org.hamcrest.Description
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.StateListDrawable
import android.graphics.drawable.Drawable
class BitmapDrawableMatcher(private val bitmap: Bitmap, private val name: String) :
BoundedMatcher<View, ImageView>(ImageView::class.java) {
override fun describeTo(description: Description?) {
description?.appendText("has image drawable resource $name")
}
override fun matchesSafely(item: ImageView): Boolean {
return sameBitmap(item.drawable, bitmap)
}
private fun sameBitmap(drawable: Drawable?, otherBitmap: Bitmap): Boolean {
var currentDrawable = drawable ?: return false
if (currentDrawable is StateListDrawable) {
currentDrawable = currentDrawable.current
}
if (currentDrawable is BitmapDrawable) {
val bitmap = currentDrawable.bitmap
return bitmap.sameAs(otherBitmap)
}
return false
}
}
......@@ -52,11 +52,11 @@ class SearchTest {
homeScreen {
}.openSearch {
verifySearchWithText()
clickDuckDuckGoEngineButton()
clickSearchEngineButton("DuckDuckGo")
typeSearch("mozilla")
verifyDuckDuckGoResults()
clickDuckDuckGoResult()
verifyDuckDuckGoURL()
verifySearchEngineResults("DuckDuckGo")
clickSearchEngineResult("DuckDuckGo")
verifySearchEngineURL("DuckDuckGo")
}
}
......
......@@ -10,12 +10,17 @@ import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.Ignore
import org.mozilla.fenix.FenixApplication
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestAssetHelper.getLoremIpsumAsset
import org.mozilla.fenix.ui.robots.checkTextSizeOnWebsite
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
/**
* Tests for verifying the main three dot menu options
......@@ -29,7 +34,7 @@ class SettingsBasicsTest {
private lateinit var mockWebServer: MockWebServer
@get:Rule
val activityTestRule = HomeActivityTestRule()
val activityIntentTestRule = HomeActivityIntentTestRule()
@Before
fun setUp() {
......@@ -45,7 +50,8 @@ class SettingsBasicsTest {
}
private fun getUiTheme(): Boolean {
val mode = activityTestRule.activity.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK)
val mode =
activityIntentTestRule.activity.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK)
return when (mode) {
Configuration.UI_MODE_NIGHT_YES -> true // dark theme is set
......@@ -68,6 +74,7 @@ class SettingsBasicsTest {
verifySearchEngineList()
verifyShowSearchSuggestions()
verifyShowSearchShortcuts()
verifyShowClipboardSuggestions()
verifySearchBrowsingHistory()
verifySearchBookmarks()
......@@ -76,7 +83,7 @@ class SettingsBasicsTest {
verifyThemes()
}.goBack {
}.openAccessibilitySubMenu {
verifyAutomaticFontSizing()
verifyAutomaticFontSizingMenuItems()
}.goBack {
// drill down to submenu
}.openDefaultBrowserSubMenu {
......@@ -86,49 +93,75 @@ class SettingsBasicsTest {
}
}
@Ignore("This is a stub test, ignore for now")
@Test
fun selectNewDefaultSearchEngine() {
// Open 3dot (main) menu
// Select settings
// Select "Search engine"
// Choose: DuckDuckGo
// Back arrow to Home
// Verify DuckDuckGo icon in Navigation bar
// Goes through the settings and changes the default search engine, then verifies it has changed.
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
changeDefaultSearchEngine("DuckDuckGo")
}.goBack {
}.goBack {
verifyDefaultSearchEngine("DuckDuckGo")
}
}
@Ignore("This is a stub test, ignore for now")
@Ignore("This test works locally, fails on firebase. https://github.com/mozilla-mobile/fenix/issues/8174")
@Test
fun toggleSearchSuggestions() {
// Enter: "mozilla" in navigation bar
// Verify more than one suggesion provided
// Open 3dot (main) menu
// Select settings
// Select "Search engine"
// Toggle 'Show search suggestions' to 'off'
// Back arrow twice to home screen
// Enter: "mozilla" in navigation bar
// Verify no suggestions provided
// Goes through the settings and changes the search suggestion toggle, then verifies it changes.
homeScreen {
}.openNavigationToolbar {
verifySearchSuggestionsAreMoreThan(1, "mozilla")
}.goBack {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
disableShowSearchSuggestions()
}.goBack {
}.goBack {
}.openNavigationToolbar {
verifySearchSuggestionsAreEqualTo(0, "mozilla")
}
}
@Ignore("This is a stub test, ignore for now")
@Test
fun toggleShowVisitedSitesAndBookmarks() {
// Visit 3 static sites
// Bookmark 2 of them
// Open 3dot (main) menu
// Enter navigation bar and verify visited sites appear
// Verify bookmarks exist
// Open 3dot (main) menu
// Select settings
// Select "Search engine"
// Toggle off "Show visited sites and bookmarks"
// Back arrow twice to home screen
// Verify history and bookmarks are gone
// Bookmarks a few websites, toggles the history and bookmarks setting to off, then verifies if the visited and bookmarked websites do not show in the suggestions.
val page1 = getGenericAsset(mockWebServer, 1)
val page2 = getGenericAsset(mockWebServer, 2)
val page3 = getGenericAsset(mockWebServer, 3)
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(page1.url) {
verifyPageContent(page1.content)
}.openThreeDotMenu {
clickAddBookmarkButton()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(page2.url) {
verifyPageContent(page2.content)
}.openThreeDotMenu {
clickAddBookmarkButton()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(page3.url) {
verifyPageContent(page3.content)
}
navigationToolbar {
verifyNoHistoryBookmarks()
}
}
@Test
fun changeThemeSetting() {
// Goes through the settings and changes the default search engine, then verifies it changes.
homeScreen {
}.openThreeDotMenu {
}.openSettings {
......@@ -141,40 +174,48 @@ class SettingsBasicsTest {
}
}
@Ignore("This is a stub test, ignore for now")
@Test
fun changeAccessibiltySettings() {
// Open 3dot (main) menu
// Select settings
// Select Accessibility
// Verify header: "Automatic Font Sizing"
// Verify description: "Font size will match your Android settings. Disable to manage font size here"
// Verify toggle is set to 'on' by default
// Toggle font size to off
// Verify that new sub-menu items appear....
// Verify header: "Font Size"
// Verify description: "Make text on websites larger or smaller"
// Verify slider bar exists
// Verify slider bar default value set to 100%
// Verify sample text "The quick brown fox..." appears 4 times
// Move slider bar to 180%
// Verify that text grows to 180%
// Back error twice to home screen
// Open static website in navigation bar
// Verify that text is now at 180%
// Select settings
// Select Accessibility
// Toggle font size back to 'off'
// Verify that "Font Size" header, description, slider bar and sample text all disappear
// Goes through the settings and changes the default text on a webpage, then verifies if the text has changed.
val fenixApp = activityIntentTestRule.activity.applicationContext as FenixApplication
val webpage = getLoremIpsumAsset(mockWebServer).url
// This value will represent the text size percentage the webpage will scale to. The default value is 100%.
val textSizePercentage = 180
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAccessibilitySubMenu {
clickFontSizingSwitch()
verifyNewMenuItems()
changeTextSizeSlider(textSizePercentage)
verifyTextSizePercentage(textSizePercentage)
}.goBack {
}.goBack {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(webpage) {
checkTextSizeOnWebsite(textSizePercentage, fenixApp.components)
}.openHomeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAccessibilitySubMenu {
clickFontSizingSwitch()
verifyNewMenuItemsAreGone()
}
}
@Ignore("This is a stub test, ignore for now")
@Test
fun changeDefaultBrowserSetting() {
// Open 3dot (main) menu
// Select settings
// Verify that "Set as default browser toggle is set to 'off' (default)
// Turn default browser toggle 'on'
// Verify that Andrdoid "Default Apps" menu appears
// Opens settings and toggles the default browser setting to on. The device settings open and allows the user to set a default browser.
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openDefaultBrowserSubMenu {
verifyDefaultBrowserIsDisabled()
clickDefaultBrowserSwitch()
verifyAndroidDefaultAppsMenuAppears()
}
}
}
......@@ -7,6 +7,7 @@
package org.mozilla.fenix.ui.robots
import androidx.recyclerview.widget.RecyclerView
import android.graphics.Bitmap
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.action.ViewActions.click
......@@ -14,12 +15,12 @@ import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
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.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.espresso.matcher.ViewMatchers.Visibility
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
import androidx.test.espresso.matcher.ViewMatchers.Visibility
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
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
......@@ -34,6 +35,8 @@ import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.click
import org.mozilla.fenix.helpers.ext.waitNotNull
import org.mozilla.fenix.components.Search
import org.mozilla.fenix.helpers.withBitmapDrawable
/**
* Implementation of Robot Pattern for the home screen menu.
......@@ -53,6 +56,7 @@ class HomeScreenRobot {
fun verifyHomeWordmark() = assertHomeWordmark()
fun verifyHomeToolbar() = assertHomeToolbar()
fun verifyHomeComponent() = assertHomeComponent()
fun verifyDefaultSearchEngine(searchEngine: String) = verifySearchEngineIcon(searchEngine)
// First Run elements
fun verifyWelcomeHeader() = assertWelcomeHeader()
......@@ -81,6 +85,7 @@ class HomeScreenRobot {
// Private mode elements
fun verifyPrivateSessionHeader() = assertPrivateSessionHeader()
fun verifyPrivateSessionMessage(visible: Boolean = true) = assertPrivateSessionMessage(visible)
fun verifyPrivateTabsCloseTabsButton() = assertPrivateTabsCloseTabsButton()
......@@ -114,7 +119,6 @@ class HomeScreenRobot {
fun typeCollectionName(name: String) {
mDevice.wait(Until.findObject(By.res("name_collection_edittext")), waitingTime)
collectionNameTextField().perform(ViewActions.replaceText(name))
collectionNameTextField().perform(ViewActions.pressImeActionButton())
}
......@@ -206,6 +210,13 @@ class HomeScreenRobot {
HomeScreenRobot().interact()
return Transition()
}
fun openNavigationToolbar(interact: NavigationToolbarRobot.() -> Unit): NavigationToolbarRobot.Transition {
assertNavigationToolbar().perform(click())
NavigationToolbarRobot().interact()
return NavigationToolbarRobot.Transition()
}
}
}
......@@ -215,6 +226,7 @@ fun homeScreen(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition
}
val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
private fun navigationToolbar() =
onView(CoreMatchers.allOf(withText("Search or enter address")))
......@@ -279,6 +291,19 @@ private fun assertHomeComponent() = onView(ViewMatchers.withResourceName("sessio
private fun threeDotButton() = onView(allOf(withId(R.id.menuButton)))
private fun verifySearchEngineIcon(searchEngineIcon: Bitmap, searchEngineName: String) {
onView(withId(R.id.search_engine_icon))
.check(matches(withBitmapDrawable(searchEngineIcon, searchEngineName)))
}
private fun getSearchEngine(searchEngineName: String) =
Search(appContext).searchEngineManager.getDefaultSearchEngine(appContext, searchEngineName)
private fun verifySearchEngineIcon(searchEngineName: String) {
val ddgSearchEngine = getSearchEngine(searchEngineName)
verifySearchEngineIcon(ddgSearchEngine.icon, ddgSearchEngine.name)
}
// First Run elements
private fun assertWelcomeHeader() =
onView(CoreMatchers.allOf(withText("Welcome to Firefox Preview!")))
......@@ -418,7 +443,8 @@ private fun assertExistingOpenTabs(title: String) =
private fun tabsListThreeDotButton() = onView(allOf(withId(R.id.tabs_overflow_button)))
private fun collectionThreeDotButton() = onView(allOf(withId(R.id.collection_overflow_button)))
private fun collectionThreeDotButton() =
onView(allOf(withId(R.id.collection_overflow_button)))
private fun collectionNameTextField() =
onView(allOf(ViewMatchers.withResourceName("name_collection_edittext")))
......
......@@ -10,26 +10,49 @@ import android.net.Uri
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.pressImeActionButton
import androidx.test.espresso.action.ViewActions.replaceText
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.action.ViewActions.typeText
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
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.not
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.click
import org.mozilla.fenix.helpers.ext.waitNotNull
import org.mozilla.fenix.helpers.assertions.AwesomeBarAssertion.Companion.suggestionsAreEqualTo
import org.mozilla.fenix.helpers.assertions.AwesomeBarAssertion.Companion.suggestionsAreGreaterThan
/**
* Implementation of Robot Pattern for the URL toolbar.
*/
class NavigationToolbarRobot {
fun verifySearchSuggestionsAreMoreThan(suggestionSize: Int, searchTerm: String) =
assertSuggestionsAreMoreThan(suggestionSize, searchTerm)
fun verifySearchSuggestionsAreEqualTo(suggestionSize: Int, searchTerm: String) =
assertSuggestionsAreEqualTo(suggestionSize, searchTerm)
fun verifyNoHistoryBookmarks() = assertNoHistoryBookmarks()
class Transition {
val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
fun enterURLAndEnterToBrowser(url: Uri, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
mDevice.waitNotNull(Until.findObject(By.res("org.mozilla.fenix.debug:id/toolbar")), waitingTime)
fun enterURLAndEnterToBrowser(
url: Uri,
interact: BrowserRobot.() -> Unit
): BrowserRobot.Transition {
mDevice.waitNotNull(
Until.findObject(By.res("org.mozilla.fenix.debug:id/toolbar")),
waitingTime
)
urlBar().click()
awesomeBar().perform(replaceText(url.toString()), pressImeActionButton())
......@@ -45,7 +68,10 @@ class NavigationToolbarRobot {
return ThreeDotMenuMainRobot.Transition()
}
fun openNewTabAndEnterToBrowser(url: Uri, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
fun openNewTabAndEnterToBrowser(
url: Uri,
interact: BrowserRobot.() -> Unit
): BrowserRobot.Transition {
mDevice.waitNotNull(Until.findObject(By.descContains("Add tab")), waitingTime)
newTab().click()
awesomeBar().perform(replaceText(url.toString()), pressImeActionButton())
......@@ -75,6 +101,13 @@ class NavigationToolbarRobot {
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun goBack(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
goBackButton()
HomeScreenRobot().interact()
return HomeScreenRobot.Transition()
}
}
}
......@@ -83,10 +116,34 @@ fun navigationToolbar(interact: NavigationToolbarRobot.() -> Unit): NavigationTo
return NavigationToolbarRobot.Transition()
}
private fun dismissOnboardingButton() = onView(ViewMatchers.withId(R.id.close_onboarding))
private fun urlBar() = onView(ViewMatchers.withId(R.id.toolbar))
private fun awesomeBar() = onView(ViewMatchers.withId(R.id.mozac_browser_toolbar_edit_url_view))
private fun threeDotButton() = onView(ViewMatchers.withContentDescription("Menu"))
private fun newTab() = onView(ViewMatchers.withContentDescription("Add tab"))
private fun fillLinkButton() = onView(ViewMatchers.withId(R.id.clipboard_url))
private fun clearAddressBar() = onView(ViewMatchers.withId(R.id.mozac_browser_toolbar_clear_view))
private fun assertSuggestionsAreEqualTo(suggestionSize: Int, searchTerm: String) {
mDevice.waitForIdle()
awesomeBar().perform(typeText(searchTerm))
mDevice.waitForIdle()
onView(withId(R.id.awesomeBar)).check(suggestionsAreEqualTo(suggestionSize))
}
private fun assertSuggestionsAreMoreThan(suggestionSize: Int, searchTerm: String) {
mDevice.waitForIdle()
awesomeBar().perform(typeText(searchTerm))
mDevice.waitForIdle()
onView(withId(R.id.awesomeBar)).check(suggestionsAreGreaterThan(suggestionSize))
}
private fun assertNoHistoryBookmarks() {
onView(withId(R.id.container))
.check(matches(not(hasDescendant(withText("Test_Page_1")))))
.check(matches(not(hasDescendant(withText("Test_Page_2")))))
.check(matches(not(hasDescendant(withText("Test_Page_3")))))
}
private fun dismissOnboardingButton() = onView(withId(R.id.close_onboarding))
private fun urlBar() = onView(withId(R.id.toolbar))
private fun awesomeBar() = onView(withId(R.id.mozac_browser_toolbar_edit_url_view))
private fun threeDotButton() = onView(withContentDescription("Menu"))
private fun newTab() = onView(withContentDescription("Add tab"))
private fun fillLinkButton() = onView(withId(R.id.fill_link_from_clipboard))
private fun clearAddressBar() = onView(withId(R.id.mozac_browser_toolbar_clear_view))
private fun goBackButton() = mDevice.pressBack()
......@@ -39,8 +39,10 @@ class SearchRobot {
fun verifyBrowserToolbar() = assertBrowserToolbarEditView()
fun verifyScanButton() = assertScanButton()
fun verifySearchWithText() = assertSearchWithText()
fun verifyDuckDuckGoResults() = assertDuckDuckGoResults()
fun verifyDuckDuckGoURL() = assertDuckDuckGoURL()
fun verifySearchEngineResults(searchEngineName: String) =
assertSearchEngineResults(searchEngineName)
fun verifySearchEngineURL(searchEngineName: String) = assertSearchEngineURL(searchEngineName)
fun verifySearchSettings() = assertSearchSettings()
fun verifySearchBarEmpty() = assertSearchBarEmpty()
......@@ -60,13 +62,21 @@ class SearchRobot {<