For #6556: Adds Telemetry counts for Search Access Points
Added two new sources to be counted ('widget' and 'shortcut') besides 'action' and 'suggestion'. Also modified/fixed some tests.master
parent
9c25d274d0
commit
981d19de13
|
@ -325,15 +325,18 @@ metrics:
|
||||||
If the search engine is bundled with Fenix `search-engine-name` will be the name of the search engine. If it's a
|
If the search engine is bundled with Fenix `search-engine-name` will be the name of the search engine. If it's a
|
||||||
custom search engine (defined: https://github.com/mozilla-mobile/fenix/issues/1607) the value will be `custom`.
|
custom search engine (defined: https://github.com/mozilla-mobile/fenix/issues/1607) the value will be `custom`.
|
||||||
|
|
||||||
`source` will either be `action` or `suggestion`
|
`source` will be: `action`, `suggestion`, `widget` or `shortcut` (depending on the source from which the search started).
|
||||||
|
Also added the `other` option for the source but it should never enter on this case.
|
||||||
send_in_pings:
|
send_in_pings:
|
||||||
- metrics
|
- metrics
|
||||||
- baseline
|
- baseline
|
||||||
bugs:
|
bugs:
|
||||||
- https://github.com/mozilla-mobile/fenix/issues/1158
|
- https://github.com/mozilla-mobile/fenix/issues/1158
|
||||||
|
- https://github.com/mozilla-mobile/fenix/issues/6556
|
||||||
data_reviews:
|
data_reviews:
|
||||||
- https://github.com/mozilla-mobile/fenix/pull/1677
|
- https://github.com/mozilla-mobile/fenix/pull/1677
|
||||||
- https://github.com/mozilla-mobile/fenix/pull/5216
|
- https://github.com/mozilla-mobile/fenix/pull/5216
|
||||||
|
- https://github.com/mozilla-mobile/fenix/pull/7310
|
||||||
notification_emails:
|
notification_emails:
|
||||||
- fenix-core@mozilla.com
|
- fenix-core@mozilla.com
|
||||||
expires: "2020-03-01"
|
expires: "2020-03-01"
|
||||||
|
|
|
@ -78,7 +78,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
|
||||||
|
|
||||||
private val externalSourceIntentProcessors by lazy {
|
private val externalSourceIntentProcessors by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
SpeechProcessingIntentProcessor(this),
|
SpeechProcessingIntentProcessor(this, components.analytics.metrics),
|
||||||
StartSearchIntentProcessor(components.analytics.metrics),
|
StartSearchIntentProcessor(components.analytics.metrics),
|
||||||
DeepLinkIntentProcessor(this),
|
DeepLinkIntentProcessor(this),
|
||||||
OpenBrowserIntentProcessor(this, ::getIntentSessionId)
|
OpenBrowserIntentProcessor(this, ::getIntentSessionId)
|
||||||
|
|
|
@ -271,27 +271,31 @@ sealed class Event {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class EventSource {
|
sealed class EventSource(open val engineSource: EngineSource) {
|
||||||
data class Suggestion(val engineSource: EngineSource) : EventSource()
|
data class Suggestion(override val engineSource: EngineSource) : EventSource(engineSource)
|
||||||
data class Action(val engineSource: EngineSource) : EventSource()
|
data class Action(override val engineSource: EngineSource) : EventSource(engineSource)
|
||||||
|
data class Widget(override val engineSource: EngineSource) : EventSource(engineSource)
|
||||||
private val source: EngineSource
|
data class Shortcut(override val engineSource: EngineSource) : EventSource(engineSource)
|
||||||
get() = when (this) {
|
data class Other(override val engineSource: EngineSource) : EventSource(engineSource)
|
||||||
is Suggestion -> engineSource
|
|
||||||
is Action -> engineSource
|
|
||||||
}
|
|
||||||
|
|
||||||
private val label: String
|
private val label: String
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
is Suggestion -> "suggestion"
|
is Suggestion -> "suggestion"
|
||||||
is Action -> "action"
|
is Action -> "action"
|
||||||
|
is Widget -> "widget"
|
||||||
|
is Shortcut -> "shortcut"
|
||||||
|
is Other -> "other"
|
||||||
}
|
}
|
||||||
|
|
||||||
val countLabel: String
|
val countLabel: String
|
||||||
get() = "${source.identifier.toLowerCase(Locale.getDefault())}.$label"
|
get() = "${engineSource.identifier.toLowerCase(Locale.getDefault())}.$label"
|
||||||
|
|
||||||
val sourceLabel: String
|
val sourceLabel: String
|
||||||
get() = "${source.descriptor}.$label"
|
get() = "${engineSource.descriptor}.$label"
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class SearchAccessPoint {
|
||||||
|
SUGGESTION, ACTION, WIDGET, SHORTCUT, NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override val extras: Map<Events.performedSearchKeys, String>?
|
override val extras: Map<Events.performedSearchKeys, String>?
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/* 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.components.metrics
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import mozilla.components.browser.search.SearchEngine
|
||||||
|
import org.mozilla.fenix.components.metrics.Event.PerformedSearch.SearchAccessPoint
|
||||||
|
import org.mozilla.fenix.components.searchengine.CustomSearchEngineStore
|
||||||
|
import org.mozilla.fenix.ext.searchEngineManager
|
||||||
|
|
||||||
|
object MetricsUtils {
|
||||||
|
fun createSearchEvent(
|
||||||
|
engine: SearchEngine,
|
||||||
|
context: Context,
|
||||||
|
searchAccessPoint: SearchAccessPoint
|
||||||
|
): Event.PerformedSearch? {
|
||||||
|
val isShortcut = engine != context.searchEngineManager.defaultSearchEngine
|
||||||
|
val isCustom = CustomSearchEngineStore.isCustomSearchEngine(context, engine.identifier)
|
||||||
|
|
||||||
|
val engineSource =
|
||||||
|
if (isShortcut) Event.PerformedSearch.EngineSource.Shortcut(engine, isCustom)
|
||||||
|
else Event.PerformedSearch.EngineSource.Default(engine, isCustom)
|
||||||
|
|
||||||
|
return when (searchAccessPoint) {
|
||||||
|
SearchAccessPoint.SUGGESTION -> Event.PerformedSearch(
|
||||||
|
Event.PerformedSearch.EventSource.Suggestion(
|
||||||
|
engineSource
|
||||||
|
)
|
||||||
|
)
|
||||||
|
SearchAccessPoint.ACTION -> Event.PerformedSearch(
|
||||||
|
Event.PerformedSearch.EventSource.Action(
|
||||||
|
engineSource
|
||||||
|
)
|
||||||
|
)
|
||||||
|
SearchAccessPoint.WIDGET -> Event.PerformedSearch(
|
||||||
|
Event.PerformedSearch.EventSource.Widget(
|
||||||
|
engineSource
|
||||||
|
)
|
||||||
|
)
|
||||||
|
SearchAccessPoint.SHORTCUT -> Event.PerformedSearch(
|
||||||
|
Event.PerformedSearch.EventSource.Shortcut(
|
||||||
|
engineSource
|
||||||
|
)
|
||||||
|
)
|
||||||
|
SearchAccessPoint.NONE -> Event.PerformedSearch(
|
||||||
|
Event.PerformedSearch.EventSource.Other(
|
||||||
|
engineSource
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,10 @@ import android.content.Intent
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import org.mozilla.fenix.BrowserDirection
|
import org.mozilla.fenix.BrowserDirection
|
||||||
import org.mozilla.fenix.HomeActivity
|
import org.mozilla.fenix.HomeActivity
|
||||||
|
import org.mozilla.fenix.components.metrics.Event
|
||||||
|
import org.mozilla.fenix.components.metrics.MetricController
|
||||||
|
import org.mozilla.fenix.components.metrics.MetricsUtils
|
||||||
|
import org.mozilla.fenix.ext.components
|
||||||
import org.mozilla.fenix.widget.VoiceSearchActivity.Companion.SPEECH_PROCESSING
|
import org.mozilla.fenix.widget.VoiceSearchActivity.Companion.SPEECH_PROCESSING
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,12 +19,21 @@ import org.mozilla.fenix.widget.VoiceSearchActivity.Companion.SPEECH_PROCESSING
|
||||||
* Once the search is complete then a new search should be started.
|
* Once the search is complete then a new search should be started.
|
||||||
*/
|
*/
|
||||||
class SpeechProcessingIntentProcessor(
|
class SpeechProcessingIntentProcessor(
|
||||||
private val activity: HomeActivity
|
private val activity: HomeActivity,
|
||||||
|
private val metrics: MetricController
|
||||||
) : HomeIntentProcessor {
|
) : HomeIntentProcessor {
|
||||||
|
|
||||||
override fun process(intent: Intent, navController: NavController, out: Intent): Boolean {
|
override fun process(intent: Intent, navController: NavController, out: Intent): Boolean {
|
||||||
return if (intent.extras?.getBoolean(HomeActivity.OPEN_TO_BROWSER_AND_LOAD) == true) {
|
return if (intent.extras?.getBoolean(HomeActivity.OPEN_TO_BROWSER_AND_LOAD) == true) {
|
||||||
out.putExtra(HomeActivity.OPEN_TO_BROWSER_AND_LOAD, false)
|
out.putExtra(HomeActivity.OPEN_TO_BROWSER_AND_LOAD, false)
|
||||||
|
|
||||||
|
val searchEvent = MetricsUtils.createSearchEvent(
|
||||||
|
activity.components.search.provider.getDefaultEngine(activity),
|
||||||
|
activity,
|
||||||
|
Event.PerformedSearch.SearchAccessPoint.WIDGET
|
||||||
|
)
|
||||||
|
searchEvent?.let { metrics.track(it) }
|
||||||
|
|
||||||
activity.openToBrowserAndLoad(
|
activity.openToBrowserAndLoad(
|
||||||
searchTermOrURL = intent.getStringExtra(SPEECH_PROCESSING).orEmpty(),
|
searchTermOrURL = intent.getStringExtra(SPEECH_PROCESSING).orEmpty(),
|
||||||
newTab = true,
|
newTab = true,
|
||||||
|
|
|
@ -22,20 +22,36 @@ class StartSearchIntentProcessor(
|
||||||
|
|
||||||
override fun process(intent: Intent, navController: NavController, out: Intent): Boolean {
|
override fun process(intent: Intent, navController: NavController, out: Intent): Boolean {
|
||||||
val event = intent.extras?.getString(HomeActivity.OPEN_TO_SEARCH)
|
val event = intent.extras?.getString(HomeActivity.OPEN_TO_SEARCH)
|
||||||
|
var source: Event.PerformedSearch.SearchAccessPoint? = null
|
||||||
return if (event != null) {
|
return if (event != null) {
|
||||||
when (event) {
|
when (event) {
|
||||||
SEARCH_WIDGET -> metrics.track(Event.SearchWidgetNewTabPressed)
|
SEARCH_WIDGET -> {
|
||||||
STATIC_SHORTCUT_NEW_TAB -> metrics.track(Event.PrivateBrowsingStaticShortcutTab)
|
metrics.track(Event.SearchWidgetNewTabPressed)
|
||||||
STATIC_SHORTCUT_NEW_PRIVATE_TAB -> metrics.track(Event.PrivateBrowsingStaticShortcutPrivateTab)
|
source = Event.PerformedSearch.SearchAccessPoint.WIDGET
|
||||||
PRIVATE_BROWSING_PINNED_SHORTCUT -> metrics.track(Event.PrivateBrowsingPinnedShortcutPrivateTab)
|
}
|
||||||
|
STATIC_SHORTCUT_NEW_TAB -> {
|
||||||
|
metrics.track(Event.PrivateBrowsingStaticShortcutTab)
|
||||||
|
source = Event.PerformedSearch.SearchAccessPoint.SHORTCUT
|
||||||
|
}
|
||||||
|
STATIC_SHORTCUT_NEW_PRIVATE_TAB -> {
|
||||||
|
metrics.track(Event.PrivateBrowsingStaticShortcutPrivateTab)
|
||||||
|
source = Event.PerformedSearch.SearchAccessPoint.SHORTCUT
|
||||||
|
}
|
||||||
|
PRIVATE_BROWSING_PINNED_SHORTCUT -> {
|
||||||
|
metrics.track(Event.PrivateBrowsingPinnedShortcutPrivateTab)
|
||||||
|
source = Event.PerformedSearch.SearchAccessPoint.SHORTCUT
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out.removeExtra(HomeActivity.OPEN_TO_SEARCH)
|
out.removeExtra(HomeActivity.OPEN_TO_SEARCH)
|
||||||
|
|
||||||
val directions = NavGraphDirections.actionGlobalSearch(
|
val directions = source?.let {
|
||||||
sessionId = null
|
NavGraphDirections.actionGlobalSearch(
|
||||||
)
|
sessionId = null,
|
||||||
navController.nav(null, directions)
|
searchAccessPoint = it
|
||||||
|
)
|
||||||
|
}
|
||||||
|
directions?.let { navController.nav(null, it) }
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
|
|
@ -14,12 +14,15 @@ 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.components.metrics.Event
|
import org.mozilla.fenix.components.metrics.Event
|
||||||
|
import org.mozilla.fenix.components.metrics.Event.PerformedSearch.SearchAccessPoint.ACTION
|
||||||
|
import org.mozilla.fenix.components.metrics.Event.PerformedSearch.SearchAccessPoint.NONE
|
||||||
|
import org.mozilla.fenix.components.metrics.Event.PerformedSearch.SearchAccessPoint.SUGGESTION
|
||||||
|
import org.mozilla.fenix.components.metrics.MetricsUtils
|
||||||
import org.mozilla.fenix.components.searchengine.CustomSearchEngineStore
|
import org.mozilla.fenix.components.searchengine.CustomSearchEngineStore
|
||||||
|
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.settings
|
import org.mozilla.fenix.ext.settings
|
||||||
import org.mozilla.fenix.ext.components
|
|
||||||
import org.mozilla.fenix.ext.searchEngineManager
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
@ -54,10 +57,21 @@ class DefaultSearchController(
|
||||||
val event = if (url.isUrl()) {
|
val event = if (url.isUrl()) {
|
||||||
Event.EnteredUrl(false)
|
Event.EnteredUrl(false)
|
||||||
} else {
|
} else {
|
||||||
createSearchEvent(store.state.searchEngineSource.searchEngine, false)
|
val searchAccessPoint = when (store.state.searchAccessPoint) {
|
||||||
|
NONE -> ACTION
|
||||||
|
else -> store.state.searchAccessPoint
|
||||||
|
}
|
||||||
|
|
||||||
|
searchAccessPoint?.let { sap ->
|
||||||
|
MetricsUtils.createSearchEvent(
|
||||||
|
store.state.searchEngineSource.searchEngine,
|
||||||
|
context,
|
||||||
|
sap
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.metrics.track(event)
|
event?.let { context.metrics.track(it) }
|
||||||
if (CustomSearchEngineStore.isCustomSearchEngine(
|
if (CustomSearchEngineStore.isCustomSearchEngine(
|
||||||
context,
|
context,
|
||||||
store.state.searchEngineSource.searchEngine.identifier
|
store.state.searchEngineSource.searchEngine.identifier
|
||||||
|
@ -111,8 +125,20 @@ class DefaultSearchController(
|
||||||
forceSearch = true
|
forceSearch = true
|
||||||
)
|
)
|
||||||
|
|
||||||
val event = createSearchEvent(store.state.searchEngineSource.searchEngine, true)
|
val searchAccessPoint = when (store.state.searchAccessPoint) {
|
||||||
context.metrics.track(event)
|
NONE -> SUGGESTION
|
||||||
|
else -> store.state.searchAccessPoint
|
||||||
|
}
|
||||||
|
|
||||||
|
val event = searchAccessPoint?.let { sap ->
|
||||||
|
MetricsUtils.createSearchEvent(
|
||||||
|
store.state.searchEngineSource.searchEngine,
|
||||||
|
context,
|
||||||
|
sap
|
||||||
|
)
|
||||||
|
}
|
||||||
|
event?.let { context.metrics.track(it) }
|
||||||
|
|
||||||
if (CustomSearchEngineStore.isCustomSearchEngine(
|
if (CustomSearchEngineStore.isCustomSearchEngine(
|
||||||
context,
|
context,
|
||||||
store.state.searchEngineSource.searchEngine.identifier
|
store.state.searchEngineSource.searchEngine.identifier
|
||||||
|
@ -142,22 +168,4 @@ class DefaultSearchController(
|
||||||
navController.nav(R.id.searchFragment, directions)
|
navController.nav(R.id.searchFragment, directions)
|
||||||
context.components.core.sessionManager.select(session)
|
context.components.core.sessionManager.select(session)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createSearchEvent(
|
|
||||||
engine: SearchEngine,
|
|
||||||
isSuggestion: Boolean
|
|
||||||
): Event.PerformedSearch {
|
|
||||||
val isShortcut = engine != context.searchEngineManager.defaultSearchEngine
|
|
||||||
val isCustom = CustomSearchEngineStore.isCustomSearchEngine(context, engine.identifier)
|
|
||||||
|
|
||||||
val engineSource =
|
|
||||||
if (isShortcut) Event.PerformedSearch.EngineSource.Shortcut(engine, isCustom)
|
|
||||||
else Event.PerformedSearch.EngineSource.Default(engine, isCustom)
|
|
||||||
|
|
||||||
val source =
|
|
||||||
if (isSuggestion) Event.PerformedSearch.EventSource.Suggestion(engineSource)
|
|
||||||
else Event.PerformedSearch.EventSource.Action(engineSource)
|
|
||||||
|
|
||||||
return Event.PerformedSearch(source)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,9 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
?.let(SearchFragmentArgs.Companion::fromBundle)
|
?.let(SearchFragmentArgs.Companion::fromBundle)
|
||||||
?.let { it.pastedText }
|
?.let { it.pastedText }
|
||||||
|
|
||||||
|
val searchAccessPoint = arguments
|
||||||
|
?.let(SearchFragmentArgs.Companion::fromBundle)?.searchAccessPoint
|
||||||
|
|
||||||
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(
|
||||||
|
@ -107,7 +110,8 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
showHistorySuggestions = requireContext().settings().shouldShowHistorySuggestions,
|
showHistorySuggestions = requireContext().settings().shouldShowHistorySuggestions,
|
||||||
showBookmarkSuggestions = requireContext().settings().shouldShowBookmarkSuggestions,
|
showBookmarkSuggestions = requireContext().settings().shouldShowBookmarkSuggestions,
|
||||||
session = session,
|
session = session,
|
||||||
pastedText = pastedText
|
pastedText = pastedText,
|
||||||
|
searchAccessPoint = searchAccessPoint
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import mozilla.components.browser.session.Session
|
||||||
import mozilla.components.lib.state.Action
|
import mozilla.components.lib.state.Action
|
||||||
import mozilla.components.lib.state.State
|
import mozilla.components.lib.state.State
|
||||||
import mozilla.components.lib.state.Store
|
import mozilla.components.lib.state.Store
|
||||||
|
import org.mozilla.fenix.components.metrics.Event
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The [Store] for holding the [SearchFragmentState] and applying [SearchFragmentAction]s.
|
* The [Store] for holding the [SearchFragmentState] and applying [SearchFragmentAction]s.
|
||||||
|
@ -55,7 +56,8 @@ data class SearchFragmentState(
|
||||||
val showHistorySuggestions: Boolean,
|
val showHistorySuggestions: Boolean,
|
||||||
val showBookmarkSuggestions: Boolean,
|
val showBookmarkSuggestions: Boolean,
|
||||||
val session: Session?,
|
val session: Session?,
|
||||||
val pastedText: String? = null
|
val pastedText: String? = null,
|
||||||
|
val searchAccessPoint: Event.PerformedSearch.SearchAccessPoint?
|
||||||
) : State
|
) : State
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -112,6 +112,10 @@
|
||||||
android:defaultValue="@null"
|
android:defaultValue="@null"
|
||||||
app:argType="string"
|
app:argType="string"
|
||||||
app:nullable="true" />
|
app:nullable="true" />
|
||||||
|
<argument
|
||||||
|
android:name="search_access_point"
|
||||||
|
app:argType="org.mozilla.fenix.components.metrics.Event$PerformedSearch$SearchAccessPoint"
|
||||||
|
android:defaultValue="NONE" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
package org.mozilla.fenix.components.metrics
|
||||||
|
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import mozilla.components.browser.search.SearchEngine
|
||||||
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.TestApplication
|
||||||
|
import org.robolectric.RobolectricTestRunner
|
||||||
|
import org.robolectric.annotation.Config
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner::class)
|
||||||
|
@Config(application = TestApplication::class)
|
||||||
|
class MetricsUtilsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun createSearchEvent() {
|
||||||
|
val engine: SearchEngine = mockk(relaxed = true)
|
||||||
|
val context = testContext
|
||||||
|
|
||||||
|
every { engine.identifier } returns ENGINE_SOURCE_IDENTIFIER
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
"$ENGINE_SOURCE_IDENTIFIER.suggestion",
|
||||||
|
MetricsUtils.createSearchEvent(
|
||||||
|
engine,
|
||||||
|
context,
|
||||||
|
Event.PerformedSearch.SearchAccessPoint.SUGGESTION
|
||||||
|
)?.eventSource?.countLabel
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
"$ENGINE_SOURCE_IDENTIFIER.action",
|
||||||
|
MetricsUtils.createSearchEvent(
|
||||||
|
engine,
|
||||||
|
context,
|
||||||
|
Event.PerformedSearch.SearchAccessPoint.ACTION
|
||||||
|
)?.eventSource?.countLabel
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
"$ENGINE_SOURCE_IDENTIFIER.widget",
|
||||||
|
MetricsUtils.createSearchEvent(
|
||||||
|
engine,
|
||||||
|
context,
|
||||||
|
Event.PerformedSearch.SearchAccessPoint.WIDGET
|
||||||
|
)?.eventSource?.countLabel
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
"$ENGINE_SOURCE_IDENTIFIER.shortcut",
|
||||||
|
MetricsUtils.createSearchEvent(
|
||||||
|
engine,
|
||||||
|
context,
|
||||||
|
Event.PerformedSearch.SearchAccessPoint.SHORTCUT
|
||||||
|
)?.eventSource?.countLabel
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val ENGINE_SOURCE_IDENTIFIER = "google-2018"
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ package org.mozilla.fenix.home.intent
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import io.mockk.Called
|
import io.mockk.Called
|
||||||
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
@ -14,6 +15,8 @@ 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.TestApplication
|
import org.mozilla.fenix.TestApplication
|
||||||
|
import org.mozilla.fenix.components.metrics.MetricController
|
||||||
|
import org.mozilla.fenix.ext.components
|
||||||
import org.mozilla.fenix.widget.VoiceSearchActivity.Companion.SPEECH_PROCESSING
|
import org.mozilla.fenix.widget.VoiceSearchActivity.Companion.SPEECH_PROCESSING
|
||||||
import org.robolectric.RobolectricTestRunner
|
import org.robolectric.RobolectricTestRunner
|
||||||
import org.robolectric.annotation.Config
|
import org.robolectric.annotation.Config
|
||||||
|
@ -25,15 +28,17 @@ class SpeechProcessingIntentProcessorTest {
|
||||||
private val activity: HomeActivity = mockk(relaxed = true)
|
private val activity: HomeActivity = mockk(relaxed = true)
|
||||||
private val navController: NavController = mockk(relaxed = true)
|
private val navController: NavController = mockk(relaxed = true)
|
||||||
private val out: Intent = mockk(relaxed = true)
|
private val out: Intent = mockk(relaxed = true)
|
||||||
|
private val metrics: MetricController = mockk(relaxed = true)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `do not process blank intents`() {
|
fun `do not process blank intents`() {
|
||||||
val processor = SpeechProcessingIntentProcessor(activity)
|
val processor = SpeechProcessingIntentProcessor(activity, metrics)
|
||||||
processor.process(Intent(), navController, out)
|
processor.process(Intent(), navController, out)
|
||||||
|
|
||||||
verify { activity wasNot Called }
|
verify { activity wasNot Called }
|
||||||
verify { navController wasNot Called }
|
verify { navController wasNot Called }
|
||||||
verify { out wasNot Called }
|
verify { out wasNot Called }
|
||||||
|
verify { metrics wasNot Called }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -41,12 +46,13 @@ class SpeechProcessingIntentProcessorTest {
|
||||||
val intent = Intent().apply {
|
val intent = Intent().apply {
|
||||||
putExtra(HomeActivity.OPEN_TO_BROWSER_AND_LOAD, false)
|
putExtra(HomeActivity.OPEN_TO_BROWSER_AND_LOAD, false)
|
||||||
}
|
}
|
||||||
val processor = SpeechProcessingIntentProcessor(activity)
|
val processor = SpeechProcessingIntentProcessor(activity, metrics)
|
||||||
processor.process(intent, navController, out)
|
processor.process(intent, navController, out)
|
||||||
|
|
||||||
verify { activity wasNot Called }
|
verify { activity wasNot Called }
|
||||||
verify { navController wasNot Called }
|
verify { navController wasNot Called }
|
||||||
verify { out wasNot Called }
|
verify { out wasNot Called }
|
||||||
|
verify { metrics wasNot Called }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -54,7 +60,9 @@ class SpeechProcessingIntentProcessorTest {
|
||||||
val intent = Intent().apply {
|
val intent = Intent().apply {
|
||||||
putExtra(HomeActivity.OPEN_TO_BROWSER_AND_LOAD, true)
|
putExtra(HomeActivity.OPEN_TO_BROWSER_AND_LOAD, true)
|
||||||
}
|
}
|
||||||
val processor = SpeechProcessingIntentProcessor(activity)
|
val processor = SpeechProcessingIntentProcessor(activity, metrics)
|
||||||
|
every { activity.components.search.provider.getDefaultEngine(activity) } returns mockk(relaxed = true)
|
||||||
|
|
||||||
processor.process(intent, navController, out)
|
processor.process(intent, navController, out)
|
||||||
|
|
||||||
verify {
|
verify {
|
||||||
|
@ -75,7 +83,9 @@ class SpeechProcessingIntentProcessorTest {
|
||||||
putExtra(HomeActivity.OPEN_TO_BROWSER_AND_LOAD, true)
|
putExtra(HomeActivity.OPEN_TO_BROWSER_AND_LOAD, true)
|
||||||
putExtra(SPEECH_PROCESSING, "hello world")
|
putExtra(SPEECH_PROCESSING, "hello world")
|
||||||
}
|
}
|
||||||
val processor = SpeechProcessingIntentProcessor(activity)
|
val processor = SpeechProcessingIntentProcessor(activity, metrics)
|
||||||
|
every { activity.components.search.provider.getDefaultEngine(activity) } returns mockk(relaxed = true)
|
||||||
|
|
||||||
processor.process(intent, mockk(), mockk(relaxed = true))
|
processor.process(intent, mockk(), mockk(relaxed = true))
|
||||||
|
|
||||||
verify {
|
verify {
|
||||||
|
|
|
@ -58,7 +58,10 @@ class StartSearchIntentProcessorTest {
|
||||||
verify { metrics.track(Event.SearchWidgetNewTabPressed) }
|
verify { metrics.track(Event.SearchWidgetNewTabPressed) }
|
||||||
verify {
|
verify {
|
||||||
navController.navigate(
|
navController.navigate(
|
||||||
NavGraphDirections.actionGlobalSearch(sessionId = null),
|
NavGraphDirections.actionGlobalSearch(
|
||||||
|
sessionId = null,
|
||||||
|
searchAccessPoint = Event.PerformedSearch.SearchAccessPoint.WIDGET
|
||||||
|
),
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import mozilla.components.browser.search.SearchEngine
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertNotSame
|
import org.junit.Assert.assertNotSame
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import org.mozilla.fenix.components.metrics.Event
|
||||||
|
|
||||||
class SearchFragmentStoreTest {
|
class SearchFragmentStoreTest {
|
||||||
|
|
||||||
|
@ -56,6 +57,7 @@ class SearchFragmentStoreTest {
|
||||||
showClipboardSuggestions = false,
|
showClipboardSuggestions = false,
|
||||||
showHistorySuggestions = false,
|
showHistorySuggestions = false,
|
||||||
showBookmarkSuggestions = false,
|
showBookmarkSuggestions = false,
|
||||||
session = null
|
session = null,
|
||||||
|
searchAccessPoint = Event.PerformedSearch.SearchAccessPoint.NONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,10 @@ import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mozilla.fenix.BrowserDirection
|
import org.mozilla.fenix.BrowserDirection
|
||||||
import org.mozilla.fenix.FenixApplication
|
import org.mozilla.fenix.FenixApplication
|
||||||
import org.mozilla.fenix.TestApplication
|
|
||||||
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.searchengine.CustomSearchEngineStore.PREF_FILE_SEARCH_ENGINES
|
import org.mozilla.fenix.components.searchengine.CustomSearchEngineStore.PREF_FILE_SEARCH_ENGINES
|
||||||
import org.mozilla.fenix.ext.metrics
|
import org.mozilla.fenix.ext.metrics
|
||||||
import org.mozilla.fenix.ext.searchEngineManager
|
import org.mozilla.fenix.ext.searchEngineManager
|
||||||
|
@ -44,6 +45,7 @@ class SearchInteractorTest {
|
||||||
val state: SearchFragmentState = mockk()
|
val state: SearchFragmentState = mockk()
|
||||||
val searchEngineManager: SearchEngineManager = mockk(relaxed = true)
|
val searchEngineManager: SearchEngineManager = mockk(relaxed = true)
|
||||||
val searchEngine = SearchEngineSource.Default(mockk(relaxed = true))
|
val searchEngine = SearchEngineSource.Default(mockk(relaxed = true))
|
||||||
|
val searchAccessPoint: Event.PerformedSearch.SearchAccessPoint = mockk(relaxed = true)
|
||||||
|
|
||||||
every { context.metrics } returns mockk(relaxed = true)
|
every { context.metrics } returns mockk(relaxed = true)
|
||||||
every { context.searchEngineManager } returns searchEngineManager
|
every { context.searchEngineManager } returns searchEngineManager
|
||||||
|
@ -52,6 +54,7 @@ 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.searchAccessPoint } returns searchAccessPoint
|
||||||
|
|
||||||
every {
|
every {
|
||||||
context.getSharedPreferences(
|
context.getSharedPreferences(
|
||||||
|
@ -170,6 +173,7 @@ class SearchInteractorTest {
|
||||||
val state: SearchFragmentState = mockk()
|
val state: SearchFragmentState = mockk()
|
||||||
val searchEngineManager: SearchEngineManager = mockk(relaxed = true)
|
val searchEngineManager: SearchEngineManager = mockk(relaxed = true)
|
||||||
val searchEngine = SearchEngineSource.Default(mockk(relaxed = true))
|
val searchEngine = SearchEngineSource.Default(mockk(relaxed = true))
|
||||||
|
val searchAccessPoint: Event.PerformedSearch.SearchAccessPoint = mockk(relaxed = true)
|
||||||
|
|
||||||
every { context.metrics } returns mockk(relaxed = true)
|
every { context.metrics } returns mockk(relaxed = true)
|
||||||
every { context.searchEngineManager } returns searchEngineManager
|
every { context.searchEngineManager } returns searchEngineManager
|
||||||
|
@ -178,6 +182,7 @@ 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.searchAccessPoint } returns searchAccessPoint
|
||||||
|
|
||||||
every {
|
every {
|
||||||
context.getSharedPreferences(
|
context.getSharedPreferences(
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue