Skip to content

Commit dad8aa1

Browse files
nalcalagmikescamell
authored andcommitted
SenseOfProtection experiment: Cohort survey param (#5889)
Task/Issue URL: https://app.asana.com/0/1202552961248957/1209874180233369/f Added a temporary survey param for experiment cohort - N/A --------- Co-authored-by: Mike Scamell <[email protected]>
1 parent b42b3b4 commit dad8aa1

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) 2025 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.app.survey.rmf
18+
19+
import com.duckduckgo.app.browser.senseofprotection.SenseOfProtectionToggles
20+
import com.duckduckgo.di.scopes.AppScope
21+
import com.duckduckgo.survey.api.SurveyParameterPlugin
22+
import com.squareup.anvil.annotations.ContributesMultibinding
23+
import javax.inject.Inject
24+
25+
// Added while senseOfProtectionNewUserExperimentApr25 is active
26+
@ContributesMultibinding(AppScope::class)
27+
class SenseOfProtectionCohortSurveyParameterPlugin @Inject constructor(
28+
private val senseOfProtectionToggles: SenseOfProtectionToggles,
29+
) : SurveyParameterPlugin {
30+
override val surveyParamKey: String = "senseProtectionCohort"
31+
32+
override suspend fun evaluate(): String = senseOfProtectionToggles.senseOfProtectionNewUserExperimentApr25().getCohort()?.name.orEmpty()
33+
}

app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.duckduckgo.anvil.annotations.ContributesViewModel
2424
import com.duckduckgo.app.browser.SwipingTabsFeatureProvider
2525
import com.duckduckgo.app.browser.senseofprotection.SenseOfProtectionExperiment
2626
import com.duckduckgo.app.browser.favicon.FaviconManager
27+
import com.duckduckgo.app.browser.senseofprotection.SenseOfProtectionToggles.Cohorts.VARIANT_2
2728
import com.duckduckgo.app.pixels.AppPixelName
2829
import com.duckduckgo.app.pixels.AppPixelName.TAB_MANAGER_GRID_VIEW_BUTTON_CLICKED
2930
import com.duckduckgo.app.pixels.AppPixelName.TAB_MANAGER_INFO_PANEL_DISMISSED
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.duckduckgo.app.survey.rmf
2+
3+
import com.duckduckgo.app.browser.senseofprotection.SenseOfProtectionToggles
4+
import com.duckduckgo.app.browser.senseofprotection.SenseOfProtectionToggles.Cohorts
5+
import com.duckduckgo.feature.toggles.api.Toggle
6+
import com.duckduckgo.feature.toggles.api.Toggle.State.Cohort
7+
import kotlinx.coroutines.test.runTest
8+
import org.junit.Assert.assertEquals
9+
import org.junit.Test
10+
import org.mockito.kotlin.doReturn
11+
import org.mockito.kotlin.mock
12+
import org.mockito.kotlin.whenever
13+
14+
class TemporaryDefaultSurveyParametersPluginTest {
15+
16+
private val mockSenseOfProtectionToggles: SenseOfProtectionToggles = mock()
17+
18+
@Test
19+
fun givenUserAssignedToModifiedControlThenCohortParamEvaluatesToModifiedControl() = runTest {
20+
val modifiedControlCohort = Cohort(Cohorts.MODIFIED_CONTROL.cohortName, 1)
21+
val mockToggle: Toggle = mock {
22+
on { it.isEnabled() } doReturn true
23+
on { it.getCohort() } doReturn modifiedControlCohort
24+
}
25+
whenever(mockSenseOfProtectionToggles.senseOfProtectionNewUserExperimentApr25()).thenReturn(mockToggle)
26+
27+
val plugin = SenseOfProtectionCohortSurveyParameterPlugin(mockSenseOfProtectionToggles)
28+
29+
assertEquals("modifiedControl", plugin.evaluate())
30+
}
31+
32+
@Test
33+
fun givenUserAssignedToVariant1ThenCohortParamEvaluatesToVariant1() = runTest {
34+
val modifiedControlCohort = Cohort(Cohorts.VARIANT_1.cohortName, 1)
35+
val mockToggle: Toggle = mock {
36+
on { it.isEnabled() } doReturn true
37+
on { it.getCohort() } doReturn modifiedControlCohort
38+
}
39+
whenever(mockSenseOfProtectionToggles.senseOfProtectionNewUserExperimentApr25()).thenReturn(mockToggle)
40+
41+
val plugin = SenseOfProtectionCohortSurveyParameterPlugin(mockSenseOfProtectionToggles)
42+
43+
assertEquals("variant1", plugin.evaluate())
44+
}
45+
46+
@Test
47+
fun givenUserAssignedToVariant2ThenCohortParamEvaluatesToVariant2() = runTest {
48+
val modifiedControlCohort = Cohort(Cohorts.VARIANT_2.cohortName, 2)
49+
val mockToggle: Toggle = mock {
50+
on { it.isEnabled() } doReturn true
51+
on { it.getCohort() } doReturn modifiedControlCohort
52+
}
53+
whenever(mockSenseOfProtectionToggles.senseOfProtectionNewUserExperimentApr25()).thenReturn(mockToggle)
54+
55+
val plugin = SenseOfProtectionCohortSurveyParameterPlugin(mockSenseOfProtectionToggles)
56+
57+
assertEquals("variant2", plugin.evaluate())
58+
}
59+
60+
@Test
61+
fun givenNotAssignedOnSenseOfProtectionExperimentThenCohortParamEvaluatesToEmptyString() = runTest {
62+
val mockToggle: Toggle = mock {
63+
on { it.isEnabled() } doReturn false
64+
on { it.getCohort() } doReturn null
65+
}
66+
whenever(mockSenseOfProtectionToggles.senseOfProtectionNewUserExperimentApr25()).thenReturn(mockToggle)
67+
68+
val plugin = SenseOfProtectionCohortSurveyParameterPlugin(mockSenseOfProtectionToggles)
69+
70+
assertEquals("", plugin.evaluate())
71+
}
72+
}

0 commit comments

Comments
 (0)