[fenix] For https://github.com/mozilla-mobile/fenix/issues/25816: Filter history suggestions depending on the selected search engine

If the current search engine is not one added by the application and not the
default one then:
- if it is a topic specific one show history from just the it's host domain
- if it is a general one then don't show history at all
- if it is the default search engine then show all history.
pull/600/head
Mugurell 2 years ago committed by mergify[bot]
parent d7dd3a587a
commit 4c76307b08

@ -85,7 +85,9 @@ sealed class SearchEngineSource {
* @property showSearchShortcutsSetting Whether the setting for showing search shortcuts is enabled
* or disabled.
* @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 showHistorySuggestionsForCurrentEngine Whether or not to show history suggestions for only
* the current search engine.
* @property showAllHistorySuggestions Whether or not to show history suggestions in the AwesomeBar
* @property showBookmarkSuggestions Whether or not to show the bookmark suggestion in the AwesomeBar
* @property showSyncedTabsSuggestions Whether or not to show the synced tabs suggestion in the AwesomeBar
* @property showSessionSuggestions Whether or not to show the session suggestion in the AwesomeBar
@ -104,7 +106,8 @@ data class SearchFragmentState(
val areShortcutsAvailable: Boolean,
val showSearchShortcutsSetting: Boolean,
val showClipboardSuggestions: Boolean,
val showHistorySuggestions: Boolean,
val showHistorySuggestionsForCurrentEngine: Boolean,
val showAllHistorySuggestions: Boolean,
val showBookmarkSuggestions: Boolean,
val showSyncedTabsSuggestions: Boolean,
val showSessionSuggestions: Boolean,
@ -154,7 +157,8 @@ fun createInitialSearchFragmentState(
areShortcutsAvailable = false,
showSearchShortcutsSetting = settings.shouldShowSearchShortcuts,
showClipboardSuggestions = settings.shouldShowClipboardSuggestions,
showHistorySuggestions = settings.shouldShowHistorySuggestions,
showHistorySuggestionsForCurrentEngine = false,
showAllHistorySuggestions = settings.shouldShowHistorySuggestions,
showBookmarkSuggestions = settings.shouldShowBookmarkSuggestions,
showSyncedTabsSuggestions = settings.shouldShowSyncedTabsSuggestions,
showSessionSuggestions = true,
@ -237,7 +241,8 @@ private fun searchStateReducer(state: SearchFragmentState, action: SearchFragmen
showSearchSuggestions = action.settings.shouldShowSearchSuggestions,
showSearchShortcuts = action.settings.shouldShowSearchShortcuts,
showClipboardSuggestions = action.settings.shouldShowClipboardSuggestions,
showHistorySuggestions = action.settings.shouldShowHistorySuggestions,
showHistorySuggestionsForCurrentEngine = false, // we'll show all history
showAllHistorySuggestions = action.settings.shouldShowHistorySuggestions,
showBookmarkSuggestions = action.settings.shouldShowBookmarkSuggestions,
showSyncedTabsSuggestions = action.settings.shouldShowSyncedTabsSuggestions,
showSessionSuggestions = true,
@ -251,7 +256,9 @@ private fun searchStateReducer(state: SearchFragmentState, action: SearchFragmen
false -> action.settings.shouldShowSearchShortcuts
},
showClipboardSuggestions = action.settings.shouldShowClipboardSuggestions,
showHistorySuggestions = when (action.settings.showUnifiedSearchFeature) {
showHistorySuggestionsForCurrentEngine = action.settings.showUnifiedSearchFeature &&
action.settings.shouldShowHistorySuggestions && !action.engine.isGeneral,
showAllHistorySuggestions = when (action.settings.showUnifiedSearchFeature) {
true -> false
false -> action.settings.shouldShowHistorySuggestions
},
@ -274,7 +281,8 @@ private fun searchStateReducer(state: SearchFragmentState, action: SearchFragmen
showSearchSuggestions = false,
showSearchShortcuts = false,
showClipboardSuggestions = false,
showHistorySuggestions = true,
showHistorySuggestionsForCurrentEngine = false,
showAllHistorySuggestions = true,
showBookmarkSuggestions = false,
showSyncedTabsSuggestions = false,
showSessionSuggestions = false,
@ -285,7 +293,8 @@ private fun searchStateReducer(state: SearchFragmentState, action: SearchFragmen
showSearchSuggestions = false,
showSearchShortcuts = false,
showClipboardSuggestions = false,
showHistorySuggestions = false,
showHistorySuggestionsForCurrentEngine = false,
showAllHistorySuggestions = false,
showBookmarkSuggestions = true,
showSyncedTabsSuggestions = false,
showSessionSuggestions = false,
@ -296,7 +305,8 @@ private fun searchStateReducer(state: SearchFragmentState, action: SearchFragmen
showSearchSuggestions = false,
showSearchShortcuts = false,
showClipboardSuggestions = false,
showHistorySuggestions = false,
showHistorySuggestionsForCurrentEngine = false,
showAllHistorySuggestions = false,
showBookmarkSuggestions = false,
showSyncedTabsSuggestions = true,
showSessionSuggestions = true,

@ -4,7 +4,10 @@
package org.mozilla.fenix.search.awesomebar
import androidx.appcompat.content.res.AppCompatResources.getDrawable
import android.content.Context
import android.graphics.drawable.Drawable
import androidx.annotation.VisibleForTesting
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.graphics.BlendModeColorFilterCompat.createBlendModeColorFilterCompat
import androidx.core.graphics.BlendModeCompat.SRC_IN
import androidx.core.graphics.drawable.toBitmap
@ -12,6 +15,7 @@ import mozilla.components.browser.state.search.SearchEngine
import mozilla.components.browser.state.state.searchEngines
import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
import mozilla.components.concept.awesomebar.AwesomeBar
import mozilla.components.concept.engine.Engine
import mozilla.components.concept.engine.EngineSession
import mozilla.components.feature.awesomebar.provider.BookmarksStorageSuggestionProvider
import mozilla.components.feature.awesomebar.provider.CombinedHistorySuggestionProvider
@ -29,6 +33,7 @@ import mozilla.components.support.ktx.android.content.getColorFromAttr
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.Components
import org.mozilla.fenix.components.Core.Companion.METADATA_HISTORY_SUGGESTION_LIMIT
import org.mozilla.fenix.components.Core.Companion.METADATA_SHORTCUT_SUGGESTION_LIMIT
import org.mozilla.fenix.ext.components
@ -46,9 +51,11 @@ class AwesomeBarView(
val view: AwesomeBarWrapper,
fromHomeFragment: Boolean,
) {
private var components: Components = activity.components
private val engineForSpeculativeConnects: Engine?
private val sessionProvider: SessionSuggestionProvider
private val historyStorageProvider: HistoryStorageSuggestionProvider
private val combinedHistoryProvider: CombinedHistorySuggestionProvider
private val defaultHistoryStorageProvider: HistoryStorageSuggestionProvider
private val defaultCombinedHistoryProvider: CombinedHistorySuggestionProvider
private val shortcutsEnginePickerProvider: ShortcutsSuggestionProvider
private val bookmarksStorageSuggestionProvider: BookmarksStorageSuggestionProvider
private val syncedTabsStorageSuggestionProvider: SyncedTabsStorageSuggestionProvider
@ -94,10 +101,9 @@ class AwesomeBarView(
}
init {
val components = activity.components
val primaryTextColor = activity.getColorFromAttr(R.attr.textPrimary)
val engineForSpeculativeConnects = when (activity.browsingModeManager.mode) {
engineForSpeculativeConnects = when (activity.browsingModeManager.mode) {
BrowsingMode.Normal -> components.core.engine
BrowsingMode.Private -> null
}
@ -112,7 +118,7 @@ class AwesomeBarView(
suggestionsHeader = activity.getString(R.string.firefox_suggest_header),
)
historyStorageProvider =
defaultHistoryStorageProvider =
HistoryStorageSuggestionProvider(
components.core.historyStorage,
loadUrlUseCase,
@ -121,7 +127,7 @@ class AwesomeBarView(
suggestionsHeader = activity.getString(R.string.firefox_suggest_header),
)
combinedHistoryProvider =
defaultCombinedHistoryProvider =
CombinedHistorySuggestionProvider(
historyStorage = components.core.historyStorage,
historyMetadataStorage = components.core.historyStorage,
@ -254,27 +260,34 @@ class AwesomeBarView(
}
@Suppress("ComplexMethod")
private fun getProvidersToAdd(
@VisibleForTesting
internal fun getProvidersToAdd(
state: SearchProviderState,
): MutableSet<AwesomeBar.SuggestionProvider> {
val providersToAdd = mutableSetOf<AwesomeBar.SuggestionProvider>()
when (state.searchEngineSource) {
is SearchEngineSource.History -> {
combinedHistoryProvider.setMaxNumberOfSuggestions(METADATA_HISTORY_SUGGESTION_LIMIT)
historyStorageProvider.setMaxNumberOfSuggestions(METADATA_HISTORY_SUGGESTION_LIMIT)
defaultCombinedHistoryProvider.setMaxNumberOfSuggestions(METADATA_HISTORY_SUGGESTION_LIMIT)
defaultHistoryStorageProvider.setMaxNumberOfSuggestions(METADATA_HISTORY_SUGGESTION_LIMIT)
}
else -> {
combinedHistoryProvider.setMaxNumberOfSuggestions(METADATA_SUGGESTION_LIMIT)
historyStorageProvider.setMaxNumberOfSuggestions(METADATA_SUGGESTION_LIMIT)
defaultCombinedHistoryProvider.setMaxNumberOfSuggestions(METADATA_SUGGESTION_LIMIT)
defaultHistoryStorageProvider.setMaxNumberOfSuggestions(METADATA_SUGGESTION_LIMIT)
}
}
if (state.showHistorySuggestions) {
if (state.showAllHistorySuggestions) {
if (activity.settings().historyMetadataUIFeature) {
providersToAdd.add(combinedHistoryProvider)
providersToAdd.add(defaultCombinedHistoryProvider)
} else {
providersToAdd.add(historyStorageProvider)
providersToAdd.add(defaultHistoryStorageProvider)
}
}
if (state.showHistorySuggestionsForCurrentEngine) {
getHistoryProvidersForSearchEngine(state.searchEngineSource)?.let {
providersToAdd.add(it)
}
}
@ -301,6 +314,46 @@ class AwesomeBarView(
return providersToAdd
}
/**
* Get a new history suggestion provider that will return suggestions only from the current
* search engine's host.
* Used only for when unified search is active.
*
* @param searchEngineSource Search engine wrapper also informing about the selection type.
*
* @return A [CombinedHistorySuggestionProvider] or [HistoryStorageSuggestionProvider] depending
* on if the history metadata feature is enabled or `null` if the current engine's host is unknown.
*/
@VisibleForTesting
internal fun getHistoryProvidersForSearchEngine(
searchEngineSource: SearchEngineSource,
): AwesomeBar.SuggestionProvider? {
val searchEngineHostFilter = searchEngineSource.searchEngine?.resultsUrl?.host ?: return null
return if (activity.settings().historyMetadataUIFeature) {
CombinedHistorySuggestionProvider(
historyStorage = components.core.historyStorage,
historyMetadataStorage = components.core.historyStorage,
loadUrlUseCase = loadUrlUseCase,
icons = components.core.icons,
engine = engineForSpeculativeConnects,
maxNumberOfSuggestions = METADATA_SUGGESTION_LIMIT,
suggestionsHeader = activity.getString(R.string.firefox_suggest_header),
resultsHostFilter = searchEngineHostFilter,
)
} else {
HistoryStorageSuggestionProvider(
historyStorage = components.core.historyStorage,
loadUrlUseCase = loadUrlUseCase,
icons = components.core.icons,
engine = engineForSpeculativeConnects,
maxNumberOfSuggestions = METADATA_SUGGESTION_LIMIT,
suggestionsHeader = activity.getString(R.string.firefox_suggest_header),
resultsHostFilter = searchEngineHostFilter,
)
}
}
private fun getSelectedSearchSuggestionProvider(state: SearchProviderState): List<AwesomeBar.SuggestionProvider> {
return when (state.searchEngineSource) {
is SearchEngineSource.Default -> listOf(
@ -366,7 +419,8 @@ class AwesomeBarView(
data class SearchProviderState(
val showSearchShortcuts: Boolean,
val showHistorySuggestions: Boolean,
val showHistorySuggestionsForCurrentEngine: Boolean,
val showAllHistorySuggestions: Boolean,
val showBookmarkSuggestions: Boolean,
val showSearchSuggestions: Boolean,
val showSyncedTabsSuggestions: Boolean,
@ -379,12 +433,18 @@ class AwesomeBarView(
const val METADATA_SUGGESTION_LIMIT = 3
const val GOOGLE_SEARCH_ENGINE_NAME = "Google"
@VisibleForTesting
internal fun getDrawable(context: Context, resId: Int): Drawable? {
return AppCompatResources.getDrawable(context, resId)
}
}
}
fun SearchFragmentState.toSearchProviderState() = AwesomeBarView.SearchProviderState(
showSearchShortcuts,
showHistorySuggestions,
showHistorySuggestionsForCurrentEngine,
showAllHistorySuggestions,
showBookmarkSuggestions,
showSearchSuggestions,
showSyncedTabsSuggestions,

@ -58,6 +58,8 @@ class SearchFragmentStoreTest {
activity.browsingModeManager.mode = BrowsingMode.Normal
every { components.core.store.state } returns BrowserState()
every { settings.shouldShowSearchShortcuts } returns true
every { settings.showUnifiedSearchFeature } returns true
every { settings.shouldShowHistorySuggestions } returns true
val expected = SearchFragmentState(
query = "",
@ -71,7 +73,8 @@ class SearchFragmentStoreTest {
showSearchShortcuts = false,
areShortcutsAvailable = false,
showClipboardSuggestions = false,
showHistorySuggestions = false,
showHistorySuggestionsForCurrentEngine = false,
showAllHistorySuggestions = true,
showBookmarkSuggestions = false,
showSyncedTabsSuggestions = false,
showSessionSuggestions = true,
@ -130,7 +133,8 @@ class SearchFragmentStoreTest {
showSearchShortcuts = false,
areShortcutsAvailable = false,
showClipboardSuggestions = false,
showHistorySuggestions = false,
showHistorySuggestionsForCurrentEngine = false,
showAllHistorySuggestions = false,
showBookmarkSuggestions = false,
showSyncedTabsSuggestions = false,
showSessionSuggestions = true,
@ -160,34 +164,163 @@ class SearchFragmentStoreTest {
}
@Test
fun selectSearchShortcutEngine() = runTest {
val initialState = emptyDefaultState()
fun `WHEN the search engine is the default one THEN search suggestions providers are updated`() = runTest {
val initialState = emptyDefaultState(showHistorySuggestionsForCurrentEngine = false)
val store = SearchFragmentStore(initialState)
every { settings.shouldShowSearchShortcuts } returns false
every { settings.shouldShowSearchSuggestions } returns true
every { settings.shouldShowClipboardSuggestions } returns true
every { settings.shouldShowHistorySuggestions } returns true
every { settings.shouldShowBookmarkSuggestions } returns false
every { settings.shouldShowSyncedTabsSuggestions } returns false
store.dispatch(SearchFragmentAction.SearchDefaultEngineSelected(searchEngine, settings)).join()
assertNotSame(initialState, store.state)
assertEquals(SearchEngineSource.Default(searchEngine), store.state.searchEngineSource)
assertTrue(store.state.showSearchSuggestions)
assertFalse(store.state.showSearchShortcuts)
assertTrue(store.state.showClipboardSuggestions)
assertFalse(store.state.showHistorySuggestionsForCurrentEngine)
assertTrue(store.state.showAllHistorySuggestions)
assertFalse(store.state.showBookmarkSuggestions)
assertFalse(store.state.showSyncedTabsSuggestions)
assertTrue(store.state.showSessionSuggestions)
}
@Test
fun `GIVEN unified search is enabled WHEN the search engine is updated to a general engine shortcut THEN search suggestions providers are updated`() = runTest {
val initialState = emptyDefaultState(showHistorySuggestionsForCurrentEngine = false)
val store = SearchFragmentStore(initialState)
every { searchEngine.isGeneral } returns true
every { settings.showUnifiedSearchFeature } returns true
every { settings.shouldShowSearchShortcuts } returns true
every { settings.shouldShowClipboardSuggestions } returns true
every { settings.shouldShowHistorySuggestions } returns true
every { settings.shouldShowBookmarkSuggestions } returns true
every { settings.shouldShowSyncedTabsSuggestions } returns true
store.dispatch(SearchFragmentAction.SearchShortcutEngineSelected(searchEngine, settings)).join()
assertNotSame(initialState, store.state)
assertEquals(SearchEngineSource.Shortcut(searchEngine), store.state.searchEngineSource)
assertTrue(store.state.showSearchSuggestions)
assertFalse(store.state.showSearchShortcuts)
assertTrue(store.state.showClipboardSuggestions)
assertFalse(store.state.showHistorySuggestionsForCurrentEngine)
assertFalse(store.state.showAllHistorySuggestions)
assertFalse(store.state.showBookmarkSuggestions)
assertFalse(store.state.showSyncedTabsSuggestions)
assertFalse(store.state.showSessionSuggestions)
}
@Test
fun `GIVEN unified search is enabled WHEN the search engine is updated to a topic specific engine shortcut THEN search suggestions providers are updated`() = runTest {
val initialState = emptyDefaultState(showHistorySuggestionsForCurrentEngine = false)
val store = SearchFragmentStore(initialState)
every { searchEngine.isGeneral } returns false
every { settings.showUnifiedSearchFeature } returns true
every { settings.shouldShowSearchSuggestions } returns false
every { settings.shouldShowSearchShortcuts } returns false
every { settings.shouldShowClipboardSuggestions } returns false
every { settings.shouldShowHistorySuggestions } returns true
every { settings.shouldShowBookmarkSuggestions } returns false
every { settings.shouldShowSyncedTabsSuggestions } returns false
store.dispatch(SearchFragmentAction.SearchShortcutEngineSelected(searchEngine, settings)).join()
assertNotSame(initialState, store.state)
assertEquals(SearchEngineSource.Shortcut(searchEngine), store.state.searchEngineSource)
assertEquals(false, store.state.showSearchShortcuts)
assertTrue(store.state.showSearchSuggestions)
assertFalse(store.state.showSearchShortcuts)
assertFalse(store.state.showClipboardSuggestions)
assertTrue(store.state.showHistorySuggestionsForCurrentEngine)
assertFalse(store.state.showAllHistorySuggestions)
assertFalse(store.state.showBookmarkSuggestions)
assertFalse(store.state.showSyncedTabsSuggestions)
assertFalse(store.state.showSessionSuggestions)
}
@Test
fun `WHEN history engine selected action dispatched THEN update search engine source`() = runTest {
val initialState = emptyDefaultState()
fun `GIVEN unified search is disabled WHEN the search engine is updated to a shortcut THEN search suggestions providers are updated`() = runTest {
val initialState = emptyDefaultState(showHistorySuggestionsForCurrentEngine = false)
val store = SearchFragmentStore(initialState)
every { settings.showUnifiedSearchFeature } returns false
every { settings.shouldShowSearchShortcuts } returns true
every { settings.shouldShowClipboardSuggestions } returns false
every { settings.shouldShowHistorySuggestions } returns true
every { settings.shouldShowBookmarkSuggestions } returns false
every { settings.shouldShowSyncedTabsSuggestions } returns true
store.dispatch(SearchFragmentAction.SearchShortcutEngineSelected(searchEngine, settings)).join()
assertNotSame(initialState, store.state)
assertEquals(SearchEngineSource.Shortcut(searchEngine), store.state.searchEngineSource)
assertTrue(store.state.showSearchSuggestions)
assertTrue(store.state.showSearchShortcuts)
assertFalse(store.state.showClipboardSuggestions)
assertFalse(store.state.showHistorySuggestionsForCurrentEngine)
assertTrue(store.state.showAllHistorySuggestions)
assertFalse(store.state.showBookmarkSuggestions)
assertTrue(store.state.showSyncedTabsSuggestions)
assertTrue(store.state.showSessionSuggestions)
}
@Test
fun `WHEN doing a history search THEN search suggestions providers are updated`() = runTest {
val initialState = emptyDefaultState(showHistorySuggestionsForCurrentEngine = true)
val store = SearchFragmentStore(initialState)
store.dispatch(SearchFragmentAction.SearchHistoryEngineSelected(searchEngine)).join()
assertNotSame(initialState, store.state)
assertEquals(SearchEngineSource.History(searchEngine), store.state.searchEngineSource)
assertFalse(store.state.showSearchSuggestions)
assertFalse(store.state.showSearchShortcuts)
assertFalse(store.state.showClipboardSuggestions)
assertFalse(store.state.showHistorySuggestionsForCurrentEngine)
assertTrue(store.state.showAllHistorySuggestions)
assertFalse(store.state.showBookmarkSuggestions)
assertFalse(store.state.showSyncedTabsSuggestions)
assertFalse(store.state.showSessionSuggestions)
}
@Test
fun `WHEN bookmarks engine selected action dispatched THEN update search engine source`() = runTest {
val initialState = emptyDefaultState()
fun `WHEN doing a bookmarks search THEN search suggestions providers are updated`() = runTest {
val initialState = emptyDefaultState(showHistorySuggestionsForCurrentEngine = true)
val store = SearchFragmentStore(initialState)
store.dispatch(SearchFragmentAction.SearchBookmarksEngineSelected(searchEngine)).join()
assertNotSame(initialState, store.state)
assertEquals(SearchEngineSource.Bookmarks(searchEngine), store.state.searchEngineSource)
assertFalse(store.state.showSearchSuggestions)
assertFalse(store.state.showSearchShortcuts)
assertFalse(store.state.showClipboardSuggestions)
assertFalse(store.state.showHistorySuggestionsForCurrentEngine)
assertFalse(store.state.showAllHistorySuggestions)
assertTrue(store.state.showBookmarkSuggestions)
assertFalse(store.state.showSyncedTabsSuggestions)
assertFalse(store.state.showSessionSuggestions)
}
@Test
fun `WHEN doing a tabs search THEN search suggestions providers are updated`() = runTest {
val initialState = emptyDefaultState(showHistorySuggestionsForCurrentEngine = true)
val store = SearchFragmentStore(initialState)
store.dispatch(SearchFragmentAction.SearchTabsEngineSelected(searchEngine)).join()
assertNotSame(initialState, store.state)
assertEquals(SearchEngineSource.Tabs(searchEngine), store.state.searchEngineSource)
assertFalse(store.state.showSearchSuggestions)
assertFalse(store.state.showSearchShortcuts)
assertFalse(store.state.showClipboardSuggestions)
assertFalse(store.state.showHistorySuggestionsForCurrentEngine)
assertFalse(store.state.showAllHistorySuggestions)
assertFalse(store.state.showBookmarkSuggestions)
assertTrue(store.state.showSyncedTabsSuggestions)
assertTrue(store.state.showSessionSuggestions)
}
@Test
@ -412,6 +545,7 @@ class SearchFragmentStoreTest {
defaultEngine: SearchEngine? = mockk(),
areShortcutsAvailable: Boolean = true,
showSearchShortcutsSetting: Boolean = false,
showHistorySuggestionsForCurrentEngine: Boolean = true,
): SearchFragmentState = SearchFragmentState(
tabId = null,
url = "",
@ -425,7 +559,8 @@ class SearchFragmentStoreTest {
showSearchShortcuts = false,
areShortcutsAvailable = areShortcutsAvailable,
showClipboardSuggestions = false,
showHistorySuggestions = false,
showHistorySuggestionsForCurrentEngine = showHistorySuggestionsForCurrentEngine,
showAllHistorySuggestions = false,
showBookmarkSuggestions = false,
showSyncedTabsSuggestions = false,
showSessionSuggestions = false,

@ -0,0 +1,439 @@
/* 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.search.awesomebar
import android.app.Activity
import android.graphics.drawable.VectorDrawable
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.mockkStatic
import io.mockk.unmockkObject
import io.mockk.unmockkStatic
import mozilla.components.feature.awesomebar.provider.BookmarksStorageSuggestionProvider
import mozilla.components.feature.awesomebar.provider.CombinedHistorySuggestionProvider
import mozilla.components.feature.awesomebar.provider.HistoryStorageSuggestionProvider
import mozilla.components.feature.awesomebar.provider.SearchActionProvider
import mozilla.components.feature.awesomebar.provider.SearchEngineSuggestionProvider
import mozilla.components.feature.awesomebar.provider.SearchSuggestionProvider
import mozilla.components.feature.awesomebar.provider.SessionSuggestionProvider
import mozilla.components.feature.syncedtabs.SyncedTabsStorageSuggestionProvider
import mozilla.components.support.ktx.android.content.getColorFromAttr
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.Core.Companion
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.search.SearchEngineSource
import org.mozilla.fenix.search.awesomebar.AwesomeBarView.SearchProviderState
import org.mozilla.fenix.utils.Settings
@RunWith(FenixRobolectricTestRunner::class)
class AwesomeBarViewTest {
private val activity: HomeActivity = mockk(relaxed = true)
private lateinit var awesomeBarView: AwesomeBarView
@Before
fun setup() {
// The following setup is needed to complete the init block of AwesomeBarView
mockkStatic("org.mozilla.fenix.ext.ContextKt")
mockkStatic("mozilla.components.support.ktx.android.content.ContextKt")
mockkObject(AwesomeBarView.Companion)
every { any<Activity>().components.core.engine } returns mockk()
every { any<Activity>().components.core.icons } returns mockk()
every { any<Activity>().components.core.store } returns mockk()
every { any<Activity>().components.core.historyStorage } returns mockk()
every { any<Activity>().components.core.bookmarksStorage } returns mockk()
every { any<Activity>().components.core.client } returns mockk()
every { any<Activity>().components.backgroundServices.syncedTabsStorage } returns mockk()
every { any<Activity>().components.core.store.state.search } returns mockk(relaxed = true)
every { any<Activity>().getColorFromAttr(any()) } returns 0
every { AwesomeBarView.Companion.getDrawable(any(), any()) } returns mockk<VectorDrawable>(relaxed = true) {
every { intrinsicWidth } returns 10
every { intrinsicHeight } returns 10
}
awesomeBarView = AwesomeBarView(
activity = activity,
interactor = mockk(),
view = mockk(),
fromHomeFragment = false,
)
}
@After
fun tearDown() {
unmockkStatic("org.mozilla.fenix.ext.ContextKt")
unmockkStatic("mozilla.components.support.ktx.android.content.ContextKt")
unmockkObject(AwesomeBarView.Companion)
}
@Test
fun `GIVEN a search from history and history metadata enabled WHEN setting the providers THEN set more suggestions to be shown`() {
val settings: Settings = mockk(relaxed = true) {
every { historyMetadataUIFeature } returns true
}
every { activity.settings() } returns settings
val state = getSearchProviderState(
searchEngineSource = SearchEngineSource.History(mockk(relaxed = true)),
)
val result = awesomeBarView.getProvidersToAdd(state)
val historyProvider = result.firstOrNull { it is CombinedHistorySuggestionProvider }
assertNotNull(historyProvider)
assertEquals(
Companion.METADATA_HISTORY_SUGGESTION_LIMIT,
(historyProvider as CombinedHistorySuggestionProvider).getMaxNumberOfSuggestions(),
)
}
@Test
fun `GIVEN a search from history and history metadata disabled WHEN setting the providers THEN set more suggestions to be shown`() {
val settings: Settings = mockk(relaxed = true) {
every { historyMetadataUIFeature } returns true
}
every { activity.settings() } returns settings
val state = getSearchProviderState(
searchEngineSource = SearchEngineSource.History(mockk(relaxed = true)),
)
val result = awesomeBarView.getProvidersToAdd(state)
val historyProvider = result.firstOrNull { it is CombinedHistorySuggestionProvider }
assertNotNull(historyProvider)
assertEquals(
Companion.METADATA_HISTORY_SUGGESTION_LIMIT,
(historyProvider as CombinedHistorySuggestionProvider).getMaxNumberOfSuggestions(),
)
}
@Test
fun `GIVEN a search not from history and history metadata enabled WHEN setting the providers THEN set less suggestions to be shown`() {
val settings: Settings = mockk(relaxed = true) {
every { historyMetadataUIFeature } returns true
}
every { activity.settings() } returns settings
val state = getSearchProviderState(
searchEngineSource = SearchEngineSource.Shortcut(mockk(relaxed = true)),
)
val result = awesomeBarView.getProvidersToAdd(state)
val historyProvider = result.firstOrNull { it is CombinedHistorySuggestionProvider }
assertNotNull(historyProvider)
assertEquals(
AwesomeBarView.METADATA_SUGGESTION_LIMIT,
(historyProvider as CombinedHistorySuggestionProvider).getMaxNumberOfSuggestions(),
)
}
@Test
fun `GIVEN a search not from history and history metadata disabled WHEN setting the providers THEN set less suggestions to be shown`() {
val settings: Settings = mockk(relaxed = true) {
every { historyMetadataUIFeature } returns true
}
every { activity.settings() } returns settings
val state = getSearchProviderState(
searchEngineSource = SearchEngineSource.Bookmarks(mockk(relaxed = true)),
)
val result = awesomeBarView.getProvidersToAdd(state)
val historyProvider = result.firstOrNull { it is CombinedHistorySuggestionProvider }
assertNotNull(historyProvider)
assertEquals(
AwesomeBarView.METADATA_SUGGESTION_LIMIT,
(historyProvider as CombinedHistorySuggestionProvider).getMaxNumberOfSuggestions(),
)
}
@Test
fun `GIVEN a search that should show filtered history WHEN history metadata is enabled THEN return a history metadata provider with an engine filter`() {
val settings: Settings = mockk(relaxed = true) {
every { historyMetadataUIFeature } returns true
}
every { activity.settings() } returns settings
val state = getSearchProviderState(
showAllHistorySuggestions = false,
searchEngineSource = SearchEngineSource.Shortcut(
mockk(relaxed = true) {
every { resultsUrl.host } returns "test"
},
),
)
val result = awesomeBarView.getProvidersToAdd(state)
val historyProvider = result.firstOrNull { it is CombinedHistorySuggestionProvider }
assertNotNull(historyProvider)
assertEquals("test", (historyProvider as CombinedHistorySuggestionProvider).resultsHostFilter)
assertEquals(AwesomeBarView.METADATA_SUGGESTION_LIMIT, historyProvider.getMaxNumberOfSuggestions())
}
@Test
fun `GIVEN a search that should show filtered history WHEN history metadata is disabled THEN return a history provider with an engine filter`() {
val settings: Settings = mockk(relaxed = true) {
every { historyMetadataUIFeature } returns false
}
every { activity.settings() } returns settings
val state = getSearchProviderState(
showAllHistorySuggestions = false,
searchEngineSource = SearchEngineSource.Shortcut(
mockk(relaxed = true) {
every { resultsUrl.host } returns "test"
},
),
)
val result = awesomeBarView.getProvidersToAdd(state)
val historyProvider = result.firstOrNull { it is HistoryStorageSuggestionProvider }
assertNotNull(historyProvider)
assertEquals("test", (historyProvider as HistoryStorageSuggestionProvider).resultsHostFilter)
assertEquals(AwesomeBarView.METADATA_SUGGESTION_LIMIT, historyProvider.getMaxNumberOfSuggestions())
}
@Test
fun `GIVEN a search from the default engine WHEN configuring providers THEN add search action and search suggestions providers`() {
val settings: Settings = mockk(relaxed = true)
every { activity.settings() } returns settings
val state = getSearchProviderState(
showAllHistorySuggestions = false,
searchEngineSource = SearchEngineSource.Default(mockk(relaxed = true)),
)
val result = awesomeBarView.getProvidersToAdd(state)
assertEquals(1, result.filterIsInstance<SearchActionProvider>().size)
assertEquals(1, result.filterIsInstance<SearchSuggestionProvider>().size)
}
@Test
fun `GIVEN a search from a shortcut engine WHEN configuring providers THEN add search action and search suggestions providers`() {
val settings: Settings = mockk(relaxed = true)
every { activity.settings() } returns settings
val state = getSearchProviderState(
showAllHistorySuggestions = false,
searchEngineSource = SearchEngineSource.Default(mockk(relaxed = true)),
)
val result = awesomeBarView.getProvidersToAdd(state)
assertEquals(1, result.filterIsInstance<SearchActionProvider>().size)
assertEquals(1, result.filterIsInstance<SearchSuggestionProvider>().size)
}
@Test
fun `GIVEN searches from other than default and shortcut engines WHEN configuring providers THEN don't add search action and search suggestion providers`() {
val settings: Settings = mockk(relaxed = true)
every { activity.settings() } returns settings
val historyState = getSearchProviderState(
searchEngineSource = SearchEngineSource.History(mockk(relaxed = true)),
)
val bookmarksState = getSearchProviderState(
searchEngineSource = SearchEngineSource.Bookmarks(mockk(relaxed = true)),
)
val tabsState = getSearchProviderState(
searchEngineSource = SearchEngineSource.Tabs(mockk(relaxed = true)),
)
val noneState = getSearchProviderState()
val historyResult = awesomeBarView.getProvidersToAdd(historyState)
val bookmarksResult = awesomeBarView.getProvidersToAdd(bookmarksState)
val tabsResult = awesomeBarView.getProvidersToAdd(tabsState)
val noneResult = awesomeBarView.getProvidersToAdd(noneState)
val allResults = historyResult + bookmarksResult + tabsResult + noneResult
assertEquals(0, allResults.filterIsInstance<SearchActionProvider>().size)
assertEquals(0, allResults.filterIsInstance<SearchSuggestionProvider>().size)
}
@Test
fun `GIVEN normal browsing mode and needing to show tabs suggestions WHEN configuring providers THEN add the tabs provider`() {
val settings: Settings = mockk(relaxed = true)
every { activity.settings() } returns settings
every { activity.browsingModeManager.mode } returns BrowsingMode.Normal
val state = getSearchProviderState(
searchEngineSource = SearchEngineSource.Shortcut(mockk(relaxed = true)),
)
val result = awesomeBarView.getProvidersToAdd(state)
assertEquals(1, result.filterIsInstance<SessionSuggestionProvider>().size)
}
@Test
fun `GIVEN private browsing mode and needing to show tabs suggestions WHEN configuring providers THEN don't add the tabs provider`() {
val settings: Settings = mockk(relaxed = true)
every { activity.settings() } returns settings
every { activity.browsingModeManager.mode } returns BrowsingMode.Private
val state = getSearchProviderState(
searchEngineSource = SearchEngineSource.Shortcut(mockk(relaxed = true)),
)
val result = awesomeBarView.getProvidersToAdd(state)
assertEquals(0, result.filterIsInstance<SessionSuggestionProvider>().size)
}
@Test
fun `GIVEN unified search feature is enabled WHEN configuring providers THEN don't add the engine suggestions provider`() {
val settings: Settings = mockk(relaxed = true) {
every { showUnifiedSearchFeature } returns true
}
every { activity.settings() } returns settings
val state = getSearchProviderState(
searchEngineSource = SearchEngineSource.Default(mockk(relaxed = true)),
)
val result = awesomeBarView.getProvidersToAdd(state)
assertEquals(0, result.filterIsInstance<SearchEngineSuggestionProvider>().size)
}
@Test
fun `GIVEN unified search feature is disabled WHEN configuring providers THEN add the engine suggestions provider`() {
val settings: Settings = mockk(relaxed = true) {
every { showUnifiedSearchFeature } returns false
}
every { activity.settings() } returns settings
val state = getSearchProviderState(
searchEngineSource = SearchEngineSource.Default(mockk(relaxed = true)),
)
val result = awesomeBarView.getProvidersToAdd(state)
assertEquals(1, result.filterIsInstance<SearchEngineSuggestionProvider>().size)
}
@Test
fun `GIVEN a search from the default engine with all suggestions asked WHEN configuring providers THEN add them all`() {
val settings: Settings = mockk(relaxed = true) {
every { showUnifiedSearchFeature } returns false
}
every { activity.settings() } returns settings
every { activity.browsingModeManager.mode } returns BrowsingMode.Normal
val state = getSearchProviderState(
searchEngineSource = SearchEngineSource.Default(mockk(relaxed = true)),
)
val result = awesomeBarView.getProvidersToAdd(state)
val historyProviders: List<HistoryStorageSuggestionProvider> = result.filterIsInstance<HistoryStorageSuggestionProvider>()
assertEquals(2, historyProviders.size)
assertNull(historyProviders[0].resultsHostFilter) // the general history provider
assertNotNull(historyProviders[1].resultsHostFilter) // the filtered history provider
assertEquals(1, result.filterIsInstance<BookmarksStorageSuggestionProvider>().size)
assertEquals(1, result.filterIsInstance<SearchActionProvider>().size)
assertEquals(1, result.filterIsInstance<SearchSuggestionProvider>().size)
assertEquals(1, result.filterIsInstance<SyncedTabsStorageSuggestionProvider>().size)
assertEquals(1, result.filterIsInstance<SessionSuggestionProvider>().size)
assertEquals(1, result.filterIsInstance<SearchEngineSuggestionProvider>().size)
}
@Test
fun `GIVEN a search from the default engine with no suggestions asked WHEN configuring providers THEN don't add any provider`() {
val settings: Settings = mockk(relaxed = true) {
every { showUnifiedSearchFeature } returns true
}
every { activity.settings() } returns settings
every { activity.browsingModeManager.mode } returns BrowsingMode.Normal
val state = getSearchProviderState(
showHistorySuggestionsForCurrentEngine = false,
showSearchShortcuts = false,
showAllHistorySuggestions = false,
showBookmarkSuggestions = false,
showSearchSuggestions = false,
showSyncedTabsSuggestions = false,
showSessionSuggestions = false,
searchEngineSource = SearchEngineSource.Default(mockk(relaxed = true)),
)
val result = awesomeBarView.getProvidersToAdd(state)
assertEquals(0, result.filterIsInstance<HistoryStorageSuggestionProvider>().size)
assertEquals(0, result.filterIsInstance<BookmarksStorageSuggestionProvider>().size)
assertEquals(0, result.filterIsInstance<SearchActionProvider>().size)
assertEquals(0, result.filterIsInstance<SearchSuggestionProvider>().size)
assertEquals(0, result.filterIsInstance<SyncedTabsStorageSuggestionProvider>().size)
assertEquals(0, result.filterIsInstance<SessionSuggestionProvider>().size)
assertEquals(0, result.filterIsInstance<SearchEngineSuggestionProvider>().size)
}
@Test
fun `GIVEN the current search engine's url is not known WHEN creating a history provider for that engine THEN return null`() {
val engineSource = SearchEngineSource.None
val result = awesomeBarView.getHistoryProvidersForSearchEngine(engineSource)
assertNull(result)
}
@Test
fun `GIVEN a valid search engine and history metadata enabled WHEN creating a history provider for that engine THEN return a history metadata provider with engine filter`() {
val settings: Settings = mockk {
every { historyMetadataUIFeature } returns true
}
every { activity.settings() } returns settings
val searchEngineSource = SearchEngineSource.Shortcut(mockk(relaxed = true))
val result = awesomeBarView.getHistoryProvidersForSearchEngine(searchEngineSource)
assertNotNull(result)
assertTrue(result is CombinedHistorySuggestionProvider)
assertNotNull((result as CombinedHistorySuggestionProvider).resultsHostFilter)
assertEquals(AwesomeBarView.METADATA_SUGGESTION_LIMIT, result.getMaxNumberOfSuggestions())
}
@Test
fun `GIVEN a valid search engine and history metadata disabled WHEN creating a history provider for that engine THEN return a history metadata provider with engine filter`() {
val settings: Settings = mockk {
every { historyMetadataUIFeature } returns false
}
every { activity.settings() } returns settings
val searchEngineSource = SearchEngineSource.Shortcut(mockk(relaxed = true))
val result = awesomeBarView.getHistoryProvidersForSearchEngine(searchEngineSource)
assertNotNull(result)
assertTrue(result is HistoryStorageSuggestionProvider)
assertNotNull((result as HistoryStorageSuggestionProvider).resultsHostFilter)
assertEquals(AwesomeBarView.METADATA_SUGGESTION_LIMIT, result.getMaxNumberOfSuggestions())
}
}
/**
* Get a default [SearchProviderState] that by default will ask for all types of suggestions.
*/
private fun getSearchProviderState(
showSearchShortcuts: Boolean = true,
showHistorySuggestionsForCurrentEngine: Boolean = true,
showAllHistorySuggestions: Boolean = true,
showBookmarkSuggestions: Boolean = true,
showSearchSuggestions: Boolean = true,
showSyncedTabsSuggestions: Boolean = true,
showSessionSuggestions: Boolean = true,
searchEngineSource: SearchEngineSource = SearchEngineSource.None,
) = SearchProviderState(
showSearchShortcuts = showSearchShortcuts,
showHistorySuggestionsForCurrentEngine = showHistorySuggestionsForCurrentEngine,
showAllHistorySuggestions = showAllHistorySuggestions,
showBookmarkSuggestions = showBookmarkSuggestions,
showSearchSuggestions = showSearchSuggestions,
showSyncedTabsSuggestions = showSyncedTabsSuggestions,
showSessionSuggestions = showSessionSuggestions,
searchEngineSource = searchEngineSource,
)

@ -259,7 +259,8 @@ private val testSearchFragmentState = SearchFragmentState(
showSearchShortcuts = false,
areShortcutsAvailable = false,
showClipboardSuggestions = false,
showHistorySuggestions = false,
showHistorySuggestionsForCurrentEngine = true,
showAllHistorySuggestions = false,
showBookmarkSuggestions = false,
showSyncedTabsSuggestions = false,
showSessionSuggestions = true,

@ -63,7 +63,8 @@ class ToolbarViewTest {
showSearchShortcuts = false,
areShortcutsAvailable = true,
showClipboardSuggestions = false,
showHistorySuggestions = false,
showHistorySuggestionsForCurrentEngine = true,
showAllHistorySuggestions = false,
showBookmarkSuggestions = false,
showSyncedTabsSuggestions = false,
showSessionSuggestions = false,

Loading…
Cancel
Save