Skip to content

Commit 797064c

Browse files
committed
Merge branch 'release/5.21.0'
2 parents 305a0d4 + 00db245 commit 797064c

Some content is hidden

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

47 files changed

+1726
-194
lines changed

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

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

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

Lines changed: 31 additions & 1 deletion
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.HttpAuthHandler
2122
import android.webkit.WebView
2223
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
2324
import androidx.lifecycle.MutableLiveData
@@ -38,9 +39,10 @@ import com.duckduckgo.app.browser.favicon.FaviconDownloader
3839
import com.duckduckgo.app.browser.model.LongPressTarget
3940
import com.duckduckgo.app.browser.omnibar.OmnibarEntryConverter
4041
import com.duckduckgo.app.browser.session.WebViewSessionStorage
42+
import com.duckduckgo.app.browser.model.BasicAuthenticationCredentials
43+
import com.duckduckgo.app.browser.model.BasicAuthenticationRequest
4144
import com.duckduckgo.app.cta.db.DismissedCtaDao
4245
import com.duckduckgo.app.cta.ui.CtaViewModel
43-
import com.duckduckgo.app.survey.db.SurveyDao
4446
import com.duckduckgo.app.global.db.AppConfigurationDao
4547
import com.duckduckgo.app.global.db.AppConfigurationEntity
4648
import com.duckduckgo.app.global.db.AppDatabase
@@ -54,6 +56,7 @@ import com.duckduckgo.app.privacy.store.PrevalenceStore
5456
import com.duckduckgo.app.settings.db.SettingsDataStore
5557
import com.duckduckgo.app.statistics.api.StatisticsUpdater
5658
import com.duckduckgo.app.statistics.pixels.Pixel
59+
import com.duckduckgo.app.survey.db.SurveyDao
5760
import com.duckduckgo.app.tabs.model.TabRepository
5861
import com.duckduckgo.app.trackerdetection.model.TrackerNetwork
5962
import com.duckduckgo.app.trackerdetection.model.TrackerNetworks
@@ -855,6 +858,33 @@ class BrowserTabViewModelTest {
855858
assertFalse(globalLayoutViewState().isNewTabState)
856859
}
857860

