Skip to content

Commit ee94341

Browse files
committed
Merge branch 'release/5.37.0'
2 parents 88a6f74 + 6ba5186 commit ee94341

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1230
-96
lines changed

app/build.gradle

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,19 +111,23 @@ ext {
111111
rxAndroid = "2.0.2"
112112
timber = "4.7.1"
113113
rxRelay = "2.0.0"
114-
leakCanary = "1.6.2"
114+
leakCanary = "2.0-beta-4"
115115
mockito = "2.18.3"
116116
mockitoKotlin = "2.0.0"
117117
commonsMath = "3.6.1"
118+
referrerLibrary = "1.0"
118119
}
119120

120121

121122
dependencies {
122123
implementation "androidx.legacy:legacy-support-v4:$legacySupport"
123124
debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanary"
124-
releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$leakCanary"
125125

126126
implementation fileTree(dir: 'libs', include: ['*.jar'])
127+
128+
//noinspection GradleDependency - 1.1 has a bug which causes a crash
129+
implementation "com.android.installreferrer:installreferrer:$referrerLibrary"
130+
127131
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
128132
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines"
129133
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines"

app/src/androidTest/java/com/duckduckgo/app/TestApplication.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,4 @@ class TestApplication : DuckDuckGoApplication() {
3434
.build()
3535
daggerAppComponent.inject(this)
3636
}
37-
38-
// We don't need to actually use leak canary for tests
39-
override fun installLeakCanary(): Boolean = true
40-
4137
}

