For #5567: Removes search shortcuts button (#5739)

* For #5567: Removes search shortcut button

* No issue: Simplifies logic for displaying shortcuts
nightly-build-test
Sawyer Blatz 5 years ago committed by GitHub
parent bc471ea59c
commit 785b8b9519
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -133,28 +133,6 @@ events:
expires: "2020-03-01" expires: "2020-03-01"
search_shortcuts: search_shortcuts:
opened:
type: event
description: >
A user opened the search shortcut menu in the search view by pressing the shortcuts button
bugs:
- 793
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/1202#issuecomment-476870449
notification_emails:
- fenix-core@mozilla.com
expires: "2020-03-01"
closed:
type: event
description: >
A user closed the search shortcut menu in the search view by pressing the shortcuts button
bugs:
- 793
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/1202#issuecomment-476870449
notification_emails:
- fenix-core@mozilla.com
expires: "2020-03-01"
selected: selected:
type: event type: event
description: > description: >

@ -32,7 +32,6 @@ class SearchTest {
verifySearchView() verifySearchView()
verifyBrowserToolbar() verifyBrowserToolbar()
verifyScanButton() verifyScanButton()
verifyShortcutsButton()
} }
} }

@ -37,7 +37,6 @@ class SearchRobot {
fun verifySearchView() = assertSearchView() fun verifySearchView() = assertSearchView()
fun verifyBrowserToolbar() = assertBrowserToolbarEditView() fun verifyBrowserToolbar() = assertBrowserToolbarEditView()
fun verifyScanButton() = assertScanButton() fun verifyScanButton() = assertScanButton()
fun verifyShortcutsButton() = assertShortcutsButton()
fun verifySearchWithText() = assertSearchWithText() fun verifySearchWithText() = assertSearchWithText()
fun verifyDuckDuckGoResults() = assertDuckDuckGoResults() fun verifyDuckDuckGoResults() = assertDuckDuckGoResults()
fun verifyDuckDuckGoURL() = assertDuckDuckGoURL() fun verifyDuckDuckGoURL() = assertDuckDuckGoURL()
@ -56,10 +55,6 @@ class SearchRobot {
allowPermissionButton().click() allowPermissionButton().click()
} }
fun clickShortcutsButton() {
shortcutsButton().perform(click())
}
fun typeSearch(searchTerm: String) { fun typeSearch(searchTerm: String) {
browserToolbarEditView().perform(typeText(searchTerm)) browserToolbarEditView().perform(typeText(searchTerm))
} }
@ -124,11 +119,6 @@ private fun scanButton(): ViewInteraction {
return onView(allOf(withId(R.id.searchScanButton))) return onView(allOf(withId(R.id.searchScanButton)))
} }
private fun shortcutsButton(): ViewInteraction {
mDevice.wait(Until.findObjects(By.res("R.id.search_shortcuts_button")), TestAssetHelper.waitingTime)
return onView(withId(R.id.searchShortcutsButton))
}
private fun clearButton() = onView(withId(R.id.mozac_browser_toolbar_clear_view)) private fun clearButton() = onView(withId(R.id.mozac_browser_toolbar_clear_view))
private fun assertDuckDuckGoURL() { private fun assertDuckDuckGoURL() {
@ -153,10 +143,6 @@ private fun assertScanButton() =
onView(allOf(withText("Scan"))) onView(allOf(withText("Scan")))
.check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
private fun assertShortcutsButton() =
onView(allOf(withText("Shortcuts")))
.check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
private fun assertSearchWithText() = private fun assertSearchWithText() =
onView(allOf(withText("SEARCH WITH"))) onView(allOf(withText("SEARCH WITH")))
.check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))

