Skip to content

Commit 6ffc9b3

Browse files
committed
Merge branch 'release/5.53.0'
2 parents 8a31ee9 + 9d7ca16 commit 6ffc9b3

File tree

85 files changed

+1973
-1181
lines changed

Some content is hidden

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

85 files changed

+1973
-1181
lines changed

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -611,16 +611,18 @@ class BrowserTabViewModelTest {
611611
}
612612

613613
@Test
614-
fun whenBrowserNotShownAndOmnibarInputDoesNotHaveFocusThenPrivacyGradeIsNotShown() {
614+
fun whenOmnibarDoesNotHaveFocusThenPrivacyGradeIsShownAndSearchIconIsHidden() {
615615
testee.onOmnibarInputStateChanged(query = "", hasFocus = false, hasQueryChanged = false)
616-
assertFalse(browserViewState().showPrivacyGrade)
616+
assertTrue(browserViewState().showPrivacyGrade)
617+
assertFalse(browserViewState().showSearchIcon)
617618
}
618619

619620
@Test
620-
fun whenBrowserShownAndOmnibarInputDoesNotHaveFocusThenPrivacyGradeIsShown() {
621+
fun whenBrowserShownAndOmnibarInputDoesNotHaveFocusThenPrivacyGradeIsShownAndSearchIconIsHidden() {
621622
testee.onUserSubmittedQuery("foo")
622623
testee.onOmnibarInputStateChanged(query = "", hasFocus = false, hasQueryChanged = false)
623624
assertTrue(browserViewState().showPrivacyGrade)
625+
assertFalse(browserViewState().showSearchIcon)
624626
}
625627

626628
@Test
@@ -630,10 +632,11 @@ class BrowserTabViewModelTest {
630632
}
631633

632634
@Test
633-
fun whenBrowserShownAndOmnibarInputHasFocusThenPrivacyGradeIsShown() {
635+
fun whenBrowserShownAndOmnibarInputHasFocusThenSearchIconIsShownAndPrivacyGradeIsHidden() {
634636
testee.onUserSubmittedQuery("foo")
635637
testee.onOmnibarInputStateChanged("", true, hasQueryChanged = false)
636-
assertTrue(browserViewState().showPrivacyGrade)
638+
assertFalse(browserViewState().showPrivacyGrade)
639+
assertTrue(browserViewState().showSearchIcon)
637640
}
638641

639642
@Test

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

Lines changed: 25 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,20 @@
1919
package com.duckduckgo.app.notification
2020

2121
import androidx.test.platform.app.InstrumentationRegistry
22+
import androidx.work.OneTimeWorkRequestBuilder
2223
import androidx.work.WorkInfo
2324
import androidx.work.WorkManager
2425
import com.duckduckgo.app.CoroutineTestRule
25-
import com.duckduckgo.app.notification.NotificationScheduler.*
26+
import com.duckduckgo.app.notification.NotificationScheduler.ClearDataNotificationWorker
27+
import com.duckduckgo.app.notification.NotificationScheduler.PrivacyNotificationWorker
2628
import com.duckduckgo.app.notification.model.SchedulableNotification
27-
import com.duckduckgo.app.notification.model.SearchNotification
2829
import com.duckduckgo.app.statistics.VariantManager
2930
import com.duckduckgo.app.statistics.VariantManager.Companion.DEFAULT_VARIANT
3031
import com.nhaarman.mockitokotlin2.any
3132
import com.nhaarman.mockitokotlin2.mock
3233
import com.nhaarman.mockitokotlin2.whenever
3334
import kotlinx.coroutines.ExperimentalCoroutinesApi
3435
import kotlinx.coroutines.runBlocking
35-
import org.junit.After
3636
import org.junit.Assert.assertTrue
3737
import org.junit.Before
3838
import org.junit.Rule
@@ -48,7 +48,6 @@ class AndroidNotificationSchedulerTest {
4848
private val variantManager: VariantManager = mock()
4949
private val clearNotification: SchedulableNotification = mock()
5050
private val privacyNotification: SchedulableNotification = mock()
51-
private val searchPromptNotification: SearchNotification = mock()
5251

5352
private val context = InstrumentationRegistry.getInstrumentation().targetContext
5453
private var workManager = WorkManager.getInstance(context)
@@ -60,135 +59,81 @@ class AndroidNotificationSchedulerTest {
6059
testee = NotificationScheduler(
6160
workManager,
6261
clearNotification,
63-
privacyNotification,
64-
searchPromptNotification
62+
privacyNotification
6563
)
6664
}
6765

68-
@After
69-
fun resetWorkers() {
70-
workManager.cancelAllWorkByTag(NotificationScheduler.CONTINUOUS_APP_USE_REQUEST_TAG)
71-
}
72-
73-
@Test
74-
fun whenPrivacyNotificationClearDataAndSearchPromptCanShowThenBothAreScheduled() = runBlocking<Unit> {
75-
whenever(privacyNotification.canShow()).thenReturn(true)
76-
whenever(clearNotification.canShow()).thenReturn(true)
77-
whenever(searchPromptNotification.canShow()).thenReturn(true)
78-
testee.scheduleNextNotification()
79-
80-
assertUnusedAppNotificationScheduled(PrivacyNotificationWorker::class.jvmName)
81-
assertContinuousAppUseNotificationScheduled(SearchPromptNotificationWorker::class.jvmName)
82-
}
83-
8466
@Test
85-
fun whenPrivacyNotificationClearDataAndSearchPromptCanShowThenPrivacyNotificationScheduled() = runBlocking<Unit> {
67+
fun whenPrivacyNotificationClearDataCanShowThenPrivacyNotificationIsScheduled() = runBlocking<Unit> {
8668
whenever(privacyNotification.canShow()).thenReturn(true)
8769
whenever(clearNotification.canShow()).thenReturn(true)
88-
whenever(searchPromptNotification.canShow()).thenReturn(false)
89-
testee.scheduleNextNotification()
90-
91-
assertUnusedAppNotificationScheduled(PrivacyNotificationWorker::class.jvmName)
92-
assertNoContinuousAppNotificationScheduled()
93-
}
94-
95-
@Test
96-
fun whenPrivacyNotificationAndSearchPromptCanShowButClearDataCannotThenThenBothAreScheduled() = runBlocking<Unit> {
97-
whenever(privacyNotification.canShow()).thenReturn(true)
98-
whenever(clearNotification.canShow()).thenReturn(false)
99-
whenever(searchPromptNotification.canShow()).thenReturn(true)
10070
testee.scheduleNextNotification()
10171

10272
assertUnusedAppNotificationScheduled(PrivacyNotificationWorker::class.jvmName)
103-
assertContinuousAppUseNotificationScheduled(SearchPromptNotificationWorker::class.jvmName)
10473
}
10574

10675
@Test
107-
fun whenPrivacyNotificationCanShowButClearDataAndSearchPromptCannotThenPrivacyNotificationScheduled() = runBlocking<Unit> {
76+
fun whenPrivacyNotificationCanShowButClearDataCannotThenPrivacyNotificationIsScheduled() = runBlocking<Unit> {
10877
whenever(privacyNotification.canShow()).thenReturn(true)
10978
whenever(clearNotification.canShow()).thenReturn(false)
110-
whenever(searchPromptNotification.canShow()).thenReturn(false)
11179
testee.scheduleNextNotification()
11280

11381
assertUnusedAppNotificationScheduled(PrivacyNotificationWorker::class.jvmName)
114-
assertNoContinuousAppNotificationScheduled()
11582
}
11683

11784
@Test
118-
fun whenPrivacyNotificationAndSearchPromptCannotShowAndClearNotificationCanShowThenBothAreScheduled() = runBlocking<Unit> {
85+
fun whenPrivacyNotificationCannotShowAndClearNotificationCanShowThenClearNotificationIsScheduled() = runBlocking<Unit> {
11986
whenever(privacyNotification.canShow()).thenReturn(false)
12087
whenever(clearNotification.canShow()).thenReturn(true)
121-
whenever(searchPromptNotification.canShow()).thenReturn(true)
12288
testee.scheduleNextNotification()
12389

12490
assertUnusedAppNotificationScheduled(ClearDataNotificationWorker::class.jvmName)
125-
assertContinuousAppUseNotificationScheduled(SearchPromptNotificationWorker::class.jvmName)
12691
}
12792

12893
@Test
129-
fun whenPrivacyNotificationAndClearNotificationCannotShowButSearchPromptCanShowThenNotificationScheduled() = runBlocking<Unit> {
94+
fun whenPrivacyNotificationAndClearNotificationCannotShowThenNoNotificationScheduled() = runBlocking<Unit> {
13095
whenever(privacyNotification.canShow()).thenReturn(false)
13196
whenever(clearNotification.canShow()).thenReturn(false)
132-
whenever(searchPromptNotification.canShow()).thenReturn(true)
13397
testee.scheduleNextNotification()
13498

135-
assertContinuousAppUseNotificationScheduled(SearchPromptNotificationWorker::class.jvmName)
13699
assertNoUnusedAppNotificationScheduled()
137100
}
138101

139102
@Test
140-
fun whenPrivacyNotificationAndClearNotificationCannotShowButSearchPromptCanThenSearchPromptNotificationScheduled() = runBlocking<Unit> {
103+
fun whenNotificationIsScheduledOldJobsAreCancelled() = runBlocking<Unit> {
141104
whenever(privacyNotification.canShow()).thenReturn(false)
142105
whenever(clearNotification.canShow()).thenReturn(false)
143-
whenever(searchPromptNotification.canShow()).thenReturn(true)
106+
107+
enqueueDeprecatedJobs()
144108

145109
testee.scheduleNextNotification()
146110

147-
assertContinuousAppUseNotificationScheduled(SearchPromptNotificationWorker::class.jvmName)
148-
assertNoUnusedAppNotificationScheduled()
111+
NotificationScheduler.allDeprecatedNotificationWorkTags().forEach {
112+
assertTrue(getScheduledWorkers(it).isEmpty())
113+
}
149114
}
150115

151-
@Test
152-
fun whenNoNotificationCanShowThenNoNotificationScheduled() = runBlocking<Unit> {
153-
whenever(privacyNotification.canShow()).thenReturn(false)
154-
whenever(clearNotification.canShow()).thenReturn(false)
155-
whenever(searchPromptNotification.canShow()).thenReturn(false)
156-
testee.scheduleNextNotification()
116+
private fun enqueueDeprecatedJobs() {
117+
NotificationScheduler.allDeprecatedNotificationWorkTags().forEach {
118+
val request = OneTimeWorkRequestBuilder<PrivacyNotificationWorker>()
119+
.addTag(it)
120+
.build()
157121

158-
assertNoNotificationScheduled()
122+
workManager.enqueue(request)
123+
}
159124
}
160125

161126
private fun assertUnusedAppNotificationScheduled(workerName: String) {
162-
assertTrue(getUnusedAppScheduledWorkers().any { it.tags.contains(workerName) })
163-
}
164-
165-
private fun assertContinuousAppUseNotificationScheduled(workerName: String) {
166-
assertTrue(getContinuousAppUseScheduledWorkers().any { it.tags.contains(workerName) })
127+
assertTrue(getScheduledWorkers(NotificationScheduler.UNUSED_APP_WORK_REQUEST_TAG).any { it.tags.contains(workerName) })
167128
}
168129

169130
private fun assertNoUnusedAppNotificationScheduled() {
170-
assertTrue(getUnusedAppScheduledWorkers().isEmpty())
171-
}
172-
173-
private fun assertNoContinuousAppNotificationScheduled() {
174-
assertTrue(getContinuousAppUseScheduledWorkers().isEmpty())
175-
}
176-
177-
private fun assertNoNotificationScheduled() {
178-
assertTrue(getUnusedAppScheduledWorkers().isEmpty())
179-
assertTrue(getContinuousAppUseScheduledWorkers().isEmpty())
180-
}
181-
182-
private fun getUnusedAppScheduledWorkers(): List<WorkInfo> {
183-
return workManager
184-
.getWorkInfosByTag(NotificationScheduler.UNUSED_APP_WORK_REQUEST_TAG)
185-
.get()
186-
.filter { it.state == WorkInfo.State.ENQUEUED }
131+
assertTrue(getScheduledWorkers(NotificationScheduler.UNUSED_APP_WORK_REQUEST_TAG).isEmpty())
187132
}
188133

189-
private fun getContinuousAppUseScheduledWorkers(): List<WorkInfo> {
134+
private fun getScheduledWorkers(tag: String): List<WorkInfo> {
190135
return workManager
191-
.getWorkInfosByTag(NotificationScheduler.CONTINUOUS_APP_USE_REQUEST_TAG)
136+
.getWorkInfosByTag(tag)
192137
.get()
193138
.filter { it.state == WorkInfo.State.ENQUEUED }
194139
}

app/src/androidTest/java/com/duckduckgo/app/settings/SettingsViewModelTest.kt

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,6 @@ class SettingsViewModelTest {
6767
@Mock
6868
private lateinit var mockVariantManager: VariantManager
6969

70-
@Mock
71-
private lateinit var notificationScheduler: AndroidNotificationScheduler
72-
7370
@Mock
7471
private lateinit var mockPixel: Pixel
7572

@@ -82,7 +79,7 @@ class SettingsViewModelTest {
8279
context = InstrumentationRegistry.getInstrumentation().targetContext
8380
commandCaptor = argumentCaptor()
8481

85-
testee = SettingsViewModel(mockAppSettingsDataStore, mockDefaultBrowserDetector, mockVariantManager, mockPixel, notificationScheduler)
82+
testee = SettingsViewModel(mockAppSettingsDataStore, mockDefaultBrowserDetector, mockVariantManager, mockPixel)
8683
testee.command.observeForever(commandObserver)
8784

8885
whenever(mockAppSettingsDataStore.automaticallyClearWhenOption).thenReturn(APP_EXIT_ONLY)
@@ -230,32 +227,5 @@ class SettingsViewModelTest {
230227
assertEquals(Command.LaunchAppIcon, commandCaptor.firstValue)
231228
}
232229

233-
@Test
234-
fun whenSearchNotificationWasPreviouslyEnabledThenViewStateIndicatesIt() {
235-
whenever(mockAppSettingsDataStore.searchNotificationEnabled).thenReturn(true)
236-
testee.start()
237-
assertTrue(latestViewState().searchNotificationEnabled)
238-
}
239-
240-
@Test
241-
fun whenSearchNotificationToggledOnThenDataStoreIsUpdatedAndNotificationShown() {
242-
testee.onSearchNotificationSettingChanged(true)
243-
verify(mockAppSettingsDataStore).searchNotificationEnabled = true
244-
verify(notificationScheduler).launchStickySearchNotification()
245-
verify(mockPixel).fire(Pixel.PixelName.QUICK_SEARCH_NOTIFICATION_ENABLED)
246-
247-
assertTrue(latestViewState().searchNotificationEnabled)
248-
}
249-
250-
@Test
251-
fun whenSearchNotificationToggledOffThenDataStoreIsUpdatedAndNotificationRemoved() {
252-
testee.onSearchNotificationSettingChanged(false)
253-
verify(mockAppSettingsDataStore).searchNotificationEnabled = false
254-
verify(notificationScheduler).dismissStickySearchNotification()
255-
verify(mockPixel).fire(Pixel.PixelName.QUICK_SEARCH_NOTIFICATION_DISABLED)
256-
257-
assertFalse(latestViewState().searchNotificationEnabled)
258-
}
259-
260230
private fun latestViewState() = testee.viewState.value!!
261231
}

app/src/androidTest/java/com/duckduckgo/app/statistics/VariantManagerTest.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,34 +30,34 @@ class VariantManagerTest {
3030
// SERP Experiment(s)
3131

3232
@Test
33-
fun serpControlVariantIsInactiveAndHasNoFeatures() {
33+
fun serpControlVariantHasExpectedWeightAndNoFeatures() {
3434
val variant = variants.first { it.key == "sc" }
35-
assertEqualsDouble(1.0, variant.weight)
35+
assertEqualsDouble(0.0, variant.weight)
3636
assertEquals(0, variant.features.size)
3737
}
3838

3939
@Test
40-
fun serpExperimentalVariantIsInactiveAndHasNoFeatures() {
40+
fun serpExperimentalVariantHasExpectedWeightAndNoFeatures() {
4141
val variant = variants.first { it.key == "se" }
42-
assertEqualsDouble(1.0, variant.weight)
42+
assertEqualsDouble(0.0, variant.weight)
4343
assertEquals(0, variant.features.size)
4444
}
4545

46-
// Search Notification Experiment
46+
// Bottom Bar Navigation Experiment
4747

4848
@Test
49-
fun searchNotificationControlVariantIsActiveAndHasNoFeatures() {
50-
val variant = variants.first { it.key == "mf" }
49+
fun bottomBarNavigationControlVariantIsActiveAndHasNoFeatures() {
50+
val variant = variants.first { it.key == "mm" }
5151
assertEqualsDouble(1.0, variant.weight)
5252
assertEquals(0, variant.features.size)
5353
}
5454

5555
@Test
56-
fun searchNotificationVariantIsActiveAndHasStickySearchNotificationFeature() {
57-
val variant = variants.first { it.key == "mg" }
56+
fun bottomBarNavigationVariantIsActiveAndHasBottomBarNavigationFeature() {
57+
val variant = variants.first { it.key == "mn" }
5858
assertEqualsDouble(1.0, variant.weight)
5959
assertEquals(1, variant.features.size)
60-
assertTrue(variant.hasFeature(StickySearchNotification))
60+
assertTrue(variant.hasFeature(BottomBarNavigation))
6161
}
6262

6363
@Test

app/src/main/AndroidManifest.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,10 @@
234234
android:name="com.duckduckgo.app.tabs.ui.TabSwitcherActivity"
235235
android:label="@string/tabActivityTitle" />
236236

237+
<activity
238+
android:name="com.duckduckgo.app.tabs.ui.TabSwitcherBottomBarFeatureActivity"
239+
android:label="@string/tabActivityTitle" />
240+
237241
<activity
238242
android:name="com.duckduckgo.app.privacy.ui.PrivacyDashboardActivity"
239243
android:label="@string/privacyDashboardActivityTitle"

app/src/main/java/com/duckduckgo/app/about/AboutDuckDuckGoActivity.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,14 @@ class AboutDuckDuckGoActivity : DuckDuckGoActivity() {
3131
override fun onCreate(savedInstanceState: Bundle?) {
3232
super.onCreate(savedInstanceState)
3333
setContentView(R.layout.activity_about_duck_duck_go)
34-
configureActionBar()
34+
setupToolbar(toolbar)
3535

3636
learnMoreLink.setOnClickListener {
3737
startActivity(BrowserActivity.intent(this, Url.ABOUT))
3838
finish()
3939
}
4040
}
4141

42-
private fun configureActionBar() {
43-
setSupportActionBar(toolbar)
44-
supportActionBar?.setDisplayHomeAsUpEnabled(true)
45-
}
46-
4742
companion object {
4843
fun intent(context: Context): Intent {
4944
return Intent(context, AboutDuckDuckGoActivity::class.java)

app/src/main/java/com/duckduckgo/app/bookmarks/ui/BookmarksActivity.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class BookmarksActivity : DuckDuckGoActivity() {
5959
override fun onCreate(savedInstanceState: Bundle?) {
6060
super.onCreate(savedInstanceState)
6161
setContentView(R.layout.activity_bookmarks)
62-
setupActionBar()
62+
setupToolbar(toolbar)
6363
setupBookmarksRecycler()
6464
observeViewModel()
6565
}
@@ -72,11 +72,6 @@ class BookmarksActivity : DuckDuckGoActivity() {
7272
recycler.addItemDecoration(separator)
7373
}
7474

75-
private fun setupActionBar() {
76-
setSupportActionBar(toolbar)
77-
supportActionBar?.setDisplayHomeAsUpEnabled(true)
78-
}
79-
8075
private fun observeViewModel() {
8176
viewModel.viewState.observe(this, Observer<BookmarksViewModel.ViewState> { viewState ->
8277
viewState?.let {

0 commit comments

Comments
 (0)