Merge remote-tracking branch 'origin/fenix/121.0' into iceraven

pull/745/head
akliuxingyuan 6 months ago
commit 91382bb269

@ -58,6 +58,9 @@ juno-onboarding:
cards:
type: json
description: Collection of user facing onboarding cards.
conditions:
type: json
description: "A collection of out the box conditional expressions to be used in determining whether a card should show or not. Each entry maps to a valid JEXL expression.\n"
messaging:
description: "The in-app messaging system.\n"
hasExposure: true

@ -248,6 +248,15 @@ android {
}
bundle {
// Profiler issues require us to temporarily package native code compressed to
// match the previous APK packaging.
// https://bugzilla.mozilla.org/show_bug.cgi?id=1865634
packagingOptions {
jniLibs {
it.useLegacyPackaging = true
}
}
language {
// Because we have runtime language selection we will keep all strings and languages
// in the base APKs.
@ -547,7 +556,7 @@ dependencies {
implementation ComponentsDependencies.androidx_coordinatorlayout
implementation FenixDependencies.google_accompanist_drawablepainter
implementation ComponentsDependencies.thirdparty_sentry_latest
implementation ComponentsDependencies.thirdparty_sentry
implementation project(':compose-awesomebar')
implementation project(':compose-cfr')

@ -7489,6 +7489,25 @@ first_session:
- Performance
- Attribution
play_store_attribution:
install_referrer_response:
type: text
send_in_pings:
- first-session
description: |
The full install referrer response.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1862737
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/4343
data_sensitivity:
# - technical
- web_activity # This is a workaround so we can use Text type for technical data.
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Attribution
source:
type: string
send_in_pings:
@ -7611,6 +7630,80 @@ play_store_attribution:
tags:
- Attribution
- Performance
meta_attribution:
app:
type: string
send_in_pings:
- first-session
description: |
The mobile application ID in Meta's attribution.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1860133
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/4171
data_sensitivity:
- technical
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Attribution
t:
type: string
send_in_pings:
- first-session
description: |
Value tracking user interaction with Meta attribution.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1860133
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/4171
data_sensitivity:
- technical
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Attribution
data:
type: text
send_in_pings:
- first-session
description: |
The Meta attribution data in encrypted format.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1860133
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/4171
data_sensitivity:
# - technical
- web_activity # This is a workaround so we can use Text type for technical data.
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Attribution
nonce:
type: string
send_in_pings:
- first-session
description: |
Nonce used to decrypt the encrypted Meta attribution data.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1860133
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/4171
data_sensitivity:
- technical
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Attribution
browser.search:
with_ads:
type: labeled_counter
@ -8296,27 +8389,10 @@ autoplay:
- SitePermissions
cookie_banners:
visited_setting:
type: event
description: A user visited the cookie banner handling screen
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1796146
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/27561
- https://github.com/mozilla-mobile/firefox-android/pull/2597
- https://github.com/mozilla-mobile/firefox-android/pull/4039
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Privacy&Security
setting_changed:
setting_changed_pmb:
type: event
description: |
A user changed their setting.
A user changed their setting in private mode.
extra_keys:
cookie_banner_setting:
description: |
@ -8392,35 +8468,23 @@ cookie_banners:
metadata:
tags:
- Privacy&Security
visited_re_engagement_dialog:
type: event
description: An user visited the cookie banner re-engagement dialog
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1797593
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/28405#issuecomment-1372489596
- https://github.com/mozilla-mobile/firefox-android/pull/2597
- https://github.com/mozilla-mobile/firefox-android/pull/4039
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Privacy&Security
opt_out_re_engagement_dialog:
type: event
report_site_domain:
type: url
description: |
An user opt out the cookie banner re-engagement
dialog by clicking the X button
A user can report a site domain(Ex. for https://edition.cnn.com/
site domain will be cnn.com) when the cookie banner reducer is not
working from the cookie banner details panel.
lifetime: ping
send_in_pings:
- cookie-banner-report-site
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1797593
- https://bugzilla.mozilla.org/show_bug.cgi?id=1805450
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/28405#issuecomment-1372489596
- https://github.com/mozilla-mobile/firefox-android/pull/2597
- https://github.com/mozilla-mobile/firefox-android/pull/1298#pullrequestreview-1350344223
- https://github.com/mozilla-mobile/firefox-android/pull/3319
- https://github.com/mozilla-mobile/firefox-android/pull/4039
data_sensitivity:
- technical
- interaction
notification_emails:
- android-probes@mozilla.com
@ -8428,16 +8492,16 @@ cookie_banners:
metadata:
tags:
- Privacy&Security
not_now_re_engagement_dialog:
report_site_cancel_button:
type: event
description: |
An user clicked the not now button on
the cookie banner re-engagement dialog
The user has pressed the report site domain cancel button
from the cookie banner reducer details panel.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1797593
- https://bugzilla.mozilla.org/show_bug.cgi?id=1805450
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/28405#issuecomment-1372489596
- https://github.com/mozilla-mobile/firefox-android/pull/2597
- https://github.com/mozilla-mobile/firefox-android/pull/1298#pullrequestreview-1350344223
- https://github.com/mozilla-mobile/firefox-android/pull/3319
- https://github.com/mozilla-mobile/firefox-android/pull/4039
data_sensitivity:
- interaction
@ -8447,34 +8511,11 @@ cookie_banners:
metadata:
tags:
- Privacy&Security
allow_re_engagement_dialog:
report_domain_site_button:
type: event
description: |
An user clicked the dismiss banner button
on the cookie banner re-engagement dialog
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1797593
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/28405#issuecomment-1372489596
- https://github.com/mozilla-mobile/firefox-android/pull/2597
- https://github.com/mozilla-mobile/firefox-android/pull/4039
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Privacy&Security
report_site_domain:
type: url
description: |
A user can report a site domain(Ex. for https://edition.cnn.com/
site domain will be cnn.com) when the cookie banner reducer is not
working from the cookie banner details panel.
lifetime: ping
send_in_pings:
- cookie-banner-report-site
The user has pressed the report site domain button
from the cookie banner reducer details panel.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1805450
data_reviews:
@ -8482,7 +8523,6 @@ cookie_banners:
- https://github.com/mozilla-mobile/firefox-android/pull/3319
- https://github.com/mozilla-mobile/firefox-android/pull/4039
data_sensitivity:
- technical
- interaction
notification_emails:
- android-probes@mozilla.com
@ -8490,17 +8530,13 @@ cookie_banners:
metadata:
tags:
- Privacy&Security
report_site_cancel_button:
cfr_shown:
type: event
description: |
The user has pressed the report site domain cancel button
from the cookie banner reducer details panel.
description: The cookie banner cfr has been shown
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1805450
- https://bugzilla.mozilla.org/show_bug.cgi?id=1859393
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/1298#pullrequestreview-1350344223
- https://github.com/mozilla-mobile/firefox-android/pull/3319
- https://github.com/mozilla-mobile/firefox-android/pull/4039
- https://bugzilla.mozilla.org/show_bug.cgi?id=1859393#c2
data_sensitivity:
- interaction
notification_emails:
@ -8509,17 +8545,15 @@ cookie_banners:
metadata:
tags:
- Privacy&Security
report_domain_site_button:
cfr_dismissal:
type: event
description: |
The user has pressed the report site domain button
from the cookie banner reducer details panel.
The cookie banners CFR was dismissed by the user by interacting
with the outside of the popup
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1805450
- https://bugzilla.mozilla.org/show_bug.cgi?id=1859393
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/1298#pullrequestreview-1350344223
- https://github.com/mozilla-mobile/firefox-android/pull/3319
- https://github.com/mozilla-mobile/firefox-android/pull/4039
- https://bugzilla.mozilla.org/show_bug.cgi?id=1859393#c2
data_sensitivity:
- interaction
notification_emails:
@ -8528,7 +8562,6 @@ cookie_banners:
metadata:
tags:
- Privacy&Security
site_permissions:
prompt_shown:
type: event
@ -10812,6 +10845,126 @@ shopping:
metadata:
tags:
- Shopping
surface_stale_analysis_shown:
type: event
description: |
Records an event when the "New info to check" card is shown.
send_in_pings:
- events
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1862776
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/4379#issuecomment-1794925138
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Shopping
surface_ads_impression:
type: event
description: |
The user viewed an ad in review checker for at least 1.5 seconds.
send_in_pings:
- events
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1865854
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/4604#issuecomment-1827890623
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Shopping
surface_ads_clicked:
type: event
description: |
The user clicked an ad in review checker.
send_in_pings:
- events
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1865854
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/4604#issuecomment-1827890623
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Shopping
surface_ads_setting_toggled:
type: event
description: |
The user toggled the ads display setting.
send_in_pings:
- events
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1865854
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/4604#issuecomment-1827890623
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
extra_keys:
action:
type: string
description: |
Whether the toggle was used to enable or disable ads. Possible values
are `enabled` and `disabled`.
metadata:
tags:
- Shopping
ads_exposure:
type: event
description: |
On a supported product page, the review checker showed analysis,
and the ads exposure pref was enabled, or review checker ads were enabled,
and when we tried to fetch an ad from the ad server, an ad was available.
Does not indicate whether the ad was actually shown.
send_in_pings:
- events
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1866992
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/4622#issuecomment-1829905076
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Shopping
surface_no_ads_available:
type: event
description: |
On a supported product page, the review checker
showed analysis, and review checker ads were enabled,
but when we tried to fetch an ad from the ad server,
no ad was available.
send_in_pings:
- events
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1866992
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/4622#issuecomment-1829905076
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Shopping
shopping.settings:
component_opted_out:
@ -10871,6 +11024,24 @@ shopping.settings:
metadata:
tags:
- Shopping
disabled_ads:
type: boolean
description: |
Indicates if the user has disabled ads.
send_in_pings:
- metrics
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1865854
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/4604#issuecomment-1827890623
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Shopping
fx_suggest:
ping_type:
type: string

@ -234,7 +234,38 @@ features:
"jump-back-in-cfr": true,
}
}
query-parameter-stripping:
description: Features for query parameter stripping.
variables:
sections-enabled:
description: "This property provides a lookup table of whether or not the given section should be enabled."
type: Map<QueryParameterStrippingSection, String>
default:
{
"query-parameter-stripping": "0",
"query-parameter-stripping-pmb": "0",
"query-parameter-stripping-allow-list": "",
"query-parameter-stripping-strip-list": "",
}
defaults:
- channel: developer
value: {
"sections-enabled": {
"query-parameter-stripping": "0",
"query-parameter-stripping-pmb": "0",
"query-parameter-stripping-allow-list": "",
"query-parameter-stripping-strip-list": "",
}
}
- channel: nightly
value: {
"sections-enabled": {
"query-parameter-stripping": "0",
"query-parameter-stripping-pmb": "0",
"query-parameter-stripping-allow-list": "",
"query-parameter-stripping-strip-list": "",
}
}
cookie-banners:
description: Features for cookie banner handling.
variables:
@ -245,8 +276,10 @@ features:
{
"feature-ui": 0,
"feature-setting-value": 0,
"dialog-re-engage-time": 4,
"feature-setting-value-pbm": 0
"feature-setting-value-pbm": 0,
"feature-setting-detect-only": 0,
"feature-setting-global-rules": 0,
"feature-setting-global-rules-sub-frames": 0,
}
defaults:
- channel: developer
@ -254,8 +287,10 @@ features:
"sections-enabled": {
"feature-ui": 1,
"feature-setting-value": 0,
"dialog-re-engage-time": 4,
"feature-setting-value-pbm": 0
"feature-setting-value-pbm": 1,
"feature-setting-detect-only": 0,
"feature-setting-global-rules": 0,
"feature-setting-global-rules-sub-frames": 0,
}
}
- channel: nightly
@ -263,8 +298,21 @@ features:
"sections-enabled": {
"feature-ui": 1,
"feature-setting-value": 0,
"dialog-re-engage-time": 4,
"feature-setting-value-pbm": 0
"feature-setting-value-pbm": 1,
"feature-setting-detect-only": 0,
"feature-setting-global-rules": 0,
"feature-setting-global-rules-sub-frames": 0,
}
}
- channel: beta
value: {
"sections-enabled": {
"feature-ui": 1,
"feature-setting-value": 0,
"feature-setting-value-pbm": 1,
"feature-setting-detect-only": 0,
"feature-setting-global-rules": 0,
"feature-setting-global-rules-sub-frames": 0,
}
}
unified-search:
@ -359,10 +407,16 @@ features:
description: if true, recommended products feature is enabled to be shown to the user based on their preference.
type: Boolean
default: false
product-recommendations-exposure:
description: if true, we want to record recommended products inventory for opted-in users, even if product recommendations are disabled.
type: Boolean
default: false
defaults:
- channel: developer
value:
enabled: true
product-recommendations: true
product-recommendations-exposure: true
print:
description: A feature for printing from the share or browser menu.
@ -461,13 +515,38 @@ types:
feature-setting-value:
description: An integer either 0 or 1 indicating if cookie banner setting should be enabled or disabled,
0 for setting the value to disabled, 1 for enabling the setting with the value reject_all.
dialog-re-engage-time:
description: An integer indicating the number of hours that needs to happen before
the re-engagement dialog shows again since the last seen, for example if set to 4
that means if the users has seen the dialog, it will see it 4 hours later.
feature-setting-value-pbm:
description: An integer either 0 or 1 indicating if cookie banner setting should be enabled or disabled,
0 for setting the value to disabled, 1 for enabling the setting with the value reject_all.
feature-setting-detect-only:
description: An integer either 0 or 1 indicating if cookie banner detect only mode
should be enabled or disabled. 0 for setting to be disabled, and 1 for enabling the setting.
feature-setting-global-rules:
description: An integer either 0 or 1 indicating if cookie banner global rules
should be enabled or disabled. 0 for setting to be disabled, and 1 for enabling the setting.
feature-setting-global-rules-sub-frames:
description: An integer either 0 or 1 indicating if cookie banner global rules sub-frames
should be enabled or disabled. 0 for setting to be disabled, and 1 for enabling the setting.
QueryParameterStrippingSection:
description: The identifiers for the options for the Query Parameter Stripping feature.
variants:
query-parameter-stripping:
description: An integer either 0 or 1 indicating if query parameter stripping
should be enabled or disabled in normal mode. 0 for setting to be disabled,
and 1 for enabling the setting.
query-parameter-stripping-pmb:
description: An integer either 0 or 1 indicating if query parameter stripping
should be enabled or disabled in private mode. 0 for setting to be disabled,
and 1 for enabling the setting.
query-parameter-stripping-allow-list:
description: An string separated by commas indicating the sites where should
from query stripping should be exempted.
query-parameter-stripping-strip-list:
description: An string separated by commas indicating the list of query params
to be stripped from URIs. This list will be merged with records
coming from RemoteSettings.
OnboardingPanel:
description: The types of onboarding panels in the onboarding page
variants:

@ -5,6 +5,16 @@ features:
description: A feature that shows juno onboarding flow.
variables:
conditions:
description: >
A collection of out the box conditional expressions to be
used in determining whether a card should show or not.
Each entry maps to a valid JEXL expression.
type: Map<String, String>
default: {
ALWAYS: "true",
NEVER: "false"
}
cards:
description: Collection of user facing onboarding cards.
type: Map<String, OnboardingCardData>
@ -98,6 +108,20 @@ objects:
description: The text to display on the secondary button.
# This should never be defaulted.
default: ""
prerequisites:
type: List<String>
description: >
A list of strings corresponding to targeting expressions.
The card will be shown if all expressions are `true` and if
no expressions in the `disqualifiers` table are true, or
if the `disqualifiers` table is empty.
default: [ ALWAYS ]
disqualifiers:
type: List<String>
description: >
A list of strings corresponding to targeting expressions.
The card will not be shown if any expression is `true`.
default: [ NEVER ]
enums:

@ -5,8 +5,8 @@
package org.mozilla.fenix.components
import android.content.Context
import mozilla.components.service.fxa.ServerConfig
import mozilla.components.service.fxa.ServerConfig.Server
import mozilla.appservices.fxaclient.FxaConfig
import mozilla.appservices.fxaclient.FxaServer
/**
* Utility to configure Firefox Account stage servers.
@ -17,7 +17,7 @@ object FxaServer {
private const val REDIRECT_URL = "urn:ietf:wg:oauth:2.0:oob:oauth-redirect-webchannel"
@Suppress("UNUSED_PARAMETER")
fun config(context: Context): ServerConfig {
return ServerConfig(Server.STAGE, CLIENT_ID, REDIRECT_URL)
fun config(context: Context): FxaConfig {
return FxaConfig(FxaServer.Stage, CLIENT_ID, REDIRECT_URL)
}
}

@ -33,7 +33,8 @@ class GenericExperimentIntegrationTest {
TestHelper.appContext.settings().showSecretDebugMenuThisSession = false
}
private fun disableStudiesViaStudiesToggle() {
@Test
fun disableStudiesViaStudiesToggle() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {

@ -1,9 +1,14 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"
[packages]
pydantic = "*"
pytest = "*"
pytest-html = "*"
pytest-metadata = "*"

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "53501c7e751ae79697bf8c7289b6095f49fed97242fe186fea42989e800c39d5"
"sha256": "6dae5ac51aa7817578a25597da1ef783475050538443ba344c88a78969e68fd9"
},
"pipfile-spec": 6,
"requires": {
@ -16,6 +16,14 @@
]
},
"default": {
"annotated-types": {
"hashes": [
"sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43",
"sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"
],
"markers": "python_version >= '3.8'",
"version": "==0.6.0"
},
"certifi": {
"hashes": [
"sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082",
@ -226,23 +234,144 @@
"markers": "python_version >= '3.8'",
"version": "==1.3.0"
},
"pydantic": {
"hashes": [
"sha256:94f336138093a5d7f426aac732dcfe7ab4eb4da243c88f891d65deb4a2556ee7",
"sha256:bc3ddf669d234f4220e6e1c4d96b061abe0998185a8d7855c0126782b7abc8c1"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==2.4.2"
},
"pydantic-core": {
"hashes": [
"sha256:042462d8d6ba707fd3ce9649e7bf268633a41018d6a998fb5fbacb7e928a183e",
"sha256:0523aeb76e03f753b58be33b26540880bac5aa54422e4462404c432230543f33",
"sha256:05560ab976012bf40f25d5225a58bfa649bb897b87192a36c6fef1ab132540d7",
"sha256:0675ba5d22de54d07bccde38997e780044dcfa9a71aac9fd7d4d7a1d2e3e65f7",
"sha256:073d4a470b195d2b2245d0343569aac7e979d3a0dcce6c7d2af6d8a920ad0bea",
"sha256:07ec6d7d929ae9c68f716195ce15e745b3e8fa122fc67698ac6498d802ed0fa4",
"sha256:0880e239827b4b5b3e2ce05e6b766a7414e5f5aedc4523be6b68cfbc7f61c5d0",
"sha256:0c27f38dc4fbf07b358b2bc90edf35e82d1703e22ff2efa4af4ad5de1b3833e7",
"sha256:0d8a8adef23d86d8eceed3e32e9cca8879c7481c183f84ed1a8edc7df073af94",
"sha256:0e2a35baa428181cb2270a15864ec6286822d3576f2ed0f4cd7f0c1708472aff",
"sha256:0f8682dbdd2f67f8e1edddcbffcc29f60a6182b4901c367fc8c1c40d30bb0a82",
"sha256:0fa467fd300a6f046bdb248d40cd015b21b7576c168a6bb20aa22e595c8ffcdd",
"sha256:128552af70a64660f21cb0eb4876cbdadf1a1f9d5de820fed6421fa8de07c893",
"sha256:1396e81b83516b9d5c9e26a924fa69164156c148c717131f54f586485ac3c15e",
"sha256:149b8a07712f45b332faee1a2258d8ef1fb4a36f88c0c17cb687f205c5dc6e7d",
"sha256:14ac492c686defc8e6133e3a2d9eaf5261b3df26b8ae97450c1647286750b901",
"sha256:14cfbb00959259e15d684505263d5a21732b31248a5dd4941f73a3be233865b9",
"sha256:14e09ff0b8fe6e46b93d36a878f6e4a3a98ba5303c76bb8e716f4878a3bee92c",
"sha256:154ea7c52e32dce13065dbb20a4a6f0cc012b4f667ac90d648d36b12007fa9f7",
"sha256:15d6bca84ffc966cc9976b09a18cf9543ed4d4ecbd97e7086f9ce9327ea48891",
"sha256:1d40f55222b233e98e3921df7811c27567f0e1a4411b93d4c5c0f4ce131bc42f",
"sha256:25bd966103890ccfa028841a8f30cebcf5875eeac8c4bde4fe221364c92f0c9a",
"sha256:2cf5bb4dd67f20f3bbc1209ef572a259027c49e5ff694fa56bed62959b41e1f9",
"sha256:2e0e2959ef5d5b8dc9ef21e1a305a21a36e254e6a34432d00c72a92fdc5ecda5",
"sha256:320f14bd4542a04ab23747ff2c8a778bde727158b606e2661349557f0770711e",
"sha256:3625578b6010c65964d177626fde80cf60d7f2e297d56b925cb5cdeda6e9925a",
"sha256:39215d809470f4c8d1881758575b2abfb80174a9e8daf8f33b1d4379357e417c",
"sha256:3f0ac9fb8608dbc6eaf17956bf623c9119b4db7dbb511650910a82e261e6600f",
"sha256:417243bf599ba1f1fef2bb8c543ceb918676954734e2dcb82bf162ae9d7bd514",
"sha256:420a692b547736a8d8703c39ea935ab5d8f0d2573f8f123b0a294e49a73f214b",
"sha256:443fed67d33aa85357464f297e3d26e570267d1af6fef1c21ca50921d2976302",
"sha256:48525933fea744a3e7464c19bfede85df4aba79ce90c60b94d8b6e1eddd67096",
"sha256:485a91abe3a07c3a8d1e082ba29254eea3e2bb13cbbd4351ea4e5a21912cc9b0",
"sha256:4a5be350f922430997f240d25f8219f93b0c81e15f7b30b868b2fddfc2d05f27",
"sha256:4d966c47f9dd73c2d32a809d2be529112d509321c5310ebf54076812e6ecd884",
"sha256:524ff0ca3baea164d6d93a32c58ac79eca9f6cf713586fdc0adb66a8cdeab96a",
"sha256:53df009d1e1ba40f696f8995683e067e3967101d4bb4ea6f667931b7d4a01357",
"sha256:5994985da903d0b8a08e4935c46ed8daf5be1cf217489e673910951dc533d430",
"sha256:5cabb9710f09d5d2e9e2748c3e3e20d991a4c5f96ed8f1132518f54ab2967221",
"sha256:5fdb39f67c779b183b0c853cd6b45f7db84b84e0571b3ef1c89cdb1dfc367325",
"sha256:600d04a7b342363058b9190d4e929a8e2e715c5682a70cc37d5ded1e0dd370b4",
"sha256:631cb7415225954fdcc2a024119101946793e5923f6c4d73a5914d27eb3d3a05",
"sha256:63974d168b6233b4ed6a0046296803cb13c56637a7b8106564ab575926572a55",
"sha256:64322bfa13e44c6c30c518729ef08fda6026b96d5c0be724b3c4ae4da939f875",
"sha256:655f8f4c8d6a5963c9a0687793da37b9b681d9ad06f29438a3b2326d4e6b7970",
"sha256:6835451b57c1b467b95ffb03a38bb75b52fb4dc2762bb1d9dbed8de31ea7d0fc",
"sha256:6db2eb9654a85ada248afa5a6db5ff1cf0f7b16043a6b070adc4a5be68c716d6",
"sha256:7c4d1894fe112b0864c1fa75dffa045720a194b227bed12f4be7f6045b25209f",
"sha256:7eb037106f5c6b3b0b864ad226b0b7ab58157124161d48e4b30c4a43fef8bc4b",
"sha256:8282bab177a9a3081fd3d0a0175a07a1e2bfb7fcbbd949519ea0980f8a07144d",
"sha256:82f55187a5bebae7d81d35b1e9aaea5e169d44819789837cdd4720d768c55d15",
"sha256:8572cadbf4cfa95fb4187775b5ade2eaa93511f07947b38f4cd67cf10783b118",
"sha256:8cdbbd92154db2fec4ec973d45c565e767ddc20aa6dbaf50142676484cbff8ee",
"sha256:8f6e6aed5818c264412ac0598b581a002a9f050cb2637a84979859e70197aa9e",
"sha256:92f675fefa977625105708492850bcbc1182bfc3e997f8eecb866d1927c98ae6",
"sha256:962ed72424bf1f72334e2f1e61b68f16c0e596f024ca7ac5daf229f7c26e4208",
"sha256:9badf8d45171d92387410b04639d73811b785b5161ecadabf056ea14d62d4ede",
"sha256:9c120c9ce3b163b985a3b966bb701114beb1da4b0468b9b236fc754783d85aa3",
"sha256:9f6f3e2598604956480f6c8aa24a3384dbf6509fe995d97f6ca6103bb8c2534e",
"sha256:a1254357f7e4c82e77c348dabf2d55f1d14d19d91ff025004775e70a6ef40ada",
"sha256:a1392e0638af203cee360495fd2cfdd6054711f2db5175b6e9c3c461b76f5175",
"sha256:a1c311fd06ab3b10805abb72109f01a134019739bd3286b8ae1bc2fc4e50c07a",
"sha256:a5cb87bdc2e5f620693148b5f8f842d293cae46c5f15a1b1bf7ceeed324a740c",
"sha256:a7a7902bf75779bc12ccfc508bfb7a4c47063f748ea3de87135d433a4cca7a2f",
"sha256:aad7bd686363d1ce4ee930ad39f14e1673248373f4a9d74d2b9554f06199fb58",
"sha256:aafdb89fdeb5fe165043896817eccd6434aee124d5ee9b354f92cd574ba5e78f",
"sha256:ae8a8843b11dc0b03b57b52793e391f0122e740de3df1474814c700d2622950a",
"sha256:b00bc4619f60c853556b35f83731bd817f989cba3e97dc792bb8c97941b8053a",
"sha256:b1f22a9ab44de5f082216270552aa54259db20189e68fc12484873d926426921",
"sha256:b3c01c2fb081fced3bbb3da78510693dc7121bb893a1f0f5f4b48013201f362e",
"sha256:b3dcd587b69bbf54fc04ca157c2323b8911033e827fffaecf0cafa5a892a0904",
"sha256:b4a6db486ac8e99ae696e09efc8b2b9fea67b63c8f88ba7a1a16c24a057a0776",
"sha256:bec7dd208a4182e99c5b6c501ce0b1f49de2802448d4056091f8e630b28e9a52",
"sha256:c0877239307b7e69d025b73774e88e86ce82f6ba6adf98f41069d5b0b78bd1bf",
"sha256:caa48fc31fc7243e50188197b5f0c4228956f97b954f76da157aae7f67269ae8",
"sha256:cfe1090245c078720d250d19cb05d67e21a9cd7c257698ef139bc41cf6c27b4f",
"sha256:d43002441932f9a9ea5d6f9efaa2e21458221a3a4b417a14027a1d530201ef1b",
"sha256:d64728ee14e667ba27c66314b7d880b8eeb050e58ffc5fec3b7a109f8cddbd63",
"sha256:d6495008733c7521a89422d7a68efa0a0122c99a5861f06020ef5b1f51f9ba7c",
"sha256:d8f1ebca515a03e5654f88411420fea6380fc841d1bea08effb28184e3d4899f",
"sha256:d99277877daf2efe074eae6338453a4ed54a2d93fb4678ddfe1209a0c93a2468",
"sha256:da01bec0a26befab4898ed83b362993c844b9a607a86add78604186297eb047e",
"sha256:db9a28c063c7c00844ae42a80203eb6d2d6bbb97070cfa00194dff40e6f545ab",
"sha256:dda81e5ec82485155a19d9624cfcca9be88a405e2857354e5b089c2a982144b2",
"sha256:e357571bb0efd65fd55f18db0a2fb0ed89d0bb1d41d906b138f088933ae618bb",
"sha256:e544246b859f17373bed915182ab841b80849ed9cf23f1f07b73b7c58baee5fb",
"sha256:e562617a45b5a9da5be4abe72b971d4f00bf8555eb29bb91ec2ef2be348cd132",
"sha256:e570ffeb2170e116a5b17e83f19911020ac79d19c96f320cbfa1fa96b470185b",
"sha256:e6f31a17acede6a8cd1ae2d123ce04d8cca74056c9d456075f4f6f85de055607",
"sha256:e9121b4009339b0f751955baf4543a0bfd6bc3f8188f8056b1a25a2d45099934",
"sha256:ebedb45b9feb7258fac0a268a3f6bec0a2ea4d9558f3d6f813f02ff3a6dc6698",
"sha256:ecaac27da855b8d73f92123e5f03612b04c5632fd0a476e469dfc47cd37d6b2e",
"sha256:ecdbde46235f3d560b18be0cb706c8e8ad1b965e5c13bbba7450c86064e96561",
"sha256:ed550ed05540c03f0e69e6d74ad58d026de61b9eaebebbaaf8873e585cbb18de",
"sha256:eeb3d3d6b399ffe55f9a04e09e635554012f1980696d6b0aca3e6cf42a17a03b",
"sha256:ef337945bbd76cce390d1b2496ccf9f90b1c1242a3a7bc242ca4a9fc5993427a",
"sha256:f1365e032a477c1430cfe0cf2856679529a2331426f8081172c4a74186f1d595",
"sha256:f23b55eb5464468f9e0e9a9935ce3ed2a870608d5f534025cd5536bca25b1402",
"sha256:f2e9072d71c1f6cfc79a36d4484c82823c560e6f5599c43c1ca6b5cdbd54f881",
"sha256:f323306d0556351735b54acbf82904fe30a27b6a7147153cbe6e19aaaa2aa429",
"sha256:f36a3489d9e28fe4b67be9992a23029c3cec0babc3bd9afb39f49844a8c721c5",
"sha256:f64f82cc3443149292b32387086d02a6c7fb39b8781563e0ca7b8d7d9cf72bd7",
"sha256:f6defd966ca3b187ec6c366604e9296f585021d922e666b99c47e78738b5666c",
"sha256:f7c2b8eb9fc872e68b46eeaf835e86bccc3a58ba57d0eedc109cbb14177be531",
"sha256:fa7db7558607afeccb33c0e4bf1c9a9a835e26599e76af6fe2fcea45904083a6",
"sha256:fcb83175cc4936a5425dde3356f079ae03c0802bbdf8ff82c035f8a54b333521"
],
"markers": "python_version >= '3.7'",
"version": "==2.10.1"
},
"pytest": {
"hashes": [
"sha256:2f2301e797521b23e4d2585a0a3d7b5e50fdddaaf7e7d6773ea26ddb17c213ab",
"sha256:460c9a59b14e27c602eb5ece2e47bec99dc5fc5f6513cf924a7d03a578991b1f"
"sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002",
"sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==7.4.1"
"version": "==7.4.2"
},
"pytest-html": {
"hashes": [
"sha256:3b473cc278272f8b5a34cd3bf10f88ac5fcb17cb5af22f9323514af00c310e64",
"sha256:79c4677ed6196417bf290d8b81f706342ae49f726f623728efa3f7dfff09f8eb"
"sha256:88682b9e8e51392472546a70a2139b27d6bc1834a4afd3e41da33c9d9f91e4a4",
"sha256:907c3e68462df129d3ee96dee58bd63f70216b06421836b22fd3fd57ef314acb"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==4.0.0"
"version": "==4.0.2"
},
"pytest-metadata": {
"hashes": [
@ -328,12 +457,19 @@
"markers": "python_version >= '3.7'",
"version": "==2.31.0"
},
"typing-extensions": {
"hashes": [
"sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0",
"sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"
],
"markers": "python_version >= '3.8'",
"version": "==4.8.0"
},
"urllib3": {
"hashes": [
"sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84",
"sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==2.0.7"
}
@ -341,32 +477,28 @@
"develop": {
"black": {
"hashes": [
"sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3",
"sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb",
"sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087",
"sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320",
"sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6",
"sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3",
"sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc",
"sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f",
"sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587",
"sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91",
"sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a",
"sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad",
"sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926",
"sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9",
"sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be",
"sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd",
"sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96",
"sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491",
"sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2",
"sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a",
"sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f",
"sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"
"sha256:0e232f24a337fed7a82c1185ae46c56c4a6167fb0fe37411b43e876892c76699",
"sha256:30b78ac9b54cf87bcb9910ee3d499d2bc893afd52495066c49d9ee6b21eee06e",
"sha256:31946ec6f9c54ed7ba431c38bc81d758970dd734b96b8e8c2b17a367d7908171",
"sha256:31b9f87b277a68d0e99d2905edae08807c007973eaa609da5f0c62def6b7c0bd",
"sha256:47c4510f70ec2e8f9135ba490811c071419c115e46f143e4dce2ac45afdcf4c9",
"sha256:481167c60cd3e6b1cb8ef2aac0f76165843a374346aeeaa9d86765fe0dd0318b",
"sha256:6901631b937acbee93c75537e74f69463adaf34379a04eef32425b88aca88a23",
"sha256:76baba9281e5e5b230c9b7f83a96daf67a95e919c2dfc240d9e6295eab7b9204",
"sha256:7fb5fc36bb65160df21498d5a3dd330af8b6401be3f25af60c6ebfe23753f747",
"sha256:960c21555be135c4b37b7018d63d6248bdae8514e5c55b71e994ad37407f45b8",
"sha256:a3c2ddb35f71976a4cfeca558848c2f2f89abc86b06e8dd89b5a65c1e6c0f22a",
"sha256:c870bee76ad5f7a5ea7bd01dc646028d05568d33b0b09b7ecfc8ec0da3f3f39c",
"sha256:d3d9129ce05b0829730323bdcb00f928a448a124af5acf90aa94d9aba6969604",
"sha256:db451a3363b1e765c172c3fd86213a4ce63fb8524c938ebd82919bf2a6e28c6a",
"sha256:e223b731a0e025f8ef427dd79d8cd69c167da807f5710add30cdf131f13dd62e",
"sha256:f20ff03f3fdd2fd4460b4f631663813e57dc277e37fb216463f3b907aa5a9bdd",
"sha256:f74892b4b836e5162aa0452393112a574dac85e13902c57dfbaaf388e4eda37c",
"sha256:f8dc7d50d94063cdfd13c82368afd8588bac4ce360e4224ac399e769d6704e98"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==23.7.0"
"version": "==23.10.0"
},
"click": {
"hashes": [

@ -1,3 +1,7 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import json
import logging
import os
@ -9,6 +13,7 @@ import pytest
import requests
from experimentintegration.gradlewbuild import GradlewBuild
from experimentintegration.models.models import TelemetryModel
KLAATU_SERVER_URL = "http://localhost:1378"
KLAATU_LOCAL_SERVER_URL = "http://localhost:1378"
@ -25,7 +30,6 @@ def pytest_addoption(parser):
)
@pytest.fixture(name="load_branches")
def fixture_load_branches(experiment_url):
branches = []
@ -68,7 +72,7 @@ def fixture_experiment_data(experiment_url):
item["style"] = "URGENT"
for count, trigger in enumerate(item["trigger"]):
if "USER_EN_SPEAKER" not in trigger:
del(item["trigger"][count])
del item["trigger"][count]
return [data]
@ -152,14 +156,55 @@ def fixture_send_test_results():
with open(f"{here.resolve()}/results/index.html", "rb") as f:
files = {"file": f}
try:
requests.post(f"{KLAATU_SERVER_URL}/test_results", files=files)
requests.post(f"{KLAATU_SERVER_URL}/test_results", files=files)
except requests.exceptions.ConnectionError:
pass
@pytest.fixture(name="check_ping_for_experiment")
def fixture_check_ping_for_experiment(experiment_slug, variables):
def _check_ping_for_experiment(
branch=None, experiment=experiment_slug, reason=None
):
model = TelemetryModel(branch=branch, experiment=experiment)
timeout = time.time() + 60 * 5
while time.time() < timeout:
data = requests.get(f"{variables['urls']['telemetry_server']}/pings").json()
events = []
for item in data:
event_items = item.get("events")
if event_items:
for event in event_items:
if (
"category" in event
and "nimbus_events" in event["category"]
and "extra" in event
and "branch" in event["extra"]
):
events.append(event)
for event in events:
event_name = event.get("name")
if (reason == "enrollment" and event_name == "enrollment") or (
reason == "unenrollment"
and event_name in ["unenrollment", "disqualification"]
):
telemetry_model = TelemetryModel(
branch=event["extra"]["branch"],
experiment=event["extra"]["experiment"],
)
if model == telemetry_model:
return True
time.sleep(5)
return False
return _check_ping_for_experiment
@pytest.fixture(name="setup_experiment")
def fixture_setup_experiment(experiment_slug, json_data, gradlewbuild_log):
def fixture_setup_experiment(experiment_slug, json_data, gradlewbuild_log, variables):
def _(branch):
requests.delete(f"{variables['urls']['telemetry_server']}/pings")
logging.info(f"Testing experiment {experiment_slug}, BRANCH: {branch[0]}")
command = f"nimbus-cli --app fenix --channel developer enroll {experiment_slug} --branch {branch[0]} --file {json_data} --reset-app"
logging.info(f"Running command {command}")

@ -0,0 +1,82 @@
from pathlib import Path
import subprocess
import yaml
def search_for_smoke_tests(tests_name):
"""Searches for smoke tests within the requested test module."""
path = Path("../ui")
files = sorted([x for x in path.iterdir() if x.is_file()])
locations = []
file_name = None
test_names = []
for name in files:
if tests_name in name.name:
file_name = name
break
with open(file_name, "r") as file:
code = file.read().split(" ")
code = [item for item in code if item != ""]
for count, item in enumerate(code):
if "class" in item or "@SmokeTest" in item:
locations.append(count)
for location in locations:
if len(test_names) == 0:
class_name = code[location + 1]
test_names.append(class_name)
else:
test_names.append(f"{class_name}#{code[location+3].strip('()')}")
return test_names
def create_test_file():
"""Create the python file to hold the tests."""
path = Path("tests/")
filename = "test_smoke_scenarios.py"
final_path = path / filename
if final_path.exists():
print("File Exists, you need to delete it to create a new one.")
return
# file exists
subprocess.run([f"touch {final_path}"], encoding="utf8", shell=True)
assert final_path.exists()
with open(final_path, "w") as file:
file.write("import pytest\n\n")
def generate_smoke_tests(tests_names=None):
"""Generate pytest code for the requested tests."""
pytest_file = "tests/test_smoke_scenarios.py"
tests = []
for test in tests_names[1:]:
test_name = test.replace("#", "_").lower()
tests.append(
f"""
@pytest.mark.smoke_test
def test_smoke_{test_name}(setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment):
setup_experiment(load_branches)
gradlewbuild.test("{test}", smoke=True)
assert check_ping_for_experiment
"""
)
with open(pytest_file, "a") as file:
for item in tests:
file.writelines(f"{item}")
if __name__ == "__main__":
test_modules = None
create_test_file()
with open("variables.yaml", "r") as file:
test_modules = yaml.safe_load(file)
for item in test_modules.get("smoke_tests"):
tests = search_for_smoke_tests(item)
generate_smoke_tests(tests)

@ -16,12 +16,17 @@ class GradlewBuild(object):
def __init__(self, log):
self.log = log
def test(self, identifier):
def test(self, identifier, smoke=None):
# self.adbrun.launch()
# Change path accordingly to go to root folder to run gradlew
os.chdir("../../../../../../../..")
cmd = f"adb shell am instrument -w -e class org.mozilla.fenix.experimentintegration.{identifier} org.mozilla.fenix.debug.test/androidx.test.runner.AndroidJUnitRunner"
test_type = "ui" if smoke else "experimentintegration"
cmd = f"adb shell am instrument -w -e class org.mozilla.fenix.{test_type}.{identifier} org.mozilla.fenix.debug.test/androidx.test.runner.AndroidJUnitRunner"
# if smoke:
# cmd = f"adb shell am instrument -w -e class org.mozilla.fenix.ui.{identifier} org.mozilla.fenix.debug.test/androidx.test.runner.AndroidJUnitRunner"
# else:
# cmd = f"adb shell am instrument -w -e class org.mozilla.fenix.experimentintegration.{identifier} org.mozilla.fenix.debug.test/androidx.test.runner.AndroidJUnitRunner"
self.logger.info("Running cmd: {}".format(cmd))

@ -0,0 +1,3 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

@ -0,0 +1,14 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""Data class Models"""
from pydantic import BaseModel
class TelemetryModel(BaseModel):
"""Experiment Telemetry model"""
branch: str
experiment: str

@ -1,12 +1,17 @@
import pytest
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True)
def test_experiment_unenrolls_via_studies_toggle(setup_experiment, gradlewbuild, load_branches):
def test_experiment_unenrolls_via_studies_toggle(setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment):
setup_experiment(load_branches)
gradlewbuild.test("GenericExperimentIntegrationTest#disableStudiesViaStudiesToggle")
gradlewbuild.test("GenericExperimentIntegrationTest#testExperimentUnenrolls")
assert check_ping_for_experiment(reason="enrollment", branch=load_branches[0])
gradlewbuild.test("GenericExperimentIntegrationTest#testExperimentUnenrolled")
assert check_ping_for_experiment(reason="unenrollment", branch=load_branches[0])
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True)
def test_experiment_unenrolls_via_secret_menu(setup_experiment, gradlewbuild, load_branches):
def test_experiment_unenrolls_via_secret_menu(setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment):
setup_experiment(load_branches)
gradlewbuild.test("GenericExperimentIntegrationTest#testExperimentUnenrollsViaSecretMenu")
gradlewbuild.test("GenericExperimentIntegrationTest#testExperimentUnenrolledViaSecretMenu")
assert check_ping_for_experiment(reason="enrollment", branch=load_branches[0])
gradlewbuild.test("GenericExperimentIntegrationTest#testExperimentUnenrolled")
assert check_ping_for_experiment(reason="unenrollment", branch=load_branches[0])

@ -1,22 +1,47 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import pytest
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True)
def test_survey_navigates_correctly(setup_experiment, gradlewbuild, load_branches):
def test_survey_navigates_correctly(
setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment
):
setup_experiment(load_branches)
gradlewbuild.test("SurveyExperimentIntegrationTest#checkSurveyNavigatesCorrectly")
assert check_ping_for_experiment(reason="enrollment", branch=load_branches[0])
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True)
def test_survey_no_thanks_navigates_correctly(setup_experiment, gradlewbuild, load_branches):
def test_survey_no_thanks_navigates_correctly(
setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment
):
setup_experiment(load_branches)
gradlewbuild.test("SurveyExperimentIntegrationTest#checkSurveyNoThanksNavigatesCorrectly")
gradlewbuild.test(
"SurveyExperimentIntegrationTest#checkSurveyNoThanksNavigatesCorrectly"
)
assert check_ping_for_experiment(reason="enrollment", branch=load_branches[0])
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True)
def test_homescreen_survey_dismisses_correctly(setup_experiment, gradlewbuild, load_branches):
def test_homescreen_survey_dismisses_correctly(
setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment
):
setup_experiment(load_branches)
gradlewbuild.test("SurveyExperimentIntegrationTest#checkHomescreenSurveyDismissesCorrectly")
gradlewbuild.test(
"SurveyExperimentIntegrationTest#checkHomescreenSurveyDismissesCorrectly"
)
assert check_ping_for_experiment(reason="enrollment", branch=load_branches[0])
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True)
def test_survey_landscape_looks_correct(setup_experiment, gradlewbuild, load_branches):
def test_survey_landscape_looks_correct(
setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment
):
setup_experiment(load_branches)
gradlewbuild.test("SurveyExperimentIntegrationTest#checkSurveyLandscapeLooksCorrect")
gradlewbuild.test(
"SurveyExperimentIntegrationTest#checkSurveyLandscapeLooksCorrect"
)
assert check_ping_for_experiment(reason="enrollment", branch=load_branches[0])

@ -1,3 +1,10 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
urls:
stage_server: "https://stage.experimenter.nonprod.dataops.mozgcp.net"
prod_server: "https://experimenter.services.mozilla.com"
telemetry_server: "http://172.25.58.187:5000"
smoke_tests:
- "AddressAutofillTest"

@ -0,0 +1,362 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@file:Suppress("DEPRECATION")
package org.mozilla.fenix.helpers
import android.Manifest
import android.app.ActivityManager
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.net.Uri
import android.os.Build
import android.os.storage.StorageManager
import android.os.storage.StorageVolume
import android.provider.Settings
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.espresso.Espresso
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.IdlingResource
import androidx.test.espresso.intent.Intents.intended
import androidx.test.espresso.intent.matcher.IntentMatchers.toPackage
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.runner.permission.PermissionRequester
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiObject
import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import junit.framework.AssertionFailedError
import org.junit.Assert
import org.junit.Assert.assertEquals
import org.mozilla.fenix.Config
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
import org.mozilla.fenix.helpers.Constants.PackageName.YOUTUBE_APP
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.ext.waitNotNull
import org.mozilla.fenix.helpers.idlingresource.NetworkConnectionIdlingResource
import org.mozilla.fenix.ui.robots.BrowserRobot
import org.mozilla.gecko.util.ThreadUtils
import java.io.File
import java.util.Locale
object AppAndSystemHelper {
fun getPermissionAllowID(): String {
return when
(Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
true -> "com.android.permissioncontroller"
false -> "com.android.packageinstaller"
}
}
@RequiresApi(Build.VERSION_CODES.R)
fun deleteDownloadedFileOnStorage(fileName: String) {
val storageManager: StorageManager? = TestHelper.appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager?
val storageVolumes = storageManager!!.storageVolumes
val storageVolume: StorageVolume = storageVolumes[0]
val file = File(storageVolume.directory!!.path + "/Download/" + fileName)
try {
if (file.exists()) {
file.delete()
Log.d("TestLog", "File delete try 1")
Assert.assertFalse("The file was not deleted", file.exists())
}
} catch (e: AssertionError) {
file.delete()
Log.d("TestLog", "File delete retried")
Assert.assertFalse("The file was not deleted", file.exists())
}
}
@RequiresApi(Build.VERSION_CODES.R)
fun clearDownloadsFolder() {
val storageManager: StorageManager? = TestHelper.appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager?
val storageVolumes = storageManager!!.storageVolumes
val storageVolume: StorageVolume = storageVolumes[0]
val downloadsFolder = File(storageVolume.directory!!.path + "/Download/")
// Check if the downloads folder exists
if (downloadsFolder.exists() && downloadsFolder.isDirectory) {
Log.i(TAG, "clearDownloadsFolder: Verified that \"DOWNLOADS\" folder exists")
val files = downloadsFolder.listFiles()
// Check if the folder is not empty
if (files != null && files.isNotEmpty()) {
Log.i(TAG, "clearDownloadsFolder: Verified that \"DOWNLOADS\" folder is not empty")
// Delete all files in the folder
for (file in files) {
file.delete()
Log.i(TAG, "clearDownloadsFolder: Deleted $file from \"DOWNLOADS\" folder")
}
}
}
}
fun setNetworkEnabled(enabled: Boolean) {
val networkDisconnectedIdlingResource = NetworkConnectionIdlingResource(false)
val networkConnectedIdlingResource = NetworkConnectionIdlingResource(true)
when (enabled) {
true -> {
mDevice.executeShellCommand("svc data enable")
mDevice.executeShellCommand("svc wifi enable")
// Wait for network connection to be completely enabled
IdlingRegistry.getInstance().register(networkConnectedIdlingResource)
Espresso.onIdle {
IdlingRegistry.getInstance().unregister(networkConnectedIdlingResource)
}
Log.i(TAG, "setNetworkEnabled: Network connection was enabled")
}
false -> {
mDevice.executeShellCommand("svc data disable")
mDevice.executeShellCommand("svc wifi disable")
// Wait for network connection to be completely disabled
IdlingRegistry.getInstance().register(networkDisconnectedIdlingResource)
Espresso.onIdle {
IdlingRegistry.getInstance().unregister(networkDisconnectedIdlingResource)
}
Log.i(TAG, "setNetworkEnabled: Network connection was disabled")
}
}
}
fun isPackageInstalled(packageName: String): Boolean {
return try {
val packageManager = InstrumentationRegistry.getInstrumentation().context.packageManager
packageManager.getApplicationInfo(packageName, 0).enabled
} catch (e: PackageManager.NameNotFoundException) {
Log.i(TAG, "isPackageInstalled: Catch block - ${e.message}")
false
}
}
fun assertExternalAppOpens(appPackageName: String) {
if (isPackageInstalled(appPackageName)) {
Log.i(TAG, "assertExternalAppOpens: $appPackageName is installed on device")
try {
Log.i(TAG, "assertExternalAppOpens: Try block")
intended(toPackage(appPackageName))
Log.i(TAG, "assertExternalAppOpens: Matched intent to $appPackageName")
} catch (e: AssertionFailedError) {
Log.i(TAG, "assertExternalAppOpens: Catch block - ${e.message}")
}
} else {
mDevice.waitNotNull(
Until.findObject(By.text("Could not open file")),
TestAssetHelper.waitingTime,
)
Log.i(TAG, "assertExternalAppOpens: Verified \"Could not open file\" message")
}
}
fun assertNativeAppOpens(appPackageName: String, url: String = "") {
if (isPackageInstalled(appPackageName)) {
mDevice.waitForIdle(TestAssetHelper.waitingTimeShort)
Assert.assertTrue(
TestHelper.mDevice.findObject(UiSelector().packageName(appPackageName))
.waitForExists(TestAssetHelper.waitingTime),
)
} else {
BrowserRobot().verifyUrl(url)
}
}
fun assertYoutubeAppOpens() = intended(toPackage(YOUTUBE_APP))
/**
* Checks whether the latest activity of the application is used for custom tabs or PWAs.
*
* @return Boolean value that helps us know if the current activity supports custom tabs or PWAs.
*/
fun isExternalAppBrowserActivityInCurrentTask(): Boolean {
val activityManager = TestHelper.appContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
mDevice.waitForIdle(TestAssetHelper.waitingTimeShort)
return activityManager.appTasks[0].taskInfo.topActivity!!.className == ExternalAppBrowserActivity::class.java.name
}
/**
* Run test with automatically registering idling resources and cleanup.
*
* @param idlingResources zero or more [IdlingResource] to be used when running [testBlock].
* @param testBlock test code to execute.
*/
fun registerAndCleanupIdlingResources(
vararg idlingResources: IdlingResource,
testBlock: () -> Unit,
) {
idlingResources.forEach {
IdlingRegistry.getInstance().register(it)
}
try {
testBlock()
} finally {
idlingResources.forEach {
IdlingRegistry.getInstance().unregister(it)
}
}
}
// Permission allow dialogs differ on various Android APIs
fun grantSystemPermission() {
val whileUsingTheAppPermissionButton: UiObject =
mDevice.findObject(UiSelector().textContains("While using the app"))
val allowPermissionButton: UiObject =
mDevice.findObject(
UiSelector()
.textContains("Allow")
.className("android.widget.Button"),
)
if (Build.VERSION.SDK_INT >= 23) {
if (whileUsingTheAppPermissionButton.waitForExists(TestAssetHelper.waitingTimeShort)) {
whileUsingTheAppPermissionButton.click()
} else if (allowPermissionButton.waitForExists(TestAssetHelper.waitingTimeShort)) {
allowPermissionButton.click()
}
}
}
// Permission deny dialogs differ on various Android APIs
fun denyPermission() {
mDevice.findObject(UiSelector().textContains("Deny")).waitForExists(TestAssetHelper.waitingTime)
mDevice.findObject(UiSelector().textContains("Deny")).click()
}
fun isTestLab(): Boolean {
return Settings.System.getString(TestHelper.appContext.contentResolver, "firebase.test.lab").toBoolean()
}
/**
* Changes the default language of the entire device, not just the app.
* Runs on Debug variant as we don't want to adjust Release permission manifests
* Runs the test in its testBlock.
* Cleans up and sets the default locale after it's done.
*/
fun runWithSystemLocaleChanged(locale: Locale, testRule: ActivityTestRule<HomeActivity>, testBlock: () -> Unit) {
if (Config.channel.isDebug) {
/* Sets permission to change device language */
PermissionRequester().apply {
addPermissions(
Manifest.permission.CHANGE_CONFIGURATION,
)
requestPermissions()
}
val defaultLocale = Locale.getDefault()
try {
setSystemLocale(locale)
testBlock()
ThreadUtils.runOnUiThread { testRule.activity.recreate() }
} catch (e: Exception) {
e.printStackTrace()
} finally {
setSystemLocale(defaultLocale)
}
}
}
/**
* Changes the default language of the entire device, not just the app.
*/
fun setSystemLocale(locale: Locale) {
val activityManagerNative = Class.forName("android.app.ActivityManagerNative")
val am = activityManagerNative.getMethod("getDefault", *arrayOfNulls(0))
.invoke(activityManagerNative, *arrayOfNulls(0))
val config = InstrumentationRegistry.getInstrumentation().context.resources.configuration
config.javaClass.getDeclaredField("locale")[config] = locale
config.javaClass.getDeclaredField("userSetLocale").setBoolean(config, true)
am.javaClass.getMethod(
"updateConfiguration",
Configuration::class.java,
).invoke(am, config)
}
fun putAppToBackground() {
mDevice.pressRecentApps()
mDevice.findObject(UiSelector().resourceId("${TestHelper.packageName}:id/container")).waitUntilGone(
TestAssetHelper.waitingTime,
)
}
fun bringAppToForeground() {
mDevice.pressRecentApps()
mDevice.findObject(UiSelector().resourceId("${TestHelper.packageName}:id/container")).waitForExists(
TestAssetHelper.waitingTime,
)
}
fun verifyKeyboardVisibility(isExpectedToBeVisible: Boolean = true) {
mDevice.waitForIdle()
assertEquals(
"Keyboard not shown",
isExpectedToBeVisible,
mDevice
.executeShellCommand("dumpsys input_method | grep mInputShown")
.contains("mInputShown=true"),
)
}
fun openAppFromExternalLink(url: String) {
val context = InstrumentationRegistry.getInstrumentation().getTargetContext()
val intent = Intent().apply {
action = Intent.ACTION_VIEW
data = Uri.parse(url)
`package` = TestHelper.packageName
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
try {
context.startActivity(intent)
} catch (ex: ActivityNotFoundException) {
intent.setPackage(null)
context.startActivity(intent)
}
}
/**
* Wrapper for tests to run only when certain conditions are met.
* For example: this method will avoid accidentally running a test on GV versions where the feature is disabled.
*/
fun runWithCondition(condition: Boolean, testBlock: () -> Unit) {
if (condition) {
testBlock()
}
}
/**
* Wrapper to launch the app using the launcher intent.
*/
fun runWithLauncherIntent(
activityTestRule: AndroidComposeTestRule<HomeActivityIntentTestRule, HomeActivity>,
testBlock: () -> Unit,
) {
val launcherIntent = Intent(Intent.ACTION_MAIN).apply {
addCategory(Intent.CATEGORY_LAUNCHER)
}
activityTestRule.activityRule.withIntent(launcherIntent).launchActivity(launcherIntent)
try {
testBlock()
} catch (e: Exception) {
e.printStackTrace()
}
}
}

