Skip to content

Commit 305a0d4

Browse files
committed
Merge branch 'release/5.20.0'
2 parents 26312e2 + 544781e commit 305a0d4

File tree

142 files changed

+4433
-731
lines changed

Some content is hidden

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

142 files changed

+4433
-731
lines changed

app/build.gradle

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,15 @@ android {
7878

7979
ext {
8080
androidX = "1.0.2"
81-
materialDesign = "1.1.0-alpha02"
81+
materialDesign = "1.0.0"
8282
architectureComponents = "1.1.1"
8383
architectureComponentsExtensions = "1.1.1"
8484
androidKtx = "1.0.1"
85+
fragmentKtx = "1.0.0"
8586
constraintLayout = "2.0.0-alpha3"
8687
lifecycle = "2.0.0"
87-
room = "2.1.0-alpha04"
88-
workManager = "1.0.0-beta03"
88+
room = "2.1.0-alpha05"
89+
workManager = "2.0.0"
8990
legacySupport = "1.0.0"
9091
espressoCore = "3.1.1"
9192
coreTesting = "2.0.0"
@@ -101,7 +102,7 @@ ext {
101102
okHttp = "3.10.0"
102103
rxJava = "2.1.10"
103104
rxAndroid = "2.0.2"
104-
timber = "4.6.1"
105+
timber = "4.7.1"
105106
rxRelay = "2.0.0"
106107
leakCanary = "1.6.2"
107108
mockito = "2.18.3"
@@ -112,6 +113,8 @@ ext {
112113

113114
dependencies {
114115
implementation "androidx.legacy:legacy-support-v4:$legacySupport"
116+
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0-beta01'
117+
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.0.0'
115118
debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanary"
116119
releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$leakCanary"
117120

@@ -124,6 +127,7 @@ dependencies {
124127
implementation "com.squareup.retrofit2:retrofit:$retrofit"
125128
implementation "com.squareup.retrofit2:converter-moshi:$retrofit"
126129
implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit"
130+
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
127131
implementation "io.reactivex.rxjava2:rxjava:$rxJava"
128132
implementation "io.reactivex.rxjava2:rxandroid:$rxAndroid"
129133
implementation "com.jakewharton.timber:timber:$timber"
@@ -139,6 +143,7 @@ dependencies {
139143

140144
// Android KTX
141145
implementation "androidx.core:core-ktx:$androidKtx"
146+
implementation "androidx.fragment:fragment-ktx:$fragmentKtx"
142147

143148
// ViewModel and LiveData
144149
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle"
@@ -153,7 +158,7 @@ dependencies {
153158
androidTestImplementation "androidx.room:room-testing:$room"
154159

155160
// WorkManager
156-
implementation "android.arch.work:work-runtime-ktx:$workManager"
161+
implementation "androidx.work:work-runtime-ktx:$workManager"
157162

158163
// Dagger
159164
kapt "com.google.dagger:dagger-android-processor:$dagger"

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package com.duckduckgo.app.browser
1818

1919
import android.view.MenuItem
2020
import android.view.View
21+
import android.webkit.WebView
2122
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
2223
import androidx.lifecycle.MutableLiveData
2324
import androidx.lifecycle.Observer
@@ -34,11 +35,12 @@ import com.duckduckgo.app.browser.LongPressHandler.RequiredAction.DownloadFile
3435
import com.duckduckgo.app.browser.LongPressHandler.RequiredAction.OpenInNewTab
3536
import com.duckduckgo.app.browser.addtohome.AddToHomeCapabilityDetector
3637
import com.duckduckgo.app.browser.favicon.FaviconDownloader
38+
import com.duckduckgo.app.browser.model.LongPressTarget
3739
import com.duckduckgo.app.browser.omnibar.OmnibarEntryConverter
3840
import com.duckduckgo.app.browser.session.WebViewSessionStorage
3941
import com.duckduckgo.app.cta.db.DismissedCtaDao
4042
import com.duckduckgo.app.cta.ui.CtaViewModel
41-
import com.duckduckgo.app.feedback.db.SurveyDao
43+
import com.duckduckgo.app.survey.db.SurveyDao
4244
import com.duckduckgo.app.global.db.AppConfigurationDao
4345
import com.duckduckgo.app.global.db.AppConfigurationEntity
4446
import com.duckduckgo.app.global.db.AppDatabase
@@ -435,7 +437,7 @@ class BrowserTabViewModelTest {
435437
@Test
436438
fun whenUrlChangedWithDuckDuckGoUrlContainingQueryThenAtbRefreshed() {
437439
changeUrl("http://duckduckgo.com?q=test")
438-
verify(mockStatisticsUpdater).refreshRetentionAtb()
440+
verify(mockStatisticsUpdater).refreshSearchRetentionAtb()
439441
}
440442

441443
@Test
@@ -695,11 +697,12 @@ class BrowserTabViewModelTest {
695697

696698
@Test
697699
fun whenUserSelectsDownloadImageOptionFromContextMenuThenDownloadFileCommandIssued() {
698-
whenever(mockLongPressHandler.userSelectedMenuItem(anyString(), any()))
700+
whenever(mockLongPressHandler.userSelectedMenuItem(any(), any()))
699701
.thenReturn(DownloadFile("example.com"))
700702

701703
val mockMenuItem: MenuItem = mock()
702-
testee.userSelectedItemFromLongPressMenu("example.com", mockMenuItem)
704+
val longPressTarget = LongPressTarget(url = "example.com", type = WebView.HitTestResult.SRC_ANCHOR_TYPE)
705+
testee.userSelectedItemFromLongPressMenu(longPressTarget, mockMenuItem)
703706
verify(mockCommandObserver, atLeastOnce()).onChanged(commandCaptor.capture())
704707
assertTrue(commandCaptor.lastValue is Command.DownloadImage)
705708

@@ -781,7 +784,8 @@ class BrowserTabViewModelTest {
781784
fun whenUserSelectsOpenTabThenTabCommandSent() {
782785
whenever(mockLongPressHandler.userSelectedMenuItem(any(), any())).thenReturn(OpenInNewTab("http://example.com"))
783786
val mockMenItem: MenuItem = mock()
784-
testee.userSelectedItemFromLongPressMenu("http://example.com", mockMenItem)
787+
val longPressTarget = LongPressTarget(url = "http://example.com", type = WebView.HitTestResult.SRC_ANCHOR_TYPE)
788+
testee.userSelectedItemFromLongPressMenu(longPressTarget, mockMenItem)
785789
val command = captureCommands().value as Command.OpenInNewTab
786790
assertEquals("http://example.com", command.query)
787791
}

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import android.view.ContextMenu
2020
import android.view.MenuItem
2121
import android.webkit.WebView.HitTestResult
2222
import androidx.test.platform.app.InstrumentationRegistry
23+
import com.duckduckgo.app.browser.model.LongPressTarget
2324
import com.duckduckgo.app.statistics.pixels.Pixel
2425
import com.nhaarman.mockitokotlin2.eq
2526
import com.nhaarman.mockitokotlin2.never
@@ -127,22 +128,25 @@ class WebViewLongPressHandlerTest {
127128
@Test
128129
fun whenUserSelectedDownloadImageOptionThenActionIsDownloadFileActionRequired() {
129130
whenever(mockMenuItem.itemId).thenReturn(WebViewLongPressHandler.CONTEXT_MENU_ID_DOWNLOAD_IMAGE)
130-
val action = testee.userSelectedMenuItem("example.com", mockMenuItem)
131+
val longPressTarget = LongPressTarget(url = "example.com", type = HitTestResult.SRC_ANCHOR_TYPE)
132+
val action = testee.userSelectedMenuItem(longPressTarget, mockMenuItem)
131133
assertTrue(action is LongPressHandler.RequiredAction.DownloadFile)
132134
}
133135

134136
@Test
135137
fun whenUserSelectedDownloadImageOptionThenDownloadFileWithCorrectUrlReturned() {
136138
whenever(mockMenuItem.itemId).thenReturn(WebViewLongPressHandler.CONTEXT_MENU_ID_DOWNLOAD_IMAGE)
137-
val action = testee.userSelectedMenuItem("example.com", mockMenuItem) as LongPressHandler.RequiredAction.DownloadFile
139+
val longPressTarget = LongPressTarget(url = "example.com", type = HitTestResult.SRC_ANCHOR_TYPE)
140+
val action = testee.userSelectedMenuItem(longPressTarget, mockMenuItem) as LongPressHandler.RequiredAction.DownloadFile
138141
assertEquals("example.com", action.url)
139142
}
140143

141144
@Test
142145
fun whenUserSelectedUnknownOptionThenNoActionRequiredReturned() {
143146
val unknownMenuId = 123
144147
whenever(mockMenuItem.itemId).thenReturn(unknownMenuId)
145-
val action = testee.userSelectedMenuItem("example.com", mockMenuItem)
148+
val longPressTarget = LongPressTarget(url = "example.com", type = HitTestResult.SRC_ANCHOR_TYPE)
149+
val action = testee.userSelectedMenuItem(longPressTarget, mockMenuItem)
146150
assertTrue(action == LongPressHandler.RequiredAction.None)
147151
}
148152

app/src/androidTest/java/com/duckduckgo/app/cta/ui/CtaViewModelTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ import com.duckduckgo.app.InstantSchedulersRule
2323
import com.duckduckgo.app.cta.db.DismissedCtaDao
2424
import com.duckduckgo.app.cta.model.CtaId
2525
import com.duckduckgo.app.cta.model.DismissedCta
26-
import com.duckduckgo.app.feedback.db.SurveyDao
27-
import com.duckduckgo.app.feedback.model.Survey
28-
import com.duckduckgo.app.feedback.model.Survey.Status.SCHEDULED
2926
import com.duckduckgo.app.global.db.AppDatabase
3027
import com.duckduckgo.app.global.install.AppInstallStore
3128
import com.duckduckgo.app.statistics.pixels.Pixel
3229
import com.duckduckgo.app.statistics.pixels.Pixel.PixelName.*
30+
import com.duckduckgo.app.survey.db.SurveyDao
31+
import com.duckduckgo.app.survey.model.Survey
32+
import com.duckduckgo.app.survey.model.Survey.Status.SCHEDULED
3333
import com.duckduckgo.app.widget.ui.WidgetCapabilities
3434
import com.nhaarman.mockitokotlin2.any
3535
import com.nhaarman.mockitokotlin2.eq

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,16 @@ class StubStatisticsModule {
3434
@Provides
3535
fun stubStatisticsUpdater(): StatisticsUpdater {
3636
return object : StatisticsUpdater {
37-
override fun refreshRetentionAtb() {
38-
}
3937

4038
override fun initializeAtb() {
4139
}
40+
41+
override fun refreshAppRetentionAtb() {
42+
}
43+
44+
override fun refreshSearchRetentionAtb() {
45+
}
46+
4247
}
4348
}
4449

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package com.duckduckgo.app.feedback.ui
2+
3+
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
4+
import androidx.lifecycle.Observer
5+
import com.duckduckgo.app.InstantSchedulersRule
6+
import com.duckduckgo.app.brokensite.BrokenSiteViewModel
7+
import com.duckduckgo.app.brokensite.BrokenSiteViewModel.Command
8+
import com.duckduckgo.app.brokensite.api.BrokenSiteSender
9+
import com.nhaarman.mockitokotlin2.any
10+
import com.nhaarman.mockitokotlin2.never
11+
import com.nhaarman.mockitokotlin2.verify
12+
import org.junit.After
13+
import org.junit.Assert.assertFalse
14+
import org.junit.Assert.assertTrue
15+
import org.junit.Before
16+
import org.junit.Rule
17+
import org.junit.Test
18+
import org.mockito.Mock
19+
import org.mockito.MockitoAnnotations
20+
21+
class BrokenSiteViewModelTest {
22+
23+
@get:Rule
24+
@Suppress("unused")
25+
var instantTaskExecutorRule = InstantTaskExecutorRule()
26+
27+
@get:Rule
28+
@Suppress("unused")
29+
val schedulers = InstantSchedulersRule()
30+
31+
@Mock
32+
private lateinit var mockBrokenSiteSender: BrokenSiteSender
33+
34+
@Mock
35+
private lateinit var mockCommandObserver: Observer<BrokenSiteViewModel.Command>
36+
37+
private lateinit var testee: BrokenSiteViewModel
38+
39+
private val viewState: BrokenSiteViewModel.ViewState
40+
get() = testee.viewState.value!!
41+
42+
@Before
43+
fun before() {
44+
MockitoAnnotations.initMocks(this)
45+
testee = BrokenSiteViewModel(mockBrokenSiteSender)
46+
testee.command.observeForever(mockCommandObserver)
47+
}
48+
49+
@After
50+
fun after() {
51+
testee.command.removeObserver(mockCommandObserver)
52+
}
53+
54+
@Test
55+
fun whenInitializedThenCannotSubmit() {
56+
assertFalse(viewState.submitAllowed)
57+
}
58+
59+
@Test
60+
fun whenNoUrlProvidedThenUrlFocused() {
61+
testee.setInitialBrokenSite(null)
62+
verify(mockCommandObserver).onChanged(Command.FocusUrl)
63+
}
64+
65+
@Test
66+
fun whenUrlProvidedThenMessageFocused() {
67+
testee.setInitialBrokenSite(url)
68+
verify(mockCommandObserver).onChanged(Command.FocusMessage)
69+
}
70+
71+
@Test
72+
fun whenUrlAndMessageNotEmptyThenCanSubmit() {
73+
testee.onBrokenSiteUrlChanged(url)
74+
testee.onFeedbackMessageChanged(message)
75+
assertTrue(viewState.submitAllowed)
76+
}
77+
78+
@Test
79+
fun whenNullUrlThenCannotSubmit() {
80+
testee.onBrokenSiteUrlChanged(null)
81+
testee.onFeedbackMessageChanged(message)
82+
assertFalse(viewState.submitAllowed)
83+
}
84+
85+
@Test
86+
fun whenEmptyUrlThenCannotSubmit() {
87+
testee.onBrokenSiteUrlChanged(" ")
88+
testee.onFeedbackMessageChanged(message)
89+
assertFalse(viewState.submitAllowed)
90+
}
91+
92+
@Test
93+
fun whenNullMessageThenCannotSubmit() {
94+
testee.onBrokenSiteUrlChanged(url)
95+
testee.onFeedbackMessageChanged(null)
96+
assertFalse(viewState.submitAllowed)
97+
}
98+
99+
@Test
100+
fun whenEmptyMessageThenCannotSubmit() {
101+
testee.onBrokenSiteUrlChanged(url)
102+
testee.onFeedbackMessageChanged(" ")
103+
assertFalse(viewState.submitAllowed)
104+
}
105+
106+
@Test
107+
fun whenCanSubmitBrokenSiteAndSubmitPressedThenFeedbackSubmitted() {
108+
testee.onBrokenSiteUrlChanged(url)
109+
testee.onFeedbackMessageChanged(message)
110+
testee.onSubmitPressed()
111+
112+
verify(mockBrokenSiteSender).submitBrokenSiteFeedback(message, url)
113+
verify(mockCommandObserver).onChanged(Command.ConfirmAndFinish)
114+
}
115+
116+
@Test
117+
fun whenCannotSubmitBrokenSiteAndSubmitPressedThenFeedbackNotSubmitted() {
118+
testee.onSubmitPressed()
119+
verify(mockBrokenSiteSender, never()).submitBrokenSiteFeedback(any(), any())
120+
verify(mockCommandObserver, never()).onChanged(Command.ConfirmAndFinish)
121+
}
122+
123+
companion object Constants {
124+
private const val url = "http://example.com"
125+
private const val message = "Feedback message"
126+
}
127+
128+
}

0 commit comments

Comments
 (0)