app/src/androidTest/java/com/duckduckgo/app/di/TestAppComponent.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ import javax.inject.Singleton
6868
RatingModule::class,
6969
AppUsageModule::class,
7070
FileModule::class,
71-
UncaughtExceptionModule::class
71+
UncaughtExceptionModule::class,
72+
PlayStoreReferralModule::class
7273
]
7374
)
7475
interface TestAppComponent : AppComponent {

app/src/androidTest/java/com/duckduckgo/app/launch/LaunchViewModelTest.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import androidx.lifecycle.Observer
2121
import com.duckduckgo.app.launch.LaunchViewModel.Command.Home
2222
import com.duckduckgo.app.launch.LaunchViewModel.Command.Onboarding
2323
import com.duckduckgo.app.onboarding.store.OnboardingStore
24+
import com.duckduckgo.app.referral.AppInstallationReferrerStateListener
2425
import com.nhaarman.mockitokotlin2.mock
2526
import com.nhaarman.mockitokotlin2.verify
2627
import com.nhaarman.mockitokotlin2.whenever
@@ -37,10 +38,11 @@ class LaunchViewModelTest {
3738
var instantTaskExecutorRule = InstantTaskExecutorRule()
3839

3940
private var onboardingStore: OnboardingStore = mock()
41+
private var appInstallationReferrerStateListener: AppInstallationReferrerStateListener = mock()
4042
private var mockCommandObserver: Observer<LaunchViewModel.Command> = mock()
4143

4244
private val testee: LaunchViewModel by lazy {
43-
LaunchViewModel(onboardingStore)
45+
LaunchViewModel(onboardingStore, appInstallationReferrerStateListener)
4446
}
4547

4648
@After
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (c) 2019 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.referral
18+
19+
import org.junit.Assert.assertEquals
20+
import org.junit.Before
21+
import org.junit.Test
22+
23+
class DurationBucketMapperTest {
24+
25+
private lateinit var testee: DurationBucketMapper
26+
27+
@Before
28+
fun setup() {
29+
testee = DurationBucketMapper()
30+
}
31+
32+
@Test
33+
fun whenDurationOneBelowNextThresholdThenCurrentBucketReturned() {
34+
assertEquals("0", testee.mapDurationToBucket(99))
35+
assertEquals("1", testee.mapDurationToBucket(199))
36+
assertEquals("2", testee.mapDurationToBucket(499))
37+
assertEquals("3", testee.mapDurationToBucket(999))
38+
assertEquals("4", testee.mapDurationToBucket(1_499))
39+
assertEquals("5", testee.mapDurationToBucket(1_999))
40+
assertEquals("6", testee.mapDurationToBucket(2_499))
41+
}
42+
43+
@Test
44+
fun whenDurationExactlyOnThresholdThenNextBucketReturned() {
45+
assertEquals("0", testee.mapDurationToBucket(0))
46+
assertEquals("1", testee.mapDurationToBucket(100))
47+
assertEquals("2", testee.mapDurationToBucket(200))
48+
assertEquals("3", testee.mapDurationToBucket(500))
49+
assertEquals("4", testee.mapDurationToBucket(1_000))
50+
assertEquals("5", testee.mapDurationToBucket(1_500))
51+
assertEquals("6", testee.mapDurationToBucket(2_000))
52+
assertEquals("7", testee.mapDurationToBucket(2_500))
53+
}
54+
55+
@Test
56+
fun whenDurationOneAboveThresholdThenNextBucketReturned() {
57+
assertEquals("0", testee.mapDurationToBucket(1))
58+
assertEquals("1", testee.mapDurationToBucket(101))
59+
assertEquals("2", testee.mapDurationToBucket(201))
60+
assertEquals("3", testee.mapDurationToBucket(501))
61+
assertEquals("4", testee.mapDurationToBucket(1_001))
62+
assertEquals("5", testee.mapDurationToBucket(1_501))
63+
assertEquals("6", testee.mapDurationToBucket(2_001))
64+
assertEquals("7", testee.mapDurationToBucket(2_501))
65+
}
66+
67+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2019 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.referral
18+
19+
import com.duckduckgo.app.referral.ParsedReferrerResult.ReferrerFound
20+
import com.duckduckgo.app.statistics.pixels.Pixel
21+
import com.nhaarman.mockitokotlin2.mock
22+
import org.junit.Assert.assertEquals
23+
import org.junit.Assert.assertTrue
24+
import org.junit.Test
25+
26+
class QueryParamReferrerParserTest {
27+
28+
private val pixel: Pixel = mock()
29+
30+
private val testee: QueryParamReferrerParser = QueryParamReferrerParser(pixel)
31+
32+
@Test
33+
fun whenReferrerDoesNotContainTargetThenNoReferrerFound() {
34+
verifyReferrerNotFound(testee.parse("ABC"))
35+
}
36+
37+
@Test
38+
fun whenReferrerContainsTargetAndLongSuffixThenShortenedReferrerFound() {
39+
val result = testee.parse("DDGRAABC")
40+
verifyReferrerFound("AB", result)
41+
}
42+
43+
@Test
44+
fun whenReferrerContainsTargetAndTwoCharSuffixThenReferrerFound() {
45+
val result = testee.parse("DDGRAXY")
46+
verifyReferrerFound("XY", result)
47+
}
48+
49+
@Test
50+
fun whenReferrerContainsTargetAndOneCharSuffixThenNoReferrerFound() {
51+
val result = testee.parse("DDGRAX")
52+
verifyReferrerNotFound(result)
53+
}
54+
55+
@Test
56+
fun whenReferrerContainsTargetButNoSuffixThenNoReferrerFound() {
57+
val result = testee.parse("DDGRAX")
58+
verifyReferrerNotFound(result)
59+
}
60+
61+
@Test
62+
fun whenReferrerIsEmptyThenNoReferrerFound() {
63+
verifyReferrerNotFound(testee.parse(""))
64+
}
65+
66+
@Test
67+
fun whenReferrerContainsTargetAsFirstParamThenReferrerFound() {
68+
val result = testee.parse("key1=DDGRAAB&key2=foo&key3=bar")
69+
verifyReferrerFound("AB", result)
70+
}
71+
72+
@Test
73+
fun whenReferrerContainsTargetAsLastParamThenReferrerFound() {
74+
val result = testee.parse("key1=foo&key2=bar&key3=DDGRAAB")
75+
verifyReferrerFound("AB", result)
76+
}
77+
78+
@Test
79+
fun whenReferrerContainsTargetWithDifferentCaseThenNoReferrerFound() {
80+
verifyReferrerNotFound(testee.parse("ddgraAB"))
81+
}
82+
83+
@Test
84+
fun whenTypeAReferrerNotFoundButTypeBFoundThenReferrerFound() {
85+
verifyReferrerFound("AB", testee.parse("key1=foo&key2=bar&key3=DDGRBAB"))
86+
}
87+
88+
private fun verifyReferrerFound(expectedReferrer: String, result: ParsedReferrerResult) {
89+
assertTrue(result is ReferrerFound)
90+
val value = (result as ReferrerFound).campaignSuffix
91+
assertEquals(expectedReferrer, value)
92+
}
93+
94+
private fun verifyReferrerNotFound(result: ParsedReferrerResult) {
95+
assertTrue(result is ParsedReferrerResult.ReferrerNotFound)
96+
}
97+
}

app/src/androidTest/java/com/duckduckgo/app/statistics/VariantManagerTest.kt

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,50 +16,26 @@
1616

1717
package com.duckduckgo.app.statistics
1818

19-
import org.junit.Assert.*
19+
import org.junit.Assert.assertEquals
20+
import org.junit.Assert.fail
2021
import org.junit.Test
2122

2223
class VariantManagerTest {
2324

2425
private val variants = VariantManager.ACTIVE_VARIANTS
2526

2627
@Test
27-
fun serpAndSharedControlVariantInactive() {
28+
fun serpAndSharedControlVariantActive() {
2829
val variant = variants.firstOrNull { it.key == "sc" }
29-
assertEqualsDouble(0.0, variant!!.weight)
30+
assertEqualsDouble(1.0, variant!!.weight)
3031
assertEquals(0, variant.features.size)
3132
}
3233

3334
@Test
34-
fun serpExperimentalVariantInactive() {
35+
fun serpExperimentalVariantActive() {
3536
val variant = variants.firstOrNull { it.key == "se" }
36-
assertEqualsDouble(0.0, variant!!.weight)
37-
assertEquals(0, variant.features.size)
38-
}
39-
40-
@Test
41-
fun defaultLightThemeExperimentVariantActive() {
42-
val variant = variants.firstOrNull { it.key == "mo" }
43-
assertEqualsDouble(1.0, variant!!.weight)
44-
}
45-
46-
@Test
47-
fun defaultLightThemeExperimentVariantHasExperimentalFeatureForLightTheme() {
48-
val variant = variants.firstOrNull { it.key == "mo" }
49-
assertEquals(1, variant!!.features.size)
50-
assertTrue(variant.hasFeature(VariantManager.VariantFeature.LightThemeExperiment))
51-
}
52-
53-
@Test
54-
fun defaultLightThemeControlGroupVariantActive() {
55-
val variant = variants.firstOrNull { it.key == "mp" }
5637
assertEqualsDouble(1.0, variant!!.weight)
57-
}
58-
59-
@Test
60-
fun defaultLightThemeControlGroupVariantHasNoExperimentFeatures() {
61-
val variant = variants.firstOrNull { it.key == "mp" }
62-
assertEquals(0, variant!!.features.size)
38+
assertEquals(0, variant.features.size)
6339
}
6440

6541
@Suppress("SameParameterValue")

app/src/main/java/com/duckduckgo/app/di/AppComponent.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ import javax.inject.Singleton
6666
RatingModule::class,
6767
AppUsageModule::class,
6868
FileModule::class,
69-
UncaughtExceptionModule::class
69+
UncaughtExceptionModule::class,
70+
PlayStoreReferralModule::class
7071
]
7172
)
7273
interface AppComponent : AndroidInjector<DuckDuckGoApplication> {
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright (c) 2019 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.di
18+
19+
import android.content.Context
20+
import android.content.pm.PackageManager
21+
import com.duckduckgo.app.referral.*
22+
import com.duckduckgo.app.statistics.pixels.Pixel
23+
import dagger.Module
24+
import dagger.Provides
25+
import javax.inject.Singleton
26+
27+
@Module
28+
class PlayStoreReferralModule {
29+
30+
@Singleton
31+
@Provides
32+
fun packageManager(context: Context) = context.packageManager
33+
34+
@Provides
35+
fun appInstallationReferrerParser(pixel: Pixel): AppInstallationReferrerParser {
36+
return QueryParamReferrerParser(pixel)
37+
}
38+
39+
@Provides
40+
@Singleton
41+
fun appInstallationReferrerStateListener(
42+
context: Context,
43+
packageManager: PackageManager,
44+
appInstallationReferrerParser: AppInstallationReferrerParser,
45+
appReferrerDataStore: AppReferrerDataStore
46+
): AppInstallationReferrerStateListener {
47+
return PlayStoreAppReferrerStateListener(context, packageManager, appInstallationReferrerParser, appReferrerDataStore)
48+
}
49+
50+
@Provides
51+
fun durationMeasuringReferrerRetriever(
52+
referrerStateListener: AppInstallationReferrerStateListener,
53+
durationBucketMapper: DurationBucketMapper,
54+
pixel: Pixel
55+
): ReferrerRetrievalTimer {
56+
return ReferrerRetrievalTimer(referrerStateListener, durationBucketMapper, pixel)
57+
}
58+
59+
@Provides
60+
fun durationBucketMapper(): DurationBucketMapper {
61+
return DurationBucketMapper()
62+
}
63+
64+
@Provides
65+
@Singleton
66+
fun appReferrerDataStore(context: Context): AppReferrerDataStore {
67+
return AppReferenceSharePreferences(context)
68+
}
69+
}

0 commit comments

Comments
 (0)