1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 package org.mozilla.fenix.ui
7 import androidx.compose.ui.test.junit4.AndroidComposeTestRule
8 import androidx.test.espresso.Espresso.pressBack
9 import okhttp3.mockwebserver.MockWebServer
10 import org.junit.After
11 import org.junit.Before
14 import org.mozilla.fenix.customannotations.SmokeTest
15 import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithSystemLocaleChanged
16 import org.mozilla.fenix.helpers.AppAndSystemHelper.setSystemLocale
17 import org.mozilla.fenix.helpers.DataGenerationHelper.setTextToClipBoard
18 import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
19 import org.mozilla.fenix.helpers.MockBrowserDataHelper.addCustomSearchEngine
20 import org.mozilla.fenix.helpers.MockBrowserDataHelper.createBookmarkItem
21 import org.mozilla.fenix.helpers.MockBrowserDataHelper.createHistoryItem
22 import org.mozilla.fenix.helpers.SearchDispatcher
23 import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
24 import org.mozilla.fenix.helpers.TestHelper.appContext
25 import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
26 import org.mozilla.fenix.helpers.TestHelper.exitMenu
27 import org.mozilla.fenix.helpers.TestHelper.restartApp
28 import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
29 import org.mozilla.fenix.helpers.TestSetup
30 import org.mozilla.fenix.ui.robots.EngineShortcut
31 import org.mozilla.fenix.ui.robots.homeScreen
32 import org.mozilla.fenix.ui.robots.navigationToolbar
33 import org.mozilla.fenix.ui.robots.searchScreen
34 import java.util.Locale
36 class SettingsSearchTest : TestSetup() {
37 private lateinit var searchMockServer: MockWebServer
38 private val defaultSearchEngineList =
46 val activityTestRule = AndroidComposeTestRule(
47 HomeActivityIntentTestRule.withDefaultSettingsOverrides(),
51 override fun setUp() {
53 searchMockServer = MockWebServer().apply {
54 dispatcher = SearchDispatcher()
60 override fun tearDown() {
62 searchMockServer.shutdown()
65 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203333
67 fun verifySearchSettingsMenuItemsTest() {
72 verifyToolbarText("Search")
73 verifySearchEnginesSectionHeader()
74 verifyDefaultSearchEngineHeader()
75 verifyDefaultSearchEngineSummary("Google")
76 verifyManageSearchShortcutsHeader()
77 verifyManageShortcutsSummary()
78 verifyAddressBarSectionHeader()
79 verifyAutocompleteURlsIsEnabled(true)
80 verifyShowClipboardSuggestionsEnabled(true)
81 verifySearchBrowsingHistoryEnabled(true)
82 verifySearchBookmarksEnabled(true)
83 verifySearchSyncedTabsEnabled(true)
84 verifyVoiceSearchEnabled(true)
85 verifyShowSearchSuggestionsEnabled(true)
86 verifyShowSearchSuggestionsInPrivateEnabled(false)
90 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203307
92 fun verifyDefaultSearchEnginesSettingsItemsTest() {
97 verifyDefaultSearchEngineHeader()
98 openDefaultSearchEngineMenu()
99 verifyToolbarText("Default search engine")
100 verifyDefaultSearchEngineList()
101 verifyDefaultSearchEngineSelected("Google")
105 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203308
108 fun verifyTheDefaultSearchEngineCanBeChangedTest() {
109 // Goes through the settings and changes the default search engine, then verifies it has changed.
110 defaultSearchEngineList.forEach {
114 }.openSearchSubMenu {
115 openDefaultSearchEngineMenu()
116 changeDefaultSearchEngine(it)
120 verifySearchEngineIcon(it)
125 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/233586
127 fun verifyUrlAutocompleteToggleTest() {
131 verifyTypedToolbarText("monster.com")
133 verifyTypedToolbarText("mozilla.org")
137 }.openSearchSubMenu {
143 verifyTypedToolbarText("moz")
147 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/361817
149 fun disableSearchBrowsingHistorySuggestionsToggleTest() {
150 val websiteURL = getGenericAsset(mockWebServer, 1).url.toString()
152 createHistoryItem(websiteURL)
157 }.openSearchSubMenu {
158 switchSearchHistoryToggle()
165 verifySuggestionsAreNotDisplayed(
173 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/412926
175 fun disableSearchBookmarksToggleTest() {
176 val website = getGenericAsset(mockWebServer, 1)
178 createBookmarkItem(website.url.toString(), website.title, 1u)
183 }.openSearchSubMenu {
184 switchSearchBookmarksToggle()
185 // We want to avoid confusion between history and bookmarks searches,
186 // so we'll disable this too.
187 switchSearchHistoryToggle()
194 verifySuggestionsAreNotDisplayed(
202 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203309
203 // Verifies setting as default a customized search engine name and URL
206 fun verifyCustomSearchEngineCanBeAddedFromSearchEngineMenuTest() {
207 val customSearchEngine = object {
208 val title = "TestSearchEngine"
209 val url = "http://localhost:${searchMockServer.port}/searchResults.html?search=%s"
215 }.openSearchSubMenu {
216 openDefaultSearchEngineMenu()
217 openAddSearchEngineMenu()
218 verifySaveSearchEngineButtonEnabled(false)
219 typeCustomEngineDetails(customSearchEngine.title, customSearchEngine.url)
220 verifySaveSearchEngineButtonEnabled(true)
221 saveNewSearchEngine()
222 verifySnackBarText("Created ${customSearchEngine.title}")
223 verifyEngineListContains(customSearchEngine.title, shouldExist = true)
224 openEngineOverflowMenu(customSearchEngine.title)
226 changeDefaultSearchEngine(customSearchEngine.title)
228 openManageShortcutsMenu()
229 verifyEngineListContains(customSearchEngine.title, shouldExist = true)
232 verifySettingsOptionSummary("Search", customSearchEngine.title)
235 verifySearchEngineIcon(customSearchEngine.title)
236 clickSearchSelectorButton()
237 verifySearchShortcutListContains(customSearchEngine.title)
241 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203335
243 fun addCustomSearchEngineToManageShortcutsListTest() {
244 val customSearchEngine = object {
245 val title = "TestSearchEngine"
246 val url = "http://localhost:${searchMockServer.port}/searchResults.html?search=%s"
252 }.openSearchSubMenu {
253 openManageShortcutsMenu()
254 openAddSearchEngineMenu()
255 typeCustomEngineDetails(customSearchEngine.title, customSearchEngine.url)
256 saveNewSearchEngine()
257 verifyEngineListContains(customSearchEngine.title, shouldExist = true)
259 openDefaultSearchEngineMenu()
260 verifyEngineListContains(customSearchEngine.title, shouldExist = true)
264 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203343
266 fun verifyLearnMoreLinksFromAddSearchEngineSectionTest() {
270 }.openSearchSubMenu {
271 openDefaultSearchEngineMenu()
272 openAddSearchEngineMenu()
273 }.clickCustomSearchStringLearnMoreLink {
275 "support.mozilla.org/en-US/kb/manage-my-default-search-engines-firefox-android?as=u&utm_source=inproduct",
279 }.openSearchSubMenu {
280 openDefaultSearchEngineMenu()
281 openAddSearchEngineMenu()
282 }.clickCustomSearchSuggestionsLearnMoreLink {
284 "support.mozilla.org/en-US/kb/manage-my-default-search-engines-firefox-android?as=u&utm_source=inproduct",
289 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203310
291 fun editCustomSearchEngineTest() {
292 val customSearchEngine = object {
293 val title = "TestSearchEngine"
294 val url = "http://localhost:${searchMockServer.port}/searchResults.html?search=%s"
295 val newTitle = "NewEngineTitle"
298 addCustomSearchEngine(searchMockServer, customSearchEngine.title)
299 restartApp(activityTestRule.activityRule)
304 }.openSearchSubMenu {
305 openDefaultSearchEngineMenu()
306 verifyEngineListContains(customSearchEngine.title, shouldExist = true)
307 openEngineOverflowMenu(customSearchEngine.title)
309 typeCustomEngineDetails(customSearchEngine.newTitle, customSearchEngine.url)
310 saveEditSearchEngine()
311 verifySnackBarText("Saved ${customSearchEngine.newTitle}")
312 verifyEngineListContains(customSearchEngine.newTitle, shouldExist = true)
314 openManageShortcutsMenu()
315 verifyEngineListContains(customSearchEngine.newTitle, shouldExist = true)
319 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203312
321 fun verifyErrorMessagesForInvalidSearchEngineUrlsTest() {
322 val customSearchEngine = object {
323 val title = "TestSearchEngine"
324 val badTemplateUrl = "http://localhost:${searchMockServer.port}/searchResults.html?search="
325 val typoUrl = "http://local:${searchMockServer.port}/searchResults.html?search=%s"
326 val goodUrl = "http://localhost:${searchMockServer.port}/searchResults.html?search=%s"
332 }.openSearchSubMenu {
333 openDefaultSearchEngineMenu()
334 openAddSearchEngineMenu()
335 typeCustomEngineDetails(customSearchEngine.title, customSearchEngine.badTemplateUrl)
336 saveNewSearchEngine()
337 verifyInvalidTemplateSearchStringFormatError()
338 typeCustomEngineDetails(customSearchEngine.title, customSearchEngine.typoUrl)
339 saveNewSearchEngine()
340 verifyErrorConnectingToSearchString(customSearchEngine.title)
341 typeCustomEngineDetails(customSearchEngine.title, customSearchEngine.goodUrl)
342 typeSearchEngineSuggestionString(customSearchEngine.badTemplateUrl)
343 saveNewSearchEngine()
344 verifyInvalidTemplateSearchStringFormatError()
345 typeSearchEngineSuggestionString(customSearchEngine.typoUrl)
346 saveNewSearchEngine()
347 verifyErrorConnectingToSearchString(customSearchEngine.title)
351 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203313
353 fun deleteCustomSearchEngineTest() {
354 val customSearchEngineTitle = "TestSearchEngine"
356 addCustomSearchEngine(mockWebServer, searchEngineName = customSearchEngineTitle)
357 restartApp(activityTestRule.activityRule)
362 }.openSearchSubMenu {
363 openDefaultSearchEngineMenu()
364 verifyEngineListContains(customSearchEngineTitle, shouldExist = true)
365 openEngineOverflowMenu(customSearchEngineTitle)
366 clickDeleteSearchEngine()
367 verifySnackBarText("Deleted $customSearchEngineTitle")
368 clickSnackbarButton("UNDO")
369 verifyEngineListContains(customSearchEngineTitle, shouldExist = true)
370 changeDefaultSearchEngine(customSearchEngineTitle)
371 openEngineOverflowMenu(customSearchEngineTitle)
372 clickDeleteSearchEngine()
373 verifyEngineListContains(customSearchEngineTitle, shouldExist = false)
374 verifyDefaultSearchEngineSelected("Google")
376 openManageShortcutsMenu()
377 verifyEngineListContains(customSearchEngineTitle, shouldExist = false)
381 clickSearchSelectorButton()
382 verifySearchShortcutListContains(customSearchEngineTitle, shouldExist = false)
386 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203339
388 fun deleteCustomSearchShortcutTest() {
389 val customSearchEngineTitle = "TestSearchEngine"
391 addCustomSearchEngine(mockWebServer, searchEngineName = customSearchEngineTitle)
392 restartApp(activityTestRule.activityRule)
397 }.openSearchSubMenu {
398 openManageShortcutsMenu()
399 verifyEngineListContains(customSearchEngineTitle, shouldExist = true)
400 openCustomShortcutOverflowMenu(activityTestRule, customSearchEngineTitle)
401 clickDeleteSearchEngine(activityTestRule)
402 verifyEngineListContains(customSearchEngineTitle, shouldExist = false)
404 openDefaultSearchEngineMenu()
405 verifyEngineListContains(customSearchEngineTitle, shouldExist = false)
409 clickSearchSelectorButton()
410 verifySearchShortcutListContains(customSearchEngineTitle, shouldExist = false)
414 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/233588
415 // Test running on beta/release builds in CI:
416 // caution when making changes to it, so they don't block the builds
417 // Goes through the settings and changes the search suggestion toggle, then verifies it changes.
420 fun verifyShowSearchSuggestionsToggleTest() {
423 // The Google related suggestions aren't always displayed on cold run
424 // Bugzilla ticket: https://bugzilla.mozilla.org/show_bug.cgi?id=1813587
425 clickSearchSelectorButton()
426 selectTemporarySearchMethod("DuckDuckGo")
427 typeSearch("mozilla ")
428 verifySearchEngineSuggestionResults(
431 searchTerm = "mozilla ",
436 }.openSearchSubMenu {
437 toggleShowSearchSuggestions()
441 // The Google related suggestions aren't always displayed on cold run
442 // Bugzilla ticket: https://bugzilla.mozilla.org/show_bug.cgi?id=1813587
443 clickSearchSelectorButton()
444 selectTemporarySearchMethod("DuckDuckGo")
445 typeSearch("mozilla")
446 verifySuggestionsAreNotDisplayed(activityTestRule, "mozilla firefox")
450 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/464420
451 // Tests the "Don't allow" option from private mode search suggestions onboarding dialog
453 fun doNotAllowSearchSuggestionsInPrivateBrowsingTest() {
455 togglePrivateBrowsingModeOnOff()
457 typeSearch("mozilla")
458 verifyAllowSuggestionsInPrivateModeDialog()
459 denySuggestionsInPrivateMode()
460 verifySuggestionsAreNotDisplayed(activityTestRule, "mozilla firefox")
464 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1957063
465 // Tests the "Allow" option from private mode search suggestions onboarding dialog
467 fun allowSearchSuggestionsInPrivateBrowsingTest() {
469 togglePrivateBrowsingModeOnOff()
471 typeSearch("mozilla")
472 verifyAllowSuggestionsInPrivateModeDialog()
473 allowSuggestionsInPrivateMode()
474 verifySearchEngineSuggestionResults(
477 searchTerm = "mozilla",
482 }.openSearchSubMenu {
483 switchShowSuggestionsInPrivateSessionsToggle()
487 typeSearch("mozilla")
488 verifySuggestionsAreNotDisplayed(activityTestRule, "mozilla firefox")
492 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/888673
494 fun verifyShowVoiceSearchToggleTest() {
497 verifyVoiceSearchButtonVisibility(true)
502 }.openSearchSubMenu {
508 verifyVoiceSearchButtonVisibility(false)
512 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/412927
514 fun verifyShowClipboardSuggestionsToggleTest() {
515 val link = "https://www.mozilla.org/en-US/"
516 setTextToClipBoard(appContext, link)
519 }.openNavigationToolbar {
520 verifyClipboardSuggestionsAreDisplayed(link, true)
521 }.visitLinkFromClipboard {
527 // After visiting the link from clipboard it shouldn't be displayed again
528 verifyClipboardSuggestionsAreDisplayed(shouldBeDisplayed = false)
529 }.goBackToHomeScreen {
530 setTextToClipBoard(appContext, link)
535 verifyClipboardSuggestionsAreDisplayed(link, true)
536 }.goBackToHomeScreen {
539 }.openSearchSubMenu {
540 verifyShowClipboardSuggestionsEnabled(true)
541 toggleClipboardSuggestion()
542 verifyShowClipboardSuggestionsEnabled(false)
550 verifyClipboardSuggestionsAreDisplayed(link, false)
554 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2233337
556 fun verifyTheSearchEnginesListsRespectTheLocaleTest() {
557 runWithSystemLocaleChanged(Locale.CHINA, activityTestRule.activityRule) {
558 // Checking search engines for CH locale
561 clickSearchSelectorButton()
562 verifySearchShortcutListContains(
568 }.dismissSearchBar {}
570 // Checking search engines for FR locale
571 setSystemLocale(Locale.FRENCH)
574 clickSearchSelectorButton()
575 verifySearchShortcutListContains(
586 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203334
588 fun verifyManageSearchShortcutsSettingsItemsTest() {
592 }.openSearchSubMenu {
593 openManageShortcutsMenu()
594 verifyToolbarText("Manage alternative search engines")
595 verifyEnginesShortcutsListHeader()
596 verifyManageShortcutsList(activityTestRule)
597 verifySearchShortcutChecked(
598 EngineShortcut(name = "Google", checkboxIndex = 1, isChecked = true),
599 EngineShortcut(name = "Bing", checkboxIndex = 4, isChecked = true),
600 EngineShortcut(name = "Amazon.com", checkboxIndex = 7, isChecked = true),
601 EngineShortcut(name = "DuckDuckGo", checkboxIndex = 10, isChecked = true),
602 EngineShortcut(name = "eBay", checkboxIndex = 13, isChecked = true),
603 EngineShortcut(name = "Wikipedia", checkboxIndex = 16, isChecked = true),
604 EngineShortcut(name = "Reddit", checkboxIndex = 19, isChecked = false),
605 EngineShortcut(name = "YouTube", checkboxIndex = 22, isChecked = false),
610 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203340
613 fun verifySearchShortcutChangesAreReflectedInSearchSelectorMenuTest() {
617 }.openSearchSubMenu {
618 openManageShortcutsMenu()
619 selectSearchShortcut(EngineShortcut(name = "Google", checkboxIndex = 1))
620 selectSearchShortcut(EngineShortcut(name = "Amazon.com", checkboxIndex = 7))
621 selectSearchShortcut(EngineShortcut(name = "Reddit", checkboxIndex = 19))
622 selectSearchShortcut(EngineShortcut(name = "YouTube", checkboxIndex = 22))
626 clickSearchSelectorButton()
627 verifySearchShortcutListContains("Google", "Amazon.com", shouldExist = false)
628 verifySearchShortcutListContains("YouTube", shouldExist = true)
629 verifySearchShortcutListContains("Reddit", shouldExist = true)