8000 Merge branch 'release/5.88.0' into main · codezwc/Android-1@5e2d072 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5e2d072

Browse files
committed
Merge branch 'release/5.88.0' into main
2 parents b2d8e7f + 1ca4c1e commit 5e2d072

File tree

71 files changed

+1198
-504
lines changed

Some content is hidden

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

71 files changed

+1198
-504
lines changed

app/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ android {
4141
}
4242
}
4343
}
44+
buildFeatures {
45+
viewBinding = true
46+
}
4447
compileOptions {
4548
sourceCompatibility = JavaVersion.VERSION_1_8
4649
targetCompatibility = JavaVersion.VERSION_1_8
@@ -164,6 +167,7 @@ dependencies {
164167
implementation AndroidX.fragmentKtx
165168

166169
// ViewModel and LiveData
170+
implementation AndroidX.lifecycle.runtimeKtx
167171
implementation AndroidX.lifecycle.viewModelKtx
168172
implementation AndroidX.lifecycle.liveDataKtx
169173
implementation AndroidX.lifecycle.process
@@ -213,6 +217,7 @@ dependencies {
213217
androidTestImplementation Testing.mockito.kotlin
214218
androidTestImplementation Square.okHttp3.mockWebServer
215219
androidTestImplementation "org.jetbrains.kotlin:kotlin-reflect:_"
220+
androidTestImplementation 'app.cash.turbine:turbine:_'
216221
}
217222

218223
tasks.register('fastlaneVersionCode') {

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

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,45 @@ package com.duckduckgo.app.browser
2020

2121
import android.content.Context
2222
import android.graphics.Bitmap
23+
import android.net.Uri
2324
import android.os.Message
2425
import android.view.View
26+
import android.webkit.ValueCallback
2527
import android.webkit.WebChromeClient
2628
import android.webkit.WebView
2729
import androidx.test.annotation.UiThreadTest
2830
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
2931
import com.duckduckgo.app.global.exception.UncaughtExceptionRepository
32+
import com.duckduckgo.app.global.exception.UncaughtExceptionSource
3033
import com.nhaarman.mockitokotlin2.*
34+
import junit.framework.TestCase.assertTrue
35+
import kotlinx.coroutines.ExperimentalCoroutinesApi
36+
import kotlinx.coroutines.runBlocking
37+
import kotlinx.coroutines.test.TestCoroutineScope
3138
import org.junit.Before
3239
import org.junit.Test
40+
import org.mockito.ArgumentMatchers.anyInt
41+
import org.mockito.ArgumentMatchers.anyString
3342

3443
class BrowserChromeClientTest {
3544

3645
private lateinit var testee: BrowserChromeClient
3746
private lateinit var webView: TestWebView
3847
private lateinit var mockWebViewClientListener: WebViewClientListener
3948
private lateinit var mockUncaughtExceptionRepository: UncaughtExceptionRepository
49+
private lateinit var mockFilePathCallback: ValueCallback<Array<Uri>>
50+
private lateinit var mockFileChooserParams: WebChromeClient.FileChooserParams
4051
private val fakeView = View(getInstrumentation().targetContext)
4152

53+
@ExperimentalCoroutinesApi
4254
@UiThreadTest
4355
@Before
4456
fun setup() {
4557
mockUncaughtExceptionRepository = mock()
46-
testee = BrowserChromeClient(mockUncaughtExceptionRepository)
58+
testee = BrowserChromeClient(mockUncaughtExceptionRepository, TestCoroutineScope())
4759
mockWebViewClientListener = mock()
60+
mockFilePathCallback = mock()
61+
mockFileChooserParams = mock()
4862
testee.webViewClientListener = mockWebViewClientListener
4963
webView = TestWebView(getInstrumentation().targetContext)
5064
}
@@ -78,12 +92,28 @@ class BrowserChromeClientTest {
7892
verify(mockCustomViewCallback, times(2)).onCustomViewHidden()
7993
}
8094

95+
@Test
96+
fun whenCustomViewShownThrowsExceptionThenRecordException() = runBlocking {
97+
val exception = RuntimeException()
98+
whenever(mockWebViewClientListener.goFullScreen(any())).thenThrow(exception)
99+
testee.onShowCustomView(fakeView, null)
100+
verify(mockUncaughtExceptionRepository).recordUncaughtException(exception, UncaughtExceptionSource.SHOW_CUSTOM_VIEW)
101+
}
102+
81103
@Test
82104
fun whenHideCustomViewCalledThenListenerInstructedToExistFullScreen() {
83105
testee.onHideCustomView()
84106
verify(mockWebViewClientListener).exitFullScreen()
85107
}
86108

109+
@Test
110+
fun whenHideCustomViewThrowsExceptionThenRecordException() = runBlocking {
111+
val exception = RuntimeException()
112+
whenever(mockWebViewClientListener.exitFullScreen()).thenThrow(exception)
113+
testee.onHideCustomView()
114+
verify(mockUncaughtExceptionRepository).recordUncaughtException(exception, UncaughtExceptionSource.HIDE_CUSTOM_VIEW)
115+
}
116+
87117
@UiThreadTest
88118
@Test
89119
fun whenOnProgressChangedCalledThenListenerInstructedToUpdateProgress() {
@@ -98,6 +128,15 @@ class BrowserChromeClientTest {
98128
verify(mockWebViewClientListener).navigationStateChanged(any())
99129
}
100130

131+
@UiThreadTest
132+
@Test
133+
fun whenOnProgressChangedThrowsExceptionThenRecordException() = runBlocking {
134+
val exception = RuntimeException()
135+
whenever(mockWebViewClientListener.progressChanged(anyInt())).thenThrow(exception)
136+
testee.onProgressChanged(webView, 10)
137+
verify(mockUncaughtExceptionRepository).recordUncaughtException(exception, UncaughtExceptionSource.ON_PROGRESS_CHANGED)
138+
}
139+
101140
@UiThreadTest
102141
@Test
103142
fun whenOnCreateWindowWithUserGestureThenMessageOpenedInNewTab() {
@@ -120,6 +159,36 @@ class BrowserChromeClientTest {
120159
verify(mockWebViewClientListener).iconReceived(webView.url, bitmap)
121160
}
122161

162+
@Test
163+
fun whenOnReceivedTitleThenTitleReceived() {
164+
val title = "title"
165+
testee.onReceivedTitle(webView, title)
166+
verify(mockWebViewClientListener).titleReceived(title)
167+
}
168+
169+
@Test
170+
fun whenOnReceivedTitleThrowsExceptionThenRecordException() = runBlocking {
171+
val exception = RuntimeException()
172+
whenever(mockWebViewClientListener.titleReceived(anyString())).thenThrow(exception)
173+
testee.onReceivedTitle(webView, "")
174+
verify(mockUncaughtExceptionRepository).recordUncaughtException(exception, UncaughtExceptionSource.RECEIVED_PAGE_TITLE)
175+
}
176+
177+
@Test
178+
fun whenOnShowFileChooserCalledThenShowFileChooser() {
179+
assertTrue(testee.onShowFileChooser(webView, mockFilePathCallback, mockFileChooserParams))
180+
verify(mockWebViewClientListener).showFileChooser(mockFilePathCallback, mockFileChooserParams)
181+
}
182+
183+
@Test
184+
fun whenShowFileChooserThrowsExceptionThenRecordException() = runBlocking {
185+
val exception = RuntimeException()
186+
whenever(mockWebViewClientListener.showFileChooser(any(), any())).thenThrow(exception)
187+
assertTrue(testee.onShowFileChooser(webView, mockFilePathCallback, mockFileChooserParams))
188+
verify(mockUncaughtExceptionRepository).recordUncaughtException(exception, UncaughtExceptionSource.SHOW_FILE_CHOOSER)
189+
verify(mockFilePathCallback).onReceiveValue(null)
190+
}
191+
123192
private val mockMsg = Message().apply {
124193
target = mock()
125194
obj = mock<WebView.WebViewTransport>()

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ import kotlinx.coroutines.flow.asStateFlow
135135
import kotlinx.coroutines.flow.consumeAsFlow
136136
import kotlinx.coroutines.flow.flowOf
137137
import kotlinx.coroutines.runBlocking
138+
import kotlinx.coroutines.test.TestCoroutineScope
138139
import kotlinx.coroutines.test.runBlockingTest
139140
import org.junit.After
140141
import org.junit.Assert.*
@@ -373,7 +374,8 @@ class BrowserTabViewModelTest {
373374
globalPrivacyControl = GlobalPrivacyControlManager(mockSettingsStore),
374375
fireproofDialogsEventHandler = fireproofDialogsEventHandler,
375376
emailManager = mockEmailManager,
376-
favoritesRepository = mockFavoritesRepository
377+
favoritesRepository = mockFavoritesRepository,
378+
appCoroutineScope = TestCoroutineScope()
377379
)
378380

379381
testee.loadData("abc", null, false)

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

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

1919
import android.content.Context
20+
import android.net.Uri
2021
import android.os.Build
2122
import android.webkit.*
2223
import androidx.core.net.toUri
@@ -32,16 +33,17 @@ import com.duckduckgo.app.browser.logindetection.WebNavigationEvent
3233
import com.duckduckgo.app.browser.model.BasicAuthenticationRequest
3334
import com.duckduckgo.app.email.EmailInjector
3435
import com.duckduckgo.app.global.exception.UncaughtExceptionRepository
36+
import com.duckduckgo.app.global.exception.UncaughtExceptionSource
3537
import com.duckduckgo.app.globalprivacycontrol.GlobalPrivacyControl
3638
import com.duckduckgo.app.runBlocking
3739
import com.duckduckgo.app.statistics.store.OfflinePixelCountDataStore
3840
import com.nhaarman.mockitokotlin2.*
3941
import kotlinx.coroutines.ExperimentalCoroutinesApi
40-
import kotlinx.coroutines.GlobalScope
41-
import kotlinx.coroutines.runBlocking
42+
import kotlinx.coroutines.test.TestCoroutineScope
4243
import org.junit.Before
4344
import org.junit.Rule
4445
import org.junit.Test
46+
import java.lang.RuntimeException
4547

4648
@ExperimentalCoroutinesApi
4749
class BrowserWebViewClientTest {
@@ -84,7 +86,7 @@ class BrowserWebViewClientTest {
8486
dosDetector,
8587
globalPrivacyControl,
8688
thirdPartyCookieManager,
87-
GlobalScope,
89+
TestCoroutineScope(),
8890
coroutinesTestRule.testDispatcherProvider,
8991
emailInjector
9092
)
@@ -151,6 +153,17 @@ class BrowserWebViewClientTest {
151153
verify(listener).requiresAuthentication(authenticationRequest)
152154
}
153155

156+
@UiThreadTest
157+
@Test
158+
fun whenOnReceivedHttpAuthRequestThrowsExceptionThenRecordException() = coroutinesTestRule.runBlocking {
159+
val exception = RuntimeException()
160+
val mockHandler = mock<HttpAuthHandler>()
161+
val mockWebView = mock<WebView>()
162+
whenever(mockWebView.url).thenThrow(exception)
163+
testee.onReceivedHttpAuthRequest(mockWebView, mockHandler, EXAMPLE_URL, EXAMPLE_URL)
164+
verify(uncaughtExceptionRepository).recordUncaughtException(exception, UncaughtExceptionSource.ON_HTTP_AUTH_REQUEST)
165+
}
166+
154167
@UiThreadTest
155168
@Test
156169
fun whenShouldInterceptRequestThenEventSentToLoginDetector() = coroutinesTestRule.runBlocking {
@@ -207,13 +220,47 @@ class BrowserWebViewClientTest {
207220
verify(emailInjector).injectEmailAutofillJs(webView, null)
208221
}
209222

223+
@UiThreadTest
224+
@Test
225+
fun whenOnPageFinishedCalledThenFlushCookies() {
226+
testee.onPageFinished(webView, null)
227+
verify(cookieManager).flush()
228+
}
229+
230+
@UiThreadTest
231+
@Test
232+
fun whenOnPageFinishedThrowsExceptionThenRecordException() = coroutinesTestRule.runBlocking {
233+
val exception = RuntimeException()
234+
val mockWebView: WebView = mock()
235+
whenever(mockWebView.url).thenThrow(exception)
236+
testee.onPageFinished(mockWebView, null)
237+
verify(uncaughtExceptionRepository).recordUncaughtException(exception, UncaughtExceptionSource.ON_PAGE_FINISHED)
238+
}
239+
210240
@UiThreadTest
211241
@Test
212242
fun whenOnPageStartedCalledThenResetInjectedJsFlagCalled() {
213243
testee.onPageStarted(webView, null, null)
214244
verify(emailInjector).resetInjectedJsFlag()
215245
}
216246

247+
@Test
248+
fun whenOnPageStartedThrowsExceptionThenRecordException() = coroutinesTestRule.runBlocking {
249+
val exception = RuntimeException()
250+
val mockWebView: WebView = mock()
251+
whenever(mockWebView.url).thenThrow(exception)
252+
testee.onPageStarted(mockWebView, null, null)
253+
verify(uncaughtExceptionRepository).recordUncaughtException(exception, UncaughtExceptionSource.ON_PAGE_STARTED)
254+
}
255+
256+
@Test
257+
fun whenShouldOverrideThrowsExceptionThenRecordException() = coroutinesTestRule.runBlocking {
258+
val exception = RuntimeException()
259+
whenever(specialUrlDetector.determineType(any<Uri>())).thenThrow(exception)
260+
testee.shouldOverrideUrlLoading(webView, "")
261+
verify(uncaughtExceptionRepository).recordUncaughtException(exception, UncaughtExceptionSource.SHOULD_OVERRIDE_REQUEST)
262+
}
263+
217264
private class TestWebView(context: Context) : WebView(context)
218265

219266
companion object {

app/src/androidTest/java/com/duckduckgo/app/browser/httpauth/WebViewHttpAuthStoreTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import com.nhaarman.mockitokotlin2.never
2929
import com.nhaarman.mockitokotlin2.verify
3030
import com.nhaarman.mockitokotlin2.whenever
3131
import kotlinx.coroutines.ExperimentalCoroutinesApi
32+
import kotlinx.coroutines.test.TestCoroutineScope
3233
import org.junit.Assert.assertEquals
3334
import org.junit.Rule
3435
import org.junit.Test
@@ -45,7 +46,7 @@ class WebViewHttpAuthStoreTest {
4546
private val webView: WebView = mock()
4647
private val databaseLocator = AuthDatabaseLocator(context)
4748

48-
private val webViewHttpAuthStore = RealWebViewHttpAuthStore(webViewDatabase, mockDatabaseCleaner, databaseLocator, coroutineRule.testDispatcherProvider)
49+
private val webViewHttpAuthStore = RealWebViewHttpAuthStore(webViewDatabase, mockDatabaseCleaner, databaseLocator, coroutineRule.testDispatcherProvider, TestCoroutineScope())
4950

5051
@Test
5152
@SdkSuppress(minSdkVersion = android.os.Build.VERSION_CODES.O)

app/src/androidTest/java/com/duckduckgo/app/browser/logindetection/NextPageLoginDetectionTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import com.nhaarman.mockitokotlin2.mock
2929
import com.nhaarman.mockitokotlin2.whenever
3030
import kotlinx.coroutines.ExperimentalCoroutinesApi
3131
import kotlinx.coroutines.delay
32+
import kotlinx.coroutines.test.TestCoroutineScope
3233
import org.junit.Assert.*
3334
import org.junit.Before
3435
import org.junit.Rule
@@ -46,7 +47,7 @@ class NextPageLoginDetectionTest {
4647
var instantTaskExecutorRule = InstantTaskExecutorRule()
4748

4849
private val mockSettingsDataStore: SettingsDataStore = mock()
49-
private val loginDetector = NextPageLoginDetection(mockSettingsDataStore)
50+
private val loginDetector = NextPageLoginDetection(mockSettingsDataStore, TestCoroutineScope())
5051

5152
private val loginObserver = mock<Observer<LoginDetected>>()
5253
private val loginEventCaptor = argumentCaptor<LoginDetected>()

app/src/androidTest/java/com/duckduckgo/app/browser/shortcut/ShortcutReceiverTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import com.duckduckgo.app.statistics.pixels.Pixel
2323
import com.nhaarman.mockitokotlin2.mock
2424
import com.nhaarman.mockitokotlin2.verify
2525
import kotlinx.coroutines.ExperimentalCoroutinesApi
26+
import kotlinx.coroutines.test.TestCoroutineScope
2627
import org.junit.Before
2728
import org.junit.Rule
2829
import org.junit.Test
@@ -38,7 +39,7 @@ class ShortcutReceiverTest {
3839

3940
@Before
4041
fun before() {
41-
testee = ShortcutReceiver(mockPixel, coroutinesTestRule.testDispatcherProvider)
42+
testee = ShortcutReceiver(mockPixel, coroutinesTestRule.testDispatcherProvider, TestCoroutineScope())
4243
}
4344

4445
@Test

app/src/androidTest/java/com/duckduckgo/app/email/db/EmailEncryptedSharedPreferencesTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.nhaarman.mockitokotlin2.mock
2424
import kotlinx.coroutines.ExperimentalCoroutinesApi
2525
import kotlinx.coroutines.FlowPreview
2626
import kotlinx.coroutines.flow.first
27+
import kotlinx.coroutines.test.TestCoroutineScope
2728
import org.junit.Assert.*
2829
import org.junit.Before
2930
import org.junit.Rule
@@ -41,7 +42,7 @@ class EmailEncryptedSharedPreferencesTest {
4142

4243
@Before
4344
fun before() {
44-
testee = EmailEncryptedSharedPreferences(InstrumentationRegistry.getInstrumentation().targetContext, mockPixel)
45+
testee = EmailEncryptedSharedPreferences(InstrumentationRegistry.getInstrumentation().targetContext, mockPixel, TestCoroutineScope())
4546
}
4647

4748
@Test

0 commit comments

Comments
 (0)
0