Skip to content

Commit 44b4566

Browse files
Merge branch 'release/5.254.0'
2 parents d737dd0 + ce43905 commit 44b4566

File tree

317 files changed

+9505
-2808
lines changed

Some content is hidden

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

317 files changed

+9505
-2808
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name: Design System Composable PR Tests
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- 'design-system/src/main/java/com/duckduckgo/common/ui/compose/**/*.kt'
7+
types: [opened, synchronize, reopened]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
maestro_test:
15+
runs-on: ubuntu-latest
16+
name: Run Design System Maestro Tests
17+
18+
steps:
19+
- name: Checkout repository
20+
uses: actions/checkout@v4
21+
with:
22+
submodules: recursive
23+
24+
- name: Set up JDK version
25+
uses: actions/setup-java@v4
26+
with:
27+
java-version-file: .github/.java-version
28+
distribution: 'adopt'
29+
30+
- name: Create folder
31+
run: mkdir apk
32+
33+
- name: Decode keys
34+
uses: davidSchuppa/base64Secret-toFile-action@v2
35+
with:
36+
secret: ${{ secrets.FAKE_RELEASE_PROPERTIES }}
37+
fileName: ddg_android_build.properties
38+
destination-path: $HOME/jenkins_static/com.duckduckgo.mobile.android/
39+
40+
- name: Decode key file
41+
uses: davidSchuppa/base64Secret-toFile-action@v2
42+
with:
43+
secret: ${{ secrets.FAKE_RELEASE_KEY }}
44+
fileName: android
45+
destination-path: $HOME/jenkins_static/com.duckduckgo.mobile.android/
46+
47+
- name: Setup Gradle
48+
uses: gradle/actions/setup-gradle@v3
49+
50+
- name: Assemble internal release APK
51+
run: ./gradlew assembleInternalRelease -Pforce-default-variant -Pskip-onboarding
52+
53+
- name: Move APK to new folder
54+
if: always()
55+
run: find . -name "*internal-release*.apk" -exec mv '{}' apk/internal.apk \;
56+
57+
- name: Run Design System Maestro Tests
58+
uses: mobile-dev-inc/[email protected]
59+
timeout-minutes: 30
60+
with:
61+
api-key: ${{ secrets.ROBIN_API_KEY }}
62+
project-id: ${{ vars.ROBIN_ANDROID_PROJECT_ID }}
63+
name: design_system_pr_${{ github.event.pull_request.number }}_${{ github.sha }}
64+
timeout: 15
65+
app-file: apk/internal.apk
66+
android-api-level: 30
67+
workspace: .maestro
68+
include-tags: androidDesignSystemTest
69+
70+
- name: Comment on PR
71+
if: failure()
72+
uses: actions/github-script@v8
73+
with:
74+
script: |
75+
github.rest.issues.createComment({
76+
issue_number: context.issue.number,
77+
owner: context.repo.owner,
78+
repo: context.repo.repo,
79+
body: "❌ Design System Maestro tests failed. Please check the [workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details."
80+
})

