Bug 1845680 - Fenix: unified search UI tests for Default and Manage search engines menus

fenix/117.0
oana.horvath 10 months ago committed by mergify[bot]
parent b7db455bda
commit fc1335b17f

@ -0,0 +1,120 @@
/* 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 android.content.Context
import androidx.test.platform.app.InstrumentationRegistry
import kotlinx.coroutines.runBlocking
import mozilla.appservices.places.BookmarkRoot
import mozilla.components.browser.icons.IconRequest
import mozilla.components.browser.icons.generator.DefaultIconGenerator
import mozilla.components.browser.state.search.SearchEngine
import mozilla.components.browser.storage.sync.PlacesBookmarksStorage
import mozilla.components.browser.storage.sync.PlacesHistoryStorage
import mozilla.components.concept.storage.PageVisit
import mozilla.components.concept.storage.VisitType
import mozilla.components.feature.search.ext.createSearchEngine
import okhttp3.mockwebserver.MockWebServer
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.search.SearchEngineSource.None.searchEngine
object MockBrowserDataHelper {
val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
/**
* Adds a new bookmark item, visible in the Bookmarks folder.
*
* @param url The URL of the bookmark item to add. URLs should use the "https://example.com" format.
* @param title The title of the bookmark item to add.
* @param position Example for the position param: 1u, 2u, etc.
*/
fun createBookmarkItem(url: String, title: String, position: UInt?) {
runBlocking {
PlacesBookmarksStorage(context)
.addItem(
BookmarkRoot.Mobile.id,
url,
title,
position,
)
}
}
/**
* Adds a new history item, visible in the History folder.
*
* @param url The URL of the history item to add. URLs should use the "https://example.com" format.
*/
fun createHistoryItem(url: String) {
runBlocking {
PlacesHistoryStorage(appContext)
.recordVisit(
url,
PageVisit(VisitType.LINK),
)
}
}
/**
* Creates a new tab with a webpage, also visible in the History folder.
*
* URLs should use the "https://example.com" format.
*/
fun createTabItem(url: String) {
runBlocking {
appContext.components.useCases.tabsUseCases.addTab(url)
}
}
/**
* Triggers a search for the provided search term in a new tab.
*
*/
fun createSearchHistory(searchTerm: String) {
appContext.components.useCases.searchUseCases.newTabSearch.invoke(searchTerm)
}
/**
* Creates a new custom search engine object.
*
* @param mockWebServer The mockWebServer instance.
* @param searchEngineName The name of the new search engine.
*/
private fun createCustomSearchEngine(mockWebServer: MockWebServer, searchEngineName: String): SearchEngine {
val searchString =
"http://localhost:${mockWebServer.port}/pages/searchResults.html?search={searchTerms}"
return createSearchEngine(
name = searchEngineName,
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
}
/**
* Adds a new custom search engine to the apps Search Engines list.
*
* @param searchEngine Use createCustomSearchEngine method to create one.
*/
fun addCustomSearchEngine(mockWebServer: MockWebServer, searchEngineName: String) {
val searchEngine = createCustomSearchEngine(mockWebServer, searchEngineName)
appContext.components.useCases.searchUseCases.addSearchEngine(searchEngine)
}
/**
* Adds and selects as default a new custom search engine to the apps Search Engines list.
*
* @param searchEngine Use createCustomSearchEngine method to create one.
*/
fun setCustomSearchEngine(mockWebServer: MockWebServer, searchEngineName: String) {
val searchEngine = createCustomSearchEngine(mockWebServer, searchEngineName)
with(appContext.components.useCases.searchUseCases) {
addSearchEngine(searchEngine)
selectSearchEngine(searchEngine)
}
}
}

