Skip to content

Commit 4c0be54

Browse files
authored
Add retention statistics
* Add install and retention statistics * Added stub statistics module for tests * Move app config to correct package * Update dependencies
1 parent 63ad354 commit 4c0be54

Some content is hidden

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

48 files changed

+809
-163
lines changed

app/build.gradle

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,13 @@ dependencies {
9191
implementation "com.android.support:appcompat-v7:$supportLibrary"
9292
implementation "com.android.support:design:$supportLibrary"
9393
implementation "com.android.support.constraint:constraint-layout:1.0.2"
94-
implementation "com.squareup.okhttp3:okhttp:3.9.1"
94+
implementation "com.squareup.okhttp3:okhttp:3.10.0"
9595
implementation "com.squareup.retrofit2:retrofit:$retrofit"
9696
implementation "com.squareup.retrofit2:converter-moshi:$retrofit"
9797
implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit"
98-
implementation "io.reactivex.rxjava2:rxjava:2.1.8"
99-
implementation "io.reactivex.rxjava2:rxandroid:2.0.1"
100-
implementation "com.jakewharton.timber:timber:4.6.0"
98+
implementation "io.reactivex.rxjava2:rxjava:2.1.10"
99+
implementation "io.reactivex.rxjava2:rxandroid:2.0.2"
100+
implementation "com.jakewharton.timber:timber:4.6.1"
101101
implementation "com.google.dagger:dagger-android:$dagger"
102102
implementation "com.google.dagger:dagger-android-support:$dagger"
103103
releaseImplementation 'com.faendir:acra:4.10.0'
@@ -127,14 +127,14 @@ dependencies {
127127
kaptAndroidTest "com.google.dagger:dagger-android-processor:$dagger"
128128
kaptAndroidTest "com.google.dagger:dagger-compiler:$dagger"
129129

130-
testImplementation "org.mockito:mockito-core:2.13.0"
130+
testImplementation "org.mockito:mockito-core:2.15.0"
131131
testImplementation "com.nhaarman:mockito-kotlin-kt1.1:1.5.0"
132132
testImplementation "junit:junit:4.12"
133133

134134
androidTestImplementation "com.android.support.test:runner:1.0.1"
135135
androidTestUtil "com.android.support.test:orchestrator:1.0.1"
136136
androidTestImplementation "com.android.support.test.espresso:espresso-core:3.0.1"
137-
androidTestImplementation "org.mockito:mockito-android:2.13.0"
137+
androidTestImplementation "org.mockito:mockito-android:2.15.0"
138138
androidTestImplementation "com.nhaarman:mockito-kotlin-kt1.1:1.5.0"
139139

140140
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright (c) 2018 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
18+
19+
object FileUtilities {
20+
21+
fun loadText(resourceName: String): String =
22+
javaClass.classLoader.getResource(resourceName).openStream().bufferedReader().use { it.readText() }
23+
24+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2018 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
18+
19+
20+
import io.reactivex.android.plugins.RxAndroidPlugins
21+
import io.reactivex.plugins.RxJavaPlugins
22+
import io.reactivex.schedulers.Schedulers
23+
import org.junit.rules.TestRule
24+
import org.junit.runner.Description
25+
import org.junit.runners.model.Statement
26+
27+
28+
class InstantSchedulersRule : TestRule {
29+
30+
override fun apply(base: Statement, description: Description): Statement {
31+
32+
return object : Statement() {
33+
34+
@Throws(Throwable::class)
35+
override fun evaluate() {
36+
37+
RxJavaPlugins.reset()
38+
RxAndroidPlugins.reset()
39+
40+
RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() }
41+
RxJavaPlugins.setComputationSchedulerHandler { Schedulers.trampoline() }
42+
RxJavaPlugins.setNewThreadSchedulerHandler { Schedulers.trampoline() }
43+
RxAndroidPlugins.setMainThreadSchedulerHandler { Schedulers.trampoline() }
44+
45+
base.evaluate()
46+
47+
RxJavaPlugins.reset()
48+
RxAndroidPlugins.reset()
49+
50+
}
51+
52+
}
53+
}
54+
55+
}

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ import com.duckduckgo.app.privacymonitor.db.NetworkPercent
3939
import com.duckduckgo.app.privacymonitor.model.PrivacyGrade
4040
import com.duckduckgo.app.privacymonitor.store.PrivacyMonitorRepository
4141
import com.duckduckgo.app.privacymonitor.store.TermsOfServiceStore
42-
import com.duckduckgo.app.settings.db.AppConfigurationDao
43-
import com.duckduckgo.app.settings.db.AppConfigurationEntity
42+
import com.duckduckgo.app.global.db.AppConfigurationDao
43+
import com.duckduckgo.app.global.db.AppConfigurationEntity
4444
import com.duckduckgo.app.settings.db.SettingsDataStore
45+
import com.duckduckgo.app.statistics.api.StatisticsUpdater
4546
import com.duckduckgo.app.trackerdetection.model.TrackerNetwork
4647
import com.duckduckgo.app.trackerdetection.model.TrackerNetworks
4748
import com.duckduckgo.app.trackerdetection.model.TrackingEvent
@@ -74,6 +75,9 @@ class BrowserViewModelTest {
7475
}
7576
}
7677

78+
@Mock
79+
private lateinit var mockStatisticsUpdater: StatisticsUpdater
80+
7781
@Mock
7882
private lateinit var mockQueryObserver: Observer<String>
7983

@@ -116,6 +120,7 @@ class BrowserViewModelTest {
116120
appConfigurationDao = db.appConfigurationDao()
117121

118122
testee = BrowserViewModel(
123+
statisticsUpdater = mockStatisticsUpdater,
119124
queryUrlConverter = mockOmnibarConverter,
120125
duckDuckGoUrlDetector = DuckDuckGoUrlDetector(),
121126
termsOfServiceStore = mockTermsOfServiceStore,
@@ -235,6 +240,12 @@ class BrowserViewModelTest {
235240
assertEquals("test", testee.viewState.value!!.omnibarText)
236241
}
237242

243+
@Test
244+
fun whenUrlChangedWithDuckDuckGoUrlContainingQueryThenAtbRefreshed() {
245+
testee.urlChanged("http://duckduckgo.com?q=test")
246+
verify(mockStatisticsUpdater).refreshRetentionAtb()
247+
}
248+
238249
@Test
239250
fun whenUrlChangedWithDuckDuckGoUrlNotContainingQueryThenFullUrlShown() {
240251
testee.urlChanged("http://duckduckgo.com")

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

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,58 @@
1717
package com.duckduckgo.app.browser
1818

1919
import android.net.Uri
20-
import org.junit.Assert.assertEquals
21-
import org.junit.Assert.assertTrue
20+
import com.duckduckgo.app.global.AppUrl.ParamKey
21+
import com.duckduckgo.app.statistics.store.StatisticsDataStore
22+
import com.nhaarman.mockito_kotlin.mock
23+
import com.nhaarman.mockito_kotlin.whenever
24+
import org.junit.Assert.*
2225
import org.junit.Before
2326
import org.junit.Test
2427

2528
class DuckDuckGoRequestRewriterTest {
2629

2730
private lateinit var testee: DuckDuckGoRequestRewriter
31+
private var mockStatisticsStore: StatisticsDataStore = mock()
2832
private lateinit var builder: Uri.Builder
2933

3034
@Before
3135
fun before() {
32-
testee = DuckDuckGoRequestRewriter(DuckDuckGoUrlDetector())
36+
testee = DuckDuckGoRequestRewriter(DuckDuckGoUrlDetector(), mockStatisticsStore)
3337
builder = Uri.Builder()
3438
}
3539

3640
@Test
3741
fun whenAddingCustomParamsSourceParameterIsAdded() {
3842
testee.addCustomQueryParams(builder)
3943
val uri = builder.build()
40-
assertTrue(uri.queryParameterNames.contains("t"))
41-
assertEquals("ddg_android", uri.getQueryParameter("t"))
44+
assertTrue(uri.queryParameterNames.contains(ParamKey.SOURCE))
45+
assertEquals("ddg_android", uri.getQueryParameter(ParamKey.SOURCE))
4246
}
4347

4448
@Test
4549
fun whenAddingCustomParamsAppVersionParameterIsAdded() {
4650
testee.addCustomQueryParams(builder)
4751
val uri = builder.build()
48-
assertTrue(uri.queryParameterNames.contains("tappv"))
52+
assertTrue(uri.queryParameterNames.contains(ParamKey.APP_VERSION))
4953
assertEquals("android_${BuildConfig.VERSION_NAME.replace(".", "_")}", uri.getQueryParameter("tappv"))
5054
}
55+
56+
@Test
57+
fun whenAddingCustomParamsIfStoreContainsAtbIsAdded() {
58+
whenever(mockStatisticsStore.atb).thenReturn("v105-2ma")
59+
testee.addCustomQueryParams(builder)
60+
val uri = builder.build()
61+
assertTrue(uri.queryParameterNames.contains(ParamKey.ATB))
62+
assertEquals("v105-2ma", uri.getQueryParameter(ParamKey.ATB))
63+
}
64+
65+
@Test
66+
fun whenAddingCustomParamsIfIsStoreMissingAtbThenAtbIsNotAdded() {
67+
whenever(mockStatisticsStore.atb).thenReturn(null)
68+
69+
testee.addCustomQueryParams(builder)
70+
val uri = builder.build()
71+
assertFalse(uri.queryParameterNames.contains(ParamKey.ATB))
72+
}
73+
5174
}

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,29 @@ class DuckDuckGoUrlDetectorTest {
4646

4747
@Test
4848
fun whenDDGUrlContainsQueryThenQueryCanBeExtracted() {
49-
val query = testee.extractQuery("https://duckduck.com?q=test%20search")
49+
val query = testee.extractQuery("https://duckduckgo.com?q=test%20search")
5050
assertEquals("test search", query)
5151
}
5252

5353
@Test
5454
fun whenDDGUrlDoesNotContainsQueryThenQueryIsNull() {
55-
val query = testee.extractQuery("https://duckduck.com")
55+
val query = testee.extractQuery("https://duckduckgo.com")
5656
assertNull(query)
5757
}
5858

5959
@Test
6060
fun whenDDGUrlContainsQueryThenQueryDetected() {
61-
assertTrue(testee.hasQuery("https://duckduck.com?q=test%20search"))
61+
assertTrue(testee.isDuckDuckGoQueryUrl("https://duckduckgo.com?q=test%20search"))
6262
}
6363

6464
@Test
6565
fun whenDDGUrlDoesNotContainsQueryThenQueryIsNotDetected() {
66-
assertFalse(testee.hasQuery("https://duckduck.com"))
66+
assertFalse(testee.isDuckDuckGoQueryUrl("https://duckduckgo.com"))
67+
}
68+
69+
@Test
70+
fun whenNonDDGUrlContainsQueryThenQueryIsNotDetected() {
71+
assertFalse(testee.isDuckDuckGoQueryUrl("https://example.com?q=test%20search"))
6772
}
6873
}
6974

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@ package com.duckduckgo.app.browser
1919
import android.net.Uri
2020
import android.support.test.runner.AndroidJUnit4
2121
import com.duckduckgo.app.browser.omnibar.QueryUrlConverter
22+
import com.duckduckgo.app.statistics.store.StatisticsDataStore
23+
import com.nhaarman.mockito_kotlin.mock
2224
import org.junit.Assert.*
2325
import org.junit.Test
2426
import org.junit.runner.RunWith
2527

2628
@RunWith(AndroidJUnit4::class)
2729
class QueryUrlConverterTest {
2830

29-
val testee: QueryUrlConverter = QueryUrlConverter(DuckDuckGoRequestRewriter(DuckDuckGoUrlDetector()))
31+
private var mockStatisticsStore: StatisticsDataStore = mock()
32+
private val testee: QueryUrlConverter = QueryUrlConverter(DuckDuckGoRequestRewriter(DuckDuckGoUrlDetector(), mockStatisticsStore))
3033

3134
@Test
3235
fun whenUserIsPresentThenIsWebUrlIsFalse() {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) 2018 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 com.duckduckgo.app.statistics.api.StatisticsService
20+
import com.duckduckgo.app.statistics.api.StatisticsUpdater
21+
import dagger.Module
22+
import dagger.Provides
23+
import retrofit2.Retrofit
24+
25+
@Module
26+
class StubStatisticsModule {
27+
28+
@Provides
29+
fun statisticsService(retrofit: Retrofit): StatisticsService =
30+
retrofit.create(StatisticsService::class.java)
31+
32+
@Provides
33+
fun stubStatisticsUpdater(): StatisticsUpdater {
34+
return object : StatisticsUpdater {
35+
override fun refreshRetentionAtb() {
36+
}
37+
38+
override fun initializeAtb() {
39+
}
40+
}
41+
}
42+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import javax.inject.Singleton
3737
StubDatabaseModule::class,
3838
StubJobSchedulerModule::class,
3939
StubAppConfigurationDownloadModule::class,
40+
StubStatisticsModule::class,
4041

4142
/* real modules */
4243
(ApplicationModule::class),

app/src/androidTest/java/com/duckduckgo/app/migration/LegacyMigrationTest.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import com.duckduckgo.app.browser.omnibar.QueryUrlConverter
2828
import com.duckduckgo.app.global.db.AppDatabase
2929
import com.duckduckgo.app.migration.legacy.LegacyDb
3030
import com.duckduckgo.app.migration.legacy.LegacyDbContracts
31+
import com.duckduckgo.app.statistics.store.StatisticsDataStore
32+
import com.nhaarman.mockito_kotlin.mock
3133
import org.junit.After
3234
import org.junit.Assert.assertEquals
3335
import org.junit.Assert.assertNotEquals
@@ -36,11 +38,12 @@ import org.junit.Test
3638
class LegacyMigrationTest {
3739

3840
// target context else we can't write a db file
39-
val context = InstrumentationRegistry.getTargetContext()
40-
val urlConverter = QueryUrlConverter(DuckDuckGoRequestRewriter(DuckDuckGoUrlDetector()))
41+
private val context = InstrumentationRegistry.getTargetContext()
42+
private var mockStatisticsStore: StatisticsDataStore = mock()
43+
private val urlConverter = QueryUrlConverter(DuckDuckGoRequestRewriter(DuckDuckGoUrlDetector(), mockStatisticsStore))
4144

42-
var appDatabase: AppDatabase = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java).build()
43-
var bookmarksDao = StubBookmarksDao()
45+
private var appDatabase: AppDatabase = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java).build()
46+
private var bookmarksDao = StubBookmarksDao()
4447

4548
@After
4649
fun after() {

0 commit comments

Comments
 (0)