Skip to content

Commit c8c0de6

Browse files
committed
Merge branch 'release/5.18.1'
2 parents 3b51b3b + 828f345 commit c8c0de6

Some content is hidden

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

45 files changed

+2523
-101
lines changed

app/schemas/com.duckduckgo.app.global.db.AppDatabase/10.json

Lines changed: 503 additions & 0 deletions
Large diffs are not rendered by default.

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import com.duckduckgo.app.tabs.model.TabRepository
5656
import com.duckduckgo.app.trackerdetection.model.TrackerNetwork
5757
import com.duckduckgo.app.trackerdetection.model.TrackerNetworks
5858
import com.duckduckgo.app.trackerdetection.model.TrackingEvent
59+
import com.duckduckgo.app.usage.search.SearchCountDao
5960
import com.duckduckgo.app.widget.ui.WidgetCapabilities
6061
import com.nhaarman.mockitokotlin2.*
6162
import org.junit.After
@@ -133,6 +134,9 @@ class BrowserTabViewModelTest {
133134
@Mock
134135
private lateinit var mockDismissedCtaDao: DismissedCtaDao
135136

137+
@Mock
138+
private lateinit var mockSearchCountDao: SearchCountDao
139+
136140
@Mock
137141
private lateinit var mockAppInstallStore: AppInstallStore
138142

@@ -192,7 +196,8 @@ class BrowserTabViewModelTest {
192196
specialUrlDetector = SpecialUrlDetectorImpl(),
193197
faviconDownloader = mockFaviconDownloader,
194198
addToHomeCapabilityDetector = mockAddToHomeCapabilityDetector,
195-
ctaViewModel = ctaViewModel
199+
ctaViewModel = ctaViewModel,
200+
searchCountDao = mockSearchCountDao
196201
)
197202

198203
testee.loadData("abc", null)

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

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@
1717
package com.duckduckgo.app.browser
1818

1919
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
20+
import androidx.lifecycle.MutableLiveData
2021
import androidx.lifecycle.Observer
2122
import com.duckduckgo.app.browser.BrowserViewModel.Command
2223
import com.duckduckgo.app.browser.BrowserViewModel.Command.DisplayMessage
2324
import com.duckduckgo.app.browser.omnibar.OmnibarEntryConverter
2425
import com.duckduckgo.app.fire.DataClearer
26+
import com.duckduckgo.app.global.rating.AppEnjoymentPromptEmitter
27+
import com.duckduckgo.app.global.rating.AppEnjoymentPromptOptions
28+
import com.duckduckgo.app.global.rating.AppEnjoymentUserEventRecorder
29+
import com.duckduckgo.app.global.rating.PromptCount
2530
import com.duckduckgo.app.privacy.ui.PrivacyDashboardActivity
2631
import com.duckduckgo.app.tabs.model.TabEntity
2732
import com.duckduckgo.app.tabs.model.TabRepository
@@ -59,12 +64,27 @@ class BrowserViewModelTest {
5964
@Mock
6065
private lateinit var mockAutomaticDataClearer: DataClearer
6166

67+
@Mock
68+
private lateinit var mockAppEnjoymentUserEventRecorder: AppEnjoymentUserEventRecorder
69+
70+
@Mock
71+
private lateinit var mockAppEnjoymentPromptEmitter: AppEnjoymentPromptEmitter
72+
6273
private lateinit var testee: BrowserViewModel
6374

6475
@Before
6576
fun before() {
6677
MockitoAnnotations.initMocks(this)
67-
testee = BrowserViewModel(mockTabRepository, mockOmnibarEntryConverter, mockAutomaticDataClearer)
78+
79+
doReturn(MutableLiveData<AppEnjoymentPromptOptions>()).whenever(mockAppEnjoymentPromptEmitter).promptType
80+
81+
testee = BrowserViewModel(
82+
tabRepository = mockTabRepository,
83+
queryUrlConverter = mockOmnibarEntryConverter,
84+
dataClearer = mockAutomaticDataClearer,
85+
appEnjoymentPromptEmitter = mockAppEnjoymentPromptEmitter,
86+
appEnjoymentUserEventRecorder = mockAppEnjoymentUserEventRecorder
87+
)
6888
testee.command.observeForever(mockCommandObserver)
6989
whenever(mockTabRepository.add()).thenReturn(TAB_ID)
7090
whenever(mockOmnibarEntryConverter.convertQueryToUrl(any())).then { it.arguments.first() }
@@ -120,6 +140,20 @@ class BrowserViewModelTest {
120140
assertEquals(DisplayMessage(R.string.fireDataCleared), commandCaptor.lastValue)
121141
}
122142

143+
@Test
144+
fun whenUserSelectedToRateAppThenPlayStoreCommandTriggered() {
145+
testee.onUserSelectedToRateApp(PromptCount.first())
146+
verify(mockCommandObserver).onChanged(commandCaptor.capture())
147+
assertEquals(Command.LaunchPlayStore, commandCaptor.lastValue)
148+
}
149+
150+
@Test
151+
fun whenUserSelectedToGiveFeedbackThenFeedbackCommandTriggered() {
152+
testee.onUserSelectedToGiveFeedback(PromptCount.first())
153+
verify(mockCommandObserver).onChanged(commandCaptor.capture())
154+
assertEquals(Command.LaunchFeedbackView, commandCaptor.lastValue)
155+
}
156+
123157
@Test
124158
fun whenViewStateCreatedThenWebViewContentShouldBeHidden() {
125159
assertTrue(testee.viewState.value!!.hideWebContent)

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,13 @@ class StubStatisticsModule {
4949
override fun fire(pixel: Pixel.PixelName, parameters: Map<String, String?>) {
5050
}
5151

52-
override fun fireCompletable(pixel: Pixel.PixelName, parameters: Map<String, String?>): Completable {
53-
return Completable.fromAction {}
52+
override fun fire(pixelName: String, parameters: Map<String, String?>) {
53+
5454
}
5555

56+
override fun fireCompletable(pixelName: String, parameters: Map<String, String?>): Completable {
57+
return Completable.fromAction {}
58+
}
5659
}
5760
}
5861
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ import android.app.Application
2020
import com.duckduckgo.app.browser.autoComplete.BrowserAutoCompleteModule
2121
import com.duckduckgo.app.browser.di.BrowserModule
2222
import com.duckduckgo.app.browser.favicon.FaviconModule
23+
import com.duckduckgo.app.browser.rating.di.RatingModule
2324
import com.duckduckgo.app.httpsupgrade.di.HttpsUpgraderModule
2425
import com.duckduckgo.app.onboarding.di.OnboardingModule
2526
import com.duckduckgo.app.surrogates.di.ResourceSurrogateModule
2627
import com.duckduckgo.app.trackerdetection.di.TrackerDetectionModule
28+
import com.duckduckgo.app.usage.di.AppUsageModule
2729
import dagger.BindsInstance
2830
import dagger.Component
2931
import dagger.android.support.AndroidSupportInjectionModule
@@ -61,7 +63,9 @@ import javax.inject.Singleton
6163
FaviconModule::class,
6264
TrackersModule::class,
6365
PrivacyModule::class,
64-
WidgetModule::class
66+
WidgetModule::class,
67+
RatingModule::class,
68+
AppUsageModule::class
6569
]
6670
)
6771
interface TestAppComponent : AppComponent {

app/src/androidTest/java/com/duckduckgo/app/global/db/AppDatabaseTest.kt

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package com.duckduckgo.app.global.db
1818

1919
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
2020
import androidx.room.Room
21+
import androidx.room.migration.Migration
2122
import androidx.room.testing.MigrationTestHelper
2223
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
2324
import androidx.test.platform.app.InstrumentationRegistry
@@ -39,14 +40,12 @@ class AppDatabaseTest {
3940

4041
@Test
4142
fun whenMigratingFromVersion1To2ThenValidationSucceeds() {
42-
testHelper.createDatabase(TEST_DB_NAME, 1).close()
43-
testHelper.runMigrationsAndValidate(TEST_DB_NAME, 2, true, AppDatabase.MIGRATION_1_TO_2)
43+
createDatabaseAndMigrate(1, 2, AppDatabase.MIGRATION_1_TO_2)
4444
}
4545

4646
@Test
4747
fun whenMigratingFromVersion2To3ThenValidationSucceeds() {
48-
testHelper.createDatabase(TEST_DB_NAME, 2).close()
49-
testHelper.runMigrationsAndValidate(TEST_DB_NAME, 3, true, AppDatabase.MIGRATION_2_TO_3)
48+
createDatabaseAndMigrate(2, 3, AppDatabase.MIGRATION_2_TO_3)
5049
}
5150

5251
@Test
@@ -59,75 +58,78 @@ class AppDatabaseTest {
5958

6059
@Test
6160
fun whenMigratingFromVersion3To4ThenValidationSucceeds() {
62-
testHelper.createDatabase(TEST_DB_NAME, 3).close()
63-
testHelper.runMigrationsAndValidate(TEST_DB_NAME, 4, true, AppDatabase.MIGRATION_3_TO_4)
61+
createDatabaseAndMigrate(3, 4, AppDatabase.MIGRATION_3_TO_4)
6462
}
6563

6664
@Test
6765
fun whenMigratingFromVersion4To5ThenValidationSucceeds() {
68-
testHelper.createDatabase(TEST_DB_NAME, 4).close()
69-
testHelper.runMigrationsAndValidate(TEST_DB_NAME, 5, true, AppDatabase.MIGRATION_4_TO_5)
66+
createDatabaseAndMigrate(4, 5, AppDatabase.MIGRATION_4_TO_5)
67+
}
68+
69+
@Test
70+
fun whenMigratingFromVersion4To5ThenUpdatePositionsOfStoredTabs() {
71+
72+
testHelper.createDatabase(TEST_DB_NAME, 4).use {
73+
it.execSQL("INSERT INTO `tabs` values ('tabid1', 'url', 'title') ")
74+
it.execSQL("INSERT INTO `tabs` values ('tabid2', 'url', 'title') ")
75+
}
76+
77+
assertEquals(0, database().tabsDao().tabs()[0].position)
78+
assertEquals(1, database().tabsDao().tabs()[1].position)
79+
}
80+
81+
@Test
82+
fun whenMigratingFromVersion4To5ThenTabsAreConsideredViewed() {
83+
84+
testHelper.createDatabase(TEST_DB_NAME, 4).use {
85+
it.execSQL("INSERT INTO `tabs` values ('tabid1', 'url', 'title') ")
86+
}
87+
88+
assertTrue(database().tabsDao().tabs()[0].viewed)
7089
}
7190

7291
@Test
7392
fun whenMigratingFromVersion5To6ThenValidationSucceeds() {
74-
testHelper.createDatabase(TEST_DB_NAME, 5).close()
75-
testHelper.runMigrationsAndValidate(TEST_DB_NAME, 6, true, AppDatabase.MIGRATION_5_TO_6)
93+
createDatabaseAndMigrate(5, 6, AppDatabase.MIGRATION_5_TO_6)
7694
}
7795

7896
@Test
7997
fun whenMigratingFromVersion6To7ThenValidationSucceeds() {
80-
testHelper.createDatabase(TEST_DB_NAME, 6).close()
81-
testHelper.runMigrationsAndValidate(TEST_DB_NAME, 7, true, AppDatabase.MIGRATION_6_TO_7)
98+
createDatabaseAndMigrate(6, 7, AppDatabase.MIGRATION_6_TO_7)
8299
}
83100

84101
@Test
85102
fun whenMigratingFromVersion7To8ThenValidationSucceeds() {
86-
testHelper.createDatabase(TEST_DB_NAME, 7).close()
87-
testHelper.runMigrationsAndValidate(TEST_DB_NAME, 8, true, AppDatabase.MIGRATION_7_TO_8)
103+
createDatabaseAndMigrate(7, 8, AppDatabase.MIGRATION_7_TO_8)
88104
}
89105

90106
@Test
91107
fun whenMigratingFromVersion8To9ThenValidationSucceeds() {
92-
testHelper.createDatabase(TEST_DB_NAME, 8).close()
93-
testHelper.runMigrationsAndValidate(TEST_DB_NAME, 9, true, AppDatabase.MIGRATION_8_TO_9)
108+
createDatabaseAndMigrate(8, 9, AppDatabase.MIGRATION_8_TO_9)
94109
}
95110

96111
@Test
97-
fun whenMigratingFromVersion4To5ThenUpdatePositionsOfStoredTabs() {
98-
99-
testHelper.createDatabase(TEST_DB_NAME, 4).use {
100-
it.execSQL("INSERT INTO `tabs` values ('tabid1', 'url', 'title') ")
101-
it.execSQL("INSERT INTO `tabs` values ('tabid2', 'url', 'title') ")
102-
}
103-
104-
assertEquals(0, database().tabsDao().tabs()[0].position)
105-
assertEquals(1, database().tabsDao().tabs()[1].position)
112+
fun whenMigratingFromVersion9To10ThenValidationSucceeds() {
113+
createDatabaseAndMigrate(9, 10, AppDatabase.MIGRATION_9_TO_10)
106114
}
107115

108-
@Test
109-
fun whenMigratingFromVersion4To5ThenTabsAreConsideredViewed() {
116+
private fun createDatabase(version: Int) {
117+
testHelper.createDatabase(TEST_DB_NAME, version).close()
118+
}
110119

111-
testHelper.createDatabase(TEST_DB_NAME, 4).use {
112-
it.execSQL("INSERT INTO `tabs` values ('tabid1', 'url', 'title') ")
113-
}
120+
private fun runMigrations(newVersion: Int, vararg migrations: Migration) {
121+
testHelper.runMigrationsAndValidate(TEST_DB_NAME, newVersion, true, *migrations)
122+
}
114123

115-
assertTrue(database().tabsDao().tabs()[0].viewed)
124+
private fun createDatabaseAndMigrate(originalVersion: Int, newVersion: Int, vararg migrations: Migration) {
125+
createDatabase(originalVersion)
126+
runMigrations(newVersion, *migrations)
116127
}
117128

118129
private fun database(): AppDatabase {
119130
val database = Room
120131
.databaseBuilder(InstrumentationRegistry.getInstrumentation().targetContext, AppDatabase::class.java, TEST_DB_NAME)
121-
.addMigrations(
122-
AppDatabase.MIGRATION_1_TO_2,
123-
AppDatabase.MIGRATION_2_TO_3,
124-
AppDatabase.MIGRATION_3_TO_4,
125-
AppDatabase.MIGRATION_4_TO_5,
126-
AppDatabase.MIGRATION_5_TO_6,
127-
AppDatabase.MIGRATION_6_TO_7,
128-
AppDatabase.MIGRATION_7_TO_8,
129-
AppDatabase.MIGRATION_8_TO_9
130-
)
132+
.addMigrations(*AppDatabase.ALL_MIGRATIONS.toTypedArray())
131133
.allowMainThreadQueries()
132134
.build()
133135

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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.global.rating
18+
19+
import com.duckduckgo.app.browser.rating.db.AppEnjoymentRepository
20+
import com.duckduckgo.app.usage.app.AppDaysUsedRepository
21+
import com.nhaarman.mockitokotlin2.mock
22+
import com.nhaarman.mockitokotlin2.whenever
23+
import kotlinx.coroutines.runBlocking
24+
import org.junit.Assert.assertFalse
25+
import org.junit.Assert.assertTrue
26+
import org.junit.Before
27+
import org.junit.Test
28+
29+
@Suppress("RemoveExplicitTypeArguments")
30+
class InitialPromptDeciderTest {
31+
32+
private lateinit var testee: InitialPromptDecider
33+
34+
private val mockAppDaysUsedRepository: AppDaysUsedRepository = mock()
35+
private val mockAppEnjoymentRepository: AppEnjoymentRepository = mock()
36+
37+
private val NOT_ENOUGH_DAYS = (MINIMUM_DAYS_USAGE_BEFORE_FIRST_PROMPT - 1).toLong()
38+
private val EXACT_NUMBER_OF_DAYS = MINIMUM_DAYS_USAGE_BEFORE_FIRST_PROMPT.toLong()
39+
private val MORE_THAN_ENOUGH_DAYS = (MINIMUM_DAYS_USAGE_BEFORE_FIRST_PROMPT + 1).toLong()
40+
41+
@Before
42+
fun setup() {
43+
testee = InitialPromptDecider(mockAppDaysUsedRepository, mockAppEnjoymentRepository)
44+
}
45+
46+
@Test
47+
fun whenUserHasNotSeenPromptBeforeAndNotUsedTheAppEnoughThenShouldNotSeePrompt() = runBlocking<Unit> {
48+
whenever(mockAppDaysUsedRepository.getNumberOfDaysAppUsed()).thenReturn(NOT_ENOUGH_DAYS)
49+
whenever(mockAppEnjoymentRepository.hasUserPreviouslySeenFirstPrompt()).thenReturn(false)
50+
assertFalse(testee.shouldShowPrompt())
51+
}
52+
53+
@Test
54+
fun whenUserHasNotSeenPromptBeforeAndUsedTheAppExactEnoughDaysThenShouldSeePrompt() = runBlocking<Unit> {
55+
whenever(mockAppDaysUsedRepository.getNumberOfDaysAppUsed()).thenReturn(EXACT_NUMBER_OF_DAYS)
56+
whenever(mockAppEnjoymentRepository.hasUserPreviouslySeenFirstPrompt()).thenReturn(false)
57+
assertTrue(testee.shouldShowPrompt())
58+
}
59+
60+
@Test
61+
fun whenUserHasNotSeenPromptBeforeAndUsedTheAppMoreThanEnoughDaysThenShouldSeePrompt() = runBlocking<Unit> {
62+
whenever(mockAppDaysUsedRepository.getNumberOfDaysAppUsed()).thenReturn(MORE_THAN_ENOUGH_DAYS)
63+
whenever(mockAppEnjoymentRepository.hasUserPreviouslySeenFirstPrompt()).thenReturn(false)
64+
assertTrue(testee.shouldShowPrompt())
65+
}
66+
67+
@Test
68+
fun whenUserHasSeenPromptBeforeAndNotUsedTheAppEnoughThenShouldNotSeePrompt() = runBlocking<Unit> {
69+
whenever(mockAppDaysUsedRepository.getNumberOfDaysAppUsed()).thenReturn(NOT_ENOUGH_DAYS)
70+
whenever(mockAppEnjoymentRepository.hasUserPreviouslySeenFirstPrompt()).thenReturn(true)
71+
assertFalse(testee.shouldShowPrompt())
72+
}
73+
74+
@Test
75+
fun whenUserHasSeenPromptBeforeAndUsedTheAppExactEnoughDaysThenShouldNotSeePrompt() = runBlocking<Unit> {
76+
whenever(mockAppDaysUsedRepository.getNumberOfDaysAppUsed()).thenReturn(EXACT_NUMBER_OF_DAYS)
77+
whenever(mockAppEnjoymentRepository.hasUserPreviouslySeenFirstPrompt()).thenReturn(true)
78+
assertFalse(testee.shouldShowPrompt())
79+
}
80+
81+
@Test
82+
fun whenUserHasSeenPromptBeforeAndUsedTheAppMoreThanEnoughDaysThenShouldNotSeePrompt() = runBlocking<Unit> {
83+
whenever(mockAppDaysUsedRepository.getNumberOfDaysAppUsed()).thenReturn(MORE_THAN_ENOUGH_DAYS)
84+
whenever(mockAppEnjoymentRepository.hasUserPreviouslySeenFirstPrompt()).thenReturn(true)
85+
assertFalse(testee.shouldShowPrompt())
86+
}
87+
88+
}

0 commit comments

Comments
 (0)