861+
@Test
862+
fun whenAuthenticationIsRequiredThenRequiresAuthenticationCommandSent() {
863+
val mockHandler = mock<HttpAuthHandler>()
864+
val siteURL = "http://example.com/requires-auth"
865+
val authenticationRequest = BasicAuthenticationRequest(mockHandler, "example.com", "test realm", siteURL)
866+
testee.requiresAuthentication(authenticationRequest)
867+
verify(mockCommandObserver, atLeastOnce()).onChanged(commandCaptor.capture())
868+
869+
val command = commandCaptor.lastValue
870+
assertTrue(command is Command.RequiresAuthentication)
871+
872+
val requiresAuthCommand = command as Command.RequiresAuthentication
873+
assertSame(authenticationRequest, requiresAuthCommand.request)
874+
}
875+
876+
@Test
877+
fun whenHandleAuthenticationThenHandlerCalledWithParameters() {
878+
val mockHandler = mock<HttpAuthHandler>()
879+
val username = "user"
880+
val password = "password"
881+
val authenticationRequest = BasicAuthenticationRequest(mockHandler, "example.com", "test realm", "")
882+
val credentials = BasicAuthenticationCredentials(username = username, password = password)
883+
testee.handleAuthentication(request = authenticationRequest, credentials = credentials)
884+
885+
verify(mockHandler, atLeastOnce()).proceed(username, password)
886+
}
887+
858888
private fun changeUrl(url: String?) {
859889
testee.loadingStarted(url)
860890
testee.progressChanged(url, 100)

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

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
package com.duckduckgo.app.browser
1818

1919
import android.content.Context
20+
import android.webkit.HttpAuthHandler
2021
import android.webkit.WebView
2122
import androidx.test.annotation.UiThreadTest
2223
import androidx.test.platform.app.InstrumentationRegistry
24+
import com.duckduckgo.app.browser.model.BasicAuthenticationRequest
2325
import com.duckduckgo.app.httpsupgrade.HttpsUpgrader
2426
import com.duckduckgo.app.statistics.pixels.Pixel
2527
import com.duckduckgo.app.statistics.store.StatisticsDataStore
@@ -46,8 +48,14 @@ class BrowserWebViewClientTest {
4648
@Before
4749
fun setup() {
4850
webView = TestWebView(InstrumentationRegistry.getInstrumentation().targetContext)
49-
50-
testee = BrowserWebViewClient(requestRewriter, specialUrlDetector, requestInterceptor, httpsUpgrader, statisticsDataStore, pixel)
51+
testee = BrowserWebViewClient(
52+
requestRewriter,
53+
specialUrlDetector,
54+
requestInterceptor,
55+
httpsUpgrader,
56+
statisticsDataStore,
57+
pixel
58+
)
5159
testee.webViewClientListener = listener
5260
}
5361

@@ -72,6 +80,15 @@ class BrowserWebViewClientTest {
7280
verify(listener).navigationOptionsChanged(any())
7381
}
7482

83+
@UiThreadTest
84+
@Test
85+
fun whenOnReceivedHttpAuthRequestThenListenerNotified() {
86+
val mockHandler = mock<HttpAuthHandler>()
87+
val authenticationRequest = BasicAuthenticationRequest(mockHandler, EXAMPLE_URL, EXAMPLE_URL, EXAMPLE_URL)
88+
testee.onReceivedHttpAuthRequest(webView, mockHandler, EXAMPLE_URL, EXAMPLE_URL)
89+
verify(listener).requiresAuthentication(authenticationRequest)
90+
}
91+
7592
private class TestWebView(context: Context) : WebView(context)
7693

7794
companion object {

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.duckduckgo.app.browser
1919
import android.content.Context
2020
import android.webkit.WebStorage
2121
import android.webkit.WebView
22+
import android.webkit.WebViewDatabase
2223
import androidx.test.annotation.UiThreadTest
2324
import androidx.test.platform.app.InstrumentationRegistry
2425
import com.duckduckgo.app.browser.session.WebViewSessionInMemoryStorage
@@ -41,10 +42,15 @@ class WebViewDataManagerTest {
4142
fun whenDataClearedThenCacheHistoryAndStorageDataCleared() {
4243
val context = InstrumentationRegistry.getInstrumentation().targetContext
4344
val webView = TestWebView(context)
44-
testee.clearData(webView, mockStorage, context)
45+
val mockWebViewDatabase = mock<WebViewDatabase>()
46+
47+
testee.clearData(webView, mockStorage, mockWebViewDatabase)
48+
4549
assertTrue(webView.historyCleared)
4650
assertTrue(webView.cacheCleared)
51+
assertTrue(webView.clearedFormData)
4752
verify(mockStorage).deleteAllData()
53+
verify(mockWebViewDatabase).clearHttpAuthUsernamePassword()
4854
}
4955

5056
@Test
@@ -57,6 +63,7 @@ class WebViewDataManagerTest {
5763

5864
var historyCleared: Boolean = false
5965
var cacheCleared: Boolean = false
66+
var clearedFormData: Boolean = false
6067

6168
override fun clearHistory() {
6269
super.clearHistory()
@@ -71,5 +78,10 @@ class WebViewDataManagerTest {
7178
cacheCleared = true
7279
}
7380
}
81+
82+
override fun clearFormData() {
83+
super.clearFormData()
84+
clearedFormData = true
85+
}
7486
}
7587
}

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import android.webkit.WebView
2323
import androidx.test.annotation.UiThreadTest
2424
import androidx.test.platform.app.InstrumentationRegistry
2525
import com.duckduckgo.app.httpsupgrade.HttpsUpgrader
26+
import com.duckduckgo.app.privacy.db.PrivacyProtectionCountDao
2627
import com.duckduckgo.app.surrogates.ResourceSurrogates
2728
import com.duckduckgo.app.surrogates.SurrogateResponse
2829
import com.duckduckgo.app.trackerdetection.TrackerDetector
@@ -32,21 +33,17 @@ import org.junit.Assert.*
3233
import org.junit.Before
3334
import org.junit.Test
3435
import org.mockito.ArgumentMatchers.anyString
35-
import org.mockito.Mock
3636
import org.mockito.MockitoAnnotations
3737

3838
class WebViewRequestInterceptorTest {
3939

4040
private lateinit var testee: WebViewRequestInterceptor
4141

42-
@Mock
43-
private lateinit var mockTrackerDetector: TrackerDetector
44-
@Mock
45-
private lateinit var mockHttpsUpgrader: HttpsUpgrader
46-
@Mock
47-
private lateinit var mockResourceSurrogates: ResourceSurrogates
48-
@Mock
49-
private lateinit var mockRequest: WebResourceRequest
42+
private var mockTrackerDetector: TrackerDetector = mock()
43+
private var mockHttpsUpgrader: HttpsUpgrader = mock()
44+
private var mockResourceSurrogates: ResourceSurrogates = mock()
45+
private var mockRequest: WebResourceRequest = mock()
46+
private val mockPrivacyProtectionCountDao: PrivacyProtectionCountDao = mock()
5047

5148
private lateinit var webView: WebView
5249

@@ -58,7 +55,8 @@ class WebViewRequestInterceptorTest {
5855
testee = WebViewRequestInterceptor(
5956
trackerDetector = mockTrackerDetector,
6057
httpsUpgrader = mockHttpsUpgrader,
61-
resourceSurrogates = mockResourceSurrogates
58+
resourceSurrogates = mockResourceSurrogates,
59+
privacyProtectionCountDao = mockPrivacyProtectionCountDao
6260
)
6361

6462
val context = InstrumentationRegistry.getInstrumentation().targetContext

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ class AppDatabaseTest {
113113
createDatabaseAndMigrate(9, 10, AppDatabase.MIGRATION_9_TO_10)
114114
}
115115

116+
@Test
117+
fun whenMigratingFromVersion10To11ThenValidationSucceeds() {
118+
createDatabaseAndMigrate(10, 11, AppDatabase.MIGRATION_10_TO_11)
119+
}
120+
116121
private fun createDatabase(version: Int) {
117122
testHelper.createDatabase(TEST_DB_NAME, version).close()
118123
}

app/src/androidTest/java/com/duckduckgo/app/notification/NotificationHandlerServiceTest.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
package com.duckduckgo.app.notification
1818

1919
import android.content.Intent
20+
import androidx.core.app.NotificationManagerCompat
2021
import androidx.test.platform.app.InstrumentationRegistry
21-
import com.duckduckgo.app.notification.NotificationHandlerService.NotificationEvent.CLEAR_DATA_CANCELLED
22-
import com.duckduckgo.app.notification.NotificationHandlerService.NotificationEvent.CLEAR_DATA_LAUNCHED
22+
import com.duckduckgo.app.notification.NotificationHandlerService.Companion.PIXEL_SUFFIX_EXTRA
23+
import com.duckduckgo.app.notification.NotificationHandlerService.NotificationEvent.CANCEL
24+
import com.duckduckgo.app.notification.NotificationHandlerService.NotificationEvent.CLEAR_DATA_LAUNCH
2325
import com.duckduckgo.app.statistics.pixels.Pixel
2426
import com.nhaarman.mockitokotlin2.any
2527
import com.nhaarman.mockitokotlin2.eq
@@ -39,21 +41,24 @@ class NotificationHandlerServiceTest {
3941
fun before() {
4042
testee.pixel = mockPixel
4143
testee.context = context
44+
testee.notificationManager = NotificationManagerCompat.from(context)
4245
}
4346

4447
@Test
4548
fun whenIntentIsClearDataLaunchedThenCorrespondingPixelIsFired() {
4649
val intent = Intent(context, NotificationHandlerService::class.java)
47-
intent.type = CLEAR_DATA_LAUNCHED
50+
intent.type = CLEAR_DATA_LAUNCH
51+
intent.putExtra(PIXEL_SUFFIX_EXTRA, "abc")
4852
testee.onHandleIntent(intent)
49-
verify(mockPixel).fire(eq(Pixel.PixelName.NOTIFICATION_LAUNCHED), any())
53+
verify(mockPixel).fire(eq("mnot_l_abc"), any())
5054
}
5155

5256
@Test
5357
fun whenIntentIsClearDataCancelledThenCorrespondingPixelIsFired() {
5458
val intent = Intent(context, NotificationHandlerService::class.java)
55-
intent.type = CLEAR_DATA_CANCELLED
59+
intent.type = CANCEL
60+
intent.putExtra(PIXEL_SUFFIX_EXTRA, "abc")
5661
testee.onHandleIntent(intent)
57-
verify(mockPixel).fire(eq(Pixel.PixelName.NOTIFICATION_CANCELLED), any())
62+
verify(mockPixel).fire(eq("mnot_c_abc"), any())
5863
}
5964
}

app/src/androidTest/java/com/duckduckgo/app/notification/NotificationSchedulerTest.kt

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,71 +14,57 @@
1414
* limitations under the License.
1515
*/
1616

17+
18+
@file:Suppress("RemoveExplicitTypeArguments")
19+
1720
package com.duckduckgo.app.notification
1821

19-
import androidx.core.app.NotificationManagerCompat
20-
import androidx.test.platform.app.InstrumentationRegistry
2122
import androidx.work.WorkInfo
2223
import androidx.work.WorkManager
23-
import com.duckduckgo.app.notification.db.NotificationDao
24-
import com.duckduckgo.app.settings.clear.ClearWhatOption
25-
import com.duckduckgo.app.settings.db.SettingsDataStore
24+
import com.duckduckgo.app.notification.model.SchedulableNotification
25+
import com.duckduckgo.app.statistics.VariantManager
26+
import com.duckduckgo.app.statistics.VariantManager.Companion.DEFAULT_VARIANT
2627
import com.nhaarman.mockitokotlin2.any
2728
import com.nhaarman.mockitokotlin2.mock
2829
import com.nhaarman.mockitokotlin2.whenever
29-
import kotlinx.coroutines.CoroutineScope
30-
import kotlinx.coroutines.Dispatchers
30+
import kotlinx.coroutines.runBlocking
3131
import org.junit.Assert.assertFalse
3232
import org.junit.Assert.assertTrue
3333
import org.junit.Before
3434
import org.junit.Test
3535

3636
class NotificationSchedulerTest {
3737

38-
private val context = InstrumentationRegistry.getInstrumentation().targetContext
39-
private val notifcationManagerCompat = NotificationManagerCompat.from(context)
40-
private val testScope = CoroutineScope(Dispatchers.Unconfined)
41-
42-
private val mockNotificationsDao: NotificationDao = mock()
43-
private val mockSettingsDataStore: SettingsDataStore = mock()
38+
private val variantManager: VariantManager = mock()
39+
private val clearNotification: SchedulableNotification = mock()
40+
private val privacyNotification: SchedulableNotification = mock()
4441

4542
private lateinit var testee: NotificationScheduler
4643

4744
@Before
4845
fun before() {
46+
whenever(variantManager.getVariant(any())).thenReturn(DEFAULT_VARIANT)
4947
testee = NotificationScheduler(
50-
mockNotificationsDao,
51-
notifcationManagerCompat,
52-
mockSettingsDataStore
48+
variantManager,
49+
clearNotification,
50+
privacyNotification
5351
)
5452
}
5553

5654
@Test
57-
fun whenNotificationtNotSeenAndOptionNotSetThenNotificationScheduled() {
58-
setup(false, ClearWhatOption.CLEAR_NONE)
59-
testee.scheduleNextNotification(testScope)
55+
fun whenClearNotificationCanShowThenNotificationScheduled() = runBlocking<Unit> {
56+
whenever(clearNotification.canShow()).thenReturn(true)
57+
testee.scheduleNextNotification()
6058
assertTrue(notificationScheduled())
6159
}
6260

6361
@Test
64-
fun whenNotificationNotSeenAndClearOptionsAlreadySetThenNotificationNotScheduled() {
65-
setup(false, ClearWhatOption.CLEAR_TABS_ONLY)
66-
testee.scheduleNextNotification(testScope)
62+
fun whenClearNotificationCannotShowThenNotificationNotScheduled() = runBlocking<Unit> {
63+
whenever(clearNotification.canShow()).thenReturn(false)
64+
testee.scheduleNextNotification()
6765
assertFalse(notificationScheduled())
6866
}
6967

70-
@Test
71-
fun whenNotificationAlreadySeenAndOptionNotSetThenNotificationNotScheduled() {
72-
setup(true, ClearWhatOption.CLEAR_NONE)
73-
testee.scheduleNextNotification(testScope)
74-
assertFalse(notificationScheduled())
75-
}
76-
77-
private fun setup(notificationSeen: Boolean, clearWhatOption: ClearWhatOption) {
78-
whenever(mockNotificationsDao.exists(any())).thenReturn(notificationSeen)
79-
whenever(mockSettingsDataStore.automaticallyClearWhatOption).thenReturn(clearWhatOption)
80-
}
81-
8268
private fun notificationScheduled(): Boolean {
8369
return WorkManager
8470
.getInstance()

0 commit comments

Comments
 (0)