For #28428: update growth data with new events
This commit is contained in:
parent
a3801065eb
commit
24674cbec4
|
@ -23,14 +23,9 @@ sealed class Event {
|
||||||
object SetAsDefault : GrowthData("xgpcgt")
|
object SetAsDefault : GrowthData("xgpcgt")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event recording the first time Firefox has been resumed in a 24 hour period.
|
* Event recording that an ad was clicked in a search engine results page.
|
||||||
*/
|
*/
|
||||||
object FirstAppOpenForDay : GrowthData("41hl22")
|
object SerpAdClicked : GrowthData("e2x17e")
|
||||||
|
|
||||||
/**
|
|
||||||
* Event recording the first time a URI is loaded in Firefox in a 24 hour period.
|
|
||||||
*/
|
|
||||||
object FirstUriLoadForDay : GrowthData("ja86ek")
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event recording the first time Firefox is used 3 days in a row in the first week of install.
|
* Event recording the first time Firefox is used 3 days in a row in the first week of install.
|
||||||
|
|
|
@ -262,6 +262,7 @@ internal class ReleaseMetricController(
|
||||||
|
|
||||||
Component.FEATURE_SEARCH to AdsTelemetry.SERP_ADD_CLICKED -> {
|
Component.FEATURE_SEARCH to AdsTelemetry.SERP_ADD_CLICKED -> {
|
||||||
BrowserSearch.adClicks[value!!].add()
|
BrowserSearch.adClicks[value!!].add()
|
||||||
|
track(Event.GrowthData.SerpAdClicked)
|
||||||
}
|
}
|
||||||
Component.FEATURE_SEARCH to AdsTelemetry.SERP_SHOWN_WITH_ADDS -> {
|
Component.FEATURE_SEARCH to AdsTelemetry.SERP_SHOWN_WITH_ADDS -> {
|
||||||
BrowserSearch.withAds[value!!].add()
|
BrowserSearch.withAds[value!!].add()
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
/* 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
|
package org.mozilla.fenix.components.metrics
|
||||||
|
|
||||||
import mozilla.components.lib.state.Middleware
|
import mozilla.components.lib.state.Middleware
|
||||||
|
@ -23,7 +27,6 @@ class MetricsMiddleware(
|
||||||
private fun handleAction(action: AppAction) = when (action) {
|
private fun handleAction(action: AppAction) = when (action) {
|
||||||
is AppAction.ResumedMetricsAction -> {
|
is AppAction.ResumedMetricsAction -> {
|
||||||
metrics.track(Event.GrowthData.SetAsDefault)
|
metrics.track(Event.GrowthData.SetAsDefault)
|
||||||
metrics.track(Event.GrowthData.FirstAppOpenForDay)
|
|
||||||
metrics.track(Event.GrowthData.FirstWeekSeriesActivity)
|
metrics.track(Event.GrowthData.FirstWeekSeriesActivity)
|
||||||
}
|
}
|
||||||
else -> Unit
|
else -> Unit
|
||||||
|
|
|
@ -47,21 +47,20 @@ internal class DefaultMetricsStorage(
|
||||||
*/
|
*/
|
||||||
override suspend fun shouldTrack(event: Event): Boolean =
|
override suspend fun shouldTrack(event: Event): Boolean =
|
||||||
withContext(dispatcher) {
|
withContext(dispatcher) {
|
||||||
// The side-effect of storing days of use needs to happen during the first two days after
|
// The side-effect of storing days of use always needs to happen.
|
||||||
// install, which would normally be skipped by shouldSendGenerally.
|
|
||||||
updateDaysOfUse()
|
updateDaysOfUse()
|
||||||
|
val currentTime = System.currentTimeMillis()
|
||||||
shouldSendGenerally() && when (event) {
|
shouldSendGenerally() && when (event) {
|
||||||
Event.GrowthData.SetAsDefault -> {
|
Event.GrowthData.SetAsDefault -> {
|
||||||
!settings.setAsDefaultGrowthSent && checkDefaultBrowser()
|
currentTime.duringFirstMonth() &&
|
||||||
}
|
!settings.setAsDefaultGrowthSent &&
|
||||||
Event.GrowthData.FirstAppOpenForDay -> {
|
checkDefaultBrowser()
|
||||||
settings.resumeGrowthLastSent.hasBeenMoreThanDaySince()
|
|
||||||
}
|
|
||||||
Event.GrowthData.FirstUriLoadForDay -> {
|
|
||||||
settings.uriLoadGrowthLastSent.hasBeenMoreThanDaySince()
|
|
||||||
}
|
}
|
||||||
Event.GrowthData.FirstWeekSeriesActivity -> {
|
Event.GrowthData.FirstWeekSeriesActivity -> {
|
||||||
shouldTrackFirstWeekActivity()
|
currentTime.duringFirstMonth() && shouldTrackFirstWeekActivity()
|
||||||
|
}
|
||||||
|
Event.GrowthData.SerpAdClicked -> {
|
||||||
|
currentTime.duringFirstMonth() && !settings.adClickGrowthSent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,15 +70,12 @@ internal class DefaultMetricsStorage(
|
||||||
Event.GrowthData.SetAsDefault -> {
|
Event.GrowthData.SetAsDefault -> {
|
||||||
settings.setAsDefaultGrowthSent = true
|
settings.setAsDefaultGrowthSent = true
|
||||||
}
|
}
|
||||||
Event.GrowthData.FirstAppOpenForDay -> {
|
|
||||||
settings.resumeGrowthLastSent = System.currentTimeMillis()
|
|
||||||
}
|
|
||||||
Event.GrowthData.FirstUriLoadForDay -> {
|
|
||||||
settings.uriLoadGrowthLastSent = System.currentTimeMillis()
|
|
||||||
}
|
|
||||||
Event.GrowthData.FirstWeekSeriesActivity -> {
|
Event.GrowthData.FirstWeekSeriesActivity -> {
|
||||||
settings.firstWeekSeriesGrowthSent = true
|
settings.firstWeekSeriesGrowthSent = true
|
||||||
}
|
}
|
||||||
|
Event.GrowthData.SerpAdClicked -> {
|
||||||
|
settings.adClickGrowthSent = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,13 +83,13 @@ internal class DefaultMetricsStorage(
|
||||||
val daysOfUse = settings.firstWeekDaysOfUseGrowthData
|
val daysOfUse = settings.firstWeekDaysOfUseGrowthData
|
||||||
val currentDate = Calendar.getInstance(Locale.US)
|
val currentDate = Calendar.getInstance(Locale.US)
|
||||||
val currentDateString = dateFormatter.format(currentDate.time)
|
val currentDateString = dateFormatter.format(currentDate.time)
|
||||||
if (currentDate.timeInMillis.withinFirstWeek() && daysOfUse.none { it == currentDateString }) {
|
if (currentDate.timeInMillis.duringFirstWeek() && daysOfUse.none { it == currentDateString }) {
|
||||||
settings.firstWeekDaysOfUseGrowthData = daysOfUse + currentDateString
|
settings.firstWeekDaysOfUseGrowthData = daysOfUse + currentDateString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldTrackFirstWeekActivity(): Boolean = Result.runCatching {
|
private fun shouldTrackFirstWeekActivity(): Boolean = Result.runCatching {
|
||||||
if (!System.currentTimeMillis().withinFirstWeek() || settings.firstWeekSeriesGrowthSent) {
|
if (!System.currentTimeMillis().duringFirstWeek() || settings.firstWeekSeriesGrowthSent) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,14 +117,13 @@ internal class DefaultMetricsStorage(
|
||||||
return false
|
return false
|
||||||
}.getOrDefault(false)
|
}.getOrDefault(false)
|
||||||
|
|
||||||
private fun Long.hasBeenMoreThanDaySince(): Boolean =
|
|
||||||
System.currentTimeMillis() - this > dayMillis
|
|
||||||
|
|
||||||
private fun Long.toCalendar(): Calendar = Calendar.getInstance(Locale.US).also { calendar ->
|
private fun Long.toCalendar(): Calendar = Calendar.getInstance(Locale.US).also { calendar ->
|
||||||
calendar.timeInMillis = this
|
calendar.timeInMillis = this
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Long.withinFirstWeek() = this < getInstalledTime() + fullWeekMillis
|
private fun Long.duringFirstWeek() = this < getInstalledTime() + fullWeekMillis
|
||||||
|
|
||||||
|
private fun Long.duringFirstMonth() = this < getInstalledTime() + shortestMonthMillis
|
||||||
|
|
||||||
private fun Calendar.createNextDay() = (this.clone() as Calendar).also { calendar ->
|
private fun Calendar.createNextDay() = (this.clone() as Calendar).also { calendar ->
|
||||||
calendar.add(Calendar.DAY_OF_MONTH, 1)
|
calendar.add(Calendar.DAY_OF_MONTH, 1)
|
||||||
|
@ -136,8 +131,7 @@ internal class DefaultMetricsStorage(
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val dayMillis: Long = 1000 * 60 * 60 * 24
|
private const val dayMillis: Long = 1000 * 60 * 60 * 24
|
||||||
private const val windowStartMillis: Long = dayMillis * 2
|
private const val shortestMonthMillis: Long = dayMillis * 28
|
||||||
private const val windowEndMillis: Long = dayMillis * 28
|
|
||||||
|
|
||||||
// Note this is 8 so that recording of FirstWeekSeriesActivity happens throughout the length
|
// Note this is 8 so that recording of FirstWeekSeriesActivity happens throughout the length
|
||||||
// of the 7th day after install
|
// of the 7th day after install
|
||||||
|
@ -146,17 +140,11 @@ internal class DefaultMetricsStorage(
|
||||||
/**
|
/**
|
||||||
* Determines whether events should be tracked based on some general criteria:
|
* Determines whether events should be tracked based on some general criteria:
|
||||||
* - user has installed as a result of a campaign
|
* - user has installed as a result of a campaign
|
||||||
* - user is within 2-28 days of install
|
|
||||||
* - tracking is still enabled through Nimbus
|
* - tracking is still enabled through Nimbus
|
||||||
*/
|
*/
|
||||||
fun shouldSendGenerally(context: Context): Boolean {
|
fun shouldSendGenerally(context: Context): Boolean {
|
||||||
val installedTime = getInstalledTime(context)
|
|
||||||
val timeDifference = System.currentTimeMillis() - installedTime
|
|
||||||
val withinWindow = timeDifference in windowStartMillis..windowEndMillis
|
|
||||||
|
|
||||||
return context.settings().adjustCampaignId.isNotEmpty() &&
|
return context.settings().adjustCampaignId.isNotEmpty() &&
|
||||||
FxNimbus.features.growthData.value().enabled &&
|
FxNimbus.features.growthData.value().enabled
|
||||||
withinWindow
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getInstalledTime(context: Context): Long = context.packageManager
|
fun getInstalledTime(context: Context): Long = context.packageManager
|
||||||
|
|
|
@ -21,7 +21,6 @@ import mozilla.components.support.base.android.Clock
|
||||||
import mozilla.components.support.base.log.logger.Logger
|
import mozilla.components.support.base.log.logger.Logger
|
||||||
import org.mozilla.fenix.GleanMetrics.Events
|
import org.mozilla.fenix.GleanMetrics.Events
|
||||||
import org.mozilla.fenix.GleanMetrics.Metrics
|
import org.mozilla.fenix.GleanMetrics.Metrics
|
||||||
import org.mozilla.fenix.components.metrics.Event
|
|
||||||
import org.mozilla.fenix.components.metrics.MetricController
|
import org.mozilla.fenix.components.metrics.MetricController
|
||||||
import org.mozilla.fenix.utils.Settings
|
import org.mozilla.fenix.utils.Settings
|
||||||
import org.mozilla.fenix.GleanMetrics.EngineTab as EngineMetrics
|
import org.mozilla.fenix.GleanMetrics.EngineTab as EngineMetrics
|
||||||
|
@ -60,9 +59,6 @@ class TelemetryMiddleware(
|
||||||
val tab = context.state.findTabOrCustomTab(action.tabId)
|
val tab = context.state.findTabOrCustomTab(action.tabId)
|
||||||
onEngineSessionKilled(context.state, tab)
|
onEngineSessionKilled(context.state, tab)
|
||||||
}
|
}
|
||||||
is EngineAction.LoadUrlAction -> {
|
|
||||||
metrics.track(Event.GrowthData.FirstUriLoadForDay)
|
|
||||||
}
|
|
||||||
else -> {
|
else -> {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
|
@ -1503,16 +1503,6 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
||||||
default = false,
|
default = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
var resumeGrowthLastSent by longPreference(
|
|
||||||
key = appContext.getPreferenceKey(R.string.pref_key_growth_resume_last_sent),
|
|
||||||
default = 0,
|
|
||||||
)
|
|
||||||
|
|
||||||
var uriLoadGrowthLastSent by longPreference(
|
|
||||||
key = appContext.getPreferenceKey(R.string.pref_key_growth_uri_load_last_sent),
|
|
||||||
default = 0,
|
|
||||||
)
|
|
||||||
|
|
||||||
var firstWeekSeriesGrowthSent by booleanPreference(
|
var firstWeekSeriesGrowthSent by booleanPreference(
|
||||||
key = appContext.getPreferenceKey(R.string.pref_key_growth_first_week_series_sent),
|
key = appContext.getPreferenceKey(R.string.pref_key_growth_first_week_series_sent),
|
||||||
default = false,
|
default = false,
|
||||||
|
@ -1522,4 +1512,9 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
||||||
key = appContext.getPreferenceKey(R.string.pref_key_growth_first_week_days_of_use),
|
key = appContext.getPreferenceKey(R.string.pref_key_growth_first_week_days_of_use),
|
||||||
default = setOf(),
|
default = setOf(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var adClickGrowthSent by booleanPreference(
|
||||||
|
key = appContext.getPreferenceKey(R.string.pref_key_growth_ad_click_sent),
|
||||||
|
default = false,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,8 +318,7 @@
|
||||||
|
|
||||||
<!-- Growth Data -->
|
<!-- Growth Data -->
|
||||||
<string name="pref_key_growth_set_as_default" translatable="false">pref_key_growth_set_as_default</string>
|
<string name="pref_key_growth_set_as_default" translatable="false">pref_key_growth_set_as_default</string>
|
||||||
<string name="pref_key_growth_resume_last_sent" translatable="false">pref_key_growth_last_resumed</string>
|
|
||||||
<string name="pref_key_growth_uri_load_last_sent" translatable="false">pref_key_growth_uri_load_last_sent</string>
|
|
||||||
<string name="pref_key_growth_first_week_series_sent" translatable="false">pref_key_growth_first_week_series_sent</string>
|
<string name="pref_key_growth_first_week_series_sent" translatable="false">pref_key_growth_first_week_series_sent</string>
|
||||||
<string name="pref_key_growth_first_week_days_of_use" translatable="false">pref_key_growth_first_week_days_of_use</string>
|
<string name="pref_key_growth_first_week_days_of_use" translatable="false">pref_key_growth_first_week_days_of_use</string>
|
||||||
|
<string name="pref_key_growth_ad_click_sent" translatable="false">pref_key_growth_ad_click_sent</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -100,68 +100,6 @@ class DefaultMetricsStorageTest {
|
||||||
assertTrue(updateSlot.captured)
|
assertTrue(updateSlot.captured)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `GIVEN that it has been less than 24 hours since last resumed sent WHEN checked for sending THEN will not be sent`() = runTest(dispatcher) {
|
|
||||||
val currentTime = System.currentTimeMillis()
|
|
||||||
every { settings.resumeGrowthLastSent } returns currentTime
|
|
||||||
|
|
||||||
val result = storage.shouldTrack(Event.GrowthData.FirstAppOpenForDay)
|
|
||||||
|
|
||||||
assertFalse(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `GIVEN that it has been more than 24 hours since last resumed sent WHEN checked for sending THEN will be sent`() = runTest(dispatcher) {
|
|
||||||
val currentTime = System.currentTimeMillis()
|
|
||||||
every { settings.resumeGrowthLastSent } returns currentTime - 1000 * 60 * 60 * 24 * 2
|
|
||||||
|
|
||||||
val result = storage.shouldTrack(Event.GrowthData.FirstAppOpenForDay)
|
|
||||||
|
|
||||||
assertTrue(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `WHEN last resumed state updated THEN settings updated accordingly`() = runTest(dispatcher) {
|
|
||||||
val updateSlot = slot<Long>()
|
|
||||||
every { settings.resumeGrowthLastSent } returns 0
|
|
||||||
every { settings.resumeGrowthLastSent = capture(updateSlot) } returns Unit
|
|
||||||
|
|
||||||
storage.updateSentState(Event.GrowthData.FirstAppOpenForDay)
|
|
||||||
|
|
||||||
assertTrue(updateSlot.captured > 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `GIVEN that it has been less than 24 hours since uri load sent WHEN checked for sending THEN will not be sent`() = runTest(dispatcher) {
|
|
||||||
val currentTime = System.currentTimeMillis()
|
|
||||||
every { settings.uriLoadGrowthLastSent } returns currentTime
|
|
||||||
|
|
||||||
val result = storage.shouldTrack(Event.GrowthData.FirstUriLoadForDay)
|
|
||||||
|
|
||||||
assertFalse(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `GIVEN that it has been more than 24 hours since uri load sent WHEN checked for sending THEN will be sent`() = runTest(dispatcher) {
|
|
||||||
val currentTime = System.currentTimeMillis()
|
|
||||||
every { settings.uriLoadGrowthLastSent } returns currentTime - 1000 * 60 * 60 * 24 * 2
|
|
||||||
|
|
||||||
val result = storage.shouldTrack(Event.GrowthData.FirstUriLoadForDay)
|
|
||||||
|
|
||||||
assertTrue(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `WHEN uri load updated THEN settings updated accordingly`() = runTest(dispatcher) {
|
|
||||||
val updateSlot = slot<Long>()
|
|
||||||
every { settings.uriLoadGrowthLastSent } returns 0
|
|
||||||
every { settings.uriLoadGrowthLastSent = capture(updateSlot) } returns Unit
|
|
||||||
|
|
||||||
storage.updateSentState(Event.GrowthData.FirstUriLoadForDay)
|
|
||||||
|
|
||||||
assertTrue(updateSlot.captured > 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `GIVEN that app has been used for less than 3 days in a row WHEN checked for first week activity THEN event will not be sent`() = runTest(dispatcher) {
|
fun `GIVEN that app has been used for less than 3 days in a row WHEN checked for first week activity THEN event will not be sent`() = runTest(dispatcher) {
|
||||||
val tomorrow = calendarStart.createNextDay()
|
val tomorrow = calendarStart.createNextDay()
|
||||||
|
@ -273,6 +211,24 @@ class DefaultMetricsStorageTest {
|
||||||
assertFalse(captureSlot.isCaptured)
|
assertFalse(captureSlot.isCaptured)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN serp ad clicked event already sent WHEN checking to track serp ad clicked THEN event will not be sent`() = runTest(dispatcher) {
|
||||||
|
every { settings.adClickGrowthSent } returns true
|
||||||
|
|
||||||
|
val result = storage.shouldTrack(Event.GrowthData.SerpAdClicked)
|
||||||
|
|
||||||
|
assertFalse(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN serp ad clicked event not sent WHEN checking to track serp ad clicked THEN event will be sent`() = runTest(dispatcher) {
|
||||||
|
every { settings.adClickGrowthSent } returns false
|
||||||
|
|
||||||
|
val result = storage.shouldTrack(Event.GrowthData.SerpAdClicked)
|
||||||
|
|
||||||
|
assertTrue(result)
|
||||||
|
}
|
||||||
|
|
||||||
private fun Calendar.copy() = clone() as Calendar
|
private fun Calendar.copy() = clone() as Calendar
|
||||||
private fun Calendar.createNextDay() = copy().apply {
|
private fun Calendar.createNextDay() = copy().apply {
|
||||||
add(Calendar.DAY_OF_MONTH, 1)
|
add(Calendar.DAY_OF_MONTH, 1)
|
||||||
|
|
|
@ -6,7 +6,6 @@ package org.mozilla.fenix.telemetry
|
||||||
|
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.verify
|
|
||||||
import mozilla.components.browser.state.action.ContentAction
|
import mozilla.components.browser.state.action.ContentAction
|
||||||
import mozilla.components.browser.state.action.EngineAction
|
import mozilla.components.browser.state.action.EngineAction
|
||||||
import mozilla.components.browser.state.action.TabListAction
|
import mozilla.components.browser.state.action.TabListAction
|
||||||
|
@ -33,7 +32,6 @@ import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mozilla.fenix.GleanMetrics.Events
|
import org.mozilla.fenix.GleanMetrics.Events
|
||||||
import org.mozilla.fenix.GleanMetrics.Metrics
|
import org.mozilla.fenix.GleanMetrics.Metrics
|
||||||
import org.mozilla.fenix.components.metrics.Event
|
|
||||||
import org.mozilla.fenix.components.metrics.MetricController
|
import org.mozilla.fenix.components.metrics.MetricController
|
||||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
import org.mozilla.fenix.utils.Settings
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
@ -352,13 +350,6 @@ class TelemetryMiddlewareTest {
|
||||||
assertNull(EngineMetrics.killForegroundAge.testGetValue())
|
assertNull(EngineMetrics.killForegroundAge.testGetValue())
|
||||||
assertEquals(600_000_000, EngineMetrics.killBackgroundAge.testGetValue()!!.sum)
|
assertEquals(600_000_000, EngineMetrics.killBackgroundAge.testGetValue()!!.sum)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `WHEN uri loaded to engine THEN matching event is sent to metrics`() {
|
|
||||||
store.dispatch(EngineAction.LoadUrlAction("", "")).joinBlocking()
|
|
||||||
|
|
||||||
verify { metrics.track(Event.GrowthData.FirstUriLoadForDay) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class FakeClock : Clock.Delegate {
|
internal class FakeClock : Clock.Delegate {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user