@ -84,12 +84,6 @@ private val Event.wrapper: EventWrapper<*>?
}, },
{ Events.performedSearchKeys.valueOf(it) } { Events.performedSearchKeys.valueOf(it) }
) )
is Event.SearchShortcutMenuOpened -> EventWrapper<NoExtraKeys>(
{ SearchShortcuts.opened.record(it) }
)
is Event.SearchShortcutMenuClosed -> EventWrapper<NoExtraKeys>(
{ SearchShortcuts.closed.record(it) }
)
is Event.SearchShortcutSelected -> EventWrapper( is Event.SearchShortcutSelected -> EventWrapper(
{ SearchShortcuts.selected.record(it) }, { SearchShortcuts.selected.record(it) },
{ SearchShortcuts.selectedKeys.valueOf(it) } { SearchShortcuts.selectedKeys.valueOf(it) }

@ -36,8 +36,6 @@ sealed class Event {
object InteractWithSearchURLArea : Event() object InteractWithSearchURLArea : Event()
object DismissedOnboarding : Event() object DismissedOnboarding : Event()
object ClearedPrivateData : Event() object ClearedPrivateData : Event()
object SearchShortcutMenuOpened : Event()
object SearchShortcutMenuClosed : Event()
object AddBookmark : Event() object AddBookmark : Event()
object RemoveBookmark : Event() object RemoveBookmark : Event()
object OpenedBookmark : Event() object OpenedBookmark : Event()

@ -251,8 +251,7 @@ class HomeFragment : Fragment() {
invokePendingDeleteJobs() invokePendingDeleteJobs()
onboarding.finish() onboarding.finish()
val directions = HomeFragmentDirections.actionHomeFragmentToSearchFragment( val directions = HomeFragmentDirections.actionHomeFragmentToSearchFragment(
sessionId = null, sessionId = null
showShortcutEnginePicker = true
) )
val extras = val extras =
FragmentNavigator.Extras.Builder() FragmentNavigator.Extras.Builder()
@ -265,8 +264,7 @@ class HomeFragment : Fragment() {
view.add_tab_button.setOnClickListener { view.add_tab_button.setOnClickListener {
invokePendingDeleteJobs() invokePendingDeleteJobs()
val directions = HomeFragmentDirections.actionHomeFragmentToSearchFragment( val directions = HomeFragmentDirections.actionHomeFragmentToSearchFragment(
sessionId = null, sessionId = null
showShortcutEnginePicker = true
) )
nav(R.id.homeFragment, directions) nav(R.id.homeFragment, directions)
} }

@ -33,8 +33,7 @@ class StartSearchIntentProcessor(
out.removeExtra(HomeActivity.OPEN_TO_SEARCH) out.removeExtra(HomeActivity.OPEN_TO_SEARCH)
val directions = NavGraphDirections.actionGlobalSearch( val directions = NavGraphDirections.actionGlobalSearch(
sessionId = null, sessionId = null
showShortcutEnginePicker = true
) )
navController.nav(null, directions) navController.nav(null, directions)
true true

@ -18,6 +18,7 @@ import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.metrics import org.mozilla.fenix.ext.metrics
import org.mozilla.fenix.ext.nav import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.searchEngineManager import org.mozilla.fenix.ext.searchEngineManager
import org.mozilla.fenix.ext.settings
/** /**
* An interface that handles the view manipulation of the Search, triggered by the Interactor * An interface that handles the view manipulation of the Search, triggered by the Interactor
@ -30,7 +31,6 @@ interface SearchController {
fun handleSearchTermsTapped(searchTerms: String) fun handleSearchTermsTapped(searchTerms: String)
fun handleSearchShortcutEngineSelected(searchEngine: SearchEngine) fun handleSearchShortcutEngineSelected(searchEngine: SearchEngine)
fun handleClickSearchEngineSettings() fun handleClickSearchEngineSettings()
fun handleTurnOnStartedTyping()
fun handleExistingSessionSelected(session: Session) fun handleExistingSessionSelected(session: Session)
} }
@ -40,10 +40,6 @@ class DefaultSearchController(
private val navController: NavController private val navController: NavController
) : SearchController { ) : SearchController {
data class UserTypingCheck(var ranOnTextChanged: Boolean, var userHasTyped: Boolean)
internal val userTypingCheck = UserTypingCheck(false, !store.state.showShortcutEnginePicker)
override fun handleUrlCommitted(url: String) { override fun handleUrlCommitted(url: String) {
if (url.isNotBlank()) { if (url.isNotBlank()) {
(context as HomeActivity).openToBrowserAndLoad( (context as HomeActivity).openToBrowserAndLoad(
@ -69,13 +65,9 @@ class DefaultSearchController(
override fun handleTextChanged(text: String) { override fun handleTextChanged(text: String) {
store.dispatch(SearchFragmentAction.UpdateQuery(text)) store.dispatch(SearchFragmentAction.UpdateQuery(text))
store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(
if (userTypingCheck.ranOnTextChanged && !userTypingCheck.userHasTyped) { text.isEmpty() && context.settings().shouldShowSearchShortcuts
store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) ))
handleTurnOnStartedTyping()
}
userTypingCheck.ranOnTextChanged = true
} }
override fun handleUrlTapped(url: String) { override fun handleUrlTapped(url: String) {
@ -111,11 +103,6 @@ class DefaultSearchController(
navController.navigate(directions) navController.navigate(directions)
} }
override fun handleTurnOnStartedTyping() {
userTypingCheck.ranOnTextChanged = true
userTypingCheck.userHasTyped = true
}
override fun handleExistingSessionSelected(session: Session) { override fun handleExistingSessionSelected(session: Session) {
val directions = SearchFragmentDirections.actionSearchFragmentToBrowserFragment(null) val directions = SearchFragmentDirections.actionSearchFragmentToBrowserFragment(null)
navController.nav(R.id.searchFragment, directions) navController.nav(R.id.searchFragment, directions)

@ -38,7 +38,6 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.components.StoreProvider import org.mozilla.fenix.components.StoreProvider
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.getColorFromAttr
import org.mozilla.fenix.ext.getSpannable import org.mozilla.fenix.ext.getSpannable
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
@ -79,10 +78,6 @@ class SearchFragment : Fragment(), BackHandler {
?.let(SearchFragmentArgs.Companion::fromBundle) ?.let(SearchFragmentArgs.Companion::fromBundle)
?.let { it.pastedText } ?.let { it.pastedText }
val displayShortcutEnginePicker = arguments
?.let(SearchFragmentArgs.Companion::fromBundle)
?.let { it.showShortcutEnginePicker } ?: false
val view = inflater.inflate(R.layout.fragment_search, container, false) val view = inflater.inflate(R.layout.fragment_search, container, false)
val url = session?.url.orEmpty() val url = session?.url.orEmpty()
val currentSearchEngine = SearchEngineSource.Default( val currentSearchEngine = SearchEngineSource.Default(
@ -93,10 +88,10 @@ class SearchFragment : Fragment(), BackHandler {
SearchFragmentStore( SearchFragmentStore(
SearchFragmentState( SearchFragmentState(
query = url, query = url,
showShortcutEnginePicker = displayShortcutEnginePicker,
searchEngineSource = currentSearchEngine, searchEngineSource = currentSearchEngine,
defaultEngineSource = currentSearchEngine, defaultEngineSource = currentSearchEngine,
showSearchSuggestions = requireContext().settings().shouldShowSearchSuggestions, showSearchSuggestions = requireContext().settings().shouldShowSearchSuggestions,
showSearchShortcuts = requireContext().settings().shouldShowSearchShortcuts && url.isEmpty(),
showClipboardSuggestions = requireContext().settings().shouldShowClipboardSuggestions, showClipboardSuggestions = requireContext().settings().shouldShowClipboardSuggestions,
showHistorySuggestions = requireContext().settings().shouldShowHistorySuggestions, showHistorySuggestions = requireContext().settings().shouldShowHistorySuggestions,
showBookmarkSuggestions = requireContext().settings().shouldShowBookmarkSuggestions, showBookmarkSuggestions = requireContext().settings().shouldShowBookmarkSuggestions,
@ -188,19 +183,6 @@ class SearchFragment : Fragment(), BackHandler {
view.toolbar_wrapper.clipToOutline = false view.toolbar_wrapper.clipToOutline = false
searchShortcutsButton.setOnClickListener {
val isOpen = searchStore.state.showShortcutEnginePicker
searchStore.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(!isOpen))
if (isOpen) {
requireComponents.analytics.metrics.track(Event.SearchShortcutMenuClosed)
} else {
requireComponents.analytics.metrics.track(Event.SearchShortcutMenuOpened)
}
searchInteractor.turnOnStartedTyping()
}
fill_link_from_clipboard.setOnClickListener { fill_link_from_clipboard.setOnClickListener {
(activity as HomeActivity) (activity as HomeActivity)
.openToBrowserAndLoad( .openToBrowserAndLoad(
@ -214,7 +196,6 @@ class SearchFragment : Fragment(), BackHandler {
awesomeBarView.update(it) awesomeBarView.update(it)
toolbarView.update(it) toolbarView.update(it)
updateSearchEngineIcon(it) updateSearchEngineIcon(it)
updateSearchShortuctsIcon(it)
updateSearchWithLabel(it) updateSearchWithLabel(it)
updateClipboardSuggestion(it, requireContext().components.clipboardHandler.url) updateClipboardSuggestion(it, requireContext().components.clipboardHandler.url)
} }
@ -276,30 +257,19 @@ class SearchFragment : Fragment(), BackHandler {
private fun updateSearchWithLabel(searchState: SearchFragmentState) { private fun updateSearchWithLabel(searchState: SearchFragmentState) {
search_with_shortcuts.visibility = search_with_shortcuts.visibility =
if (searchState.showShortcutEnginePicker) View.VISIBLE else View.GONE if (searchState.showSearchShortcuts) View.VISIBLE else View.GONE
} }
private fun updateClipboardSuggestion(searchState: SearchFragmentState, clipboardUrl: String?) { private fun updateClipboardSuggestion(searchState: SearchFragmentState, clipboardUrl: String?) {
val shouldBeVisible = val visibility =
if (searchState.showClipboardSuggestions && searchState.query.isEmpty() && !clipboardUrl.isNullOrEmpty()) if (searchState.showClipboardSuggestions && searchState.query.isEmpty() && !clipboardUrl.isNullOrEmpty())
View.VISIBLE else View.GONE View.VISIBLE else View.GONE
fill_link_from_clipboard.visibility = shouldBeVisible fill_link_from_clipboard.visibility = visibility
divider_line.visibility = shouldBeVisible divider_line.visibility = visibility
clipboard_url.text = clipboardUrl clipboard_url.text = clipboardUrl
} }
private fun updateSearchShortuctsIcon(searchState: SearchFragmentState) {
with(requireContext()) {
val showShortcuts = searchState.showShortcutEnginePicker
searchShortcutsButton?.isChecked = showShortcuts
val color = if (showShortcuts) R.attr.contrastText else R.attr.primaryText
searchShortcutsButton.compoundDrawables[0]?.setTint(getColorFromAttr(color))
}
}
override fun onRequestPermissionsResult( override fun onRequestPermissionsResult(
requestCode: Int, requestCode: Int,
permissions: Array<String>, permissions: Array<String>,

@ -33,10 +33,10 @@ sealed class SearchEngineSource {
/** /**
* The state for the Search Screen * The state for the Search Screen
* @property query The current search query string * @property query The current search query string
* @property showShortcutEnginePicker Whether or not to show the available search engine view
* @property searchEngineSource The current selected search engine with the context of how it was selected * @property searchEngineSource The current selected search engine with the context of how it was selected
* @property defaultEngineSource The current default search engine source * @property defaultEngineSource The current default search engine source
* @property showSearchSuggestions Whether or not to show search suggestions from the search engine in the AwesomeBar * @property showSearchSuggestions Whether or not to show search suggestions from the search engine in the AwesomeBar
* @property showSearchShortcuts Whether or not to show search shortcuts in the AwesomeBar
* @property showClipboardSuggestions Whether or not to show clipboard suggestion in the AwesomeBar * @property showClipboardSuggestions Whether or not to show clipboard suggestion in the AwesomeBar
* @property showHistorySuggestions Whether or not to show history suggestions in the AwesomeBar * @property showHistorySuggestions Whether or not to show history suggestions in the AwesomeBar
* @property showBookmarkSuggestions Whether or not to show the bookmark suggestion in the AwesomeBar * @property showBookmarkSuggestions Whether or not to show the bookmark suggestion in the AwesomeBar
@ -45,10 +45,10 @@ sealed class SearchEngineSource {
*/ */
data class SearchFragmentState( data class SearchFragmentState(
val query: String, val query: String,
val showShortcutEnginePicker: Boolean,
val searchEngineSource: SearchEngineSource, val searchEngineSource: SearchEngineSource,
val defaultEngineSource: SearchEngineSource.Default, val defaultEngineSource: SearchEngineSource.Default,
val showSearchSuggestions: Boolean, val showSearchSuggestions: Boolean,
val showSearchShortcuts: Boolean,
val showClipboardSuggestions: Boolean, val showClipboardSuggestions: Boolean,
val showHistorySuggestions: Boolean, val showHistorySuggestions: Boolean,
val showBookmarkSuggestions: Boolean, val showBookmarkSuggestions: Boolean,
@ -74,16 +74,15 @@ private fun searchStateReducer(state: SearchFragmentState, action: SearchFragmen
is SearchFragmentAction.SearchShortcutEngineSelected -> is SearchFragmentAction.SearchShortcutEngineSelected ->
state.copy( state.copy(
searchEngineSource = SearchEngineSource.Shortcut(action.engine), searchEngineSource = SearchEngineSource.Shortcut(action.engine),
showShortcutEnginePicker = false showSearchShortcuts = false
) )
is SearchFragmentAction.ShowSearchShortcutEnginePicker -> is SearchFragmentAction.ShowSearchShortcutEnginePicker ->
state.copy(showShortcutEnginePicker = action.show) state.copy(showSearchShortcuts = action.show)
is SearchFragmentAction.UpdateQuery -> is SearchFragmentAction.UpdateQuery ->
state.copy(query = action.query) state.copy(query = action.query)
is SearchFragmentAction.SelectNewDefaultSearchEngine -> is SearchFragmentAction.SelectNewDefaultSearchEngine ->
state.copy( state.copy(
searchEngineSource = SearchEngineSource.Default(action.engine), searchEngineSource = SearchEngineSource.Default(action.engine)
showShortcutEnginePicker = false
) )
} }
} }

@ -45,10 +45,6 @@ class SearchInteractor(
searchController.handleClickSearchEngineSettings() searchController.handleClickSearchEngineSettings()
} }
fun turnOnStartedTyping() {
searchController.handleTurnOnStartedTyping()
}
override fun onExistingSessionSelected(session: Session) { override fun onExistingSessionSelected(session: Session) {
searchController.handleExistingSessionSelected(session) searchController.handleExistingSessionSelected(session)
} }

@ -166,7 +166,7 @@ class AwesomeBarView(
fun update(state: SearchFragmentState) { fun update(state: SearchFragmentState) {
view.removeAllProviders() view.removeAllProviders()
if (state.showShortcutEnginePicker) { if (state.showSearchShortcuts) {
view.addProviders(shortcutsEnginePickerProvider) view.addProviders(shortcutsEnginePickerProvider)
} else { } else {
if (state.showSearchSuggestions) { if (state.showSearchSuggestions) {

@ -16,7 +16,7 @@ import org.mozilla.fenix.settings.SharedPreferenceUpdater
class SearchEngineFragment : PreferenceFragmentCompat() { class SearchEngineFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.search_engine_preferences, rootKey) setPreferencesFromResource(R.xml.search_preferences, rootKey)
} }
override fun onResume() { override fun onResume() {
@ -29,7 +29,10 @@ class SearchEngineFragment : PreferenceFragmentCompat() {
isChecked = context.settings().shouldShowSearchSuggestions isChecked = context.settings().shouldShowSearchSuggestions
} }
searchSuggestionsPreference?.onPreferenceChangeListener = SharedPreferenceUpdater() val showSearchShortcuts =
findPreference<SwitchPreference>(getPreferenceKey(R.string.pref_key_show_search_shortcuts))?.apply {
isChecked = context.settings().shouldShowSearchShortcuts
}
val showHistorySuggestions = val showHistorySuggestions =
findPreference<SwitchPreference>(getPreferenceKey(R.string.pref_key_search_browsing_history))?.apply { findPreference<SwitchPreference>(getPreferenceKey(R.string.pref_key_search_browsing_history))?.apply {
@ -46,6 +49,8 @@ class SearchEngineFragment : PreferenceFragmentCompat() {
isChecked = context.settings().shouldShowClipboardSuggestions isChecked = context.settings().shouldShowClipboardSuggestions
} }
searchSuggestionsPreference?.onPreferenceChangeListener = SharedPreferenceUpdater()
showSearchShortcuts?.onPreferenceChangeListener = SharedPreferenceUpdater()
showHistorySuggestions?.onPreferenceChangeListener = SharedPreferenceUpdater() showHistorySuggestions?.onPreferenceChangeListener = SharedPreferenceUpdater()
showBookmarkSuggestions?.onPreferenceChangeListener = SharedPreferenceUpdater() showBookmarkSuggestions?.onPreferenceChangeListener = SharedPreferenceUpdater()
showClipboardSuggestions?.onPreferenceChangeListener = SharedPreferenceUpdater() showClipboardSuggestions?.onPreferenceChangeListener = SharedPreferenceUpdater()

@ -163,6 +163,11 @@ class Settings private constructor(
default = true default = true
) )
val shouldShowSearchShortcuts by booleanPreference(
appContext.getPreferenceKey(R.string.pref_key_show_search_shortcuts),
default = true
)
val shouldUseDarkTheme by booleanPreference( val shouldUseDarkTheme by booleanPreference(
appContext.getPreferenceKey(R.string.pref_key_dark_theme), appContext.getPreferenceKey(R.string.pref_key_dark_theme),
default = false default = false

@ -156,12 +156,5 @@
android:drawableStart="@drawable/ic_qr" android:drawableStart="@drawable/ic_qr"
android:textOff="@string/search_scan_button" android:textOff="@string/search_scan_button"
android:textOn="@string/search_scan_button" /> android:textOn="@string/search_scan_button" />
<ToggleButton
android:id="@+id/searchShortcutsButton"
style="@style/search_pill"
android:drawableStart="@drawable/ic_search"
android:textOff="@string/search_shortcuts_button"
android:textOn="@string/search_shortcuts_button" />
</LinearLayout> </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

@ -98,10 +98,6 @@
android:name="session_id" android:name="session_id"
app:argType="string" app:argType="string"
app:nullable="true" /> app:nullable="true" />
<argument
android:name="showShortcutEnginePicker"
android:defaultValue="false"
app:argType="boolean" />
<action <action
android:id="@+id/action_searchFragment_to_searchEngineFragment" android:id="@+id/action_searchFragment_to_searchEngineFragment"
app:destination="@id/searchEngineFragment" app:destination="@id/searchEngineFragment"

@ -65,6 +65,7 @@
<string name="pref_key_search_widget_installed" translatable="false">pref_key_search_widget_installed</string> <string name="pref_key_search_widget_installed" translatable="false">pref_key_search_widget_installed</string>
<!-- Search Settings --> <!-- Search Settings -->
<string name="pref_key_show_search_shortcuts" translatable="false">pref_key_show_search_shortcuts</string>
<string name="pref_key_show_search_suggestions" translatable="false">pref_key_show_search_suggestions</string> <string name="pref_key_show_search_suggestions" translatable="false">pref_key_show_search_suggestions</string>
<string name="pref_key_show_clipboard_suggestions" translatable="false">pref_key_show_clipboard_suggestions</string> <string name="pref_key_show_clipboard_suggestions" translatable="false">pref_key_show_clipboard_suggestions</string>
<string name="pref_key_search_browsing_history" translatable="false">pref_key_search_browsing_history</string> <string name="pref_key_search_browsing_history" translatable="false">pref_key_search_browsing_history</string>

@ -95,8 +95,6 @@
<!-- Search Fragment --> <!-- Search Fragment -->
<!-- Button in the search view that lets a user search by scanning a QR code --> <!-- Button in the search view that lets a user search by scanning a QR code -->
<string name="search_scan_button">Scan</string> <string name="search_scan_button">Scan</string>
<!-- Button in the search view that lets a user search by using a shortcut -->
<string name="search_shortcuts_button">Shortcuts</string>
<!-- Button in the search view when shortcuts are displayed that takes a user to the search engine settings --> <!-- Button in the search view when shortcuts are displayed that takes a user to the search engine settings -->
<string name="search_shortcuts_engine_settings">Search engine settings</string> <string name="search_shortcuts_engine_settings">Search engine settings</string>
<!-- Header displayed when selecting a shortcut search engine --> <!-- Header displayed when selecting a shortcut search engine -->
@ -175,6 +173,8 @@
<!-- Preference for developers --> <!-- Preference for developers -->
<string name="preferences_remote_debugging">Remote debugging via USB</string> <string name="preferences_remote_debugging">Remote debugging via USB</string>
<!-- Preference title for switch preference to show search suggestions --> <!-- Preference title for switch preference to show search suggestions -->
<string name="preferences_show_search_shortcuts">Show search shortcuts</string>
<!-- Preference title for switch preference to show search suggestions -->
<string name="preferences_show_search_suggestions">Show search suggestions</string> <string name="preferences_show_search_suggestions">Show search suggestions</string>
<!-- Preference title for switch preference to show a clipboard suggestion when searching --> <!-- Preference title for switch preference to show a clipboard suggestion when searching -->
<string name="preferences_show_clipboard_suggestions">Show clipboard suggestions</string> <string name="preferences_show_clipboard_suggestions">Show clipboard suggestions</string>

@ -17,6 +17,11 @@
android:title="@string/preferences_show_search_suggestions" android:title="@string/preferences_show_search_suggestions"
app:iconSpaceReserved="false" app:iconSpaceReserved="false"
app:allowDividerAbove="false"/> app:allowDividerAbove="false"/>
<SwitchPreference
android:defaultValue="true"
android:key="@string/pref_key_show_search_shortcuts"
android:title="@string/preferences_show_search_shortcuts"
app:iconSpaceReserved="false"/>
<SwitchPreference <SwitchPreference
android:defaultValue="true" android:defaultValue="true"
android:key="@string/pref_key_show_clipboard_suggestions" android:key="@string/pref_key_show_clipboard_suggestions"

@ -66,8 +66,7 @@ class StartSearchIntentProcessorTest {
verify { verify {
navController.navigate( navController.navigate(
NavGraphDirections.actionGlobalSearch( NavGraphDirections.actionGlobalSearch(
sessionId = null, sessionId = null
showShortcutEnginePicker = true
) )
) )
} }

@ -6,25 +6,37 @@ package org.mozilla.fenix.search
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavDirections import androidx.navigation.NavDirections
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.mockk.every import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
import io.mockk.verify import io.mockk.verify
import kotlinx.coroutines.ObsoleteCoroutinesApi
import mozilla.components.browser.search.SearchEngine import mozilla.components.browser.search.SearchEngine
import mozilla.components.browser.session.Session import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager import mozilla.components.browser.session.SessionManager
import org.junit.Assert.assertTrue import mozilla.components.support.test.robolectric.testContext
import org.junit.Assert.assertFalse
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.TestApplication
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.metrics import org.mozilla.fenix.ext.metrics
import org.mozilla.fenix.ext.nav import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.searchEngineManager import org.mozilla.fenix.ext.searchEngineManager
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.utils.Settings
import org.mozilla.fenix.whatsnew.clear
import org.robolectric.annotation.Config
@ObsoleteCoroutinesApi
@RunWith(AndroidJUnit4::class)
@Config(application = TestApplication::class)
class DefaultSearchControllerTest { class DefaultSearchControllerTest {
private val context: HomeActivity = mockk(relaxed = true) private val context: HomeActivity = mockk(relaxed = true)
@ -37,10 +49,10 @@ class DefaultSearchControllerTest {
private val sessionManager: SessionManager = mockk(relaxed = true) private val sessionManager: SessionManager = mockk(relaxed = true)
private lateinit var controller: DefaultSearchController private lateinit var controller: DefaultSearchController
private lateinit var settings: Settings
@Before @Before
fun setUp() { fun setUp() {
every { store.state.showShortcutEnginePicker } returns false
every { context.searchEngineManager.defaultSearchEngine } returns defaultSearchEngine every { context.searchEngineManager.defaultSearchEngine } returns defaultSearchEngine
every { store.state.session } returns session every { store.state.session } returns session
every { store.state.searchEngineSource.searchEngine } returns searchEngine every { store.state.searchEngineSource.searchEngine } returns searchEngine
@ -52,6 +64,8 @@ class DefaultSearchControllerTest {
store = store, store = store,
navController = navController navController = navController
) )
settings = testContext.settings().apply { testContext.settings().clear() }
} }
@Test @Test
@ -77,16 +91,71 @@ class DefaultSearchControllerTest {
} }
@Test @Test
fun handleTextChanged() { fun handleTextChangedNonEmpty() {
val text = "fenix" val text = "fenix"
controller.handleTextChanged(text) controller.handleTextChanged(text)
verify { store.dispatch(SearchFragmentAction.UpdateQuery(text)) } verify { store.dispatch(SearchFragmentAction.UpdateQuery(text)) }
verify(inverse = true) { }
store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false))
} @Test
assertTrue(controller.userTypingCheck.ranOnTextChanged) fun handleTextChangedEmpty() {
val text = ""
controller.handleTextChanged(text)
verify { store.dispatch(SearchFragmentAction.UpdateQuery(text)) }
}
@Test
fun `show search shortcuts when setting enabled AND query empty`() {
val text = ""
controller.handleTextChanged(text)
verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(true)) }
}
@Test
fun `do not show search shortcuts when setting enabled AND query non-empty`() {
val text = "mozilla"
controller.handleTextChanged(text)
verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) }
}
@Test
fun `do not show search shortcuts when setting disabled AND query empty`() {
testContext.settings().preferences
.edit()
.putBoolean(testContext.getString(R.string.pref_key_show_search_shortcuts), false)
.apply()
assertFalse(testContext.settings().shouldShowSearchShortcuts)
val text = ""
controller.handleTextChanged(text)
verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) }
}
@Test
fun `do not show search shortcuts when setting disabled AND query non-empty`() {
testContext.settings().preferences
.edit()
.putBoolean(testContext.getString(R.string.pref_key_show_search_shortcuts), false)
.apply()
assertFalse(testContext.settings().shouldShowSearchShortcuts)
val text = "mozilla"
controller.handleTextChanged(text)
verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) }
} }
@Test @Test
@ -137,14 +206,6 @@ class DefaultSearchControllerTest {
verify { navController.navigate(directions) } verify { navController.navigate(directions) }
} }
@Test
fun handleTurnOnStartedTyping() {
controller.handleTurnOnStartedTyping()
assertTrue(controller.userTypingCheck.ranOnTextChanged)
assertTrue(controller.userTypingCheck.userHasTyped)
}
@Test @Test
fun handleExistingSessionSelected() { fun handleExistingSessionSelected() {
val session: Session = mockk(relaxed = true) val session: Session = mockk(relaxed = true)

@ -33,6 +33,7 @@ class SearchFragmentStoreTest {
store.dispatch(SearchFragmentAction.SearchShortcutEngineSelected(searchEngine)).join() store.dispatch(SearchFragmentAction.SearchShortcutEngineSelected(searchEngine)).join()
assertNotSame(initialState, store.state) assertNotSame(initialState, store.state)
assertEquals(SearchEngineSource.Shortcut(searchEngine), store.state.searchEngineSource) assertEquals(SearchEngineSource.Shortcut(searchEngine), store.state.searchEngineSource)
assertEquals(false, store.state.showSearchShortcuts)
} }
@Test @Test
@ -42,15 +43,15 @@ class SearchFragmentStoreTest {
store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(true)).join() store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(true)).join()
assertNotSame(initialState, store.state) assertNotSame(initialState, store.state)
assertEquals(true, store.state.showShortcutEnginePicker) assertEquals(true, store.state.showSearchShortcuts)
} }
private fun emptyDefaultState(): SearchFragmentState = SearchFragmentState( private fun emptyDefaultState(): SearchFragmentState = SearchFragmentState(
query = "", query = "",
searchEngineSource = mockk(), searchEngineSource = mockk(),
defaultEngineSource = mockk(), defaultEngineSource = mockk(),
showShortcutEnginePicker = false,
showSearchSuggestions = false, showSearchSuggestions = false,
showSearchShortcuts = false,
showClipboardSuggestions = false, showClipboardSuggestions = false,
showHistorySuggestions = false, showHistorySuggestions = false,
showBookmarkSuggestions = false, showBookmarkSuggestions = false,

@ -38,7 +38,6 @@ class SearchInteractorTest {
every { context.openToBrowserAndLoad(any(), any(), any(), any(), any(), any()) } just Runs every { context.openToBrowserAndLoad(any(), any(), any(), any(), any(), any()) } just Runs
every { store.state } returns state every { store.state } returns state
every { state.showShortcutEnginePicker } returns true
every { state.session } returns null every { state.session } returns null
every { state.searchEngineSource } returns searchEngine every { state.searchEngineSource } returns searchEngine
@ -111,7 +110,6 @@ class SearchInteractorTest {
every { store.state } returns state every { store.state } returns state
every { state.session } returns null every { state.session } returns null
every { state.showShortcutEnginePicker } returns true
val searchController: SearchController = DefaultSearchController( val searchController: SearchController = DefaultSearchController(
context, context,
@ -146,7 +144,6 @@ class SearchInteractorTest {
every { store.state } returns state every { store.state } returns state
every { state.session } returns null every { state.session } returns null
every { state.searchEngineSource } returns searchEngine every { state.searchEngineSource } returns searchEngine
every { state.showShortcutEnginePicker } returns true
val searchController: SearchController = DefaultSearchController( val searchController: SearchController = DefaultSearchController(
context, context,

@ -246,6 +246,13 @@ class SettingsTest {
assertTrue(settings.shouldShowClipboardSuggestions) assertTrue(settings.shouldShowClipboardSuggestions)
} }
@Test
fun shouldShowSearchShortcuts() {
// When just created
// Then
assertTrue(settings.shouldShowSearchShortcuts)
}
@Test @Test
fun shouldShowHistorySuggestions() { fun shouldShowHistorySuggestions() {
// When just created // When just created

Loading…
Cancel
Save