@ -52,6 +52,7 @@ import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import junit.framework.AssertionFailedError
import mozilla.components.browser.state.search.SearchEngine
import mozilla.components.browser.state.state.availableSearchEngines
import mozilla.components.support.ktx.android.content.appName
import org.hamcrest.CoreMatchers
import org.hamcrest.CoreMatchers.allOf
@ -345,13 +346,6 @@ object TestHelper {
fun getStringResource(id: Int, argument: String = appName) = appContext.resources.getString(id, argument)
fun setCustomSearchEngine(searchEngine: SearchEngine) {
with(appContext.components.useCases.searchUseCases) {
addSearchEngine(searchEngine)
selectSearchEngine(searchEngine)
}
}
// Permission allow dialogs differ on various Android APIs
fun grantSystemPermission() {
val whileUsingTheAppPermissionButton: UiObject =
@ -423,7 +417,7 @@ object TestHelper {
/**
* Changes the default language of the entire device, not just the app.
*/
private fun setSystemLocale(locale: Locale) {
fun setSystemLocale(locale: Locale) {
val activityManagerNative = Class.forName("android.app.ActivityManagerNative")
val am = activityManagerNative.getMethod("getDefault", *arrayOfNulls(0))
.invoke(activityManagerNative, *arrayOfNulls(0))
@ -498,4 +492,24 @@ object TestHelper {
.contains("mInputShown=true"),
)
}
/**
* The list of Search engines for the "home" region of the user.
* For en-us it will return the 6 engines selected by default: Google, Bing, DuckDuckGo, Amazon, Ebay, Wikipedia.
*/
fun getRegionSearchEnginesList(): List<SearchEngine> {
val searchEnginesList = appContext.components.core.store.state.search.regionSearchEngines
assertTrue("Search engines list returned nothing", searchEnginesList.isNotEmpty())
return searchEnginesList
}
/**
* The list of Search engines available to be added by user choice.
* For en-us it will return the 2 engines: Reddit, Youtube.
*/
fun getAvailableSearchEngines(): List<SearchEngine> {
val searchEnginesList = appContext.components.core.store.state.search.availableSearchEngines
assertTrue("Search engines list returned nothing", searchEnginesList.isNotEmpty())
return searchEnginesList
}
}

@ -9,9 +9,6 @@ import android.hardware.camera2.CameraManager
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.core.net.toUri
import androidx.test.espresso.Espresso
import mozilla.components.browser.icons.IconRequest
import mozilla.components.browser.icons.generator.DefaultIconGenerator
import mozilla.components.feature.search.ext.createSearchEngine
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Assume
@ -23,6 +20,7 @@ import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.Constants
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MatcherHelper
import org.mozilla.fenix.helpers.MockBrowserDataHelper.setCustomSearchEngine
import org.mozilla.fenix.helpers.SearchDispatcher
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
@ -47,7 +45,7 @@ import org.mozilla.fenix.ui.robots.searchScreen
class ComposeSearchTest {
lateinit var searchMockServer: MockWebServer
lateinit var queryString: String
private val queryString: String = "firefox"
private val generalEnginesList = listOf("DuckDuckGo", "Google", "Bing")
private val topicEnginesList = listOf("Amazon.com", "Wikipedia", "eBay")
@ -229,12 +227,10 @@ class ComposeSearchTest {
@Test
fun accessSearchSettingFromSearchSelectorMenuTest() {
queryString = "firefox"
searchScreen {
clickSearchSelectorButton()
}.clickSearchEngineSettings {
verifySearchSettingsToolbar()
verifyToolbarText("Search")
openDefaultSearchEngineMenu()
changeDefaultSearchEngine("DuckDuckGo")
TestHelper.exitMenu()
@ -242,14 +238,12 @@ class ComposeSearchTest {
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
verifyUrl("firefox")
verifyUrl(queryString)
}
}
@Test
fun clearSearchTest() {
queryString = "test"
homeScreen {
}.openSearch {
typeSearch(queryString)
@ -262,16 +256,9 @@ class ComposeSearchTest {
@SmokeTest
@Test
fun searchGroupShowsInRecentlyVisitedTest() {
queryString = "test search"
val searchEngineName = "TestSearchEngine"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(TestHelper.appContext, IconRequest(searchString)).bitmap,
)
TestHelper.setCustomSearchEngine(customSearchEngine)
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -300,16 +287,9 @@ class ComposeSearchTest {
val secondPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 2).url
val originPageUrl =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search=test%20search".toUri()
queryString = "test search"
val searchEngineName = "TestSearchEngine"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(TestHelper.appContext, IconRequest(searchString)).bitmap,
)
TestHelper.setCustomSearchEngine(customSearchEngine)
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -348,16 +328,9 @@ class ComposeSearchTest {
@Ignore("Failing due to known bug, see https://github.com/mozilla-mobile/fenix/issues/23818")
@Test
fun searchGroupGeneratedInTheSameTabTest() {
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(TestHelper.appContext, IconRequest(searchString)).bitmap,
)
TestHelper.setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -378,16 +351,9 @@ class ComposeSearchTest {
@SmokeTest
@Test
fun noSearchGroupFromPrivateBrowsingTest() {
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(TestHelper.appContext, IconRequest(searchString)).bitmap,
)
TestHelper.setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -417,18 +383,11 @@ class ComposeSearchTest {
@SmokeTest
@Test
fun deleteItemsFromSearchGroupHistoryTest() {
queryString = "test search"
val firstPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 1).url
val secondPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 2).url
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(TestHelper.appContext, IconRequest(searchString)).bitmap,
)
TestHelper.setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -465,17 +424,10 @@ class ComposeSearchTest {
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun deleteSearchGroupFromHistoryTest() {
queryString = "test search"
val firstPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 1).url
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(TestHelper.appContext, IconRequest(searchString)).bitmap,
)
TestHelper.setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -514,16 +466,10 @@ class ComposeSearchTest {
fun reopenTabsFromSearchGroupTest() {
val firstPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 1).url
val secondPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 2).url
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(TestHelper.appContext, IconRequest(searchString)).bitmap,
)
TestHelper.setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -567,16 +513,9 @@ class ComposeSearchTest {
@Test
fun sharePageFromASearchGroupTest() {
val firstPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 1).url
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(TestHelper.appContext, IconRequest(searchString)).bitmap,
)
TestHelper.setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -611,8 +550,6 @@ class ComposeSearchTest {
// Default search code for Google-US
@Test
fun defaultSearchCodeGoogleUS() {
queryString = "firefox"
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
@ -627,8 +564,6 @@ class ComposeSearchTest {
// Default search code for Bing-US
@Test
fun defaultSearchCodeBingUS() {
queryString = "firefox"
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -652,8 +587,6 @@ class ComposeSearchTest {
// Default search code for DuckDuckGo-US
@Test
fun defaultSearchCodeDuckDuckGoUS() {
queryString = "firefox"
homeScreen {
}.openThreeDotMenu {
}.openSettings {

@ -10,9 +10,6 @@ import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.core.net.toUri
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import androidx.test.espresso.Espresso.pressBack
import mozilla.components.browser.icons.IconRequest
import mozilla.components.browser.icons.generator.DefaultIconGenerator
import mozilla.components.feature.search.ext.createSearchEngine
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Assume.assumeTrue
@ -26,6 +23,7 @@ import org.mozilla.fenix.helpers.Constants.searchEngineCodes
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.MockBrowserDataHelper.setCustomSearchEngine
import org.mozilla.fenix.helpers.SearchDispatcher
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.appContext
@ -36,7 +34,6 @@ import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.grantSystemPermission
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.setCustomSearchEngine
import org.mozilla.fenix.helpers.TestHelper.verifyKeyboardVisibility
import org.mozilla.fenix.ui.robots.clickContextMenuItem
import org.mozilla.fenix.ui.robots.clickPageObject
@ -58,7 +55,7 @@ import org.mozilla.fenix.ui.robots.searchScreen
class SearchTest {
lateinit var searchMockServer: MockWebServer
lateinit var queryString: String
private var queryString = "firefox"
private val generalEnginesList = listOf("DuckDuckGo", "Google", "Bing")
private val topicEnginesList = listOf("Amazon.com", "Wikipedia", "eBay")
@ -239,12 +236,10 @@ class SearchTest {
@Test
fun accessSearchSettingFromSearchSelectorMenuTest() {
queryString = "firefox"
searchScreen {
clickSearchSelectorButton()
}.clickSearchEngineSettings {
verifySearchSettingsToolbar()
verifyToolbarText("Search")
openDefaultSearchEngineMenu()
changeDefaultSearchEngine("DuckDuckGo")
exitMenu()
@ -252,14 +247,12 @@ class SearchTest {
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
verifyUrl("firefox")
verifyUrl(queryString)
}
}
@Test
fun clearSearchTest() {
queryString = "test"
homeScreen {
}.openSearch {
typeSearch(queryString)
@ -272,16 +265,9 @@ class SearchTest {
@SmokeTest
@Test
fun searchGroupShowsInRecentlyVisitedTest() {
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -310,16 +296,9 @@ class SearchTest {
val secondPageUrl = getGenericAsset(searchMockServer, 2).url
val originPageUrl =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search=test%20search".toUri()
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -358,16 +337,9 @@ class SearchTest {
@Ignore("Failing due to known bug, see https://github.com/mozilla-mobile/fenix/issues/23818")
@Test
fun searchGroupGeneratedInTheSameTabTest() {
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -388,16 +360,9 @@ class SearchTest {
@SmokeTest
@Test
fun noSearchGroupFromPrivateBrowsingTest() {
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -427,18 +392,11 @@ class SearchTest {
@SmokeTest
@Test
fun deleteItemsFromSearchGroupHistoryTest() {
queryString = "test search"
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
val secondPageUrl = getGenericAsset(searchMockServer, 2).url
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -475,17 +433,10 @@ class SearchTest {
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun deleteSearchGroupFromHistoryTest() {
queryString = "test search"
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -524,16 +475,9 @@ class SearchTest {
fun reopenTabsFromSearchGroupTest() {
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
val secondPageUrl = getGenericAsset(searchMockServer, 2).url
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -577,16 +521,9 @@ class SearchTest {
@Test
fun sharePageFromASearchGroupTest() {
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
setCustomSearchEngine(customSearchEngine)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
@ -621,8 +558,6 @@ class SearchTest {
// Default search code for Google-US
@Test
fun defaultSearchCodeGoogleUS() {
queryString = "firefox"
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
@ -637,8 +572,6 @@ class SearchTest {
// Default search code for Bing-US
@Test
fun defaultSearchCodeBingUS() {
queryString = "firefox"
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -662,8 +595,6 @@ class SearchTest {
// Default search code for DuckDuckGo-US
@Test
fun defaultSearchCodeDuckDuckGoUS() {
queryString = "firefox"
homeScreen {
}.openThreeDotMenu {
}.openSettings {

@ -8,22 +8,24 @@ import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.MockBrowserDataHelper.addCustomSearchEngine
import org.mozilla.fenix.helpers.SearchDispatcher
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.helpers.TestHelper.setSystemLocale
import org.mozilla.fenix.helpers.TestHelper.setTextToClipBoard
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.ui.robots.EngineShortcut
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.searchScreen
import org.mozilla.fenix.ui.util.ARABIC_LANGUAGE_HEADER
import java.util.Locale
class SettingsSearchTest {
private lateinit var mockWebServer: MockWebServer
@ -46,6 +48,11 @@ class SettingsSearchTest {
dispatcher = AndroidAssetDispatcher()
start()
}
searchMockServer = MockWebServer().apply {
dispatcher = SearchDispatcher()
start()
}
}
@After
@ -59,7 +66,7 @@ class SettingsSearchTest {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
verifySearchSettingsToolbar()
verifyToolbarText("Search")
verifySearchEnginesSectionHeader()
verifyDefaultSearchEngineHeader()
verifyDefaultSearchEngineSummary("Google")
@ -77,6 +84,20 @@ class SettingsSearchTest {
}
}
@Test
fun defaultSearchEnginesSettingsItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
verifyDefaultSearchEngineHeader()
openDefaultSearchEngineMenu()
verifyToolbarText("Default search engine")
verifyDefaultSearchEngineList()
verifyDefaultSearchEngineSelected("Google")
}
}
@SmokeTest
@Test
fun selectNewDefaultSearchEngine() {
@ -224,11 +245,7 @@ class SettingsSearchTest {
@SmokeTest
@Test
fun addCustomDefaultSearchEngineTest() {
searchMockServer = MockWebServer().apply {
dispatcher = SearchDispatcher()
start()
}
val searchEngine = object {
val customSearchEngine = object {
val title = "TestSearchEngine"
val url = "http://localhost:${searchMockServer.port}/searchResults.html?search=%s"
}
@ -240,24 +257,192 @@ class SettingsSearchTest {
openDefaultSearchEngineMenu()
openAddSearchEngineMenu()
verifySaveSearchEngineButtonEnabled(false)
typeCustomEngineDetails(searchEngine.title, searchEngine.url)
typeCustomEngineDetails(customSearchEngine.title, customSearchEngine.url)
verifySaveSearchEngineButtonEnabled(true)
saveNewSearchEngine()
verifyEngineListContains(searchEngine.title)
openEngineOverflowMenu(searchEngine.title)
verifySnackBarText("Created ${customSearchEngine.title}")
verifyEngineListContains(customSearchEngine.title, shouldExist = true)
openEngineOverflowMenu(customSearchEngine.title)
pressBack()
changeDefaultSearchEngine(searchEngine.title)
changeDefaultSearchEngine(customSearchEngine.title)
pressBack()
openManageShortcutsMenu()
verifyEngineListContains(searchEngine.title)
verifyEngineListContains(customSearchEngine.title, shouldExist = true)
pressBack()
}.goBack {
verifySettingsOptionSummary("Search", searchEngine.title)
verifySettingsOptionSummary("Search", customSearchEngine.title)
}.goBack {
}.openSearch {
verifySearchEngineIcon(searchEngine.title)
verifySearchEngineIcon(customSearchEngine.title)
clickSearchSelectorButton()
verifySearchShortcutListContains(searchEngine.title)
verifySearchShortcutListContains(customSearchEngine.title)
}
}
@Test
fun addSearchEngineToManageShortcutsListTest() {
val customSearchEngine = object {
val title = "TestSearchEngine"
val url = "http://localhost:${searchMockServer.port}/searchResults.html?search=%s"
}
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
openManageShortcutsMenu()
openAddSearchEngineMenu()
typeCustomEngineDetails(customSearchEngine.title, customSearchEngine.url)
saveNewSearchEngine()
verifyEngineListContains(customSearchEngine.title, shouldExist = true)
pressBack()
openDefaultSearchEngineMenu()
verifyEngineListContains(customSearchEngine.title, shouldExist = true)
}
}
@Test
fun addSearchEngineLearnMoreLinksTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
openDefaultSearchEngineMenu()
openAddSearchEngineMenu()
}.clickCustomSearchStringLearnMoreLink {
verifyUrl(
"support.mozilla.org/en-US/kb/manage-my-default-search-engines-firefox-android?as=u&utm_source=inproduct",
)
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
openDefaultSearchEngineMenu()
openAddSearchEngineMenu()
}.clickCustomSearchSuggestionsLearnMoreLink {
verifyUrl(
"support.mozilla.org/en-US/kb/manage-my-default-search-engines-firefox-android?as=u&utm_source=inproduct",
)
}
}
@Test
fun editCustomSearchEngineTest() {
val customSearchEngine = object {
val title = "TestSearchEngine"
val url = "http://localhost:${searchMockServer.port}/searchResults.html?search=%s"
val newTitle = "NewEngineTitle"
}
addCustomSearchEngine(searchMockServer, customSearchEngine.title)
restartApp(activityTestRule.activityRule)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
openDefaultSearchEngineMenu()
verifyEngineListContains(customSearchEngine.title, shouldExist = true)
openEngineOverflowMenu(customSearchEngine.title)
clickEdit()
typeCustomEngineDetails(customSearchEngine.newTitle, customSearchEngine.url)
saveEditSearchEngine()
verifySnackBarText("Saved ${customSearchEngine.newTitle}")
verifyEngineListContains(customSearchEngine.newTitle, shouldExist = true)
pressBack()
openManageShortcutsMenu()
verifyEngineListContains(customSearchEngine.newTitle, shouldExist = true)
}
}
@Test
fun errorForInvalidSearchEngineStringsTest() {
val customSearchEngine = object {
val title = "TestSearchEngine"
val badTemplateUrl = "http://localhost:${searchMockServer.port}/searchResults.html?search="
val typoUrl = "http://local:${searchMockServer.port}/searchResults.html?search=%s"
val goodUrl = "http://localhost:${searchMockServer.port}/searchResults.html?search=%s"
}
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
openDefaultSearchEngineMenu()
openAddSearchEngineMenu()
typeCustomEngineDetails(customSearchEngine.title, customSearchEngine.badTemplateUrl)
saveNewSearchEngine()
verifyInvalidTemplateSearchStringFormatError()
typeCustomEngineDetails(customSearchEngine.title, customSearchEngine.typoUrl)
saveNewSearchEngine()
verifyErrorConnectingToSearchString(customSearchEngine.title)
typeCustomEngineDetails(customSearchEngine.title, customSearchEngine.goodUrl)
typeSearchEngineSuggestionString(customSearchEngine.badTemplateUrl)
saveNewSearchEngine()
verifyInvalidTemplateSearchStringFormatError()
typeSearchEngineSuggestionString(customSearchEngine.typoUrl)
saveNewSearchEngine()
verifyErrorConnectingToSearchString(customSearchEngine.title)
}
}
@Test
fun deleteCustomSearchEngineTest() {
val customSearchEngineTitle = "TestSearchEngine"
addCustomSearchEngine(mockWebServer, searchEngineName = customSearchEngineTitle)
restartApp(activityTestRule.activityRule)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
openDefaultSearchEngineMenu()
verifyEngineListContains(customSearchEngineTitle, shouldExist = true)
openEngineOverflowMenu(customSearchEngineTitle)
clickDeleteSearchEngine()
verifySnackBarText("Deleted $customSearchEngineTitle")
clickUndoSnackBarButton()
verifyEngineListContains(customSearchEngineTitle, shouldExist = true)
changeDefaultSearchEngine(customSearchEngineTitle)
openEngineOverflowMenu(customSearchEngineTitle)
clickDeleteSearchEngine()
verifyEngineListContains(customSearchEngineTitle, shouldExist = false)
verifyDefaultSearchEngineSelected("Google")
pressBack()
openManageShortcutsMenu()
verifyEngineListContains(customSearchEngineTitle, shouldExist = false)
exitMenu()
}
searchScreen {
clickSearchSelectorButton()
verifySearchShortcutListContains(customSearchEngineTitle, shouldExist = false)
}
}
@Test
fun deleteCustomSearchShortcutTest() {
val customSearchEngineTitle = "TestSearchEngine"
addCustomSearchEngine(mockWebServer, searchEngineName = customSearchEngineTitle)
restartApp(activityTestRule.activityRule)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
openManageShortcutsMenu()
verifyEngineListContains(customSearchEngineTitle, shouldExist = true)
openCustomShortcutOverflowMenu(activityTestRule, customSearchEngineTitle)
clickDeleteSearchEngine(activityTestRule)
verifyEngineListContains(customSearchEngineTitle, shouldExist = false)
pressBack()
openDefaultSearchEngineMenu()
verifyEngineListContains(customSearchEngineTitle, shouldExist = false)
exitMenu()
}
searchScreen {
clickSearchSelectorButton()
verifySearchShortcutListContains(customSearchEngineTitle, shouldExist = false)
}
}
@ -363,74 +548,103 @@ class SettingsSearchTest {
}
}
// Expected for app language set to Arabic
@Test
fun deleteCustomSearchEngineTest() {
searchMockServer = MockWebServer().apply {
dispatcher = SearchDispatcher()
start()
fun verifySearchEnginesWithRTLLocale() {
val arabicLocale = Locale("ar", "AR")
runWithSystemLocaleChanged(arabicLocale, activityTestRule.activityRule) {
homeScreen {
}.openSearch {
verifyTranslatedFocusedNavigationToolbar("ابحث أو أدخِل عنوانا")
clickSearchSelectorButton()
verifySearchShortcutListContains(
"Google",
"Bing",
"Amazon.com",
"DuckDuckGo",
"ويكيبيديا (ar)",
)
selectTemporarySearchMethod("ويكيبيديا (ar)")
}.submitQuery("firefox") {
verifyUrl("firefox")
}
}
val searchEngine = object {
val title = "TestSearchEngine"
val url = "http://localhost:${searchMockServer.port}/searchResults.html?search=%s"
}
@Test
fun searchEnginesListRespectLocaleTest() {
runWithSystemLocaleChanged(Locale.CHINA, activityTestRule.activityRule) {
// Checking search engines for CH locale
homeScreen {
}.openSearch {
clickSearchSelectorButton()
verifySearchShortcutListContains(
"Google",
"百度",
"Bing",
"DuckDuckGo",
)
}.dismissSearchBar {}
// Checking search engines for FR locale
setSystemLocale(Locale.FRENCH)
homeScreen {
}.openSearch {
clickSearchSelectorButton()
verifySearchShortcutListContains(
"Google",
"Bing",
"DuckDuckGo",
"Qwant",
"Wikipédia (fr)",
)
}
}
}
@Test
fun manageSearchShortcutsSettingsItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
openDefaultSearchEngineMenu()
openAddSearchEngineMenu()
verifySaveSearchEngineButtonEnabled(false)
typeCustomEngineDetails(searchEngine.title, searchEngine.url)
verifySaveSearchEngineButtonEnabled(true)
saveNewSearchEngine()
verifyEngineListContains(searchEngine.title)
openEngineOverflowMenu(searchEngine.title)
clickDeleteSearchEngine()
clickUndoSnackBarButton()
verifyEngineListContains(searchEngine.title)
changeDefaultSearchEngine(searchEngine.title)
openEngineOverflowMenu(searchEngine.title)
clickDeleteSearchEngine()
verifySnackBarText("Deleted ${searchEngine.title}")
verifyEngineListDoesNotContain(searchEngine.title)
openManageShortcutsMenu()
verifyToolbarText("Manage search shortcuts")
verifyEnginesShortcutsListHeader()
verifyManageShortcutsList(activityTestRule)
verifySearchShortcutChecked(
EngineShortcut(name = "Google", checkboxIndex = 1, isChecked = true),
EngineShortcut(name = "Bing", checkboxIndex = 4, isChecked = true),
EngineShortcut(name = "Amazon.com", checkboxIndex = 7, isChecked = true),
EngineShortcut(name = "DuckDuckGo", checkboxIndex = 10, isChecked = true),
EngineShortcut(name = "eBay", checkboxIndex = 13, isChecked = true),
EngineShortcut(name = "Wikipedia", checkboxIndex = 16, isChecked = true),
EngineShortcut(name = "Reddit", checkboxIndex = 19, isChecked = false),
EngineShortcut(name = "YouTube", checkboxIndex = 22, isChecked = false),
)
}
}
// Expected for app language set to Arabic
@SmokeTest
@Test
fun verifySearchEnginesWithRTLLocale() {
fun changeSearchShortcutsListTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openLanguageSubMenu {
TestHelper.registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(
activityTestRule.activity.findViewById(R.id.locale_list),
2,
),
) {
selectLanguage("Arabic")
verifyLanguageHeaderIsTranslated(ARABIC_LANGUAGE_HEADER)
}
}.openSearchSubMenu {
openManageShortcutsMenu()
selectSearchShortcut(EngineShortcut(name = "Google", checkboxIndex = 1))
selectSearchShortcut(EngineShortcut(name = "Amazon.com", checkboxIndex = 7))
selectSearchShortcut(EngineShortcut(name = "Reddit", checkboxIndex = 19))
selectSearchShortcut(EngineShortcut(name = "YouTube", checkboxIndex = 22))
exitMenu()
}
exitMenu()
homeScreen {
}.openSearch {
verifyTranslatedFocusedNavigationToolbar("ابحث أو أدخِل عنوانا")
searchScreen {
clickSearchSelectorButton()
verifySearchShortcutListContains(
"Google",
"Bing",
"Amazon.com",
"DuckDuckGo",
"ويكيبيديا (ar)",
)
selectTemporarySearchMethod("ويكيبيديا (ar)")
}.submitQuery("firefox") {
verifyUrl("firefox")
verifySearchShortcutListContains("Google", "Amazon.com", shouldExist = false)
verifySearchShortcutListContains("YouTube", shouldExist = true)
verifySearchShortcutListContains("Reddit", shouldExist = true)
}
}
}

@ -42,7 +42,6 @@ import androidx.test.uiautomator.UiScrollable
import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import androidx.test.uiautomator.Until.findObject
import mozilla.components.browser.state.state.searchEngines
import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.CoreMatchers.containsString
import org.hamcrest.CoreMatchers.instanceOf
@ -51,7 +50,6 @@ import org.junit.Assert
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.Constants.LISTS_MAXSWIPES
import org.mozilla.fenix.helpers.Constants.LONG_CLICK_DURATION
import org.mozilla.fenix.helpers.HomeActivityComposeTestRule
@ -69,7 +67,6 @@ import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndDescription
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.appName
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
@ -950,12 +947,6 @@ private fun assertHomeComponent() =
private fun threeDotButton() = onView(allOf(withId(R.id.menuButton)))
private fun getSearchEngine(searchEngineName: String) =
appContext.components.core.store.state.search.searchEngines.find { it.name == searchEngineName }
private fun collectionTitle(title: String, rule: ComposeTestRule) =
rule.onNode(hasText(title))
private fun assertExistingTopSitesList() =
onView(allOf(withId(R.id.top_sites_list)))
.check((matches(withEffectiveVisibility(Visibility.VISIBLE))))

@ -204,12 +204,19 @@ class SearchRobot {
)
}
fun verifySearchShortcutListContains(vararg searchEngineName: String) {
fun verifySearchShortcutListContains(vararg searchEngineName: String, shouldExist: Boolean = true) {
searchEngineName.forEach {
assertTrue(
searchShortcutList.getChild(UiSelector().text(it))
.waitForExists(waitingTimeShort),
)
if (shouldExist) {
assertTrue(
searchShortcutList.getChild(UiSelector().text(it))
.waitForExists(waitingTimeShort),
)
} else {
assertTrue(
searchShortcutList.getChild(UiSelector().text(it))
.waitUntilGone(waitingTimeShort),
)
}
}
}

@ -6,10 +6,22 @@
package org.mozilla.fenix.ui.robots
import androidx.compose.ui.test.SemanticsMatcher
import androidx.compose.ui.test.assert
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.hasAnySibling
import androidx.compose.ui.test.hasContentDescription
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.ComposeTestRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso.closeSoftKeyboard
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.ViewInteraction
import androidx.test.espresso.action.ViewActions.clearText
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
@ -21,20 +33,20 @@ import androidx.test.espresso.matcher.ViewMatchers.withClassName
import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withParent
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiSelector
import org.hamcrest.CoreMatchers
import org.hamcrest.CoreMatchers.not
import org.hamcrest.Matchers.allOf
import org.hamcrest.Matchers.endsWith
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.getAvailableSearchEngines
import org.mozilla.fenix.helpers.TestHelper.getRegionSearchEnginesList
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.hasCousin
import org.mozilla.fenix.helpers.TestHelper.mDevice
@ -47,12 +59,12 @@ import org.mozilla.fenix.helpers.isEnabled
* Implementation of Robot Pattern for the settings search sub menu.
*/
class SettingsSubMenuSearchRobot {
fun verifySearchSettingsToolbar() {
fun verifyToolbarText(title: String) {
onView(
allOf(
withId(R.id.navigationToolbar),
hasDescendant(withContentDescription(R.string.action_bar_up_description)),
hasDescendant(withText(R.string.preferences_search)),
hasDescendant(withText(title)),
),
).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
}
@ -79,23 +91,55 @@ class SettingsSubMenuSearchRobot {
.check(matches(hasSibling(withText("Edit engines visible in the search menu"))))
}
fun verifyEnginesShortcutsListHeader() {
assertTrue(itemWithText("Engines visible on the search menu").exists())
}
fun verifyAddressBarSectionHeader() {
onView(withText("Address bar")).check(matches(isDisplayed()))
}
fun verifySearchEngineList() {
onView(withText("Google"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
onView(withText("Amazon.com"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
onView(withText("Bing"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
onView(withText("DuckDuckGo"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
onView(withText("Wikipedia"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
onView(withText("Add search engine"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
fun verifyDefaultSearchEngineList() {
defaultSearchEngineOption("Google")
.check(matches(hasSibling(withId(R.id.engine_icon))))
.check(matches(isDisplayed()))
defaultSearchEngineOption("Bing")
.check(matches(hasSibling(withId(R.id.engine_icon))))
.check(matches(isDisplayed()))
defaultSearchEngineOption("DuckDuckGo")
.check(matches(hasSibling(withId(R.id.engine_icon))))
.check(matches(isDisplayed()))
assertTrue(addSearchEngineButton.exists())
}
fun verifyManageShortcutsList(testRule: ComposeTestRule) {
val availableShortcutsEngines = getRegionSearchEnginesList() + getAvailableSearchEngines()
availableShortcutsEngines.forEach {
testRule.onNodeWithText(it.name)
.assert(hasAnySibling(hasContentDescription("${it.name} search engine")))
.assertIsDisplayed()
}
assertTrue(addSearchEngineButton.exists())
}
/**
* Method that verifies the selected engines inside the Manage search shortcuts list.
*/
fun verifySearchShortcutChecked(vararg engineShortcut: EngineShortcut) {
engineShortcut.forEach {
val shortcutIsChecked = mDevice.findObject(UiSelector().text(it.name))
.getFromParent(
UiSelector().index(it.checkboxIndex),
).isChecked
if (it.isChecked) {
assertTrue(shortcutIsChecked)
} else {
assertFalse(shortcutIsChecked)
}
}
}
fun verifyAutocompleteURlsIsEnabled(enabled: Boolean) {
@ -168,17 +212,16 @@ class SettingsSubMenuSearchRobot {
.perform(click())
}
fun selectSearchShortcut(shortcut: EngineShortcut) {
mDevice.findObject(UiSelector().text(shortcut.name))
.getFromParent(UiSelector().index(shortcut.checkboxIndex))
.click()
}
fun toggleAutocomplete() = autocompleteSwitchButton().click()
fun toggleShowSearchSuggestions() = showSearchSuggestionSwitchButton().click()
fun toggleShowSearchShortcuts() =
itemContainingText(getStringResource(R.string.preferences_show_search_engines))
.also {
it.waitForExists(waitingTimeShort)
it.click()
}
fun toggleVoiceSearch() {
voiceSearchSwitchButton().perform(click())
}
@ -191,31 +234,21 @@ class SettingsSubMenuSearchRobot {
fun switchSearchBookmarksToggle() = searchBookmarksSwitchButton().click()
fun switchShowSuggestionsInPrivateSessionsToggle() = showSuggestionsInPrivateModeSwitch().click()
fun switchShowSuggestionsInPrivateSessionsToggle() =
showSuggestionsInPrivateModeSwitch().click()
fun openAddSearchEngineMenu() = addSearchEngineButton().click()
fun openAddSearchEngineMenu() = addSearchEngineButton.click()
fun verifyEngineListContains(searchEngineName: String) {
assertTrue(itemWithText(searchEngineName).waitForExists(waitingTimeShort))
}
fun verifyEngineListDoesNotContain(searchEngineName: String) = assertEngineListDoesNotContain(searchEngineName)
fun verifyDefaultSearchEngine(searchEngineName: String) {
onView(
allOf(
withId(R.id.radio_button),
withParent(withChild(withText(searchEngineName))),
),
).check(matches(isChecked(true)))
fun verifyEngineListContains(searchEngineName: String, shouldExist: Boolean) {
if (shouldExist) {
assertTrue(itemWithText(searchEngineName).waitForExists(waitingTimeShort))
} else {
assertFalse(itemWithText(searchEngineName).waitForExists(waitingTimeShort))
}
}
fun verifyThreeDotButtonIsNotDisplayed(searchEngineName: String) = assertThreeDotButtonIsNotDisplayed(searchEngineName)
fun verifyAddSearchEngineListContains(vararg searchEngines: String) {
for (searchEngine in searchEngines) {
onView(withId(R.id.search_engine_group)).check(matches(hasDescendant(withText(searchEngine))))
}
fun verifyDefaultSearchEngineSelected(searchEngineName: String) {
defaultSearchEngineOption(searchEngineName).check(matches(isChecked(true)))
}
fun verifySaveSearchEngineButtonEnabled(enabled: Boolean) {
@ -223,12 +256,8 @@ class SettingsSubMenuSearchRobot {
}
fun saveNewSearchEngine() {
closeSoftKeyboard()
addSearchEngineSaveButton().click()
assertTrue(
mDevice.findObject(
UiSelector().textContains("Default search engine"),
).waitForExists(waitingTime),
)
}
fun typeCustomEngineDetails(engineName: String, engineURL: String) {
@ -254,10 +283,6 @@ class SettingsSubMenuSearchRobot {
)
} catch (e: AssertionError) {
println("The name or the search string were not set properly")
//
// // Lets again set both name and search string
// goBackButton().click()
// openAddSearchEngineMenu()
mDevice.findObject(By.res("$packageName:id/edit_engine_name")).clear()
mDevice.findObject(By.res("$packageName:id/edit_engine_name")).setText(engineName)
@ -281,27 +306,36 @@ class SettingsSubMenuSearchRobot {
}
}
fun typeSearchEngineSuggestionString(searchSuggestionString: String) {
onView(withId(R.id.edit_suggest_string))
.click()
.perform(clearText())
.perform(typeText(searchSuggestionString))
}
// Used in the non-Compose Default search engines menu
fun openEngineOverflowMenu(searchEngineName: String) {
mDevice.findObject(
UiSelector().resourceId("org.mozilla.fenix.debug:id/overflow_menu"),
).waitForExists(waitingTime)
threeDotMenu(searchEngineName).waitForExists(waitingTimeShort)
threeDotMenu(searchEngineName).click()
}
fun deleteMultipleSearchEngines(vararg searchEngines: String) {
for (searchEngine in searchEngines) {
openEngineOverflowMenu(searchEngine)
clickDeleteSearchEngine()
}
// Used in the composable Manage shortcuts menu, otherwise the overflow menu is not visible
fun openCustomShortcutOverflowMenu(testRule: ComposeTestRule, searchEngineName: String) {
testRule.onNode(overflowMenuWithSiblingText(searchEngineName)).performClick()
}
fun clickEdit() = onView(withText("Edit")).click()
// Used in the Default search engine menu
fun clickDeleteSearchEngine() =
mDevice.findObject(
UiSelector().textContains(getStringResource(R.string.search_engine_delete)),
).click()
// Used in the composable Manage search shortcuts menu, otherwise the overflow menu is not visible
fun clickDeleteSearchEngine(testRule: ComposeTestRule) =
testRule.onNodeWithText("Delete").performClick()
fun clickUndoSnackBarButton() =
mDevice.findObject(
UiSelector()
@ -317,7 +351,17 @@ class SettingsSubMenuSearchRobot {
)
}
fun verifyShowSearchEnginesToggleState(enabled: Boolean) = assertShowSearchEnginesToggle(enabled)
fun verifyInvalidTemplateSearchStringFormatError() {
closeSoftKeyboard()
onView(withText(getStringResource(R.string.search_add_custom_engine_error_missing_template)))
.check(matches(isDisplayed()))
}
fun verifyErrorConnectingToSearchString(searchEngineName: String) {
closeSoftKeyboard()
onView(withText(getStringResource(R.string.search_add_custom_engine_error_cannot_reach, searchEngineName)))
.check(matches(isDisplayed()))
}
class Transition {
fun goBack(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition {
@ -327,16 +371,36 @@ class SettingsSubMenuSearchRobot {
SettingsRobot().interact()
return SettingsRobot.Transition()
}
fun clickCustomSearchStringLearnMoreLink(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
onView(withId(R.id.custom_search_engines_learn_more)).click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun clickCustomSearchSuggestionsLearnMoreLink(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
onView(withId(R.id.custom_search_suggestions_learn_more)).click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
}
}
fun searchSettingsScreen(interact: SettingsSubMenuSearchRobot.() -> Unit): SettingsSubMenuSearchRobot.Transition {
SettingsSubMenuSearchRobot().interact()
return SettingsSubMenuSearchRobot.Transition()
}
/**
* Matches search shortcut items inside the 'Manage search shortcuts' menu
* @param name, of type String, should be the name of the search engine.
* @param checkboxIndex, of type Int, is the checkbox' index afferent to the search engine.
* @param isChecked, of type Boolean, should show if the checkbox is expected to be checked.
*/
class EngineShortcut(
val name: String,
val checkboxIndex: Int,
val isChecked: Boolean = true,
)
private val defaultSearchEngineHeader =
onView(withText("Default search engine"))
private val defaultSearchEngineHeader = onView(withText("Default search engine"))
private val manageSearchShortcutsHeader = onView(withText("Manage search shortcuts"))
@ -417,48 +481,21 @@ private fun showSuggestionsInPrivateModeSwitch(): ViewInteraction {
private fun goBackButton() =
onView(CoreMatchers.allOf(withContentDescription("Navigate up")))
private fun addSearchEngineButton() = onView(withText("Add search engine"))
private val addSearchEngineButton = mDevice.findObject(UiSelector().text("Add search engine"))
private fun addSearchEngineSaveButton() = onView(withId(R.id.save_button))
private fun assertEngineListDoesNotContain(searchEngineName: String) {
onView(withId(R.id.search_engine_group)).check(matches(not(hasDescendant(withText(searchEngineName)))))
}
private fun assertThreeDotButtonIsNotDisplayed(searchEngineName: String) =
threeDotMenu(searchEngineName).check(matches(not(isDisplayed())))
private fun assertShowSearchEnginesToggle(enabled: Boolean) =
if (enabled) {
onView(withText(R.string.preferences_show_search_engines))
.check(
matches(
hasCousin(
allOf(
withClassName(endsWith("Switch")),
ViewMatchers.isChecked(),
),
),
),
)
} else {
onView(withText(R.string.preferences_show_search_engines))
.check(
matches(
hasCousin(
allOf(
withClassName(endsWith("Switch")),
ViewMatchers.isNotChecked(),
),
),
),
)
}
private fun threeDotMenu(searchEngineName: String) =
mDevice.findObject(UiSelector().text(searchEngineName))
.getFromParent(UiSelector().description("More options"))
private fun defaultSearchEngineOption(searchEngineName: String) =
onView(
allOf(
withId(R.id.overflow_menu),
withParent(withChild(withText(searchEngineName))),
withId(R.id.radio_button),
hasSibling(withText(searchEngineName)),
),
)
private fun overflowMenuWithSiblingText(text: String): SemanticsMatcher =
hasAnySibling(hasText(text)) and hasContentDescription("More options")

Loading…
Cancel
Save