16
16
17
17
package com.duckduckgo.app.browser
18
18
19
+ import android.graphics.Bitmap
19
20
import android.net.Uri
20
21
import android.view.MenuItem
21
22
import android.view.View
@@ -44,7 +45,7 @@ import com.duckduckgo.app.browser.LongPressHandler.RequiredAction.DownloadFile
44
45
import com.duckduckgo.app.browser.LongPressHandler.RequiredAction.OpenInNewTab
45
46
import com.duckduckgo.app.browser.addtohome.AddToHomeCapabilityDetector
46
47
import com.duckduckgo.app.browser.downloader.FileDownloader
47
- import com.duckduckgo.app.browser.favicon.FaviconDownloader
48
+ import com.duckduckgo.app.browser.favicon.FaviconManager
48
49
import com.duckduckgo.app.browser.logindetection.LoginDetected
49
50
import com.duckduckgo.app.browser.logindetection.NavigationAwareLoginDetector
50
51
import com.duckduckgo.app.browser.logindetection.NavigationEvent.LoginAttempt
@@ -103,14 +104,14 @@ import com.duckduckgo.app.trackerdetection.model.TrackingEvent
103
104
import com.duckduckgo.app.usage.search.SearchCountDao
104
105
import com.duckduckgo.app.widget.ui.WidgetCapabilities
105
106
import com.nhaarman.mockitokotlin2.*
107
+ import dagger.Lazy
106
108
import io.reactivex.Observable
107
109
import io.reactivex.Single
108
110
import kotlinx.coroutines.ExperimentalCoroutinesApi
109
111
import kotlinx.coroutines.flow.emptyFlow
110
112
import kotlinx.coroutines.runBlocking
111
113
import kotlinx.coroutines.test.runBlockingTest
112
114
import org.junit.After
113
- import org.junit.Assert
114
115
import org.junit.Assert.*
115
116
import org.junit.Before
116
117
import org.junit.Rule
@@ -119,6 +120,7 @@ import org.mockito.*
119
120
import org.mockito.ArgumentMatchers.anyString
120
121
import org.mockito.Mockito.never
121
122
import org.mockito.Mockito.verify
123
+ import java.io.File
122
124
import java.util.concurrent.TimeUnit
123
125
124
126
@ExperimentalCoroutinesApi
@@ -168,7 +170,7 @@ class BrowserTabViewModelTest {
168
170
private lateinit var webViewSessionStorage: WebViewSessionStorage
169
171
170
172
@Mock
171
- private lateinit var mockFaviconDownloader : FaviconDownloader
173
+ private lateinit var mockFaviconManager : FaviconManager
172
174
173
175
@Mock
174
176
private lateinit var mockAddToHomeCapabilityDetector: AddToHomeCapabilityDetector
@@ -221,6 +223,8 @@ class BrowserTabViewModelTest {
221
223
@Mock
222
224
private lateinit var geoLocationPermissions: GeoLocationPermissions
223
225
226
+ private val lazyFaviconManager = Lazy { mockFaviconManager }
227
+
224
228
private lateinit var mockAutoCompleteApi: AutoCompleteApi
225
229
226
230
private lateinit var ctaViewModel: CtaViewModel
@@ -295,14 +299,18 @@ class BrowserTabViewModelTest {
295
299
longPressHandler = mockLongPressHandler,
296
300
webViewSessionStorage = webViewSessionStorage,
297
301
specialUrlDetector = SpecialUrlDetectorImpl (),
298
- faviconDownloader = mockFaviconDownloader ,
302
+ faviconManager = mockFaviconManager ,
299
303
addToHomeCapabilityDetector = mockAddToHomeCapabilityDetector,
300
304
ctaViewModel = ctaViewModel,
301
305
searchCountDao = mockSearchCountDao,
302
306
pixel = mockPixel,
303
307
dispatchers = coroutineRule.testDispatcherProvider,
304
- fireproofWebsiteRepository = FireproofWebsiteRepository (fireproofWebsiteDao, coroutineRule.testDispatcherProvider),
305
- locationPermissionsRepository = LocationPermissionsRepository (locationPermissionsDao, coroutineRule.testDispatcherProvider),
308
+ fireproofWebsiteRepository = FireproofWebsiteRepository (fireproofWebsiteDao, coroutineRule.testDispatcherProvider, lazyFaviconManager),
309
+ locationPermissionsRepository = LocationPermissionsRepository (
310
+ locationPermissionsDao,
311
+ lazyFaviconManager,
312
+ coroutineRule.testDispatcherProvider
313
+ ),
306
314
geoLocationPermissions = geoLocationPermissions,
307
315
navigationAwareLoginDetector = mockNavigationAwareLoginDetector,
308
316
userEventsStore = mockUserEventsStore,
@@ -2541,7 +2549,7 @@ class BrowserTabViewModelTest {
2541
2549
2542
2550
verify(mockPixel).fire(Pixel .PixelName .PRECISE_LOCATION_SYSTEM_DIALOG_NEVER )
2543
2551
verify(geoLocationPermissions).clear(domain)
2544
- Assert . assertEquals(locationPermissionsDao.getPermission(domain)!! .permission, LocationPermissionType .DENY_ALWAYS )
2552
+ assertEquals(locationPermissionsDao.getPermission(domain)!! .permission, LocationPermissionType .DENY_ALWAYS )
2545
2553
}
2546
2554
2547
2555
@Test
@@ -2673,6 +2681,163 @@ class BrowserTabViewModelTest {
2673
2681
verify(mockSettingsStore).appLocationPermissionDeniedForever = false
2674
2682
}
2675
2683
2684
+ @Test
2685
+ fun whenPrefetchFaviconThenPrefetchToTemp () = coroutineRule.runBlocking {
2686
+ val url = " https://www.example.com/"
2687
+ givenCurrentSite(url)
2688
+ testee.prefetchFavicon(url)
2689
+
2690
+ verify(mockFaviconManager).prefetchToTemp(" TAB_ID" , url)
2691
+ }
2692
+
2693
+ @Test
2694
+ fun whenPrefetchFaviconAndFaviconExistsThenUpdateTabFavicon () = coroutineRule.runBlocking {
2695
+ val url = " https://www.example.com/"
2696
+ val file = File (" test" )
2697
+ givenCurrentSite(url)
2698
+ whenever(mockFaviconManager.prefetchToTemp(any(), any())).thenReturn(file)
2699
+
2700
+ testee.prefetchFavicon(url)
2701
+
2702
+ verify(mockTabsRepository).updateTabFavicon(" TAB_ID" , file.name)
2703
+ }
2704
+
2705
+ @Test
2706
+ fun whenPrefetchFaviconAndFaviconDoesNotExistThenDoNotCallUpdateTabFavicon () = coroutineRule.runBlocking {
2707
+ whenever(mockFaviconManager.prefetchToTemp(any(), any())).thenReturn(null )
2708
+
2709
+ testee.prefetchFavicon(" url" )
2710
+
2711
+ verify(mockTabsRepository, never()).updateTabFavicon(any(), any())
2712
+ }
2713
+
2714
+ @Test
2715
+ fun whenIconReceivedThenSaveToTemp () = coroutineRule.runBlocking {
2716
+ givenOneActiveTabSelected()
2717
+ val bitmap: Bitmap = Bitmap .createBitmap(1 , 1 , Bitmap .Config .RGB_565 )
2718
+
2719
+ testee.iconReceived(bitmap)
2720
+
2721
+ verify(mockFaviconManager).saveToTemp(" TAB_ID" , bitmap, " https://example.com" )
2722
+ }
2723
+
2724
+ @Test
2725
+ fun whenIconReceivedIfCorrectlySavedThenUpdateTabFavicon () = coroutineRule.runBlocking {
2726
+ givenOneActiveTabSelected()
2727
+ val bitmap: Bitmap = Bitmap .createBitmap(1 , 1 , Bitmap .Config .RGB_565 )
2728
+ val file = File (" test" )
2729
+ whenever(mockFaviconManager.saveToTemp(any(), any(), any())).thenReturn(file)
2730
+
2731
+ testee.iconReceived(bitmap)
2732
+
2733
+ verify(mockTabsRepository).updateTabFavicon(" TAB_ID" , file.name)
2734
+ }
2735
+
2736
+ @Test
2737
+ fun whenIconReceivedIfNotCorrectlySavedThenDoNotUpdateTabFavicon () = coroutineRule.runBlocking {
2738
+ givenOneActiveTabSelected()
2739
+ val bitmap: Bitmap = Bitmap .createBitmap(1 , 1 , Bitmap .Config .RGB_565 )
2740
+ whenever(mockFaviconManager.saveToTemp(any(), any(), any())).thenReturn(null )
2741
+
2742
+ testee.iconReceived(bitmap)
2743
+
2744
+ verify(mockTabsRepository, never()).updateTabFavicon(any(), any())
2745
+ }
2746
+
2747
+ @Test
2748
+ fun whenOnSiteLocationPermissionSelectedAndPermissionIsAllowAlwaysThenPersistFavicon () = coroutineRule.runBlocking {
2749
+ val url = " http://example.com"
2750
+ val permission = LocationPermissionType .ALLOW_ALWAYS
2751
+ givenNewPermissionRequestFromDomain(url)
2752
+
2753
+ testee.onSiteLocationPermissionSelected(url, permission)
2754
+
2755
+ verify(mockFaviconManager).persistFavicon(any(), eq(url))
2756
+ }
2757
+
2758
+ @Test
2759
+ fun whenOnSiteLocationPermissionSelectedAndPermissionIsDenyAlwaysThenPersistFavicon () = coroutineRule.runBlocking {
2760
+ val url = " http://example.com"
2761
+ val permission = LocationPermissionType .DENY_ALWAYS
2762
+ givenNewPermissionRequestFromDomain(url)
2763
+
2764
+ testee.onSiteLocationPermissionSelected(url, permission)
2765
+
2766
+ verify(mockFaviconManager).persistFavicon(any(), eq(url))
2767
+ }
2768
+
2769
+ @Test
2770
+ fun whenOnSystemLocationPermissionNeverAllowedThenPersistFavicon () = coroutineRule.runBlocking {
2771
+ val url = " http://example.com"
2772
+ givenNewPermissionRequestFromDomain(url)
2773
+
2774
+ testee.onSystemLocationPermissionNeverAllowed()
2775
+
2776
+ verify(mockFaviconManager).persistFavicon(any(), eq(url))
2777
+ }
2778
+
2779
+ @Test
2780
+ fun whenBookmarkAddedThenPersistFavicon () = coroutineRule.runBlocking {
2781
+ val url = " http://example.com"
2782
+ loadUrl(url, " A title" )
2783
+
2784
+ testee.onBookmarkAddRequested()
2785
+
2786
+ verify(mockFaviconManager).persistFavicon(any(), eq(url))
2787
+ }
2788
+
2789
+ @Test
2790
+ fun whenBookmarkAddedButUrlIsNullThenDoNotPersistFavicon () = coroutineRule.runBlocking {
2791
+ loadUrl(null , " A title" )
2792
+
2793
+ testee.onBookmarkAddRequested()
2794
+
2795
+ verify(mockFaviconManager, never()).persistFavicon(any(), any())
2796
+ }
2797
+
2798
+ @Test
2799
+ fun whenFireproofWebsiteAddedThenPersistFavicon () = coroutineRule.runBlocking {
2800
+ val url = " http://example.com"
2801
+ loadUrl(url, isBrowserShowing = true )
2802
+
2803
+ testee.onFireproofWebsiteMenuClicked()
2804
+
2805
+ assertCommandIssued<Command .ShowFireproofWebSiteConfirmation > {
2806
+ verify(mockFaviconManager).persistFavicon(any(), eq(this .fireproofWebsiteEntity.domain))
2807
+ }
2808
+ }
2809
+
2810
+ @Test
2811
+ fun whenOnPinPageToHomeSelectedThenAddHomeShortcutCommandIssuedWithFavicon () = coroutineRule.runBlocking {
2812
+ val url = " http://example.com"
2813
+ val bitmap: Bitmap = Bitmap .createBitmap(1 , 1 , Bitmap .Config .RGB_565 )
2814
+ whenever(mockFaviconManager.loadFromTemp(any(), any())).thenReturn(bitmap)
2815
+ loadUrl(url, " A title" )
2816
+
2817
+ testee.onPinPageToHomeSelected()
2818
+
2819
+ assertCommandIssued<Command .AddHomeShortcut > {
2820
+ assertEquals(bitmap, this .icon)
2821
+ assertEquals(url, this .url)
2822
+ assertEquals(" example.com" , this .title)
2823
+ }
2824
+ }
2825
+
2826
+ @Test
2827
+ fun whenOnPinPageToHomeSelectedAndFaviconDoesNotExistThenAddHomeShortcutCommandIssuedWithoutFavicon () = coroutineRule.runBlocking {
2828
+ val url = " http://example.com"
2829
+ whenever(mockFaviconManager.loadFromTemp(any(), any())).thenReturn(null )
2830
+ loadUrl(url, " A title" )
2831
+
2832
+ testee.onPinPageToHomeSelected()
2833
+
2834
+ assertCommandIssued<Command .AddHomeShortcut > {
2835
+ assertNull(this .icon)
2836
+ assertEquals(url, this .url)
2837
+ assertEquals(" example.com" , this .title)
2838
+ }
2839
+ }
2840
+
2676
2841
private fun givenNewPermissionRequestFromDomain (domain : String ) {
2677
2842
testee.onSiteLocationPermissionRequested(domain, StubPermissionCallback ())
2678
2843
}
0 commit comments