For #24211: Remove wrapper from search related metrics.

Removes wrapper from search labeled counter and performed search event.
pull/543/head
mcarare 2 years ago committed by mergify[bot]
parent 00156907c0
commit dfe23e8b77

@ -108,6 +108,7 @@ events:
* default.suggestion
* shortcut.action
* shortcut.suggestion
type: string
bugs:
- https://github.com/mozilla-mobile/fenix/issues/959
- https://github.com/mozilla-mobile/fenix/issues/19923

@ -4,10 +4,8 @@
package org.mozilla.fenix.components.metrics
import mozilla.components.browser.state.search.SearchEngine
import org.mozilla.fenix.GleanMetrics.Autoplay
import org.mozilla.fenix.GleanMetrics.ContextMenu
import org.mozilla.fenix.GleanMetrics.Events
import org.mozilla.fenix.GleanMetrics.SearchTerms
import java.util.Locale
@ -91,70 +89,6 @@ sealed class Event {
// Interaction events with extras
data class PerformedSearch(val eventSource: EventSource) : Event() {
sealed class EngineSource {
abstract val engine: SearchEngine
abstract val isCustom: Boolean
data class Default(override val engine: SearchEngine, override val isCustom: Boolean) :
EngineSource()
data class Shortcut(override val engine: SearchEngine, override val isCustom: Boolean) :
EngineSource()
// https://github.com/mozilla-mobile/fenix/issues/1607
// Sanitize identifiers for custom search engines.
val identifier: String
get() = if (isCustom) "custom" else engine.id
val searchEngine: SearchEngine
get() = when (this) {
is Default -> engine
is Shortcut -> engine
}
val descriptor: String
get() = when (this) {
is Default -> "default"
is Shortcut -> "shortcut"
}
}
sealed class EventSource(open val engineSource: EngineSource) {
data class Suggestion(override val engineSource: EngineSource) :
EventSource(engineSource)
data class Action(override val engineSource: EngineSource) : EventSource(engineSource)
data class Widget(override val engineSource: EngineSource) : EventSource(engineSource)
data class Shortcut(override val engineSource: EngineSource) : EventSource(engineSource)
data class TopSite(override val engineSource: EngineSource) : EventSource(engineSource)
data class Other(override val engineSource: EngineSource) : EventSource(engineSource)
private val label: String
get() = when (this) {
is Suggestion -> "suggestion"
is Action -> "action"
is Widget -> "widget"
is Shortcut -> "shortcut"
is TopSite -> "topsite"
is Other -> "other"
}
val countLabel: String
get() = "${engineSource.identifier.lowercase(Locale.getDefault())}.$label"
val sourceLabel: String
get() = "${engineSource.descriptor}.$label"
}
enum class SearchAccessPoint {
SUGGESTION, ACTION, WIDGET, SHORTCUT, TOPSITE, NONE
}
override val extras: Map<Events.performedSearchKeys, String>?
get() = mapOf(Events.performedSearchKeys.source to eventSource.sourceLabel)
}
data class SearchWithAds(val providerName: String) : Event() {
val label: String
get() = providerName

@ -15,10 +15,8 @@ import org.mozilla.fenix.GleanMetrics.BrowserSearch
import org.mozilla.fenix.GleanMetrics.ContextMenu
import org.mozilla.fenix.GleanMetrics.ContextualMenu
import org.mozilla.fenix.GleanMetrics.CreditCards
import org.mozilla.fenix.GleanMetrics.Events
import org.mozilla.fenix.GleanMetrics.HomeMenu
import org.mozilla.fenix.GleanMetrics.HomeScreen
import org.mozilla.fenix.GleanMetrics.Metrics
import org.mozilla.fenix.GleanMetrics.Pings
import org.mozilla.fenix.GleanMetrics.ProgressiveWebApp
import org.mozilla.fenix.GleanMetrics.RecentBookmarks
@ -75,13 +73,6 @@ private class EventWrapper<T : Enum<T>>(
// FIXME(#19967): Migrate to non-deprecated API.
private val Event.wrapper: EventWrapper<*>?
get() = when (this) {
is Event.PerformedSearch -> EventWrapper(
{
Metrics.searchCount[this.eventSource.countLabel].add(1)
Events.performedSearch.record(it)
},
{ Events.performedSearchKeys.valueOf(it) }
)
is Event.SearchWithAds -> EventWrapper<NoExtraKeys>(
{
BrowserSearch.withAds[label].add(1)

@ -13,10 +13,9 @@ import com.google.android.gms.common.GooglePlayServicesRepairableException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import mozilla.components.browser.state.search.SearchEngine
import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.support.base.log.logger.Logger
import org.mozilla.fenix.components.metrics.Event.PerformedSearch.SearchAccessPoint
import org.mozilla.fenix.GleanMetrics.Events
import org.mozilla.fenix.GleanMetrics.Metrics
import java.io.IOException
import java.security.NoSuchAlgorithmException
import java.security.spec.InvalidKeySpecException
@ -24,53 +23,37 @@ import javax.crypto.SecretKeyFactory
import javax.crypto.spec.PBEKeySpec
object MetricsUtils {
fun createSearchEvent(
/**
* Possible sources for a performed search.
*/
enum class Source {
ACTION, SHORTCUT, SUGGESTION, TOPSITE, WIDGET, NONE
}
/**
* Records the appropriate metric for performed searches.
* @engine the engine used for searching.
* @isDefault whether te engine is the default engine or not.
* @searchAccessPoint the source of the search. Can be one of the values of [Source].
*/
fun recordSearchMetrics(
engine: SearchEngine,
store: BrowserStore,
searchAccessPoint: SearchAccessPoint
): Event.PerformedSearch? {
val isShortcut = engine != store.state.search.selectedOrDefaultSearchEngine
val isCustom = engine.type == SearchEngine.Type.CUSTOM
isDefault: Boolean,
searchAccessPoint: Source
) {
val identifier = if (engine.type == SearchEngine.Type.CUSTOM) "custom" else engine.id
val source = searchAccessPoint.name.lowercase()
val engineSource =
if (isShortcut) {
Event.PerformedSearch.EngineSource.Shortcut(engine, isCustom)
} else {
Event.PerformedSearch.EngineSource.Default(engine, isCustom)
}
Metrics.searchCount["$identifier.$source"].add()
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.TOPSITE -> Event.PerformedSearch(
Event.PerformedSearch.EventSource.TopSite(
engineSource
)
)
SearchAccessPoint.NONE -> Event.PerformedSearch(
Event.PerformedSearch.EventSource.Other(
engineSource
)
)
val performedSearchExtra = if (isDefault) {
"default.$source"
} else {
"shortcut.$source"
}
Events.performedSearch.record(Events.PerformedSearchExtra(performedSearchExtra))
}
/**

@ -8,11 +8,11 @@ import android.content.Intent
import android.os.StrictMode
import androidx.navigation.NavController
import mozilla.components.browser.state.search.SearchEngine
import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.feature.search.ext.waitForSelectedOrDefaultSearchEngine
import org.mozilla.fenix.BrowserDirection
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
@ -52,12 +52,11 @@ class SpeechProcessingIntentProcessor(
private fun launchToBrowser(searchEngine: SearchEngine, text: String) {
activity.components.strictMode.resetAfter(StrictMode.allowThreadDiskReads()) {
val searchEvent = MetricsUtils.createSearchEvent(
MetricsUtils.recordSearchMetrics(
searchEngine,
store,
Event.PerformedSearch.SearchAccessPoint.WIDGET
searchEngine == store.state.search.selectedOrDefaultSearchEngine,
MetricsUtils.Source.WIDGET
)
searchEvent?.let { metrics.track(it) }
}
activity.openToBrowserAndLoad(

@ -12,8 +12,8 @@ import org.mozilla.fenix.GleanMetrics.SearchWidget
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.R
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.nav
/**
@ -30,12 +30,12 @@ class StartSearchIntentProcessor(
val source = when (event) {
SEARCH_WIDGET -> {
SearchWidget.newTabButton.record(NoExtras())
Event.PerformedSearch.SearchAccessPoint.WIDGET
MetricsUtils.Source.WIDGET
}
STATIC_SHORTCUT_NEW_TAB,
STATIC_SHORTCUT_NEW_PRIVATE_TAB,
PRIVATE_BROWSING_PINNED_SHORTCUT -> {
Event.PerformedSearch.SearchAccessPoint.SHORTCUT
MetricsUtils.Source.SHORTCUT
}
else -> null
}

@ -13,6 +13,7 @@ import androidx.navigation.NavController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import mozilla.components.browser.state.search.SearchEngine
import mozilla.components.browser.state.selector.getNormalOrPrivateTabs
import mozilla.components.browser.state.state.availableSearchEngines
import mozilla.components.browser.state.state.searchEngines
@ -48,7 +49,6 @@ 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.ext.metrics
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.gleanplumb.Message
@ -417,17 +417,18 @@ class DefaultSessionControlController(
SupportUtils.POCKET_TRENDING_URL -> Pocket.pocketTopSiteClicked.record(NoExtras())
}
val availableEngines = getAvailableSearchEngines()
val searchAccessPoint = Event.PerformedSearch.SearchAccessPoint.TOPSITE
val event =
availableEngines.firstOrNull { engine ->
engine.resultUrls.firstOrNull { it.contains(topSite.url) } != null
}?.let { searchEngine ->
searchAccessPoint.let { sap ->
MetricsUtils.createSearchEvent(searchEngine, store, sap)
}
}
event?.let { activity.metrics.track(it) }
val availableEngines: List<SearchEngine> = getAvailableSearchEngines()
val searchAccessPoint = MetricsUtils.Source.TOPSITE
availableEngines.firstOrNull { engine ->
engine.resultUrls.firstOrNull { it.contains(topSite.url) } != null
}?.let { searchEngine ->
MetricsUtils.recordSearchMetrics(
searchEngine,
searchEngine == store.state.search.selectedOrDefaultSearchEngine,
searchAccessPoint
)
}
val tabId = addTabUseCase.invoke(
url = appendSearchAttributionToUrlIfNeeded(topSite.url),
@ -593,15 +594,12 @@ class DefaultSessionControlController(
if (clipboardText.isUrl() || searchEngine == null) {
Events.enteredUrl.record(Events.EnteredUrlExtra(autocomplete = false))
} else {
val searchAccessPoint = Event.PerformedSearch.SearchAccessPoint.ACTION
val event = searchAccessPoint.let { sap ->
MetricsUtils.createSearchEvent(
searchEngine,
store,
sap
)
}
event?.let { activity.metrics.track(it) }
val searchAccessPoint = MetricsUtils.Source.ACTION
MetricsUtils.recordSearchMetrics(
searchEngine,
searchEngine == store.state.search.selectedOrDefaultSearchEngine,
searchAccessPoint
)
}
}

@ -13,6 +13,7 @@ import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.AlertDialog
import androidx.navigation.NavController
import mozilla.components.browser.state.search.SearchEngine
import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.EngineSession.LoadUrlFlags
import mozilla.components.feature.tabs.TabsUseCases
@ -22,7 +23,6 @@ import org.mozilla.fenix.GleanMetrics.Events
import org.mozilla.fenix.GleanMetrics.SearchShortcuts
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
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.crashes.CrashListActivity
@ -106,20 +106,15 @@ class SearchDialogController(
Events.enteredUrl.record(Events.EnteredUrlExtra(autocomplete = false))
} else {
val searchAccessPoint = when (fragmentStore.state.searchAccessPoint) {
Event.PerformedSearch.SearchAccessPoint.NONE -> Event.PerformedSearch.SearchAccessPoint.ACTION
MetricsUtils.Source.NONE -> MetricsUtils.Source.ACTION
else -> fragmentStore.state.searchAccessPoint
}
val event = searchAccessPoint?.let { sap ->
MetricsUtils.createSearchEvent(
searchEngine,
store,
sap
)
}
event?.let {
metrics.track(it)
}
MetricsUtils.recordSearchMetrics(
searchEngine,
searchEngine == store.state.search.selectedOrDefaultSearchEngine,
searchAccessPoint
)
}
}
@ -176,18 +171,16 @@ class SearchDialogController(
)
val searchAccessPoint = when (fragmentStore.state.searchAccessPoint) {
Event.PerformedSearch.SearchAccessPoint.NONE -> Event.PerformedSearch.SearchAccessPoint.SUGGESTION
MetricsUtils.Source.NONE -> MetricsUtils.Source.SUGGESTION
else -> fragmentStore.state.searchAccessPoint
}
if (searchAccessPoint != null && searchEngine != null) {
MetricsUtils.createSearchEvent(
if (searchEngine != null) {
MetricsUtils.recordSearchMetrics(
searchEngine,
store,
searchEngine == store.state.search.selectedOrDefaultSearchEngine,
searchAccessPoint
)?.apply {
metrics.track(this)
}
)
}
}

@ -15,7 +15,7 @@ import mozilla.components.lib.state.Store
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.Components
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricsUtils
/**
* The [Store] for holding the [SearchFragmentState] and applying [SearchFragmentAction]s.
@ -80,16 +80,19 @@ data class SearchFragmentState(
val showSyncedTabsSuggestions: Boolean,
val tabId: String?,
val pastedText: String? = null,
val searchAccessPoint: Event.PerformedSearch.SearchAccessPoint?,
val searchAccessPoint: MetricsUtils.Source,
val clipboardHasUrl: Boolean = false
) : State
/**
* Creates the initial state for the search fragment.
*/
fun createInitialSearchFragmentState(
activity: HomeActivity,
components: Components,
tabId: String?,
pastedText: String?,
searchAccessPoint: Event.PerformedSearch.SearchAccessPoint
searchAccessPoint: MetricsUtils.Source
): SearchFragmentState {
val settings = components.settings
val tab = tabId?.let { components.core.store.state.findTab(it) }

@ -211,7 +211,7 @@
<argument
android:name="search_access_point"
android:defaultValue="NONE"
app:argType="org.mozilla.fenix.components.metrics.Event$PerformedSearch$SearchAccessPoint" />
app:argType="org.mozilla.fenix.components.metrics.MetricsUtils$Source" />
</dialog>
<fragment

@ -1,60 +0,0 @@
/* 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 io.mockk.every
import io.mockk.mockk
import mozilla.components.browser.state.search.SearchEngine
import mozilla.components.browser.state.store.BrowserStore
import org.junit.Assert
import org.junit.Test
/**
* Just the Roboelectric tests for MetricsUtil. Splitting these files out means our other tests will run more quickly.
* FenixRobolectricTestRunner also breaks our ability to use mockkStatic on Base64.
*/
class MetricsUtilsTestRoboelectric {
@Test
fun createSearchEvent() {
val store = BrowserStore()
val engine: SearchEngine = mockk(relaxed = true)
every { engine.id } returns MetricsUtilsTest.ENGINE_SOURCE_IDENTIFIER
Assert.assertEquals(
"${MetricsUtilsTest.ENGINE_SOURCE_IDENTIFIER}.suggestion",
MetricsUtils.createSearchEvent(
engine,
store,
Event.PerformedSearch.SearchAccessPoint.SUGGESTION
)?.eventSource?.countLabel
)
Assert.assertEquals(
"${MetricsUtilsTest.ENGINE_SOURCE_IDENTIFIER}.action",
MetricsUtils.createSearchEvent(
engine,
store,
Event.PerformedSearch.SearchAccessPoint.ACTION
)?.eventSource?.countLabel
)
Assert.assertEquals(
"${MetricsUtilsTest.ENGINE_SOURCE_IDENTIFIER}.widget",
MetricsUtils.createSearchEvent(
engine,
store,
Event.PerformedSearch.SearchAccessPoint.WIDGET
)?.eventSource?.countLabel
)
Assert.assertEquals(
"${MetricsUtilsTest.ENGINE_SOURCE_IDENTIFIER}.shortcut",
MetricsUtils.createSearchEvent(
engine,
store,
Event.PerformedSearch.SearchAccessPoint.SHORTCUT
)?.eventSource?.countLabel
)
}
}

@ -0,0 +1,254 @@
/* 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 io.mockk.every
import io.mockk.mockk
import mozilla.components.browser.state.search.SearchEngine
import mozilla.components.service.glean.testing.GleanTestRule
import mozilla.components.support.test.robolectric.testContext
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.GleanMetrics.Events
import org.mozilla.fenix.GleanMetrics.Metrics
import org.mozilla.fenix.components.metrics.MetricsUtilsTest.Companion.ENGINE_SOURCE_IDENTIFIER
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
/**
* Just the Robolectric tests for MetricsUtil. Splitting these files out means our other tests will run more quickly.
* FenixRobolectricTestRunner also breaks our ability to use mockkStatic on Base64.
*/
@RunWith(FenixRobolectricTestRunner::class) // for gleanTestRule
class MetricsUtilsTestRobolectric {
@get:Rule
val gleanTestRule = GleanTestRule(testContext)
@Test
fun `given a CUSTOM engine, when the search source is a ACTION the proper labeled metric is recorded`() {
assertFalse(Metrics.searchCount["custom.action"].testHasValue())
val engine: SearchEngine = mockk(relaxed = true)
every { engine.id } returns ENGINE_SOURCE_IDENTIFIER
every { engine.type } returns SearchEngine.Type.CUSTOM
MetricsUtils.recordSearchMetrics(
engine,
false,
MetricsUtils.Source.ACTION
)
assertTrue(Metrics.searchCount["custom.action"].testHasValue())
}
@Test
fun `given a CUSTOM engine, when the search source is a SHORTCUT the proper labeled metric is recorded`() {
assertFalse(Metrics.searchCount["custom.shortcut"].testHasValue())
val engine: SearchEngine = mockk(relaxed = true)
every { engine.id } returns ENGINE_SOURCE_IDENTIFIER
every { engine.type } returns SearchEngine.Type.CUSTOM
MetricsUtils.recordSearchMetrics(
engine,
false,
MetricsUtils.Source.SHORTCUT
)
assertTrue(Metrics.searchCount["custom.shortcut"].testHasValue())
}
@Test
fun `given a CUSTOM engine, when the search source is a SUGGESTION the proper labeled metric is recorded`() {
assertFalse(Metrics.searchCount["custom.suggestion"].testHasValue())
val engine: SearchEngine = mockk(relaxed = true)
every { engine.id } returns ENGINE_SOURCE_IDENTIFIER
every { engine.type } returns SearchEngine.Type.CUSTOM
MetricsUtils.recordSearchMetrics(
engine,
false,
MetricsUtils.Source.SUGGESTION
)
assertTrue(Metrics.searchCount["custom.suggestion"].testHasValue())
}
@Test
fun `given a CUSTOM engine, when the search source is a TOPSITE the proper labeled metric is recorded`() {
assertFalse(Metrics.searchCount["custom.topsite"].testHasValue())
val engine: SearchEngine = mockk(relaxed = true)
every { engine.id } returns ENGINE_SOURCE_IDENTIFIER
every { engine.type } returns SearchEngine.Type.CUSTOM
MetricsUtils.recordSearchMetrics(
engine,
false,
MetricsUtils.Source.TOPSITE
)
assertTrue(Metrics.searchCount["custom.topsite"].testHasValue())
}
@Test
fun `given a CUSTOM engine, when the search source is a WIDGET the proper labeled metric is recorded`() {
assertFalse(Metrics.searchCount["custom.widget"].testHasValue())
val engine: SearchEngine = mockk(relaxed = true)
every { engine.id } returns ENGINE_SOURCE_IDENTIFIER
every { engine.type } returns SearchEngine.Type.CUSTOM
MetricsUtils.recordSearchMetrics(
engine,
false,
MetricsUtils.Source.WIDGET
)
assertTrue(Metrics.searchCount["custom.widget"].testHasValue())
}
@Test
fun `given a BUNDLED engine, when the search source is an ACTION the proper labeled metric is recorded`() {
assertFalse(Metrics.searchCount["$ENGINE_SOURCE_IDENTIFIER.action"].testHasValue())
val engine: SearchEngine = mockk(relaxed = true)
every { engine.id } returns ENGINE_SOURCE_IDENTIFIER
every { engine.type } returns SearchEngine.Type.BUNDLED
MetricsUtils.recordSearchMetrics(
engine,
false,
MetricsUtils.Source.ACTION
)
assertTrue(Metrics.searchCount["$ENGINE_SOURCE_IDENTIFIER.action"].testHasValue())
}
@Test
fun `given a BUNDLED engine, when the search source is a TOPSITE the proper labeled metric is recorded`() {
assertFalse(Metrics.searchCount["$ENGINE_SOURCE_IDENTIFIER.topsite"].testHasValue())
val engine: SearchEngine = mockk(relaxed = true)
every { engine.id } returns ENGINE_SOURCE_IDENTIFIER
every { engine.type } returns SearchEngine.Type.BUNDLED
MetricsUtils.recordSearchMetrics(
engine,
false,
MetricsUtils.Source.TOPSITE
)
assertTrue(Metrics.searchCount["$ENGINE_SOURCE_IDENTIFIER.topsite"].testHasValue())
}
@Test
fun `given a BUNDLED engine, when the search source is a SHORTCUT the proper labeled metric is recorded`() {
assertFalse(Metrics.searchCount["$ENGINE_SOURCE_IDENTIFIER.shortcut"].testHasValue())
val engine: SearchEngine = mockk(relaxed = true)
every { engine.id } returns ENGINE_SOURCE_IDENTIFIER
every { engine.type } returns SearchEngine.Type.BUNDLED
MetricsUtils.recordSearchMetrics(
engine,
false,
MetricsUtils.Source.SHORTCUT
)
assertTrue(Metrics.searchCount["$ENGINE_SOURCE_IDENTIFIER.shortcut"].testHasValue())
}
@Test
fun `given a BUNDLED engine, when the search source is a SUGGESTION the proper labeled metric is recorded`() {
assertFalse(Metrics.searchCount["$ENGINE_SOURCE_IDENTIFIER.suggestion"].testHasValue())
val engine: SearchEngine = mockk(relaxed = true)
every { engine.id } returns ENGINE_SOURCE_IDENTIFIER
every { engine.type } returns SearchEngine.Type.BUNDLED
MetricsUtils.recordSearchMetrics(
engine,
false,
MetricsUtils.Source.SUGGESTION
)
assertTrue(Metrics.searchCount["$ENGINE_SOURCE_IDENTIFIER.suggestion"].testHasValue())
}
@Test
fun `given a BUNDLED engine, when the search source is a WIDGET the proper labeled metric is recorded`() {
assertFalse(Metrics.searchCount["$ENGINE_SOURCE_IDENTIFIER.widget"].testHasValue())
val engine: SearchEngine = mockk(relaxed = true)
every { engine.id } returns ENGINE_SOURCE_IDENTIFIER
every { engine.type } returns SearchEngine.Type.BUNDLED
MetricsUtils.recordSearchMetrics(
engine,
false,
MetricsUtils.Source.WIDGET
)
assertTrue(Metrics.searchCount["$ENGINE_SOURCE_IDENTIFIER.widget"].testHasValue())
}
@Test
fun `given a DEFAULT engine, when the search source is a WIDGET the proper labeled metric is recorded`() {
assertFalse(Events.performedSearch.testHasValue())
val engine: SearchEngine = mockk(relaxed = true)
every { engine.id } returns ENGINE_SOURCE_IDENTIFIER
every { engine.type } returns SearchEngine.Type.BUNDLED
MetricsUtils.recordSearchMetrics(
engine,
true,
MetricsUtils.Source.WIDGET
)
assertTrue(Events.performedSearch.testHasValue())
val snapshot = Events.performedSearch.testGetValue()
assertEquals(1, snapshot.size)
assertEquals("default.widget", snapshot.single().extra?.getValue("source"))
}
@Test
fun `given a NON DEFAULT engine, when the search source is a WIDGET the proper labeled metric is recorded`() {
assertFalse(Events.performedSearch.testHasValue())
val engine: SearchEngine = mockk(relaxed = true)
every { engine.id } returns ENGINE_SOURCE_IDENTIFIER
every { engine.type } returns SearchEngine.Type.BUNDLED
MetricsUtils.recordSearchMetrics(
engine,
false,
MetricsUtils.Source.WIDGET
)
assertTrue(Events.performedSearch.testHasValue())
val snapshot = Events.performedSearch.testGetValue()
assertEquals(1, snapshot.size)
assertEquals("shortcut.widget", snapshot.single().extra?.getValue("source"))
}
}

@ -37,7 +37,6 @@ import mozilla.components.service.glean.testing.GleanTestRule
import mozilla.components.support.test.ext.joinBlocking
import mozilla.components.support.test.robolectric.testContext
import mozilla.components.support.test.rule.MainCoroutineRule
import mozilla.telemetry.glean.private.NoExtras
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
@ -63,7 +62,6 @@ import org.mozilla.fenix.components.TabCollectionStorage
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.components.appstate.AppState
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.Event.PerformedSearch.EngineSource
import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
@ -583,13 +581,14 @@ class DefaultSessionControlControllerTest {
@Test
fun handleSelectGoogleDefaultTopSite_EventPerformedSearchTopSite() {
assertFalse(Events.performedSearch.testHasValue())
val topSite = TopSite.Default(
id = 1L,
title = "Google",
url = SupportUtils.GOOGLE_URL,
createdAt = 0
)
val engineSource = EngineSource.Default(googleSearchEngine, false)
val controller = spyk(createController())
every { controller.getAvailableSearchEngines() } returns listOf(googleSearchEngine)
@ -601,15 +600,7 @@ class DefaultSessionControlControllerTest {
controller.handleSelectTopSite(topSite, position = 0)
verify {
metrics.track(
Event.PerformedSearch(
Event.PerformedSearch.EventSource.TopSite(
engineSource
)
)
)
}
assertTrue(Events.performedSearch.testHasValue())
assertTrue(TopSites.openDefault.testHasValue())
assertEquals(1, TopSites.openDefault.testGetValue().size)
@ -625,13 +616,14 @@ class DefaultSessionControlControllerTest {
@Test
fun handleSelectDuckDuckGoTopSite_EventPerformedSearchTopSite() {
assertFalse(Events.performedSearch.testHasValue())
val topSite = TopSite.Pinned(
id = 1L,
title = "DuckDuckGo",
url = "https://duckduckgo.com",
createdAt = 0
)
val engineSource = EngineSource.Shortcut(duckDuckGoSearchEngine, false)
val controller = spyk(createController())
every { controller.getAvailableSearchEngines() } returns listOf(googleSearchEngine, duckDuckGoSearchEngine)
@ -643,16 +635,7 @@ class DefaultSessionControlControllerTest {
controller.handleSelectTopSite(topSite, position = 0)
verify {
metrics.track(
Event.PerformedSearch(
Event.PerformedSearch.EventSource.TopSite(
engineSource
)
)
)
}
TopSites.openPinned.record(NoExtras())
assertTrue(Events.performedSearch.testHasValue())
} finally {
unmockkStatic("mozilla.components.browser.state.state.SearchStateKt")
}
@ -956,6 +939,7 @@ class DefaultSessionControlControllerTest {
@Test
fun handlePasteAndGo() {
assertFalse(Events.enteredUrl.testHasValue())
assertFalse(Events.performedSearch.testHasValue())
createController().handlePasteAndGo("text")
@ -966,9 +950,10 @@ class DefaultSessionControlControllerTest {
from = BrowserDirection.FromHome,
engine = searchEngine
)
metrics.track(any<Event.PerformedSearch>())
}
assertTrue(Events.performedSearch.testHasValue())
createController().handlePasteAndGo("https://mozilla.org")
verify {
activity.openToBrowserAndLoad(

@ -21,8 +21,8 @@ import org.mozilla.fenix.GleanMetrics.SearchWidget
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.R
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.nav
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
@ -77,7 +77,7 @@ class StartSearchIntentProcessorTest {
null,
NavGraphDirections.actionGlobalSearchDialog(
sessionId = null,
searchAccessPoint = Event.PerformedSearch.SearchAccessPoint.WIDGET
searchAccessPoint = MetricsUtils.Source.WIDGET
),
options
)

@ -8,8 +8,10 @@ import androidx.appcompat.app.AlertDialog
import androidx.navigation.NavController
import androidx.navigation.NavDirections
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.mockk
import io.mockk.mockkObject
import io.mockk.spyk
@ -78,7 +80,7 @@ class SearchDialogControllerTest {
every { navController.currentDestination } returns mockk {
every { id } returns R.id.searchDialogFragment
}
every { MetricsUtils.createSearchEvent(searchEngine, browserStore, any()) } returns null
every { MetricsUtils.recordSearchMetrics(searchEngine, any(), any()) } just Runs
}
@After

@ -28,7 +28,7 @@ import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.components.Components
import org.mozilla.fenix.components.metrics.Event.PerformedSearch.SearchAccessPoint
import org.mozilla.fenix.components.metrics.MetricsUtils
import org.mozilla.fenix.utils.Settings
class SearchFragmentStoreTest {
@ -70,7 +70,7 @@ class SearchFragmentStoreTest {
showSyncedTabsSuggestions = false,
tabId = null,
pastedText = "pastedText",
searchAccessPoint = SearchAccessPoint.ACTION
searchAccessPoint = MetricsUtils.Source.ACTION
)
assertEquals(
@ -80,7 +80,7 @@ class SearchFragmentStoreTest {
components,
tabId = null,
pastedText = "pastedText",
searchAccessPoint = SearchAccessPoint.ACTION
searchAccessPoint = MetricsUtils.Source.ACTION
)
)
assertEquals(
@ -90,7 +90,7 @@ class SearchFragmentStoreTest {
components,
tabId = "tabId",
pastedText = "pastedText",
searchAccessPoint = SearchAccessPoint.ACTION
searchAccessPoint = MetricsUtils.Source.ACTION
)
)
}
@ -128,14 +128,14 @@ class SearchFragmentStoreTest {
showSyncedTabsSuggestions = false,
tabId = "tabId",
pastedText = "",
searchAccessPoint = SearchAccessPoint.SHORTCUT
searchAccessPoint = MetricsUtils.Source.SHORTCUT
),
createInitialSearchFragmentState(
activity,
components,
tabId = "tabId",
pastedText = "",
searchAccessPoint = SearchAccessPoint.SHORTCUT
searchAccessPoint = MetricsUtils.Source.SHORTCUT
)
)
}
@ -347,6 +347,6 @@ class SearchFragmentStoreTest {
showHistorySuggestions = false,
showBookmarkSuggestions = false,
showSyncedTabsSuggestions = false,
searchAccessPoint = SearchAccessPoint.NONE
searchAccessPoint = MetricsUtils.Source.NONE
)
}

@ -24,7 +24,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricsUtils
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.search.SearchEngineSource
import org.mozilla.fenix.search.SearchFragmentState
@ -57,7 +57,7 @@ class ToolbarViewTest {
showHistorySuggestions = false,
showBookmarkSuggestions = false,
showSyncedTabsSuggestions = false,
searchAccessPoint = Event.PerformedSearch.SearchAccessPoint.NONE
searchAccessPoint = MetricsUtils.Source.NONE
)
@Before

@ -435,7 +435,6 @@
<ID>UndocumentedPublicClass:Event.kt$Event.OpenedLink$Mode</ID>
<ID>UndocumentedPublicClass:Event.kt$Event.PerformedSearch$EngineSource</ID>
<ID>UndocumentedPublicClass:Event.kt$Event.PerformedSearch$EventSource</ID>
<ID>UndocumentedPublicClass:Event.kt$Event.PerformedSearch$SearchAccessPoint</ID>
<ID>UndocumentedPublicClass:Event.kt$Event.PerformedSearch.EngineSource$Default : EngineSource</ID>
<ID>UndocumentedPublicClass:Event.kt$Event.PerformedSearch.EngineSource$Shortcut : EngineSource</ID>
<ID>UndocumentedPublicClass:Event.kt$Event.PerformedSearch.EventSource$Action : EventSource</ID>
@ -1076,7 +1075,6 @@
<ID>UndocumentedPublicFunction:MetricsService.kt$MetricsService$fun start()</ID>
<ID>UndocumentedPublicFunction:MetricsService.kt$MetricsService$fun stop()</ID>
<ID>UndocumentedPublicFunction:MetricsService.kt$MetricsService$fun track(event: Event)</ID>
<ID>UndocumentedPublicFunction:MetricsUtils.kt$MetricsUtils$fun createSearchEvent( engine: SearchEngine, store: BrowserStore, searchAccessPoint: SearchAccessPoint ): Event.PerformedSearch?</ID>
<ID>UndocumentedPublicFunction:Mode.kt$CurrentMode$fun emitModeChanges()</ID>
<ID>UndocumentedPublicFunction:Mode.kt$CurrentMode$fun getCurrentMode()</ID>
<ID>UndocumentedPublicFunction:Mode.kt$Mode.Companion$fun fromBrowsingMode(browsingMode: BrowsingMode)</ID>
@ -1178,7 +1176,6 @@
<ID>UndocumentedPublicFunction:SearchDialogController.kt$SearchController$fun handleUrlTapped(url: String, flags: LoadUrlFlags = LoadUrlFlags.none())</ID>
<ID>UndocumentedPublicFunction:SearchDialogController.kt$SearchDialogController$@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) fun buildDialog(): AlertDialog.Builder</ID>
<ID>UndocumentedPublicFunction:SearchDialogInteractor.kt$SearchDialogInteractor$fun onCameraPermissionsNeeded()</ID>
<ID>UndocumentedPublicFunction:SearchFragmentStore.kt$fun createInitialSearchFragmentState( activity: HomeActivity, components: Components, tabId: String?, pastedText: String?, searchAccessPoint: Event.PerformedSearch.SearchAccessPoint ): SearchFragmentState</ID>
<ID>UndocumentedPublicFunction:SearchStringValidator.kt$SearchStringValidator$fun isSearchStringValid(client: Client, searchString: String): Result</ID>
<ID>UndocumentedPublicFunction:SearchWidgetProvider.kt$SearchWidgetProvider.Companion$fun updateAllWidgets(context: Context)</ID>
<ID>UndocumentedPublicFunction:SelectBookmarkFolderAdapter.kt$SelectBookmarkFolderAdapter$fun updateData(tree: BookmarkNode?, hideFolderGuid: String?)</ID>

Loading…
Cancel
Save