@@ -42,6 +42,7 @@ import com.duckduckgo.app.browser.BrowserTabViewModel.Command.Navigate
4242import com.duckduckgo.app.browser.LongPressHandler.RequiredAction.DownloadFile
4343import com.duckduckgo.app.browser.LongPressHandler.RequiredAction.OpenInNewTab
4444import com.duckduckgo.app.browser.addtohome.AddToHomeCapabilityDetector
45+ import com.duckduckgo.app.browser.defaultbrowsing.DefaultBrowserDetector
4546import com.duckduckgo.app.browser.favicon.FaviconDownloader
4647import com.duckduckgo.app.browser.model.BasicAuthenticationCredentials
4748import com.duckduckgo.app.browser.model.BasicAuthenticationRequest
@@ -52,6 +53,7 @@ import com.duckduckgo.app.cta.db.DismissedCtaDao
5253import com.duckduckgo.app.cta.model.DismissedCta
5354import com.duckduckgo.app.cta.ui.CtaViewModel
5455import com.duckduckgo.app.cta.ui.DaxBubbleCta
56+ import com.duckduckgo.app.cta.ui.DaxDialogCta
5557import com.duckduckgo.app.cta.ui.HomePanelCta
5658import com.duckduckgo.app.global.db.AppDatabase
5759import com.duckduckgo.app.global.install.AppInstallStore
@@ -176,6 +178,9 @@ class BrowserTabViewModelTest {
176178 @Mock
177179 private lateinit var mockPrivacySettingsStore: PrivacySettingsStore
178180
181+ @Mock
182+ private lateinit var mockDefaultBrowserDetector: DefaultBrowserDetector
183+
179184 private lateinit var mockAutoCompleteApi: AutoCompleteApi
180185
181186 private lateinit var ctaViewModel: CtaViewModel
@@ -208,7 +213,8 @@ class BrowserTabViewModelTest {
208213 mockVariantManager,
209214 mockSettingsStore,
210215 mockOnboardingStore,
211- mockPrivacySettingsStore
216+ mockPrivacySettingsStore,
217+ mockDefaultBrowserDetector
212218 )
213219
214220 val siteFactory = SiteFactory (mockPrivacyPractices, mockEntityLookup)
@@ -240,7 +246,9 @@ class BrowserTabViewModelTest {
240246 searchCountDao = mockSearchCountDao,
241247 pixel = mockPixel,
242248 variantManager = mockVariantManager,
243- dispatchers = coroutineRule.testDispatcherProvider
249+ dispatchers = coroutineRule.testDispatcherProvider,
250+ defaultBrowserDetector = mockDefaultBrowserDetector,
251+ installStore = mockAppInstallStore
244252 )
245253
246254 testee.loadData(" abc" , null , false )
@@ -1361,7 +1369,7 @@ class BrowserTabViewModelTest {
13611369 @Test
13621370 fun whenSurveyCtaDismissedAndNoOtherCtaPossibleCtaIsNull () {
13631371 testee.onSurveyChanged(Survey (" abc" , " http://example.com" , daysInstalled = 1 , status = Survey .Status .SCHEDULED ))
1364- testee.onUserDismissedCta()
1372+ testee.onUserDismissedCta(testee.ctaViewState.value !! .cta !! )
13651373 assertNull(testee.ctaViewState.value!! .cta)
13661374 }
13671375
@@ -1372,7 +1380,7 @@ class BrowserTabViewModelTest {
13721380 whenever(mockWidgetCapabilities.hasInstalledWidgets).thenReturn(false )
13731381
13741382 testee.onSurveyChanged(Survey (" abc" , " http://example.com" , daysInstalled = 1 , status = Survey .Status .SCHEDULED ))
1375- testee.onUserDismissedCta()
1383+ testee.onUserDismissedCta(testee.ctaViewState.value !! .cta !! )
13761384 assertEquals(HomePanelCta .AddWidgetAuto , testee.ctaViewState.value!! .cta)
13771385 }
13781386
@@ -1467,75 +1475,171 @@ class BrowserTabViewModelTest {
14671475 @Test
14681476 fun whenUserClickedCtaButtonThenFirePixel () {
14691477 val cta = DaxBubbleCta .DaxIntroCta (mockOnboardingStore, mockAppInstallStore)
1470- testee.ctaViewState.value = BrowserTabViewModel .CtaViewState (cta = cta)
1471-
1472- testee.onUserClickCtaOkButton()
1478+ testee.onUserClickCtaOkButton(cta)
14731479 verify(mockPixel).fire(cta.okPixel!! , cta.pixelOkParameters())
14741480 }
14751481
14761482 @Test
1477- fun whenUserClickedCtaButtonThenLaunchSurveyCommand () {
1483+ fun whenUserClickedSurveyCtaButtonThenLaunchSurveyCommand () {
14781484 val cta = HomePanelCta .Survey (Survey (" abc" , " http://example.com" , daysInstalled = 1 , status = Survey .Status .SCHEDULED ))
1479- testee.ctaViewState.value = BrowserTabViewModel .CtaViewState (cta = cta)
1480-
1481- testee.onUserClickCtaOkButton()
1485+ testee.onUserClickCtaOkButton(cta)
14821486 assertCommandIssued<Command .LaunchSurvey >()
14831487 }
14841488
14851489 @Test
1486- fun whenUserClickedCtaButtonThenLaunchAddWidgetCommand () {
1490+ fun whenUserClickedAddWidgetCtaButtonThenLaunchAddWidgetCommand () {
14871491 val cta = HomePanelCta .AddWidgetAuto
1488- testee.ctaViewState.value = BrowserTabViewModel .CtaViewState (cta = cta)
1489-
1490- testee.onUserClickCtaOkButton()
1492+ testee.onUserClickCtaOkButton(cta)
14911493 assertCommandIssued<Command .LaunchAddWidget >()
14921494 }
14931495
14941496 @Test
1495- fun whenUserClickedCtaButtonThenLaunchLegacyAddWidgetCommand () {
1497+ fun whenUserClickedLegacyAddWidgetCtaButtonThenLaunchLegacyAddWidgetCommand () {
14961498 val cta = HomePanelCta .AddWidgetInstructions
1497- testee.ctaViewState.value = BrowserTabViewModel .CtaViewState (cta = cta)
1499+ testee.onUserClickCtaOkButton(cta)
1500+ assertCommandIssued<Command .LaunchLegacyAddWidget >()
1501+ }
14981502
1499- testee.onUserClickCtaOkButton()
1503+ @Test
1504+ fun whenUserClickedDefaultBrowserCtaButtonWithoutDefaultBrowserThenLaunchDialogCommand () {
1505+ whenever(mockDefaultBrowserDetector.hasDefaultBrowser()).thenReturn(false )
1506+ val cta = DaxDialogCta .DefaultBrowserCta (mockDefaultBrowserDetector, mock(), mock())
1507+ testee.onUserClickCtaOkButton(cta)
1508+ assertCommandIssued<Command .OpenDefaultBrowserDialog >()
1509+ }
1510+
1511+ @Test
1512+ fun whenUserClickedDefaultBrowserCtaButtonWithDefaultBrowserThenOpenDefaultBrowserSettings () {
1513+ whenever(mockDefaultBrowserDetector.hasDefaultBrowser()).thenReturn(true )
1514+ val cta = DaxDialogCta .DefaultBrowserCta (mockDefaultBrowserDetector, mock(), mock())
1515+ testee.onUserClickCtaOkButton(cta)
1516+ assertCommandIssued<Command .OpenDefaultBrowserSettings >()
1517+ }
1518+
1519+ @Test
1520+ fun whenUserClickedDaxSearchWidgetCtaButtonWithWidgetCapabilitiesThenLaunchAddWidget () {
1521+ whenever(mockWidgetCapabilities.supportsAutomaticWidgetAdd).thenReturn(true )
1522+ val cta = DaxDialogCta .SearchWidgetCta (mockWidgetCapabilities, mock(), mock())
1523+ testee.onUserClickCtaOkButton(cta)
1524+ assertCommandIssued<Command .LaunchAddWidget >()
1525+ }
1526+
1527+ @Test
1528+ fun whenUserClickedDaxSearchWidgetCtaButtonWithoutWidgetCapabilitiesThenLaunchLegacyAddWidget () {
1529+ whenever(mockWidgetCapabilities.supportsAutomaticWidgetAdd).thenReturn(false )
1530+ val cta = DaxDialogCta .SearchWidgetCta (mockWidgetCapabilities, mock(), mock())
1531+ testee.onUserClickCtaOkButton(cta)
15001532 assertCommandIssued<Command .LaunchLegacyAddWidget >()
15011533 }
15021534
15031535 @Test
15041536 fun whenUserDismissedCtaThenFirePixel () {
15051537 val cta = HomePanelCta .Survey (Survey (" abc" , " http://example.com" , daysInstalled = 1 , status = Survey .Status .SCHEDULED ))
1506- testee.ctaViewState.value = BrowserTabViewModel .CtaViewState (cta = cta)
1507-
1508- testee.onUserDismissedCta()
1538+ testee.onUserDismissedCta(cta)
15091539 verify(mockPixel).fire(cta.cancelPixel!! , cta.pixelCancelParameters())
15101540 }
15111541
15121542 @Test
15131543 fun whenUserDismissedCtaThenRegisterInDatabase () {
15141544 val cta = HomePanelCta .AddWidgetAuto
1515- testee.ctaViewState.value = BrowserTabViewModel .CtaViewState (cta = cta)
1516-
1517- testee.onUserDismissedCta()
1545+ testee.onUserDismissedCta(cta)
15181546 verify(mockDismissedCtaDao).insert(DismissedCta (cta.ctaId))
15191547 }
15201548
15211549 @Test
15221550 fun whenUserDismissedSurveyCtaThenDoNotRegisterInDatabase () {
15231551 val cta = HomePanelCta .Survey (Survey (" abc" , " http://example.com" , daysInstalled = 1 , status = Survey .Status .SCHEDULED ))
1524- testee.ctaViewState.value = BrowserTabViewModel .CtaViewState (cta = cta)
1525-
1526- testee.onUserDismissedCta()
1552+ testee.onUserDismissedCta(cta)
15271553 verify(mockDismissedCtaDao, never()).insert(DismissedCta (cta.ctaId))
15281554 }
15291555
15301556 @Test
15311557 fun whenUserDismissedSurveyCtaThenCancelScheduledSurveys () {
15321558 val cta = HomePanelCta .Survey (Survey (" abc" , " http://example.com" , daysInstalled = 1 , status = Survey .Status .SCHEDULED ))
1533- testee.ctaViewState.value = BrowserTabViewModel .CtaViewState (cta = cta)
1534-
1535- testee.onUserDismissedCta()
1559+ testee.onUserDismissedCta(cta)
15361560 verify(mockSurveyDao).cancelScheduledSurveys()
15371561 }
15381562
1563+ @Test
1564+ fun whenUserFailedSettingDdgAsDefaultBrowserFromSettingsThenFirePixelAndUpdateInstallStore () {
1565+ whenever(mockDefaultBrowserDetector.isDefaultBrowser()).thenReturn(false )
1566+
1567+ testee.onUserTriedToSetAsDefaultBrowserFromSettings()
1568+
1569+ verify(mockAppInstallStore).defaultBrowser = false
1570+ verify(mockPixel).fire(Pixel .PixelName .DEFAULT_BROWSER_NOT_SET , defaultBrowserPixelParams(Pixel .PixelValues .DEFAULT_BROWSER_SETTINGS ))
1571+ }
1572+
1573+ @Test
1574+ fun whenUserHasSetDdgAsDefaultBrowserFromSettingsThenFirePixelAndUpdateInstallStore () {
1575+ whenever(mockDefaultBrowserDetector.isDefaultBrowser()).thenReturn(true )
1576+
1577+ testee.onUserTriedToSetAsDefaultBrowserFromSettings()
1578+
1579+ verify(mockAppInstallStore).defaultBrowser = true
1580+ verify(mockPixel).fire(Pixel .PixelName .DEFAULT_BROWSER_SET , defaultBrowserPixelParams(Pixel .PixelValues .DEFAULT_BROWSER_SETTINGS ))
1581+ }
1582+
1583+ @Test
1584+ fun whenUserFailedSettingDdgAsDefaultBrowserFromDialogOnceThenOpenDefaultBrowserDialogAgain () {
1585+ whenever(mockDefaultBrowserDetector.isDefaultBrowser()).thenReturn(false )
1586+
1587+ testee.onUserTriedToSetAsDefaultBrowserFromDialog()
1588+
1589+ assertCommandIssued<Command .OpenDefaultBrowserDialog >()
1590+ }
1591+
1592+ @Test
1593+ fun whenUserFailedSettingDdgAsDefaultBrowserFromDialogTwiceThenFirePixelAndUpdateInstallStore () {
1594+ whenever(mockDefaultBrowserDetector.isDefaultBrowser()).thenReturn(false )
1595+
1596+ testee.onUserTriedToSetAsDefaultBrowserFromDialog()
1597+ testee.onUserTriedToSetAsDefaultBrowserFromDialog()
1598+
1599+ verify(mockAppInstallStore, times(2 )).defaultBrowser = false
1600+ verify(mockPixel).fire(
1601+ Pixel .PixelName .DEFAULT_BROWSER_NOT_SET ,
1602+ defaultBrowserPixelParams(Pixel .PixelValues .DEFAULT_BROWSER_JUST_ONCE_MAX )
1603+ )
1604+ }
1605+
1606+ @Test
1607+ fun whenUserHasSetDdgAsDefaultBrowserFromDialogThenFirePixelAndUpdateInstallStore () {
1608+ whenever(mockDefaultBrowserDetector.isDefaultBrowser()).thenReturn(true )
1609+
1610+ testee.onUserTriedToSetAsDefaultBrowserFromDialog()
1611+
1612+ verify(mockAppInstallStore).defaultBrowser = true
1613+ verify(mockPixel).fire(Pixel .PixelName .DEFAULT_BROWSER_SET , defaultBrowserPixelParams(Pixel .PixelValues .DEFAULT_BROWSER_DIALOG ))
1614+ }
1615+
1616+ @Test
1617+ fun whenUserDismissesDefaultBrowserDialogThenFirePixelAndUpdateInstallStore () {
1618+ whenever(mockDefaultBrowserDetector.isDefaultBrowser()).thenReturn(false )
1619+
1620+ testee.onUserDismissedDefaultBrowserDialog()
1621+
1622+ verify(mockAppInstallStore).defaultBrowser = false
1623+ verify(mockPixel).fire(
1624+ Pixel .PixelName .DEFAULT_BROWSER_NOT_SET ,
1625+ defaultBrowserPixelParams(Pixel .PixelValues .DEFAULT_BROWSER_DIALOG_DISMISSED )
1626+ )
1627+ }
1628+
1629+ @Test
1630+ fun whenDefaultBrowserDialogDismissedAfterSelectingDefaultExternalBrowserAlwThenFirePixelAndUpdateInstallStore () {
1631+ whenever(mockDefaultBrowserDetector.isDefaultBrowser()).thenReturn(false )
1632+ whenever(mockDefaultBrowserDetector.hasDefaultBrowser()).thenReturn(true )
1633+
1634+ testee.onUserDismissedDefaultBrowserDialog()
1635+
1636+ verify(mockAppInstallStore).defaultBrowser = false
1637+ verify(mockPixel).fire(
1638+ Pixel .PixelName .DEFAULT_BROWSER_NOT_SET ,
1639+ defaultBrowserPixelParams(Pixel .PixelValues .DEFAULT_BROWSER_EXTERNAL )
1640+ )
1641+ }
1642+
15391643 private inline fun <reified T : Command > assertCommandIssued (instanceAssertions : T .() -> Unit = {}) {
15401644 verify(mockCommandObserver, atLeastOnce()).onChanged(commandCaptor.capture())
15411645 val issuedCommand = commandCaptor.allValues.find { it is T }
@@ -1548,6 +1652,12 @@ class BrowserTabViewModelTest {
15481652 Pixel .PixelParameter .BOOKMARK_CAPABLE to bookmarkCapable.toString()
15491653 )
15501654
1655+ private fun defaultBrowserPixelParams (origin : String ) = mapOf (
1656+ Pixel .PixelParameter .DEFAULT_BROWSER_SET_FROM_ONBOARDING to false .toString(),
1657+ Pixel .PixelParameter .DEFAULT_BROWSER_SET_ORIGIN to origin
1658+ )
1659+
1660+
15511661 private fun givenExpectedCtaAddWidgetInstructions () {
15521662 setBrowserShowing(false )
15531663 whenever(mockWidgetCapabilities.supportsStandardWidgetAdd).thenReturn(true )
0 commit comments