Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create base branch for behavioral toast report #5171

Merged
merged 59 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
12e4927
Create base branch for behavioral toast report
CrisBarreiro Oct 22, 2024
79950e2
Add FF for enabling behavioral toast report
CrisBarreiro Oct 22, 2024
c92e3b5
Rename BrokenSitePromptDataStoreModule
CrisBarreiro Nov 7, 2024
ad1c50f
Migrate getMaxDismissStreak to Flow
CrisBarreiro Nov 7, 2024
38be613
Rename (2)
CrisBarreiro Nov 7, 2024
6f89d79
Migrate BrokenSiteDataStore to use regular flows
CrisBarreiro Nov 7, 2024
3ab2935
Remove unnecessary dispatcher
CrisBarreiro Nov 7, 2024
1de24ea
Create toast UI
CrisBarreiro Oct 22, 2024
762bdca
Add banner to onboarding and handle clicks
CrisBarreiro Oct 24, 2024
a23c4bd
Only show broken site prompt if RC is on
CrisBarreiro Oct 28, 2024
e7cdcab
Add click logic
CrisBarreiro Oct 28, 2024
7ca5476
Remove pixels
CrisBarreiro Oct 29, 2024
f375c74
Fix buttons margin
CrisBarreiro Oct 29, 2024
45f007b
Fix CI issues
CrisBarreiro Oct 30, 2024
29d45be
Fix failing test
CrisBarreiro Oct 30, 2024
cd43fdb
Make isFeatureEnabled a suspend function
CrisBarreiro Nov 6, 2024
e8036b3
Fix banner background
CrisBarreiro Nov 6, 2024
3023e68
Migrate from StateFlow to Flow
CrisBarreiro Nov 7, 2024
58992c5
Handle user refreshes
CrisBarreiro Oct 29, 2024
1ce477b
Fix dialog not being dismissed when switching tabs or navigating via …
CrisBarreiro Oct 31, 2024
8dbca65
Determine refreshes using URL comparison
CrisBarreiro Nov 5, 2024
da3072c
Fix tests
CrisBarreiro Nov 5, 2024
79e4392
Rename method
CrisBarreiro Nov 5, 2024
e3cda7d
Do not show prompt on DDG sites
CrisBarreiro Oct 31, 2024
f6831a2
Simplify testing
CrisBarreiro Nov 5, 2024
02ae3d3
Fix tests
CrisBarreiro Nov 5, 2024
30a65a8
Remove comment
CrisBarreiro Nov 5, 2024
a73b831
Add logs and remove testing tweaks
CrisBarreiro Nov 5, 2024
0270368
Fix tests
CrisBarreiro Nov 5, 2024
daf78c7
Fix dismiss streak
CrisBarreiro Nov 6, 2024
298f35e
Dismiss prompt when URL changed
CrisBarreiro Nov 7, 2024
c6f17e1
Remove debug/test logs
CrisBarreiro Nov 7, 2024
2836259
Disable old protections popup
CrisBarreiro Nov 12, 2024
5c0ebc9
Add pixels and remove ATB
CrisBarreiro Nov 5, 2024
e460197
Test pixels fired
CrisBarreiro Nov 5, 2024
72728c9
Remove m prefix from pixel
CrisBarreiro Nov 7, 2024
8f0963f
Update copy and request translations
CrisBarreiro Nov 8, 2024
62753df
Fix strings file
CrisBarreiro Nov 12, 2024
11b2b1f
Translate strings-broken-site to values-lt
daxmobile Nov 12, 2024
2f495ae
Translate strings-broken-site to values-nb
daxmobile Nov 12, 2024
7094325
Translate strings-broken-site to values-bg
daxmobile Nov 12, 2024
3dca692
Translate strings-broken-site to values-cs
daxmobile Nov 12, 2024
3977911
Translate strings-broken-site to values-ro
daxmobile Nov 12, 2024
c16acb2
Translate strings-broken-site to values-et
daxmobile Nov 13, 2024
012fd96
Translate strings to values-sk
daxmobile Nov 15, 2024
e057c92
Translate strings to values-es
daxmobile Nov 15, 2024
22eef30
Translate strings to values-nl
daxmobile Nov 15, 2024
0120980
Translate strings to values-sl
daxmobile Nov 15, 2024
64f761e
Translate strings to values-lt
daxmobile Nov 15, 2024
41683f7
Translate strings to values-da
daxmobile Nov 15, 2024
38d3fa9
Translate strings to values-sv
daxmobile Nov 15, 2024
f8dfbb8
Translate strings to values-hu
daxmobile Nov 15, 2024
5040fa0
Translate strings to values-et
daxmobile Nov 16, 2024
2ff3573
Translate strings to values-ru
daxmobile Nov 16, 2024
a443479
Translate strings to values-bg
daxmobile Nov 16, 2024
4cde35a
Translate strings to values-fr
daxmobile Nov 17, 2024
c503da4
Translate strings to values-hr
daxmobile Nov 17, 2024
947907f
Translate strings to values-el
daxmobile Nov 18, 2024
a87f64d
Remove TODO
CrisBarreiro Nov 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Do not show prompt on DDG sites
  • Loading branch information
