Loading app/src/main/java/org/mozilla/fenix/components/searchengine/FenixSearchEngineProvider.kt +12 −7 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ package org.mozilla.fenix.components.searchengine import android.content.Context import androidx.annotation.VisibleForTesting import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job Loading @@ -21,16 +22,15 @@ import org.mozilla.fenix.ext.settings import java.util.Locale @SuppressWarnings("TooManyFunctions") class FenixSearchEngineProvider( open class FenixSearchEngineProvider( private val context: Context ) : SearchEngineProvider, CoroutineScope by CoroutineScope(Job() + Dispatchers.IO) { private val baseSearchEngines = async { open val baseSearchEngines = async { AssetsSearchEngineProvider(LocaleSearchLocalizationProvider()).loadSearchEngines(context) } private val bundledSearchEngines = async { open val bundledSearchEngines = async { val defaultEngineIdentifiers = baseSearchEngines.await().list.map { it.identifier }.toSet() AssetsSearchEngineProvider( LocaleSearchLocalizationProvider(), filters = listOf(object : SearchEngineFilter { Loading @@ -43,7 +43,7 @@ class FenixSearchEngineProvider( ).loadSearchEngines(context) } private var customSearchEngines = async { open var customSearchEngines = async { CustomSearchEngineProvider().loadSearchEngines(context) } Loading @@ -56,6 +56,10 @@ class FenixSearchEngineProvider( return engines.list.find { it.name == selectedName } ?: engines.default ?: engines.list.first() } /** * @return a list of all SearchEngines that are currently active. These are the engines that * are readily available throughout the app. */ fun installedSearchEngines(context: Context): SearchEngineList = runBlocking { val engineList = loadedSearchEngines.await() val installedIdentifiers = installedSearchEngineIdentifiers(context) Loading Loading @@ -141,16 +145,17 @@ class FenixSearchEngineProvider( prefs.edit().putStringSet(INSTALLED_ENGINES_KEY, defaultSet).apply() defaultSet } else { prefs(context).getStringSet(INSTALLED_ENGINES_KEY, setOf()) ?: setOf() prefs.getStringSet(INSTALLED_ENGINES_KEY, setOf()) ?: setOf() } val customEngineIdentifiers = customSearchEngines.await().list.map { it.identifier }.toSet() return identifiers + customEngineIdentifiers } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) companion object { private val BUNDLED_SEARCH_ENGINES = listOf("ecosia", "reddit", "startpage", "yahoo", "youtube") private const val PREF_FILE = "fenix-search-engine-provider" const val PREF_FILE = "fenix-search-engine-provider" private const val INSTALLED_ENGINES_KEY = "fenix-installed-search-engines" } } app/src/test/java/org/mozilla/fenix/components/searchengine/FenixSearchEngineProviderTest.kt 0 → 100644 +109 −0 Original line number Diff line number Diff line package org.mozilla.fenix.components.searchengine import android.content.Context import android.graphics.Bitmap import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Deferred 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.Before import org.junit.Test import org.mockito.Mockito import org.mockito.Mockito.`when` import org.mockito.Mockito.mock import java.util.UUID @ExperimentalCoroutinesApi class FenixSearchEngineProviderTest { private val testContext = mockk<Context>() private lateinit var fenixSearchEngineProvider: FenixSearchEngineProvider @Before fun before() { fenixSearchEngineProvider = FakeFenixSearchEngineProvider(testContext) every { testContext.getSharedPreferences(FenixSearchEngineProvider.PREF_FILE, Context.MODE_PRIVATE) } returns mockk(relaxed = true) } /* TODO TEST: - public API happy path - list ordering - deduping - the above after adding/removing */ @Test fun `temp test class inits`() = runBlockingTest { val t = fenixSearchEngineProvider.loadSearchEngines(testContext) println(t) } } class FakeFenixSearchEngineProvider(context: Context) : FenixSearchEngineProvider(context) { override val defaultEngines: Deferred<SearchEngineList> get() { val google = mockSearchEngine(id = "google-b-1-m", n = "Google") return CompletableDeferred( SearchEngineList( listOf( google, mockSearchEngine("bing", "Bing"), mockSearchEngine("amazondotcom", "Amazon.com") ), default = google ) ) } override val bundledEngines = CompletableDeferred( SearchEngineList( listOf( mockSearchEngine("ecosia", "Ecosia"), mockSearchEngine("reddit", "Reddit"), mockSearchEngine("startpage", "Startpage.com") ), default = null ) ) override var customEngines: Deferred<SearchEngineList> get() { return CompletableDeferred( SearchEngineList( listOf( mockSearchEngine("my custom site", "my custom site") ), default = null ) ) } set(_) = throw RuntimeException("Setting not currently supported on this fake") private fun mockSearchEngine( id: String, n: String = id // TODO this fails with `Missing calls inside every { ... } block`. Not sure why // ) = mockk<SearchEngine> { // every { identifier } returns id // every { name } returns n // every { icon } returns mockk() // } ): SearchEngine { return mock(SearchEngine::class.java).apply { `when`(identifier).thenReturn(id) `when`(name).thenReturn(n) `when`(icon).thenReturn(mock(Bitmap::class.java)) } } } Loading
app/src/main/java/org/mozilla/fenix/components/searchengine/FenixSearchEngineProvider.kt +12 −7 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ package org.mozilla.fenix.components.searchengine import android.content.Context import androidx.annotation.VisibleForTesting import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job Loading @@ -21,16 +22,15 @@ import org.mozilla.fenix.ext.settings import java.util.Locale @SuppressWarnings("TooManyFunctions") class FenixSearchEngineProvider( open class FenixSearchEngineProvider( private val context: Context ) : SearchEngineProvider, CoroutineScope by CoroutineScope(Job() + Dispatchers.IO) { private val baseSearchEngines = async { open val baseSearchEngines = async { AssetsSearchEngineProvider(LocaleSearchLocalizationProvider()).loadSearchEngines(context) } private val bundledSearchEngines = async { open val bundledSearchEngines = async { val defaultEngineIdentifiers = baseSearchEngines.await().list.map { it.identifier }.toSet() AssetsSearchEngineProvider( LocaleSearchLocalizationProvider(), filters = listOf(object : SearchEngineFilter { Loading @@ -43,7 +43,7 @@ class FenixSearchEngineProvider( ).loadSearchEngines(context) } private var customSearchEngines = async { open var customSearchEngines = async { CustomSearchEngineProvider().loadSearchEngines(context) } Loading @@ -56,6 +56,10 @@ class FenixSearchEngineProvider( return engines.list.find { it.name == selectedName } ?: engines.default ?: engines.list.first() } /** * @return a list of all SearchEngines that are currently active. These are the engines that * are readily available throughout the app. */ fun installedSearchEngines(context: Context): SearchEngineList = runBlocking { val engineList = loadedSearchEngines.await() val installedIdentifiers = installedSearchEngineIdentifiers(context) Loading Loading @@ -141,16 +145,17 @@ class FenixSearchEngineProvider( prefs.edit().putStringSet(INSTALLED_ENGINES_KEY, defaultSet).apply() defaultSet } else { prefs(context).getStringSet(INSTALLED_ENGINES_KEY, setOf()) ?: setOf() prefs.getStringSet(INSTALLED_ENGINES_KEY, setOf()) ?: setOf() } val customEngineIdentifiers = customSearchEngines.await().list.map { it.identifier }.toSet() return identifiers + customEngineIdentifiers } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) companion object { private val BUNDLED_SEARCH_ENGINES = listOf("ecosia", "reddit", "startpage", "yahoo", "youtube") private const val PREF_FILE = "fenix-search-engine-provider" const val PREF_FILE = "fenix-search-engine-provider" private const val INSTALLED_ENGINES_KEY = "fenix-installed-search-engines" } }
app/src/test/java/org/mozilla/fenix/components/searchengine/FenixSearchEngineProviderTest.kt 0 → 100644 +109 −0 Original line number Diff line number Diff line package org.mozilla.fenix.components.searchengine import android.content.Context import android.graphics.Bitmap import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Deferred 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.Before import org.junit.Test import org.mockito.Mockito import org.mockito.Mockito.`when` import org.mockito.Mockito.mock import java.util.UUID @ExperimentalCoroutinesApi class FenixSearchEngineProviderTest { private val testContext = mockk<Context>() private lateinit var fenixSearchEngineProvider: FenixSearchEngineProvider @Before fun before() { fenixSearchEngineProvider = FakeFenixSearchEngineProvider(testContext) every { testContext.getSharedPreferences(FenixSearchEngineProvider.PREF_FILE, Context.MODE_PRIVATE) } returns mockk(relaxed = true) } /* TODO TEST: - public API happy path - list ordering - deduping - the above after adding/removing */ @Test fun `temp test class inits`() = runBlockingTest { val t = fenixSearchEngineProvider.loadSearchEngines(testContext) println(t) } } class FakeFenixSearchEngineProvider(context: Context) : FenixSearchEngineProvider(context) { override val defaultEngines: Deferred<SearchEngineList> get() { val google = mockSearchEngine(id = "google-b-1-m", n = "Google") return CompletableDeferred( SearchEngineList( listOf( google, mockSearchEngine("bing", "Bing"), mockSearchEngine("amazondotcom", "Amazon.com") ), default = google ) ) } override val bundledEngines = CompletableDeferred( SearchEngineList( listOf( mockSearchEngine("ecosia", "Ecosia"), mockSearchEngine("reddit", "Reddit"), mockSearchEngine("startpage", "Startpage.com") ), default = null ) ) override var customEngines: Deferred<SearchEngineList> get() { return CompletableDeferred( SearchEngineList( listOf( mockSearchEngine("my custom site", "my custom site") ), default = null ) ) } set(_) = throw RuntimeException("Setting not currently supported on this fake") private fun mockSearchEngine( id: String, n: String = id // TODO this fails with `Missing calls inside every { ... } block`. Not sure why // ) = mockk<SearchEngine> { // every { identifier } returns id // every { name } returns n // every { icon } returns mockk() // } ): SearchEngine { return mock(SearchEngine::class.java).apply { `when`(identifier).thenReturn(id) `when`(name).thenReturn(n) `when`(icon).thenReturn(mock(Bitmap::class.java)) } } }