.maestro/ads_preview_flows/1-_design-system-components.yaml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ tags:
2424
- assertVisible: "COLOR PALETTE"
2525
- tapOn: "TYPOGRAPHY"
2626
- scrollUntilVisible:
27+
timeout: 50000
28+
speed: 60
2729
element:
2830
text: "Text Appearance Caption"
2931
direction: DOWN
@@ -37,13 +39,17 @@ tags:
3739
- assertVisible: "Keep Using"
3840
- tapOn: "Keep Using"
3941
- scrollUntilVisible:
42+
timeout: 50000
43+
speed: 60
4044
element:
4145
text: "Stacked Text Alert Dialog With 4 buttons"
4246
direction: DOWN
4347
- tapOn: "Stacked Text Alert Dialog With 4 buttons"
4448
- assertVisible: "Keep Using"
4549
- tapOn: "Keep Using"
4650
- scrollUntilVisible:
51+
timeout: 50000
52+
speed: 60
4753
element:
4854
text: "Promo Bottom Sheet with image"
4955
direction: DOWN
@@ -60,6 +66,8 @@ tags:
6066
- tapOn:
6167
id: "com.duckduckgo.mobile.android:id/bottomSheetPromoPrimaryButton"
6268
- scrollUntilVisible:
69+
timeout: 50000
70+
speed: 60
6371
element:
6472
text: "Cookie Consent dialog with animation"
6573
direction: DOWN
@@ -72,7 +80,7 @@ tags:
7280
- tapOn:
7381
id: "com.duckduckgo.mobile.android:id/primaryCta"
7482
- tapOn: "LAYOUTS"
75-
- assertVisible: "Expandable Layout"
83+
- assertVisible: "Dax Dialog Card"
7684
- tapOn: "INTERACTIVE"
7785
- tapOn:
7886
id: "com.duckduckgo.mobile.android:id/dax_switch_one"
@@ -100,11 +108,15 @@ tags:
100108
index: 0
101109
- tapOn: "LIST ITEMS"
102110
- scrollUntilVisible:
111+
timeout: 50000
112+
speed: 60
103113
element:
104114
text: "With Beta Pill and Switch"
105115
direction: DOWN
106116
- tapOn: "Others"
107117
- scrollUntilVisible:
118+
timeout: 50000
119+
speed: 60
108120
element:
109121
text: "Enable Dark Theme"
110122
direction: UP

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ dependencies {
374374
implementation project(':saved-sites-api')
375375
implementation project(':saved-sites-impl')
376376
implementation project(':saved-sites-store')
377+
internalImplementation project(':saved-sites-internal')
377378

378379
implementation project(':runtime-checks-impl')
379380
implementation project(':runtime-checks-store')

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

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ import com.duckduckgo.app.statistics.pixels.Pixel.PixelType.Unique
193193
import com.duckduckgo.app.statistics.pixels.Pixel.PixelValues.DAX_INITIAL_CTA
194194
import com.duckduckgo.app.statistics.pixels.Pixel.PixelValues.DAX_SERP_CTA
195195
import com.duckduckgo.app.surrogates.SurrogateResponse
196+
import com.duckduckgo.app.systemsearch.DeviceAppLookup
196197
import com.duckduckgo.app.tabs.model.TabEntity
197198
import com.duckduckgo.app.tabs.model.TabRepository
198199
import com.duckduckgo.app.tabs.store.TabStatsBucketing
@@ -203,6 +204,8 @@ import com.duckduckgo.app.trackerdetection.model.TrackingEvent
203204
import com.duckduckgo.app.usage.search.SearchCountDao
204205
import com.duckduckgo.app.widget.ui.WidgetCapabilities
205206
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
207+
import com.duckduckgo.autoconsent.impl.pixels.AutoConsentPixel
208+
import com.duckduckgo.autoconsent.impl.pixels.AutoconsentPixelManager
206209
import com.duckduckgo.autofill.api.AutofillCapabilityChecker
207210
import com.duckduckgo.autofill.api.domain.app.LoginCredentials
208211
import com.duckduckgo.autofill.api.email.EmailManager
@@ -293,7 +296,6 @@ import com.duckduckgo.site.permissions.api.SitePermissionsManager.LocationPermis
293296
import com.duckduckgo.site.permissions.api.SitePermissionsManager.SitePermissionQueryResponse
294297
import com.duckduckgo.site.permissions.api.SitePermissionsManager.SitePermissions
295298
import com.duckduckgo.subscriptions.api.SUBSCRIPTIONS_FEATURE_NAME
296-
import com.duckduckgo.subscriptions.api.SubscriptionRebrandingFeatureToggle
297299
import com.duckduckgo.subscriptions.api.Subscriptions
298300
import com.duckduckgo.subscriptions.api.SubscriptionsJSHelper
299301
import com.duckduckgo.sync.api.favicons.FaviconsFetchingPrompt
@@ -400,6 +402,8 @@ class BrowserTabViewModelTest {
400402

401403
private val mockHttpErrorPixels: HttpErrorPixels = mock()
402404

405+
private val mockAutoconsentPixelManager: AutoconsentPixelManager = mock()
406+
403407
private val mockOnboardingStore: OnboardingStore = mock()
404408

405409
private val mockAutoCompleteService: AutoCompleteService = mock()
@@ -580,7 +584,6 @@ class BrowserTabViewModelTest {
580584
private val mockSiteHttpErrorHandler: HttpCodeSiteErrorHandler = mock()
581585
private val mockSubscriptionsJSHelper: SubscriptionsJSHelper = mock()
582586
private val mockOnboardingHomeScreenWidgetToggles: OnboardingHomeScreenWidgetToggles = mock()
583-
private val mockRebrandingFeatureToggle: SubscriptionRebrandingFeatureToggle = mock()
584587
private val tabManager: TabManager = mock()
585588

586589
private val mockAddressDisplayFormatter: AddressDisplayFormatter by lazy {
@@ -618,6 +621,8 @@ class BrowserTabViewModelTest {
618621
private val fakeMessagingPlugins = FakeWebMessagingPluginPoint()
619622
private val fakePostMessageWrapperPlugins = FakePostMessageWrapperPluginPoint()
620623

624+
private val mockDeviceAppLookup: DeviceAppLookup = mock()
625+
621626
@Before
622627
fun before() =
623628
runTest {
@@ -648,6 +653,9 @@ class BrowserTabViewModelTest {
648653
mockHistory,
649654
DefaultDispatcherProvider(),
650655
mockPixel,
656+
mockDeviceAppLookup,
657+
coroutineRule.testScope,
658+
AutoComplete.Config(),
651659
)
652660
val fireproofWebsiteRepositoryImpl =
653661
FireproofWebsiteRepositoryImpl(
@@ -713,7 +721,6 @@ class BrowserTabViewModelTest {
713721
brokenSitePrompt = mockBrokenSitePrompt,
714722
onboardingHomeScreenWidgetToggles = mockOnboardingHomeScreenWidgetToggles,
715723
onboardingDesignExperimentManager = mockOnboardingDesignExperimentManager,
716-
rebrandingFeatureToggle = mockRebrandingFeatureToggle,
717724
)
718725

719726
val siteFactory =
@@ -847,6 +854,7 @@ class BrowserTabViewModelTest {
847854
webMessagingPlugins = fakeMessagingPlugins,
848855
postMessageWrapperPlugins = fakePostMessageWrapperPlugins,
849856
addressBarTrackersAnimationFeatureToggle = mockAddressBarTrackersAnimationFeatureToggle,
857+
autoconsentPixelManager = mockAutoconsentPixelManager,
850858
)
851859

852860
testee.loadData("abc", null, false, false)
@@ -6498,6 +6506,48 @@ class BrowserTabViewModelTest {
64986506
assertCommandIssued<ShowAutoconsentAnimation>()
64996507
}
65006508

6509+
@Test
6510+
fun whenAutoConsentPopupHandledAndCosmeticTrueThenFireAnimationShownCosmeticPixel() {
6511+
testee.browserViewState.value =
6512+
testee.browserViewState.value?.copy(
6513+
browserShowing = true,
6514+
maliciousSiteBlocked = false,
6515+
maliciousSiteStatus = null,
6516+
)
6517+
6518+
testee.onAutoConsentPopUpHandled(true)
6519+
6520+
verify(mockAutoconsentPixelManager).fireDailyPixel(AutoConsentPixel.AUTOCONSENT_ANIMATION_SHOWN_COSMETIC_DAILY)
6521+
}
6522+
6523+
@Test
6524+
fun whenAutoConsentPopupHandledAndCosmeticFalseThenFireAnimationShownPixel() {
6525+
testee.browserViewState.value =
6526+
testee.browserViewState.value?.copy(
6527+
browserShowing = true,
6528+
maliciousSiteBlocked = false,
6529+
maliciousSiteStatus = null,
6530+
)
6531+
6532+
testee.onAutoConsentPopUpHandled(false)
6533+
6534+
verify(mockAutoconsentPixelManager).fireDailyPixel(AutoConsentPixel.AUTOCONSENT_ANIMATION_SHOWN_DAILY)
6535+
}
6536+
6537+
@Test
6538+
fun whenAutoConsentPopupHandledAndMaliciousSiteBlockedThenNoPixelFired() {
6539+
testee.browserViewState.value =
6540+
testee.browserViewState.value?.copy(
6541+
browserShowing = true,
6542+
maliciousSiteBlocked = true,
6543+
maliciousSiteStatus = PHISHING,
6544+
)
6545+
6546+
testee.onAutoConsentPopUpHandled(true)
6547+
6548+
verify(mockAutoconsentPixelManager, never()).fireDailyPixel(any())
6549+
}
6550+
65016551
@Test
65026552
fun whenVisitSiteThenUpdateLoadingViewStateAndOmnibarViewState() {
65036553
testee.browserViewState.value =
@@ -7159,6 +7209,28 @@ class BrowserTabViewModelTest {
71597209
verify(mockOnboardingDesignExperimentManager).fireFireButtonClickedFromOnboardingPixel()
71607210
}
71617211

7212+
@Test
7213+
fun whenFireMenuSelectedAndFireButtonHighlightedThenHighlightIsCleared() = runTest {
7214+
testee.browserViewState.value = browserViewState().copy(fireButton = HighlightableButton.Visible(highlighted = true))
7215+
7216+
testee.onFireMenuSelected()
7217+
7218+
val viewState = testee.browserViewState.value
7219+
assertNotNull(viewState)
7220+
assertFalse((viewState.fireButton as HighlightableButton.Visible).highlighted)
7221+
}
7222+
7223+
@Test
7224+
fun whenFireMenuSelectedAndFireButtonNotHighlightedThenStateUnchanged() = runTest {
7225+
testee.browserViewState.value = browserViewState().copy(fireButton = HighlightableButton.Visible(highlighted = false))
7226+
7227+
testee.onFireMenuSelected()
7228+
7229+
val viewState = testee.browserViewState.value
7230+
assertNotNull(viewState)
7231+
assertFalse((viewState.fireButton as HighlightableButton.Visible).highlighted)
7232+
}
7233+
71627234
@Test
71637235
fun whenInputScreenEnabledAndSwitchToNewTabThenLaunchInputScreenCommandTriggered() =
71647236
runTest {

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

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,15 @@ class BrowserWebViewClientTest {
10181018
fun whenPageFinishesBeforeStartingThenPixelIsNotFired() {
10191019
val mockWebView = getImmediatelyInvokedMockWebView()
10201020
testee.onPageFinished(mockWebView, EXAMPLE_URL)
1021-
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any(), any())
1021+
verify(pageLoadedHandler, never()).onPageLoaded(
1022+
any(),
1023+
any(),
1024+
any(),
1025+
any(),
1026+
any(),
1027+
any(),
1028+
any(),
1029+
)
10221030
}
10231031

10241032
@Test
@@ -1032,7 +1040,15 @@ class BrowserWebViewClientTest {
10321040
testee.onPageFinished(mockWebView, EXAMPLE_URL)
10331041
val startArgumentCaptor = argumentCaptor<Long>()
10341042
val endArgumentCaptor = argumentCaptor<Long>()
1035-
verify(pageLoadedHandler).onPageLoaded(any(), eq(null), startArgumentCaptor.capture(), endArgumentCaptor.capture(), any())
1043+
verify(pageLoadedHandler).onPageLoaded(
1044+
any(),
1045+
eq(null),
1046+
startArgumentCaptor.capture(),
1047+
endArgumentCaptor.capture(),
1048+
any(),
1049+
any(),
1050+
any(),
1051+
)
10361052
assertEquals(0L, startArgumentCaptor.firstValue)
10371053
assertEquals(10L, endArgumentCaptor.firstValue)
10381054
}
@@ -1045,7 +1061,7 @@ class BrowserWebViewClientTest {
10451061
whenever(mockWebView.settings).thenReturn(mock())
10461062
testee.onPageStarted(mockWebView, "about:blank", null)
10471063
testee.onPageFinished(mockWebView, "about:blank")
1048-
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any(), any())
1064+
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any(), any(), any(), any())
10491065
}
10501066

10511067
@Test
@@ -1054,7 +1070,7 @@ class BrowserWebViewClientTest {
10541070
whenever(mockWebView.settings).thenReturn(mock())
10551071
testee.onPageStarted(mockWebView, EXAMPLE_URL, null)
10561072
testee.onPageFinished(mockWebView, EXAMPLE_URL)
1057-
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any(), any())
1073+
verify(pageLoadedHandler, never()).onPageLoaded(any(), any(), any(), any(), any(), any(), any())
10581074
}
10591075

10601076
@Test
@@ -1087,7 +1103,15 @@ class BrowserWebViewClientTest {
10871103

10881104
val startArgumentCaptor = argumentCaptor<Long>()
10891105
val endArgumentCaptor = argumentCaptor<Long>()
1090-
verify(pageLoadedHandler).onPageLoaded(any(), eq(null), startArgumentCaptor.capture(), endArgumentCaptor.capture(), any())
1106+
verify(pageLoadedHandler).onPageLoaded(
1107+
any(),
1108+
eq(null),
1109+
startArgumentCaptor.capture(),
1110+
endArgumentCaptor.capture(),
1111+
any(),
1112+
any(),
1113+
any(),
1114+
)
10911115
assertEquals(0L, startArgumentCaptor.firstValue)
10921116
assertEquals(10L, endArgumentCaptor.firstValue)
10931117
}
@@ -1109,7 +1133,15 @@ class BrowserWebViewClientTest {
11091133
testee.onPageFinished(mockWebView, EXAMPLE_URL)
11101134
val startArgumentCaptor = argumentCaptor<Long>()
11111135
val endArgumentCaptor = argumentCaptor<Long>()
1112-
verify(pageLoadedHandler).onPageLoaded(any(), eq(null), startArgumentCaptor.capture(), endArgumentCaptor.capture(), any())
1136+
verify(pageLoadedHandler).onPageLoaded(
1137+
any(),
1138+
eq(null),
1139+
startArgumentCaptor.capture(),
1140+
endArgumentCaptor.capture(),
1141+
any(),
1142+
any(),
1143+
any(),
1144+
)
11131145
assertEquals(5L, startArgumentCaptor.firstValue)
11141146
assertEquals(10L, endArgumentCaptor.firstValue)
11151147
}

0 commit comments

Comments
 (0)