1
0
Fork 0

Add tests for search (#12437)

master
Tiger Oakes 2020-07-14 10:32:04 -07:00 committed by GitHub
parent e9fb1a61c7
commit 1ff64cab67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 257 additions and 21 deletions

View File

@ -96,9 +96,7 @@ private fun searchStateReducer(state: SearchFragmentState, action: SearchFragmen
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)
)
is SearchFragmentAction.AllowSearchSuggestionsInPrivateModePrompt -> is SearchFragmentAction.AllowSearchSuggestionsInPrivateModePrompt ->
state.copy(showSearchSuggestionsHint = action.show) state.copy(showSearchSuggestionsHint = action.show)
is SearchFragmentAction.SetShowSearchSuggestions -> is SearchFragmentAction.SetShowSearchSuggestions ->

View File

@ -34,16 +34,15 @@ class ShortcutsSuggestionProvider(
override suspend fun onInputChanged(text: String): List<AwesomeBar.Suggestion> { override suspend fun onInputChanged(text: String): List<AwesomeBar.Suggestion> {
val suggestions = mutableListOf<AwesomeBar.Suggestion>() val suggestions = mutableListOf<AwesomeBar.Suggestion>()
searchEngineProvider.installedSearchEngines(context).list.forEach { searchEngineProvider.installedSearchEngines(context).list.mapTo(suggestions) {
suggestions.add( AwesomeBar.Suggestion(
AwesomeBar.Suggestion( provider = this,
provider = this, id = it.identifier,
id = it.identifier, icon = it.icon,
icon = it.icon, title = it.name,
title = it.name, onSuggestionClicked = {
onSuggestionClicked = { selectShortcutEngine(it)
selectShortcutEngine(it) }
})
) )
} }
@ -55,7 +54,8 @@ class ShortcutsSuggestionProvider(
title = context.getString(R.string.search_shortcuts_engine_settings), title = context.getString(R.string.search_shortcuts_engine_settings),
onSuggestionClicked = { onSuggestionClicked = {
selectShortcutEngineSettings() selectShortcutEngineSettings()
}) }
)
) )
return suggestions return suggestions
} }

View File

@ -22,24 +22,24 @@ import org.mozilla.fenix.theme.ThemeManager
/** /**
* Interface for the Toolbar Interactor. This interface is implemented by objects that want * 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 { interface ToolbarInteractor {
/** /**
* Called when a user hits the return key while [BrowserToolbarView] has focus. * Called when a user hits the return key while [ToolbarView] has focus.
* @param url the text inside the [BrowserToolbarView] when committed * @param url the text inside the [ToolbarView] when committed
*/ */
fun onUrlCommitted(url: String) fun onUrlCommitted(url: String)
/** /**
* Called when a user removes focus from the [BrowserToolbarView] * Called when a user removes focus from the [ToolbarView]
*/ */
fun onEditingCanceled() fun onEditingCanceled()
/** /**
* Called whenever the text inside the [BrowserToolbarView] changes * Called whenever the text inside the [ToolbarView] changes
* @param text the current text displayed by [BrowserToolbarView] * @param text the current text displayed by [ToolbarView]
*/ */
fun onTextChanged(text: String) fun onTextChanged(text: String)
} }
@ -103,7 +103,7 @@ class ToolbarView(
override fun onTextChanged(text: String) { override fun onTextChanged(text: String) {
url = text url = text
this@ToolbarView.interactor.onTextChanged(text) interactor.onTextChanged(text)
} }
}) })
} }

View File

@ -5,13 +5,17 @@
package org.mozilla.fenix.search package org.mozilla.fenix.search
import io.mockk.mockk import io.mockk.mockk
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import mozilla.components.browser.search.SearchEngine import mozilla.components.browser.search.SearchEngine
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotSame import org.junit.Assert.assertNotSame
import org.junit.Assert.assertTrue
import org.junit.Test import org.junit.Test
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
@ExperimentalCoroutinesApi
class SearchFragmentStoreTest { class SearchFragmentStoreTest {
@Test @Test
@ -57,6 +61,43 @@ class SearchFragmentStoreTest {
assertEquals(false, store.state.showSearchShortcuts) 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( private fun emptyDefaultState(): SearchFragmentState = SearchFragmentState(
tabId = null, tabId = null,
url = "", url = "",

View File

@ -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()
}
}
}

View File

@ -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
)
}