Skip to content

Commit be5132b

Browse files
Re-enable use our app experiment (#1156)
1 parent 6206eea commit be5132b

File tree

16 files changed

+409
-53
lines changed

16 files changed

+409
-53
lines changed

app/src/androidTest/java/com/duckduckgo/app/browser/BrowserTabViewModelTest.kt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,14 +1819,6 @@ class BrowserTabViewModelTest {
18191819
verify(mockPixel).fire(cta.shownPixel!!, cta.pixelShownParameters())
18201820
}
18211821

1822-
@Test
1823-
fun whenManualCtaShownThenFirePixel() {
1824-
val cta = HomePanelCta.Survey(Survey("abc", "http://example.com", daysInstalled = 1, status = Survey.Status.SCHEDULED))
1825-
1826-
testee.onManualCtaShown(cta)
1827-
verify(mockPixel).fire(cta.shownPixel!!, cta.pixelShownParameters())
1828-
}
1829-
18301822
@Test
18311823
fun whenRegisterDaxBubbleCtaDismissedThenRegisterInDatabase() = coroutineRule.runBlocking {
18321824
val cta = DaxBubbleCta.DaxIntroCta(mockOnboardingStore, mockAppInstallStore)

app/src/androidTest/java/com/duckduckgo/app/browser/shortcut/ShortcutReceiverTest.kt

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,65 @@
1717
package com.duckduckgo.app.browser.shortcut
1818

1919
import android.content.Intent
20+
import com.duckduckgo.app.CoroutineTestRule
21+
import com.duckduckgo.app.global.events.db.UserEventKey
2022
import com.duckduckgo.app.global.events.db.UserEventsStore
2123
import com.duckduckgo.app.global.useourapp.UseOurAppDetector
2224
import com.duckduckgo.app.pixels.AppPixelName
25+
import com.duckduckgo.app.runBlocking
26+
import com.duckduckgo.app.statistics.Variant
27+
import com.duckduckgo.app.statistics.VariantManager
2328
import com.duckduckgo.app.statistics.pixels.Pixel
2429
import com.nhaarman.mockitokotlin2.mock
30+
import com.nhaarman.mockitokotlin2.never
2531
import com.nhaarman.mockitokotlin2.verify
32+
import com.nhaarman.mockitokotlin2.whenever
33+
import kotlinx.coroutines.ExperimentalCoroutinesApi
2634
import org.junit.Before
35+
import org.junit.Rule
2736
import org.junit.Test
2837

38+
@ExperimentalCoroutinesApi
2939
class ShortcutReceiverTest {
3040

41+
@get:Rule
42+
var coroutinesTestRule = CoroutineTestRule()
43+
3144
private val mockUserEventsStore: UserEventsStore = mock()
3245
private val mockPixel: Pixel = mock()
46+
private val mockVariantManager: VariantManager = mock()
3347
private lateinit var testee: ShortcutReceiver
3448

3549
@Before
3650
fun before() {
37-
testee = ShortcutReceiver(UseOurAppDetector(mockUserEventsStore), mockPixel)
51+
testee = ShortcutReceiver(UseOurAppDetector(mockUserEventsStore), mockPixel, mockUserEventsStore, coroutinesTestRule.testDispatcherProvider, mockVariantManager)
52+
}
53+
54+
@Test
55+
fun whenIntentReceivedIfUrlIsFromUseOurAppDomainAndVariantIsInAppUsageThenRegisterTimestamp() = coroutinesTestRule.runBlocking {
56+
setInAppUsageVariant()
57+
val intent = Intent()
58+
intent.putExtra(ShortcutBuilder.SHORTCUT_URL_ARG, "https://facebook.com")
59+
intent.putExtra(ShortcutBuilder.SHORTCUT_TITLE_ARG, "Title")
60+
testee.onReceive(null, intent)
61+
62+
verify(mockUserEventsStore).registerUserEvent(UserEventKey.USE_OUR_APP_SHORTCUT_ADDED)
63+
}
64+
65+
@Test
66+
fun whenIntentReceivedIfUrlIsFromUseOurAppDomainAndVariantIsNotInAppUsageThenDoNotRegisterTimestamp() = coroutinesTestRule.runBlocking {
67+
setDefaultVariant()
68+
val intent = Intent()
69+
intent.putExtra(ShortcutBuilder.SHORTCUT_URL_ARG, "https://facebook.com")
70+
intent.putExtra(ShortcutBuilder.SHORTCUT_TITLE_ARG, "Title")
71+
testee.onReceive(null, intent)
72+
73+
verify(mockUserEventsStore, never()).registerUserEvent(UserEventKey.USE_OUR_APP_SHORTCUT_ADDED)
3874
}
3975

4076
@Test
4177
fun whenIntentReceivedIfUrlContainsUseOurAppDomainThenFirePixel() {
78+
setDefaultVariant()
4279
val intent = Intent()
4380
intent.putExtra(ShortcutBuilder.SHORTCUT_URL_ARG, "https://facebook.com")
4481
intent.putExtra(ShortcutBuilder.SHORTCUT_TITLE_ARG, "Title")
@@ -47,8 +84,20 @@ class ShortcutReceiverTest {
4784
verify(mockPixel).fire(AppPixelName.USE_OUR_APP_SHORTCUT_ADDED)
4885
}
4986

87+
@Test
88+
fun whenIntentReceivedIfUrlIsNotFromUseOurAppDomainThenDoNotRegisterEvent() = coroutinesTestRule.runBlocking {
89+
setDefaultVariant()
90+
val intent = Intent()
91+
intent.putExtra(ShortcutBuilder.SHORTCUT_URL_ARG, "www.example.com")
92+
intent.putExtra(ShortcutBuilder.SHORTCUT_TITLE_ARG, "Title")
93+
testee.onReceive(null, intent)
94+
95+
verify(mockUserEventsStore, never()).registerUserEvent(UserEventKey.USE_OUR_APP_SHORTCUT_ADDED)
96+
}
97+
5098
@Test
5199
fun whenIntentReceivedIfUrlIsNotFromUseOurAppDomainThenFireShortcutAddedPixel() {
100+
setDefaultVariant()
52101
val intent = Intent()
53102
intent.putExtra(ShortcutBuilder.SHORTCUT_URL_ARG, "www.example.com")
54103
intent.putExtra(ShortcutBuilder.SHORTCUT_TITLE_ARG, "Title")
@@ -57,4 +106,21 @@ class ShortcutReceiverTest {
57106
verify(mockPixel).fire(AppPixelName.SHORTCUT_ADDED)
58107
}
59108

109+
private fun setDefaultVariant() {
110+
whenever(mockVariantManager.getVariant()).thenReturn(VariantManager.DEFAULT_VARIANT)
111+
}
112+
113+
private fun setInAppUsageVariant() {
114+
whenever(mockVariantManager.getVariant()).thenReturn(
115+
Variant(
116+
"test",
117+
features = listOf(
118+
VariantManager.VariantFeature.InAppUsage,
119+
VariantManager.VariantFeature.RemoveDay1AndDay3Notifications,
120+
VariantManager.VariantFeature.KillOnboarding
121+
),
122+
filterBy = { true }
123+
)
124+
)
125+
}
60126
}

app/src/androidTest/java/com/duckduckgo/app/notification/AndroidNotificationSchedulerTest.kt

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ import com.duckduckgo.app.CoroutineTestRule
2929
import com.duckduckgo.app.notification.NotificationScheduler.ClearDataNotificationWorker
3030
import com.duckduckgo.app.notification.NotificationScheduler.PrivacyNotificationWorker
3131
import com.duckduckgo.app.notification.model.SchedulableNotification
32+
import com.duckduckgo.app.statistics.Variant
33+
import com.duckduckgo.app.statistics.VariantManager
34+
import com.duckduckgo.app.statistics.VariantManager.Companion.DEFAULT_VARIANT
3235
import com.nhaarman.mockitokotlin2.mock
3336
import com.nhaarman.mockitokotlin2.whenever
3437
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -47,6 +50,8 @@ class AndroidNotificationSchedulerTest {
4750

4851
private val clearNotification: SchedulableNotification = mock()
4952
private val privacyNotification: SchedulableNotification = mock()
53+
private val useOurAppNotification: SchedulableNotification = mock()
54+
private val variantManager: VariantManager = mock()
5055

5156
private val context = InstrumentationRegistry.getInstrumentation().targetContext
5257
private lateinit var workManager: WorkManager
@@ -59,7 +64,9 @@ class AndroidNotificationSchedulerTest {
5964
testee = NotificationScheduler(
6065
workManager,
6166
clearNotification,
62-
privacyNotification
67+
privacyNotification,
68+
useOurAppNotification,
69+
variantManager
6370
)
6471
}
6572

@@ -76,6 +83,7 @@ class AndroidNotificationSchedulerTest {
7683

7784
@Test
7885
fun whenPrivacyNotificationClearDataCanShowThenPrivacyNotificationIsScheduled() = runBlocking<Unit> {
86+
setDefaultVariant()
7987
whenever(privacyNotification.canShow()).thenReturn(true)
8088
whenever(clearNotification.canShow()).thenReturn(true)
8189
testee.scheduleNextNotification()
@@ -85,6 +93,7 @@ class AndroidNotificationSchedulerTest {
8593

8694
@Test
8795
fun whenPrivacyNotificationCanShowButClearDataCannotThenPrivacyNotificationIsScheduled() = runBlocking<Unit> {
96+
setDefaultVariant()
8897
whenever(privacyNotification.canShow()).thenReturn(true)
8998
whenever(clearNotification.canShow()).thenReturn(false)
9099
testee.scheduleNextNotification()
@@ -94,6 +103,7 @@ class AndroidNotificationSchedulerTest {
94103

95104
@Test
96105
fun whenPrivacyNotificationCannotShowAndClearNotificationCanShowThenClearNotificationIsScheduled() = runBlocking<Unit> {
106+
setDefaultVariant()
97107
whenever(privacyNotification.canShow()).thenReturn(false)
98108
whenever(clearNotification.canShow()).thenReturn(true)
99109
testee.scheduleNextNotification()
@@ -103,13 +113,137 @@ class AndroidNotificationSchedulerTest {
103113

104114
@Test
105115
fun whenPrivacyNotificationAndClearNotificationCannotShowThenNoNotificationScheduled() = runBlocking<Unit> {
116+
setDefaultVariant()
106117
whenever(privacyNotification.canShow()).thenReturn(false)
107118
whenever(clearNotification.canShow()).thenReturn(false)
108119
testee.scheduleNextNotification()
109120

110121
assertNoNotificationScheduled()
111122
}
112123

124+
@Test
125+
fun whenInAppUsageVariantAndUseOurAppNotificationCanShowThenNotificationScheduled() = runBlocking {
126+
givenNoInactiveUserNotifications()
127+
setInAppUsageVariant()
128+
whenever(useOurAppNotification.canShow()).thenReturn(true)
129+
130+
testee.scheduleNextNotification()
131+
132+
assertNotificationScheduled(NotificationScheduler.UseOurAppNotificationWorker::class.jvmName, NotificationScheduler.USE_OUR_APP_WORK_REQUEST_TAG)
133+
}
134+
135+
@Test
136+
fun whenInAppUsageVariantUseOurAppNotificationCannotShowThenNoNotificationScheduled() = runBlocking {
137+
givenNoInactiveUserNotifications()
138+
setInAppUsageVariant()
139+
whenever(useOurAppNotification.canShow()).thenReturn(false)
140+
141+
testee.scheduleNextNotification()
142+
143+
assertNoNotificationScheduled(NotificationScheduler.USE_OUR_APP_WORK_REQUEST_TAG)
144+
}
145+
146+
@Test
147+
fun whenInAppUsageSecondControlVariantThenNoNotificationScheduled() = runBlocking<Unit> {
148+
setInAppUsageSecondControlVariant()
149+
whenever(useOurAppNotification.canShow()).thenReturn(true)
150+
151+
testee.scheduleNextNotification()
152+
153+
assertNoNotificationScheduled(NotificationScheduler.USE_OUR_APP_WORK_REQUEST_TAG)
154+
}
155+
156+
@Test
157+
fun whenInAppUsageControlVariantThenNoNotificationScheduled() = runBlocking<Unit> {
158+
givenNoInactiveUserNotifications()
159+
setInAppUsageControlVariant()
160+
whenever(useOurAppNotification.canShow()).thenReturn(true)
161+
162+
testee.scheduleNextNotification()
163+
164+
assertNoNotificationScheduled(NotificationScheduler.USE_OUR_APP_WORK_REQUEST_TAG)
165+
}
166+
167+
@Test
168+
fun whenInAppUsageControlVariantAndPrivacyNotificationClearDataCanShowThenPrivacyNotificationIsScheduled() = runBlocking<Unit> {
169+
setInAppUsageControlVariant()
170+
whenever(privacyNotification.canShow()).thenReturn(true)
171+
whenever(clearNotification.canShow()).thenReturn(true)
172+
testee.scheduleNextNotification()
173+
174+
assertNotificationScheduled(PrivacyNotificationWorker::class.jvmName)
175+
}
176+
177+
@Test
178+
fun whenInAppUsageControlVariantAndPrivacyNotificationCanShowButClearDataCannotThenPrivacyNotificationIsScheduled() = runBlocking<Unit> {
179+
setInAppUsageControlVariant()
180+
whenever(privacyNotification.canShow()).thenReturn(true)
181+
whenever(clearNotification.canShow()).thenReturn(false)
182+
testee.scheduleNextNotification()
183+
184+
assertNotificationScheduled(PrivacyNotificationWorker::class.jvmName)
185+
}
186+
187+
@Test
188+
fun whenInAppUsageControlVariantAndPrivacyNotificationCannotShowAndClearNotificationCanShowThenClearNotificationScheduled() = runBlocking<Unit> {
189+
setInAppUsageControlVariant()
190+
whenever(privacyNotification.canShow()).thenReturn(false)
191+
whenever(clearNotification.canShow()).thenReturn(true)
192+
testee.scheduleNextNotification()
193+
194+
assertNotificationScheduled(ClearDataNotificationWorker::class.jvmName)
195+
}
196+
197+
@Test
198+
fun whenInAppUsageControlVariantAndPrivacyNotificationAndClearNotificationCannotShowThenNoNotificationScheduled() = runBlocking<Unit> {
199+
setDefaultVariant()
200+
whenever(privacyNotification.canShow()).thenReturn(false)
201+
whenever(clearNotification.canShow()).thenReturn(false)
202+
testee.scheduleNextNotification()
203+
204+
assertNoNotificationScheduled()
205+
}
206+
207+
private suspend fun givenNoInactiveUserNotifications() {
208+
whenever(privacyNotification.canShow()).thenReturn(false)
209+
whenever(clearNotification.canShow()).thenReturn(false)
210+
}
211+
212+
private fun setInAppUsageVariant() {
213+
whenever(variantManager.getVariant()).thenReturn(
214+
Variant(
215+
"test",
216+
features = listOf(
217+
VariantManager.VariantFeature.InAppUsage,
218+
VariantManager.VariantFeature.RemoveDay1AndDay3Notifications,
219+
VariantManager.VariantFeature.KillOnboarding
220+
),
221+
filterBy = { true }
222+
)
223+
)
224+
}
225+
226+
private fun setInAppUsageSecondControlVariant() {
227+
whenever(variantManager.getVariant()).thenReturn(
228+
Variant(
229+
"test",
230+
features = listOf(
231+
VariantManager.VariantFeature.RemoveDay1AndDay3Notifications,
232+
VariantManager.VariantFeature.KillOnboarding
233+
),
234+
filterBy = { true }
235+
)
236+
)
237+
}
238+
239+
private fun setInAppUsageControlVariant() {
240+
whenever(variantManager.getVariant()).thenReturn(Variant("test", features = emptyList(), filterBy = { true }))
241+
}
242+
243+
private fun setDefaultVariant() {
244+
whenever(variantManager.getVariant()).thenReturn(DEFAULT_VARIANT)
245+
}
246+
113247
private fun assertNotificationScheduled(workerName: String, tag: String = NotificationScheduler.UNUSED_APP_WORK_REQUEST_TAG) {
114248
assertTrue(getScheduledWorkers(tag).any { it.tags.contains(workerName) })
115249
}

0 commit comments

Comments
 (0)