@ -4,10 +4,13 @@
package org.mozilla.fenix.helpers
import org.mozilla.fenix.helpers.TestHelper.getSponsoredShortcutTitle
import org.mozilla.fenix.helpers.DataGenerationHelper.getSponsoredShortcutTitle
object Constants {
// Tag used for logging
const val TAG = "MozUITestLog"
// Device or AVD requires a Google Services Android OS installation
object PackageName {
const val GOOGLE_PLAY_SERVICES = "com.android.vending"
@ -18,6 +21,7 @@ object Constants {
const val GMAIL_APP = "com.google.android.gm"
const val PHONE_APP = "com.android.dialer"
const val ANDROID_SETTINGS = "com.android.settings"
const val PRINT_SPOOLER = "com.android.printspooler"
}
const val SPEECH_RECOGNITION = "android.speech.action.RECOGNIZE_SPEECH"

@ -0,0 +1,113 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.helpers
import android.app.PendingIntent
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiSelector
import mozilla.components.browser.state.search.SearchEngine
import mozilla.components.browser.state.state.availableSearchEngines
import org.junit.Assert
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.utils.IntentUtils
object DataGenerationHelper {
val appContext: Context = InstrumentationRegistry.getInstrumentation().targetContext
fun createCustomTabIntent(
pageUrl: String,
customMenuItemLabel: String = "",
customActionButtonDescription: String = "",
): Intent {
val appContext = InstrumentationRegistry.getInstrumentation()
.targetContext
.applicationContext
val pendingIntent = PendingIntent.getActivity(appContext, 0, Intent(), IntentUtils.defaultIntentPendingFlags)
val customTabsIntent = CustomTabsIntent.Builder()
.addMenuItem(customMenuItemLabel, pendingIntent)
.setShareState(CustomTabsIntent.SHARE_STATE_ON)
.setActionButton(
createTestBitmap(),
customActionButtonDescription,
pendingIntent,
true,
)
.build()
customTabsIntent.intent.data = Uri.parse(pageUrl)
return customTabsIntent.intent
}
private fun createTestBitmap(): Bitmap {
val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
canvas.drawColor(Color.GREEN)
return bitmap
}
fun getStringResource(id: Int, argument: String = TestHelper.appName) = TestHelper.appContext.resources.getString(id, argument)
private val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
fun generateRandomString(stringLength: Int) =
(1..stringLength)
.map { kotlin.random.Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("")
/**
* Creates clipboard data.
*/
fun setTextToClipBoard(context: Context, message: String) {
val clipBoard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipData = ClipData.newPlainText("label", message)
clipBoard.setPrimaryClip(clipData)
}
/**
* Returns sponsored shortcut title based on the index.
*/
fun getSponsoredShortcutTitle(position: Int): String {
val sponsoredShortcut = mDevice.findObject(
UiSelector()
.resourceId("${TestHelper.packageName}:id/top_site_item")
.index(position - 1),
).getChild(
UiSelector()
.resourceId("${TestHelper.packageName}:id/top_site_title"),
).text
return sponsoredShortcut
}
/**
* The list of Search engines for the "home" region of the user.
* For en-us it will return the 6 engines selected by default: Google, Bing, DuckDuckGo, Amazon, Ebay, Wikipedia.
*/
fun getRegionSearchEnginesList(): List<SearchEngine> {
val searchEnginesList = appContext.components.core.store.state.search.regionSearchEngines
Assert.assertTrue("Search engines list returned nothing", searchEnginesList.isNotEmpty())
return searchEnginesList
}
/**
* The list of Search engines available to be added by user choice.
* For en-us it will return the 2 engines: Reddit, Youtube.
*/
fun getAvailableSearchEngines(): List<SearchEngine> {
val searchEnginesList = TestHelper.appContext.components.core.store.state.search.availableSearchEngines
Assert.assertTrue("Search engines list returned nothing", searchEnginesList.isNotEmpty())
return searchEnginesList
}
}

@ -67,11 +67,6 @@ interface FeatureSettingsHelper {
*/
var etpPolicy: ETPPolicy
/**
* Enable or disable cookie banner reduction dialog.
*/
var isCookieBannerReductionDialogEnabled: Boolean
/**
* Enable or disable open in app banner.
*/

@ -33,7 +33,6 @@ class FeatureSettingsHelperDelegate() : FeatureSettingsHelper {
isTCPCFREnabled = settings.shouldShowTotalCookieProtectionCFR,
isWallpaperOnboardingEnabled = settings.showWallpaperOnboarding,
isDeleteSitePermissionsEnabled = settings.deleteSitePermissions,
isCookieBannerReductionDialogEnabled = !settings.userOptOutOfReEngageCookieBannerDialog,
isOpenInAppBannerEnabled = settings.shouldShowOpenInAppBanner,
etpPolicy = getETPPolicy(settings),
tabsTrayRewriteEnabled = settings.enableTabsTrayToCompose,
@ -63,7 +62,6 @@ class FeatureSettingsHelperDelegate() : FeatureSettingsHelper {
override var isRecentlyVisitedFeatureEnabled: Boolean by updatedFeatureFlags::isRecentlyVisitedFeatureEnabled
override var isPWAsPromptEnabled: Boolean by updatedFeatureFlags::isPWAsPromptEnabled
override var isTCPCFREnabled: Boolean by updatedFeatureFlags::isTCPCFREnabled
override var isCookieBannerReductionDialogEnabled: Boolean by updatedFeatureFlags::isCookieBannerReductionDialogEnabled
override var isOpenInAppBannerEnabled: Boolean by updatedFeatureFlags::isOpenInAppBannerEnabled
override var etpPolicy: ETPPolicy by updatedFeatureFlags::etpPolicy
override var tabsTrayRewriteEnabled: Boolean by updatedFeatureFlags::tabsTrayRewriteEnabled
@ -90,7 +88,6 @@ class FeatureSettingsHelperDelegate() : FeatureSettingsHelper {
settings.shouldShowTotalCookieProtectionCFR = featureFlags.isTCPCFREnabled
settings.showWallpaperOnboarding = featureFlags.isWallpaperOnboardingEnabled
settings.deleteSitePermissions = featureFlags.isDeleteSitePermissionsEnabled
settings.userOptOutOfReEngageCookieBannerDialog = !featureFlags.isCookieBannerReductionDialogEnabled
settings.shouldShowOpenInAppBanner = featureFlags.isOpenInAppBannerEnabled
settings.enableTabsTrayToCompose = featureFlags.tabsTrayRewriteEnabled
settings.enableComposeTopSites = featureFlags.composeTopSitesEnabled
@ -109,7 +106,6 @@ private data class FeatureFlags(
var isTCPCFREnabled: Boolean,
var isWallpaperOnboardingEnabled: Boolean,
var isDeleteSitePermissionsEnabled: Boolean,
var isCookieBannerReductionDialogEnabled: Boolean,
var isOpenInAppBannerEnabled: Boolean,
var etpPolicy: ETPPolicy,
var tabsTrayRewriteEnabled: Boolean,

@ -52,7 +52,6 @@ class HomeActivityTestRule(
isTCPCFREnabled: Boolean = settings.shouldShowTotalCookieProtectionCFR,
isWallpaperOnboardingEnabled: Boolean = settings.showWallpaperOnboarding,
isDeleteSitePermissionsEnabled: Boolean = settings.deleteSitePermissions,
isCookieBannerReductionDialogEnabled: Boolean = !settings.userOptOutOfReEngageCookieBannerDialog,
isOpenInAppBannerEnabled: Boolean = settings.shouldShowOpenInAppBanner,
etpPolicy: ETPPolicy = getETPPolicy(settings),
tabsTrayRewriteEnabled: Boolean = false,
@ -67,7 +66,6 @@ class HomeActivityTestRule(
this.isTCPCFREnabled = isTCPCFREnabled
this.isWallpaperOnboardingEnabled = isWallpaperOnboardingEnabled
this.isDeleteSitePermissionsEnabled = isDeleteSitePermissionsEnabled
this.isCookieBannerReductionDialogEnabled = isCookieBannerReductionDialogEnabled
this.isOpenInAppBannerEnabled = isOpenInAppBannerEnabled
this.etpPolicy = etpPolicy
this.tabsTrayRewriteEnabled = tabsTrayRewriteEnabled
@ -126,7 +124,6 @@ class HomeActivityTestRule(
isPWAsPromptEnabled = false,
isTCPCFREnabled = false,
isWallpaperOnboardingEnabled = false,
isCookieBannerReductionDialogEnabled = false,
isOpenInAppBannerEnabled = false,
composeTopSitesEnabled = composeTopSitesEnabled,
)
@ -164,7 +161,6 @@ class HomeActivityIntentTestRule internal constructor(
isTCPCFREnabled: Boolean = settings.shouldShowTotalCookieProtectionCFR,
isWallpaperOnboardingEnabled: Boolean = settings.showWallpaperOnboarding,
isDeleteSitePermissionsEnabled: Boolean = settings.deleteSitePermissions,
isCookieBannerReductionDialogEnabled: Boolean = !settings.userOptOutOfReEngageCookieBannerDialog,
isOpenInAppBannerEnabled: Boolean = settings.shouldShowOpenInAppBanner,
etpPolicy: ETPPolicy = getETPPolicy(settings),
tabsTrayRewriteEnabled: Boolean = false,
@ -179,7 +175,6 @@ class HomeActivityIntentTestRule internal constructor(
this.isTCPCFREnabled = isTCPCFREnabled
this.isWallpaperOnboardingEnabled = isWallpaperOnboardingEnabled
this.isDeleteSitePermissionsEnabled = isDeleteSitePermissionsEnabled
this.isCookieBannerReductionDialogEnabled = isCookieBannerReductionDialogEnabled
this.isOpenInAppBannerEnabled = isOpenInAppBannerEnabled
this.etpPolicy = etpPolicy
this.tabsTrayRewriteEnabled = tabsTrayRewriteEnabled
@ -244,7 +239,6 @@ class HomeActivityIntentTestRule internal constructor(
isTCPCFREnabled = settings.shouldShowTotalCookieProtectionCFR
isWallpaperOnboardingEnabled = settings.showWallpaperOnboarding
isDeleteSitePermissionsEnabled = settings.deleteSitePermissions
isCookieBannerReductionDialogEnabled = !settings.userOptOutOfReEngageCookieBannerDialog
isOpenInAppBannerEnabled = settings.shouldShowOpenInAppBanner
etpPolicy = getETPPolicy(settings)
}
@ -275,7 +269,6 @@ class HomeActivityIntentTestRule internal constructor(
isPWAsPromptEnabled = false,
isTCPCFREnabled = false,
isWallpaperOnboardingEnabled = false,
isCookieBannerReductionDialogEnabled = false,
isOpenInAppBannerEnabled = false,
composeTopSitesEnabled = composeTopSitesEnabled,
)

@ -4,10 +4,12 @@
package org.mozilla.fenix.helpers
import android.util.Log
import androidx.test.uiautomator.UiObject
import androidx.test.uiautomator.UiSelector
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.mDevice
@ -17,101 +19,131 @@ import org.mozilla.fenix.helpers.TestHelper.mDevice
*/
object MatcherHelper {
fun itemWithResId(resourceId: String) =
mDevice.findObject(UiSelector().resourceId(resourceId))
fun itemWithResId(resourceId: String): UiObject {
Log.i(TAG, "Looking for item with resource id: $resourceId")
return mDevice.findObject(UiSelector().resourceId(resourceId))
}
fun itemContainingText(itemText: String) =
mDevice.findObject(UiSelector().textContains(itemText))
fun itemContainingText(itemText: String): UiObject {
Log.i(TAG, "Looking for item with text: $itemText")
return mDevice.findObject(UiSelector().textContains(itemText))
}
fun itemWithText(itemText: String) =
mDevice.findObject(UiSelector().text(itemText))
fun itemWithText(itemText: String): UiObject {
Log.i(TAG, "Looking for item with text: $itemText")
return mDevice.findObject(UiSelector().text(itemText))
}
fun itemWithDescription(description: String) =
mDevice.findObject(UiSelector().descriptionContains(description))
fun itemWithDescription(description: String): UiObject {
Log.i(TAG, "Looking for item with description: $description")
return mDevice.findObject(UiSelector().descriptionContains(description))
}
fun checkedItemWithResId(resourceId: String, isChecked: Boolean) =
mDevice.findObject(UiSelector().resourceId(resourceId).checked(isChecked))
fun itemWithIndex(index: Int): UiObject {
Log.i(TAG, "Looking for item with index: $index")
return mDevice.findObject(UiSelector().index(index))
}
fun itemWithClassName(className: String): UiObject {
Log.i(TAG, "Looking for item with class name: $className")
return mDevice.findObject(UiSelector().className(className))
}
fun itemWithResIdAndIndex(resourceId: String, index: Int): UiObject {
Log.i(TAG, "Looking for item with resource id: $resourceId and index: $index")
return mDevice.findObject(UiSelector().resourceId(resourceId).index(index))
}
fun checkedItemWithResIdAndText(resourceId: String, text: String, isChecked: Boolean) =
mDevice.findObject(
fun itemWithClassNameAndIndex(className: String, index: Int): UiObject {
Log.i(TAG, "Looking for item with class name: $className and index: $index")
return mDevice.findObject(UiSelector().className(className).index(index))
}
fun checkedItemWithResId(resourceId: String, isChecked: Boolean): UiObject {
Log.i(TAG, "Looking for checked item with resource id: $resourceId")
return mDevice.findObject(UiSelector().resourceId(resourceId).checked(isChecked))
}
fun checkedItemWithResIdAndText(resourceId: String, text: String, isChecked: Boolean): UiObject {
Log.i(TAG, "Looking for checked item with resource id: $resourceId and text: $text")
return mDevice.findObject(
UiSelector()
.resourceId(resourceId)
.textContains(text)
.checked(isChecked),
)
}
fun itemWithResIdAndDescription(resourceId: String, description: String) =
mDevice.findObject(UiSelector().resourceId(resourceId).descriptionContains(description))
fun itemWithResIdAndText(resourceId: String, text: String) =
mDevice.findObject(UiSelector().resourceId(resourceId).text(text))
fun itemWithResIdContainingText(resourceId: String, text: String) =
mDevice.findObject(UiSelector().resourceId(resourceId).textContains(text))
fun itemWithResIdAndDescription(resourceId: String, description: String): UiObject {
Log.i(TAG, "Looking for item with resource id: $resourceId and description: $description")
return mDevice.findObject(UiSelector().resourceId(resourceId).descriptionContains(description))
}
fun assertItemWithResIdExists(vararg appItems: UiObject, exists: Boolean = true) {
if (exists) {
for (appItem in appItems) {
assertTrue(appItem.waitForExists(waitingTime))
}
} else {
for (appItem in appItems) {
assertFalse(appItem.waitForExists(waitingTimeShort))
}
}
fun itemWithResIdAndText(resourceId: String, text: String): UiObject {
Log.i(TAG, "Looking for item with resource id: $resourceId and text: $text")
return mDevice.findObject(UiSelector().resourceId(resourceId).text(text))
}
fun assertItemContainingTextExists(vararg appItems: UiObject, exists: Boolean = true) {
for (appItem in appItems) {
if (exists) {
assertTrue(appItem.waitForExists(waitingTime))
} else {
assertFalse(appItem.waitForExists(waitingTimeShort))
}
}
fun itemWithResIdContainingText(resourceId: String, text: String): UiObject {
Log.i(TAG, "Looking for item with resource id: $resourceId and containing text: $text")
return mDevice.findObject(UiSelector().resourceId(resourceId).textContains(text))
}
fun assertItemWithDescriptionExists(vararg appItems: UiObject, exists: Boolean = true) {
fun assertUIObjectExists(
vararg appItems: UiObject,
exists: Boolean = true,
waitingTime: Long = TestAssetHelper.waitingTime,
) {
for (appItem in appItems) {
if (exists) {
assertTrue(appItem.waitForExists(waitingTime))
assertTrue("${appItem.selector} does not exist", appItem.waitForExists(waitingTime))
Log.i(TAG, "assertUIObjectExists: Verified ${appItem.selector} exists")
} else {
assertFalse(appItem.waitForExists(waitingTimeShort))
assertFalse("${appItem.selector} exists", appItem.waitForExists(waitingTimeShort))
Log.i(TAG, "assertUIObjectExists: Verified ${appItem.selector} does not exist")
}
}
}
fun assertCheckedItemWithResIdExists(vararg appItems: UiObject) {
fun assertUIObjectIsGone(vararg appItems: UiObject) {
for (appItem in appItems) {
assertTrue(appItem.waitForExists(waitingTime))
assertTrue("${appItem.selector} is not gone", appItem.waitUntilGone(waitingTime))
Log.i(TAG, "assertUIObjectIsGone: Verified ${appItem.selector} is gone")
}
}
fun assertCheckedItemWithResIdAndTextExists(vararg appItems: UiObject) {
fun assertItemTextEquals(vararg appItems: UiObject, expectedText: String, isEqual: Boolean = true) {
for (appItem in appItems) {
assertTrue(appItem.waitForExists(waitingTime))
}
}
fun assertItemWithResIdAndDescriptionExists(vararg appItems: UiObject) {
for (appItem in appItems) {
assertTrue(appItem.waitForExists(waitingTime))
if (isEqual) {
assertTrue(
"${appItem.selector} text does not equal to $expectedText",
appItem.text.equals(expectedText),
)
Log.i(TAG, "assertItemTextEquals: Verified ${appItem.selector} text equals to $expectedText")
} else {
assertFalse(
"${appItem.selector} text equals to $expectedText",
appItem.text.equals(expectedText),
)
Log.i(TAG, "assertItemTextEquals: Verified ${appItem.selector} text does not equal to $expectedText")
}
}
}
fun assertItemWithResIdAndTextExists(vararg appItems: UiObject, exists: Boolean = true) {
fun assertItemTextContains(vararg appItems: UiObject, itemText: String) {
for (appItem in appItems) {
if (exists) {
assertTrue(appItem.waitForExists(waitingTime))
} else {
assertFalse(appItem.waitForExists(waitingTimeShort))
}
assertTrue(
"${appItem.selector} text does not contain $itemText",
appItem.text.contains(itemText),
)
Log.i(TAG, "assertItemTextContains: Verified ${appItem.selector} text contains $itemText")
}
}
fun assertItemIsEnabledAndVisible(vararg appItems: UiObject) {
for (appItem in appItems) {
assertTrue(appItem.waitForExists(waitingTime) && appItem.isEnabled)
Log.i(TAG, "assertItemIsEnabledAndVisible: Verified ${appItem.selector} is visible and enabled")
}
}
}

@ -13,9 +13,9 @@ import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
import org.mozilla.fenix.components.PermissionStorage
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.IdlingResourceHelper.unregisterAllIdlingResources
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.setNetworkEnabled
/**
* Rule to retry flaky tests for a given number of times, catching some of the more common exceptions.

@ -2,83 +2,43 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@file:Suppress("DEPRECATION")
package org.mozilla.fenix.helpers
import android.Manifest
import android.app.ActivityManager
import android.app.PendingIntent
import android.content.ActivityNotFoundException
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.storage.StorageManager
import android.os.storage.StorageVolume
import android.provider.Settings
import android.util.Log
import android.view.View
import androidx.annotation.RequiresApi
import androidx.browser.customtabs.CustomTabsIntent
import androidx.test.espresso.Espresso
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.IdlingResource
import androidx.test.espresso.action.ViewActions.longClick
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.Intents.intended
import androidx.test.espresso.intent.matcher.IntentMatchers.toPackage
import androidx.test.espresso.matcher.ViewMatchers.hasSibling
import androidx.test.espresso.matcher.ViewMatchers.withChild
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withParent
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.runner.permission.PermissionRequester
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject
import androidx.test.uiautomator.UiScrollable
import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import junit.framework.AssertionFailedError
import mozilla.components.browser.state.search.SearchEngine
import mozilla.components.browser.state.state.availableSearchEngines
import mozilla.components.support.ktx.android.content.appName
import org.hamcrest.CoreMatchers
import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.Matcher
import org.junit.Assert
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.Config
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.Constants.PackageName.YOUTUBE_APP
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.ext.waitNotNull
import org.mozilla.fenix.helpers.idlingresource.NetworkConnectionIdlingResource
import org.mozilla.fenix.ui.robots.BrowserRobot
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.utils.IntentUtils
import org.mozilla.gecko.util.ThreadUtils
import java.io.File
import java.util.Locale
object TestHelper {
@ -125,14 +85,6 @@ object TestHelper {
activity.launchActivity(null)
}
fun getPermissionAllowID(): String {
return when
(Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
true -> "com.android.permissioncontroller"
false -> "com.android.packageinstaller"
}
}
fun waitUntilObjectIsFound(resourceName: String) {
mDevice.waitNotNull(
Until.findObjects(By.res(resourceName)),
@ -164,180 +116,13 @@ object TestHelper {
onView(withId(resId)).check(ViewAssertions.matches(withText(CoreMatchers.containsString(urlSubstring))))
}
fun openAppFromExternalLink(url: String) {
val context = InstrumentationRegistry.getInstrumentation().getTargetContext()
val intent = Intent().apply {
action = Intent.ACTION_VIEW
data = Uri.parse(url)
`package` = packageName
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
try {
context.startActivity(intent)
} catch (ex: ActivityNotFoundException) {
intent.setPackage(null)
context.startActivity(intent)
}
}
@RequiresApi(Build.VERSION_CODES.R)
fun deleteDownloadedFileOnStorage(fileName: String) {
val storageManager: StorageManager? = appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager?
val storageVolumes = storageManager!!.storageVolumes
val storageVolume: StorageVolume = storageVolumes[0]
val file = File(storageVolume.directory!!.path + "/Download/" + fileName)
try {
if (file.exists()) {
file.delete()
Log.d("TestLog", "File delete try 1")
assertFalse("The file was not deleted", file.exists())
}
} catch (e: AssertionError) {
file.delete()
Log.d("TestLog", "File delete retried")
assertFalse("The file was not deleted", file.exists())
}
}
fun setNetworkEnabled(enabled: Boolean) {
val networkDisconnectedIdlingResource = NetworkConnectionIdlingResource(false)
val networkConnectedIdlingResource = NetworkConnectionIdlingResource(true)
when (enabled) {
true -> {
mDevice.executeShellCommand("svc data enable")
mDevice.executeShellCommand("svc wifi enable")
// Wait for network connection to be completely enabled
IdlingRegistry.getInstance().register(networkConnectedIdlingResource)
Espresso.onIdle {
IdlingRegistry.getInstance().unregister(networkConnectedIdlingResource)
}
}
false -> {
mDevice.executeShellCommand("svc data disable")
mDevice.executeShellCommand("svc wifi disable")
// Wait for network connection to be completely disabled
IdlingRegistry.getInstance().register(networkDisconnectedIdlingResource)
Espresso.onIdle {
IdlingRegistry.getInstance().unregister(networkDisconnectedIdlingResource)
}
}
}
}
fun createCustomTabIntent(
pageUrl: String,
customMenuItemLabel: String = "",
customActionButtonDescription: String = "",
): Intent {
val appContext = InstrumentationRegistry.getInstrumentation()
.targetContext
.applicationContext
val pendingIntent = PendingIntent.getActivity(appContext, 0, Intent(), IntentUtils.defaultIntentPendingFlags)
val customTabsIntent = CustomTabsIntent.Builder()
.addMenuItem(customMenuItemLabel, pendingIntent)
.setShareState(CustomTabsIntent.SHARE_STATE_ON)
.setActionButton(
createTestBitmap(),
customActionButtonDescription,
pendingIntent,
true,
)
.build()
customTabsIntent.intent.data = Uri.parse(pageUrl)
return customTabsIntent.intent
}
private fun createTestBitmap(): Bitmap {
val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
canvas.drawColor(Color.GREEN)
return bitmap
}
fun isPackageInstalled(packageName: String): Boolean {
return try {
val packageManager = InstrumentationRegistry.getInstrumentation().context.packageManager
packageManager.getApplicationInfo(packageName, 0).enabled
} catch (exception: PackageManager.NameNotFoundException) {
false
}
}
fun assertExternalAppOpens(appPackageName: String) {
if (isPackageInstalled(appPackageName)) {
try {
intended(toPackage(appPackageName))
} catch (e: AssertionFailedError) {
e.printStackTrace()
}
} else {
mDevice.waitNotNull(
Until.findObject(By.text("Could not open file")),
waitingTime,
)
}
}
fun assertNativeAppOpens(appPackageName: String, url: String = "") {
if (isPackageInstalled(appPackageName)) {
mDevice.waitForIdle(waitingTimeShort)
assertTrue(
mDevice.findObject(UiSelector().packageName(appPackageName))
.waitForExists(waitingTime),
)
} else {
BrowserRobot().verifyUrl(url)
}
}
fun assertYoutubeAppOpens() = intended(toPackage(YOUTUBE_APP))
/**
* Checks whether the latest activity of the application is used for custom tabs or PWAs.
*
* @return Boolean value that helps us know if the current activity supports custom tabs or PWAs.
*/
fun isExternalAppBrowserActivityInCurrentTask(): Boolean {
val activityManager = appContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
mDevice.waitForIdle(waitingTimeShort)
return activityManager.appTasks[0].taskInfo.topActivity!!.className == ExternalAppBrowserActivity::class.java.name
}
/**
* Run test with automatically registering idling resources and cleanup.
*
* @param idlingResources zero or more [IdlingResource] to be used when running [testBlock].
* @param testBlock test code to execute.
*/
fun registerAndCleanupIdlingResources(
vararg idlingResources: IdlingResource,
testBlock: () -> Unit,
) {
idlingResources.forEach {
IdlingRegistry.getInstance().register(it)
}
try {
testBlock()
} finally {
idlingResources.forEach {
IdlingRegistry.getInstance().unregister(it)
}
}
}
// exit from Menus to home screen or browser
fun exitMenu() {
val toolbar =
mDevice.findObject(UiSelector().resourceId("$packageName:id/toolbar"))
while (!toolbar.waitForExists(waitingTimeShort)) {
mDevice.pressBack()
Log.i(TAG, "exitMenu: Exiting app settings menus using device back button")
}
}
@ -356,172 +141,8 @@ object TestHelper {
)
}
fun getStringResource(id: Int, argument: String = appName) = appContext.resources.getString(id, argument)
// Permission allow dialogs differ on various Android APIs
fun grantSystemPermission() {
val whileUsingTheAppPermissionButton: UiObject =
mDevice.findObject(UiSelector().textContains("While using the app"))
val allowPermissionButton: UiObject =
mDevice.findObject(
UiSelector()
.textContains("Allow")
.className("android.widget.Button"),
)
if (Build.VERSION.SDK_INT >= 23) {
if (whileUsingTheAppPermissionButton.waitForExists(waitingTimeShort)) {
whileUsingTheAppPermissionButton.click()
} else if (allowPermissionButton.waitForExists(waitingTimeShort)) {
allowPermissionButton.click()
}
}
}
// Permission deny dialogs differ on various Android APIs
fun denyPermission() {
mDevice.findObject(UiSelector().textContains("Deny")).waitForExists(waitingTime)
mDevice.findObject(UiSelector().textContains("Deny")).click()
}
fun isTestLab(): Boolean {
return Settings.System.getString(appContext.contentResolver, "firebase.test.lab").toBoolean()
}
private val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
fun generateRandomString(stringLength: Int) =
(1..stringLength)
.map { kotlin.random.Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("")
/**
* Changes the default language of the entire device, not just the app.
* Runs on Debug variant as we don't want to adjust Release permission manifests
* Runs the test in its testBlock.
* Cleans up and sets the default locale after it's done.
*/
fun runWithSystemLocaleChanged(locale: Locale, testRule: ActivityTestRule<HomeActivity>, testBlock: () -> Unit) {
if (Config.channel.isDebug) {
/* Sets permission to change device language */
PermissionRequester().apply {
addPermissions(
Manifest.permission.CHANGE_CONFIGURATION,
)
requestPermissions()
}
val defaultLocale = Locale.getDefault()
try {
setSystemLocale(locale)
testBlock()
ThreadUtils.runOnUiThread { testRule.activity.recreate() }
} catch (e: Exception) {
e.printStackTrace()
} finally {
setSystemLocale(defaultLocale)
}
}
}
/**
* Changes the default language of the entire device, not just the app.
*/
fun setSystemLocale(locale: Locale) {
val activityManagerNative = Class.forName("android.app.ActivityManagerNative")
val am = activityManagerNative.getMethod("getDefault", *arrayOfNulls(0))
.invoke(activityManagerNative, *arrayOfNulls(0))
val config = InstrumentationRegistry.getInstrumentation().context.resources.configuration
config.javaClass.getDeclaredField("locale")[config] = locale
config.javaClass.getDeclaredField("userSetLocale").setBoolean(config, true)
am.javaClass.getMethod(
"updateConfiguration",
Configuration::class.java,
).invoke(am, config)
}
/**
* Creates clipboard data.
*/
fun setTextToClipBoard(context: Context, message: String) {
val clipBoard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipData = ClipData.newPlainText("label", message)
clipBoard.setPrimaryClip(clipData)
}
/**
* Returns sponsored shortcut title based on the index.
*/
fun getSponsoredShortcutTitle(position: Int): String {
val sponsoredShortcut = mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/top_site_item")
.index(position - 1),
).getChild(
UiSelector()
.resourceId("$packageName:id/top_site_title"),
).text
return sponsoredShortcut
}
fun verifyLightThemeApplied(expected: Boolean) =
assertFalse("Light theme not selected", expected)
fun verifyDarkThemeApplied(expected: Boolean) = assertTrue("Dark theme not selected", expected)
/**
* Wrapper for tests to run only when certain conditions are met.
* For example: this method will avoid accidentally running a test on GV versions where the feature is disabled.
*/
fun runWithCondition(condition: Boolean, testBlock: () -> Unit) {
if (condition) {
testBlock()
}
}
fun putAppToBackground() {
mDevice.pressRecentApps()
mDevice.findObject(UiSelector().resourceId("$packageName:id/container")).waitUntilGone(waitingTime)
}
fun bringAppToForeground() {
mDevice.pressRecentApps()
mDevice.findObject(UiSelector().resourceId("$packageName:id/container")).waitForExists(waitingTime)
}
fun verifyKeyboardVisibility(isExpectedToBeVisible: Boolean = true) {
mDevice.waitForIdle()
assertEquals(
"Keyboard not shown",
isExpectedToBeVisible,
mDevice
.executeShellCommand("dumpsys input_method | grep mInputShown")
.contains("mInputShown=true"),
)
}
/**
* The list of Search engines for the "home" region of the user.
* For en-us it will return the 6 engines selected by default: Google, Bing, DuckDuckGo, Amazon, Ebay, Wikipedia.
*/
fun getRegionSearchEnginesList(): List<SearchEngine> {
val searchEnginesList = appContext.components.core.store.state.search.regionSearchEngines
assertTrue("Search engines list returned nothing", searchEnginesList.isNotEmpty())
return searchEnginesList
}
/**
* The list of Search engines available to be added by user choice.
* For en-us it will return the 2 engines: Reddit, Youtube.
*/
fun getAvailableSearchEngines(): List<SearchEngine> {
val searchEnginesList = appContext.components.core.store.state.search.availableSearchEngines
assertTrue("Search engines list returned nothing", searchEnginesList.isNotEmpty())
return searchEnginesList
}
}

@ -4,9 +4,11 @@
package org.mozilla.fenix.helpers.ext
import android.util.Log
import androidx.test.uiautomator.SearchCondition
import androidx.test.uiautomator.UiDevice
import org.junit.Assert.assertNotNull
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.TestAssetHelper
/**
@ -17,4 +19,8 @@ import org.mozilla.fenix.helpers.TestAssetHelper
fun UiDevice.waitNotNull(
searchCondition: SearchCondition<*>,
waitTime: Long = TestAssetHelper.waitingTime,
) = assertNotNull(wait(searchCondition, waitTime))
) {
Log.i(TAG, "Wait not null: $searchCondition")
assertNotNull(wait(searchCondition, waitTime))
Log.i(TAG, "Found $searchCondition not null")
}

@ -4,12 +4,19 @@
package org.mozilla.fenix.onboarding.view
import io.mockk.every
import io.mockk.mockk
import mozilla.components.service.nimbus.evalJexlSafe
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.experiments.nimbus.GleanPlumbMessageHelper
import org.mozilla.experiments.nimbus.StringHolder
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.nimbus.FxNimbus
import org.mozilla.fenix.nimbus.JunoOnboarding
import org.mozilla.fenix.nimbus.OnboardingCardData
import org.mozilla.fenix.nimbus.OnboardingCardType
@ -19,28 +26,242 @@ class JunoOnboardingMapperTest {
val activityTestRule =
HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
private lateinit var junoOnboardingFeature: JunoOnboarding
private lateinit var jexlConditions: Map<String, String>
private lateinit var jexlHelper: GleanPlumbMessageHelper
private lateinit var evalFunction: (String) -> Boolean
@Before
fun setup() {
junoOnboardingFeature = FxNimbus.features.junoOnboarding.value()
jexlConditions = junoOnboardingFeature.conditions
jexlHelper = mockk(relaxed = true)
evalFunction = { condition -> jexlHelper.evalJexlSafe(condition) }
every { evalFunction("true") } returns true
every { evalFunction("false") } returns false
}
@Test
fun showNotificationTrue_showAddWidgetFalse_pagesToDisplay_returnsSortedListOfAllConvertedPages_withoutAddWidgetPage() {
val expected = listOf(defaultBrowserPageUiData, syncPageUiData, notificationPageUiData)
assertEquals(expected, unsortedAllKnownCardData.toPageUiData(true, false))
assertEquals(
expected,
unsortedAllKnownCardData.toPageUiData(
showNotificationPage = true,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test
fun showNotificationFalse_showAddWidgetFalse_pagesToDisplay_returnsSortedListOfConvertedPages_withoutNotificationPage_and_addWidgetPage() {
val expected = listOf(defaultBrowserPageUiData, syncPageUiData)
assertEquals(expected, unsortedAllKnownCardData.toPageUiData(false, false))
assertEquals(
expected,
unsortedAllKnownCardData.toPageUiData(
showNotificationPage = false,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test
fun showNotificationFalse_showAddWidgetTrue_pagesToDisplay_returnsSortedListOfAllConvertedPages_withoutNotificationPage() {
val expected = listOf(defaultBrowserPageUiData, addSearchWidgetPageUiData, syncPageUiData)
assertEquals(expected, unsortedAllKnownCardData.toPageUiData(false, true))
assertEquals(
expected,
unsortedAllKnownCardData.toPageUiData(
showNotificationPage = false,
showAddWidgetPage = true,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test
fun showNotificationTrue_and_showAddWidgetTrue_pagesToDisplay_returnsSortedListOfConvertedPages() {
val expected = listOf(defaultBrowserPageUiData, addSearchWidgetPageUiData, syncPageUiData, notificationPageUiData)
assertEquals(expected, unsortedAllKnownCardData.toPageUiData(true, true))
val expected = listOf(
defaultBrowserPageUiData,
addSearchWidgetPageUiData,
syncPageUiData,
notificationPageUiData,
)
assertEquals(
expected,
unsortedAllKnownCardData.toPageUiData(
showNotificationPage = true,
showAddWidgetPage = true,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test
fun cardConditionsMatchJexlConditions_shouldDisplayCard_returnsConvertedPage() {
val jexlConditions = mapOf("ALWAYS" to "true", "NEVER" to "false")
val expected = listOf(defaultBrowserPageUiData)
assertEquals(
expected,
listOf(defaultBrowserCardData).toPageUiData(
showNotificationPage = false,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test
fun noJexlConditionsAndNoCardConditions_shouldDisplayCard_returnsNoPage() {
val jexlConditions = mapOf<String, String>()
val expected = emptyList<OnboardingPageUiData>()
assertEquals(
expected,
listOf(addSearchWidgetCardDataNoConditions).toPageUiData(
showNotificationPage = false,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test
fun noJexlConditions_shouldDisplayCard_returnsNoPage() {
val jexlConditions = mapOf<String, String>()
val expected = emptyList<OnboardingPageUiData>()
assertEquals(
expected,
listOf(defaultBrowserCardData).toPageUiData(
showNotificationPage = false,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test
fun prerequisitesMatchJexlConditions_shouldDisplayCard_returnsConvertedPage() {
val jexlConditions = mapOf("ALWAYS" to "true")
val expected = listOf(defaultBrowserPageUiData)
assertEquals(
expected,
listOf(defaultBrowserCardData).toPageUiData(
showNotificationPage = false,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test
fun prerequisitesDontMatchJexlConditions_shouldDisplayCard_returnsNoPage() {
val jexlConditions = mapOf("NEVER" to "false")
val expected = emptyList<OnboardingPageUiData>()
assertEquals(
expected,
listOf(defaultBrowserCardData).toPageUiData(
showNotificationPage = false,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test
fun noCardConditions_shouldDisplayCard_returnsNoPage() {
val jexlConditions = mapOf("ALWAYS" to "true", "NEVER" to "false")
val expected = emptyList<OnboardingPageUiData>()
assertEquals(
expected,
listOf(addSearchWidgetCardDataNoConditions).toPageUiData(
showNotificationPage = false,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test
fun noDisqualifiers_shouldDisplayCard_returnsConvertedPage() {
val jexlConditions = mapOf("ALWAYS" to "true", "NEVER" to "false")
val expected = listOf(defaultBrowserPageUiData)
assertEquals(
expected,
listOf(defaultBrowserCardDataNoDisqualifiers).toPageUiData(
showNotificationPage = false,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test
fun disqualifiersMatchJexlConditions_shouldDisplayCard_returnsConvertedPage() {
val jexlConditions = mapOf("NEVER" to "false")
val expected = listOf(syncPageUiData)
assertEquals(
expected,
listOf(syncCardData).toPageUiData(
showNotificationPage = false,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test
fun disqualifiersDontMatchJexlConditions_shouldDisplayCard_returnsNoPage() {
val jexlConditions = mapOf("NEVER" to "false")
val expected = listOf<OnboardingPageUiData>()
assertEquals(
expected,
listOf(notificationCardData).toPageUiData(
showNotificationPage = false,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test
fun noPrerequisites_shouldDisplayCard_returnsConvertedPage() {
val jexlConditions = mapOf("ALWAYS" to "true", "NEVER" to "false")
val expected = listOf(syncPageUiData)
assertEquals(
expected,
listOf(syncCardData).toPageUiData(
showNotificationPage = false,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
}
@ -88,7 +309,36 @@ private val defaultBrowserCardData = OnboardingCardData(
primaryButtonLabel = StringHolder(null, "default browser primary button text"),
secondaryButtonLabel = StringHolder(null, "default browser secondary button text"),
ordering = 10,
prerequisites = listOf("ALWAYS"),
disqualifiers = listOf("NEVER"),
)
private val defaultBrowserCardDataNoDisqualifiers = OnboardingCardData(
cardType = OnboardingCardType.DEFAULT_BROWSER,
imageRes = R.drawable.ic_onboarding_welcome,
title = StringHolder(null, "default browser title"),
body = StringHolder(null, "default browser body with link text"),
linkText = StringHolder(null, "link text"),
primaryButtonLabel = StringHolder(null, "default browser primary button text"),
secondaryButtonLabel = StringHolder(null, "default browser secondary button text"),
ordering = 10,
prerequisites = listOf("ALWAYS"),
disqualifiers = listOf(),
)
private val addSearchWidgetCardDataNoConditions = OnboardingCardData(
cardType = OnboardingCardType.ADD_SEARCH_WIDGET,
imageRes = R.drawable.ic_onboarding_search_widget,
title = StringHolder(null, "add search widget title"),
body = StringHolder(null, "add search widget body with link text"),
linkText = StringHolder(null, "link text"),
primaryButtonLabel = StringHolder(null, "add search widget primary button text"),
secondaryButtonLabel = StringHolder(null, "add search widget secondary button text"),
ordering = 15,
prerequisites = listOf(),
disqualifiers = listOf(),
)
private val addSearchWidgetCardData = OnboardingCardData(
cardType = OnboardingCardType.ADD_SEARCH_WIDGET,
imageRes = R.drawable.ic_onboarding_search_widget,
@ -99,6 +349,7 @@ private val addSearchWidgetCardData = OnboardingCardData(
secondaryButtonLabel = StringHolder(null, "add search widget secondary button text"),
ordering = 15,
)
private val syncCardData = OnboardingCardData(
cardType = OnboardingCardType.SYNC_SIGN_IN,
imageRes = R.drawable.ic_onboarding_sync,
@ -107,7 +358,10 @@ private val syncCardData = OnboardingCardData(
primaryButtonLabel = StringHolder(null, "sync primary button text"),
secondaryButtonLabel = StringHolder(null, "sync secondary button text"),
ordering = 20,
prerequisites = listOf(),
disqualifiers = listOf("NEVER"),
)
private val notificationCardData = OnboardingCardData(
cardType = OnboardingCardType.NOTIFICATION_PERMISSION,
imageRes = R.drawable.ic_notification_permission,
@ -116,6 +370,8 @@ private val notificationCardData = OnboardingCardData(
primaryButtonLabel = StringHolder(null, "notification primary button text"),
secondaryButtonLabel = StringHolder(null, "notification secondary button text"),
ordering = 30,
prerequisites = listOf(),
disqualifiers = listOf("NEVER", "OTHER"),
)
private val unsortedAllKnownCardData = listOf(

@ -26,11 +26,9 @@ import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.ext.toUri
import org.mozilla.fenix.helpers.ext.waitNotNull
import org.mozilla.fenix.ui.robots.accountSettings
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.settingsSubMenuLoginsAndPassword
@Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
@ -55,9 +53,10 @@ class SyncIntegrationTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/352905
// History item Desktop -> Fenix
@Test
fun checkHistoryFromDesktopTest() {
fun syncHistoryBetweenMobileAndDesktopTest() {
signInFxSync()
tapReturnToPreviousApp()
// Let's wait until homescreen is shown to go to three dot menu
@ -70,9 +69,10 @@ class SyncIntegrationTest {
historyAfterSyncIsShown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/330146
// Bookmark item Desktop -> Fenix
@Test
fun checkBookmarkFromDesktopTest() {
fun syncBookmarksTest() {
signInFxSync()
tapReturnToPreviousApp()
homeScreen {
@ -81,9 +81,10 @@ class SyncIntegrationTest {
bookmarkAfterSyncIsShown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243353
@SmokeTest
@Test
fun checkAccountSettings() {
fun manageAccountSettingsTest() {
signInFxSync()
mDevice.waitNotNull(Until.findObjects(By.text("Account")), TestAssetHelper.waitingTime)
@ -104,9 +105,10 @@ class SyncIntegrationTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/466387
// Login item Desktop -> Fenix
@Test
fun checkLoginsFromDesktopTest() {
fun synLoginsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -136,44 +138,6 @@ class SyncIntegrationTest {
}
}
// Bookmark item Fenix -> Desktop
@Test
fun checkBookmarkFromDeviceTest() {
val defaultWebPage = "example.com".toUri()!!
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage) {
}.openThreeDotMenu {
}.bookmarkPage {
}.openThreeDotMenu {
}.openSettings {
}.openTurnOnSyncMenu {
useEmailInsteadButton()
typeEmail()
tapOnContinueButton()
typePassword()
sleep(TestAssetHelper.waitingTimeShort)
tapOnSignIn()
}
}
// History item Fenix -> Desktop
@Test
fun checkHistoryFromDeviceTest() {
val defaultWebPage = "example.com".toUri()!!
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage) {
}.openThreeDotMenu {
}.openSettings {
}.openTurnOnSyncMenu {
useEmailInsteadButton()
typeEmail()
tapOnContinueButton()
typePassword()
sleep(TestAssetHelper.waitingTimeShort)
tapOnSignIn()
}
}
// Useful functions for the tests
fun typeEmail() {
val emailInput = mDevice.findObject(

@ -1,91 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.searchScreen
class AddToHomeScreenTest {
private lateinit var mockWebServer: MockWebServer
@get:Rule
val composeTestRule =
AndroidComposeTestRule(HomeActivityTestRule.withDefaultSettingsOverrides()) { it.activity }
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// Verifies the Add to home screen option in a tab's 3 dot menu
@SmokeTest
@Test
fun mainMenuAddToHomeScreenTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val shortcutTitle = TestHelper.generateRandomString(5)
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
}.openThreeDotMenu {
expandMenu()
}.openAddToHomeScreen {
clickCancelShortcutButton()
}
browserScreen {
}.openThreeDotMenu {
expandMenu()
}.openAddToHomeScreen {
verifyShortcutTextFieldTitle("Test_Page_1")
addShortcutName(shortcutTitle)
clickAddShortcutButton()
clickAddAutomaticallyButton()
}.openHomeScreenShortcut(shortcutTitle) {
verifyUrl(website.url.toString())
verifyTabCounter("1")
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/414970
@Ignore("Failure, more details at: https://bugzilla.mozilla.org/show_bug.cgi?id=1830005")
@SmokeTest
@Test
fun addPrivateBrowsingShortcutFromHomeScreenCFRTest() {
homeScreen {
}.triggerPrivateBrowsingShortcutPrompt {
verifyNoThanksPrivateBrowsingShortcutButton(composeTestRule)
verifyAddPrivateBrowsingShortcutButton(composeTestRule)
clickAddPrivateBrowsingShortcutButton(composeTestRule)
clickAddAutomaticallyButton()
}.openHomeScreenShortcut("Private ${TestHelper.appName}") {}
searchScreen {
verifySearchView()
}.dismissSearchBar {
verifyCommonMythsLink()
}
}
}

@ -18,6 +18,7 @@ import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.ui.robots.autofillScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -25,6 +26,36 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
class AddressAutofillTest {
private lateinit var mockWebServer: MockWebServer
object FirstAddressAutofillDetails {
var navigateToAutofillSettings = true
var isAddressAutofillEnabled = true
var userHasSavedAddress = false
var firstName = "Mozilla"
var middleName = "Fenix"
var lastName = "Firefox"
var streetAddress = "Harrison Street"
var city = "San Francisco"
var state = "Alaska"
var zipCode = "94105"
var country = "United States"
var phoneNumber = "555-5555"
var emailAddress = "foo@bar.com"
}
object SecondAddressAutofillDetails {
var navigateToAutofillSettings = false
var firstName = "Android"
var middleName = "Test"
var lastName = "Name"
var streetAddress = "Fort Street"
var city = "San Jose"
var state = "Arizona"
var zipCode = "95141"
var country = "United States"
var phoneNumber = "777-7777"
var emailAddress = "fuu@bar.org"
}
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
@ -48,22 +79,21 @@ class AddressAutofillTest {
val addressFormPage =
TestAssetHelper.getAddressFormAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
clickAddAddressButton()
autofillScreen {
fillAndSaveAddress(
"Mozilla",
"Fenix",
"Firefox",
"Harrison Street",
"San Francisco",
"Alaska",
"94105",
"United States",
"555-5555",
"foo@bar.com",
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
zipCode = FirstAddressAutofillDetails.zipCode,
country = FirstAddressAutofillDetails.country,
phoneNumber = FirstAddressAutofillDetails.phoneNumber,
emailAddress = FirstAddressAutofillDetails.emailAddress,
)
}.goBack {
}.goBack {
@ -86,22 +116,21 @@ class AddressAutofillTest {
@SmokeTest
@Test
fun deleteSavedAddressTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
clickAddAddressButton()
autofillScreen {
fillAndSaveAddress(
"Mozilla",
"Fenix",
"Firefox",
"Harrison Street",
"San Francisco",
"Alaska",
"94105",
"United States",
"555-5555",
"foo@bar.com",
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
zipCode = FirstAddressAutofillDetails.zipCode,
country = FirstAddressAutofillDetails.country,
phoneNumber = FirstAddressAutofillDetails.phoneNumber,
emailAddress = FirstAddressAutofillDetails.emailAddress,
)
clickManageAddressesButton()
clickSavedAddress("Mozilla")
@ -130,22 +159,21 @@ class AddressAutofillTest {
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836841
@Test
fun verifyEditAddressViewTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
clickAddAddressButton()
autofillScreen {
fillAndSaveAddress(
"Mozilla",
"Fenix",
"Firefox",
"Harrison Street",
"San Francisco",
"Alaska",
"94105",
"United States",
"555-5555",
"foo@bar.com",
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
zipCode = FirstAddressAutofillDetails.zipCode,
country = FirstAddressAutofillDetails.country,
phoneNumber = FirstAddressAutofillDetails.phoneNumber,
emailAddress = FirstAddressAutofillDetails.emailAddress,
)
clickManageAddressesButton()
clickSavedAddress("Mozilla")
@ -159,23 +187,21 @@ class AddressAutofillTest {
val addressFormPage =
TestAssetHelper.getAddressFormAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
verifyAddressAutofillSection(true, false)
clickAddAddressButton()
autofillScreen {
fillAndSaveAddress(
"Mozilla",
"Fenix",
"Firefox",
"Harrison Street",
"San Francisco",
"Alaska",
"94105",
"United States",
"555-5555",
"foo@bar.com",
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
zipCode = FirstAddressAutofillDetails.zipCode,
country = FirstAddressAutofillDetails.country,
phoneNumber = FirstAddressAutofillDetails.phoneNumber,
emailAddress = FirstAddressAutofillDetails.emailAddress,
)
}
@ -207,23 +233,21 @@ class AddressAutofillTest {
val addressFormPage =
TestAssetHelper.getAddressFormAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
verifyAddressAutofillSection(true, false)
clickAddAddressButton()
autofillScreen {
fillAndSaveAddress(
"Mozilla",
"Fenix",
"Firefox",
"Harrison Street",
"San Francisco",
"Alaska",
"94105",
"United States",
"555-5555",
"foo@bar.com",
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
zipCode = FirstAddressAutofillDetails.zipCode,
country = FirstAddressAutofillDetails.country,
phoneNumber = FirstAddressAutofillDetails.phoneNumber,
emailAddress = FirstAddressAutofillDetails.emailAddress,
)
}
@ -247,37 +271,36 @@ class AddressAutofillTest {
val addressFormPage =
TestAssetHelper.getAddressFormAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
verifyAddressAutofillSection(true, false)
clickAddAddressButton()
autofillScreen {
fillAndSaveAddress(
"Mozilla",
"Fenix",
"Firefox",
"Harrison Street",
"San Francisco",
"Alaska",
"94105",
"United States",
"555-5555",
"foo@bar.com",
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
zipCode = FirstAddressAutofillDetails.zipCode,
country = FirstAddressAutofillDetails.country,
phoneNumber = FirstAddressAutofillDetails.phoneNumber,
emailAddress = FirstAddressAutofillDetails.emailAddress,
)
clickManageAddressesButton()
clickAddAddressButton()
fillAndSaveAddress(
"Android",
"Test",
"Name",
"Fort Street",
"San Jose",
"Arizona",
"95141",
"United States",
"777-7777",
"fuu@bar.org",
navigateToAutofillSettings = SecondAddressAutofillDetails.navigateToAutofillSettings,
firstName = SecondAddressAutofillDetails.firstName,
middleName = SecondAddressAutofillDetails.middleName,
lastName = SecondAddressAutofillDetails.lastName,
streetAddress = SecondAddressAutofillDetails.streetAddress,
city = SecondAddressAutofillDetails.city,
state = SecondAddressAutofillDetails.state,
zipCode = SecondAddressAutofillDetails.zipCode,
country = SecondAddressAutofillDetails.country,
phoneNumber = SecondAddressAutofillDetails.phoneNumber,
emailAddress = SecondAddressAutofillDetails.emailAddress,
)
verifyManageAddressesToolbarTitle()
}
@ -311,37 +334,36 @@ class AddressAutofillTest {
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836850
@Test
fun verifySavedAddressCanBeEditedTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
verifyAddressAutofillSection(true, false)
clickAddAddressButton()
autofillScreen {
fillAndSaveAddress(
"Mozilla",
"Fenix",
"Firefox",
"Harrison Street",
"San Francisco",
"Alaska",
"94105",
"United States",
"555-5555",
"foo@bar.com",
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
zipCode = FirstAddressAutofillDetails.zipCode,
country = FirstAddressAutofillDetails.country,
phoneNumber = FirstAddressAutofillDetails.phoneNumber,
emailAddress = FirstAddressAutofillDetails.emailAddress,
)
clickManageAddressesButton()
clickSavedAddress("Mozilla")
fillAndSaveAddress(
"Android",
"Test",
"Name",
"Fort Street",
"San Jose",
"Arizona",
"95141",
"United States",
"777-7777",
"fuu@bar.org",
navigateToAutofillSettings = SecondAddressAutofillDetails.navigateToAutofillSettings,
firstName = SecondAddressAutofillDetails.firstName,
middleName = SecondAddressAutofillDetails.middleName,
lastName = SecondAddressAutofillDetails.lastName,
streetAddress = SecondAddressAutofillDetails.streetAddress,
city = SecondAddressAutofillDetails.city,
state = SecondAddressAutofillDetails.state,
zipCode = SecondAddressAutofillDetails.zipCode,
country = SecondAddressAutofillDetails.country,
phoneNumber = SecondAddressAutofillDetails.phoneNumber,
emailAddress = SecondAddressAutofillDetails.emailAddress,
)
verifyManageAddressesToolbarTitle()
}
@ -370,22 +392,21 @@ class AddressAutofillTest {
val addressFormPage =
TestAssetHelper.getAddressFormAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
clickAddAddressButton()
autofillScreen {
fillAndSaveAddress(
"Mozilla",
"Fenix",
"Firefox",
"Harrison Street",
"San Francisco",
"Alaska",
"94105",
"United States",
"555-5555",
"foo@bar.com",
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
zipCode = FirstAddressAutofillDetails.zipCode,
country = FirstAddressAutofillDetails.country,
phoneNumber = FirstAddressAutofillDetails.phoneNumber,
emailAddress = FirstAddressAutofillDetails.emailAddress,
)
}
@ -410,23 +431,21 @@ class AddressAutofillTest {
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836838
@Test
fun verifyAutofillAddressSectionTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
verifyAddressAutofillSection(true, false)
clickAddAddressButton()
autofillScreen {
fillAndSaveAddress(
"Mozilla",
"Fenix",
"Firefox",
"Harrison Street",
"San Francisco",
"Alaska",
"94105",
"United States",
"555-5555",
"foo@bar.com",
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
zipCode = FirstAddressAutofillDetails.zipCode,
country = FirstAddressAutofillDetails.country,
phoneNumber = FirstAddressAutofillDetails.phoneNumber,
emailAddress = FirstAddressAutofillDetails.emailAddress,
)
verifyAddressAutofillSection(true, true)
clickManageAddressesButton()

@ -22,6 +22,7 @@ import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.bookmarkStorage
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MockBrowserDataHelper.createBookmarkItem
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
@ -30,7 +31,6 @@ import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.ui.robots.bookmarksMenu
import org.mozilla.fenix.ui.robots.browserScreen

@ -13,12 +13,12 @@ import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.setNetworkEnabled
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.navigationToolbar

@ -20,6 +20,7 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.bookmarkStorage
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.RetryTestRule
@ -27,7 +28,6 @@ import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.ui.robots.bookmarksMenu
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
@ -78,6 +78,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/522919
@Test
fun verifyEmptyBookmarksMenuTest() {
homeScreen {
@ -101,6 +102,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/522920
@Test
fun cancelCreateBookmarkFolderTest() {
homeScreen {
@ -114,6 +116,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2299619
@Test
fun cancelingChangesInEditModeAreNotSavedTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -138,6 +141,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325633
@SmokeTest
@Test
fun editBookmarksNameAndUrlTest() {
@ -165,6 +169,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/341696
@Test
fun copyBookmarkURLTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -191,8 +196,9 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325634
@Test
fun threeDotMenuShareBookmarkTest() {
fun shareBookmarkTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
@ -211,6 +217,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325636
@Test
fun openBookmarkInNewTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -229,6 +236,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1919261
@Test
fun verifyOpenAllInNewTabsOptionTest() {
val webPages = listOf(
@ -271,6 +279,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1919262
@Test
fun verifyOpenAllInPrivateTabsTest() {
val webPages = listOf(
@ -306,6 +315,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325637
@Test
fun openBookmarkInPrivateTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -324,6 +334,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325635
@Test
fun deleteBookmarkTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -351,6 +362,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2300275
@Test
fun bookmarksMultiSelectionToolbarItemsTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -376,6 +388,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2300276
@SmokeTest
@Test
fun openMultipleSelectedBookmarksInANewTabTest() {
@ -406,6 +419,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2300277
@Test
fun openMultipleSelectedBookmarksInPrivateTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -429,6 +443,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325644
@SmokeTest
@Test
fun deleteMultipleSelectedBookmarksTest() {
@ -476,8 +491,9 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2301355
@Test
fun multipleSelectionShareButtonTest() {
fun shareMultipleSelectedBookmarksTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
@ -500,6 +516,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325639
@Test
fun createBookmarkFolderTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -524,6 +541,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325645
@Test
fun navigateBookmarksFoldersTest() {
homeScreen {
@ -547,8 +565,9 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/374855
@Test
fun cantSelectDesktopFoldersTest() {
fun cantSelectDefaultFoldersTest() {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
@ -561,6 +580,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2299703
@Test
fun deleteBookmarkInEditModeTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -583,6 +603,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715710
@Test
fun verifySearchBookmarksViewTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -654,6 +675,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715711
@Test
fun verifyVoiceSearchInBookmarksTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -707,6 +729,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325642
// Verifies that deleting a Bookmarks folder also removes the item from inside it.
@SmokeTest
@Test

@ -65,6 +65,7 @@ class ComposeCollectionTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/353823
@SmokeTest
@Test
fun createFirstCollectionUsingHomeScreenButtonTest() {
@ -97,6 +98,7 @@ class ComposeCollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343422
@SmokeTest
@Test
fun verifyExpandedCollectionItemsTest() {
@ -147,6 +149,7 @@ class ComposeCollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343425
@SmokeTest
@Test
fun openAllTabsFromACollectionTest() {
@ -181,6 +184,7 @@ class ComposeCollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343426
@SmokeTest
@Test
fun shareAllTabsFromACollectionTest() {
@ -208,6 +212,7 @@ class ComposeCollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343428
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@SmokeTest
@ -248,6 +253,7 @@ class ComposeCollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2319453
// open a webpage, and add currently opened tab to existing collection
@Test
fun saveTabToExistingCollectionFromMainMenuTest() {
@ -276,8 +282,9 @@ class ComposeCollectionTest {
}
}
// Testrail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343423
@Test
fun verifyAddTabButtonOfCollectionMenu() {
fun saveTabToExistingCollectionUsingTheAddTabButtonTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
val secondWebPage = getGenericAsset(mockWebServer, 2)
@ -303,6 +310,7 @@ class ComposeCollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343424
@Test
fun renameCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
@ -325,6 +333,7 @@ class ComposeCollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/991248
@Test
fun createCollectionUsingSelectTabsButtonTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
@ -347,6 +356,7 @@ class ComposeCollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2319455
@Test
fun removeTabFromCollectionUsingTheCloseButtonTest() {
val webPage = getGenericAsset(mockWebServer, 1)
@ -378,6 +388,7 @@ class ComposeCollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343427
@Test
fun removeTabFromCollectionUsingSwipeLeftActionTest() {
val testPage = getGenericAsset(mockWebServer, 1)
@ -410,6 +421,7 @@ class ComposeCollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/991278
@Test
fun removeTabFromCollectionUsingSwipeRightActionTest() {
val testPage = getGenericAsset(mockWebServer, 1)
@ -442,6 +454,7 @@ class ComposeCollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/991276
@Test
fun createCollectionByLongPressingOpenTabsTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
@ -474,6 +487,7 @@ class ComposeCollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/344897
@Test
fun navigateBackInCollectionFlowTest() {
val webPage = getGenericAsset(mockWebServer, 1)

@ -15,13 +15,13 @@ import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.Constants
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.ui.robots.clickContextMenuItem
import org.mozilla.fenix.ui.robots.clickPageObject
@ -75,6 +75,7 @@ class ComposeContextMenusTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243837
@Test
fun verifyOpenLinkNewTabContextMenuOptionTest() {
val pageLinks =
@ -98,6 +99,7 @@ class ComposeContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/244655
@Test
fun verifyOpenLinkInNewPrivateTabContextMenuOptionTest() {
val pageLinks =
@ -120,6 +122,7 @@ class ComposeContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243832
@Test
fun verifyCopyLinkContextMenuOptionTest() {
val pageLinks =
@ -140,6 +143,7 @@ class ComposeContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243838
@Test
fun verifyShareLinkContextMenuOptionTest() {
val pageLinks =
@ -159,6 +163,7 @@ class ComposeContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243833
@Test
fun verifyOpenImageNewTabContextMenuOptionTest() {
val pageLinks =
@ -178,6 +183,7 @@ class ComposeContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243834
@Test
fun verifyCopyImageLocationContextMenuOptionTest() {
val pageLinks =
@ -198,6 +204,7 @@ class ComposeContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243835
@Test
fun verifySaveImageContextMenuOptionTest() {
val pageLinks =
@ -221,6 +228,7 @@ class ComposeContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/352050
@Test
fun verifyContextMenuLinkVariationsTest() {
val pageLinks =
@ -244,6 +252,7 @@ class ComposeContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2333840
@Test
fun verifyPDFContextMenuLinkVariationsTest() {
val genericURL =
@ -264,6 +273,7 @@ class ComposeContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/832094
@Test
fun verifyOpenLinkInAppContextMenuOptionTest() {
val defaultWebPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)

@ -22,12 +22,12 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.historyMenu
import org.mozilla.fenix.ui.robots.homeScreen
@ -74,6 +74,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243285
@Test
fun verifyEmptyHistoryMenuTest() {
homeScreen {
@ -85,6 +86,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2302742
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@SmokeTest
@ -110,6 +112,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243288
@Test
fun deleteHistoryItemTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -130,6 +133,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1848881
@SmokeTest
@Test
fun deleteAllHistoryTest() {
@ -154,6 +158,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/339690
@SmokeTest
@Test
fun historyMultiSelectionToolbarItemsTest() {
@ -182,6 +187,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/339696
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1807268")
@Test
fun openMultipleSelectedHistoryItemsInANewTabTest() {
@ -212,6 +218,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/346098
@Test
fun openMultipleSelectedHistoryItemsInPrivateTabTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -237,6 +244,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/346099
@Test
fun deleteMultipleSelectedHistoryItemsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -271,6 +279,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/339701
@Test
fun shareMultipleSelectedHistoryItemsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -297,6 +306,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715627
@Test
fun verifySearchHistoryViewTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -339,6 +349,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715631
@Test
fun verifyVoiceSearchInHistoryTest() {
homeScreen {
@ -351,6 +362,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715632
@Test
fun verifySearchForHistoryItemsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -376,6 +388,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715634
@Test
fun verifyDeletedHistoryItemsCanNotBeSearchedTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -418,6 +431,7 @@ class ComposeHistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903590
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@SmokeTest

@ -146,22 +146,6 @@ class ComposeHomeScreenTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1569867
@Test
fun verifyJumpBackInContextualHintTest() {
activityTestRule.activityRule.applySettingsExceptions {
it.isJumpBackInCFREnabled = true
}
val genericPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericPage.url) {
}.goToHomescreen {
verifyJumpBackInMessage(activityTestRule)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1569839
@Test
fun verifyCustomizeHomepageButtonTest() {

@ -139,7 +139,7 @@ class ComposeMediaNotificationTest {
mDevice.pressBack()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903595
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903595
@Test
fun mediaSystemNotificationInPrivateModeTest() {
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)

@ -14,9 +14,9 @@ import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.ui.robots.navigationToolbar
import java.util.Locale
@ -56,6 +56,7 @@ class ComposeNavigationToolbarTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/987326
// Swipes the nav bar left/right to switch between tabs
@SmokeTest
@Test
@ -75,6 +76,7 @@ class ComposeNavigationToolbarTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/987327
// Because it requires changing system prefs, this test will run only on Debug builds
@Test
fun swipeToSwitchTabInRTLTest() {

@ -17,6 +17,10 @@ import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertNativeAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.denyPermission
import org.mozilla.fenix.helpers.AppAndSystemHelper.grantSystemPermission
import org.mozilla.fenix.helpers.AppAndSystemHelper.verifyKeyboardVisibility
import org.mozilla.fenix.helpers.Constants
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MatcherHelper
@ -27,7 +31,6 @@ import org.mozilla.fenix.helpers.SearchDispatcher
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.verifyKeyboardVisibility
import org.mozilla.fenix.ui.robots.clickContextMenuItem
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -61,7 +64,6 @@ class ComposeSearchTest {
isRecentTabsFeatureEnabled = false,
isTCPCFREnabled = false,
isWallpaperOnboardingEnabled = false,
isCookieBannerReductionDialogEnabled = false,
tabsTrayRewriteEnabled = true,
),
) { it.activity }
@ -79,13 +81,14 @@ class ComposeSearchTest {
searchMockServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154189
@Test
fun verifySearchBarItemsTest() {
navigationToolbar {
verifyDefaultSearchEngine("Google")
verifySearchBarPlaceholder("Search or enter address")
}.clickUrlbar {
TestHelper.verifyKeyboardVisibility(isExpectedToBeVisible = true)
verifyKeyboardVisibility(isExpectedToBeVisible = true)
verifyScanButtonVisibility(visible = true)
verifyVoiceSearchButtonVisibility(enabled = true)
verifySearchBarPlaceholder("Search or enter address")
@ -95,6 +98,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154190
@Test
fun verifySearchSelectorMenuItemsTest() {
homeScreen {
@ -109,6 +113,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154194
@Test
fun verifySearchPlaceholderForGeneralDefaultSearchEnginesTest() {
generalEnginesList.forEach {
@ -126,6 +131,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154195
@Test
fun verifySearchPlaceholderForNotDefaultGeneralSearchEnginesTest() {
val generalEnginesList = listOf("DuckDuckGo", "Bing")
@ -140,6 +146,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154196
@Test
fun verifySearchPlaceholderForTopicSpecificSearchEnginesTest() {
val topicEnginesList = listOf("Amazon.com", "Wikipedia", "eBay")
@ -154,6 +161,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1059459
@SmokeTest
@Test
fun verifyQRScanningCameraAccessDialogTest() {
@ -163,7 +171,7 @@ class ComposeSearchTest {
homeScreen {
}.openSearch {
clickScanButton()
TestHelper.denyPermission()
denyPermission()
clickScanButton()
clickDismissPermissionRequiredDialog()
}
@ -171,10 +179,11 @@ class ComposeSearchTest {
}.openSearch {
clickScanButton()
clickGoToPermissionsSettings()
TestHelper.assertNativeAppOpens(Constants.PackageName.ANDROID_SETTINGS)
assertNativeAppOpens(Constants.PackageName.ANDROID_SETTINGS)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/235397
@SmokeTest
@Test
fun scanQRCodeToOpenAWebpageTest() {
@ -184,11 +193,12 @@ class ComposeSearchTest {
homeScreen {
}.openSearch {
clickScanButton()
TestHelper.grantSystemPermission()
grantSystemPermission()
verifyScannerOpen()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154191
@Test
fun verifyScanButtonAvailableOnlyForGeneralSearchEnginesTest() {
generalEnginesList.forEach {
@ -210,6 +220,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/235395
// Verifies a temporary change of search engine from the Search shortcut menu
@SmokeTest
@Test
@ -229,6 +240,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/233589
@Test
fun defaultSearchEnginesCanBeSetFromSearchSelectorMenuTest() {
searchScreen {
@ -246,6 +258,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/522918
@Test
fun verifyClearSearchButtonTest() {
homeScreen {
@ -256,6 +269,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1623441
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@SmokeTest
@Test
@ -284,6 +298,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1592229
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun verifyAPageIsAddedToASearchGroupOnlyOnceTest() {
@ -329,6 +344,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1591782
@Ignore("Failing due to known bug, see https://github.com/mozilla-mobile/fenix/issues/23818")
@Test
fun searchGroupIsGeneratedWhenNavigatingInTheSameTabTest() {
@ -352,6 +368,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1591781
@SmokeTest
@Test
fun searchGroupIsNotGeneratedForLinksOpenedInPrivateTabsTest() {
@ -383,6 +400,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1592269
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@SmokeTest
@Test
@ -425,6 +443,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1592242
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun deleteSearchGroupFromHomeScreenTest() {
@ -465,6 +484,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1592235
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun openAPageFromHomeScreenSearchGroupTest() {
@ -513,6 +533,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1592238
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun shareAPageFromHomeScreenSearchGroupTest() {
@ -551,6 +572,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1232633
// Default search code for Google-US
@Test
fun defaultSearchCodeGoogleUS() {
@ -571,6 +593,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1232637
// Default search code for Bing-US
@Test
fun defaultSearchCodeBingUS() {
@ -600,6 +623,7 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1232638
// Default search code for DuckDuckGo-US
@Test
fun defaultSearchCodeDuckDuckGoUS() {

@ -17,17 +17,18 @@ import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.clearDownloadsFolder
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestAssetHelper.getStorageTestAsset
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.deleteDownloadedFileOnStorage
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.setNetworkEnabled
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.downloadRobot
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -65,8 +66,12 @@ class ComposeSettingsDeleteBrowsingDataOnQuitTest {
@After
fun tearDown() {
mockWebServer.shutdown()
// Check and clear the downloads folder
clearDownloadsFolder()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416048
@Test
fun deleteBrowsingDataOnQuitSettingTest() {
homeScreen {
@ -95,6 +100,7 @@ class ComposeSettingsDeleteBrowsingDataOnQuitTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416049
@Test
fun deleteOpenTabsOnQuitTest() {
val testPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -119,6 +125,7 @@ class ComposeSettingsDeleteBrowsingDataOnQuitTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416050
@Test
fun deleteBrowsingHistoryOnQuitTest() {
val genericPage =
@ -182,6 +189,7 @@ class ComposeSettingsDeleteBrowsingDataOnQuitTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1243096
@SmokeTest
@Test
fun deleteDownloadsOnQuitTest() {
@ -194,13 +202,10 @@ class ComposeSettingsDeleteBrowsingDataOnQuitTest {
clickDeleteBrowsingOnQuitButtonSwitch()
exitMenu()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
}.clickDownloadLink("smallZip.zip") {
verifyDownloadPrompt("smallZip.zip")
}.clickDownload {
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "smallZip.zip")
verifyDownloadCompleteNotificationPopup()
}.closeCompletedDownloadPrompt {
}.closeDownloadPrompt {
}.goToHomescreen {
}.openThreeDotMenu {
clickQuit()
@ -212,9 +217,9 @@ class ComposeSettingsDeleteBrowsingDataOnQuitTest {
}.openDownloadsManager {
verifyEmptyDownloadsList()
}
deleteDownloadedFileOnStorage("smallZip.zip")
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416053
@SmokeTest
@Test
fun deleteSitePermissionsOnQuitTest() {
@ -250,9 +255,10 @@ class ComposeSettingsDeleteBrowsingDataOnQuitTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416052
@Test
fun deleteCachedFilesOnQuitTest() {
val pocketTopArticles = TestHelper.getStringResource(R.string.pocket_pinned_top_articles)
val pocketTopArticles = getStringResource(R.string.pocket_pinned_top_articles)
homeScreen {
}.openThreeDotMenu {

@ -13,15 +13,15 @@ import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestAssetHelper.getStorageTestAsset
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.setNetworkEnabled
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -58,6 +58,7 @@ class ComposeSettingsDeleteBrowsingDataTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/937561
@Test
fun deleteBrowsingDataOptionStatesTest() {
homeScreen {
@ -116,6 +117,7 @@ class ComposeSettingsDeleteBrowsingDataTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/517811
@Test
fun deleteOpenTabsBrowsingDataWithNoOpenTabsTest() {
homeScreen {
@ -133,6 +135,7 @@ class ComposeSettingsDeleteBrowsingDataTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/353531
@SmokeTest
@Test
fun deleteOpenTabsBrowsingDataTest() {
@ -165,6 +168,7 @@ class ComposeSettingsDeleteBrowsingDataTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/378864
@SmokeTest
@Test
fun deleteBrowsingHistoryTest() {
@ -195,6 +199,7 @@ class ComposeSettingsDeleteBrowsingDataTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416041
@SmokeTest
@Test
fun deleteCookiesAndSiteDataTest() {
@ -233,6 +238,7 @@ class ComposeSettingsDeleteBrowsingDataTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416042
@SmokeTest
@Test
fun deleteCachedFilesTest() {

@ -25,7 +25,6 @@ import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.closeApp
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.verifyKeyboardVisibility
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
@ -86,7 +85,7 @@ class ComposeTabbedBrowsingTest {
mockWebServer.shutdown()
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903599
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903599
@Test
fun closeAllTabsTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -118,9 +117,9 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903604
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2349580
@Test
fun closingTabsMethodsTest() {
fun closingTabsTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -133,36 +132,43 @@ class ComposeTabbedBrowsingTest {
}
browserScreen {
verifyTabCounter("1")
}.openComposeTabDrawer(composeTestRule) {
closeTab()
}
homeScreen {
verifyTabCounter("0")
}.openNavigationToolbar {
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903604
@Test
fun swipeToCloseTabsTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
waitForPageToLoad()
}.openComposeTabDrawer(composeTestRule) {
verifyExistingOpenTabs("Test_Page_1")
swipeTabRight("Test_Page_1")
verifySnackBarText("Tab closed")
}
homeScreen {
verifyTabCounter("0")
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
waitForPageToLoad()
}.openComposeTabDrawer(composeTestRule) {
verifyExistingOpenTabs("Test_Page_1")
swipeTabLeft("Test_Page_1")
verifySnackBarText("Tab closed")
}
homeScreen {
verifyTabCounter("0")
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903591
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903591
@Test
fun closingPrivateTabsMethodsTest() {
fun closingPrivateTabsTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen { }.togglePrivateBrowsingMode()
homeScreen { }.togglePrivateBrowsingMode(switchPBModeOn = true)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openComposeTabDrawer(composeTestRule) {
@ -173,33 +179,10 @@ class ComposeTabbedBrowsingTest {
}
browserScreen {
verifyTabCounter("1")
}.openComposeTabDrawer(composeTestRule) {
closeTab()
}
homeScreen {
verifyTabCounter("0")
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openComposeTabDrawer(composeTestRule) {
verifyExistingOpenTabs("Test_Page_1")
swipeTabRight("Test_Page_1")
verifySnackBarText("Private tab closed")
}
homeScreen {
verifyTabCounter("0")
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openComposeTabDrawer(composeTestRule) {
verifyExistingOpenTabs("Test_Page_1")
swipeTabLeft("Test_Page_1")
verifySnackBarText("Private tab closed")
}
homeScreen {
verifyTabCounter("0")
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903606
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903606
@SmokeTest
@Test
fun tabMediaControlButtonTest() {
@ -240,6 +223,7 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903602
@Test
fun verifyTabTrayNotShowingStateHalfExpanded() {
homeScreen {
@ -263,7 +247,7 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903600
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903600
@Test
fun verifyEmptyTabTray() {
homeScreen {
@ -280,7 +264,7 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903585
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903585
@Test
fun verifyEmptyPrivateTabsTrayTest() {
homeScreen {
@ -298,7 +282,7 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903601
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903601
@Test
fun verifyTabsTrayWithOpenTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -322,7 +306,7 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903587
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903587
@SmokeTest
@Test
fun verifyPrivateTabsTrayWithOpenTabTest() {
@ -347,78 +331,133 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/927314
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/927314
@Test
fun tabsCounterShortcutMenuTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
fun tabsCounterShortcutMenuCloseTabTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
}.enterURLAndEnterToBrowser(firstWebPage.url) {
waitForPageToLoad()
}.goToHomescreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(secondWebPage.url) {
waitForPageToLoad()
}
navigationToolbar {
}.openTabButtonShortcutsMenu {
verifyTabButtonShortcutMenuItems()
}.closeTabFromShortcutsMenu {
browserScreen {
verifyTabCounter("1")
verifyPageContent(firstWebPage.content)
}
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2343663
@Test
fun tabsCounterShortcutMenuNewPrivateTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewPrivateTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
}.dismissSearchBar {
verifyPrivateBrowsingHomeScreenItems()
verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = true)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2343662
@Test
fun tabsCounterShortcutMenuNewTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
}.dismissSearchBar {
verifyHomeWordmark()
verifyNavigationToolbar()
verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = false)
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/927314
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/927315
@Test
fun privateTabsCounterShortcutMenuTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
fun privateTabsCounterShortcutMenuCloseTabTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
homeScreen {}.togglePrivateBrowsingMode()
homeScreen {}.togglePrivateBrowsingMode(switchPBModeOn = true)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
}.enterURLAndEnterToBrowser(firstWebPage.url) {
waitForPageToLoad()
}.goToHomescreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(secondWebPage.url) {
waitForPageToLoad()
}
navigationToolbar {
}.openTabButtonShortcutsMenu {
verifyTabButtonShortcutMenuItems()
}.closeTabFromShortcutsMenu {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
browserScreen {
verifyTabCounter("1")
verifyPageContent(firstWebPage.content)
}
}.openTabButtonShortcutsMenu {
}.closeTabFromShortcutsMenu {
homeScreen {
verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = true)
}
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2344199
@Test
fun privateTabsCounterShortcutMenuNewPrivateTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {}.togglePrivateBrowsingMode(switchPBModeOn = true)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
waitForPageToLoad()
}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewPrivateTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
}.dismissSearchBar {
verifyCommonMythsLink()
verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = true)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2344198
@Test
fun privateTabsCounterShortcutMenuNewTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {}.togglePrivateBrowsingMode(switchPBModeOn = true)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
verifyPageContent(defaultWebPage.content)
}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
verifySearchToolbar(isDisplayed = true)
}.dismissSearchBar {
// Verify normal browsing homescreen
verifyExistingTopSitesList()
verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = false)
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/1046683
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1046683
@Test
fun verifySyncedTabsWhenUserIsNotSignedInTest() {
navigationToolbar {
@ -432,7 +471,7 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903598
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903598
@SmokeTest
@Test
fun shareTabsFromTabsTrayTest() {

@ -15,11 +15,11 @@ import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.DataGenerationHelper.generateRandomString
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.generateRandomString
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.waitUntilSnackbarGone
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreenWithComposeTopSites
@ -60,6 +60,7 @@ class ComposeTopSitesTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/532598
@SmokeTest
@Test
fun addAWebsiteAsATopSiteTest() {
@ -78,6 +79,7 @@ class ComposeTopSitesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/532599
@Test
fun openTopSiteInANewTabTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
@ -105,6 +107,7 @@ class ComposeTopSitesTest {
mDevice.pressBack()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/532600
@Test
fun openTopSiteInANewPrivateTabTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
@ -126,6 +129,7 @@ class ComposeTopSitesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1110321
@Test
fun renameATopSiteTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
@ -150,6 +154,7 @@ class ComposeTopSitesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/532601
@Test
fun removeTopSiteUsingMenuButtonTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
@ -176,6 +181,7 @@ class ComposeTopSitesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2323641
@Test
fun removeTopSiteFromMainMenuTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
@ -199,6 +205,7 @@ class ComposeTopSitesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/561582
// Expected for en-us defaults
@Test
fun verifyENLocalesDefaultTopSitesListTest() {
@ -211,6 +218,7 @@ class ComposeTopSitesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1050642
@SmokeTest
@Test
fun addAndRemoveMostViewedTopSiteTest() {

@ -14,13 +14,13 @@ import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.Constants.PackageName.YOUTUBE_APP
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.ui.robots.clickContextMenuItem
import org.mozilla.fenix.ui.robots.clickPageObject

@ -1,72 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
class CookieBannerReductionTest {
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1980504
// Bug causing flakiness https://bugzilla.mozilla.org/show_bug.cgi?id=1807440
@Ignore("Disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1852803")
@SmokeTest
@Test
fun verifyCookieBannerReductionFunctionalityTest() {
val webSite = "startsiden.no"
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(webSite.toUri()) {
waitForPageToLoad()
verifyCookieBannerExists(exists = true)
}.openThreeDotMenu {
}.openSettings {
verifySettingsOptionSummary("Cookie banner reduction", "Off")
}.openCookieBannerReductionSubMenu {
verifyCookieBannerView(isCookieBannerReductionChecked = false)
clickCookieBannerReductionToggle()
verifyCheckedCookieBannerReductionToggle(isCookieBannerReductionChecked = true)
}.goBack {
verifySettingsOptionSummary("Cookie banner reduction", "On")
}
exitMenu()
browserScreen {
verifyCookieBannerExists(exists = false)
}
restartApp(activityTestRule)
browserScreen {
verifyCookieBannerExists(exists = false)
}.openThreeDotMenu {
}.openSettings {
}.openCookieBannerReductionSubMenu {
clickCookieBannerReductionToggle()
verifyCheckedCookieBannerReductionToggle(false)
}
exitMenu()
browserScreen {
waitForPageToLoad()
}.openThreeDotMenu {
}.refreshPage {
verifyCookieBannerExists(exists = false)
}
}
}

@ -16,10 +16,10 @@ import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen

@ -12,14 +12,14 @@ import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.bringAppToForeground
import org.mozilla.fenix.helpers.AppAndSystemHelper.putAppToBackground
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.bringAppToForeground
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.putAppToBackground
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -369,6 +369,7 @@ class CreditCardAutofillTest {
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1512794
@Ignore("Failing, see https://bugzilla.mozilla.org/show_bug.cgi?id=1853625")
@Test
fun verifyMultipleCreditCardsCanBeAddedTest() {
val creditCardFormPage = TestAssetHelper.getCreditCardFormAsset(mockWebServer)

@ -19,14 +19,14 @@ import org.junit.Test
import org.mozilla.fenix.IntentReceiverActivity
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.openAppFromExternalLink
import org.mozilla.fenix.helpers.DataGenerationHelper.createCustomTabIntent
import org.mozilla.fenix.helpers.FeatureSettingsHelperDelegate
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.createCustomTabIntent
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.openAppFromExternalLink
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.customTabScreen

@ -5,13 +5,15 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import org.junit.After
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AppAndSystemHelper.clearDownloadsFolder
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.downloadRobot
/**
* Test for verifying downloading a list of different file types:
@ -28,6 +30,12 @@ class DownloadFileTypesTest(fileName: String) {
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
@After
fun tearDown() {
// Check and clear the downloads folder
clearDownloadsFolder()
}
companion object {
// Creating test data. The test will take each file name as a parameter and run it individually.
@JvmStatic
@ -45,17 +53,14 @@ class DownloadFileTypesTest(fileName: String) {
)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/251028&group_by=cases:section_id&group_id=31659&group_order=asc
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/251028
@SmokeTest
@Test
fun allFilesAppearInDownloadsMenuTest() {
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = downloadFile)
verifyDownloadCompleteNotificationPopup()
}.closeCompletedDownloadPrompt {
}.closeDownloadPrompt {
}.openThreeDotMenu {
}.openDownloadsManager {
waitForDownloadsListToExist()

@ -13,17 +13,18 @@ import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.clearDownloadsFolder
import org.mozilla.fenix.helpers.AppAndSystemHelper.deleteDownloadedFileOnStorage
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_APPS_PHOTOS
import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_DOCS
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.deleteDownloadedFileOnStorage
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.setNetworkEnabled
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.downloadRobot
@ -72,63 +73,45 @@ class DownloadTest {
mockWebServer.shutdown()
setNetworkEnabled(enabled = true)
// Check and clear the downloads folder
clearDownloadsFolder()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243844
@Test
fun verifyTheDownloadPromptsTest() {
downloadFile = "web_icon.png"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "web_icon.png")
verifyDownloadCompleteNotificationPopup()
}.clickOpen("image/png") {}
downloadRobot {
verifyPhotosAppOpens()
}
mDevice.pressBack()
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2299405
@Test
fun verifyTheDownloadFailedNotificationsTest() {
downloadFile = "1GB.zip"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "1GB.zip")
setNetworkEnabled(enabled = false)
verifyDownloadFailedPrompt(downloadFile)
verifyDownloadFailedPrompt("1GB.zip")
setNetworkEnabled(enabled = true)
clickTryAgainButton()
}
mDevice.openNotification()
notificationShade {
verifySystemNotificationDoesNotExist("Download failed")
verifySystemNotificationExists(downloadFile)
verifySystemNotificationExists("1GB.zip")
}.closeNotificationTray {}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2298616
@Test
fun verifyDownloadCompleteNotificationTest() {
downloadFile = "web_icon.png"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "web_icon.png")
verifyDownloadCompleteNotificationPopup()
}
mDevice.openNotification()
@ -146,7 +129,6 @@ class DownloadTest {
)
verifySystemNotificationDoesNotExist("Firefox Fenix")
}.closeNotificationTray {}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/451563
@ -154,19 +136,9 @@ class DownloadTest {
@SmokeTest
@Test
fun pauseResumeCancelDownloadTest() {
// Clear the "Firefox Fenix default browser notification"
notificationShade {
cancelAllShownNotifications()
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "1GB.zip")
}
downloadFile = "1GB.zip"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {}
mDevice.openNotification()
notificationShade {
verifySystemNotificationExists("Firefox Fenix")
@ -175,7 +147,7 @@ class DownloadTest {
verifySystemNotificationExists("Download paused")
clickDownloadNotificationControlButton("RESUME")
clickDownloadNotificationControlButton("CANCEL")
verifySystemNotificationDoesNotExist(downloadFile)
verifySystemNotificationDoesNotExist("1GB.zip")
mDevice.pressBack()
}
browserScreen {
@ -183,79 +155,41 @@ class DownloadTest {
}.openDownloadsManager {
verifyEmptyDownloadsList()
}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2301474
@Test
fun openDownloadedFileFromDownloadsMenuTest() {
downloadFile = "web_icon.png"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "web_icon.png")
verifyDownloadCompleteNotificationPopup()
}
browserScreen {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyDownloadedFileName(downloadFile)
openDownloadedFile(downloadFile)
verifyDownloadedFileName("web_icon.png")
openDownloadedFile("web_icon.png")
verifyPhotosAppOpens()
mDevice.pressBack()
}
deleteDownloadedFileOnStorage(downloadFile)
}
// Save PDF file from the share overlay
@SmokeTest
@Test
fun saveAndOpenPdfTest() {
val genericURL =
TestAssetHelper.getGenericAsset(mockWebServer, 3)
downloadFile = "pdfForm.pdf"
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
clickPageObject(itemWithText("PDF form file"))
}.openThreeDotMenu {
}.clickShareButton {
}.clickSaveAsPDF {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
}.clickOpen("application/pdf") {
assertExternalAppOpens(GOOGLE_DOCS)
}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1114970
@Test
fun deleteDownloadedFileTest() {
downloadFile = "smallZip.zip"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
verifyDownloadedFileName(downloadFile)
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "smallZip.zip")
}
browserScreen {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyDownloadedFileName(downloadFile)
deleteDownloadedItem(downloadFile)
verifyDownloadedFileName("smallZip.zip")
deleteDownloadedItem("smallZip.zip")
clickSnackbarButton("UNDO")
verifyDownloadedFileName(downloadFile)
deleteDownloadedItem(downloadFile)
verifyDownloadedFileName("smallZip.zip")
deleteDownloadedItem("smallZip.zip")
verifyEmptyDownloadsList()
}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2302662
@ -264,14 +198,10 @@ class DownloadTest {
val firstDownloadedFile = "smallZip.zip"
val secondDownloadedFile = "textfile.txt"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(firstDownloadedFile) {
verifyDownloadPrompt(firstDownloadedFile)
}.clickDownload {
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = firstDownloadedFile)
verifyDownloadedFileName(firstDownloadedFile)
}.closeCompletedDownloadPrompt {
}.closeDownloadPrompt {
}.clickDownloadLink(secondDownloadedFile) {
verifyDownloadPrompt(secondDownloadedFile)
}.clickDownload {
@ -295,29 +225,21 @@ class DownloadTest {
clickMultiSelectRemoveButton()
verifyEmptyDownloadsList()
}
deleteDownloadedFileOnStorage(firstDownloadedFile)
deleteDownloadedFileOnStorage(secondDownloadedFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2301537
@Test
fun fileDeletedFromStorageIsDeletedEverywhereTest() {
val downloadFile = "smallZip.zip"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "smallZip.zip")
verifyDownloadCompleteNotificationPopup()
}
browserScreen {
}.openThreeDotMenu {
}.openDownloadsManager {
waitForDownloadsListToExist()
verifyDownloadedFileName(downloadFile)
deleteDownloadedFileOnStorage(downloadFile)
verifyDownloadedFileName("smallZip.zip")
deleteDownloadedFileOnStorage("smallZip.zip")
}.exitDownloadsManagerToBrowser {
}.openThreeDotMenu {
}.openDownloadsManager {
@ -325,39 +247,24 @@ class DownloadTest {
exitMenu()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "smallZip.zip")
verifyDownloadCompleteNotificationPopup()
}
browserScreen {
}.openThreeDotMenu {
}.openDownloadsManager {
waitForDownloadsListToExist()
verifyDownloadedFileName(downloadFile)
verifyDownloadedFileName("smallZip.zip")
}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/457112
@Ignore("Failing: https://bugzilla.mozilla.org/show_bug.cgi?id=1840994")
@Test
fun systemNotificationCantBeDismissedWhileInProgressTest() {
// Clear the "Firefox Fenix default browser notification"
notificationShade {
cancelAllShownNotifications()
}
downloadFile = "1GB.zip"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "1GB.zip")
}
browserScreen {
}.openNotificationShade {
@ -368,31 +275,21 @@ class DownloadTest {
swipeDownloadNotification(direction = "Right", shouldDismissNotification = false)
clickDownloadNotificationControlButton("CANCEL")
}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2299297
@Test
fun notificationCanBeDismissedIfDownloadIsInterruptedTest() {
// Clear the "Firefox Fenix default browser notification"
notificationShade {
cancelAllShownNotifications()
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "1GB.zip")
}
downloadFile = "1GB.zip"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {}
setNetworkEnabled(enabled = false)
browserScreen {
}.openNotificationShade {
verifySystemNotificationExists("Download failed")
expandNotificationMessage()
verifySystemNotificationExists("Download failed")
swipeDownloadNotification("Left", true)
verifySystemNotificationDoesNotExist("Firefox Fenix")
}.closeNotificationTray {}
@ -401,26 +298,16 @@ class DownloadTest {
}.closeDownloadPrompt {
verifyDownloadPromptIsDismissed()
}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1632384
@Test
fun warningWhenClosingPrivateTabsWhileDownloadingTest() {
downloadFile = "1GB.zip"
// Clear the "Firefox Fenix default browser notification"
notificationShade {
cancelAllShownNotifications()
}
homeScreen {
}.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {}
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "1GB.zip")
}
browserScreen {
}.openTabDrawer {
closeTab()
@ -431,28 +318,16 @@ class DownloadTest {
}.openNotificationShade {
verifySystemNotificationExists("Firefox Fenix")
}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2302663
@Test
fun cancelActivePrivateBrowsingDownloadsTest() {
downloadFile = "1GB.zip"
// Clear the "Firefox Fenix default browser notification"
notificationShade {
cancelAllShownNotifications()
}
homeScreen {
}.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {}
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "1GB.zip")
}
browserScreen {
}.openTabDrawer {
closeTab()
@ -463,12 +338,13 @@ class DownloadTest {
}.openNotificationShade {
verifySystemNotificationDoesNotExist("Firefox Fenix")
}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2048448
// Save edited PDF file from the share overlay
@SmokeTest
@Test
fun saveEditedPdfTest() {
fun saveAsPdfFunctionalityTest() {
val genericURL =
TestAssetHelper.getGenericAsset(mockWebServer, 3)
downloadFile = "pdfForm.pdf"
@ -486,6 +362,29 @@ class DownloadTest {
}.clickOpen("application/pdf") {
assertExternalAppOpens(GOOGLE_DOCS)
}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/244125
@Test
fun restartDownloadFromAppNotificationAfterConnectionIsInterruptedTest() {
downloadFile = "1GB.zip"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
setNetworkEnabled(false)
}.clickDownload {
verifyDownloadFailedPrompt(downloadFile)
setNetworkEnabled(true)
clickTryAgainButton()
}
browserScreen {
}.openNotificationShade {
verifySystemNotificationExists("Firefox Fenix")
expandNotificationMessage()
clickDownloadNotificationControlButton("CANCEL")
}
}
}

@ -351,8 +351,6 @@ class EnhancedTrackingProtectionTest {
enhancedTrackingProtection {
}.openEnhancedTrackingProtectionSheet {
}.openDetails {
verifyCrossSiteCookiesBlocked(true)
navigateBackToDetails()
verifyCryptominersBlocked(true)
navigateBackToDetails()
verifyFingerprintersBlocked(true)

@ -22,13 +22,13 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MockBrowserDataHelper
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.historyMenu
import org.mozilla.fenix.ui.robots.homeScreen
@ -466,4 +466,18 @@ class HistoryTest {
verifyEmptyHistoryView()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243287
@Test
fun openHistoryItemTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
}.openHistory {
}.openWebsite(defaultWebPage.url) {
verifyUrl(defaultWebPage.url.toString())
}
}
}

@ -10,6 +10,7 @@ import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
@ -17,8 +18,10 @@ import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.searchScreen
/**
* Tests for verifying the presence of home screen and first-run homescreen elements
@ -166,4 +169,39 @@ class HomeScreenTest {
verifyCustomizeHomepageButton(true)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/414970
@Ignore("Failure, more details at: https://bugzilla.mozilla.org/show_bug.cgi?id=1830005")
@SmokeTest
@Test
fun addPrivateBrowsingShortcutFromHomeScreenCFRTest() {
homeScreen {
}.triggerPrivateBrowsingShortcutPrompt {
verifyNoThanksPrivateBrowsingShortcutButton(activityTestRule)
verifyAddPrivateBrowsingShortcutButton(activityTestRule)
clickAddPrivateBrowsingShortcutButton(activityTestRule)
clickAddAutomaticallyButton()
}.openHomeScreenShortcut("Private ${TestHelper.appName}") {}
searchScreen {
verifySearchView()
}.dismissSearchBar {
verifyCommonMythsLink()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1569867
@Test
fun verifyJumpBackInContextualHintTest() {
activityTestRule.activityRule.applySettingsExceptions {
it.isJumpBackInCFREnabled = true
}
val genericPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericPage.url) {
}.goToHomescreen {
verifyJumpBackInMessage(activityTestRule)
}
}
}

@ -16,12 +16,15 @@ import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertNativeAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertYoutubeAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithCondition
import org.mozilla.fenix.helpers.Constants.PackageName.PRINT_SPOOLER
import org.mozilla.fenix.helpers.DataGenerationHelper.generateRandomString
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.assertYoutubeAppOpens
import org.mozilla.fenix.helpers.TestHelper.runWithCondition
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickContextMenuItem
import org.mozilla.fenix.ui.robots.clickPageObject
@ -260,7 +263,7 @@ class MainMenuTest {
@Test
fun addPageShortcutToHomeScreenTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val shortcutTitle = TestHelper.generateRandomString(5)
val shortcutTitle = generateRandomString(5)
homeScreen {
}.openNavigationToolbar {
@ -351,4 +354,33 @@ class MainMenuTest {
verifyPageContent("REFRESHED")
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2282411
@Test
fun printWebPageFromMainMenuTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.clickPrintButton {
assertNativeAppOpens(PRINT_SPOOLER)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2282408
@Test
fun printWebPageFromShareMenuTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.clickShareButton {
}.clickPrintButton {
assertNativeAppOpens(PRINT_SPOOLER)
}
}
}

@ -0,0 +1,119 @@
package org.mozilla.fenix.ui
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.junit4.ComposeTestRule
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performScrollToIndex
import androidx.compose.ui.unit.dp
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.compose.ext.onShown
private const val ON_SHOWN_ROOT_TAG = "onShownRoot"
private const val ON_SHOWN_SETTLE_TIME_MS = 1000
private const val ON_SHOWN_INDEX = 15
private const val ON_SHOWN_NODE_COUNT = 30
class ModifierTest {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun verifyModifierOnShownWhenScrolledToWithNoSettleTime() {
var onShown = false
composeTestRule.setContent {
ModifierOnShownContent(
settleTime = 0,
onVisible = {
onShown = true
},
)
}
composeTestRule.scrollToOnShownIndex()
assertTrue(onShown)
}
@Test
fun verifyModifierOnShownAfterSettled() {
var onShown = false
composeTestRule.setContent {
ModifierOnShownContent(
onVisible = {
onShown = true
},
)
}
composeTestRule.scrollToOnShownIndex()
assertFalse(onShown)
composeTestRule.waitUntil(ON_SHOWN_SETTLE_TIME_MS + 500L) { onShown }
assertTrue(onShown)
}
@Test
fun verifyModifierOnShownWhenNotVisible() {
val indexToValidate = ON_SHOWN_NODE_COUNT - 1
var onShown = false
composeTestRule.setContent {
ModifierOnShownContent(
indexToValidate = indexToValidate,
settleTime = 0,
onVisible = {
onShown = true
},
)
}
assertFalse(onShown)
}
private fun ComposeTestRule.scrollToOnShownIndex(index: Int = ON_SHOWN_INDEX) {
this.onNodeWithTag(ON_SHOWN_ROOT_TAG)
.performScrollToIndex(index)
}
@Composable
private fun ModifierOnShownContent(
indexToValidate: Int = ON_SHOWN_INDEX,
settleTime: Int = ON_SHOWN_SETTLE_TIME_MS,
onVisible: () -> Unit,
) {
LazyColumn(
modifier = Modifier.testTag(ON_SHOWN_ROOT_TAG),
) {
items(ON_SHOWN_NODE_COUNT) { index ->
val modifier = if (index == indexToValidate) {
Modifier.onShown(
threshold = 1.0f,
settleTime = settleTime,
onVisible = onVisible,
)
} else {
Modifier
}
Text(
text = "Test item $index",
modifier = modifier
.fillMaxWidth()
.height(50.dp),
)
}
}
}
}

@ -14,9 +14,9 @@ import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import java.util.Locale

@ -10,9 +10,9 @@ import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.TestHelper.verifyUrl
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen

@ -0,0 +1,70 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithLauncherIntent
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.ui.robots.homeScreen
class OnboardingTest {
@get:Rule
val activityTestRule =
AndroidComposeTestRule(
HomeActivityIntentTestRule.withDefaultSettingsOverrides(launchActivity = false),
) { it.activity }
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2122321
@Test
fun verifyFirstOnboardingCardItemsTest() {
runWithLauncherIntent(activityTestRule) {
homeScreen {
verifyFirstOnboardingCard(activityTestRule)
}
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2122334
@SmokeTest
@Test
fun verifyFirstOnboardingCardItemsFunctionalityTest() {
runWithLauncherIntent(activityTestRule) {
homeScreen {
clickNotNowOnboardingButton(activityTestRule)
verifySecondOnboardingCard(activityTestRule)
swipeSecondOnboardingCardToRight()
}.clickSetAsDefaultBrowserOnboardingButton(activityTestRule) {
verifyAndroidDefaultAppsMenuAppears()
}.goBackToOnboardingScreen {
verifySecondOnboardingCard(activityTestRule)
}
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2122343
@Test
fun verifySecondOnboardingCardItemsTest() {
runWithLauncherIntent(activityTestRule) {
homeScreen {
clickNotNowOnboardingButton(activityTestRule)
verifySecondOnboardingCard(activityTestRule)
}
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2122344
@SmokeTest
@Test
fun verifySecondOnboardingCardSignInFunctionalityTest() {
runWithLauncherIntent(activityTestRule) {
homeScreen {
clickNotNowOnboardingButton(activityTestRule)
verifySecondOnboardingCard(activityTestRule)
}.clickSignInOnboardingButton(activityTestRule) {
verifyTurnOnSyncMenu()
}
}
}
}

@ -14,6 +14,8 @@ import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.clearDownloadsFolder
import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_DOCS
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper
@ -21,8 +23,6 @@ import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.TestHelper.deleteDownloadedFileOnStorage
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -50,6 +50,9 @@ class PDFViewerTest {
@After
fun tearDown() {
mockWebServer.shutdown()
// Check and clear the downloads folder
clearDownloadsFolder()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2048140
@ -96,7 +99,6 @@ class PDFViewerTest {
}.clickOpen("application/pdf") {
assertExternalAppOpens(GOOGLE_DOCS)
}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2283305

@ -15,10 +15,10 @@ import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.ViewVisibilityIdlingResource
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.navigationToolbar

@ -15,12 +15,12 @@ import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar

@ -21,6 +21,12 @@ import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertNativeAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.denyPermission
import org.mozilla.fenix.helpers.AppAndSystemHelper.grantSystemPermission
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithCondition
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.helpers.AppAndSystemHelper.verifyKeyboardVisibility
import org.mozilla.fenix.helpers.Constants.PackageName.ANDROID_SETTINGS
import org.mozilla.fenix.helpers.Constants.searchEngineCodes
import org.mozilla.fenix.helpers.HomeActivityTestRule
@ -32,17 +38,11 @@ import org.mozilla.fenix.helpers.MockBrowserDataHelper.createTabItem
import org.mozilla.fenix.helpers.MockBrowserDataHelper.setCustomSearchEngine
import org.mozilla.fenix.helpers.SearchDispatcher
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.assertNativeAppOpens
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.denyPermission
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.grantSystemPermission
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.runWithCondition
import org.mozilla.fenix.helpers.TestHelper.verifyKeyboardVisibility
import org.mozilla.fenix.ui.robots.clickContextMenuItem
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -77,7 +77,6 @@ class SearchTest {
isRecentTabsFeatureEnabled = false,
isTCPCFREnabled = false,
isWallpaperOnboardingEnabled = false,
isCookieBannerReductionDialogEnabled = false,
tabsTrayRewriteEnabled = false,
),
) { it.activity }
@ -792,7 +791,7 @@ class SearchTest {
fun verifySearchEnginesFunctionalityUsingRTLLocaleTest() {
val arabicLocale = Locale("ar", "AR")
TestHelper.runWithSystemLocaleChanged(arabicLocale, activityTestRule.activityRule) {
runWithSystemLocaleChanged(arabicLocale, activityTestRule.activityRule) {
homeScreen {
}.openSearch {
verifyTranslatedFocusedNavigationToolbar("ابحث أو أدخِل عنوانا")

@ -13,16 +13,15 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper.getEnhancedTrackingProtectionAsset
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestHelper.waitUntilSnackbarGone
import org.mozilla.fenix.ui.robots.addonsMenu
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
/**
* Tests for verifying the functionality of installing or removing addons
@ -101,8 +100,7 @@ class SettingsAddonsTest {
val addonName = "uBlock Origin"
addonsMenu {
installAddon(addonName)
verifyAddonInstallCompleted(addonName, activityTestRule)
installAddon(addonName, activityTestRule)
closeAddonInstallCompletePrompt()
}.openDetailedMenuForAddon(addonName) {
}.removeAddon(activityTestRule) {
@ -115,25 +113,34 @@ class SettingsAddonsTest {
}
}
// TODO: Harden to dynamically install addons from position
// in list of detected addons on screen instead of hard-coded values.
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/561600
// Installs uBlock add-on and checks that the app doesn't crash while loading pages with trackers
// Installs 2 add-on and checks that the app doesn't crash while navigating the app
@SmokeTest
@Test
fun noCrashWithAddonInstalledTest() {
// setting ETP to Strict mode to test it works with add-ons
activityTestRule.activity.settings().setStrictETP()
val addonName = "uBlock Origin"
val uBlockAddon = "uBlock Origin"
val darkReaderAddon = "Dark Reader"
val trackingProtectionPage = getEnhancedTrackingProtectionAsset(mockWebServer)
addonsMenu {
installAddon(addonName)
verifyAddonInstallCompleted(addonName, activityTestRule)
installAddon(uBlockAddon, activityTestRule)
closeAddonInstallCompletePrompt()
installAddon(darkReaderAddon, activityTestRule)
closeAddonInstallCompletePrompt()
}.goBack {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(trackingProtectionPage.url) {
verifyUrl(trackingProtectionPage.url.toString())
}.goToHomescreen {
}.openTopSiteTabWithTitle("Top Articles") {
}.openThreeDotMenu {
}.openSettings {
verifySettingsView()
}
}
@ -141,22 +148,38 @@ class SettingsAddonsTest {
@SmokeTest
@Test
fun verifyUBlockWorksInPrivateModeTest() {
TestHelper.appContext.settings().shouldShowCookieBannersCFR = false
val addonName = "uBlock Origin"
val genericPage = getGenericAsset(mockWebServer, 1)
addonsMenu {
installAddon(addonName)
verifyAddonInstallCompleted(addonName, activityTestRule)
installAddon(addonName, activityTestRule)
selectAllowInPrivateBrowsing()
closeAddonInstallCompletePrompt()
}.goBack {
}.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(genericPage.url) {
verifyPageContent(genericPage.content)
}.openContextMenuOnSponsoredShortcut("Top Articles") {
}.openTopSiteInPrivateTab {
waitForPageToLoad()
}.openThreeDotMenu {
openAddonsSubList()
verifyAddonAvailableInMainMenu(addonName)
verifyTrackersBlockedByUblock()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/875785
@Test
fun verifyUBlockWorksInNormalModeTest() {
val addonName = "uBlock Origin"
addonsMenu {
installAddon(addonName, activityTestRule)
closeAddonInstallCompletePrompt()
}.goBack {
}.openTopSiteTabWithTitle("Top Articles") {
waitForPageToLoad()
}.openThreeDotMenu {
openAddonsSubList()
verifyTrackersBlockedByUblock()
}
}
}

@ -13,12 +13,14 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertYoutubeAppOpens
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.assertYoutubeAppOpens
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -201,6 +203,7 @@ class SettingsAdvancedTest {
// Assumes Youtube is installed and enabled
@Test
fun privateBrowsingAskBeforeOpeningLinkInAppCancelTest() {
TestHelper.appContext.settings().shouldShowCookieBannersCFR = false
val externalLinksPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
homeScreen {

@ -16,17 +16,18 @@ import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestAssetHelper.getStorageTestAsset
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.deleteDownloadedFileOnStorage
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.setNetworkEnabled
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.downloadRobot
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -58,6 +59,9 @@ class SettingsDeleteBrowsingDataOnQuitTest {
@After
fun tearDown() {
mockWebServer.shutdown()
// Check and clear the downloads folder
AppAndSystemHelper.clearDownloadsFolder()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416048
@ -191,13 +195,10 @@ class SettingsDeleteBrowsingDataOnQuitTest {
clickDeleteBrowsingOnQuitButtonSwitch()
exitMenu()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
}.clickDownloadLink("smallZip.zip") {
verifyDownloadPrompt("smallZip.zip")
}.clickDownload {
downloadRobot {
openPageAndDownloadFile(url = downloadTestPage.toUri(), downloadFile = "smallZip.zip")
verifyDownloadCompleteNotificationPopup()
}.closeCompletedDownloadPrompt {
}.closeDownloadPrompt {
}.goToHomescreen {
}.openThreeDotMenu {
clickQuit()
@ -209,7 +210,6 @@ class SettingsDeleteBrowsingDataOnQuitTest {
}.openDownloadsManager {
verifyEmptyDownloadsList()
}
deleteDownloadedFileOnStorage("smallZip.zip")
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416053
@ -251,7 +251,7 @@ class SettingsDeleteBrowsingDataOnQuitTest {
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416052
@Test
fun deleteCachedFilesOnQuitTest() {
val pocketTopArticles = TestHelper.getStringResource(R.string.pocket_pinned_top_articles)
val pocketTopArticles = getStringResource(R.string.pocket_pinned_top_articles)
homeScreen {
}.openThreeDotMenu {

@ -13,15 +13,15 @@ import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestAssetHelper.getStorageTestAsset
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.setNetworkEnabled
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen

@ -1,100 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.ui
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.ui.robots.homeScreen
/**
* Tests for verifying the main three dot menu options
*
*/
class SettingsDeveloperToolsTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
@get:Rule
val activityTestRule = HomeActivityTestRule()
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// Walks through settings developer tools menu and sub-menus to ensure all items are present
@Test
fun settingsDeveloperToolsItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
verifyRemoteDebuggingButton()
}
}
// DEVELOPER TOOLS
@Ignore("This is a stub test, ignore for now")
@Test
fun turnOnRemoteDebuggingViaUsb() {
// Open terminal
// Verify USB debugging is off
// Open 3dot (main) menu
// Select settings
// Toggle Remote debugging via USB to 'on'
// Open terminal
// Verify USB debugging is on
}
// ABOUT
@Ignore("This is a stub test, ignore for now")
@Test
fun verifyHelpRedirect() {
// Open 3dot (main) menu
// Select settings
// Click on "Help"
// Verify redirect to: https://support.mozilla.org/
}
@Ignore("This is a stub test, ignore for now")
@Test
fun verifyRateOnGooglePlayRedirect() {
// Open 3dot (main) menu
// Select settings
// Click on "Rate on Google Play"
// Verify Android "Open with Google Play Store" sub menu
}
@Ignore("This is a stub test, ignore for now")
@Test
fun verifyAboutFirefoxPreview() {
// Open 3dot (main) menu
// Select settings
// Click on "Verify About Firefox Preview"
// Verify about page contains....
// Build #
// Version #
// "Firefox Preview is produced by Mozilla"
// Day, Date, timestamp
// "Open source libraries we use"
}
}

@ -14,14 +14,14 @@ import org.mozilla.fenix.FenixApplication
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper.getLoremIpsumAsset
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeLong
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.TestHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.ui.robots.checkTextSizeOnWebsite
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.util.FRENCH_LANGUAGE_HEADER

@ -12,11 +12,11 @@ import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.openAppFromExternalLink
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.openAppFromExternalLink
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
@ -103,12 +103,12 @@ class SettingsHomepageTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.goToHomescreen {
verifyRecentlyVisitedSectionIsDisplayed()
verifyRecentlyVisitedSectionIsDisplayed(true)
}.openThreeDotMenu {
}.openCustomizeHome {
clickRecentlyVisited()
}.goBackToHomeScreen {
verifyRecentlyVisitedSectionIsNotDisplayed()
verifyRecentlyVisitedSectionIsDisplayed(false)
}
}
@ -141,12 +141,12 @@ class SettingsHomepageTest {
}.openThreeDotMenu {
}.bookmarkPage {
}.goToHomescreen {
verifyRecentBookmarksSectionIsDisplayed()
verifyRecentBookmarksSectionIsDisplayed(exists = true)
}.openThreeDotMenu {
}.openCustomizeHome {
clickRecentBookmarksButton()
}.goBackToHomeScreen {
verifyRecentBookmarksSectionIsNotDisplayed()
verifyRecentBookmarksSectionIsDisplayed(exists = false)
}
}

@ -55,8 +55,7 @@ class SettingsPrivacyTest {
verifyPrivateBrowsingButton()
verifyHTTPSOnlyModeButton()
verifySettingsOptionSummary("HTTPS-Only Mode", "Off")
verifyCookieBannerReductionButton()
verifySettingsOptionSummary("Cookie banner reduction", "Off")
verifySettingsOptionSummary("Cookie Banner Blocker in private browsing", "")
verifyEnhancedTrackingProtectionButton()
verifySettingsOptionSummary("Enhanced Tracking Protection", "Standard")
verifySitePermissionsButton()

@ -10,9 +10,10 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.openAppFromExternalLink
import org.mozilla.fenix.helpers.DataGenerationHelper.generateRandomString
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.ui.robots.addToHomeScreen
@ -22,7 +23,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
class SettingsPrivateBrowsingTest {
private lateinit var mockWebServer: MockWebServer
private val pageShortcutName = TestHelper.generateRandomString(5)
private val pageShortcutName = generateRandomString(5)
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@ -63,7 +64,7 @@ class SettingsPrivateBrowsingTest {
setOpenLinksInPrivateOn()
TestHelper.openAppFromExternalLink(firstWebPage.url.toString())
openAppFromExternalLink(firstWebPage.url.toString())
browserScreen {
verifyUrl(firstWebPage.url.toString())
@ -75,7 +76,7 @@ class SettingsPrivateBrowsingTest {
setOpenLinksInPrivateOff()
// We need to open a different link, otherwise it will open the same session
TestHelper.openAppFromExternalLink(secondWebPage.url.toString())
openAppFromExternalLink(secondWebPage.url.toString())
browserScreen {
verifyUrl(secondWebPage.url.toString())

@ -14,6 +14,9 @@ import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.helpers.AppAndSystemHelper.setSystemLocale
import org.mozilla.fenix.helpers.DataGenerationHelper.setTextToClipBoard
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MockBrowserDataHelper.addCustomSearchEngine
import org.mozilla.fenix.helpers.MockBrowserDataHelper.createBookmarkItem
@ -23,9 +26,6 @@ import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.helpers.TestHelper.setSystemLocale
import org.mozilla.fenix.helpers.TestHelper.setTextToClipBoard
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.ui.robots.EngineShortcut
import org.mozilla.fenix.ui.robots.homeScreen

@ -18,13 +18,13 @@ import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.grantSystemPermission
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestAssetHelper.getMutedVideoPageAsset
import org.mozilla.fenix.helpers.TestAssetHelper.getVideoPageAsset
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.grantSystemPermission
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen

@ -1,68 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.ui
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
/**
* Tests for verifying the main three dot menu options
*
*/
class SettingsSyncTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
@get:Rule
val activityTestRule = HomeActivityTestRule()
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// Walks through settings sync menu and sub-menus to ensure all items are present
@Ignore("This is a stub test, ignore for now")
@Test
fun settingsSyncItemsTest() {
// SYNC
// Open 3dot (main) menu
// Select settings
// Verify header: "Turn on Sync"
// Verify description: "Sync bookmarks, history, and more with your Firefox Account"
}
// SYNC
@Ignore("This is a stub test, ignore for now")
@Test
fun turnOnSync() {
// Note this requires a test Firefox Account and a desktop
// Open 3dot (main) menu
// Select settings
// Click on "Turn on Sync"
// Open Firefox on laptop and go to https://firefox.com/pair
// Pair with QR code and/or alternate method
// Verify pairing
}
}

@ -20,14 +20,14 @@ import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.grantSystemPermission
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MockLocationUpdatesRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.TestHelper.grantSystemPermission
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.navigationToolbar

@ -15,9 +15,9 @@ import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.Constants.defaultTopSitesList
import org.mozilla.fenix.helpers.DataGenerationHelper.getSponsoredShortcutTitle
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.getSponsoredShortcutTitle
import org.mozilla.fenix.ui.robots.homeScreen
/**

@ -23,7 +23,6 @@ import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.closeApp
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.verifyKeyboardVisibility
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -77,7 +76,7 @@ class TabbedBrowsingTest {
mockWebServer.shutdown()
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903599
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903599
@Test
fun closeAllTabsTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -110,9 +109,9 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903604
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2349580
@Test
fun closingTabsMethodsTest() {
fun closingTabsTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -125,13 +124,17 @@ class TabbedBrowsingTest {
}
browserScreen {
verifyTabCounter("1")
}.openTabDrawer {
closeTab()
}
homeScreen {
verifyTabCounter("0")
}.openNavigationToolbar {
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903604
@Test
fun swipeToCloseTabsTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
waitForPageToLoad()
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
swipeTabRight("Test_Page_1")
@ -141,6 +144,7 @@ class TabbedBrowsingTest {
verifyTabCounter("0")
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
waitForPageToLoad()
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
swipeTabLeft("Test_Page_1")
@ -151,12 +155,12 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903591
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903591
@Test
fun closingPrivateTabsMethodsTest() {
fun closingPrivateTabsTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen { }.togglePrivateBrowsingMode()
homeScreen { }.togglePrivateBrowsingMode(switchPBModeOn = true)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openTabDrawer {
@ -168,33 +172,10 @@ class TabbedBrowsingTest {
}
browserScreen {
verifyTabCounter("1")
}.openTabDrawer {
closeTab()
}
homeScreen {
verifyTabCounter("0")
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
swipeTabRight("Test_Page_1")
verifySnackBarText("Private tab closed")
}
homeScreen {
verifyTabCounter("0")
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
swipeTabLeft("Test_Page_1")
verifySnackBarText("Private tab closed")
}
homeScreen {
verifyTabCounter("0")
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903606
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903606
@SmokeTest
@Test
fun tabMediaControlButtonTest() {
@ -235,7 +216,7 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903598
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903598
@SmokeTest
@Test
fun shareTabsFromTabsTrayTest() {
@ -269,6 +250,7 @@ class TabbedBrowsingTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903602
@Test
fun verifyTabTrayNotShowingStateHalfExpanded() {
navigationToolbar {
@ -292,7 +274,7 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903600
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903600
@Test
fun verifyEmptyTabTray() {
navigationToolbar {
@ -307,7 +289,7 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903585
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903585
@Test
fun verifyEmptyPrivateTabsTrayTest() {
navigationToolbar {
@ -323,7 +305,7 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903601
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903601
@Test
fun verifyTabsTrayWithOpenTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -349,7 +331,7 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903587
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903587
@SmokeTest
@Test
fun verifyPrivateTabsTrayWithOpenTabTest() {
@ -374,80 +356,133 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/927315
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/927314
@Test
fun tabsCounterShortcutMenuTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
fun tabsCounterShortcutMenuCloseTabTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
}.enterURLAndEnterToBrowser(firstWebPage.url) {
waitForPageToLoad()
}.goToHomescreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(secondWebPage.url) {
waitForPageToLoad()
}
navigationToolbar {
}.openTabButtonShortcutsMenu {
verifyTabButtonShortcutMenuItems()
}.closeTabFromShortcutsMenu {
browserScreen {
verifyTabCounter("1")
verifyPageContent(firstWebPage.content)
}
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2343663
@Test
fun tabsCounterShortcutMenuNewPrivateTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewPrivateTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
}.dismissSearchBar {
verifyPrivateBrowsingHomeScreenItems()
verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = true)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2343662
@Test
fun tabsCounterShortcutMenuNewTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
}.dismissSearchBar {
verifyHomeWordmark()
verifyNavigationToolbar()
verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = false)
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/927314
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/927315
@Test
fun privateTabsCounterShortcutMenuTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
fun privateTabsCounterShortcutMenuCloseTabTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
homeScreen {}.togglePrivateBrowsingMode()
homeScreen {}.togglePrivateBrowsingMode(switchPBModeOn = true)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
waitForPageToLoad()
}.goToHomescreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(secondWebPage.url) {
waitForPageToLoad()
}
navigationToolbar {
}.openTabButtonShortcutsMenu {
verifyTabButtonShortcutMenuItems()
}.closeTabFromShortcutsMenu {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
browserScreen {
verifyTabCounter("1")
verifyPageContent(firstWebPage.content)
}
}.openTabButtonShortcutsMenu {
}.closeTabFromShortcutsMenu {
homeScreen {
verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = true)
}
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2344199
@Test
fun privateTabsCounterShortcutMenuNewPrivateTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {}.togglePrivateBrowsingMode(switchPBModeOn = true)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
waitForPageToLoad()
}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewPrivateTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
}.dismissSearchBar {
verifyCommonMythsLink()
verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = true)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2344198
@Test
fun privateTabsCounterShortcutMenuNewTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {}.togglePrivateBrowsingMode(switchPBModeOn = true)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
verifyPageContent(defaultWebPage.content)
}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
verifySearchToolbar(isDisplayed = true)
}.dismissSearchBar {
// Verify normal browsing homescreen
verifyExistingTopSitesList()
verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = false)
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/1046683
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1046683
@Test
fun verifySyncedTabsWhenUserIsNotSignedInTest() {
navigationToolbar {
@ -495,12 +530,9 @@ class TabbedBrowsingTest {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
}.openTabDrawer {
}.openNewTab {
}.submitQuery(secondWebPage.url.toString()) {
}
}.submitQuery(secondWebPage.url.toString()) {}
closeApp(activityTestRule)
restartApp(activityTestRule)
homeScreen {
verifyPrivateBrowsingHomeScreenItems()
}.openTabDrawer {

@ -15,11 +15,11 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.Constants.defaultTopSitesList
import org.mozilla.fenix.helpers.DataGenerationHelper.generateRandomString
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.generateRandomString
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.waitUntilSnackbarGone
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen

@ -10,6 +10,7 @@ import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.components.toolbar.CFR_MINIMUM_NUMBER_OPENED_TABS
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
@ -28,12 +29,12 @@ class TotalCookieProtectionTest {
val composeTestRule = AndroidComposeTestRule(
HomeActivityTestRule(
isTCPCFREnabled = true,
isCookieBannerReductionDialogEnabled = false,
),
) { it.activity }
@Before
fun setUp() {
CFR_MINIMUM_NUMBER_OPENED_TABS = 0
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -43,6 +44,7 @@ class TotalCookieProtectionTest {
@After
fun tearDown() {
mockWebServer.shutdown()
CFR_MINIMUM_NUMBER_OPENED_TABS = 5
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2260552

@ -24,7 +24,7 @@ class UpgradingUsersOnboardingTest {
HomeActivityIntentTestRule(isHomeOnboardingDialogEnabled = true),
) { it.activity }
// https://testrail.stage.mozaws.net/index.php?/cases/view/1913592
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1913592
@Test
fun upgradingUsersOnboardingScreensTest() {
homeScreen {
@ -34,7 +34,7 @@ class UpgradingUsersOnboardingTest {
}
}
// https://testrail.stage.mozaws.net/index.php?/cases/view/1913591
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1913591
@Test
fun upgradingUsersOnboardingCanBeSkippedTest() {
homeScreen {
@ -50,7 +50,7 @@ class UpgradingUsersOnboardingTest {
}
}
// https://testrail.stage.mozaws.net/index.php?/cases/view/1932156
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1932156
@Test
fun upgradingUsersOnboardingSignInButtonTest() {
homeScreen {

@ -10,6 +10,7 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertNativeAppOpens
import org.mozilla.fenix.helpers.Constants
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
@ -18,7 +19,6 @@ import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestAssetHelper.getHTMLControlsFormAsset
import org.mozilla.fenix.helpers.TestHelper.assertNativeAppOpens
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.navigationToolbar
import java.time.LocalDate

@ -13,8 +13,8 @@ import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiScrollable
import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import org.junit.Assert.assertTrue
import org.mozilla.fenix.helpers.MatcherHelper.assertItemContainingTextExists
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
@ -38,7 +38,7 @@ class AddToHomeScreenRobot {
fun addShortcutName(title: String) = shortcutTextField.setText(title)
fun verifyShortcutTextFieldTitle(title: String) = assertItemContainingTextExists(shortcutTitle(title))
fun verifyShortcutTextFieldTitle(title: String) = assertUIObjectExists(shortcutTitle(title))
fun clickAddShortcutButton() =
confirmAddToHomeScreenButton.clickAndWaitForNewWindow(waitingTime)
@ -60,12 +60,8 @@ class AddToHomeScreenRobot {
}
}
fun verifyShortcutAdded(shortcutTitle: String) {
assertTrue(
mDevice.findObject(UiSelector().text(shortcutTitle))
.waitForExists(waitingTime),
)
}
fun verifyShortcutAdded(shortcutTitle: String) =
assertUIObjectExists(itemContainingText(shortcutTitle))
class Transition {
fun openHomeScreenShortcut(title: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {

@ -31,20 +31,18 @@ import androidx.test.uiautomator.Until
import org.hamcrest.Matchers.allOf
import org.hamcrest.Matchers.containsString
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.MatcherHelper.assertItemContainingTextExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithDescriptionExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdExists
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithDescription
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.click
@ -101,17 +99,16 @@ class BookmarksRobot {
fun verifyCopySnackBarText() = assertSnackBarText("URL copied")
fun verifyEditBookmarksView() {
assertItemWithDescriptionExists(itemWithDescription("Navigate up"))
assertItemContainingTextExists(itemWithText(getStringResource(R.string.edit_bookmark_fragment_title)))
assertItemWithResIdExists(
fun verifyEditBookmarksView() =
assertUIObjectExists(
itemWithDescription("Navigate up"),
itemWithText(getStringResource(R.string.edit_bookmark_fragment_title)),
itemWithResId("$packageName:id/delete_bookmark_button"),
itemWithResId("$packageName:id/save_bookmark_button"),
itemWithResId("$packageName:id/bookmarkNameEdit"),
itemWithResId("$packageName:id/bookmarkUrlEdit"),
itemWithResId("$packageName:id/bookmarkParentFolderSelector"),
)
}
fun verifyKeyboardHidden() = assertKeyboardVisibility(isExpectedToBeVisible = false)
@ -260,7 +257,7 @@ class BookmarksRobot {
}
fun verifySearchedBookmarkExists(bookmarkUrl: String, exists: Boolean = true) =
assertItemContainingTextExists(itemContainingText(bookmarkUrl), exists = exists)
assertUIObjectExists(itemContainingText(bookmarkUrl), exists = exists)
fun dismissBookmarksSearchBar() = mDevice.pressBack()
@ -403,12 +400,7 @@ private fun assertBookmarkFolderIsNotCreated(title: String) {
.resourceId("$packageName:id/bookmarks_wrapper"),
).waitForExists(waitingTime)
assertFalse(
mDevice.findObject(
UiSelector()
.textContains(title),
).waitForExists(waitingTimeShort),
)
assertUIObjectExists(itemContainingText(title), exists = false)
}
private fun assertBookmarkFavicon(forUrl: Uri) = bookmarkFavicon(forUrl.toString()).check(
@ -434,12 +426,12 @@ private fun assertBookmarkIsDeleted(expectedTitle: String) {
.resourceId("$packageName:id/bookmarks_wrapper"),
).waitForExists(waitingTime)
assertFalse(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/title")
.textContains(expectedTitle),
).waitForExists(waitingTimeShort),
assertUIObjectExists(
itemWithResIdContainingText(
"$packageName:id/title",
expectedTitle,
),
exists = false,
)
}
private fun assertUndoDeleteSnackBarButton() =

@ -15,6 +15,7 @@ import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.ViewInteraction
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.contrib.PickerActions
@ -41,10 +42,12 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.Constants.LONG_CLICK_DURATION
import org.mozilla.fenix.helpers.Constants.RETRY_COUNT
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityComposeTestRule
import org.mozilla.fenix.helpers.MatcherHelper.assertItemContainingTextExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdAndTextExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemTextEquals
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectIsGone
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithDescription
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
@ -56,7 +59,6 @@ import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeLong
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.appName
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.waitForObjects
@ -68,7 +70,7 @@ import java.time.LocalDate
class BrowserRobot {
private lateinit var sessionLoadedIdlingResource: SessionLoadedIdlingResource
fun waitForPageToLoad() = progressBar.waitUntilGone(waitingTime)
fun waitForPageToLoad() = assertUIObjectIsGone(progressBar())
fun verifyCurrentPrivateSession(context: Context) {
val selectedTab = context.components.core.store.state.selectedTab
@ -79,12 +81,11 @@ class BrowserRobot {
sessionLoadedIdlingResource = SessionLoadedIdlingResource()
runWithIdleRes(sessionLoadedIdlingResource) {
assertTrue(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/mozac_browser_toolbar_url_view")
.textContains(url.replace("http://", "")),
).waitForExists(waitingTime),
assertUIObjectExists(
itemWithResIdContainingText(
"$packageName:id/mozac_browser_toolbar_url_view",
url.replace("http://", ""),
),
)
}
}
@ -105,7 +106,6 @@ class BrowserRobot {
* document.querySelector('#testContent').innerText == expectedText
*
*/
fun verifyPageContent(expectedText: String) {
sessionLoadedIdlingResource = SessionLoadedIdlingResource()
@ -115,10 +115,7 @@ class BrowserRobot {
)
runWithIdleRes(sessionLoadedIdlingResource) {
assertTrue(
"Page didn't load or doesn't contain the expected text",
mDevice.findObject(UiSelector().textContains(expectedText)).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText(expectedText))
}
}
@ -150,7 +147,7 @@ class BrowserRobot {
for (i in 1..RETRY_COUNT) {
try {
assertTrue(cacheSizeInfo.waitForExists(waitingTime))
assertUIObjectExists(cacheSizeInfo)
break
} catch (e: AssertionError) {
browserScreen {
@ -160,63 +157,55 @@ class BrowserRobot {
}
}
fun verifyTabCounter(expectedText: String) {
val counter =
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/counter_text")
.text(expectedText),
)
assertTrue(counter.waitForExists(waitingTime))
}
fun verifyTabCounter(expectedText: String) =
assertUIObjectExists(
itemWithResIdContainingText(
"$packageName:id/counter_text",
expectedText,
),
)
fun verifySnackBarText(expectedText: String) {
mDevice.waitForObjects(mDevice.findObject(UiSelector().textContains(expectedText)))
assertTrue(
mDevice.findObject(
UiSelector()
.textContains(expectedText),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText(expectedText))
}
fun verifyContextMenuForLocalHostLinks(containsURL: Uri) {
// If the link is directing to another local asset the "Download link" option is not available
// If the link is not re-directing to an external app the "Open link in external app" option is not available
assertItemContainingTextExists(
assertUIObjectExists(
contextMenuLinkUrl(containsURL.toString()),
contextMenuOpenLinkInNewTab,
contextMenuOpenLinkInPrivateTab,
contextMenuCopyLink,
contextMenuShareLink,
contextMenuOpenLinkInNewTab(),
contextMenuOpenLinkInPrivateTab(),
contextMenuCopyLink(),
contextMenuShareLink(),
)
}
fun verifyContextMenuForLinksToOtherApps(containsURL: String) {
// If the link is re-directing to an external app the "Open link in external app" option is available
// If the link is not directing to another local asset the "Download link" option is not available
assertItemContainingTextExists(
assertUIObjectExists(
contextMenuLinkUrl(containsURL),
contextMenuOpenLinkInNewTab,
contextMenuOpenLinkInPrivateTab,
contextMenuCopyLink,
contextMenuDownloadLink,
contextMenuShareLink,
contextMenuOpenInExternalApp,
contextMenuOpenLinkInNewTab(),
contextMenuOpenLinkInPrivateTab(),
contextMenuCopyLink(),
contextMenuDownloadLink(),
contextMenuShareLink(),
contextMenuOpenInExternalApp(),
)
}
fun verifyContextMenuForLinksToOtherHosts(containsURL: Uri) {
// If the link is re-directing to another host the "Download link" option is available
// If the link is not re-directing to an external app the "Open link in external app" option is not available
assertItemContainingTextExists(
assertUIObjectExists(
contextMenuLinkUrl(containsURL.toString()),
contextMenuOpenLinkInNewTab,
contextMenuOpenLinkInPrivateTab,
contextMenuCopyLink,
contextMenuDownloadLink,
contextMenuShareLink,
contextMenuOpenLinkInNewTab(),
contextMenuOpenLinkInPrivateTab(),
contextMenuCopyLink(),
contextMenuDownloadLink(),
contextMenuShareLink(),
)
}
@ -243,8 +232,7 @@ class BrowserRobot {
)
}
fun verifyNavURLBarHidden() =
assertTrue(navURLBar().waitUntilGone(waitingTime))
fun verifyNavURLBarHidden() = assertUIObjectIsGone(navURLBar())
fun verifySecureConnectionLockIcon() =
onView(withId(R.id.mozac_browser_toolbar_security_indicator))
@ -265,21 +253,17 @@ class BrowserRobot {
)
}
fun verifyNotificationDotOnMainMenu() {
assertTrue(
mDevice.findObject(UiSelector().resourceId("$packageName:id/notification_dot"))
.waitForExists(waitingTime),
)
}
fun verifyNotificationDotOnMainMenu() =
assertUIObjectExists(itemWithResId("$packageName:id/notification_dot"))
fun verifyHomeScreenButton() =
homeScreenButton().check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
fun verifySearchBar() = assertTrue(searchBar().waitForExists(waitingTime))
fun verifySearchBar() = assertUIObjectExists(searchBar())
fun dismissContentContextMenu() {
mDevice.pressBack()
assertItemWithResIdExists(itemWithResId("$packageName:id/engineView"))
assertUIObjectExists(itemWithResId("$packageName:id/engineView"))
}
fun createBookmark(url: Uri, folder: String? = null) {
@ -300,20 +284,14 @@ class BrowserRobot {
fun longClickPDFImage() = longClickPageObject(itemWithResId("pdfjs_internal_id_13R"))
fun verifyPDFReaderToolbarItems() {
assertTrue(
itemWithResIdAndText("download", "Download")
.waitForExists(waitingTime),
fun verifyPDFReaderToolbarItems() =
assertUIObjectExists(
itemWithResIdContainingText("download", "Download"),
itemWithResIdContainingText("openInApp", "Open in app"),
)
assertTrue(
itemWithResIdAndText("openInApp", "Open in app")
.waitForExists(waitingTime),
)
}
fun clickSubmitLoginButton() {
clickPageObject(itemWithResId("submit"))
itemWithResId("submit").waitUntilGone(waitingTime)
assertUIObjectIsGone(itemWithResId("submit"))
mDevice.waitForIdle(waitingTimeLong)
}
@ -321,7 +299,7 @@ class BrowserRobot {
clickPageObject(itemWithResId("password"))
setPageObjectText(itemWithResId("password"), password)
assertTrue(mDevice.findObject(UiSelector().text(password)).waitUntilGone(waitingTime))
assertUIObjectIsGone(itemWithText(password))
}
/**
@ -357,10 +335,10 @@ class BrowserRobot {
// failing to swipe on Firebase sometimes, so it tries again
try {
navURLBar().swipeRight(2)
assertTrue(mDevice.findObject(UiSelector().text(tabUrl)).waitUntilGone(waitingTime))
assertUIObjectIsGone(itemWithText(tabUrl))
} catch (e: AssertionError) {
navURLBar().swipeRight(2)
assertTrue(mDevice.findObject(UiSelector().text(tabUrl)).waitUntilGone(waitingTime))
assertUIObjectIsGone(itemWithText(tabUrl))
}
}
@ -368,19 +346,19 @@ class BrowserRobot {
// failing to swipe on Firebase sometimes, so it tries again
try {
navURLBar().swipeLeft(2)
assertTrue(mDevice.findObject(UiSelector().text(tabUrl)).waitUntilGone(waitingTime))
assertUIObjectIsGone(itemWithText(tabUrl))
} catch (e: AssertionError) {
navURLBar().swipeLeft(2)
assertTrue(mDevice.findObject(UiSelector().text(tabUrl)).waitUntilGone(waitingTime))
assertUIObjectIsGone(itemWithText(tabUrl))
}
}
fun clickSuggestedLoginsButton() {
for (i in 1..RETRY_COUNT) {
try {
mDevice.waitForObjects(suggestedLogins)
suggestedLogins.click()
mDevice.waitForObjects(suggestedLogins)
mDevice.waitForObjects(suggestedLogins())
suggestedLogins().click()
mDevice.waitForObjects(suggestedLogins())
break
} catch (e: UiObjectNotFoundException) {
if (i == RETRY_COUNT) {
@ -407,8 +385,8 @@ class BrowserRobot {
fun clickSelectAddressButton() {
for (i in 1..RETRY_COUNT) {
try {
assertTrue(selectAddressButton.waitForExists(waitingTime))
selectAddressButton.clickAndWaitForNewWindow(waitingTime)
assertUIObjectExists(selectAddressButton())
selectAddressButton().clickAndWaitForNewWindow(waitingTime)
break
} catch (e: AssertionError) {
@ -424,7 +402,7 @@ class BrowserRobot {
}
}
fun verifySelectAddressButtonExists(exists: Boolean) = assertItemWithResIdExists(selectAddressButton, exists = exists)
fun verifySelectAddressButtonExists(exists: Boolean) = assertUIObjectExists(selectAddressButton(), exists = exists)
fun changeCreditCardExpiryDate(expiryDate: String) =
itemWithResId("expiryMonthAndYear").setText(expiryDate)
@ -451,17 +429,22 @@ class BrowserRobot {
}
fun verifyUpdateOrSaveCreditCardPromptExists(exists: Boolean) =
assertItemWithResIdAndTextExists(
assertUIObjectExists(
itemWithResId("$packageName:id/save_credit_card_header"),
exists = exists,
)
fun verifySelectCreditCardPromptExists(exists: Boolean) =
assertItemWithResIdExists(selectCreditCardButton, exists = exists)
assertUIObjectExists(selectCreditCardButton(), exists = exists)
fun verifyCreditCardSuggestion(vararg creditCardNumbers: String) {
for (creditCardNumber in creditCardNumbers) {
assertTrue(creditCardSuggestion(creditCardNumber).waitForExists(waitingTime))
assertUIObjectExists(
itemWithResIdContainingText(
"$packageName:id/credit_card_number",
creditCardNumber,
),
)
}
}
@ -470,29 +453,17 @@ class BrowserRobot {
UiSelector()
.resourceId("$packageName:id/mozac_feature_login_multiselect_expand"),
).waitForExists(waitingTime)
assertTrue(
mDevice.findObject(UiSelector().textContains(userName)).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText(userName))
}
fun verifyPrefilledLoginCredentials(userName: String, password: String, credentialsArePrefilled: Boolean) {
// Sometimes the assertion of the pre-filled logins fails so we are re-trying after refreshing the page
for (i in 1..RETRY_COUNT) {
try {
if (credentialsArePrefilled) {
mDevice.waitForObjects(itemWithResId("username"))
assertTrue(itemWithResId("username").text.equals(userName))
mDevice.waitForObjects(itemWithResId("password"))
assertTrue(itemWithResId("password").text.equals(password))
} else {
mDevice.waitForObjects(itemWithResId("username"))
assertFalse(itemWithResId("username").text.equals(userName))
mDevice.waitForObjects(itemWithResId("password"))
assertFalse(itemWithResId("password").text.equals(password))
}
mDevice.waitForObjects(itemWithResId("username"))
assertItemTextEquals(itemWithResId("username"), expectedText = userName, isEqual = credentialsArePrefilled)
mDevice.waitForObjects(itemWithResId("password"))
assertItemTextEquals(itemWithResId("password"), expectedText = password, isEqual = credentialsArePrefilled)
break
} catch (e: AssertionError) {
@ -515,26 +486,17 @@ class BrowserRobot {
fun verifyAutofilledAddress(streetAddress: String) {
mDevice.waitForObjects(itemWithResIdAndText("streetAddress", streetAddress))
assertTrue(
itemWithResIdAndText("streetAddress", streetAddress)
.waitForExists(waitingTime),
)
assertUIObjectExists(itemWithResIdAndText("streetAddress", streetAddress))
}
fun verifyManuallyFilledAddress(apartment: String) {
mDevice.waitForObjects(itemWithResIdAndText("apartment", apartment))
assertTrue(
itemWithResIdAndText("apartment", apartment)
.waitForExists(waitingTime),
)
assertUIObjectExists(itemWithResIdAndText("apartment", apartment))
}
fun verifyAutofilledCreditCard(creditCardNumber: String) {
mDevice.waitForObjects(itemWithResIdAndText("cardNumber", creditCardNumber))
assertTrue(
itemWithResIdAndText("cardNumber", creditCardNumber)
.waitForExists(waitingTime),
)
assertUIObjectExists(itemWithResIdAndText("cardNumber", creditCardNumber))
}
fun verifyPrefilledPWALoginCredentials(userName: String, shortcutTitle: String) {
@ -543,9 +505,9 @@ class BrowserRobot {
var currentTries = 0
while (currentTries++ < 3) {
try {
assertTrue(itemWithResId("submit").waitForExists(waitingTime))
assertUIObjectExists(itemWithResId("submit"))
itemWithResId("submit").click()
assertTrue(itemWithResId("username").text.equals(userName))
assertItemTextEquals(itemWithResId("username"), expectedText = userName)
break
} catch (e: AssertionError) {
addToHomeScreen {
@ -555,12 +517,12 @@ class BrowserRobot {
}
fun verifySaveLoginPromptIsDisplayed() =
assertItemWithResIdExists(
assertUIObjectExists(
itemWithResId("$packageName:id/feature_prompt_login_fragment"),
)
fun verifySaveLoginPromptIsNotDisplayed() =
assertItemWithResIdExists(
assertUIObjectExists(
itemWithResId("$packageName:id/feature_prompt_login_fragment"),
exists = false,
)
@ -568,11 +530,7 @@ class BrowserRobot {
fun verifyTrackingProtectionWebContent(state: String) {
for (i in 1..RETRY_COUNT) {
try {
assertTrue(
mDevice.findObject(
UiSelector().textContains(state),
).waitForExists(waitingTimeLong),
)
assertUIObjectExists(itemContainingText(state))
break
} catch (e: AssertionError) {
@ -618,7 +576,7 @@ class BrowserRobot {
}
}
fun selectTime(hour: Int, minute: Int) =
fun selectTime(hour: Int, minute: Int): ViewInteraction =
onView(
isAssignableFrom(TimePicker::class.java),
).inRoot(
@ -626,14 +584,14 @@ class BrowserRobot {
).perform(PickerActions.setTime(hour, minute))
fun verifySelectedDate() {
val currentDate = LocalDate.now()
val currentDay = currentDate.dayOfMonth
val currentMonth = currentDate.month
val currentYear = currentDate.year
for (i in 1..RETRY_COUNT) {
try {
assertTrue(
mDevice.findObject(
UiSelector()
.text("Selected date is: $currentDate"),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText("Selected date is: $currentDate"))
break
} catch (e: AssertionError) {
@ -646,32 +604,21 @@ class BrowserRobot {
}
}
assertTrue(
mDevice.findObject(
UiSelector()
.text("Selected date is: $currentDate"),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText("Selected date is: $currentDate"))
}
fun verifyNoDateIsSelected() {
assertFalse(
mDevice.findObject(
UiSelector()
.text("Selected date is: $currentDate"),
).waitForExists(waitingTimeShort),
val currentDate = LocalDate.now()
assertUIObjectExists(
itemContainingText("Selected date is: $currentDate"),
exists = false,
)
}
fun verifySelectedTime(hour: Int, minute: Int) {
for (i in 1..RETRY_COUNT) {
try {
assertTrue(
mDevice.findObject(
UiSelector()
.text("Selected time is: $hour:$minute"),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText("Selected time is: $hour:$minute"))
break
} catch (e: AssertionError) {
@ -685,24 +632,13 @@ class BrowserRobot {
clickPageObject(itemWithResId("submitTime"))
}
}
assertTrue(
mDevice.findObject(
UiSelector()
.text("Selected time is: $hour:$minute"),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText("Selected time is: $hour:$minute"))
}
fun verifySelectedColor(hexValue: String) {
for (i in 1..RETRY_COUNT) {
try {
assertTrue(
mDevice.findObject(
UiSelector()
.text("Selected color is: $hexValue"),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText("Selected color is: $hexValue"))
break
} catch (e: AssertionError) {
@ -715,12 +651,7 @@ class BrowserRobot {
}
}
assertTrue(
mDevice.findObject(
UiSelector()
.text("Selected color is: $hexValue"),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText("Selected color is: $hexValue"))
}
fun verifySelectedDropDownOption(optionName: String) {
@ -732,12 +663,7 @@ class BrowserRobot {
.resourceId("submitOption"),
).waitForExists(waitingTime)
assertTrue(
mDevice.findObject(
UiSelector()
.text("Selected option is: $optionName"),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText("Selected option is: $optionName"))
break
} catch (e: AssertionError) {
@ -749,36 +675,19 @@ class BrowserRobot {
}
}
assertTrue(
mDevice.findObject(
UiSelector()
.text("Selected option is: $optionName"),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText("Selected option is: $optionName"))
}
fun verifyNoTimeIsSelected(hour: Int, minute: Int) {
assertFalse(
mDevice.findObject(
UiSelector()
.text("Selected date is: $hour:$minute"),
).waitForExists(waitingTimeShort),
)
}
fun verifyNoTimeIsSelected(hour: Int, minute: Int) =
assertUIObjectExists(itemContainingText("Selected date is: $hour:$minute"), exists = false)
fun verifyColorIsNotSelected(hexValue: String) {
assertFalse(
mDevice.findObject(
UiSelector()
.text("Selected date is: $hexValue"),
).waitForExists(waitingTimeShort),
)
}
fun verifyColorIsNotSelected(hexValue: String) =
assertUIObjectExists(itemContainingText("Selected date is: $hexValue"), exists = false)
fun verifyCookieBannerExists(exists: Boolean) {
for (i in 1..RETRY_COUNT) {
try {
assertItemWithResIdExists(cookieBanner, exists = exists)
assertUIObjectExists(cookieBanner(), exists = exists)
break
} catch (e: AssertionError) {
if (i == RETRY_COUNT) {
@ -792,12 +701,12 @@ class BrowserRobot {
}
}
}
assertItemWithResIdExists(cookieBanner, exists = exists)
assertUIObjectExists(cookieBanner(), exists = exists)
}
fun verifyOpenLinkInAnotherAppPrompt() {
assertItemWithResIdExists(itemWithResId("$packageName:id/parentPanel"))
assertItemContainingTextExists(
assertUIObjectExists(
itemWithResId("$packageName:id/parentPanel"),
itemContainingText(
getStringResource(R.string.mozac_feature_applinks_normal_confirm_dialog_title),
),
@ -810,7 +719,7 @@ class BrowserRobot {
fun verifyPrivateBrowsingOpenLinkInAnotherAppPrompt(url: String, pageObject: UiObject) {
for (i in 1..RETRY_COUNT) {
try {
assertItemContainingTextExists(
assertUIObjectExists(
itemContainingText(
getStringResource(R.string.mozac_feature_applinks_confirm_dialog_title),
),
@ -834,40 +743,34 @@ class BrowserRobot {
}
fun verifyFindInPageBar(exists: Boolean) =
assertItemWithResIdExists(
assertUIObjectExists(
itemWithResId("$packageName:id/findInPageView"),
exists = exists,
)
fun verifyConnectionErrorMessage() {
assertItemContainingTextExists(
fun verifyConnectionErrorMessage() =
assertUIObjectExists(
itemContainingText(getStringResource(R.string.mozac_browser_errorpages_connection_failure_title)),
itemWithResId("errorTryAgain"),
)
assertItemWithResIdExists(itemWithResId("errorTryAgain"))
}
fun verifyAddressNotFoundErrorMessage() {
assertItemContainingTextExists(
fun verifyAddressNotFoundErrorMessage() =
assertUIObjectExists(
itemContainingText(getStringResource(R.string.mozac_browser_errorpages_unknown_host_title)),
itemWithResId("errorTryAgain"),
)
assertItemWithResIdExists(itemWithResId("errorTryAgain"))
}
fun verifyNoInternetConnectionErrorMessage() {
assertItemContainingTextExists(
fun verifyNoInternetConnectionErrorMessage() =
assertUIObjectExists(
itemContainingText(getStringResource(R.string.mozac_browser_errorpages_no_internet_title)),
itemWithResId("errorTryAgain"),
)
assertItemWithResIdExists(itemWithResId("errorTryAgain"))
}
fun verifyOpenLinksInAppsCFRExists(exists: Boolean) {
for (i in 1..RETRY_COUNT) {
try {
assertItemWithResIdExists(
assertUIObjectExists(
itemWithResId("$packageName:id/banner_container"),
exists = exists,
)
assertItemWithResIdAndTextExists(
itemWithResIdContainingText(
"$packageName:id/banner_info_message",
getStringResource(R.string.open_in_app_cfr_info_message_2),
@ -889,54 +792,25 @@ class BrowserRobot {
browserScreen {
}.openThreeDotMenu {
}.refreshPage {
progressBar.waitUntilGone(waitingTimeLong)
waitForPageToLoad()
}
}
}
}
}
fun verifySurveyButton() {
val button = mDevice.findObject(
UiSelector().text(
getStringResource(
R.string.preferences_take_survey,
),
),
)
assertTrue(button.waitForExists(waitingTime))
}
fun verifySurveyButton() = assertUIObjectExists(itemContainingText(getStringResource(R.string.preferences_take_survey)))
fun verifySurveyButtonDoesNotExist() {
val button = mDevice.findObject(
UiSelector().text(
getStringResource(
R.string.preferences_take_survey,
),
),
)
assertTrue(button.waitUntilGone(waitingTime))
}
fun verifySurveyButtonDoesNotExist() =
assertUIObjectIsGone(itemWithText(getStringResource(R.string.preferences_take_survey)))
fun verifySurveyNoThanksButton() {
val button = mDevice.findObject(
UiSelector().text(
getStringResource(
R.string.preferences_not_take_survey,
),
),
fun verifySurveyNoThanksButton() =
assertUIObjectExists(
itemContainingText(getStringResource(R.string.preferences_not_take_survey)),
)
assertTrue(button.waitForExists(waitingTime))
}
fun verifyHomeScreenSurveyCloseButton() {
val button = mDevice.findObject(
UiSelector().descriptionContains(
"Close",
),
)
assertTrue(button.waitForExists(waitingTime))
}
fun verifyHomeScreenSurveyCloseButton() =
assertUIObjectExists(itemWithDescription("Close"))
fun clickOpenLinksInAppsDismissCFRButton() =
itemWithResIdContainingText(
@ -970,13 +844,13 @@ class BrowserRobot {
fun longClickToolbar() = mDevice.findObject(By.res("$packageName:id/mozac_browser_toolbar_url_view")).click(LONG_CLICK_DURATION)
fun verifyDownloadPromptIsDismissed() =
assertItemWithResIdExists(
assertUIObjectExists(
itemWithResId("$packageName:id/viewDynamicDownloadDialog"),
exists = false,
)
fun verifyCancelPrivateDownloadsPrompt(numberOfActiveDownloads: String) {
assertItemWithResIdAndTextExists(
assertUIObjectExists(
itemWithResIdContainingText(
"$packageName:id/title",
getStringResource(R.string.mozac_feature_downloads_cancel_active_downloads_warning_content_title),
@ -996,17 +870,20 @@ class BrowserRobot {
)
}
fun clickStayInPrivateBrowsingPromptButton() =
fun clickStayInPrivateBrowsingPromptButton() {
itemWithResIdContainingText(
"$packageName:id/deny_button",
getStringResource(R.string.mozac_feature_downloads_cancel_active_private_downloads_deny),
).click()
Log.i(TAG, "clickStayInPrivateBrowsingPromptButton: Clicked \"STAY IN PRIVATE BROWSING\" prompt button")
}
fun clickCancelPrivateDownloadsPromptButton() {
itemWithResIdContainingText(
"$packageName:id/accept_button",
getStringResource(R.string.mozac_feature_downloads_cancel_active_downloads_accept),
).click()
Log.i(TAG, "clickCancelPrivateDownloadsPromptButton: Clicked \"CANCEL DOWNLOADS\" prompt button")
mDevice.waitForWindowUpdate(packageName, waitingTime)
}
@ -1014,6 +891,7 @@ class BrowserRobot {
fun fillPdfForm(name: String) {
// Set PDF form text for the text box
itemWithResId("pdfjs_internal_id_10R").setText(name)
Log.i(TAG, "fillPdfForm: Set PDF form text box text to: $name")
mDevice.waitForWindowUpdate(packageName, waitingTime)
if (
!itemWithResId("pdfjs_internal_id_11R").exists() &&
@ -1023,15 +901,19 @@ class BrowserRobot {
) {
// Close the keyboard
mDevice.pressBack()
Log.i(TAG, "fillPdfForm: Closing the keyboard using device back button")
}
// Click PDF form check box
itemWithResId("pdfjs_internal_id_11R").click()
Log.i(TAG, "fillPdfForm: Clicked PDF form check box")
}
class Transition {
fun openThreeDotMenu(interact: ThreeDotMenuMainRobot.() -> Unit): ThreeDotMenuMainRobot.Transition {
mDevice.waitForIdle(waitingTime)
Log.i(TAG, "openThreeDotMenu: Device was idle for $waitingTime ms")
threeDotButton().perform(click())
Log.i(TAG, "openThreeDotMenu: Clicked the main menu button")
ThreeDotMenuMainRobot().interact()
return ThreeDotMenuMainRobot.Transition()
@ -1057,10 +939,7 @@ class BrowserRobot {
)
tabsCounter().click()
assertTrue(
itemWithResId("$packageName:id/new_tab_button")
.waitForExists(waitingTime),
)
assertUIObjectExists(itemWithResId("$packageName:id/new_tab_button"))
break
} catch (e: AssertionError) {
@ -1072,10 +951,7 @@ class BrowserRobot {
}
}
assertTrue(
itemWithResId("$packageName:id/new_tab_button")
.waitForExists(waitingTime),
)
assertUIObjectExists(itemWithResId("$packageName:id/new_tab_button"))
TabDrawerRobot().interact()
return TabDrawerRobot.Transition()
@ -1114,6 +990,7 @@ class BrowserRobot {
fun openNotificationShade(interact: NotificationRobot.() -> Unit): NotificationRobot.Transition {
mDevice.openNotification()
Log.i(TAG, "openNotificationShade: Opened notification tray")
NotificationRobot().interact()
return NotificationRobot.Transition()
@ -1288,23 +1165,24 @@ class BrowserRobot {
}
fun clickSurveyButton(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
surveyButton.waitForExists(waitingTime)
surveyButton.click()
surveyButton().waitForExists(waitingTime)
surveyButton().click()
BrowserRobot().interact()
return Transition()
}
fun clickNoThanksSurveyButton(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
surveyNoThanksButton.waitForExists(waitingTime)
surveyNoThanksButton.click()
surveyNoThanksButton().waitForExists(waitingTime)
surveyNoThanksButton().click()
BrowserRobot().interact()
return Transition()
}
fun clickHomeScreenSurveyCloseButton(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
homescreenSurveyCloseButton.waitForExists(waitingTime)
homescreenSurveyCloseButton.click()
homescreenSurveyCloseButton().waitForExists(waitingTime)
homescreenSurveyCloseButton().click()
BrowserRobot().interact()
return Transition()
@ -1317,9 +1195,9 @@ fun browserScreen(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
return BrowserRobot.Transition()
}
fun navURLBar() = itemWithResId("$packageName:id/toolbar")
private fun navURLBar() = itemWithResId("$packageName:id/toolbar")
fun searchBar() = itemWithResId("$packageName:id/mozac_browser_toolbar_url_view")
private fun searchBar() = itemWithResId("$packageName:id/mozac_browser_toolbar_url_view")
fun homeScreenButton() = onView(withContentDescription(R.string.browser_toolbar_home))
@ -1328,38 +1206,38 @@ private fun threeDotButton() = onView(withContentDescription("Menu"))
private fun tabsCounter() =
mDevice.findObject(By.res("$packageName:id/counter_root"))
private val progressBar =
private fun progressBar() =
itemWithResId("$packageName:id/mozac_browser_toolbar_progress")
private val suggestedLogins = itemWithResId("$packageName:id/loginSelectBar")
private val selectAddressButton = itemWithResId("$packageName:id/select_address_header")
private val selectCreditCardButton = itemWithResId("$packageName:id/select_credit_card_header")
private fun creditCardSuggestion(creditCardNumber: String) =
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/credit_card_number")
.textContains(creditCardNumber),
)
private fun suggestedLogins() = itemWithResId("$packageName:id/loginSelectBar")
private fun selectAddressButton() = itemWithResId("$packageName:id/select_address_header")
private fun selectCreditCardButton() = itemWithResId("$packageName:id/select_credit_card_header")
private fun siteSecurityToolbarButton() =
itemWithResId("$packageName:id/mozac_browser_toolbar_security_indicator")
fun clickPageObject(item: UiObject) {
for (i in 1..RETRY_COUNT) {
Log.i(TAG, "clickPageObject: For loop i = $i")
try {
Log.i(TAG, "clickPageObject: Try block")
item.waitForExists(waitingTime)
item.click()
Log.i(TAG, "clickPageObject: Clicked ${item.selector}")
break
} catch (e: UiObjectNotFoundException) {
Log.i(TAG, "clickPageObject: Catch block")
if (i == RETRY_COUNT) {
throw e
} else {
browserScreen {
Log.i(TAG, "clickPageObject: Browser screen")
}.openThreeDotMenu {
Log.i(TAG, "clickPageObject: Opened main menu")
}.refreshPage {
progressBar.waitUntilGone(waitingTime)
waitForPageToLoad()
Log.i(TAG, "clickPageObject: Page refreshed, progress bar is gone")
}
}
}
@ -1380,7 +1258,7 @@ fun longClickPageObject(item: UiObject) {
browserScreen {
}.openThreeDotMenu {
}.refreshPage {
progressBar.waitUntilGone(waitingTime)
waitForPageToLoad()
}
}
}
@ -1412,7 +1290,7 @@ fun setPageObjectText(webPageItem: UiObject, text: String) {
browserScreen {
}.openThreeDotMenu {
}.refreshPage {
progressBar.waitUntilGone(waitingTime)
waitForPageToLoad()
}
}
}
@ -1424,11 +1302,7 @@ fun clearTextFieldItem(item: UiObject) {
item.clearTextField()
}
private val currentDate = LocalDate.now()
private val currentDay = currentDate.dayOfMonth
private val currentMonth = currentDate.month
private val currentYear = currentDate.year
private val cookieBanner = itemWithResId("startsiden-gdpr-disclaimer")
private fun cookieBanner() = itemWithResId("startsiden-gdpr-disclaimer")
// Context menu items
// Link URL
@ -1436,34 +1310,34 @@ private fun contextMenuLinkUrl(linkUrl: String) =
itemContainingText(linkUrl)
// Open link in new tab option
private val contextMenuOpenLinkInNewTab =
private fun contextMenuOpenLinkInNewTab() =
itemContainingText(getStringResource(R.string.mozac_feature_contextmenu_open_link_in_new_tab))
// Open link in private tab option
private val contextMenuOpenLinkInPrivateTab =
private fun contextMenuOpenLinkInPrivateTab() =
itemContainingText(getStringResource(R.string.mozac_feature_contextmenu_open_link_in_private_tab))
// Copy link option
private val contextMenuCopyLink =
private fun contextMenuCopyLink() =
itemContainingText(getStringResource(R.string.mozac_feature_contextmenu_copy_link))
// Download link option
private val contextMenuDownloadLink =
private fun contextMenuDownloadLink() =
itemContainingText(getStringResource(R.string.mozac_feature_contextmenu_download_link))
// Share link option
private val contextMenuShareLink =
private fun contextMenuShareLink() =
itemContainingText(getStringResource(R.string.mozac_feature_contextmenu_share_link))
// Open in external app option
private val contextMenuOpenInExternalApp =
private fun contextMenuOpenInExternalApp() =
itemContainingText(getStringResource(R.string.mozac_feature_contextmenu_open_link_in_external_app))
private val surveyButton =
private fun surveyButton() =
itemContainingText(getStringResource(R.string.preferences_take_survey))
private val surveyNoThanksButton =
private fun surveyNoThanksButton() =
itemContainingText(getStringResource(R.string.preferences_not_take_survey))
private val homescreenSurveyCloseButton =
private fun homescreenSurveyCloseButton() =
itemWithDescription("Close")

@ -7,7 +7,6 @@ package org.mozilla.fenix.ui.robots
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.hasContentDescription
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.isDialog
import androidx.compose.ui.test.junit4.ComposeTestRule
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTouchInput
@ -21,17 +20,17 @@ import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiScrollable
import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.MatcherHelper.assertItemContainingTextExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithDescriptionExists
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.MatcherHelper.assertItemTextEquals
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectIsGone
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithDescription
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText
@ -40,28 +39,16 @@ import org.mozilla.fenix.helpers.ext.waitNotNull
class CollectionRobot {
fun verifySelectCollectionScreen() {
assertTrue(
mDevice.findObject(UiSelector().text("Select collection"))
.exists(),
fun verifySelectCollectionScreen() =
assertUIObjectExists(
itemContainingText("Select collection"),
itemContainingText("Add new collection"),
itemWithResId("$packageName:id/collections_list"),
)
assertTrue(
mDevice.findObject(UiSelector().resourceId("$packageName:id/collections_list"))
.exists(),
)
assertTrue(
mDevice.findObject(UiSelector().text("Add new collection"))
.exists(),
)
}
fun clickAddNewCollection() = addNewCollectionButton().click()
fun verifyCollectionNameTextField() {
assertTrue(
mainMenuEditCollectionNameField().waitForExists(waitingTime),
)
}
fun verifyCollectionNameTextField() = assertUIObjectExists(mainMenuEditCollectionNameField())
// names a collection saved from tab drawer
fun typeCollectionNameAndSave(collectionName: String) {
@ -71,13 +58,12 @@ class CollectionRobot {
}
fun verifyTabsSelectedCounterText(numOfTabs: Int) {
mDevice.findObject(UiSelector().text("Select tabs to save"))
.waitUntilGone(waitingTime)
itemWithText("Select tabs to save").waitUntilGone(waitingTime)
val tabsCounter = mDevice.findObject(UiSelector().resourceId("$packageName:id/bottom_bar_text"))
when (numOfTabs) {
1 -> assertTrue(tabsCounter.text.equals("$numOfTabs tab selected"))
2 -> assertTrue(tabsCounter.text.equals("$numOfTabs tabs selected"))
1 -> assertItemTextEquals(tabsCounter, expectedText = "$numOfTabs tab selected")
2 -> assertItemTextEquals(tabsCounter, expectedText = "$numOfTabs tabs selected")
}
}
@ -88,33 +74,17 @@ class CollectionRobot {
fun verifyTabSavedInCollection(title: String, visible: Boolean = true) {
if (visible) {
scrollToElementByText(title)
assertTrue(
collectionListItem(title).waitForExists(waitingTime),
)
assertUIObjectExists(collectionListItem(title))
} else {
assertTrue(
collectionListItem(title).waitUntilGone(waitingTime),
)
assertUIObjectIsGone(collectionListItem(title))
}
}
fun verifyCollectionTabUrl(visible: Boolean, url: String) {
val tabUrl = mDevice.findObject(UiSelector().text(url))
if (visible) {
assertTrue(tabUrl.exists())
} else {
assertFalse(tabUrl.exists())
}
}
fun verifyCollectionTabUrl(visible: Boolean, url: String) =
assertUIObjectExists(itemContainingText(url), exists = visible)
fun verifyShareCollectionButtonIsVisible(visible: Boolean) {
if (visible) {
assertTrue(shareCollectionButton().exists())
} else {
assertFalse(shareCollectionButton().exists())
}
}
fun verifyShareCollectionButtonIsVisible(visible: Boolean) =
assertUIObjectExists(shareCollectionButton(), exists = visible)
fun verifyCollectionMenuIsVisible(visible: Boolean, rule: ComposeTestRule) {
if (visible) {
@ -160,17 +130,8 @@ class CollectionRobot {
.performClick()
}
fun verifyCollectionItemRemoveButtonIsVisible(title: String, visible: Boolean) {
if (visible) {
assertTrue(
removeTabFromCollectionButton(title).exists(),
)
} else {
assertFalse(
removeTabFromCollectionButton(title).exists(),
)
}
}
fun verifyCollectionItemRemoveButtonIsVisible(title: String, visible: Boolean) =
assertUIObjectExists(removeTabFromCollectionButton(title), exists = visible)
fun removeTabFromCollection(title: String) = removeTabFromCollectionButton(title).click()
@ -202,9 +163,9 @@ class CollectionRobot {
title: String,
interact: HomeScreenRobot.() -> Unit,
): HomeScreenRobot.Transition {
assertItemContainingTextExists(itemContainingText(title))
assertUIObjectExists(itemContainingText(title))
itemContainingText(title).clickAndWaitForNewWindow(waitingTimeShort)
assertItemWithDescriptionExists(itemWithDescription(getStringResource(R.string.remove_tab_from_collection)), exists = false)
assertUIObjectExists(itemWithDescription(getStringResource(R.string.remove_tab_from_collection)), exists = false)
HomeScreenRobot().interact()
return HomeScreenRobot.Transition()

@ -39,16 +39,15 @@ import androidx.test.espresso.action.GeneralLocation
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.matcher.ViewMatchers
import com.google.android.material.bottomsheet.BottomSheetBehavior
import junit.framework.TestCase
import org.hamcrest.Matcher
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.Constants
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityComposeTestRule
import org.mozilla.fenix.helpers.MatcherHelper.assertItemContainingTextExists
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.clickAtLocationInView
import org.mozilla.fenix.helpers.idlingresource.BottomSheetBehaviorStateIdlingResource
@ -87,7 +86,7 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest
fun verifySyncedTabsListWhenUserIsNotSignedIn() {
verifySyncedTabsList()
assertItemContainingTextExists(
assertUIObjectExists(
itemContainingText(getStringResource(R.string.synced_tabs_sign_in_message)),
itemContainingText(getStringResource(R.string.sync_sign_in)),
itemContainingText(getStringResource(R.string.tab_drawer_fab_sync)),
@ -109,8 +108,9 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest
fun verifyNoExistingOpenTabs(vararg titles: String) {
titles.forEach { title ->
TestCase.assertFalse(
itemContainingText(title).waitForExists(TestAssetHelper.waitingTimeShort),
assertUIObjectExists(
itemContainingText(title),
exists = false,
)
}
}

@ -12,19 +12,17 @@ import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiSelector
import junit.framework.TestCase.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.Constants.LONG_CLICK_DURATION
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithDescriptionExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdAndTextExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdExists
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithDescription
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestHelper.appName
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.waitForObjects
@ -36,16 +34,16 @@ import org.mozilla.fenix.helpers.click
class CustomTabRobot {
fun verifyCustomTabsSiteInfoButton() =
assertItemWithResIdExists(
assertUIObjectExists(
itemWithResId("$packageName:id/mozac_browser_toolbar_security_indicator"),
)
fun verifyCustomTabsShareButton() =
assertItemWithDescriptionExists(
assertUIObjectExists(
itemWithDescription(getStringResource(R.string.mozac_feature_customtabs_share_link)),
)
fun verifyMainMenuButton() = assertItemWithResIdExists(mainMenuButton)
fun verifyMainMenuButton() = assertUIObjectExists(mainMenuButton)
fun verifyDesktopSiteButtonExists() {
desktopSiteButton().check(matches(isDisplayed()))
@ -55,26 +53,20 @@ class CustomTabRobot {
findInPageButton().check(matches(isDisplayed()))
}
fun verifyPoweredByTextIsDisplayed() {
assertTrue(
mDevice.findObject(UiSelector().textContains("POWERED BY $appName"))
.waitForExists(waitingTime),
)
}
fun verifyPoweredByTextIsDisplayed() =
assertUIObjectExists(itemContainingText("POWERED BY $appName"))
fun verifyOpenInBrowserButtonExists() {
openInBrowserButton().check(matches(isDisplayed()))
}
fun verifyBackButtonExists() = assertTrue(backButton().waitForExists(waitingTime))
fun verifyBackButtonExists() = assertUIObjectExists(itemWithDescription("Back"))
fun verifyForwardButtonExists() = assertTrue(forwardButton().waitForExists(waitingTime))
fun verifyForwardButtonExists() = assertUIObjectExists(itemWithDescription("Forward"))
fun verifyRefreshButtonExists() = assertTrue(refreshButton().waitForExists(waitingTime))
fun verifyRefreshButtonExists() = assertUIObjectExists(itemWithDescription("Refresh"))
fun verifyCustomMenuItem(label: String) {
assertTrue(mDevice.findObject(UiSelector().text(label)).waitForExists(waitingTime))
}
fun verifyCustomMenuItem(label: String) = assertUIObjectExists(itemContainingText(label))
fun verifyCustomTabCloseButton() {
closeButton().check(matches(isDisplayed()))
@ -95,17 +87,13 @@ class CustomTabRobot {
waitingTime,
)
assertTrue(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/mozac_browser_toolbar_title_view")
.textContains(title),
).waitForExists(waitingTime),
assertUIObjectExists(
itemWithResIdContainingText("$packageName:id/mozac_browser_toolbar_title_view", title),
)
}
fun verifyCustomTabUrl(Url: String) {
assertItemWithResIdAndTextExists(
assertUIObjectExists(
itemWithResIdContainingText("$packageName:id/mozac_browser_toolbar_url_view", Url.drop(7)),
)
}
@ -135,10 +123,10 @@ class CustomTabRobot {
fun clickCustomTabCloseButton() = closeButton().click()
fun verifyCustomTabActionButton(customTabActionButtonDescription: String) =
assertItemWithDescriptionExists(itemWithDescription(customTabActionButtonDescription))
assertUIObjectExists(itemWithDescription(customTabActionButtonDescription))
fun verifyPDFReaderToolbarItems() =
assertItemWithResIdAndTextExists(
assertUIObjectExists(
itemWithResIdAndText("download", "Download"),
itemWithResIdAndText("openInApp", "Open in app"),
)
@ -183,12 +171,6 @@ private fun findInPageButton() = onView(withText("Find in page"))
private fun openInBrowserButton() = onView(withText("Open in $appName"))
private fun refreshButton() = mDevice.findObject(UiSelector().description("Refresh"))
private fun forwardButton() = mDevice.findObject(UiSelector().description("Forward"))
private fun backButton() = mDevice.findObject(UiSelector().description("Back"))
private fun closeButton() = onView(withContentDescription("Return to previous app"))
private fun customTabToolbar() = mDevice.findObject(By.res("$packageName:id/toolbar"))

@ -7,6 +7,7 @@
package org.mozilla.fenix.ui.robots
import android.content.Intent
import android.net.Uri
import android.util.Log
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
@ -22,20 +23,20 @@ import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import org.hamcrest.CoreMatchers
import org.hamcrest.CoreMatchers.allOf
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.getPermissionAllowID
import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_APPS_PHOTOS
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithDescription
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeLong
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.click
@ -47,168 +48,181 @@ import org.mozilla.fenix.helpers.ext.waitNotNull
class DownloadRobot {
fun verifyDownloadPrompt(fileName: String) = assertDownloadPrompt(fileName)
fun verifyDownloadCompleteNotificationPopup() {
assertTrue(
"Download notification Open button not found",
mDevice.findObject(UiSelector().text("Open"))
.waitForExists(waitingTime),
)
assertTrue(
"Download completed notification text doesn't match",
mDevice.findObject(UiSelector().textContains("Download completed"))
.waitForExists(waitingTime),
)
assertTrue(
"Downloaded file name not visible",
mDevice.findObject(UiSelector().resourceId("$packageName:id/download_dialog_filename"))
.waitForExists(waitingTime),
)
fun verifyDownloadPrompt(fileName: String) {
var currentTries = 0
while (currentTries++ < 3) {
Log.i(TAG, "verifyDownloadPrompt: While loop currentTries = $currentTries")
try {
Log.i(TAG, "verifyDownloadPrompt: Try block")
assertUIObjectExists(
itemWithResId("$packageName:id/download_button"),
itemContainingText(fileName),
)
break
} catch (e: AssertionError) {
Log.i(TAG, "verifyDownloadPrompt: Catch block")
Log.e("DOWNLOAD_ROBOT", "Failed to find locator: ${e.localizedMessage}")
browserScreen {
}.clickDownloadLink(fileName) {
}
}
}
}
fun verifyDownloadFailedPrompt(fileName: String) {
assertTrue(
itemWithResId("$packageName:id/download_dialog_icon")
.waitForExists(waitingTime),
fun verifyDownloadCompleteNotificationPopup() =
assertUIObjectExists(
itemContainingText(getStringResource(R.string.mozac_feature_downloads_button_open)),
itemContainingText(getStringResource(R.string.mozac_feature_downloads_completed_notification_text2)),
itemWithResId("$packageName:id/download_dialog_filename"),
)
assertTrue(
"Download dialog title not displayed",
itemWithResIdAndText(
fun verifyDownloadFailedPrompt(fileName: String) =
assertUIObjectExists(
itemWithResId("$packageName:id/download_dialog_icon"),
itemWithResIdContainingText(
"$packageName:id/download_dialog_title",
"Download failed",
).waitForExists(waitingTime),
)
assertTrue(
"Download file name not displayed",
getStringResource(R.string.mozac_feature_downloads_failed_notification_text2),
),
itemWithResIdContainingText(
"$packageName:id/download_dialog_filename",
fileName,
).waitForExists(waitingTime),
)
assertTrue(
"Try again button not displayed",
itemWithResIdAndText(
),
itemWithResIdContainingText(
"$packageName:id/download_dialog_action_button",
"Try Again",
).waitForExists(waitingTime),
getStringResource(R.string.mozac_feature_downloads_button_try_again),
),
)
}
fun clickTryAgainButton() {
itemWithResIdAndText(
"$packageName:id/download_dialog_action_button",
"Try Again",
).click()
Log.i(TAG, "clickTryAgainButton: Clicked \"TRY AGAIN\" in app prompt button")
}
fun verifyPhotosAppOpens() = assertExternalAppOpens(GOOGLE_APPS_PHOTOS)
fun verifyDownloadedFileName(fileName: String) {
assertTrue(
"$fileName not found in Downloads list",
mDevice.findObject(UiSelector().text(fileName))
.waitForExists(waitingTime),
)
}
fun verifyDownloadedFileName(fileName: String) =
assertUIObjectExists(itemContainingText(fileName))
fun verifyDownloadedFileIcon() = assertDownloadedFileIcon()
fun verifyDownloadedFileIcon() = assertUIObjectExists(itemWithResId("$packageName:id/favicon"))
fun verifyEmptyDownloadsList() {
Log.i(TAG, "verifyEmptyDownloadsList: Looking for empty download list")
mDevice.findObject(UiSelector().resourceId("$packageName:id/download_empty_view"))
.waitForExists(waitingTime)
onView(withText("No downloaded files")).check(matches(isDisplayed()))
Log.i(TAG, "verifyEmptyDownloadsList: Verified \"No downloaded files\" list message")
}
fun waitForDownloadsListToExist() =
assertTrue(
"Downloads list either empty or not displayed",
mDevice.findObject(UiSelector().resourceId("$packageName:id/download_list"))
.waitForExists(waitingTime),
)
assertUIObjectExists(itemWithResId("$packageName:id/download_list"))
fun openDownloadedFile(fileName: String) {
downloadedFile(fileName)
.check(matches(isDisplayed()))
.click()
Log.i(TAG, "openDownloadedFile: Clicked downloaded file: $fileName")
}
fun deleteDownloadedItem(fileName: String) =
fun deleteDownloadedItem(fileName: String) {
onView(
allOf(
withId(R.id.overflow_menu),
hasSibling(withText(fileName)),
),
).click()
Log.i(TAG, "deleteDownloadedItem: Deleted downloaded file: $fileName using trash bin icon")
}
fun longClickDownloadedItem(title: String) =
fun longClickDownloadedItem(title: String) {
onView(
allOf(
withId(R.id.title),
withText(title),
),
).perform(longClick())
Log.i(TAG, "longClickDownloadedItem: Long clicked downloaded file: $title")
}
fun selectDownloadedItem(title: String) =
fun selectDownloadedItem(title: String) {
onView(
allOf(
withId(R.id.title),
withText(title),
),
).perform(click())
Log.i(TAG, "selectDownloadedItem: Selected downloaded file: $title")
}
fun openMultiSelectMoreOptionsMenu() =
fun openMultiSelectMoreOptionsMenu() {
itemWithDescription(getStringResource(R.string.content_description_menu)).click()
Log.i(TAG, "openMultiSelectMoreOptionsMenu: Clicked multi-select more options button")
}
fun clickMultiSelectRemoveButton() =
fun clickMultiSelectRemoveButton() {
itemWithResIdContainingText("$packageName:id/title", "Remove").click()
Log.i(TAG, "clickMultiSelectRemoveButton: Clicked multi-select remove button")
}
fun openPageAndDownloadFile(url: Uri, downloadFile: String) {
navigationToolbar {
}.enterURLAndEnterToBrowser(url) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
}
}
class Transition {
fun clickDownload(interact: DownloadRobot.() -> Unit): Transition {
downloadButton().click()
Log.i(TAG, "clickDownload: Clicked \"DOWNLOAD\" button from prompt")
DownloadRobot().interact()
return Transition()
}
fun closeCompletedDownloadPrompt(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
closeCompletedDownloadButton().click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun closeDownloadPrompt(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
itemWithResId("$packageName:id/download_dialog_close_button").click()
Log.i(TAG, "closeDownloadPrompt: Dismissed download prompt by clicking close prompt button")
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun clickOpen(type: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
Log.i(TAG, "clickOpen: Looking for \"OPEN\" download prompt button")
openDownloadButton().waitForExists(waitingTime)
openDownloadButton().click()
Log.i(TAG, "clickOpen: Clicked \"OPEN\" download prompt button")
// verify open intent is matched with associated data type
Intents.intended(
CoreMatchers.allOf(
allOf(
IntentMatchers.hasAction(Intent.ACTION_VIEW),
IntentMatchers.hasType(type),
),
)
Log.i(TAG, "clickOpen: Verified that open intent is matched with associated data type")
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun clickAllowPermission(interact: DownloadRobot.() -> Unit): Transition {
Log.i(TAG, "clickAllowPermission: Looking for \"ALLOW\" permission button")
mDevice.waitNotNull(
Until.findObject(By.res(TestHelper.getPermissionAllowID() + ":id/permission_allow_button")),
Until.findObject(By.res(getPermissionAllowID() + ":id/permission_allow_button")),
waitingTime,
)
val allowPermissionButton = mDevice.findObject(By.res(TestHelper.getPermissionAllowID() + ":id/permission_allow_button"))
allowPermissionButton.click()
mDevice.findObject(By.res(getPermissionAllowID() + ":id/permission_allow_button")).click()
Log.i(TAG, "clickAllowPermission: Clicked \"ALLOW\" permission button")
DownloadRobot().interact()
return Transition()
@ -216,6 +230,7 @@ class DownloadRobot {
fun exitDownloadsManagerToBrowser(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
onView(withContentDescription("Navigate up")).click()
Log.i(TAG, "exitDownloadsManagerToBrowser: Exited download manager to browser by clicking the navigate up toolbar button")
BrowserRobot().interact()
return BrowserRobot.Transition()
@ -223,6 +238,7 @@ class DownloadRobot {
fun goBack(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
goBackButton().click()
Log.i(TAG, "exitDownloadsManagerToBrowser: Exited download manager to home screen by clicking the navigate up toolbar button")
HomeScreenRobot().interact()
return HomeScreenRobot.Transition()
@ -235,38 +251,6 @@ fun downloadRobot(interact: DownloadRobot.() -> Unit): DownloadRobot.Transition
return DownloadRobot.Transition()
}
private fun assertDownloadPrompt(fileName: String) {
var currentTries = 0
while (currentTries++ < 3) {
try {
assertTrue(
"Download prompt button not visible",
mDevice.findObject(UiSelector().resourceId("$packageName:id/download_button"))
.waitForExists(waitingTimeLong),
)
assertTrue(
"$fileName title doesn't match",
mDevice.findObject(UiSelector().text(fileName))
.waitForExists(waitingTimeLong),
)
break
} catch (e: AssertionError) {
Log.e("DOWNLOAD_ROBOT", "Failed to find locator: ${e.localizedMessage}")
browserScreen {
}.clickDownloadLink(fileName) {
}
}
}
}
private fun closeCompletedDownloadButton() =
onView(withId(R.id.download_dialog_close_button))
private fun closePromptButton() =
onView(withId(R.id.close_button))
private fun downloadButton() =
onView(withId(R.id.download_button))
.check(matches(isDisplayed()))
@ -276,11 +260,4 @@ private fun openDownloadButton() =
private fun downloadedFile(fileName: String) = onView(withText(fileName))
private fun assertDownloadedFileIcon() =
assertTrue(
"Downloaded file icon not found",
mDevice.findObject(UiSelector().resourceId("$packageName:id/favicon"))
.exists(),
)
private fun goBackButton() = onView(withContentDescription("Navigate up"))

@ -17,15 +17,15 @@ import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import junit.framework.TestCase.assertTrue
import org.hamcrest.Matchers.allOf
import org.hamcrest.Matchers.containsString
import org.hamcrest.Matchers.not
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdExists
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.click
@ -42,10 +42,7 @@ class EnhancedTrackingProtectionRobot {
fun verifyETPSwitchVisibility(visible: Boolean) = assertETPSwitchVisibility(visible)
fun verifyCrossSiteCookiesBlocked(isBlocked: Boolean) {
assertTrue(
mDevice.findObject(UiSelector().resourceId("$packageName:id/cross_site_tracking"))
.waitForExists(waitingTime),
)
assertUIObjectExists(itemWithResId("$packageName:id/cross_site_tracking"))
crossSiteCookiesBlockListButton.click()
// Verifies the trackers block/allow list
onView(withId(R.id.details_blocking_header))
@ -63,10 +60,7 @@ class EnhancedTrackingProtectionRobot {
}
fun verifySocialMediaTrackersBlocked(isBlocked: Boolean) {
assertTrue(
mDevice.findObject(UiSelector().resourceId("$packageName:id/social_media_trackers"))
.waitForExists(waitingTime),
)
assertUIObjectExists(itemWithResId("$packageName:id/social_media_trackers"))
socialTrackersBlockListButton.click()
// Verifies the trackers block/allow list
onView(withId(R.id.details_blocking_header))
@ -85,10 +79,7 @@ class EnhancedTrackingProtectionRobot {
}
fun verifyFingerprintersBlocked(isBlocked: Boolean) {
assertTrue(
mDevice.findObject(UiSelector().resourceId("$packageName:id/fingerprinters"))
.waitForExists(waitingTime),
)
assertUIObjectExists(itemWithResId("$packageName:id/fingerprinters"))
fingerprintersBlockListButton.click()
// Verifies the trackers block/allow list
onView(withId(R.id.details_blocking_header))
@ -107,10 +98,7 @@ class EnhancedTrackingProtectionRobot {
}
fun verifyCryptominersBlocked(isBlocked: Boolean) {
assertTrue(
mDevice.findObject(UiSelector().resourceId("$packageName:id/cryptominers"))
.waitForExists(waitingTime),
)
assertUIObjectExists(itemWithResId("$packageName:id/cryptominers"))
cryptominersBlockListButton.click()
// Verifies the trackers block/allow list
onView(withId(R.id.details_blocking_header))
@ -129,10 +117,7 @@ class EnhancedTrackingProtectionRobot {
}
fun verifyTrackingContentBlocked(isBlocked: Boolean) {
assertTrue(
mDevice.findObject(UiSelector().text("Tracking Content"))
.waitForExists(waitingTime),
)
assertUIObjectExists(itemWithText("Tracking Content"))
trackingContentBlockListButton.click()
// Verifies the trackers block/allow list
onView(withId(R.id.details_blocking_header))
@ -166,7 +151,7 @@ class EnhancedTrackingProtectionRobot {
}
fun verifyETPSectionIsDisplayedInQuickSettingsSheet(isDisplayed: Boolean) =
assertItemWithResIdExists(
assertUIObjectExists(
itemWithResId("$packageName:id/trackingProtectionLayout"),
exists = isDisplayed,
)
@ -304,9 +289,5 @@ private val fingerprintersBlockListButton =
private fun assertSecuritySheetIsCompletelyDisplayed() {
mDevice.findObject(UiSelector().description(getStringResource(R.string.quick_settings_sheet)))
.waitForExists(waitingTime)
assertTrue(
mDevice.findObject(
UiSelector().resourceId("$packageName:id/quick_action_sheet"),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemWithResId("$packageName:id/quick_action_sheet"))
}

@ -21,13 +21,13 @@ import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import org.hamcrest.Matchers
import org.hamcrest.Matchers.allOf
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.click
@ -60,13 +60,8 @@ class HistoryRobot {
assertVisitedTimeTitle()
}
fun verifyHistoryItemExists(shouldExist: Boolean, item: String) {
if (shouldExist) {
assertTrue(mDevice.findObject(UiSelector().textContains(item)).waitForExists(waitingTime))
} else {
assertFalse(mDevice.findObject(UiSelector().textContains(item)).waitForExists(waitingTimeShort))
}
}
fun verifyHistoryItemExists(shouldExist: Boolean, item: String) =
assertUIObjectExists(itemContainingText(item), exists = shouldExist)
fun verifyFirstTestPageTitle(title: String) = assertTestPageTitle(title)
@ -111,22 +106,15 @@ class HistoryRobot {
snackBarUndoButton().click()
}
fun verifySearchGroupDisplayed(shouldBeDisplayed: Boolean, searchTerm: String, groupSize: Int) {
fun verifySearchGroupDisplayed(shouldBeDisplayed: Boolean, searchTerm: String, groupSize: Int) =
// checks if the search group exists in the Recently visited section
if (shouldBeDisplayed) {
assertTrue(
mDevice.findObject(UiSelector().text(searchTerm))
.getFromParent(UiSelector().text("$groupSize sites"))
.waitForExists(waitingTimeShort),
)
} else {
assertFalse(
mDevice.findObject(UiSelector().text(searchTerm))
.getFromParent(UiSelector().text("$groupSize sites"))
.waitForExists(waitingTimeShort),
)
}
}
assertUIObjectExists(
itemContainingText(searchTerm)
.getFromParent(
UiSelector().text("$groupSize sites"),
),
exists = shouldBeDisplayed,
)
fun openSearchGroup(searchTerm: String) {
mDevice.findObject(UiSelector().text(searchTerm)).waitForExists(waitingTime)
@ -208,10 +196,11 @@ private fun assertTestPageTitle(title: String) = testPageTitle()
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
.check(matches(withText(title)))
private fun assertDeleteConfirmationMessage() {
assertTrue(deleteHistoryPromptTitle().waitForExists(waitingTime))
assertTrue(deleteHistoryPromptSummary().waitForExists(waitingTime))
}
private fun assertDeleteConfirmationMessage() =
assertUIObjectExists(
itemWithResIdContainingText("$packageName:id/title", getStringResource(R.string.delete_history_prompt_title)),
itemWithResIdContainingText("$packageName:id/body", getStringResource(R.string.delete_history_prompt_body_2)),
)
private fun assertCopySnackBarText() = snackBarText().check(matches(withText("URL copied")))
@ -223,22 +212,6 @@ private fun snackBarUndoButton() = onView(withId(R.id.snackbar_btn))
private fun assertUndoDeleteSnackBarButton() =
snackBarUndoButton().check(matches(withText("UNDO")))
private fun deleteHistoryPromptTitle() =
mDevice
.findObject(
UiSelector()
.textContains(getStringResource(R.string.delete_history_prompt_title))
.resourceId("$packageName:id/title"),
)
private fun deleteHistoryPromptSummary() =
mDevice
.findObject(
UiSelector()
.textContains(getStringResource(R.string.delete_history_prompt_body_2))
.resourceId("$packageName:id/body"),
)
private fun deleteHistoryEverythingOption() =
mDevice
.findObject(

@ -6,6 +6,7 @@
package org.mozilla.fenix.ui.robots
import android.util.Log
import android.view.View
import android.widget.EditText
import android.widget.TextView
@ -47,25 +48,27 @@ import org.hamcrest.CoreMatchers.containsString
import org.hamcrest.CoreMatchers.instanceOf
import org.hamcrest.Matchers
import org.junit.Assert
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.Constants.LISTS_MAXSWIPES
import org.mozilla.fenix.helpers.Constants.LONG_CLICK_DURATION
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityComposeTestRule
import org.mozilla.fenix.helpers.MatcherHelper.assertItemContainingTextExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithDescriptionExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdAndTextExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdExists
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectIsGone
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithDescription
import org.mozilla.fenix.helpers.MatcherHelper.itemWithIndex
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndDescription
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndIndex
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.appName
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText
@ -83,55 +86,38 @@ class HomeScreenRobot {
" service provider, it makes it easier to keep what you do online private from anyone" +
" else who uses this device."
fun verifyNavigationToolbar() = assertItemWithResIdExists(navigationToolbar)
fun verifyNavigationToolbar() = assertUIObjectExists(navigationToolbar)
fun verifyHomeScreen() = assertItemWithResIdExists(homeScreen)
fun verifyHomeScreen() = assertUIObjectExists(homeScreen)
fun verifyPrivateBrowsingHomeScreenItems() {
verifyHomeScreenAppBarItems()
assertItemContainingTextExists(itemContainingText(privateSessionMessage))
assertUIObjectExists(itemContainingText(privateSessionMessage))
verifyCommonMythsLink()
}
fun verifyHomeScreenAppBarItems() =
assertItemWithResIdExists(homeScreen, privateBrowsingButton, homepageWordmark)
assertUIObjectExists(homeScreen, privateBrowsingButton, homepageWordmark)
fun verifyNavigationToolbarItems(numberOfOpenTabs: String = "0") {
assertItemWithResIdExists(navigationToolbar, menuButton)
assertItemWithResIdAndTextExists(tabCounter(numberOfOpenTabs))
}
fun verifyNavigationToolbarItems(numberOfOpenTabs: String = "0") =
assertUIObjectExists(navigationToolbar, menuButton, tabCounter(numberOfOpenTabs))
fun verifyHomePrivateBrowsingButton() = assertItemWithResIdExists(privateBrowsingButton)
fun verifyHomeMenuButton() = assertItemWithResIdExists(menuButton)
fun verifyHomePrivateBrowsingButton() = assertUIObjectExists(privateBrowsingButton)
fun verifyHomeMenuButton() = assertUIObjectExists(menuButton)
fun verifyTabButton() = assertTabButton()
fun verifyCollectionsHeader() = assertCollectionsHeader()
fun verifyNoCollectionsText() = assertNoCollectionsText()
fun verifyHomeWordmark() {
homeScreenList().scrollToBeginning(3)
assertItemWithResIdExists(homepageWordmark)
assertUIObjectExists(homepageWordmark)
}
fun verifyHomeComponent() = assertHomeComponent()
fun verifyTabCounter(numberOfOpenTabs: String) =
assertItemWithResIdAndTextExists(tabCounter(numberOfOpenTabs))
fun verifyWallpaperImageApplied(isEnabled: Boolean) {
if (isEnabled) {
assertTrue(
mDevice.findObject(
UiSelector().resourceId("$packageName:id/wallpaperImageView"),
).waitForExists(waitingTimeShort),
)
} else {
assertFalse(
mDevice.findObject(
UiSelector().resourceId("$packageName:id/wallpaperImageView"),
).waitForExists(waitingTimeShort),
)
}
assertUIObjectExists(tabCounter(numberOfOpenTabs))
mDevice.findObject(UiSelector())
}
fun verifyWallpaperImageApplied(isEnabled: Boolean) =
assertUIObjectExists(itemWithResId("$packageName:id/wallpaperImageView"), exists = isEnabled)
// Upgrading users onboarding dialog
fun verifyUpgradingUserOnboardingFirstScreen(testRule: ComposeTestRule) {
@ -147,6 +133,58 @@ class HomeScreenRobot {
}
}
fun verifyFirstOnboardingCard(composeTestRule: ComposeTestRule) {
composeTestRule.also {
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_default_browser_title_nimbus_2),
).assertExists()
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_default_browser_description_nimbus_2),
).assertExists()
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_default_browser_positive_button),
).assertExists()
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_default_browser_negative_button),
).assertExists()
}
}
fun verifySecondOnboardingCard(composeTestRule: ComposeTestRule) {
composeTestRule.also {
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_sign_in_title_2),
).assertExists()
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_sign_in_description_2),
).assertExists()
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_sign_in_positive_button),
).assertExists()
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_sign_in_negative_button),
).assertExists()
}
}
fun clickNotNowOnboardingButton(composeTestRule: ComposeTestRule) =
composeTestRule.onNodeWithText(
getStringResource(R.string.juno_onboarding_default_browser_negative_button),
).performClick()
fun swipeSecondOnboardingCardToRight() =
mDevice.findObject(
UiSelector().textContains(
getStringResource(R.string.juno_onboarding_sign_in_title_2),
),
).swipeRight(3)
fun clickGetStartedButton(testRule: ComposeTestRule) =
testRule.onNodeWithText(getStringResource(R.string.onboarding_home_get_started_button)).performClick()
@ -175,20 +213,18 @@ class HomeScreenRobot {
.performClick()
fun verifyCommonMythsLink() =
assertItemContainingTextExists(itemContainingText(getStringResource(R.string.private_browsing_common_myths)))
assertUIObjectExists(itemContainingText(getStringResource(R.string.private_browsing_common_myths)))
fun verifyExistingTopSitesList() = assertExistingTopSitesList()
fun verifyNotExistingTopSitesList(title: String) = assertNotExistingTopSitesList(title)
fun verifySponsoredShortcutDoesNotExist(sponsoredShortcutTitle: String, position: Int) =
assertFalse(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/top_site_item")
.index(position - 1),
).getChild(
UiSelector()
.textContains(sponsoredShortcutTitle),
).waitForExists(waitingTimeShort),
assertUIObjectExists(
itemWithResIdAndIndex("$packageName:id/top_site_item", index = position - 1)
.getChild(
UiSelector()
.textContains(sponsoredShortcutTitle),
),
exists = false,
)
fun verifyNotExistingSponsoredTopSitesList() = assertSponsoredTopSitesNotDisplayed()
fun verifyExistingTopSitesTabs(title: String) {
@ -204,35 +240,31 @@ class HomeScreenRobot {
fun verifyJumpBackInSectionIsDisplayed() {
scrollToElementByText(getStringResource(R.string.recent_tabs_header))
assertTrue(jumpBackInSection().waitForExists(waitingTime))
assertUIObjectExists(itemContainingText(getStringResource(R.string.recent_tabs_header)))
}
fun verifyJumpBackInSectionIsNotDisplayed() = assertJumpBackInSectionIsNotDisplayed()
fun verifyJumpBackInSectionIsNotDisplayed() =
assertUIObjectExists(itemContainingText(getStringResource(R.string.recent_tabs_header)), exists = false)
fun verifyJumpBackInItemTitle(testRule: ComposeTestRule, itemTitle: String) =
assertJumpBackInItemTitle(testRule, itemTitle)
fun verifyJumpBackInItemWithUrl(testRule: ComposeTestRule, itemUrl: String) =
assertJumpBackInItemWithUrl(testRule, itemUrl)
fun verifyJumpBackInShowAllButton() = assertJumpBackInShowAllButton()
fun verifyRecentlyVisitedSectionIsDisplayed() = assertRecentlyVisitedSectionIsDisplayed()
fun verifyRecentlyVisitedSectionIsNotDisplayed() = assertRecentlyVisitedSectionIsNotDisplayed()
fun verifyRecentBookmarksSectionIsDisplayed() = assertRecentBookmarksSectionIsDisplayed()
fun verifyRecentBookmarksSectionIsNotDisplayed() = assertRecentBookmarksSectionIsNotDisplayed()
fun verifyPocketSectionIsDisplayed() = assertPocketSectionIsDisplayed()
fun verifyPocketSectionIsNotDisplayed() = assertPocketSectionIsNotDisplayed()
fun verifyRecentlyVisitedSectionIsDisplayed(exists: Boolean) = assertRecentlyVisitedSectionIsDisplayed(exists)
fun verifyRecentBookmarksSectionIsDisplayed(exists: Boolean) = assertRecentBookmarksSectionIsDisplayed(exists)
fun verifyPocketSectionIsDisplayed(exists: Boolean) = assertPocketSectionIsDisplayed(exists)
fun verifyRecentlyVisitedSearchGroupDisplayed(shouldBeDisplayed: Boolean, searchTerm: String, groupSize: Int) {
// checks if the search group exists in the Recently visited section
if (shouldBeDisplayed) {
scrollToElementByText("Recently visited")
assertTrue(
mDevice.findObject(UiSelector().text(searchTerm))
.getFromParent(UiSelector().text("$groupSize sites"))
.waitForExists(waitingTimeShort),
assertUIObjectExists(
itemContainingText(searchTerm)
.getFromParent(UiSelector().text("$groupSize sites")),
)
} else {
assertTrue(
mDevice.findObject(UiSelector().text(searchTerm))
.getFromParent(UiSelector().text("$groupSize sites"))
.waitUntilGone(waitingTimeShort),
assertUIObjectIsGone(
itemContainingText(searchTerm)
.getFromParent(UiSelector().text("$groupSize sites")),
)
}
}
@ -240,9 +272,9 @@ class HomeScreenRobot {
// Collections elements
fun verifyCollectionIsDisplayed(title: String, collectionExists: Boolean = true) {
if (collectionExists) {
assertTrue(mDevice.findObject(UiSelector().text(title)).waitForExists(waitingTime))
assertUIObjectExists(itemContainingText(title))
} else {
assertTrue(mDevice.findObject(UiSelector().text(title)).waitUntilGone(waitingTime))
assertUIObjectIsGone(itemWithText(title))
}
}
@ -265,24 +297,10 @@ class HomeScreenRobot {
fun verifyThoughtProvokingStories(enabled: Boolean) {
if (enabled) {
scrollToElementByText(getStringResource(R.string.pocket_stories_header_1))
assertTrue(
mDevice.findObject(
UiSelector()
.textContains(
getStringResource(R.string.pocket_stories_header_1),
),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText(getStringResource(R.string.pocket_stories_header_1)))
} else {
homeScreenList().scrollToEnd(LISTS_MAXSWIPES)
assertFalse(
mDevice.findObject(
UiSelector()
.textContains(
getStringResource(R.string.pocket_stories_header_1),
),
).waitForExists(waitingTimeShort),
)
assertUIObjectExists(itemContainingText(getStringResource(R.string.pocket_stories_header_1)), exists = false)
}
}
@ -296,12 +314,7 @@ class HomeScreenRobot {
for (position in 0..8) {
pocketStoriesList
.scrollIntoView(UiSelector().index(position))
assertTrue(
"Pocket story item at position $position not found.",
mDevice.findObject(UiSelector().index(position))
.waitForExists(waitingTimeShort),
)
assertUIObjectExists(itemWithIndex(position))
}
}
@ -323,33 +336,16 @@ class HomeScreenRobot {
fun verifyDiscoverMoreStoriesButton() {
pocketStoriesList
.scrollIntoView(UiSelector().text("Discover more"))
assertTrue(
mDevice.findObject(UiSelector().text("Discover more"))
.waitForExists(waitingTimeShort),
)
assertUIObjectExists(itemWithText("Discover more"))
}
fun verifyStoriesByTopic(enabled: Boolean) {
if (enabled) {
scrollToElementByText(getStringResource(R.string.pocket_stories_categories_header))
assertTrue(
mDevice.findObject(
UiSelector()
.textContains(
getStringResource(R.string.pocket_stories_categories_header),
),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText(getStringResource(R.string.pocket_stories_categories_header)))
} else {
homeScreenList().scrollToEnd(LISTS_MAXSWIPES)
assertFalse(
mDevice.findObject(
UiSelector()
.textContains(
getStringResource(R.string.pocket_stories_categories_header),
),
).waitForExists(waitingTimeShort),
)
assertUIObjectExists(itemContainingText(getStringResource(R.string.pocket_stories_categories_header)), exists = false)
}
}
@ -375,26 +371,16 @@ class HomeScreenRobot {
fun verifyPoweredByPocket() {
homeScreenList().scrollIntoView(mDevice.findObject(UiSelector().resourceId("pocket.header")))
assertTrue(mDevice.findObject(UiSelector().resourceId("pocket.header.title")).exists())
assertUIObjectExists(itemWithResId("pocket.header.title"))
}
fun verifyCustomizeHomepageButton(enabled: Boolean) {
if (enabled) {
scrollToElementByText(getStringResource(R.string.browser_menu_customize_home_1))
assertTrue(
mDevice.findObject(
UiSelector()
.textContains("Customize homepage"),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText("Customize homepage"))
} else {
homeScreenList().scrollToEnd(LISTS_MAXSWIPES)
assertFalse(
mDevice.findObject(
UiSelector()
.textContains("Customize homepage"),
).waitForExists(waitingTimeShort),
)
assertUIObjectExists(itemContainingText("Customize homepage"), exists = false)
}
}
@ -444,6 +430,10 @@ class HomeScreenRobot {
)
}
fun verifyIfInPrivateOrNormalMode(privateBrowsingEnabled: Boolean) {
assert(isPrivateModeEnabled() == privateBrowsingEnabled)
}
class Transition {
fun openTabDrawer(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition {
@ -470,14 +460,20 @@ class HomeScreenRobot {
fun openThreeDotMenu(interact: ThreeDotMenuMainRobot.() -> Unit): ThreeDotMenuMainRobot.Transition {
// Issue: https://github.com/mozilla-mobile/fenix/issues/21578
try {
Log.i(TAG, "openThreeDotMenu: Try block")
Log.i(TAG, "openThreeDotMenu: Looking for main menu button")
mDevice.waitNotNull(
Until.findObject(By.res("$packageName:id/menuButton")),
waitingTime,
)
} catch (e: AssertionError) {
Log.i(TAG, "openThreeDotMenu: Catch block")
mDevice.pressBack()
Log.i(TAG, "openThreeDotMenu: Pressed device back button")
} finally {
Log.i(TAG, "openThreeDotMenu: Finally block")
threeDotButton().perform(click())
Log.i(TAG, "openThreeDotMenu: Clicked main menu button")
}
ThreeDotMenuMainRobot().interact()
@ -503,17 +499,16 @@ class HomeScreenRobot {
return SyncSignInRobot.Transition()
}
fun togglePrivateBrowsingMode() {
if (
!itemWithResIdAndDescription(
"$packageName:id/privateBrowsingButton",
"Disable private browsing",
).exists()
) {
mDevice.findObject(UiSelector().resourceId("$packageName:id/privateBrowsingButton"))
.waitForExists(
waitingTime,
)
fun togglePrivateBrowsingMode(switchPBModeOn: Boolean = true) {
// Switch to private browsing homescreen
if (switchPBModeOn && !isPrivateModeEnabled()) {
privateBrowsingButton.waitForExists(waitingTime)
privateBrowsingButton.click()
}
// Switch to normal browsing homescreen
if (!switchPBModeOn && isPrivateModeEnabled()) {
privateBrowsingButton.waitForExists(waitingTime)
privateBrowsingButton.click()
}
}
@ -672,9 +667,9 @@ class HomeScreenRobot {
}
fun expandCollection(title: String, interact: CollectionRobot.() -> Unit): CollectionRobot.Transition {
assertItemContainingTextExists(itemContainingText(title))
assertUIObjectExists(itemContainingText(title))
itemContainingText(title).clickAndWaitForNewWindow(waitingTimeShort)
assertItemWithDescriptionExists(itemWithDescription(getStringResource(R.string.remove_tab_from_collection)))
assertUIObjectExists(itemWithDescription(getStringResource(R.string.remove_tab_from_collection)))
CollectionRobot().interact()
return CollectionRobot.Transition()
@ -772,6 +767,30 @@ class HomeScreenRobot {
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun clickSetAsDefaultBrowserOnboardingButton(
composeTestRule: ComposeTestRule,
interact: SettingsRobot.() -> Unit,
): SettingsRobot.Transition {
composeTestRule.onNodeWithText(
getStringResource(R.string.juno_onboarding_default_browser_positive_button),
).performClick()
SettingsRobot().interact()
return SettingsRobot.Transition()
}
fun clickSignInOnboardingButton(
composeTestRule: ComposeTestRule,
interact: SyncSignInRobot.() -> Unit,
): SyncSignInRobot.Transition {
composeTestRule.onNodeWithText(
getStringResource(R.string.juno_onboarding_sign_in_positive_button),
).performClick()
SyncSignInRobot().interact()
return SyncSignInRobot.Transition()
}
}
}
@ -825,7 +844,7 @@ private fun assertHomeComponent() =
private fun threeDotButton() = onView(allOf(withId(R.id.menuButton)))
private fun assertExistingTopSitesList() =
assertItemWithResIdExists(itemWithResId("$packageName:id/top_sites_list"))
assertUIObjectExists(itemWithResId("$packageName:id/top_sites_list"))
private fun assertExistingTopSitesTabs(title: String) {
mDevice.findObject(
@ -840,62 +859,51 @@ private fun assertExistingTopSitesTabs(title: String) {
}
private fun assertSponsoredShortcutLogoIsDisplayed(position: Int) =
assertTrue(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/top_site_item")
.index(position - 1),
).getChild(
UiSelector()
.resourceId("$packageName:id/favicon_card"),
).waitForExists(waitingTime),
assertUIObjectExists(
itemWithResIdAndIndex(resourceId = "$packageName:id/top_site_item", index = position - 1)
.getChild(
UiSelector()
.resourceId("$packageName:id/favicon_card"),
),
)
private fun assertSponsoredSubtitleIsDisplayed(position: Int) =
assertTrue(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/top_site_item")
.index(position - 1),
).getChild(
UiSelector()
.resourceId("$packageName:id/top_site_subtitle"),
).waitForExists(waitingTime),
assertUIObjectExists(
itemWithResIdAndIndex(resourceId = "$packageName:id/top_site_item", index = position - 1)
.getChild(
UiSelector()
.resourceId("$packageName:id/top_site_subtitle"),
),
)
private fun assertSponsoredShortcutTitle(sponsoredShortcutTitle: String, position: Int) =
assertTrue(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/top_site_item")
.index(position - 1),
).getChild(
UiSelector()
.textContains(sponsoredShortcutTitle),
).waitForExists(waitingTime),
assertUIObjectExists(
itemWithResIdAndIndex(resourceId = "$packageName:id/top_site_item", index = position - 1)
.getChild(
UiSelector()
.textContains(sponsoredShortcutTitle),
),
)
private fun assertNotExistingTopSitesList(title: String) {
mDevice.findObject(UiSelector().text(title)).waitUntilGone(waitingTime)
assertFalse(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/top_site_title")
.textContains(title),
).waitForExists(waitingTimeShort),
assertUIObjectExists(
itemWithResIdContainingText(
"$packageName:id/top_site_title",
title,
),
exists = false,
)
}
private fun assertSponsoredTopSitesNotDisplayed() {
assertFalse(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/top_site_subtitle")
.textContains(getStringResource(R.string.top_sites_sponsored_label)),
).waitForExists(waitingTimeShort),
private fun assertSponsoredTopSitesNotDisplayed() =
assertUIObjectExists(
itemWithResIdContainingText(
"$packageName:id/top_site_subtitle",
getStringResource(R.string.top_sites_sponsored_label),
),
exists = false,
)
}
private fun assertTopSiteContextMenuItems() {
mDevice.waitNotNull(
@ -908,8 +916,6 @@ private fun assertTopSiteContextMenuItems() {
)
}
private fun assertJumpBackInSectionIsNotDisplayed() = assertFalse(jumpBackInSection().waitForExists(waitingTimeShort))
private fun assertJumpBackInItemTitle(testRule: ComposeTestRule, itemTitle: String) =
testRule.onNodeWithTag("recent.tab.title", useUnmergedTree = true).assert(hasText(itemTitle))
@ -917,44 +923,21 @@ private fun assertJumpBackInItemWithUrl(testRule: ComposeTestRule, itemUrl: Stri
testRule.onNodeWithTag("recent.tab.url", useUnmergedTree = true).assert(hasText(itemUrl))
private fun assertJumpBackInShowAllButton() =
assertTrue(
mDevice
.findObject(
UiSelector()
.textContains(getStringResource(R.string.recent_tabs_show_all)),
).waitForExists(waitingTime),
)
private fun assertRecentlyVisitedSectionIsDisplayed() = assertTrue(recentlyVisitedSection().waitForExists(waitingTime))
private fun assertRecentlyVisitedSectionIsNotDisplayed() = assertFalse(recentlyVisitedSection().waitForExists(waitingTimeShort))
assertUIObjectExists(itemContainingText(getStringResource(R.string.recent_tabs_show_all)))
private fun assertRecentBookmarksSectionIsDisplayed() =
assertTrue(recentBookmarksSection().waitForExists(waitingTime))
private fun assertRecentlyVisitedSectionIsDisplayed(exists: Boolean) =
assertUIObjectExists(itemContainingText(getStringResource(R.string.history_metadata_header_2)), exists = exists)
private fun assertRecentBookmarksSectionIsNotDisplayed() =
assertFalse(recentBookmarksSection().waitForExists(waitingTimeShort))
private fun assertRecentBookmarksSectionIsDisplayed(exists: Boolean) =
assertUIObjectExists(itemContainingText(getStringResource(R.string.recently_saved_title)), exists = exists)
private fun assertPocketSectionIsDisplayed() = assertTrue(pocketSection().waitForExists(waitingTime))
private fun assertPocketSectionIsNotDisplayed() = assertFalse(pocketSection().waitForExists(waitingTimeShort))
private fun assertPocketSectionIsDisplayed(exists: Boolean) =
assertUIObjectExists(itemContainingText(getStringResource(R.string.pocket_stories_header_1)), exists = exists)
private fun saveTabsToCollectionButton() = onView(withId(R.id.add_tabs_to_collections_button))
private fun tabsCounter() = onView(withId(R.id.tab_button))
private fun jumpBackInSection() =
mDevice.findObject(UiSelector().textContains(getStringResource(R.string.recent_tabs_header)))
private fun recentlyVisitedSection() =
mDevice.findObject(UiSelector().textContains(getStringResource(R.string.history_metadata_header_2)))
private fun recentBookmarksSection() =
mDevice.findObject(UiSelector().textContains(getStringResource(R.string.recently_saved_title)))
private fun pocketSection() =
mDevice.findObject(UiSelector().textContains(getStringResource(R.string.pocket_stories_header_1)))
private fun sponsoredShortcut(sponsoredShortcutTitle: String) =
mDevice.findObject(
By
@ -969,6 +952,13 @@ private val homeScreen =
itemWithResId("$packageName:id/homeLayout")
private val privateBrowsingButton =
itemWithResId("$packageName:id/privateBrowsingButton")
private fun isPrivateModeEnabled(): Boolean =
itemWithResIdAndDescription(
"$packageName:id/privateBrowsingButton",
"Disable private browsing",
).exists()
private val homepageWordmark =
itemWithResId("$packageName:id/wordmark")

@ -8,6 +8,7 @@ package org.mozilla.fenix.ui.robots
import android.net.Uri
import android.os.Build
import android.util.Log
import androidx.compose.ui.test.onNodeWithTag
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso.onView
@ -30,18 +31,22 @@ import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.CoreMatchers.not
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.Constants
import org.mozilla.fenix.helpers.Constants.LONG_CLICK_DURATION
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityComposeTestRule
import org.mozilla.fenix.helpers.MatcherHelper.assertItemTextEquals
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.SessionLoadedIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.waitForObjects
@ -76,32 +81,15 @@ class NavigationToolbarRobot {
readerViewToggle().click()
}
fun verifyClipboardSuggestionsAreDisplayed(link: String = "", shouldBeDisplayed: Boolean) {
when (shouldBeDisplayed) {
true -> {
assertTrue(
mDevice.findObject(UiSelector().resourceId("$packageName:id/fill_link_from_clipboard"))
.waitForExists(waitingTime),
)
assertTrue(
mDevice.findObject(UiSelector().resourceId("$packageName:id/clipboard_url").text(link))
.waitForExists(waitingTime),
)
}
false -> {
assertFalse(
mDevice.findObject(UiSelector().resourceId("$packageName:id/fill_link_from_clipboard"))
.waitForExists(waitingTimeShort),
)
assertFalse(
mDevice.findObject(UiSelector().resourceId("$packageName:id/clipboard_url").text(link))
.waitForExists(waitingTimeShort),
)
}
}
}
fun verifyClipboardSuggestionsAreDisplayed(link: String = "", shouldBeDisplayed: Boolean) =
assertUIObjectExists(
itemWithResId("$packageName:id/fill_link_from_clipboard"),
itemWithResIdAndText(
"$packageName:id/clipboard_url",
link,
),
exists = shouldBeDisplayed,
)
fun longClickEditModeToolbar() =
mDevice.findObject(By.res("$packageName:id/mozac_browser_toolbar_edit_url_view")).click(LONG_CLICK_DURATION)
@ -125,17 +113,13 @@ class NavigationToolbarRobot {
// New unified search UI selector
fun verifySearchBarPlaceholder(text: String) {
urlBar().waitForExists(waitingTime)
assertTrue(
urlBar().text == text,
)
assertItemTextEquals(urlBar(), expectedText = text)
}
// New unified search UI selector
fun verifyDefaultSearchEngine(engineName: String) =
assertTrue(
searchSelectorButton
.getChild(UiSelector().description(engineName))
.waitForExists(waitingTime),
assertUIObjectExists(
searchSelectorButton.getChild(UiSelector().description(engineName)),
)
fun verifyTextSelectionOptions(vararg textSelectionOptions: String) {
@ -154,19 +138,18 @@ class NavigationToolbarRobot {
sessionLoadedIdlingResource = SessionLoadedIdlingResource()
openEditURLView()
Log.i(TAG, "enterURLAndEnterToBrowser: Opened edit mode URL view")
awesomeBar().setText(url.toString())
Log.i(TAG, "enterURLAndEnterToBrowser: Set toolbar text to: $url")
mDevice.pressEnter()
Log.i(TAG, "enterURLAndEnterToBrowser: Clicked enter on keyboard, submitted query")
runWithIdleRes(sessionLoadedIdlingResource) {
assertTrue(
mDevice.findObject(
UiSelector().resourceId("$packageName:id/browserLayout"),
).waitForExists(waitingTime) || mDevice.findObject(
UiSelector().resourceId("$packageName:id/download_button"),
).waitForExists(waitingTime) || mDevice.findObject(
UiSelector().text(getStringResource(R.string.tcp_cfr_message)),
).waitForExists(waitingTime),
itemWithResId("$packageName:id/browserLayout").waitForExists(waitingTime) ||
itemWithResId("$packageName:id/download_button").waitForExists(waitingTime) ||
itemWithText(getStringResource(R.string.tcp_cfr_message)).waitForExists(waitingTime),
)
}
@ -290,8 +273,9 @@ class NavigationToolbarRobot {
}
fun openTabButtonShortcutsMenu(interact: NavigationToolbarRobot.() -> Unit): Transition {
mDevice.waitNotNull(Until.findObject(By.desc("Tabs")))
mDevice.waitNotNull(Until.findObject(By.res("$packageName:id/counter_root")))
tabsCounter().click(LONG_CLICK_DURATION)
Log.i(TAG, "Tabs counter long-click successful.")
NavigationToolbarRobot().interact()
return Transition()
@ -309,6 +293,7 @@ class NavigationToolbarRobot {
ViewActions.click(),
),
)
Log.i(TAG, "Clicked the tab shortcut Close tab button.")
NavigationToolbarRobot().interact()
return Transition()
@ -316,7 +301,7 @@ class NavigationToolbarRobot {
fun openNewTabFromShortcutsMenu(interact: SearchRobot.() -> Unit): SearchRobot.Transition {
mDevice.waitForIdle(waitingTime)
Log.i(TAG, "Looking for tab shortcut New tab button.")
onView(withId(R.id.mozac_browser_menu_recyclerView))
.perform(
RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>(
@ -326,6 +311,7 @@ class NavigationToolbarRobot {
ViewActions.click(),
),
)
Log.i(TAG, "Clicked the tab shortcut New tab button.")
SearchRobot().interact()
return SearchRobot.Transition()
@ -333,7 +319,7 @@ class NavigationToolbarRobot {
fun openNewPrivateTabFromShortcutsMenu(interact: SearchRobot.() -> Unit): SearchRobot.Transition {
mDevice.waitForIdle(waitingTime)
Log.i(TAG, "Looking for tab shortcut New private tab button.")
onView(withId(R.id.mozac_browser_menu_recyclerView))
.perform(
RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>(
@ -343,6 +329,7 @@ class NavigationToolbarRobot {
ViewActions.click(),
),
)
Log.i(TAG, "Clicked the tab shortcut New private tab button.")
SearchRobot().interact()
return SearchRobot.Transition()
@ -375,15 +362,11 @@ fun navigationToolbar(interact: NavigationToolbarRobot.() -> Unit): NavigationTo
}
fun openEditURLView() {
mDevice.waitNotNull(
Until.findObject(By.res("$packageName:id/toolbar")),
waitingTime,
)
urlBar().waitForExists(waitingTime)
urlBar().click()
mDevice.waitNotNull(
Until.findObject(By.res("$packageName:id/mozac_browser_toolbar_edit_url_view")),
waitingTime,
)
Log.i(TAG, "openEditURLView: URL bar clicked.")
itemWithResId("$packageName:id/mozac_browser_toolbar_edit_url_view").waitForExists(waitingTime)
Log.i(TAG, "openEditURLView: Edit URL bar displayed.")
}
private fun assertNoHistoryBookmarks() {

@ -6,13 +6,14 @@ package org.mozilla.fenix.ui.robots
import android.app.NotificationManager
import android.content.Context
import android.util.Log
import androidx.test.uiautomator.UiScrollable
import androidx.test.uiautomator.UiSelector
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.helpers.Constants.RETRY_COUNT
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdAndTextExists
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper
@ -29,34 +30,43 @@ class NotificationRobot {
while (!notificationFound) {
scrollToEnd()
Log.i(TAG, "verifySystemNotificationExists: Scrolling to the end of the notification tray")
Log.i(TAG, "verifySystemNotificationExists: Looking for $notificationMessage notification")
notificationFound = mDevice.findObject(notification).waitForExists(waitingTime)
}
assertTrue(notificationFound)
assertUIObjectExists(itemWithText(notificationMessage))
}
fun clearNotifications() {
if (clearButton.exists()) {
Log.i(TAG, "clearNotifications: Verified that clear notifications button exists")
clearButton.click()
Log.i(TAG, "clearNotifications: Clicked clear notifications button")
} else {
scrollToEnd()
Log.i(TAG, "clearNotifications: Scrolled to end of notifications tray")
if (clearButton.exists()) {
Log.i(TAG, "clearNotifications: Verified that clear notifications button exists")
clearButton.click()
Log.i(TAG, "clearNotifications: Clicked clear notifications button")
} else if (notificationTray().exists()) {
mDevice.pressBack()
Log.i(TAG, "clearNotifications: Dismiss notifications tray by clicking device back button")
}
}
}
fun cancelAllShownNotifications() {
cancelAll()
Log.i(TAG, "cancelAllShownNotifications: Canceled all system notifications")
}
fun verifySystemNotificationDoesNotExist(notificationMessage: String) {
Log.i(TAG, "verifySystemNotificationDoesNotExist: Waiting for $notificationMessage notification to be gone")
mDevice.findObject(UiSelector().textContains(notificationMessage)).waitUntilGone(waitingTime)
assertFalse(
mDevice.findObject(UiSelector().textContains(notificationMessage)).waitForExists(waitingTimeShort),
)
assertUIObjectExists(itemContainingText(notificationMessage), exists = false)
Log.i(TAG, "verifySystemNotificationDoesNotExist: Verified that $notificationMessage notification does not exist")
}
fun verifyPrivateTabsNotification() {
@ -71,42 +81,49 @@ class NotificationRobot {
fun clickDownloadNotificationControlButton(action: String) {
for (i in 1..RETRY_COUNT) {
Log.i(TAG, "clickPageObject: For loop i = $i")
try {
assertItemWithResIdAndTextExists(downloadSystemNotificationButton(action))
assertUIObjectExists(downloadSystemNotificationButton(action))
downloadSystemNotificationButton(action).clickAndWaitForNewWindow(waitingTimeShort)
assertItemWithResIdAndTextExists(
Log.i(TAG, "clickDownloadNotificationControlButton: Clicked app notification $action button and waits for a new window for $waitingTimeShort ms")
assertUIObjectExists(
downloadSystemNotificationButton(action),
exists = false,
)
break
} catch (e: AssertionError) {
Log.i(TAG, "clickDownloadNotificationControlButton: Catch block")
if (i == RETRY_COUNT) {
throw e
}
mDevice.waitForWindowUpdate(packageName, waitingTimeShort)
Log.i(TAG, "clickDownloadNotificationControlButton: Waited $waitingTimeShort ms for window update")
}
}
}
fun verifyMediaSystemNotificationButtonState(action: String) {
assertTrue(mediaSystemNotificationButton(action).waitForExists(waitingTime))
}
fun verifyMediaSystemNotificationButtonState(action: String) =
assertUIObjectExists(mediaSystemNotificationButton(action))
fun expandNotificationMessage() {
while (!notificationHeader.exists()) {
scrollToEnd()
Log.i(TAG, "expandNotificationMessage: Scrolled to end of notification tray")
}
if (notificationHeader.exists()) {
// expand the notification
notificationHeader.click()
Log.i(TAG, "expandNotificationMessage: Clicked the app notification")
// double check if notification actions are viewable by checking for action existence; otherwise scroll again
while (!mDevice.findObject(UiSelector().resourceId("android:id/action0")).exists() &&
!mDevice.findObject(UiSelector().resourceId("android:id/actions_container")).exists()
) {
Log.i(TAG, "expandNotificationMessage: App notification action buttons do not exist")
scrollToEnd()
Log.i(TAG, "expandNotificationMessage: Scrolled to end of notification tray")
}
}
}
@ -119,9 +136,12 @@ class NotificationRobot {
) {
// In case it fails, retry max 3x the swipe action on download system notifications
for (i in 1..RETRY_COUNT) {
Log.i(TAG, "swipeDownloadNotification: For loop i = $i")
try {
Log.i(TAG, "swipeDownloadNotification: Try block")
var retries = 0
while (itemContainingText(appName).exists() && retries++ < 3) {
Log.i(TAG, "swipeDownloadNotification: While loop retries = $retries")
// Swipe left the download system notification
if (direction == "Left") {
itemContainingText(appName)
@ -129,6 +149,7 @@ class NotificationRobot {
it.waitForExists(waitingTime)
it.swipeLeft(3)
}
Log.i(TAG, "swipeDownloadNotification: Swiped left download notification")
} else {
// Swipe right the download system notification
itemContainingText(appName)
@ -136,17 +157,20 @@ class NotificationRobot {
it.waitForExists(waitingTime)
it.swipeRight(3)
}
Log.i(TAG, "swipeDownloadNotification: Swiped right download notification")
}
}
// Not all download related system notifications can be dismissed
if (shouldDismissNotification) {
assertFalse(itemContainingText(appName).waitForExists(waitingTimeShort))
assertUIObjectExists(itemContainingText(appName), exists = false)
} else {
assertTrue(itemContainingText(appName).waitForExists(waitingTimeShort))
assertUIObjectExists(itemContainingText(appName))
Log.i(TAG, "swipeDownloadNotification: Verified that $appName notification exist")
}
break
} catch (e: AssertionError) {
Log.i(TAG, "swipeDownloadNotification: Catch block")
if (i == RETRY_COUNT) {
throw e
} else {
@ -157,6 +181,7 @@ class NotificationRobot {
if (canExpandNotification) {
// In all cases the download system notification title will be the app name
verifySystemNotificationExists(appName)
Log.i(TAG, "swipeDownloadNotification: Verified that $appName notification exist")
expandNotificationMessage()
} else {
// Using the download completed system notification summary to bring in to view an properly verify it
@ -169,17 +194,17 @@ class NotificationRobot {
}
fun clickNotification(notificationMessage: String) {
Log.i(TAG, "clickNotification: Looking for $notificationMessage notification")
mDevice.findObject(UiSelector().text(notificationMessage)).waitForExists(waitingTime)
mDevice.findObject(UiSelector().text(notificationMessage)).clickAndWaitForNewWindow(waitingTimeShort)
Log.i(TAG, "clickNotification: Clicked $notificationMessage notification and waiting for $waitingTimeShort ms for a new window")
}
class Transition {
fun clickClosePrivateTabsNotification(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
try {
assertTrue(
closePrivateTabsNotification().exists(),
)
assertUIObjectExists(closePrivateTabsNotification())
} catch (e: AssertionError) {
notificationTray().flingToEnd(1)
}
@ -192,6 +217,7 @@ class NotificationRobot {
fun closeNotificationTray(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
mDevice.pressBack()
Log.i(TAG, "closeNotificationTray: Closed notification tray using device back button")
BrowserRobot().interact()
return BrowserRobot.Transition()

@ -5,14 +5,14 @@
package org.mozilla.fenix.ui.robots
import androidx.test.uiautomator.UiSelector
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.helpers.TestHelper.isExternalAppBrowserActivityInCurrentTask
import org.mozilla.fenix.helpers.AppAndSystemHelper.isExternalAppBrowserActivityInCurrentTask
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
class PwaRobot {
fun verifyCustomTabToolbarIsNotDisplayed() = assertFalse(customTabToolbar().exists())
fun verifyCustomTabToolbarIsNotDisplayed() = assertUIObjectExists(customTabToolbar(), exists = false)
fun verifyPwaActivityInCurrentTask() = assertTrue(isExternalAppBrowserActivityInCurrentTask())
class Transition

@ -18,7 +18,7 @@ import org.hamcrest.Matchers
import org.hamcrest.Matchers.allOf
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.HomeActivityComposeTestRule
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdAndTextExists
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
@ -57,7 +57,7 @@ class RecentlyClosedTabsRobot {
}
fun verifyRecentlyClosedTabsPageTitle(title: String) =
assertItemWithResIdAndTextExists(
assertUIObjectExists(
recentlyClosedTabsPageTitle(title),
)

@ -29,22 +29,25 @@ import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiSelector
import org.hamcrest.CoreMatchers.allOf
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.AppAndSystemHelper.grantSystemPermission
import org.mozilla.fenix.helpers.AppAndSystemHelper.isPackageInstalled
import org.mozilla.fenix.helpers.Constants
import org.mozilla.fenix.helpers.Constants.LONG_CLICK_DURATION
import org.mozilla.fenix.helpers.Constants.RETRY_COUNT
import org.mozilla.fenix.helpers.Constants.SPEECH_RECOGNITION
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdExists
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.MatcherHelper.assertItemTextContains
import org.mozilla.fenix.helpers.MatcherHelper.assertItemTextEquals
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectIsGone
import org.mozilla.fenix.helpers.MatcherHelper.itemWithDescription
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.SessionLoadedIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.grantSystemPermission
import org.mozilla.fenix.helpers.TestHelper.isPackageInstalled
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.waitForObjects
@ -53,38 +56,19 @@ import org.mozilla.fenix.helpers.TestHelper.waitForObjects
* Implementation of Robot Pattern for the search fragment.
*/
class SearchRobot {
fun verifySearchView() =
assertTrue(
mDevice.findObject(
UiSelector().resourceId("$packageName:id/search_wrapper"),
).waitForExists(waitingTime),
)
fun verifySearchView() = assertUIObjectExists(itemWithResId("$packageName:id/search_wrapper"))
fun verifySearchToolbar(isDisplayed: Boolean) =
assertItemWithResIdExists(
assertUIObjectExists(
itemWithResId("$packageName:id/mozac_browser_toolbar_edit_url_view"),
exists = isDisplayed,
)
fun verifyScanButtonVisibility(visible: Boolean = true) {
if (visible) {
assertTrue(
scanButton.waitForExists(waitingTime),
)
} else {
assertTrue(
scanButton.waitUntilGone(waitingTime),
)
}
}
fun verifyScanButtonVisibility(visible: Boolean = true) =
assertUIObjectExists(scanButton, exists = visible)
fun verifyVoiceSearchButtonVisibility(enabled: Boolean) {
if (enabled) {
assertTrue(voiceSearchButton.waitForExists(waitingTime))
} else {
assertFalse(voiceSearchButton.waitForExists(waitingTimeShort))
}
}
fun verifyVoiceSearchButtonVisibility(enabled: Boolean) =
assertUIObjectExists(voiceSearchButton, exists = enabled)
// Device or AVD requires a Google Services Android OS installation
fun startVoiceSearch() {
@ -154,33 +138,14 @@ class SearchRobot {
}
}
fun verifyAllowSuggestionsInPrivateModeDialog() {
assertTrue(
mDevice.findObject(
UiSelector().text(getStringResource(R.string.search_suggestions_onboarding_title)),
).waitForExists(waitingTime),
)
assertTrue(
mDevice.findObject(
UiSelector().text(getStringResource(R.string.search_suggestions_onboarding_text)),
).exists(),
)
assertTrue(
mDevice.findObject(
UiSelector().text("Learn more"),
).exists(),
fun verifyAllowSuggestionsInPrivateModeDialog() =
assertUIObjectExists(
itemWithText(getStringResource(R.string.search_suggestions_onboarding_title)),
itemWithText(getStringResource(R.string.search_suggestions_onboarding_text)),
itemWithText("Learn more"),
itemWithText(getStringResource(R.string.search_suggestions_onboarding_allow_button)),
itemWithText(getStringResource(R.string.search_suggestions_onboarding_do_not_allow_button)),
)
assertTrue(
mDevice.findObject(
UiSelector().text(getStringResource(R.string.search_suggestions_onboarding_allow_button)),
).exists(),
)
assertTrue(
mDevice.findObject(
UiSelector().text(getStringResource(R.string.search_suggestions_onboarding_do_not_allow_button)),
).exists(),
)
}
fun denySuggestionsInPrivateMode() {
mDevice.findObject(
@ -194,37 +159,28 @@ class SearchRobot {
).click()
}
fun verifySearchSelectorButton() {
assertTrue(searchSelectorButton.waitForExists(waitingTime))
}
fun verifySearchSelectorButton() = assertUIObjectExists(searchSelectorButton)
fun clickSearchSelectorButton() {
searchSelectorButton.waitForExists(waitingTime)
searchSelectorButton.click()
}
fun verifySearchEngineIcon(name: String) =
assertTrue(itemWithDescription(name).waitForExists(waitingTime))
fun verifySearchEngineIcon(name: String) = assertUIObjectExists(itemWithDescription(name))
fun verifySearchBarPlaceholder(text: String) {
browserToolbarEditView().waitForExists(waitingTime)
assertTrue(
browserToolbarEditView().text == text,
)
assertItemTextEquals(browserToolbarEditView(), expectedText = text)
}
fun verifySearchShortcutListContains(vararg searchEngineName: String, shouldExist: Boolean = true) {
searchEngineName.forEach {
if (shouldExist) {
assertTrue(
searchShortcutList.getChild(UiSelector().text(it))
.waitForExists(waitingTimeShort),
assertUIObjectExists(
searchShortcutList.getChild(UiSelector().text(it)),
)
} else {
assertTrue(
searchShortcutList.getChild(UiSelector().text(it))
.waitUntilGone(waitingTimeShort),
)
assertUIObjectIsGone(searchShortcutList.getChild(UiSelector().text(it)))
}
}
}
@ -304,7 +260,7 @@ class SearchRobot {
}
fun verifyTranslatedFocusedNavigationToolbar(toolbarHintString: String) =
assertTrue(browserToolbarEditView().text.contains(toolbarHintString))
assertItemTextContains(browserToolbarEditView(), itemText = toolbarHintString)
fun verifyTypedToolbarText(expectedText: String) {
mDevice.findObject(UiSelector().resourceId("$packageName:id/toolbar"))
@ -323,9 +279,9 @@ class SearchRobot {
onView(withId(R.id.toolbar))
.check(
if (bottomPosition) {
PositionAssertions.isCompletelyBelow(withId(R.id.pill_wrapper_divider))
PositionAssertions.isCompletelyBelow(withId(R.id.keyboard_divider))
} else {
PositionAssertions.isCompletelyAbove(withId(R.id.pill_wrapper_divider))
PositionAssertions.isCompletelyAbove(withId(R.id.keyboard_divider))
},
)
}
@ -334,14 +290,13 @@ class SearchRobot {
private lateinit var sessionLoadedIdlingResource: SessionLoadedIdlingResource
fun dismissSearchBar(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
mDevice.waitForIdle()
closeSoftKeyboard()
mDevice.pressBack()
try {
assertTrue(searchWrapper().waitUntilGone(waitingTimeShort))
searchWrapper().waitForExists(waitingTime)
mDevice.pressBack()
assertUIObjectIsGone(searchWrapper())
} catch (e: AssertionError) {
mDevice.pressBack()
assertTrue(searchWrapper().waitUntilGone(waitingTimeShort))
assertUIObjectIsGone(searchWrapper())
}
HomeScreenRobot().interact()
@ -364,11 +319,7 @@ class SearchRobot {
mDevice.pressEnter()
runWithIdleRes(sessionLoadedIdlingResource) {
assertTrue(
mDevice.findObject(
UiSelector().resourceId("$packageName:id/browserLayout"),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemWithResId("$packageName:id/browserLayout"))
}
BrowserRobot().interact()

@ -8,6 +8,7 @@ package org.mozilla.fenix.ui.robots
import android.content.Intent
import android.net.Uri
import android.util.Log
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.ViewInteraction
@ -40,20 +41,20 @@ import junit.framework.AssertionFailedError
import org.hamcrest.CoreMatchers
import org.hamcrest.CoreMatchers.endsWith
import org.hamcrest.Matchers.allOf
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.AppAndSystemHelper.isPackageInstalled
import org.mozilla.fenix.helpers.Constants.LISTS_MAXSWIPES
import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_PLAY_SERVICES
import org.mozilla.fenix.helpers.Constants.RETRY_COUNT
import org.mozilla.fenix.helpers.MatcherHelper.assertItemContainingTextExists
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.appName
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.hasCousin
import org.mozilla.fenix.helpers.TestHelper.isPackageInstalled
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText
@ -76,7 +77,7 @@ class SettingsRobot {
fun verifyAccessibilityButton() = assertAccessibilityButton()
fun verifySetAsDefaultBrowserButton() = assertSetAsDefaultBrowserButton()
fun verifyTabsButton() =
assertItemContainingTextExists(itemContainingText(getStringResource(R.string.preferences_tabs)))
assertUIObjectExists(itemContainingText(getStringResource(R.string.preferences_tabs)))
fun verifyHomepageButton() = assertHomepageButton()
fun verifyAutofillButton() = assertAutofillButton()
fun verifyLanguageButton() = assertLanguageButton()
@ -106,9 +107,6 @@ class SettingsRobot {
fun verifyPrivacyHeading() = assertPrivacyHeading()
fun verifyHTTPSOnlyModeButton() = assertHTTPSOnlyModeButton()
fun verifyCookieBannerReductionButton() =
onView(withText(R.string.preferences_cookie_banner_reduction)).check(matches(isDisplayed()))
fun verifyEnhancedTrackingProtectionButton() = assertEnhancedTrackingProtectionButton()
fun verifyLoginsAndPasswordsButton() = assertLoginsAndPasswordsButton()
fun verifyPrivateBrowsingButton() = assertPrivateBrowsingButton()
@ -188,8 +186,8 @@ class SettingsRobot {
// ABOUT SECTION
fun verifyAboutHeading() = assertAboutHeading()
fun verifyRateOnGooglePlay() = assertTrue(rateOnGooglePlayHeading().waitForExists(waitingTime))
fun verifyAboutFirefoxPreview() = assertTrue(aboutFirefoxHeading().waitForExists(waitingTime))
fun verifyRateOnGooglePlay() = assertUIObjectExists(rateOnGooglePlayHeading())
fun verifyAboutFirefoxPreview() = assertUIObjectExists(aboutFirefoxHeading())
fun verifyGooglePlayRedirect() = assertGooglePlayRedirect()
fun verifySettingsOptionSummary(setting: String, summary: String) {
@ -210,6 +208,14 @@ class SettingsRobot {
return HomeScreenRobot.Transition()
}
fun goBackToOnboardingScreen(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
mDevice.pressBack()
mDevice.waitForIdle(waitingTimeShort)
HomeScreenRobot().interact()
return HomeScreenRobot.Transition()
}
fun goBackToBrowser(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
goBackButton().click()
@ -264,8 +270,10 @@ class SettingsRobot {
fun openAutofillSubMenu(interact: SettingsSubMenuAutofillRobot.() -> Unit): SettingsSubMenuAutofillRobot.Transition {
mDevice.findObject(UiSelector().textContains(getStringResource(R.string.preferences_autofill)))
.also {
Log.i(TAG, "openAutofillSubMenu: Looking for \"Autofill\" settings button")
it.waitForExists(waitingTime)
it.click()
Log.i(TAG, "openAutofillSubMenu: Clicked \"Autofill\" settings button")
}
SettingsSubMenuAutofillRobot().interact()
@ -311,14 +319,6 @@ class SettingsRobot {
return SettingsSubMenuSetDefaultBrowserRobot.Transition()
}
fun openCookieBannerReductionSubMenu(interact: SettingsSubMenuCookieBannerReductionRobot.() -> Unit): SettingsSubMenuCookieBannerReductionRobot.Transition {
scrollToElementByText(getStringResource(R.string.preferences_cookie_banner_reduction))
itemContainingText(getStringResource(R.string.preferences_cookie_banner_reduction)).click()
SettingsSubMenuCookieBannerReductionRobot().interact()
return SettingsSubMenuCookieBannerReductionRobot.Transition()
}
fun openEnhancedTrackingProtectionSubMenu(interact: SettingsSubMenuEnhancedTrackingProtectionRobot.() -> Unit): SettingsSubMenuEnhancedTrackingProtectionRobot.Transition {
scrollToElementByText("Enhanced Tracking Protection")
fun enhancedTrackingProtectionButton() =
@ -428,8 +428,7 @@ class SettingsRobot {
fun openExperimentsMenu(interact: SettingsSubMenuExperimentsRobot.() -> Unit): SettingsSubMenuExperimentsRobot.Transition {
scrollToElementByText("Nimbus Experiments")
fun nimbusExperimentsButton() = mDevice.findObject(textContains("Nimbus Experiments"))
nimbusExperimentsButton().click()
onView(withText(getStringResource(R.string.preferences_nimbus_experiments))).click()
SettingsSubMenuExperimentsRobot().interact()
return SettingsSubMenuExperimentsRobot.Transition()
@ -640,10 +639,7 @@ private fun aboutFirefoxHeading(): UiObject {
for (i in 1..RETRY_COUNT) {
try {
settingsList().scrollToEnd(LISTS_MAXSWIPES)
assertTrue(
mDevice.findObject(UiSelector().text("About $appName"))
.waitForExists(waitingTime),
)
assertUIObjectExists(itemWithText("About $appName"))
break
} catch (e: AssertionError) {

@ -26,14 +26,13 @@ import androidx.test.uiautomator.UiSelector
import mozilla.components.support.utils.ext.getPackageInfoCompat
import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.CoreMatchers.containsString
import org.junit.Assert.assertTrue
import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.Constants.LISTS_MAXSWIPES
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.appName
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.settings.SupportUtils
import java.text.SimpleDateFormat
@ -156,11 +155,7 @@ private fun assertCrashes() {
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
.perform(click())
assertTrue(
mDevice.findObject(
UiSelector().textContains("No crash reports have been submitted."),
).waitForExists(waitingTime),
)
assertUIObjectExists(itemContainingText("No crash reports have been submitted."))
for (i in 1..3) {
Espresso.pressBack()

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save