CrisBarreiro committed Nov 18, 2024
commit e3cda7ddcafd58005441a10825dc0da06744f91c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class CtaViewModelTest {
whenever(mockDuckPlayer.getUserPreferences()).thenReturn(UserPreferences(false, AlwaysAsk))
whenever(mockDuckPlayer.isYouTubeUrl(any())).thenReturn(false)
whenever(mockDuckPlayer.isSimulatedYoutubeNoCookie(any())).thenReturn(false)
whenever(mockBrokenSitePrompt.shouldShowBrokenSitePrompt()).thenReturn(false)
whenever(mockBrokenSitePrompt.shouldShowBrokenSitePrompt(any())).thenReturn(false)
whenever(mockBrokenSitePrompt.isFeatureEnabled()).thenReturn(false)

testee = CtaViewModel(
Expand Down Expand Up @@ -180,26 +180,26 @@ class CtaViewModelTest {
}

@Test
fun whenCtaShownAndCtaIsDaxAndCanNotSendPixelThenPixelIsNotFired() {
fun whenCtaShownAndCtaIsDaxAndCanNotSendPixelThenPixelIsNotFired() = runTest {
testee.onCtaShown(DaxBubbleCta.DaxIntroSearchOptionsCta(mockOnboardingStore, mockAppInstallStore))
verify(mockPixel, never()).fire(eq(SURVEY_CTA_SHOWN), any(), any(), eq(Count))
}

@Test
fun whenCtaShownAndCtaIsDaxAndCanSendPixelThenPixelIsFired() {
fun whenCtaShownAndCtaIsDaxAndCanSendPixelThenPixelIsFired() = runTest {
whenever(mockOnboardingStore.onboardingDialogJourney).thenReturn("s:0")
testee.onCtaShown(DaxBubbleCta.DaxEndCta(mockOnboardingStore, mockAppInstallStore))
verify(mockPixel, never()).fire(eq(SURVEY_CTA_SHOWN), any(), any(), eq(Count))
}

@Test
fun whenCtaShownAndCtaIsNotDaxThenPixelIsFired() {
fun whenCtaShownAndCtaIsNotDaxThenPixelIsFired() = runTest {
testee.onCtaShown(HomePanelCta.AddWidgetAuto)
verify(mockPixel).fire(eq(WIDGET_CTA_SHOWN), any(), any(), eq(Count))
}

@Test
fun whenCtaLaunchedPixelIsFired() {
fun whenCtaLaunchedPixelIsFired() = runTest {
testee.onUserClickCtaOkButton(HomePanelCta.AddWidgetAuto)
verify(mockPixel).fire(eq(WIDGET_CTA_LAUNCHED), any(), any(), eq(Count))
}
Expand Down Expand Up @@ -284,7 +284,7 @@ class CtaViewModelTest {
@Test
fun whenRefreshCtaWhileBrowsingAndHideTipsIsTrueAndShouldShowBrokenSitePromptThenReturnBrokenSitePrompt() = runTest {
whenever(mockSettingsDataStore.hideTips).thenReturn(true)
whenever(mockBrokenSitePrompt.shouldShowBrokenSitePrompt()).thenReturn(true)
whenever(mockBrokenSitePrompt.shouldShowBrokenSitePrompt(any())).thenReturn(true)
val site = site(url = "http://www.facebook.com", entity = TestEntity("Facebook", "Facebook", 9.0))

val value = testee.refreshCta(coroutineRule.testDispatcher, isBrowserShowing = true, site = site)
Expand Down Expand Up @@ -685,14 +685,14 @@ class CtaViewModelTest {
}

@Test
fun whenCtaShownIfCtaIsNotMarkedAsReadOnShowThenCtaNotInsertedInDatabase() {
fun whenCtaShownIfCtaIsNotMarkedAsReadOnShowThenCtaNotInsertedInDatabase() = runTest {
testee.onCtaShown(OnboardingDaxDialogCta.DaxSerpCta(mockOnboardingStore, mockAppInstallStore))

verify(mockDismissedCtaDao, never()).insert(DismissedCta(CtaId.DAX_DIALOG_SERP))
}

@Test
fun whenCtaShownIfCtaIsMarkedAsReadOnShowThenCtaInsertedInDatabase() {
fun whenCtaShownIfCtaIsMarkedAsReadOnShowThenCtaInsertedInDatabase() = runTest {
testee.onCtaShown(OnboardingDaxDialogCta.DaxEndCta(mockOnboardingStore, mockAppInstallStore, mockSettingsDataStore))

verify(mockDismissedCtaDao).insert(DismissedCta(CtaId.DAX_END))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2661,7 +2661,9 @@ class BrowserTabViewModel @Inject constructor(
}

fun onUserClickCtaOkButton(cta: Cta) {
ctaViewModel.onUserClickCtaOkButton(cta)
viewModelScope.launch {
ctaViewModel.onUserClickCtaOkButton(cta)
}
val onboardingCommand = when (cta) {
is HomePanelCta.AddWidgetAuto, is HomePanelCta.AddWidgetInstructions -> LaunchAddWidget
is OnboardingDaxDialogCta -> onOnboardingCtaOkButtonClicked(cta)
Expand Down Expand Up @@ -3423,7 +3425,6 @@ class BrowserTabViewModel @Inject constructor(
}

private fun onBrokenSiteCtaDismissButtonClicked(cta: BrokenSitePromptDialogCta): Command? {
onUserDismissedCta(cta)
viewModelScope.launch {
command.value = HideBrokenSitePromptCta(cta)
}
Expand Down
18 changes: 15 additions & 3 deletions app/src/main/java/com/duckduckgo/app/cta/ui/CtaViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class CtaViewModel @Inject constructor(
}
}

fun onCtaShown(cta: Cta) {
suspend fun onCtaShown(cta: Cta) {
cta.shownPixel?.let {
val canSendPixel = when (cta) {
is DaxCta -> cta.canSendShownPixel()
Expand All @@ -130,6 +130,10 @@ class CtaViewModel @Inject constructor(
if (cta is OnboardingDaxDialogCta && cta.markAsReadOnShow) {
dismissedCtaDao.insert(DismissedCta(cta.ctaId))
}

if (cta is BrokenSitePromptDialogCta) {
brokenSitePrompt.ctaShown()
}
}

suspend fun registerDaxBubbleCtaDismissed(cta: Cta) {
Expand All @@ -150,6 +154,10 @@ class CtaViewModel @Inject constructor(

suspend fun onUserDismissedCta(cta: Cta) {
withContext(dispatchers.io()) {
if (cta is BrokenSitePromptDialogCta) {
brokenSitePrompt.userDismissedPrompt()
}

cta.cancelPixel?.let {
pixel.fire(it, cta.pixelCancelParameters())
}
Expand All @@ -160,10 +168,14 @@ class CtaViewModel @Inject constructor(
}
}

fun onUserClickCtaOkButton(cta: Cta) {
suspend fun onUserClickCtaOkButton(cta: Cta) {
cta.okPixel?.let {
pixel.fire(it, cta.pixelOkParameters())
}

if (cta is BrokenSitePromptDialogCta) {
brokenSitePrompt.userAcceptedPrompt()
}
}

suspend fun refreshCta(
Expand Down Expand Up @@ -303,7 +315,7 @@ class CtaViewModel @Inject constructor(
}

if (!canShowOnboardingDaxDialogCta()) {
return if (withContext(dispatchers.io()) { brokenSitePrompt.shouldShowBrokenSitePrompt() }) {
return if (brokenSitePrompt.shouldShowBrokenSitePrompt(nonNullSite.url)) {
BrokenSitePromptDialogCta()
} else {
null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,7 @@ interface BrokenSitePrompt {

fun getUserRefreshesCount(): Int

suspend fun shouldShowBrokenSitePrompt(): Boolean
suspend fun shouldShowBrokenSitePrompt(url: String): Boolean

suspend fun ctaShown()
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import com.duckduckgo.app.di.AppCoroutineScope
import com.duckduckgo.brokensite.impl.SharedPreferencesDuckPlayerDataStore.Keys.COOL_DOWN_DAYS
Expand Down Expand Up @@ -47,8 +48,8 @@ interface BrokenSitePomptDataStore {
suspend fun setDismissStreakResetDays(days: Int)
suspend fun getDismissStreakResetDays(): Int

suspend fun setCoolDownDays(days: Int)
suspend fun getCoolDownDays(): Int
suspend fun setCoolDownDays(days: Long)
suspend fun getCoolDownDays(): Long
suspend fun setDismissStreak(streak: Int)
suspend fun getDismissStreak(): Int
suspend fun setNextShownDate(nextShownDate: LocalDate?)
Expand All @@ -65,7 +66,7 @@ class SharedPreferencesDuckPlayerDataStore @Inject constructor(
private object Keys {
val MAX_DISMISS_STREAK = intPreferencesKey(name = "MAX_DISMISS_STREAK")
val DISMISS_STREAK_RESET_DAYS = intPreferencesKey(name = "DISMISS_STREAK_RESET_DAYS")
val COOL_DOWN_DAYS = intPreferencesKey(name = "COOL_DOWN_DAYS")
val COOL_DOWN_DAYS = longPreferencesKey(name = "COOL_DOWN_DAYS")
val DISMISS_STREAK = intPreferencesKey(name = "DISMISS_STREAK")
val NEXT_SHOWN_DATE = stringPreferencesKey(name = "NEXT_SHOWN_DATE")
}
Expand All @@ -84,11 +85,10 @@ class SharedPreferencesDuckPlayerDataStore @Inject constructor(
}
.distinctUntilChanged()

private val coolDownDays: Flow<Int> = store.data
private val coolDownDays: Flow<Long> = store.data
.map { prefs ->
prefs[COOL_DOWN_DAYS] ?: 7
}
.distinctUntilChanged()

private val dismissStreak: Flow<Int> = store.data
.map { prefs ->
Expand All @@ -114,11 +114,11 @@ class SharedPreferencesDuckPlayerDataStore @Inject constructor(

override suspend fun getDismissStreakResetDays(): Int = dismissStreakResetDays.first()

override suspend fun setCoolDownDays(days: Int) {
override suspend fun setCoolDownDays(days: Long) {
store.edit { prefs -> prefs[COOL_DOWN_DAYS] = days }
}

override suspend fun getCoolDownDays(): Int = coolDownDays.first()
override suspend fun getCoolDownDays(): Long = coolDownDays.first()

override suspend fun setDismissStreak(streak: Int) {
store.edit { prefs -> prefs[DISMISS_STREAK] = streak }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ interface BrokenSiteReportRepository {
suspend fun setDismissStreakResetDays(days: Int)
suspend fun getDismissStreakResetDays(): Int

suspend fun setCoolDownDays(days: Int)
suspend fun getCoolDownDays(): Int
suspend fun setCoolDownDays(days: Long)
suspend fun getCoolDownDays(): Long

suspend fun setBrokenSitePromptRCSettings(maxDismissStreak: Int, dismissStreakResetDays: Int, coolDownDays: Int)

Expand All @@ -56,6 +56,7 @@ interface BrokenSiteReportRepository {
suspend fun incrementDismissStreak()
suspend fun getDismissStreak(): Int
suspend fun resetDismissStreak()

fun resetRefreshCount()
fun addRefresh(url: Uri, localDateTime: LocalDateTime)
fun getAndUpdateUserRefreshesBetween(t1: LocalDateTime, t2: LocalDateTime): Int
Expand Down Expand Up @@ -113,11 +114,11 @@ class RealBrokenSiteReportRepository(
override suspend fun getDismissStreakResetDays(): Int =
brokenSitePromptDataStore.getDismissStreakResetDays()

override suspend fun setCoolDownDays(days: Int) {
override suspend fun setCoolDownDays(days: Long) {
brokenSitePromptDataStore.setCoolDownDays(days)
}

override suspend fun getCoolDownDays(): Int =
override suspend fun getCoolDownDays(): Long =
brokenSitePromptDataStore.getCoolDownDays()

override suspend fun setBrokenSitePromptRCSettings(
Expand All @@ -127,7 +128,7 @@ class RealBrokenSiteReportRepository(
) {
setMaxDismissStreak(maxDismissStreak)
setDismissStreakResetDays(dismissStreakResetDays)
setCoolDownDays(coolDownDays)
setCoolDownDays(coolDownDays.toLong())
}

override suspend fun resetDismissStreak() {
Expand All @@ -136,6 +137,7 @@ class RealBrokenSiteReportRepository(

override suspend fun setNextShownDate(nextShownDate: LocalDate?) {
brokenSitePromptDataStore.setNextShownDate(nextShownDate)
// Log.d("BrokenSitePrompt", "Next shown date set to $nextShownDate")
}

override suspend fun getDismissStreak(): Int {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
package com.duckduckgo.brokensite.impl

import android.net.Uri
import android.util.Log
import androidx.annotation.VisibleForTesting
import com.duckduckgo.app.browser.DuckDuckGoUrlDetector
import com.duckduckgo.brokensite.api.BrokenSitePrompt
import com.duckduckgo.common.utils.CurrentTimeProvider
import com.duckduckgo.di.scopes.AppScope
import com.squareup.anvil.annotations.ContributesBinding
import java.time.LocalDate
import javax.inject.Inject

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
Expand All @@ -36,30 +37,32 @@ class RealBrokenSitePrompt @Inject constructor(
private val brokenSiteReportRepository: BrokenSiteReportRepository,
private val brokenSitePromptRCFeature: BrokenSitePromptRCFeature,
private val currentTimeProvider: CurrentTimeProvider,
private val duckGoUrlDetector: DuckDuckGoUrlDetector,
) : BrokenSitePrompt {

private val _featureEnabled by lazy { brokenSitePromptRCFeature.self().isEnabled() }

override suspend fun userDismissedPrompt() {
if (!_featureEnabled) return
brokenSiteReportRepository.getNextShownDate()?.let {
if (brokenSiteReportRepository.getDismissStreak() == brokenSiteReportRepository.getMaxDismissStreak() - 1) {
val nextShownDate = brokenSiteReportRepository.getNextShownDate()
val newNextShownDate = LocalDate.now().plusDays(brokenSiteReportRepository.getCoolDownDays().toLong())

if (newNextShownDate.isAfter(nextShownDate)) {
brokenSiteReportRepository.setNextShownDate(newNextShownDate)
}
Log.d("BrokenSitePrompt", "User dismissed prompt, dismiss streak: ${brokenSiteReportRepository.getDismissStreak()}")
if (brokenSiteReportRepository.getDismissStreak() >= brokenSiteReportRepository.getMaxDismissStreak() - 1) {
val nextShownDate = brokenSiteReportRepository.getNextShownDate()
val newNextShownDate = currentTimeProvider.localDateNow().plusDays(brokenSiteReportRepository.getDismissStreakResetDays().toLong())

Log.d("BrokenSitePrompt", "User dismissed. Next shown date: $nextShownDate, new next show date: $newNextShownDate")

if (nextShownDate == null || newNextShownDate.isAfter(nextShownDate)) {
brokenSiteReportRepository.setNextShownDate(newNextShownDate)
}
}
brokenSiteReportRepository.incrementDismissStreak()
}

override suspend fun userAcceptedPrompt() {
if (!_featureEnabled) return
Log.d("BrokenSitePrompt", "User accepted")

brokenSiteReportRepository.resetDismissStreak()
// TODO (cbarreiro) Set next shown date based on limiting logic: https://app.asana.com/0/0/1208572901396846/f
brokenSiteReportRepository.setNextShownDate(null)
}

override suspend fun isFeatureEnabled(): Boolean {
Expand All @@ -83,7 +86,19 @@ class RealBrokenSitePrompt @Inject constructor(
)
}

override suspend fun shouldShowBrokenSitePrompt(): Boolean {
return isFeatureEnabled() && getUserRefreshesCount() >= REFRESH_COUNT_LIMIT
override suspend fun shouldShowBrokenSitePrompt(url: String): Boolean {
return isFeatureEnabled() &&
getUserRefreshesCount() >= REFRESH_COUNT_LIMIT &&
// && brokenSiteReportRepository.getNextShownDate()?.isBefore(currentTimeProvider.localDateNow()) ?: true
!duckGoUrlDetector.isDuckDuckGoUrl(url)
}

override suspend fun ctaShown() {
Log.d("BrokenSitePrompt", "CTA shown")
val nextShownDate = brokenSiteReportRepository.getNextShownDate()?.atStartOfDay()
val newNextShownDate = currentTimeProvider.localDateTimeNow().plusDays(brokenSiteReportRepository.getCoolDownDays())
if (nextShownDate == null || newNextShownDate.isAfter(nextShownDate)) {
brokenSiteReportRepository.setNextShownDate(newNextShownDate.toLocalDate())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class RealBrokenSitePromptTest {
whenever(mockCurrentTimeProvider.localDateTimeNow()).thenReturn(LocalDateTime.now())
whenever(mockBrokenSiteReportRepository.getAndUpdateUserRefreshesBetween(any(), any())).thenReturn(REFRESH_COUNT_LIMIT)

val result = testee.shouldShowBrokenSitePrompt()
val result = testee.shouldShowBrokenSitePrompt(nonNullSite.url)

assertTrue(result)
}
Expand All @@ -155,7 +155,7 @@ class RealBrokenSitePromptTest {
whenever(mockCurrentTimeProvider.localDateTimeNow()).thenReturn(LocalDateTime.now())
whenever(mockBrokenSiteReportRepository.getAndUpdateUserRefreshesBetween(any(), any())).thenReturn(2)

val result = testee.shouldShowBrokenSitePrompt()
val result = testee.shouldShowBrokenSitePrompt(nonNullSite.url)

assertFalse(result)
}
Expand All @@ -165,7 +165,7 @@ class RealBrokenSitePromptTest {
whenever(mockCurrentTimeProvider.localDateTimeNow()).thenReturn(LocalDateTime.now())
fakeBrokenSitePromptRCFeature.self().setRawStoredState(State(false))

val result = testee.shouldShowBrokenSitePrompt()
val result = testee.shouldShowBrokenSitePrompt(nonNullSite.url)

assertFalse(result)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class RealBrokenSiteReportRepositoryTest {

@Test
fun whenCoolDownDaysCalledThenCoolDownDaysIsCalled() = runTest {
val days = 7
val days = 7L

testee.setCoolDownDays(days)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.duckduckgo.common.utils
import android.os.SystemClock
import com.duckduckgo.di.scopes.AppScope
import com.squareup.anvil.annotations.ContributesBinding
import java.time.LocalDate
import java.time.LocalDateTime
import javax.inject.Inject

Expand All @@ -28,6 +29,8 @@ interface CurrentTimeProvider {
fun currentTimeMillis(): Long

fun localDateTimeNow(): LocalDateTime

fun localDateNow(): LocalDate
}

@ContributesBinding(AppScope::class)
Expand All @@ -37,4 +40,6 @@ class RealCurrentTimeProvider @Inject constructor() : CurrentTimeProvider {
override fun currentTimeMillis(): Long = System.currentTimeMillis()

override fun localDateTimeNow(): LocalDateTime = LocalDateTime.now()

override fun localDateNow(): LocalDate = LocalDate.now()
}