Skip to content

Commit 52a5a56

Browse files
committed
Merge branch 'release/5.75.0' into main
2 parents d388e19 + 9633240 commit 52a5a56

21 files changed

+1209
-113
lines changed

app/src/androidTest/java/com/duckduckgo/app/autocomplete/api/AutoCompleteApiTest.kt

Lines changed: 334 additions & 16 deletions
Large diffs are not rendered by default.

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

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ import io.reactivex.Observable
112112
import io.reactivex.Single
113113
import kotlinx.coroutines.ExperimentalCoroutinesApi
114114
import kotlinx.coroutines.channels.Channel
115-
import kotlinx.coroutines.flow.*
115+
import kotlinx.coroutines.flow.consumeAsFlow
116+
import kotlinx.coroutines.flow.flowOf
116117
import kotlinx.coroutines.runBlocking
117118
import kotlinx.coroutines.test.runBlockingTest
118119
import org.junit.After
@@ -124,6 +125,7 @@ import org.mockito.*
124125
import org.mockito.ArgumentMatchers.anyString
125126
import org.mockito.Mockito.never
126127
import org.mockito.Mockito.verify
128+
import org.mockito.internal.util.DefaultMockingDetails
127129
import java.io.File
128130
import java.util.*
129131
import java.util.concurrent.TimeUnit
@@ -256,7 +258,7 @@ class BrowserTabViewModelTest {
256258

257259
@Before
258260
fun before() {
259-
MockitoAnnotations.initMocks(this)
261+
MockitoAnnotations.openMocks(this)
260262
db = Room.inMemoryDatabaseBuilder(getInstrumentation().targetContext, AppDatabase::class.java)
261263
.allowMainThreadQueries()
262264
.build()
@@ -541,7 +543,7 @@ class BrowserTabViewModelTest {
541543
testee.onUserSubmittedQuery("foo")
542544

543545
coroutineRule.runBlocking {
544-
verify(mockTabsRepository).delete(selectedTabLiveData.value!!)
546+
verify(mockTabsRepository).deleteCurrentTabAndSelectSource()
545547
}
546548
}
547549

@@ -636,6 +638,16 @@ class BrowserTabViewModelTest {
636638
assertCommandNotIssued<Command.HideWebContent>()
637639
}
638640

641+
@Test
642+
fun whenUserRedirectedThenNotifyLoginDetector() = coroutineRule.runBlocking {
643+
loadUrl("http://duckduckgo.com")
644+
testee.progressChanged(100)
645+
646+
overrideUrl("http://example.com")
647+
648+
verify(mockNavigationAwareLoginDetector).onEvent(NavigationEvent.Redirect("http://example.com"))
649+
}
650+
639651
@Test
640652
fun whenLoadingProgressReaches50ThenShowWebContent() = coroutineRule.runBlocking {
641653
loadUrl("http://duckduckgo.com")
@@ -953,7 +965,7 @@ class BrowserTabViewModelTest {
953965

954966
@Test
955967
fun whenEnteringQueryWithAutoCompleteEnabledThenAutoCompleteSuggestionsShown() {
956-
whenever(mockBookmarksDao.bookmarksByQuery("%foo%")).thenReturn(Single.just(emptyList()))
968+
whenever(mockBookmarksDao.bookmarksObservable()).thenReturn(Single.just(emptyList()))
957969
whenever(mockAutoCompleteService.autoComplete("foo")).thenReturn(Observable.just(emptyList()))
958970
doReturn(true).whenever(mockSettingsStore).autoCompleteSuggestionsEnabled
959971
testee.onOmnibarInputStateChanged("foo", true, hasQueryChanged = true)
@@ -1196,7 +1208,7 @@ class BrowserTabViewModelTest {
11961208
testee.onRefreshRequested()
11971209

11981210
coroutineRule.runBlocking {
1199-
verify(mockTabsRepository).delete(selectedTabLiveData.value!!)
1211+
verify(mockTabsRepository).deleteCurrentTabAndSelectSource()
12001212
}
12011213
}
12021214

@@ -1446,7 +1458,7 @@ class BrowserTabViewModelTest {
14461458
showErrorWithAction.action()
14471459

14481460
coroutineRule.runBlocking {
1449-
verify(mockTabsRepository).delete(selectedTabLiveData.value!!)
1461+
verify(mockTabsRepository).deleteCurrentTabAndSelectSource()
14501462
}
14511463
}
14521464

@@ -1618,7 +1630,7 @@ class BrowserTabViewModelTest {
16181630
fun whenCloseCurrentTabSelectedThenTabDeletedFromRepository() = runBlocking {
16191631
givenOneActiveTabSelected()
16201632
testee.closeCurrentTab()
1621-
verify(mockTabsRepository).delete(selectedTabLiveData.value!!)
1633+
verify(mockTabsRepository).deleteCurrentTabAndSelectSource()
16221634
}
16231635

16241636
@Test
@@ -2460,12 +2472,12 @@ class BrowserTabViewModelTest {
24602472
givenDeviceLocationSharingIsEnabled(true)
24612473
givenLocationPermissionIsEnabled(true)
24622474
givenCurrentSite(domain)
2463-
2475+
givenNewPermissionRequestFromDomain(domain)
24642476
testee.onSiteLocationPermissionSelected(domain, LocationPermissionType.ALLOW_ONCE)
24652477

24662478
givenNewPermissionRequestFromDomain(domain)
24672479

2468-
assertCommandNotIssued<Command.CheckSystemLocationPermission>()
2480+
assertCommandIssuedTimes<Command.CheckSystemLocationPermission>(times = 1)
24692481
}
24702482

24712483
@Test
@@ -2704,11 +2716,7 @@ class BrowserTabViewModelTest {
27042716
givenLocationPermissionIsEnabled(true)
27052717

27062718
loadUrl("https://www.example.com", isBrowserShowing = true)
2707-
2708-
assertCommandIssued<Command.ShowDomainHasPermissionMessage>()
2709-
27102719
loadUrl("https://www.example.com", isBrowserShowing = true)
2711-
27122720
assertCommandIssuedTimes<Command.ShowDomainHasPermissionMessage>(1)
27132721
}
27142722

@@ -3032,7 +3040,7 @@ class BrowserTabViewModelTest {
30323040
loadUrl("http://duckduckgo.com")
30333041
testee.progressChanged(100)
30343042

3035-
assertCommandNotIssued<Command.RefreshUserAgent>()
3043+
assertCommandIssued<Command.RefreshUserAgent>()
30363044
}
30373045

30383046
@Test
@@ -3062,6 +3070,34 @@ class BrowserTabViewModelTest {
30623070
assertFalse(browserViewState().canChangeBrowsingMode)
30633071
}
30643072

3073+
@Test
3074+
fun whenRequestFileDownloadAndUrlIsBlobThenConvertBlobToDataUriCommandSent() {
3075+
val blobUrl = "blob:https://example.com/283nasdho23jkasdAjd"
3076+
val mime = "application/plain"
3077+
3078+
testee.requestFileDownload(blobUrl, null, mime, true)
3079+
3080+
assertCommandIssued<Command.ConvertBlobToDataUri> {
3081+
assertEquals(blobUrl, url)
3082+
assertEquals(mime, mimeType)
3083+
}
3084+
}
3085+
3086+
@Test
3087+
fun whenRequestFileDownloadAndUrlIsNotBlobThenRquestFileDownloadCommandSent() {
3088+
val normalUrl = "https://example.com/283nasdho23jkasdAjd"
3089+
val mime = "application/plain"
3090+
3091+
testee.requestFileDownload(normalUrl, null, mime, true)
3092+
3093+
assertCommandIssued<Command.RequestFileDownload> {
3094+
assertEquals(normalUrl, url)
3095+
assertEquals(mime, mimeType)
3096+
assertNull(contentDisposition)
3097+
assertTrue(requestUserConfirmation)
3098+
}
3099+
}
3100+
30653101
private suspend fun givenFireButtonPulsing() {
30663102
whenever(mockUserStageStore.getUserAppStage()).thenReturn(AppStage.DAX_ONBOARDING)
30673103
dismissedCtaDaoChannel.send(listOf(DismissedCta(CtaId.DAX_DIALOG_TRACKERS_FOUND)))
@@ -3097,13 +3133,22 @@ class BrowserTabViewModelTest {
30973133
}
30983134

30993135
private inline fun <reified T : Command> assertCommandNotIssued() {
3100-
val issuedCommand = commandCaptor.allValues.find { it is T }
3101-
assertNull(issuedCommand)
3136+
val defaultMockingDetails = DefaultMockingDetails(mockCommandObserver)
3137+
if (defaultMockingDetails.invocations.isNotEmpty()) {
3138+
verify(mockCommandObserver, atLeastOnce()).onChanged(commandCaptor.capture())
3139+
val issuedCommand = commandCaptor.allValues.find { it is T }
3140+
assertNull(issuedCommand)
3141+
}
31023142
}
31033143

31043144
private inline fun <reified T : Command> assertCommandIssuedTimes(times: Int) {
3105-
val timesIssued = commandCaptor.allValues.count { it is T }
3106-
assertEquals(times, timesIssued)
3145+
if (times == 0) {
3146+
assertCommandNotIssued<T>()
3147+
} else {
3148+
verify(mockCommandObserver, atLeastOnce()).onChanged(commandCaptor.capture())
3149+
val timesIssued = commandCaptor.allValues.count { it is T }
3150+
assertEquals(times, timesIssued)
3151+
}
31073152
}
31083153

31093154
private fun pixelParams(showedBookmarks: Boolean, bookmarkCapable: Boolean) = mapOf(
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (c) 2021 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.browser.downloader
18+
19+
import android.webkit.WebView
20+
import androidx.test.annotation.UiThreadTest
21+
import androidx.test.platform.app.InstrumentationRegistry
22+
import com.duckduckgo.app.browser.R
23+
import com.nhaarman.mockitokotlin2.spy
24+
import com.nhaarman.mockitokotlin2.verify
25+
import org.junit.Before
26+
import org.junit.Test
27+
28+
class BlobConverterInjectorJsTest {
29+
lateinit var testee: BlobConverterInjectorJs
30+
private val blobUrl = "blob:https://example.com/283nasdho23jkasdAjd"
31+
private val contentType = "application/plain"
32+
33+
@Before
34+
fun setup() {
35+
testee = BlobConverterInjectorJs()
36+
}
37+
38+
@UiThreadTest
39+
@Test
40+
fun whenConvertBlobIntoDataUriAndDownloadThenInjectJsCode() {
41+
val jsToEvaluate = getJsToEvaluate().replace("%blobUrl%", blobUrl).replace("%contentType%", contentType)
42+
val webView = spy(WebView(InstrumentationRegistry.getInstrumentation().targetContext))
43+
44+
testee.convertBlobIntoDataUriAndDownload(webView, blobUrl, contentType)
45+
46+
verify(webView).evaluateJavascript(jsToEvaluate, null)
47+
}
48+
49+
private fun getJsToEvaluate(): String {
50+
val js = InstrumentationRegistry.getInstrumentation().targetContext.resources.openRawResource(
51+
R.raw.blob_converter
52+
)
53+
.bufferedReader()
54+
.use { it.readText() }
55+
return "javascript:$js"
56+
}
57+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2021 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.browser.downloader
18+
19+
import org.junit.Assert.*
20+
import org.junit.Before
21+
import org.junit.Test
22+
23+
class BlobConverterJavascriptInterfaceTest {
24+
25+
lateinit var testee: BlobConverterJavascriptInterface
26+
var result: String = ""
27+
28+
@Before
29+
fun setup() {
30+
testee = BlobConverterJavascriptInterface { first, second -> result = first + second }
31+
}
32+
33+
@Test
34+
fun whenConvertToBlobDataUriThenLambdaCalled() {
35+
testee.convertBlobToDataUri("first", "second")
36+
37+
assertEquals("firstsecond", result)
38+
}
39+
}

0 commit comments

Comments
 (0)