Add tests for search (#12437)
parent
e9fb1a61c7
commit
1ff64cab67
|
@ -96,9 +96,7 @@ private fun searchStateReducer(state: SearchFragmentState, action: SearchFragmen
|
|||
is SearchFragmentAction.UpdateQuery ->
|
||||
state.copy(query = action.query)
|
||||
is SearchFragmentAction.SelectNewDefaultSearchEngine ->
|
||||
state.copy(
|
||||
searchEngineSource = SearchEngineSource.Default(action.engine)
|
||||
)
|
||||
state.copy(searchEngineSource = SearchEngineSource.Default(action.engine))
|
||||
is SearchFragmentAction.AllowSearchSuggestionsInPrivateModePrompt ->
|
||||
state.copy(showSearchSuggestionsHint = action.show)
|
||||
is SearchFragmentAction.SetShowSearchSuggestions ->
|
||||
|
|
|
@ -34,16 +34,15 @@ class ShortcutsSuggestionProvider(
|
|||
override suspend fun onInputChanged(text: String): List<AwesomeBar.Suggestion> {
|
||||
val suggestions = mutableListOf<AwesomeBar.Suggestion>()
|
||||
|
||||
searchEngineProvider.installedSearchEngines(context).list.forEach {
|
||||
suggestions.add(
|
||||
AwesomeBar.Suggestion(
|
||||
provider = this,
|
||||
id = it.identifier,
|
||||
icon = it.icon,
|
||||
title = it.name,
|
||||
onSuggestionClicked = {
|
||||
selectShortcutEngine(it)
|
||||
})
|
||||
searchEngineProvider.installedSearchEngines(context).list.mapTo(suggestions) {
|
||||
AwesomeBar.Suggestion(
|
||||
provider = this,
|
||||
id = it.identifier,
|
||||
icon = it.icon,
|
||||
title = it.name,
|
||||
onSuggestionClicked = {
|
||||
selectShortcutEngine(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -55,7 +54,8 @@ class ShortcutsSuggestionProvider(
|
|||
title = context.getString(R.string.search_shortcuts_engine_settings),
|
||||
onSuggestionClicked = {
|
||||
selectShortcutEngineSettings()
|
||||
})
|
||||
}
|
||||
)
|
||||
)
|
||||
return suggestions
|
||||
}
|
||||
|
|
|
@ -22,24 +22,24 @@ import org.mozilla.fenix.theme.ThemeManager
|
|||
|
||||
/**
|
||||
* Interface for the Toolbar Interactor. This interface is implemented by objects that want
|
||||
* to respond to user interaction on the [BrowserToolbarView]
|
||||
* to respond to user interaction on the [ToolbarView]
|
||||
*/
|
||||
interface ToolbarInteractor {
|
||||
|
||||
/**
|
||||
* Called when a user hits the return key while [BrowserToolbarView] has focus.
|
||||
* @param url the text inside the [BrowserToolbarView] when committed
|
||||
* Called when a user hits the return key while [ToolbarView] has focus.
|
||||
* @param url the text inside the [ToolbarView] when committed
|
||||
*/
|
||||
fun onUrlCommitted(url: String)
|
||||
|
||||
/**
|
||||
* Called when a user removes focus from the [BrowserToolbarView]
|
||||
* Called when a user removes focus from the [ToolbarView]
|
||||
*/
|
||||
fun onEditingCanceled()
|
||||
|
||||
/**
|
||||
* Called whenever the text inside the [BrowserToolbarView] changes
|
||||
* @param text the current text displayed by [BrowserToolbarView]
|
||||
* Called whenever the text inside the [ToolbarView] changes
|
||||
* @param text the current text displayed by [ToolbarView]
|
||||
*/
|
||||
fun onTextChanged(text: String)
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ class ToolbarView(
|
|||
|
||||
override fun onTextChanged(text: String) {
|
||||
url = text
|
||||
this@ToolbarView.interactor.onTextChanged(text)
|
||||
interactor.onTextChanged(text)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -5,13 +5,17 @@
|
|||
package org.mozilla.fenix.search
|
||||
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import mozilla.components.browser.search.SearchEngine
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNotSame
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
class SearchFragmentStoreTest {
|
||||
|
||||
@Test
|
||||
|
@ -57,6 +61,43 @@ class SearchFragmentStoreTest {
|
|||
assertEquals(false, store.state.showSearchShortcuts)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun showSearchSuggestions() = runBlocking {
|
||||
val initialState = emptyDefaultState()
|
||||
val store = SearchFragmentStore(initialState)
|
||||
|
||||
store.dispatch(SearchFragmentAction.SetShowSearchSuggestions(true)).join()
|
||||
assertNotSame(initialState, store.state)
|
||||
assertTrue(store.state.showSearchSuggestions)
|
||||
|
||||
store.dispatch(SearchFragmentAction.SetShowSearchSuggestions(false)).join()
|
||||
assertFalse(store.state.showSearchSuggestions)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun allowSearchInPrivateMode() = runBlocking {
|
||||
val initialState = emptyDefaultState()
|
||||
val store = SearchFragmentStore(initialState)
|
||||
|
||||
store.dispatch(SearchFragmentAction.AllowSearchSuggestionsInPrivateModePrompt(true)).join()
|
||||
assertNotSame(initialState, store.state)
|
||||
assertTrue(store.state.showSearchSuggestionsHint)
|
||||
|
||||
store.dispatch(SearchFragmentAction.AllowSearchSuggestionsInPrivateModePrompt(false)).join()
|
||||
assertFalse(store.state.showSearchSuggestionsHint)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun selectNewDefaultEngine() = runBlocking {
|
||||
val initialState = emptyDefaultState()
|
||||
val store = SearchFragmentStore(initialState)
|
||||
val engine = mockk<SearchEngine>()
|
||||
|
||||
store.dispatch(SearchFragmentAction.SelectNewDefaultSearchEngine(engine)).join()
|
||||
assertNotSame(initialState, store.state)
|
||||
assertEquals(SearchEngineSource.Default(engine), store.state.searchEngineSource)
|
||||
}
|
||||
|
||||
private fun emptyDefaultState(): SearchFragmentState = SearchFragmentState(
|
||||
tabId = null,
|
||||
url = "",
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/* 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.content.Context
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.unmockkStatic
|
||||
import io.mockk.verifySequence
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import mozilla.components.browser.search.SearchEngine
|
||||
import mozilla.components.browser.search.provider.SearchEngineList
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.searchengine.FenixSearchEngineProvider
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
class ShortcutsSuggestionProviderTest {
|
||||
|
||||
private lateinit var context: Context
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockkStatic(AppCompatResources::class)
|
||||
context = mockk {
|
||||
every { getString(R.string.search_shortcuts_engine_settings) } returns "Search engine settings"
|
||||
}
|
||||
|
||||
every { AppCompatResources.getDrawable(context, R.drawable.ic_settings) } returns null
|
||||
}
|
||||
|
||||
@After
|
||||
fun teardown() {
|
||||
unmockkStatic(AppCompatResources::class)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should clear is always false`() {
|
||||
val provider = ShortcutsSuggestionProvider(mockk(), mockk(), mockk(), mockk())
|
||||
assertFalse(provider.shouldClearSuggestions)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns suggestions from search engine provider`() = runBlockingTest {
|
||||
val engineOne = mockk<SearchEngine> {
|
||||
every { identifier } returns "1"
|
||||
every { name } returns "EngineOne"
|
||||
every { icon } returns mockk()
|
||||
}
|
||||
val engineTwo = mockk<SearchEngine> {
|
||||
every { identifier } returns "2"
|
||||
every { name } returns "EngineTwo"
|
||||
every { icon } returns mockk()
|
||||
}
|
||||
val searchEngineProvider = mockk<FenixSearchEngineProvider> {
|
||||
every { installedSearchEngines(context) } returns SearchEngineList(
|
||||
list = listOf(engineOne, engineTwo),
|
||||
default = null
|
||||
)
|
||||
}
|
||||
val provider = ShortcutsSuggestionProvider(searchEngineProvider, context, mockk(), mockk())
|
||||
|
||||
val suggestions = provider.onInputChanged("")
|
||||
assertEquals(3, suggestions.size)
|
||||
|
||||
assertEquals(provider, suggestions[0].provider)
|
||||
assertEquals(engineOne.identifier, suggestions[0].id)
|
||||
assertEquals(engineOne.icon, suggestions[0].icon)
|
||||
assertEquals(engineOne.name, suggestions[0].title)
|
||||
|
||||
assertEquals(provider, suggestions[1].provider)
|
||||
assertEquals(engineTwo.identifier, suggestions[1].id)
|
||||
assertEquals(engineTwo.icon, suggestions[1].icon)
|
||||
assertEquals(engineTwo.name, suggestions[1].title)
|
||||
|
||||
assertEquals(provider, suggestions[2].provider)
|
||||
assertEquals("Search engine settings", suggestions[2].id)
|
||||
assertEquals("Search engine settings", suggestions[2].title)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `callbacks are triggered when suggestions are clicked`() = runBlockingTest {
|
||||
val engineOne = mockk<SearchEngine>(relaxed = true)
|
||||
val searchEngineProvider = mockk<FenixSearchEngineProvider> {
|
||||
every { installedSearchEngines(context) } returns SearchEngineList(
|
||||
list = listOf(engineOne),
|
||||
default = null
|
||||
)
|
||||
}
|
||||
val selectShortcutEngine = mockk<(SearchEngine) -> Unit>(relaxed = true)
|
||||
val selectShortcutEngineSettings = mockk<() -> Unit>(relaxed = true)
|
||||
val provider = ShortcutsSuggestionProvider(
|
||||
searchEngineProvider,
|
||||
context,
|
||||
selectShortcutEngine,
|
||||
selectShortcutEngineSettings
|
||||
)
|
||||
|
||||
val suggestions = provider.onInputChanged("")
|
||||
assertEquals(2, suggestions.size)
|
||||
|
||||
suggestions[0].onSuggestionClicked?.invoke()
|
||||
suggestions[1].onSuggestionClicked?.invoke()
|
||||
|
||||
verifySequence {
|
||||
selectShortcutEngine(engineOne)
|
||||
selectShortcutEngineSettings()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/* 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.toolbar
|
||||
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.just
|
||||
import io.mockk.slot
|
||||
import io.mockk.spyk
|
||||
import io.mockk.verify
|
||||
import mozilla.components.browser.toolbar.BrowserToolbar
|
||||
import mozilla.components.concept.engine.Engine
|
||||
import mozilla.components.concept.toolbar.Toolbar
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class ToolbarViewTest {
|
||||
|
||||
@MockK(relaxed = true) private lateinit var interactor: ToolbarInteractor
|
||||
@MockK private lateinit var engine: Engine
|
||||
private lateinit var toolbar: BrowserToolbar
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockKAnnotations.init(this)
|
||||
toolbar = spyk(BrowserToolbar(testContext))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `sets up interactor listeners`() {
|
||||
val urlCommitListener = slot<(String) -> Boolean>()
|
||||
val editListener = slot<Toolbar.OnEditListener>()
|
||||
every { toolbar.setOnUrlCommitListener(capture(urlCommitListener)) } just Runs
|
||||
every { toolbar.setOnEditListener(capture(editListener)) } just Runs
|
||||
|
||||
buildToolbarView(isPrivate = false)
|
||||
|
||||
assertFalse(urlCommitListener.captured("test"))
|
||||
verify { interactor.onUrlCommitted("test") }
|
||||
|
||||
assertFalse(editListener.captured.onCancelEditing())
|
||||
verify { interactor.onEditingCanceled() }
|
||||
|
||||
editListener.captured.onTextChanged("https://example.com")
|
||||
verify { interactor.onTextChanged("https://example.com") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `sets toolbar to normal mode`() {
|
||||
buildToolbarView(isPrivate = false)
|
||||
assertFalse(toolbar.private)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `sets toolbar to private mode`() {
|
||||
buildToolbarView(isPrivate = true)
|
||||
assertTrue(toolbar.private)
|
||||
}
|
||||
|
||||
private fun buildToolbarView(isPrivate: Boolean) = ToolbarView(
|
||||
testContext,
|
||||
interactor,
|
||||
historyStorage = null,
|
||||
isPrivate = isPrivate,
|
||||
view = toolbar,
|
||||
engine = engine
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue