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

pull/700/head
akliuxingyuan 7 months ago
commit 10defdb011

@ -35,6 +35,7 @@ projects:
- feature-customtabs
- feature-downloads
- feature-findinpage
- feature-fxsuggest
- feature-intent
- feature-logins
- feature-media

@ -15,6 +15,14 @@ extensions-process:
enabled:
type: boolean
description: "If true, the extensions process is enabled."
fx-suggest:
description: A feature that provides Firefox Suggest search suggestions.
hasExposure: true
exposureDescription: ""
variables:
enabled:
type: boolean
description: "Whether the feature is enabled. When Firefox Suggest is enabled, Firefox will download and store new search suggestions in the background, and show additional Search settings to control which suggestions appear in the awesomebar. When Firefox Suggest is disabled, Firefox will not download new suggestions, and hide the additional Search settings.\n"
glean:
description: A feature that provides server-side configurations for Glean metrics (aka Server Knobs).
hasExposure: true
@ -47,9 +55,6 @@ juno-onboarding:
cards:
type: json
description: Collection of user facing onboarding cards.
enabled:
type: boolean
description: "if true, juno onboarding is shown to the user."
messaging:
description: "The in-app messaging system.\n"
hasExposure: true
@ -199,6 +204,9 @@ shopping-experience:
enabled:
type: boolean
description: "if true, the shopping experience feature is shown to the user."
product-recommendations:
type: boolean
description: "if true, recommended products feature is enabled to be shown to the user based on their preference."
splash-screen:
description: "A feature that extends splash screen duration, allowing additional data fetching time for the app's initial run."
hasExposure: true

@ -1,3 +1,4 @@
import com.android.build.api.variant.FilterConfiguration
import org.apache.tools.ant.util.StringUtils
plugins {
@ -12,18 +13,16 @@ apply plugin: 'jacoco'
apply plugin: 'androidx.navigation.safeargs.kotlin'
apply plugin: 'com.google.android.gms.oss-licenses-plugin'
import com.android.build.OutputFile
import groovy.json.JsonOutput
import org.gradle.internal.logging.text.StyledTextOutput.Style
import org.gradle.internal.logging.text.StyledTextOutputFactory
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import static org.gradle.api.tasks.testing.TestResult.ResultType
apply from: 'benchmark.gradle'
android {
compileSdkVersion config.compileSdkVersion
project.maybeConfigForJetpackBenchmark(it)
if (project.hasProperty("testBuildType")) {
// Allowing to configure the test build type via command line flag (./gradlew -PtestBuildType=beta ..)
@ -34,6 +33,7 @@ android {
defaultConfig {
applicationId "io.github.forkmaintainers"
minSdkVersion config.minSdkVersion
compileSdk config.compileSdkVersion
targetSdkVersion config.targetSdkVersion
versionCode 1
versionName Config.generateDebugVersionName()
@ -218,9 +218,7 @@ android {
animationsDisabled = true
}
flavorDimensions "engine"
flavorDimensions "product"
flavorDimensions.add("product")
productFlavors {
fenix {
@ -286,7 +284,7 @@ android {
namespace 'org.mozilla.fenix'
}
android.applicationVariants.all { variant ->
android.applicationVariants.configureEach { variant ->
// -------------------------------------------------------------------------------------------------
// Generate version codes for builds
@ -312,7 +310,7 @@ android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def isMozillaOnline = project.hasProperty("mozillaOnline") || gradle.hasProperty("localProperties.mozillaOnline")
def abi = output.getFilter(OutputFile.ABI)
def abi = output.getFilter(FilterConfiguration.FilterType.ABI.name())
// If it is a Mozilla Online build, use a unified version code of armeabi-v7a
def arch = (isMozillaOnline) ? "armeabi-v7a" : abi
// We use the same version code generator, that we inherited from Fennec, across all channels - even on
@ -507,12 +505,8 @@ nimbus {
experimenterManifest = ".experimenter.yaml"
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
freeCompilerArgs += [
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
]
}
tasks.withType(KotlinCompile).configureEach {
kotlinOptions.freeCompilerArgs += "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
}
dependencies {
@ -559,6 +553,7 @@ dependencies {
implementation project(':feature-contextmenu')
implementation project(':feature-customtabs')
implementation project(':feature-downloads')
implementation project(':feature-fxsuggest')
implementation project(':feature-intent')
implementation project(':feature-media')
implementation project(':feature-prompts')
@ -635,7 +630,7 @@ dependencies {
implementation FenixDependencies.androidx_navigation_fragment
implementation FenixDependencies.androidx_navigation_ui
implementation ComponentsDependencies.androidx_recyclerview
implementation FenixDependencies.androidx_lifecycle_common
implementation ComponentsDependencies.androidx_lifecycle_common
implementation ComponentsDependencies.androidx_lifecycle_livedata
implementation ComponentsDependencies.androidx_lifecycle_process
implementation ComponentsDependencies.androidx_lifecycle_runtime
@ -737,13 +732,13 @@ if (project.hasProperty("coverage")) {
toolVersion = Versions.jacoco
}
android.applicationVariants.all { variant ->
android.applicationVariants.configureEach { variant ->
tasks.register("jacoco${variant.name.capitalize()}TestReport", JacocoReport) {
dependsOn "test${variant.name.capitalize()}UnitTest"
reports {
xml.enabled = true
html.enabled = true
xml.required = true
html.required = true
}
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*',
@ -782,7 +777,7 @@ tasks.register('printVariants') {
doLast {
def variants = android.applicationVariants.collect { variant -> [
apks: variant.outputs.collect { output -> [
abi: output.getFilter(com.android.build.VariantOutput.FilterType.ABI),
abi: output.getFilter(FilterConfiguration.FilterType.ABI.name()),
fileName: output.outputFile.name
]},
build_type: variant.buildType.name,
@ -801,22 +796,22 @@ tasks.register('printVariants') {
}
}
task buildTranslationArray {
tasks.register('buildTranslationArray') {
// This isn't running as a task, instead the array is build when the gradle file is parsed.
// https://github.com/mozilla-mobile/fenix/issues/14175
def foundLocales = new StringBuilder()
foundLocales.append("new String[]{")
fileTree("src/main/res").visit { FileVisitDetails details ->
if(details.file.path.endsWith("${File.separator}strings.xml")){
def languageCode = details.file.parent.tokenize(File.separator).last().replaceAll('values-','').replaceAll('-r','-')
if (details.file.path.endsWith("${File.separator}strings.xml")) {
def languageCode = details.file.parent.tokenize(File.separator).last().replaceAll('values-', '').replaceAll('-r', '-')
languageCode = (languageCode == "values") ? "en-US" : languageCode
foundLocales.append("\"").append(languageCode).append("\"").append(",")
}
}
foundLocales.append("}")
def foundLocalesString = foundLocales.toString().replaceAll(',}','}')
def foundLocalesString = foundLocales.toString().replaceAll(',}', '}')
android.defaultConfig.buildConfigField "String[]", "SUPPORTED_LOCALE_ARRAY", foundLocalesString
}
@ -878,7 +873,7 @@ if (gradle.hasProperty('localProperties.autoPublish.glean.dir')) {
apply from: "../${gleanSrcDir}/build-scripts/substitute-local-glean.gradle"
}
android.applicationVariants.all { variant ->
android.applicationVariants.configureEach { variant ->
tasks.register("apkSize${variant.name.capitalize()}", ApkSizeTask) {
variantName = variant.name
apks = variant.outputs.collect { output -> output.outputFile.name }

@ -2539,6 +2539,28 @@ metrics:
metadata:
tags:
- Experiments
device_total_ram:
type: quantity
lifetime: application
description: >
The total amount of memory this device in bytes, when available will be
MemoryInfo.advertisedMem otherwise it will be MemoryInfo.totalMem.
This doesn't represent memory available to the application however.
send_in_pings:
- metrics
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1853967
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/2620
data_sensitivity:
- technical
notification_emails:
- android-probes@mozilla.com
expires: never
unit: integer
metadata:
tags:
- Performance
search_page_load_time:
type: timing_distribution
time_unit: millisecond

@ -348,6 +348,10 @@ features:
description: if true, the shopping experience feature is shown to the user.
type: Boolean
default: false
product-recommendations:
description: if true, recommended products feature is enabled to be shown to the user based on their preference.
type: Boolean
default: false
defaults:
- channel: developer
value:
@ -384,6 +388,24 @@ features:
description: The channel Id param name with arg.
type: Map<String, String>
default: {}
fx-suggest:
description: A feature that provides Firefox Suggest search suggestions.
variables:
enabled:
description: >
Whether the feature is enabled. When Firefox Suggest is enabled,
Firefox will download and store new search suggestions in the
background, and show additional Search settings to control which
suggestions appear in the awesomebar. When Firefox Suggest is
disabled, Firefox will not download new suggestions, and hide the
additional Search settings.
type: Boolean
default: false
defaults:
- channel: developer
value:
enabled: true
types:
objects: {}

@ -5,10 +5,6 @@ features:
description: A feature that shows juno onboarding flow.
variables:
enabled:
description: if true, juno onboarding is shown to the user.
type: Boolean
default: false
cards:
description: Collection of user facing onboarding cards.
type: Map<String, OnboardingCardData>
@ -51,14 +47,6 @@ features:
primary-button-label: juno_onboarding_enable_notifications_positive_button
secondary-button-label: juno_onboarding_enable_notifications_negative_button
defaults:
- channel: developer
value:
enabled: false
- channel: nightly
value:
enabled: true
objects:
OnboardingCardData:

@ -13,7 +13,7 @@ features:
defaults:
- channel: developer
value:
felt-privacy-enabled: true
felt-privacy-enabled: false
- channel: nightly
value:
felt-privacy-enabled: false

@ -8,19 +8,22 @@
<p>Misc Link Types</p>
<section>
<a href="https://duckduckgo.com/">External link</a>
<a href="mailto://example@example.com">Email link</a>
</section>
<section>
<a href="mailto://example@example.com">Email link</a>
<a href="tel://1234567890">Telephone link</a>
</section>
<section>
<a href="tel://1234567890">Telephone link</a>
<a href="vnd.youtube://@Mozilla">Youtube schema link</a>
</section>
<section>
<a href="https://m.youtube.com/user/mozilla?cbrd=1">Youtube link</a>
<a href="https://m.youtube.com/user/mozilla?cbrd=1">Youtube full link</a>
</section>
<section>
<a href="http://play.google.com/store/apps/details?id=org.mozilla.firefox">Playstore link</a>
</section>
</html>

@ -7,6 +7,8 @@ name = "pypi"
pytest = "*"
pytest-html = "*"
pytest-metadata = "*"
pytest-variables = "*"
pyyaml = "*"
requests = "*"
[dev-packages]

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "917d5c85bd6545dedfbce6aedbd76bd1516993e65943ecfbf7affbece9a2a0ab"
"sha256": "53501c7e751ae79697bf8c7289b6095f49fed97242fe186fea42989e800c39d5"
},
"pipfile-spec": 6,
"requires": {
@ -16,141 +16,94 @@
]
},
"default": {
"black": {
"hashes": [
"sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5",
"sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915",
"sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326",
"sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940",
"sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b",
"sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30",
"sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c",
"sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c",
"sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab",
"sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27",
"sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2",
"sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961",
"sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9",
"sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb",
"sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70",
"sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331",
"sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2",
"sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266",
"sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d",
"sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6",
"sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b",
"sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925",
"sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8",
"sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4",
"sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"
],
"index": "pypi",
"version": "==23.3.0"
},
"certifi": {
"hashes": [
"sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7",
"sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"
"sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082",
"sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"
],
"markers": "python_version >= '3.6'",
"version": "==2023.5.7"
"version": "==2023.7.22"
},
"charset-normalizer": {
"hashes": [
"sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6",
"sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1",
"sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e",
"sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373",
"sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62",
"sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230",
"sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be",
"sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c",
"sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0",
"sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448",
"sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f",
"sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649",
"sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d",
"sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0",
"sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706",
"sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a",
"sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59",
"sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23",
"sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5",
"sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb",
"sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e",
"sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e",
"sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c",
"sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28",
"sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d",
"sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41",
"sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974",
"sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce",
"sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f",
"sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1",
"sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d",
"sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8",
"sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017",
"sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31",
"sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7",
"sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8",
"sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e",
"sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14",
"sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd",
"sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d",
"sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795",
"sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b",
"sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b",
"sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b",
"sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203",
"sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f",
"sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19",
"sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1",
"sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a",
"sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac",
"sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9",
"sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0",
"sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137",
"sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f",
"sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6",
"sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5",
"sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909",
"sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f",
"sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0",
"sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324",
"sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755",
"sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb",
"sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854",
"sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c",
"sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60",
"sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84",
"sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0",
"sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b",
"sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1",
"sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531",
"sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1",
"sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11",
"sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326",
"sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df",
"sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"
"sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96",
"sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c",
"sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710",
"sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706",
"sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020",
"sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252",
"sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad",
"sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329",
"sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a",
"sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f",
"sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6",
"sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4",
"sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a",
"sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46",
"sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2",
"sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23",
"sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace",
"sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd",
"sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982",
"sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10",
"sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2",
"sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea",
"sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09",
"sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5",
"sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149",
"sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489",
"sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9",
"sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80",
"sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592",
"sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3",
"sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6",
"sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed",
"sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c",
"sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200",
"sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a",
"sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e",
"sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d",
"sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6",
"sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623",
"sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669",
"sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3",
"sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa",
"sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9",
"sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2",
"sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f",
"sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1",
"sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4",
"sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a",
"sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8",
"sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3",
"sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029",
"sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f",
"sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959",
"sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22",
"sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7",
"sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952",
"sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346",
"sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e",
"sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d",
"sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299",
"sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd",
"sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a",
"sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3",
"sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037",
"sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94",
"sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c",
"sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858",
"sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a",
"sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449",
"sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c",
"sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918",
"sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1",
"sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c",
"sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac",
"sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"
],
"markers": "python_full_version >= '3.7.0'",
"version": "==3.1.0"
},
"click": {
"hashes": [
"sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
"sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
],
"markers": "python_version >= '3.7'",
"version": "==8.1.3"
},
"flake8": {
"hashes": [
"sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7",
"sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181"
],
"index": "pypi",
"version": "==6.0.0"
"version": "==3.2.0"
},
"idna": {
"hashes": [
@ -168,21 +121,69 @@
"markers": "python_version >= '3.7'",
"version": "==2.0.0"
},
"mccabe": {
"jinja2": {
"hashes": [
"sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325",
"sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"
"sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852",
"sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"
],
"markers": "python_version >= '3.6'",
"version": "==0.7.0"
"markers": "python_version >= '3.7'",
"version": "==3.1.2"
},
"mypy-extensions": {
"markupsafe": {
"hashes": [
"sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d",
"sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"
"sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e",
"sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e",
"sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431",
"sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686",
"sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559",
"sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc",
"sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c",
"sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0",
"sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4",
"sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9",
"sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575",
"sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba",
"sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d",
"sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3",
"sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00",
"sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155",
"sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac",
"sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52",
"sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f",
"sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8",
"sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b",
"sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24",
"sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea",
"sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198",
"sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0",
"sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee",
"sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be",
"sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2",
"sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707",
"sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6",
"sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58",
"sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779",
"sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636",
"sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c",
"sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad",
"sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee",
"sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc",
"sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2",
"sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48",
"sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7",
"sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e",
"sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b",
"sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa",
"sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5",
"sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e",
"sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb",
"sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9",
"sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57",
"sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc",
"sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"
],
"markers": "python_version >= '3.5'",
"version": "==1.0.0"
"markers": "python_version >= '3.7'",
"version": "==2.1.3"
},
"packaging": {
"hashes": [
@ -192,94 +193,219 @@
"markers": "python_version >= '3.7'",
"version": "==23.1"
},
"pathspec": {
"pluggy": {
"hashes": [
"sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687",
"sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"
"sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12",
"sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"
],
"markers": "python_version >= '3.7'",
"version": "==0.11.1"
"markers": "python_version >= '3.8'",
"version": "==1.3.0"
},
"platformdirs": {
"pytest": {
"hashes": [
"sha256:b0cabcb11063d21a0b261d557acb0a9d2126350e63b70cdf7db6347baea456dc",
"sha256:ca9ed98ce73076ba72e092b23d3c93ea6c4e186b3f1c3dad6edd98ff6ffcca2e"
"sha256:2f2301e797521b23e4d2585a0a3d7b5e50fdddaaf7e7d6773ea26ddb17c213ab",
"sha256:460c9a59b14e27c602eb5ece2e47bec99dc5fc5f6513cf924a7d03a578991b1f"
],
"markers": "python_version >= '3.7'",
"version": "==3.8.0"
"index": "pypi",
"version": "==7.4.1"
},
"pluggy": {
"pytest-html": {
"hashes": [
"sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849",
"sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"
"sha256:3b473cc278272f8b5a34cd3bf10f88ac5fcb17cb5af22f9323514af00c310e64",
"sha256:79c4677ed6196417bf290d8b81f706342ae49f726f623728efa3f7dfff09f8eb"
],
"markers": "python_version >= '3.7'",
"version": "==1.2.0"
"index": "pypi",
"version": "==4.0.0"
},
"py": {
"pytest-metadata": {
"hashes": [
"sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719",
"sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"
"sha256:769a9c65d2884bd583bc626b0ace77ad15dbe02dd91a9106d47fd46d9c2569ca",
"sha256:a17b1e40080401dc23177599208c52228df463db191c1a573ccdffacd885e190"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==1.11.0"
"index": "pypi",
"version": "==3.0.0"
},
"pycodestyle": {
"pytest-variables": {
"hashes": [
"sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053",
"sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"
"sha256:190d9d4da5a6013eb02df2049f6047d911cdbe44c5b1734a6acc1748433c93d0",
"sha256:ab84235417afac5a0a7dd4c3918287d9c7329d2e16d570d6e943f8d8e02533b9"
],
"markers": "python_version >= '3.6'",
"version": "==2.10.0"
"index": "pypi",
"version": "==3.0.0"
},
"pyflakes": {
"pyyaml": {
"hashes": [
"sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf",
"sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"
"sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5",
"sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc",
"sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df",
"sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741",
"sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206",
"sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27",
"sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595",
"sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62",
"sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98",
"sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696",
"sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290",
"sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9",
"sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d",
"sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6",
"sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867",
"sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47",
"sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486",
"sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6",
"sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3",
"sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007",
"sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938",
"sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0",
"sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c",
"sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735",
"sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d",
"sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28",
"sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4",
"sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba",
"sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8",
"sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5",
"sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd",
"sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3",
"sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0",
"sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515",
"sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c",
"sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c",
"sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924",
"sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34",
"sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43",
"sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859",
"sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673",
"sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54",
"sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a",
"sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b",
"sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab",
"sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa",
"sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c",
"sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585",
"sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d",
"sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"
],
"markers": "python_version >= '3.6'",
"version": "==3.0.1"
"index": "pypi",
"version": "==6.0.1"
},
"pytest": {
"requests": {
"hashes": [
"sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32",
"sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"
"sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f",
"sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"
],
"index": "pypi",
"version": "==7.4.0"
"version": "==2.31.0"
},
"pytest-html": {
"urllib3": {
"hashes": [
"sha256:868c08564a68d8b2c26866f1e33178419bb35b1e127c33784a28622eb827f3f3",
"sha256:c4e2f4bb0bffc437f51ad2174a8a3e71df81bbc2f6894604e604af18fbe687c3"
"sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11",
"sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"
],
"markers": "python_version >= '3.7'",
"version": "==2.0.4"
}
},
"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"
],
"index": "pypi",
"version": "==3.2.0"
"version": "==23.7.0"
},
"pytest-metadata": {
"click": {
"hashes": [
"sha256:769a9c65d2884bd583bc626b0ace77ad15dbe02dd91a9106d47fd46d9c2569ca",
"sha256:a17b1e40080401dc23177599208c52228df463db191c1a573ccdffacd885e190"
"sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
"sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"
],
"index": "pypi",
"version": "==3.0.0"
"markers": "python_version >= '3.7'",
"version": "==8.1.7"
},
"requests": {
"flake8": {
"hashes": [
"sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f",
"sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"
"sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23",
"sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"
],
"index": "pypi",
"version": "==2.31.0"
"version": "==6.1.0"
},
"urllib3": {
"mccabe": {
"hashes": [
"sha256:48e7fafa40319d358848e1bc6809b208340fafe2096f1725d05d67443d0483d1",
"sha256:bee28b5e56addb8226c96f7f13ac28cb4c301dd5ea8a6ca179c0b9835e032825"
"sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325",
"sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"
],
"markers": "python_version >= '3.6'",
"version": "==0.7.0"
},
"mypy-extensions": {
"hashes": [
"sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d",
"sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"
],
"markers": "python_version >= '3.5'",
"version": "==1.0.0"
},
"packaging": {
"hashes": [
"sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61",
"sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"
],
"markers": "python_version >= '3.7'",
"version": "==2.0.3"
"version": "==23.1"
},
"pathspec": {
"hashes": [
"sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20",
"sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"
],
"markers": "python_version >= '3.7'",
"version": "==0.11.2"
},
"platformdirs": {
"hashes": [
"sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d",
"sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"
],
"markers": "python_version >= '3.7'",
"version": "==3.10.0"
},
"pycodestyle": {
"hashes": [
"sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0",
"sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8"
],
"markers": "python_version >= '3.8'",
"version": "==2.11.0"
},
"pyflakes": {
"hashes": [
"sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774",
"sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"
],
"markers": "python_version >= '3.8'",
"version": "==3.1.0"
}
},
"develop": {}
}
}

@ -22,7 +22,11 @@ class SurveyExperimentIntegrationTest {
private val experimentName = "Viewpoint"
@get:Rule
val activityTestRule = HomeActivityTestRule()
val activityTestRule = HomeActivityTestRule(
isJumpBackInCFREnabled = false,
isPWAsPromptEnabled = false,
isTCPCFREnabled = false,
)
@Before
fun setUp() {
@ -38,7 +42,25 @@ class SurveyExperimentIntegrationTest {
fun checkSurveyNavigatesCorrectly() {
browserScreen {
verifySurveyButton()
}.clickSurveyButton {}
}.clickSurveyButton {
verifyUrl(surveyURL)
}
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openExperimentsMenu {
verifyExperimentExists(experimentName)
}
}
@Test
fun checkSurveyNoThanksNavigatesCorrectly() {
browserScreen {
verifySurveyNoThanksButton()
}.clickNoThanksSurveyButton {
verifyTabCounter("0")
}
homeScreen {
}.openThreeDotMenu {

@ -1,4 +1,5 @@
import json
import logging
import os
from pathlib import Path
import subprocess
@ -15,15 +16,32 @@ KLAATU_LOCAL_SERVER_URL = "http://localhost:1378"
here = Path()
def load_branches():
def pytest_addoption(parser):
parser.addoption(
"--experiment", action="store", help="The experiments experimenter URL"
)
parser.addoption(
"--stage", action="store_true", default=None, help="Use the stage server"
)
@pytest.fixture(name="load_branches")
def fixture_load_branches(experiment_url):
branches = []
data = requests.get(f"{KLAATU_SERVER_URL}/experiment").json()
for item in reversed(data):
if isinstance(item, dict):
if experiment_url:
data = experiment_url
else:
try:
data = requests.get(f"{KLAATU_SERVER_URL}/experiment").json()
except ConnectionRefusedError:
logging.warn("No URL or experiment slug provided, exiting.")
exit()
else:
data = item
break
for item in reversed(data):
data = item
break
experiment = requests.get(data).json()
for item in experiment["branches"]:
branches.append(item["slug"])
@ -45,7 +63,6 @@ def gradlewbuild(gradlewbuild_log):
@pytest.fixture(name="experiment_data")
def fixture_experiment_data(experiment_url):
data = requests.get(experiment_url).json()
del(data["branches"][0]["features"][0]["value"]["message-under-experiment"])
for item in data["branches"][0]["features"][0]["value"]["messages"].values():
for count, trigger in enumerate(item["trigger"]):
if "USER_EN_SPEAKER" not in trigger:
@ -54,17 +71,33 @@ def fixture_experiment_data(experiment_url):
@pytest.fixture(name="experiment_url", scope="module")
def fixture_experiment_url():
data = requests.get(f"{KLAATU_LOCAL_SERVER_URL}/experiment").json()
def fixture_experiment_url(request, variables):
url = None
for item in data:
if isinstance(item, dict):
continue
if slug := request.config.getoption("--experiment"):
# Build URL from slug
if request.config.getoption("--stage"):
url = f"{variables['urls']['stage_server']}/api/v6/experiments/{slug}"
else:
url = item
url = f"{variables['urls']['prod_server']}/api/v6/experiments/{slug}"
else:
try:
data = requests.get(f"{KLAATU_SERVER_URL}/experiment").json()
except requests.exceptions.ConnectionError:
logging.error("No URL or experiment slug provided, exiting.")
exit()
else:
for item in data:
if isinstance(item, dict):
continue
else:
url = item
yield url
return_data = {"url": url}
requests.put(f"{KLAATU_SERVER_URL}/experiment", json=return_data)
try:
requests.put(f"{KLAATU_SERVER_URL}/experiment", json=return_data)
except requests.exceptions.ConnectionError:
pass
@pytest.fixture(name="json_data")
@ -116,13 +149,17 @@ def fixture_send_test_results():
with open(f"{here.resolve()}/results/index.html", "rb") as f:
files = {"file": f}
requests.post(f"{KLAATU_SERVER_URL}/test_results", files=files)
try:
requests.post(f"{KLAATU_SERVER_URL}/test_results", files=files)
except requests.exceptions.ConnectionError:
pass
@pytest.fixture(name="setup_experiment", params=load_branches(), autouse=True)
def fixture_setup_experiment(experiment_slug, json_data, gradlewbuild_log, request):
def _():
command = f"nimbus-cli --app fenix --channel developer enroll {experiment_slug} --branch {request.param} --file {json_data} --reset-app"
@pytest.fixture(name="setup_experiment")
def fixture_setup_experiment(experiment_slug, json_data, gradlewbuild_log):
def _(branch):
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"
try:
out = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:

@ -1,4 +1,4 @@
[pytest]
addopts = --verbose --html=results/index.html --self-contained-html
addopts = --verbose --html=results/index.html --self-contained-html --variables=variables.yaml
log_cli = true
log_cli_level = info

@ -1,3 +1,12 @@
def test_survey_navigates_correctly(setup_experiment, gradlewbuild):
setup_experiment()
import pytest
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True)
def test_survey_navigates_correctly(setup_experiment, gradlewbuild, load_branches):
setup_experiment(load_branches)
gradlewbuild.test("SurveyExperimentIntegrationTest#checkSurveyNavigatesCorrectly")
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True)
def test_survey_no_thanks_navigates_correctly(setup_experiment, gradlewbuild, load_branches):
setup_experiment(load_branches)
gradlewbuild.test("SurveyExperimentIntegrationTest#checkSurveyNoThanksNavigatesCorrectly")

@ -0,0 +1,3 @@
urls:
stage_server: "https://stage.experimenter.nonprod.dataops.mozgcp.net"
prod_server: "https://experimenter.services.mozilla.com"

@ -82,6 +82,11 @@ interface FeatureSettingsHelper {
*/
var tabsTrayRewriteEnabled: Boolean
/**
* Enable or disable the Top Sites to Compose rewrite.
*/
var composeTopSitesEnabled: Boolean
fun applyFlagUpdates()
fun resetAllFeatureFlags()

@ -37,6 +37,7 @@ class FeatureSettingsHelperDelegate() : FeatureSettingsHelper {
isOpenInAppBannerEnabled = settings.shouldShowOpenInAppBanner,
etpPolicy = getETPPolicy(settings),
tabsTrayRewriteEnabled = settings.enableTabsTrayToCompose,
composeTopSitesEnabled = settings.enableComposeTopSites,
)
/**
@ -66,6 +67,7 @@ class FeatureSettingsHelperDelegate() : FeatureSettingsHelper {
override var isOpenInAppBannerEnabled: Boolean by updatedFeatureFlags::isOpenInAppBannerEnabled
override var etpPolicy: ETPPolicy by updatedFeatureFlags::etpPolicy
override var tabsTrayRewriteEnabled: Boolean by updatedFeatureFlags::tabsTrayRewriteEnabled
override var composeTopSitesEnabled: Boolean by updatedFeatureFlags::composeTopSitesEnabled
override fun applyFlagUpdates() {
applyFeatureFlags(updatedFeatureFlags)
@ -91,6 +93,7 @@ class FeatureSettingsHelperDelegate() : FeatureSettingsHelper {
settings.userOptOutOfReEngageCookieBannerDialog = !featureFlags.isCookieBannerReductionDialogEnabled
settings.shouldShowOpenInAppBanner = featureFlags.isOpenInAppBannerEnabled
settings.enableTabsTrayToCompose = featureFlags.tabsTrayRewriteEnabled
settings.enableComposeTopSites = featureFlags.composeTopSitesEnabled
setETPPolicy(featureFlags.etpPolicy)
}
}
@ -110,6 +113,7 @@ private data class FeatureFlags(
var isOpenInAppBannerEnabled: Boolean,
var etpPolicy: ETPPolicy,
var tabsTrayRewriteEnabled: Boolean,
var composeTopSitesEnabled: Boolean,
)
internal fun getETPPolicy(settings: Settings): ETPPolicy {

@ -56,6 +56,7 @@ class HomeActivityTestRule(
isOpenInAppBannerEnabled: Boolean = settings.shouldShowOpenInAppBanner,
etpPolicy: ETPPolicy = getETPPolicy(settings),
tabsTrayRewriteEnabled: Boolean = false,
composeTopSitesEnabled: Boolean = false,
) : this(initialTouchMode, launchActivity, skipOnboarding) {
this.isHomeOnboardingDialogEnabled = isHomeOnboardingDialogEnabled
this.isPocketEnabled = isPocketEnabled
@ -70,6 +71,7 @@ class HomeActivityTestRule(
this.isOpenInAppBannerEnabled = isOpenInAppBannerEnabled
this.etpPolicy = etpPolicy
this.tabsTrayRewriteEnabled = tabsTrayRewriteEnabled
this.composeTopSitesEnabled = composeTopSitesEnabled
}
/**
@ -114,6 +116,7 @@ class HomeActivityTestRule(
launchActivity: Boolean = true,
skipOnboarding: Boolean = false,
tabsTrayRewriteEnabled: Boolean = false,
composeTopSitesEnabled: Boolean = false,
) = HomeActivityTestRule(
initialTouchMode = initialTouchMode,
launchActivity = launchActivity,
@ -125,6 +128,7 @@ class HomeActivityTestRule(
isWallpaperOnboardingEnabled = false,
isCookieBannerReductionDialogEnabled = false,
isOpenInAppBannerEnabled = false,
composeTopSitesEnabled = composeTopSitesEnabled,
)
}
}
@ -164,6 +168,7 @@ class HomeActivityIntentTestRule internal constructor(
isOpenInAppBannerEnabled: Boolean = settings.shouldShowOpenInAppBanner,
etpPolicy: ETPPolicy = getETPPolicy(settings),
tabsTrayRewriteEnabled: Boolean = false,
composeTopSitesEnabled: Boolean = false,
) : this(initialTouchMode, launchActivity, skipOnboarding) {
this.isHomeOnboardingDialogEnabled = isHomeOnboardingDialogEnabled
this.isPocketEnabled = isPocketEnabled
@ -178,6 +183,7 @@ class HomeActivityIntentTestRule internal constructor(
this.isOpenInAppBannerEnabled = isOpenInAppBannerEnabled
this.etpPolicy = etpPolicy
this.tabsTrayRewriteEnabled = tabsTrayRewriteEnabled
this.composeTopSitesEnabled = composeTopSitesEnabled
}
private val longTapUserPreference = getLongPressTimeout()
@ -259,6 +265,7 @@ class HomeActivityIntentTestRule internal constructor(
launchActivity: Boolean = true,
skipOnboarding: Boolean = false,
tabsTrayRewriteEnabled: Boolean = false,
composeTopSitesEnabled: Boolean = false,
) = HomeActivityIntentTestRule(
initialTouchMode = initialTouchMode,
launchActivity = launchActivity,
@ -270,6 +277,7 @@ class HomeActivityIntentTestRule internal constructor(
isWallpaperOnboardingEnabled = false,
isCookieBannerReductionDialogEnabled = false,
isOpenInAppBannerEnabled = false,
composeTopSitesEnabled = composeTopSitesEnabled,
)
}
}

@ -56,7 +56,7 @@ object MockWebServerHelper {
* If the dispatcher is unable to read a requested asset, it will fail the test by throwing an
* Exception on the main thread.
*
* @sample [org.mozilla.fenix.ui.NavigationToolbarTest.visitURLTest]
* @sample [org.mozilla.fenix.ui.BookmarksTest.verifyBookmarkButtonTest]
*/
const val HTTP_OK = 200
const val HTTP_NOT_FOUND = 404

@ -187,9 +187,11 @@ object TestHelper {
val storageVolume: StorageVolume = storageVolumes[0]
val file = File(storageVolume.directory!!.path + "/Download/" + fileName)
try {
file.delete()
Log.d("TestLog", "File delete try 1")
assertFalse("The file was not deleted", file.exists())
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")

@ -37,7 +37,7 @@
"sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082",
"sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"
],
"index": "pypi",
"markers": "python_version >= '3.6'",
"version": "==2023.7.22"
},
"cffi": {
@ -192,32 +192,32 @@
},
"cryptography": {
"hashes": [
"sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711",
"sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7",
"sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd",
"sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e",
"sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58",
"sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0",
"sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d",
"sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83",
"sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831",
"sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766",
"sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b",
"sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c",
"sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182",
"sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f",
"sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa",
"sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4",
"sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a",
"sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2",
"sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76",
"sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5",
"sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee",
"sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f",
"sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14"
"sha256:0d09fb5356f975974dbcb595ad2d178305e5050656affb7890a1583f5e02a306",
"sha256:23c2d778cf829f7d0ae180600b17e9fceea3c2ef8b31a99e3c694cbbf3a24b84",
"sha256:3fb248989b6363906827284cd20cca63bb1a757e0a2864d4c1682a985e3dca47",
"sha256:41d7aa7cdfded09b3d73a47f429c298e80796c8e825ddfadc84c8a7f12df212d",
"sha256:42cb413e01a5d36da9929baa9d70ca90d90b969269e5a12d39c1e0d475010116",
"sha256:4c2f0d35703d61002a2bbdcf15548ebb701cfdd83cdc12471d2bae80878a4207",
"sha256:4fd871184321100fb400d759ad0cddddf284c4b696568204d281c902fc7b0d81",
"sha256:5259cb659aa43005eb55a0e4ff2c825ca111a0da1814202c64d28a985d33b087",
"sha256:57a51b89f954f216a81c9d057bf1a24e2f36e764a1ca9a501a6964eb4a6800dd",
"sha256:652627a055cb52a84f8c448185922241dd5217443ca194d5739b44612c5e6507",
"sha256:67e120e9a577c64fe1f611e53b30b3e69744e5910ff3b6e97e935aeb96005858",
"sha256:6af1c6387c531cd364b72c28daa29232162010d952ceb7e5ca8e2827526aceae",
"sha256:6d192741113ef5e30d89dcb5b956ef4e1578f304708701b8b73d38e3e1461f34",
"sha256:7efe8041897fe7a50863e51b77789b657a133c75c3b094e51b5e4b5cec7bf906",
"sha256:84537453d57f55a50a5b6835622ee405816999a7113267739a1b4581f83535bd",
"sha256:8f09daa483aedea50d249ef98ed500569841d6498aa9c9f4b0531b9964658922",
"sha256:95dd7f261bb76948b52a5330ba5202b91a26fbac13ad0e9fc8a3ac04752058c7",
"sha256:a74fbcdb2a0d46fe00504f571a2a540532f4c188e6ccf26f1f178480117b33c4",
"sha256:a983e441a00a9d57a4d7c91b3116a37ae602907a7618b882c8013b5762e80574",
"sha256:ab8de0d091acbf778f74286f4989cf3d1528336af1b59f3e5d2ebca8b5fe49e1",
"sha256:aeb57c421b34af8f9fe830e1955bf493a86a7996cc1338fe41b30047d16e962c",
"sha256:ce785cf81a7bdade534297ef9e490ddff800d956625020ab2ec2780a556c313e",
"sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de"
],
"markers": "python_version >= '3.7'",
"version": "==41.0.2"
"index": "pypi",
"version": "==41.0.3"
},
"distro": {
"hashes": [
@ -229,11 +229,11 @@
},
"exceptiongroup": {
"hashes": [
"sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5",
"sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"
"sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9",
"sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"
],
"markers": "python_version < '3.11'",
"version": "==1.1.2"
"version": "==1.1.3"
},
"fxapom": {
"hashes": [
@ -373,11 +373,11 @@
},
"pluggy": {
"hashes": [
"sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849",
"sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"
"sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12",
"sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"
],
"markers": "python_version >= '3.7'",
"version": "==1.2.0"
"markers": "python_version >= '3.8'",
"version": "==1.3.0"
},
"progressbar2": {
"hashes": [
@ -495,19 +495,19 @@
},
"selenium": {
"hashes": [
"sha256:40241b9d872f58959e9b34e258488bf11844cd86142fd68182bd41db9991fc5c",
"sha256:871bf800c4934f745b909c8dfc7d15c65cf45bd2e943abd54451c810ada395e3"
"sha256:95be6aa449a0ab4ac1198bb9de71bbe9170405e04b9752f4b450dc7292a21828",
"sha256:b2c48b1440db54a0653300d9955f5421390723d53b36ec835e18de8e13bbd401"
],
"markers": "python_version >= '3.7'",
"version": "==4.10.0"
"markers": "python_version >= '3.8'",
"version": "==4.12.0"
},
"setuptools": {
"hashes": [
"sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f",
"sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"
"sha256:00478ca80aeebeecb2f288d3206b0de568df5cd2b8fada1209843cc9a8d88a48",
"sha256:af3d5949030c3f493f550876b2fd1dd5ec66689c4ee5d5344f009746f71fd5a8"
],
"markers": "python_version >= '3.7'",
"version": "==68.0.0"
"markers": "python_version >= '3.8'",
"version": "==68.2.0"
},
"six": {
"hashes": [
@ -557,11 +557,11 @@
},
"trio-websocket": {
"hashes": [
"sha256:1a748604ad906a7dcab9a43c6eb5681e37de4793ba0847ef0bc9486933ed027b",
"sha256:a9937d48e8132ebf833019efde2a52ca82d223a30a7ea3e8d60a7d28f75a4e3a"
"sha256:c7a620c4013c34b7e4477d89fe76695da1e455e4510a8d7ae13f81c632bdce1d",
"sha256:e66b3db3e2453017431dfbd352081006654e1241c2a6800dc2f43d7df54d55c5"
],
"markers": "python_version >= '3.7'",
"version": "==0.10.3"
"version": "==0.10.4"
},
"typing-extensions": {
"hashes": [

@ -4,34 +4,28 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
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.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
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.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.searchScreen
class AddToHomeScreenTest {
private lateinit var mockWebServer: MockWebServer
private val downloadTestPage =
"https://storage.googleapis.com/mobile_test_assets/test_app/downloads.html"
private val pdfFileName = "washington.pdf"
private val pdfFileURL = "storage.googleapis.com/mobile_test_assets/public/washington.pdf"
private val pdfFileContent = "Washington Crossing the Delaware"
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
val composeTestRule =
AndroidComposeTestRule(HomeActivityTestRule.withDefaultSettingsOverrides()) { it.activity }
@Before
fun setUp() {
@ -76,17 +70,15 @@ class AddToHomeScreenTest {
}
}
@Ignore("Failure, more details at: https://bugzilla.mozilla.org/show_bug.cgi?id=1830005")
@SmokeTest
@Test
fun addPrivateBrowsingShortcutTest() {
homeScreen {
}.dismissOnboarding()
homeScreen {
}.triggerPrivateBrowsingShortcutPrompt {
verifyNoThanksPrivateBrowsingShortcutButton()
verifyAddPrivateBrowsingShortcutButton()
clickAddPrivateBrowsingShortcutButton()
verifyNoThanksPrivateBrowsingShortcutButton(composeTestRule)
verifyAddPrivateBrowsingShortcutButton(composeTestRule)
clickAddPrivateBrowsingShortcutButton(composeTestRule)
clickAddAutomaticallyButton()
}.openHomeScreenShortcut("Private ${TestHelper.appName}") {}
searchScreen {
@ -95,23 +87,4 @@ class AddToHomeScreenTest {
verifyCommonMythsLink()
}
}
@SmokeTest
@Test
fun addPDFToHomeScreenTest() {
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
clickPageObject(itemContainingText(pdfFileName))
verifyUrl(pdfFileURL)
verifyPageContent(pdfFileContent)
}.openThreeDotMenu {
expandMenu()
}.openAddToHomeScreen {
verifyShortcutTextFieldTitle(pdfFileName)
clickAddShortcutButton()
clickAddAutomaticallyButton()
}.openHomeScreenShortcut(pdfFileName) {
verifyUrl(pdfFileURL)
}
}
}

@ -41,6 +41,7 @@ class AddressAutofillTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836845
@SmokeTest
@Test
fun verifyAddressAutofillTest() {
@ -81,6 +82,7 @@ class AddressAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836856
@SmokeTest
@Test
fun deleteSavedAddressTest() {
@ -111,6 +113,7 @@ class AddressAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836840
@Test
fun verifyAddAddressViewTest() {
homeScreen {
@ -124,6 +127,7 @@ class AddressAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836841
@Test
fun verifyEditAddressViewTest() {
homeScreen {
@ -149,6 +153,7 @@ class AddressAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836839
@Test
fun verifyAddressAutofillToggleTest() {
val addressFormPage =
@ -196,6 +201,7 @@ class AddressAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836847
@Test
fun verifyManageAddressesPromptOptionTest() {
val addressFormPage =
@ -234,9 +240,10 @@ class AddressAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836849
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1814032")
@Test
fun verifyAddressAutofillSelectionTest() {
fun verifyMultipleAddressesSelectionTest() {
val addressFormPage =
TestAssetHelper.getAddressFormAsset(mockWebServer)
@ -301,6 +308,7 @@ class AddressAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836850
@Test
fun verifySavedAddressCanBeEditedTest() {
homeScreen {
@ -339,6 +347,7 @@ class AddressAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836848
@Test
fun verifyStateFieldUpdatesInAccordanceWithCountryFieldTest() {
homeScreen {
@ -355,6 +364,7 @@ class AddressAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836858
@Test
fun verifyFormFieldCanBeFilledManuallyTest() {
val addressFormPage =
@ -397,6 +407,7 @@ class AddressAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836838
@Test
fun verifyAutofillAddressSectionTest() {
homeScreen {

@ -27,7 +27,6 @@ import org.mozilla.fenix.helpers.MockBrowserDataHelper.createBookmarkItem
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
@ -81,6 +80,7 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/522919
@Test
fun verifyEmptyBookmarksMenuTest() {
homeScreen {
@ -93,18 +93,6 @@ class BookmarksTest {
verifyAddFolderButton()
verifyCloseButton()
verifyBookmarkTitle("Desktop Bookmarks")
}
}
}
@Test
fun defaultDesktopBookmarksFoldersTest() {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 1),
) {
selectFolder("Desktop Bookmarks")
verifyFolderTitle("Bookmarks Menu")
verifyFolderTitle("Bookmarks Toolbar")
@ -116,54 +104,31 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2301370
@Test
fun verifyBookmarkButtonTest() {
fun verifyAddBookmarkButtonTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
}.bookmarkPage {
verifySnackBarText("Bookmark saved!")
}.openThreeDotMenu {
verifyEditBookmarkButton()
}
}
@Test
fun addBookmarkTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {
verifyBookmarksMenuView()
verifyBookmarkTitle(defaultWebPage.title)
verifyBookmarkedURL(defaultWebPage.url.toString())
verifyBookmarkFavicon(defaultWebPage.url)
}
}
}
@Test
fun createBookmarkFolderTest() {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 1),
) {
clickAddFolderButton()
verifyKeyboardVisible()
addNewFolderName(bookmarksFolderName)
saveNewFolder()
verifyFolderTitle(bookmarksFolderName)
verifyKeyboardHidden()
}
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/522920
@Test
fun cancelCreateBookmarkFolderTest() {
homeScreen {
@ -177,9 +142,9 @@ class BookmarksTest {
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2299619
@Test
fun cancelEditBookmarkTest() {
fun cancelingChangesInEditModeAreNotSavedTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -202,9 +167,10 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325633
@SmokeTest
@Test
fun editBookmarkTest() {
fun editBookmarksNameAndUrlTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
@ -229,6 +195,7 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/341696
@Test
fun copyBookmarkURLTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -255,8 +222,9 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325634
@Test
fun threeDotMenuShareBookmarkTest() {
fun shareBookmarkTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
@ -275,6 +243,7 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325636
@Test
fun openBookmarkInNewTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -293,9 +262,10 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1919261
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1807268")
@Test
fun openAllInTabsTest() {
fun verifyOpenAllInNewTabsOptionTest() {
val webPages = listOf(
TestAssetHelper.getGenericAsset(mockWebServer, 1),
TestAssetHelper.getGenericAsset(mockWebServer, 2),
@ -336,9 +306,10 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1919262
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1807268")
@Test
fun openAllInPrivateTabsTest() {
fun verifyOpenAllInPrivateTabsTest() {
val webPages = listOf(
TestAssetHelper.getGenericAsset(mockWebServer, 1),
TestAssetHelper.getGenericAsset(mockWebServer, 2),
@ -372,6 +343,7 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325637
@Test
fun openBookmarkInPrivateTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -390,30 +362,11 @@ class BookmarksTest {
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325635
@Test
fun deleteBookmarkTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {}
}.openThreeDotMenu(defaultWebPage.title) {
}.clickDelete {
verifyDeleteSnackBarText()
verifyUndoDeleteSnackBarButton()
}
}
@SmokeTest
@Test
fun undoDeleteBookmarkTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
@ -431,10 +384,13 @@ class BookmarksTest {
) {
verifyBookmarkedURL(defaultWebPage.url.toString())
}
}.openThreeDotMenu(defaultWebPage.title) {
}.clickDelete {
verifyBookmarkIsDeleted(defaultWebPage.title)
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2300275
@Test
fun bookmarksMultiSelectionToolbarItemsTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -460,9 +416,10 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2300276
@SmokeTest
@Test
fun openSelectionInNewTabTest() {
fun openMultipleSelectedBookmarksInANewTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
@ -489,9 +446,9 @@ class BookmarksTest {
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2300277
@Test
fun openSelectionInPrivateTabTest() {
fun openMultipleSelectedBookmarksInPrivateTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
@ -513,9 +470,10 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325644
@SmokeTest
@Test
fun deleteMultipleSelectionTest() {
fun deleteMultipleSelectedBookmarksTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
@ -539,20 +497,9 @@ class BookmarksTest {
bookmarksMenu {
verifyDeleteMultipleBookmarksSnackBar()
}
}
@SmokeTest
@Test
fun undoDeleteMultipleSelectionTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
browserScreen {
createBookmark(firstWebPage.url)
createBookmark(secondWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
clickUndoDeleteButton()
verifyBookmarkedURL(firstWebPage.url.toString())
verifyBookmarkedURL(secondWebPage.url.toString())
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 3),
) {
@ -568,14 +515,12 @@ class BookmarksTest {
bookmarksMenu {
verifyDeleteMultipleBookmarksSnackBar()
clickUndoDeleteButton()
verifyBookmarkedURL(firstWebPage.url.toString())
verifyBookmarkedURL(secondWebPage.url.toString())
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2301355
@Test
fun multipleSelectionShareButtonTest() {
fun shareMultipleSelectedBookmarksTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
@ -598,43 +543,9 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325639
@Test
fun multipleBookmarkDeletionsTest() {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
createFolder("1")
getInstrumentation().waitForIdleSync()
createFolder("2")
getInstrumentation().waitForIdleSync()
createFolder("3")
getInstrumentation().waitForIdleSync()
}.openThreeDotMenu("1") {
}.clickDelete {
verifyDeleteFolderConfirmationMessage()
confirmDeletion()
verifyDeleteSnackBarText()
}.openThreeDotMenu("2") {
}.clickDelete {
verifyDeleteFolderConfirmationMessage()
confirmDeletion()
verifyDeleteSnackBarText()
verifyFolderTitle("3")
// On some devices we need to wait for the Snackbar to be gone before continuing
TestHelper.waitUntilSnackbarGone()
}.closeMenu {
}
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
verifyFolderTitle("3")
}
}
@SmokeTest
@Test
fun changeBookmarkParentFolderTest() {
fun createBookmarkFolderTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
@ -643,13 +554,13 @@ class BookmarksTest {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {
createFolder(bookmarksFolderName)
}
) {}
}.openThreeDotMenu(defaultWebPage.title) {
}.clickEdit {
clickParentFolderSelector()
selectFolder(bookmarksFolderName)
clickAddNewFolderButtonFromSelectFolderView()
addNewFolderName(bookmarksFolderName)
saveNewFolder()
navigateUp()
saveEditBookmark()
selectFolder(bookmarksFolderName)
@ -657,6 +568,7 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325645
@Test
fun navigateBookmarksFoldersTest() {
homeScreen {
@ -680,8 +592,9 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/374855
@Test
fun cantSelectDesktopFoldersTest() {
fun cantSelectDefaultFoldersTest() {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
@ -694,16 +607,7 @@ class BookmarksTest {
}
}
@Test
fun verifyCloseMenuTest() {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
}.closeMenu {
verifyHomeScreen()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2299703
@Test
fun deleteBookmarkInEditModeTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -726,31 +630,7 @@ class BookmarksTest {
}
}
@SmokeTest
@Test
fun undoDeleteBookmarkFolderTest() {
browserScreen {
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 1),
) {
createFolder("My Folder")
verifyFolderTitle("My Folder")
}
}.openThreeDotMenu("My Folder") {
}.clickDelete {
cancelFolderDeletion()
verifyFolderTitle("My Folder")
}.openThreeDotMenu("My Folder") {
}.clickDelete {
confirmDeletion()
verifyDeleteSnackBarText()
clickUndoDeleteButton()
verifyFolderTitle("My Folder")
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715710
@Test
fun verifySearchBookmarksViewTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -788,6 +668,7 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715712
@Test
fun verifySearchForBookmarkedItemsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -803,13 +684,13 @@ class BookmarksTest {
// Search for a valid term
typeSearch(firstWebPage.title)
verifySearchEngineSuggestionResults(activityTestRule, firstWebPage.url.toString(), searchTerm = firstWebPage.title)
verifyNoSuggestionsAreDisplayed(activityTestRule, secondWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, secondWebPage.url.toString())
}.dismissSearchBar {}
bookmarksMenu {
}.clickSearchButton {
// Search for invalid term
typeSearch("Android")
verifyNoSuggestionsAreDisplayed(
verifySuggestionsAreNotDisplayed(
activityTestRule,
firstWebPage.url.toString(),
secondWebPage.url.toString(),
@ -817,6 +698,7 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715711
@Test
fun verifyVoiceSearchInBookmarksTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -832,8 +714,9 @@ class BookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715714
@Test
fun verifyDeletedBookmarksCanNotBeSearchedTest() {
fun verifyDeletedBookmarksAreNotDisplayedAsSearchResultsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
val thirdWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 3)
@ -853,8 +736,8 @@ class BookmarksTest {
}.clickSearchButton {
// Search for a valid term
typeSearch("generic")
verifyNoSuggestionsAreDisplayed(activityTestRule, firstWebPage.url.toString())
verifyNoSuggestionsAreDisplayed(activityTestRule, secondWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, firstWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, secondWebPage.url.toString())
verifySearchEngineSuggestionResults(activityTestRule, thirdWebPage.url.toString(), searchTerm = "generic")
pressBack()
}
@ -865,7 +748,54 @@ class BookmarksTest {
}.clickSearchButton {
// Search for a valid term
typeSearch("generic")
verifyNoSuggestionsAreDisplayed(activityTestRule, thirdWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, thirdWebPage.url.toString())
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/325642
@SmokeTest
@Test
fun deleteBookmarkFoldersTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
createBookmark(website.url)
}.openThreeDotMenu {
}.openBookmarks {
verifyBookmarkTitle("Test_Page_1")
createFolder("My Folder")
verifyFolderTitle("My Folder")
}.openThreeDotMenu("Test_Page_1") {
}.clickEdit {
clickParentFolderSelector()
selectFolder("My Folder")
navigateUp()
saveEditBookmark()
createFolder("My Folder 2")
verifyFolderTitle("My Folder 2")
}.openThreeDotMenu("My Folder 2") {
}.clickEdit {
clickParentFolderSelector()
selectFolder("My Folder")
navigateUp()
saveEditBookmark()
}.openThreeDotMenu("My Folder") {
}.clickDelete {
cancelFolderDeletion()
verifyFolderTitle("My Folder")
}.openThreeDotMenu("My Folder") {
}.clickDelete {
confirmDeletion()
verifyDeleteSnackBarText()
clickUndoDeleteButton()
verifyFolderTitle("My Folder")
}.openThreeDotMenu("My Folder") {
}.clickDelete {
confirmDeletion()
verifyDeleteSnackBarText()
verifyBookmarkIsDeleted("My Folder")
verifyBookmarkIsDeleted("My Folder 2")
verifyBookmarkIsDeleted("Test_Page_1")
}
}
}

@ -15,6 +15,7 @@ import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.ui.robots.browserScreen
@ -94,6 +95,19 @@ class CollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2283299
@Test
fun createFirstCollectionFromMainMenuTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
}.openSaveToCollection {
verifyCollectionNameTextField()
}
}
@SmokeTest
@Test
fun verifyExpandedCollectionItemsTest() {

@ -24,7 +24,6 @@ import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
@ -91,18 +90,6 @@ class ComposeBookmarksTest {
verifyAddFolderButton()
verifyCloseButton()
verifyBookmarkTitle("Desktop Bookmarks")
}
}
}
@Test
fun defaultDesktopBookmarksFoldersTest() {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 1),
) {
selectFolder("Desktop Bookmarks")
verifyFolderTitle("Bookmarks Menu")
verifyFolderTitle("Bookmarks Toolbar")
@ -114,54 +101,6 @@ class ComposeBookmarksTest {
}
}
@Test
fun verifyBookmarkButtonTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
}.bookmarkPage {
}.openThreeDotMenu {
verifyEditBookmarkButton()
}
}
@Test
fun addBookmarkTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {
verifyBookmarkedURL(defaultWebPage.url.toString())
verifyBookmarkFavicon(defaultWebPage.url)
}
}
}
@Test
fun createBookmarkFolderTest() {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 1),
) {
clickAddFolderButton()
verifyKeyboardVisible()
addNewFolderName(bookmarksFolderName)
saveNewFolder()
verifyFolderTitle(bookmarksFolderName)
verifyKeyboardHidden()
}
}
}
@Test
fun cancelCreateBookmarkFolderTest() {
homeScreen {
@ -175,9 +114,8 @@ class ComposeBookmarksTest {
}
}
@SmokeTest
@Test
fun cancelEditBookmarkTest() {
fun cancelingChangesInEditModeAreNotSavedTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -202,7 +140,7 @@ class ComposeBookmarksTest {
@SmokeTest
@Test
fun editBookmarkTest() {
fun editBookmarksNameAndUrlTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
@ -292,7 +230,7 @@ class ComposeBookmarksTest {
}
@Test
fun openAllInTabsTest() {
fun verifyOpenAllInNewTabsOptionTest() {
val webPages = listOf(
TestAssetHelper.getGenericAsset(mockWebServer, 1),
TestAssetHelper.getGenericAsset(mockWebServer, 2),
@ -334,7 +272,7 @@ class ComposeBookmarksTest {
}
@Test
fun openAllInPrivateTabsTest() {
fun verifyOpenAllInPrivateTabsTest() {
val webPages = listOf(
TestAssetHelper.getGenericAsset(mockWebServer, 1),
TestAssetHelper.getGenericAsset(mockWebServer, 2),
@ -386,30 +324,10 @@ class ComposeBookmarksTest {
}
}
@SmokeTest
@Test
fun deleteBookmarkTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {}
}.openThreeDotMenu(defaultWebPage.title) {
}.clickDelete {
verifyDeleteSnackBarText()
verifyUndoDeleteSnackBarButton()
}
}
@SmokeTest
@Test
fun undoDeleteBookmarkTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
@ -427,10 +345,12 @@ class ComposeBookmarksTest {
) {
verifyBookmarkedURL(defaultWebPage.url.toString())
}
}.openThreeDotMenu(defaultWebPage.title) {
}.clickDelete {
verifyBookmarkIsDeleted(defaultWebPage.title)
}
}
@SmokeTest
@Test
fun bookmarksMultiSelectionToolbarItemsTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -458,7 +378,7 @@ class ComposeBookmarksTest {
@SmokeTest
@Test
fun openSelectionInNewTabTest() {
fun openMultipleSelectedBookmarksInANewTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
@ -486,9 +406,8 @@ class ComposeBookmarksTest {
}
}
@SmokeTest
@Test
fun openSelectionInPrivateTabTest() {
fun openMultipleSelectedBookmarksInPrivateTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
@ -512,7 +431,7 @@ class ComposeBookmarksTest {
@SmokeTest
@Test
fun deleteMultipleSelectionTest() {
fun deleteMultipleSelectedBookmarksTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
@ -536,20 +455,9 @@ class ComposeBookmarksTest {
bookmarksMenu {
verifyDeleteMultipleBookmarksSnackBar()
}
}
@SmokeTest
@Test
fun undoDeleteMultipleSelectionTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
browserScreen {
createBookmark(firstWebPage.url)
createBookmark(secondWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
clickUndoDeleteButton()
verifyBookmarkedURL(firstWebPage.url.toString())
verifyBookmarkedURL(secondWebPage.url.toString())
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 3),
) {
@ -565,9 +473,6 @@ class ComposeBookmarksTest {
bookmarksMenu {
verifyDeleteMultipleBookmarksSnackBar()
clickUndoDeleteButton()
verifyBookmarkedURL(firstWebPage.url.toString())
verifyBookmarkedURL(secondWebPage.url.toString())
}
}
@ -596,42 +501,7 @@ class ComposeBookmarksTest {
}
@Test
fun multipleBookmarkDeletionsTest() {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
createFolder("1")
getInstrumentation().waitForIdleSync()
createFolder("2")
getInstrumentation().waitForIdleSync()
createFolder("3")
getInstrumentation().waitForIdleSync()
}.openThreeDotMenu("1") {
}.clickDelete {
verifyDeleteFolderConfirmationMessage()
confirmDeletion()
verifyDeleteSnackBarText()
}.openThreeDotMenu("2") {
}.clickDelete {
verifyDeleteFolderConfirmationMessage()
confirmDeletion()
verifyDeleteSnackBarText()
verifyFolderTitle("3")
// On some devices we need to wait for the Snackbar to be gone before continuing
TestHelper.waitUntilSnackbarGone()
}.closeMenu {
}
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
verifyFolderTitle("3")
}
}
@SmokeTest
@Test
fun changeBookmarkParentFolderTest() {
fun createBookmarkFolderTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
@ -640,13 +510,13 @@ class ComposeBookmarksTest {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {
createFolder(bookmarksFolderName)
}
) {}
}.openThreeDotMenu(defaultWebPage.title) {
}.clickEdit {
clickParentFolderSelector()
selectFolder(bookmarksFolderName)
clickAddNewFolderButtonFromSelectFolderView()
addNewFolderName(bookmarksFolderName)
saveNewFolder()
navigateUp()
saveEditBookmark()
selectFolder(bookmarksFolderName)
@ -691,16 +561,6 @@ class ComposeBookmarksTest {
}
}
@Test
fun verifyCloseMenuTest() {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
}.closeMenu {
verifyHomeScreen()
}
}
@Test
fun deleteBookmarkInEditModeTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -723,31 +583,6 @@ class ComposeBookmarksTest {
}
}
@SmokeTest
@Test
fun undoDeleteBookmarkFolderTest() {
browserScreen {
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 1),
) {
createFolder("My Folder")
verifyFolderTitle("My Folder")
}
}.openThreeDotMenu("My Folder") {
}.clickDelete {
cancelFolderDeletion()
verifyFolderTitle("My Folder")
}.openThreeDotMenu("My Folder") {
}.clickDelete {
confirmDeletion()
verifyDeleteSnackBarText()
clickUndoDeleteButton()
verifyFolderTitle("My Folder")
}
}
@Test
fun verifySearchBookmarksViewTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -788,6 +623,7 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715712
@Test
fun verifySearchForBookmarkedItemsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -810,11 +646,11 @@ class ComposeBookmarksTest {
// Search for a valid term
typeSearch(firstWebPage.title)
verifySearchEngineSuggestionResults(activityTestRule, firstWebPage.url.toString(), searchTerm = firstWebPage.title)
verifyNoSuggestionsAreDisplayed(activityTestRule, secondWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, secondWebPage.url.toString())
// Search for invalid term
typeSearch("Android")
verifyNoSuggestionsAreDisplayed(activityTestRule, firstWebPage.url.toString())
verifyNoSuggestionsAreDisplayed(activityTestRule, secondWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, firstWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, secondWebPage.url.toString())
}
}
@ -833,8 +669,9 @@ class ComposeBookmarksTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715714
@Test
fun verifyDeletedBookmarksCanNotBeSearchedTest() {
fun verifyDeletedBookmarksAreNotDisplayedAsSearchResultsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
val thirdWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 3)
@ -854,8 +691,8 @@ class ComposeBookmarksTest {
}.clickSearchButton {
// Search for a valid term
typeSearch("generic")
verifyNoSuggestionsAreDisplayed(activityTestRule, firstWebPage.url.toString())
verifyNoSuggestionsAreDisplayed(activityTestRule, secondWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, firstWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, secondWebPage.url.toString())
verifySearchEngineSuggestionResults(activityTestRule, thirdWebPage.url.toString(), searchTerm = "generic")
pressBack()
}
@ -866,7 +703,55 @@ class ComposeBookmarksTest {
}.clickSearchButton {
// Search for a valid term
typeSearch("generic")
verifyNoSuggestionsAreDisplayed(activityTestRule, thirdWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, thirdWebPage.url.toString())
}
}
// Verifies that deleting a Bookmarks folder also removes the item from inside it.
@SmokeTest
@Test
fun deleteBookmarkFoldersTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
createBookmark(website.url)
}.openThreeDotMenu {
}.openBookmarks {
verifyBookmarkTitle("Test_Page_1")
createFolder("My Folder")
verifyFolderTitle("My Folder")
}.openThreeDotMenu("Test_Page_1") {
}.clickEdit {
clickParentFolderSelector()
selectFolder("My Folder")
navigateUp()
saveEditBookmark()
createFolder("My Folder 2")
verifyFolderTitle("My Folder 2")
}.openThreeDotMenu("My Folder 2") {
}.clickEdit {
clickParentFolderSelector()
selectFolder("My Folder")
navigateUp()
saveEditBookmark()
}.openThreeDotMenu("My Folder") {
}.clickDelete {
cancelFolderDeletion()
verifyFolderTitle("My Folder")
}.openThreeDotMenu("My Folder") {
}.clickDelete {
confirmDeletion()
verifyDeleteSnackBarText()
clickUndoDeleteButton()
verifyFolderTitle("My Folder")
}.openThreeDotMenu("My Folder") {
}.clickDelete {
confirmDeletion()
verifyDeleteSnackBarText()
verifyBookmarkIsDeleted("My Folder")
verifyBookmarkIsDeleted("My Folder 2")
verifyBookmarkIsDeleted("Test_Page_1")
navigateUp()
}
}
}

@ -15,12 +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.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.assertYoutubeAppOpens
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
@ -235,7 +236,7 @@ class ComposeContextMenusTest {
}
downloadRobot {
verifyDownloadNotificationPopup()
verifyDownloadCompleteNotificationPopup()
}.clickOpen("image/jpeg") {} // verify open intent is matched with associated data type
downloadRobot {
verifyPhotosAppOpens()
@ -291,9 +292,10 @@ class ComposeContextMenusTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
longClickPageObject(itemContainingText("Youtube link"))
longClickPageObject(itemContainingText("Youtube full link"))
verifyContextMenuForLinksToOtherApps("youtube.com")
clickContextMenuItem("Open link in external app")
assertYoutubeAppOpens()
assertExternalAppOpens(Constants.PackageName.YOUTUBE_APP)
}
}
}

@ -75,7 +75,7 @@ class ComposeHistoryTest {
}
@Test
fun noHistoryItemsInCacheTest() {
fun verifyEmptyHistoryMenuTest() {
homeScreen {
}.openThreeDotMenu {
verifyHistoryButton()
@ -87,8 +87,9 @@ class ComposeHistoryTest {
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@SmokeTest
@Test
fun visitedUrlHistoryTest() {
fun verifyHistoryMenuWithHistoryItemsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -104,6 +105,7 @@ class ComposeHistoryTest {
verifyVisitedTimeTitle()
verifyFirstTestPageTitle("Test_Page_1")
verifyTestPageUrl(firstWebPage.url)
verifyDeleteHistoryItemButton("Test_Page_1")
}
}
}
@ -128,50 +130,6 @@ class ComposeHistoryTest {
}
}
@Test
fun undoDeleteHistoryItemTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1),
) {
clickDeleteHistoryButton(firstWebPage.url.toString())
}
verifyUndoDeleteSnackBarButton()
clickUndoDeleteButton()
verifyHistoryItemExists(true, firstWebPage.url.toString())
}
}
@SmokeTest
@Test
fun cancelDeleteAllHistoryTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1),
) {
clickDeleteAllHistoryButton()
}
verifyDeleteConfirmationMessage()
selectEverythingOption()
cancelDeleteHistory()
verifyHistoryItemExists(true, firstWebPage.url.toString())
}
}
@SmokeTest
@Test
fun deleteAllHistoryTest() {
@ -226,7 +184,7 @@ class ComposeHistoryTest {
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1807268")
@Test
fun openHistoryInNewTabTest() {
fun openMultipleSelectedHistoryItemsInANewTabTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -255,7 +213,7 @@ class ComposeHistoryTest {
}
@Test
fun openHistoryInPrivateTabTest() {
fun openMultipleSelectedHistoryItemsInPrivateTabTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -280,7 +238,7 @@ class ComposeHistoryTest {
}
@Test
fun deleteMultipleSelectionTest() {
fun deleteMultipleSelectedHistoryItemsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
@ -314,7 +272,7 @@ class ComposeHistoryTest {
}
@Test
fun shareButtonTest() {
fun shareMultipleSelectedHistoryItemsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -409,12 +367,12 @@ class ComposeHistoryTest {
// Search for a valid term
typeSearch(firstWebPage.title)
verifySearchEngineSuggestionResults(activityTestRule, firstWebPage.url.toString(), searchTerm = firstWebPage.title)
verifyNoSuggestionsAreDisplayed(activityTestRule, secondWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, secondWebPage.url.toString())
clickClearButton()
// Search for invalid term
typeSearch("Android")
verifyNoSuggestionsAreDisplayed(activityTestRule, firstWebPage.url.toString())
verifyNoSuggestionsAreDisplayed(activityTestRule, secondWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, firstWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, secondWebPage.url.toString())
}
}
@ -445,8 +403,8 @@ class ComposeHistoryTest {
}.clickSearchButton {
// Search for a valid term
typeSearch("generic")
verifyNoSuggestionsAreDisplayed(activityTestRule, firstWebPage.url.toString())
verifyNoSuggestionsAreDisplayed(activityTestRule, secondWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, firstWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, secondWebPage.url.toString())
verifySearchEngineSuggestionResults(activityTestRule, thirdWebPage.url.toString(), searchTerm = "generic")
pressBack()
}
@ -456,7 +414,7 @@ class ComposeHistoryTest {
}.clickSearchButton {
// Search for a valid term
typeSearch("generic")
verifyNoSuggestionsAreDisplayed(activityTestRule, thirdWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, thirdWebPage.url.toString())
}
}
}

@ -63,7 +63,6 @@ class ComposeHomeScreenTest {
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1844580")
@Test
fun homeScreenItemsTest() {
homeScreen {}.dismissOnboarding()
homeScreen {
verifyHomeWordmark()
verifyHomePrivateBrowsingButton()
@ -86,7 +85,6 @@ class ComposeHomeScreenTest {
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/244199
@Test
fun privateBrowsingHomeScreenItemsTest() {
homeScreen { }.dismissOnboarding()
homeScreen { }.togglePrivateBrowsingMode()
homeScreen {

@ -5,7 +5,6 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.core.net.toUri
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
@ -16,11 +15,8 @@ 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.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import java.util.Locale
@ -60,51 +56,6 @@ class ComposeNavigationToolbarTest {
mockWebServer.shutdown()
}
@Test
fun goBackTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val nextWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(nextWebPage.url) {
verifyUrl(nextWebPage.url.toString())
}.openThreeDotMenu {
}.goToPreviousPage {
mDevice.waitForIdle()
verifyUrl(defaultWebPage.url.toString())
}
}
@Test
fun goForwardTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val nextWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(nextWebPage.url) {
mDevice.waitForIdle()
verifyUrl(nextWebPage.url.toString())
}.openThreeDotMenu {
}.goToPreviousPage {
mDevice.waitForIdle()
verifyUrl(defaultWebPage.url.toString())
}
// Re-open the three-dot menu for verification
navigationToolbar {
}.openThreeDotMenu {
verifyThreeDotMenuExists()
}.goForward {
verifyUrl(nextWebPage.url.toString())
}
}
// Swipes the nav bar left/right to switch between tabs
@SmokeTest
@Test
@ -144,126 +95,4 @@ class ComposeNavigationToolbarTest {
}
}
}
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@Test
fun visitURLTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
verifyUrl(defaultWebPage.url.toString())
}
}
@Test
fun findInPageTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 3)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
verifyThreeDotMenuExists()
verifyFindInPageButton()
}.openFindInPage {
verifyFindInPageNextButton()
verifyFindInPagePrevButton()
verifyFindInPageCloseButton()
enterFindInPageQuery("a")
verifyFindNextInPageResult("1/3")
clickFindInPageNextButton()
verifyFindNextInPageResult("2/3")
clickFindInPageNextButton()
verifyFindNextInPageResult("3/3")
clickFindInPagePrevButton()
verifyFindPrevInPageResult("2/3")
clickFindInPagePrevButton()
verifyFindPrevInPageResult("1/3")
}.closeFindInPageWithCloseButton {
verifyFindInPageBar(false)
}.openThreeDotMenu {
}.openFindInPage {
enterFindInPageQuery("3")
verifyFindNextInPageResult("1/1")
}.closeFindInPageWithBackButton {
verifyFindInPageBar(false)
}
}
@Test
fun pdfFindInPageTest() {
val genericURL =
TestAssetHelper.getGenericAsset(mockWebServer, 3)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
clickPageObject(itemWithText("PDF form file"))
}.openThreeDotMenu {
verifyThreeDotMenuExists()
verifyFindInPageButton()
}.openFindInPage {
verifyFindInPageNextButton()
verifyFindInPagePrevButton()
verifyFindInPageCloseButton()
enterFindInPageQuery("l")
verifyFindNextInPageResult("1/2")
clickFindInPageNextButton()
verifyFindNextInPageResult("2/2")
clickFindInPagePrevButton()
verifyFindPrevInPageResult("1/2")
}.closeFindInPageWithCloseButton {
verifyFindInPageBar(false)
}.openThreeDotMenu {
}.openFindInPage {
enterFindInPageQuery("p")
verifyFindNextInPageResult("1/1")
}.closeFindInPageWithBackButton {
verifyFindInPageBar(false)
}
}
@SmokeTest
@Test
fun verifySecurePageSecuritySubMenuTest() {
val defaultWebPage = "https://mozilla-mobile.github.io/testapp/loginForm"
val defaultWebPageTitle = "Login_form"
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.toUri()) {
}.openSiteSecuritySheet {
verifyQuickActionSheet(defaultWebPage, true)
openSecureConnectionSubMenu(true)
verifySecureConnectionSubMenu(defaultWebPageTitle, defaultWebPage, true)
}
}
@SmokeTest
@Test
fun verifyInsecurePageSecuritySubMenuTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
waitForPageToLoad()
}.openSiteSecuritySheet {
verifyQuickActionSheet(defaultWebPage.url.toString(), false)
openSecureConnectionSubMenu(false)
verifySecureConnectionSubMenu(defaultWebPage.title, defaultWebPage.url.toString(), false)
}
}
@Test
fun verifyClearCookiesFromQuickSettingsTest() {
val helpPageUrl = "mozilla.org"
homeScreen {
}.openThreeDotMenu {
}.openHelp {
}.openSiteSecuritySheet {
clickQuickActionSheetClearSiteData()
verifyClearSiteDataPrompt(helpPageUrl)
}
}
}

@ -666,7 +666,7 @@ class ComposeSearchTest {
clickSearchSelectorButton()
selectTemporarySearchMethod(searchEngineName = "Tabs")
typeSearch(searchTerm = "Mozilla")
verifyNoSuggestionsAreDisplayed(rule = activityTestRule, "Mozilla")
verifySuggestionsAreNotDisplayed(rule = activityTestRule, "Mozilla")
clickClearButton()
verifySearchBarPlaceholder("Search tabs")
}
@ -686,7 +686,7 @@ class ComposeSearchTest {
clickSearchSelectorButton()
selectTemporarySearchMethod(searchEngineName = "Tabs")
typeSearch(searchTerm = "Mozilla")
verifyNoSuggestionsAreDisplayed(rule = activityTestRule, "Mozilla")
verifySuggestionsAreNotDisplayed(rule = activityTestRule, "Mozilla")
clickClearButton()
typeSearch(searchTerm = "generic")
verifyTypedToolbarText("generic")
@ -725,7 +725,7 @@ class ComposeSearchTest {
}.clickSearchSelectorButton {
selectTemporarySearchMethod("Bookmarks")
typeSearch("test")
verifyNoSuggestionsAreDisplayed(activityTestRule, "test")
verifySuggestionsAreNotDisplayed(activityTestRule, "test")
}
}
@ -752,7 +752,7 @@ class ComposeSearchTest {
}.dismissSearchBar {
}.openSearch {
typeSearch("mozilla ")
verifyNoSuggestionsAreDisplayed(activityTestRule, "Test1", "Test2")
verifySuggestionsAreNotDisplayed(activityTestRule, "Test1", "Test2")
}
}
@ -776,7 +776,7 @@ class ComposeSearchTest {
clickSearchSelectorButton()
selectTemporarySearchMethod(searchEngineName = "History")
typeSearch(searchTerm = "Mozilla")
verifyNoSuggestionsAreDisplayed(rule = activityTestRule, "Mozilla")
verifySuggestionsAreNotDisplayed(rule = activityTestRule, "Mozilla")
clickClearButton()
verifySearchBarPlaceholder("Search history")
}

@ -68,7 +68,7 @@ class ComposeSettingsDeleteBrowsingDataOnQuitTest {
}
@Test
fun deleteBrowsingDataOnQuitSettingsItemsTest() {
fun deleteBrowsingDataOnQuitSettingTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -120,7 +120,7 @@ class ComposeSettingsDeleteBrowsingDataOnQuitTest {
}
@Test
fun deleteHistoryOnQuitTest() {
fun deleteBrowsingHistoryOnQuitTest() {
val genericPage =
getStorageTestAsset(mockWebServer, "generic1.html")
@ -147,6 +147,7 @@ class ComposeSettingsDeleteBrowsingDataOnQuitTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416051
@Test
fun deleteCookiesAndSiteDataOnQuitTest() {
val storageWritePage =
@ -198,7 +199,7 @@ class ComposeSettingsDeleteBrowsingDataOnQuitTest {
}.clickDownloadLink("smallZip.zip") {
verifyDownloadPrompt("smallZip.zip")
}.clickDownload {
verifyDownloadNotificationPopup()
verifyDownloadCompleteNotificationPopup()
}.closeCompletedDownloadPrompt {
}.goToHomescreen {
}.openThreeDotMenu {

@ -117,7 +117,7 @@ class ComposeSettingsDeleteBrowsingDataTest {
}
@Test
fun deleteTabsDataWithNoOpenTabsTest() {
fun deleteOpenTabsBrowsingDataWithNoOpenTabsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -135,7 +135,7 @@ class ComposeSettingsDeleteBrowsingDataTest {
@SmokeTest
@Test
fun deleteTabsDataTest() {
fun deleteOpenTabsBrowsingDataTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {

@ -1,384 +1,238 @@
/* 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.ui
import android.view.View
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.core.net.toUri
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.uiautomator.UiDevice
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.mediasession.MediaSession
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.IntentReceiverActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
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.assertYoutubeAppOpens
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.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
/**
* Test Suite that contains a part of the Smoke and Sanity tests defined in TestRail:
* https://testrail.stage.mozaws.net/index.php?/suites/view/3192
* Other smoke tests have been marked with the @SmokeTest annotation throughout the ui package in order to limit this class expansion.
* These tests will verify different functionalities of the app as a way to quickly detect regressions in main areas
*/
@Suppress("ForbiddenComment")
@SmokeTest
class ComposeSmokeTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
private val customMenuItem = "TestMenuItem"
private lateinit var browserStore: BrowserStore
@get:Rule(order = 0)
val activityTestRule = AndroidComposeTestRule(
HomeActivityIntentTestRule.withDefaultSettingsOverrides(
tabsTrayRewriteEnabled = true,
),
) { it.activity }
@get: Rule(order = 1)
val intentReceiverActivityTestRule = ActivityTestRule(
IntentReceiverActivity::class.java,
true,
false,
)
@Rule(order = 2)
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
// Initializing this as part of class construction, below the rule would throw a NPE
// So we are initializing this here instead of in all related tests.
browserStore = activityTestRule.activity.components.core.store
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// Device or AVD requires a Google Services Android OS installation with Play Store installed
// Verifies the Open in app button when an app is installed
@Test
fun mainMenuOpenInAppTest() {
val youtubeURL = "vnd.youtube://".toUri()
navigationToolbar {
}.enterURLAndEnterToBrowser(youtubeURL) {
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.clickOpenInApp {
assertYoutubeAppOpens()
}
}
// Verifies that deleting a Bookmarks folder also removes the item from inside it.
@Test
fun deleteNonEmptyBookmarkFolderTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
createBookmark(website.url)
}.openThreeDotMenu {
}.openBookmarks {
verifyBookmarkTitle("Test_Page_1")
createFolder("My Folder")
verifyFolderTitle("My Folder")
}.openThreeDotMenu("Test_Page_1") {
}.clickEdit {
clickParentFolderSelector()
selectFolder("My Folder")
navigateUp()
saveEditBookmark()
createFolder("My Folder 2")
verifyFolderTitle("My Folder 2")
}.openThreeDotMenu("My Folder 2") {
}.clickEdit {
clickParentFolderSelector()
selectFolder("My Folder")
navigateUp()
saveEditBookmark()
}.openThreeDotMenu("My Folder") {
}.clickDelete {
cancelFolderDeletion()
verifyFolderTitle("My Folder")
}.openThreeDotMenu("My Folder") {
}.clickDelete {
confirmDeletion()
verifyDeleteSnackBarText()
verifyBookmarkIsDeleted("My Folder")
verifyBookmarkIsDeleted("My Folder 2")
verifyBookmarkIsDeleted("Test_Page_1")
navigateUp()
}
browserScreen {
}.openThreeDotMenu {
verifyAddBookmarkButton()
}
}
@Test
fun shareTabsFromTabsTrayTest() {
val firstWebsite = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebsite = TestAssetHelper.getGenericAsset(mockWebServer, 2)
val firstWebsiteTitle = firstWebsite.title
val secondWebsiteTitle = secondWebsite.title
val sharingApp = "Gmail"
val sharedUrlsString = "${firstWebsite.url}\n\n${secondWebsite.url}"
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(firstWebsite.url) {
verifyPageContent(firstWebsite.content)
}.openComposeTabDrawer(activityTestRule) {
}.openNewTab {
}.submitQuery(secondWebsite.url.toString()) {
verifyPageContent(secondWebsite.content)
}.openComposeTabDrawer(activityTestRule) {
verifyExistingOpenTabs("Test_Page_1")
verifyExistingOpenTabs("Test_Page_2")
}.openThreeDotMenu {
verifyShareAllTabsButton()
}.clickShareAllTabsButton {
verifyShareTabsOverlay(firstWebsiteTitle, secondWebsiteTitle)
verifySharingWithSelectedApp(
sharingApp,
sharedUrlsString,
"$firstWebsiteTitle, $secondWebsiteTitle",
)
}
}
@Test
fun privateTabsTrayWithOpenedTabTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
}.openComposeTabDrawer(activityTestRule) {
verifyNormalBrowsingButtonIsSelected(false)
verifyPrivateBrowsingButtonIsSelected(true)
verifySyncedTabsButtonIsSelected(false)
verifyThreeDotButton()
verifyNormalTabCounter()
verifyPrivateTabsList()
verifyExistingOpenTabs(website.title)
verifyTabCloseButton()
verifyTabThumbnail()
verifyFab()
}
}
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@Test
fun noHistoryInPrivateBrowsingTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openHistory {
verifyEmptyHistoryView()
}
}
@Test
fun mainMenuInstallPWATest() {
val pwaPage = "https://mozilla-mobile.github.io/testapp/"
navigationToolbar {
}.enterURLAndEnterToBrowser(pwaPage.toUri()) {
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.clickInstall {
clickAddAutomaticallyButton()
}.openHomeScreenShortcut("TEST_APP") {
mDevice.waitForIdle()
verifyNavURLBarHidden()
}
}
// Verifies that reader mode is detected and the custom appearance controls are displayed
@Test
fun verifyReaderViewAppearanceUI() {
val readerViewPage =
TestAssetHelper.getLoremIpsumAsset(mockWebServer)
val estimatedReadingTime = "1 - 2 minutes"
navigationToolbar {
}.enterURLAndEnterToBrowser(readerViewPage.url) {
mDevice.waitForIdle()
}
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE,
),
) {}
navigationToolbar {
verifyReaderViewDetected(true)
toggleReaderView()
}
browserScreen {
waitForPageToLoad()
verifyPageContent(estimatedReadingTime)
}.openThreeDotMenu {
verifyReaderViewAppearance(true)
}.openReaderViewAppearance {
verifyAppearanceFontGroup(true)
verifyAppearanceFontSansSerif(true)
verifyAppearanceFontSerif(true)
verifyAppearanceFontIncrease(true)
verifyAppearanceFontDecrease(true)
verifyAppearanceColorGroup(true)
verifyAppearanceColorDark(true)
verifyAppearanceColorLight(true)
verifyAppearanceColorSepia(true)
}
}
@Ignore("Failing, see https://bugzilla.mozilla.org/show_bug.cgi?id=1846941")
@Test
fun tabMediaControlButtonTest() {
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
navigationToolbar {
}.enterURLAndEnterToBrowser(audioTestPage.url) {
mDevice.waitForIdle()
clickPageObject(itemWithText("Play"))
assertPlaybackState(browserStore, MediaSession.PlaybackState.PLAYING)
}.openComposeTabDrawer(activityTestRule) {
verifyTabMediaControlButtonState("Pause")
clickTabMediaControlButton("Pause")
verifyTabMediaControlButtonState("Play")
}.openTab(audioTestPage.title) {
assertPlaybackState(browserStore, MediaSession.PlaybackState.PAUSED)
}
}
// For API>23
// Verifies the default browser switch opens the system default apps menu.
@Test
fun changeDefaultBrowserSetting() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
verifyDefaultBrowserToggle(false)
clickDefaultBrowserSwitch()
verifyAndroidDefaultAppsMenuAppears()
}
// Dismiss the request
mDevice.pressBack()
}
@Test
fun goToHomeScreenBottomToolbarTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
mDevice.waitForIdle()
}.goToHomescreen {
verifyHomeScreen()
}
}
@Test
fun goToHomeScreenTopToolbarTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openCustomizeSubMenu {
clickTopToolbarToggle()
}.goBack {
}.goBack {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
mDevice.waitForIdle()
}.goToHomescreen {
verifyHomeScreen()
}
}
@Test
fun goToHomeScreenBottomToolbarPrivateModeTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
togglePrivateBrowsingModeOnOff()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
mDevice.waitForIdle()
}.goToHomescreen {
verifyHomeScreen()
}
}
@Test
fun goToHomeScreenTopToolbarPrivateModeTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
togglePrivateBrowsingModeOnOff()
}.openThreeDotMenu {
}.openSettings {
}.openCustomizeSubMenu {
clickTopToolbarToggle()
}.goBack {
}.goBack {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
mDevice.waitForIdle()
}.goToHomescreen {
verifyHomeScreen()
}
}
}
/* 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.ui
import android.view.View
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.core.net.toUri
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.uiautomator.UiDevice
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.mediasession.MediaSession
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.IntentReceiverActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
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.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.ViewVisibilityIdlingResource
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
/**
* Test Suite that contains a part of the Smoke and Sanity tests defined in TestRail:
* https://testrail.stage.mozaws.net/index.php?/suites/view/3192
* Other smoke tests have been marked with the @SmokeTest annotation throughout the ui package in order to limit this class expansion.
* These tests will verify different functionalities of the app as a way to quickly detect regressions in main areas
*/
@Suppress("ForbiddenComment")
@SmokeTest
class ComposeSmokeTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
private val customMenuItem = "TestMenuItem"
private lateinit var browserStore: BrowserStore
@get:Rule(order = 0)
val activityTestRule = AndroidComposeTestRule(
HomeActivityIntentTestRule.withDefaultSettingsOverrides(
tabsTrayRewriteEnabled = true,
),
) { it.activity }
@get: Rule(order = 1)
val intentReceiverActivityTestRule = ActivityTestRule(
IntentReceiverActivity::class.java,
true,
false,
)
@Rule(order = 2)
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
// Initializing this as part of class construction, below the rule would throw a NPE
// So we are initializing this here instead of in all related tests.
browserStore = activityTestRule.activity.components.core.store
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
@Test
fun shareTabsFromTabsTrayTest() {
val firstWebsite = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebsite = TestAssetHelper.getGenericAsset(mockWebServer, 2)
val firstWebsiteTitle = firstWebsite.title
val secondWebsiteTitle = secondWebsite.title
val sharingApp = "Gmail"
val sharedUrlsString = "${firstWebsite.url}\n\n${secondWebsite.url}"
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(firstWebsite.url) {
verifyPageContent(firstWebsite.content)
}.openComposeTabDrawer(activityTestRule) {
}.openNewTab {
}.submitQuery(secondWebsite.url.toString()) {
verifyPageContent(secondWebsite.content)
}.openComposeTabDrawer(activityTestRule) {
verifyExistingOpenTabs("Test_Page_1")
verifyExistingOpenTabs("Test_Page_2")
}.openThreeDotMenu {
verifyShareAllTabsButton()
}.clickShareAllTabsButton {
verifyShareTabsOverlay(firstWebsiteTitle, secondWebsiteTitle)
verifySharingWithSelectedApp(
sharingApp,
sharedUrlsString,
"$firstWebsiteTitle, $secondWebsiteTitle",
)
}
}
@Test
fun privateTabsTrayWithOpenedTabTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
}.openComposeTabDrawer(activityTestRule) {
verifyNormalBrowsingButtonIsSelected(false)
verifyPrivateBrowsingButtonIsSelected(true)
verifySyncedTabsButtonIsSelected(false)
verifyThreeDotButton()
verifyNormalTabCounter()
verifyPrivateTabsList()
verifyExistingOpenTabs(website.title)
verifyTabCloseButton()
verifyTabThumbnail()
verifyFab()
}
}
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@Test
fun noHistoryInPrivateBrowsingTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openHistory {
verifyEmptyHistoryView()
}
}
@Test
fun mainMenuInstallPWATest() {
val pwaPage = "https://mozilla-mobile.github.io/testapp/"
navigationToolbar {
}.enterURLAndEnterToBrowser(pwaPage.toUri()) {
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.clickInstall {
clickAddAutomaticallyButton()
}.openHomeScreenShortcut("TEST_APP") {
mDevice.waitForIdle()
verifyNavURLBarHidden()
}
}
// Verifies that reader mode is detected and the custom appearance controls are displayed
@Test
fun verifyReaderViewAppearanceUI() {
val readerViewPage =
TestAssetHelper.getLoremIpsumAsset(mockWebServer)
val estimatedReadingTime = "1 - 2 minutes"
navigationToolbar {
}.enterURLAndEnterToBrowser(readerViewPage.url) {
mDevice.waitForIdle()
}
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE,
),
) {}
navigationToolbar {
verifyReaderViewDetected(true)
toggleReaderView()
}
browserScreen {
waitForPageToLoad()
verifyPageContent(estimatedReadingTime)
}.openThreeDotMenu {
verifyReaderViewAppearance(true)
}.openReaderViewAppearance {
verifyAppearanceFontGroup(true)
verifyAppearanceFontSansSerif(true)
verifyAppearanceFontSerif(true)
verifyAppearanceFontIncrease(true)
verifyAppearanceFontDecrease(true)
verifyAppearanceColorGroup(true)
verifyAppearanceColorDark(true)
verifyAppearanceColorLight(true)
verifyAppearanceColorSepia(true)
}
}
@Test
fun tabMediaControlButtonTest() {
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
navigationToolbar {
}.enterURLAndEnterToBrowser(audioTestPage.url) {
mDevice.waitForIdle()
clickPageObject(itemWithText("Play"))
assertPlaybackState(browserStore, MediaSession.PlaybackState.PLAYING)
}.openComposeTabDrawer(activityTestRule) {
verifyTabMediaControlButtonState("Pause")
clickTabMediaControlButton("Pause")
verifyTabMediaControlButtonState("Play")
}.openTab(audioTestPage.title) {
assertPlaybackState(browserStore, MediaSession.PlaybackState.PAUSED)
}
}
}

@ -0,0 +1,256 @@
/* 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 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.Rule
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.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
import org.mozilla.fenix.ui.robots.navigationToolbar
/**
* Tests Top Sites functionality
*
* - Verifies 'Add to Firefox Home' UI functionality
* - Verifies 'Top Sites' context menu UI functionality
* - Verifies 'Top Site' usage UI functionality
* - Verifies existence of default top sites available on the home-screen
*/
class ComposeTopSitesTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
@get:Rule
val composeTestRule =
AndroidComposeTestRule(
HomeActivityTestRule.withDefaultSettingsOverrides(
composeTopSitesEnabled = true,
),
) { it.activity }
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
@SmokeTest
@Test
fun verifyAddToFirefoxHome() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
expandMenu()
verifyAddToShortcutsButton(true)
}.addToFirefoxHome {
verifySnackBarText(getStringResource(R.string.snackbar_added_to_shortcuts))
}.goToHomescreenWithComposeTopSites(composeTestRule) {
verifyExistingTopSitesList()
verifyExistingTopSiteItem(defaultWebPage.title)
}
}
@Test
fun verifyOpenTopSiteNormalTab() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
expandMenu()
verifyAddToShortcutsButton(true)
}.addToFirefoxHome {
verifySnackBarText(getStringResource(R.string.snackbar_added_to_shortcuts))
}.goToHomescreenWithComposeTopSites(composeTestRule) {
verifyExistingTopSitesList()
verifyExistingTopSiteItem(defaultWebPage.title)
}.openTopSiteTabWithTitle(title = defaultWebPage.title) {
verifyUrl(defaultWebPage.url.toString().replace("http://", ""))
}.goToHomescreenWithComposeTopSites(composeTestRule) {
verifyExistingTopSitesList()
verifyExistingTopSiteItem(defaultWebPage.title)
}.openContextMenuOnTopSitesWithTitle(defaultWebPage.title) {
verifyTopSiteContextMenuItems()
}
// Dismiss context menu popup
mDevice.pressBack()
}
@Test
fun verifyOpenTopSitePrivateTab() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
expandMenu()
verifyAddToShortcutsButton(true)
}.addToFirefoxHome {
verifySnackBarText(getStringResource(R.string.snackbar_added_to_shortcuts))
}.goToHomescreenWithComposeTopSites(composeTestRule) {
verifyExistingTopSitesList()
verifyExistingTopSiteItem(defaultWebPage.title)
}.openContextMenuOnTopSitesWithTitle(defaultWebPage.title) {
verifyTopSiteContextMenuItems()
}.openTopSiteInPrivate() {
verifyCurrentPrivateSession(composeTestRule.activity.applicationContext)
}
}
@Test
fun verifyRenameTopSite() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
val newPageTitle = generateRandomString(5)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
waitForPageToLoad()
}.openThreeDotMenu {
expandMenu()
verifyAddToShortcutsButton(true)
}.addToFirefoxHome {
verifySnackBarText(getStringResource(R.string.snackbar_added_to_shortcuts))
}.goToHomescreenWithComposeTopSites(composeTestRule) {
verifyExistingTopSitesList()
verifyExistingTopSiteItem(defaultWebPage.title)
}.openContextMenuOnTopSitesWithTitle(defaultWebPage.title) {
verifyTopSiteContextMenuItems()
}.renameTopSite(newPageTitle) {
verifyExistingTopSitesList()
verifyExistingTopSiteItem(newPageTitle)
}
}
@Test
fun verifyRemoveTopSite() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
expandMenu()
verifyAddToShortcutsButton(true)
}.addToFirefoxHome {
verifySnackBarText(getStringResource(R.string.snackbar_added_to_shortcuts))
}.goToHomescreenWithComposeTopSites(composeTestRule) {
verifyExistingTopSitesList()
verifyExistingTopSiteItem(defaultWebPage.title)
}.openContextMenuOnTopSitesWithTitle(defaultWebPage.title) {
verifyTopSiteContextMenuItems()
}.removeTopSite {
verifyNotExistingTopSiteItem(defaultWebPage.title)
}
}
@Test
fun verifyUndoRemoveTopSite() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
expandMenu()
verifyAddToShortcutsButton(true)
}.addToFirefoxHome {
verifySnackBarText(getStringResource(R.string.snackbar_added_to_shortcuts))
}.goToHomescreenWithComposeTopSites(composeTestRule) {
verifyExistingTopSitesList()
verifyExistingTopSiteItem(defaultWebPage.title)
}.openContextMenuOnTopSitesWithTitle(defaultWebPage.title) {
verifyTopSiteContextMenuItems()
}.removeTopSite {
clickSnackbarButton("UNDO")
verifyExistingTopSiteItem(defaultWebPage.title)
}
}
@Test
fun verifyRemoveTopSiteFromMainMenu() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
expandMenu()
verifyAddToShortcutsButton(true)
}.addToFirefoxHome {
verifySnackBarText(getStringResource(R.string.snackbar_added_to_shortcuts))
}.goToHomescreenWithComposeTopSites(composeTestRule) {
verifyExistingTopSitesList()
verifyExistingTopSiteItem(defaultWebPage.title)
}.openTopSiteTabWithTitle(defaultWebPage.title) {
}.openThreeDotMenu {
verifyRemoveFromShortcutsButton()
}.clickRemoveFromShortcuts {
}.goToHomescreenWithComposeTopSites(composeTestRule) {
verifyNotExistingTopSiteItem(defaultWebPage.title)
}
}
// Expected for en-us defaults
@Test
fun verifyDefaultTopSitesList() {
homeScreenWithComposeTopSites(composeTestRule) {
verifyExistingTopSitesList()
val topSitesTitles = arrayListOf("Google", "Top Articles", "Wikipedia")
topSitesTitles.forEach { value ->
verifyExistingTopSiteItem(value)
}
}
}
@SmokeTest
@Test
fun addAndRemoveMostViewedTopSiteTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
for (i in 0..1) {
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
waitForPageToLoad()
}
}
browserScreen {
}.goToHomescreenWithComposeTopSites(composeTestRule) {
verifyExistingTopSitesList()
verifyExistingTopSiteItem(defaultWebPage.title)
}.openContextMenuOnTopSitesWithTitle(defaultWebPage.title) {
}.deleteTopSiteFromHistory {
verifySnackBarText(getStringResource(R.string.snackbar_top_site_removed))
waitUntilSnackbarGone()
}.openThreeDotMenu {
}.openHistory {
verifyEmptyHistoryView()
}
}
}

@ -15,12 +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.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.assertYoutubeAppOpens
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
@ -231,7 +232,7 @@ class ContextMenusTest {
}
downloadRobot {
verifyDownloadNotificationPopup()
verifyDownloadCompleteNotificationPopup()
}.clickOpen("image/jpeg") {} // verify open intent is matched with associated data type
downloadRobot {
verifyPhotosAppOpens()
@ -287,10 +288,10 @@ class ContextMenusTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
longClickPageObject(itemContainingText("Youtube link"))
verifyContextMenuForLinksToOtherApps("youtube.com".toUri())
longClickPageObject(itemContainingText("Youtube full link"))
verifyContextMenuForLinksToOtherApps("youtube.com")
clickContextMenuItem("Open link in external app")
assertYoutubeAppOpens()
assertExternalAppOpens(YOUTUBE_APP)
}
}
}

@ -14,17 +14,17 @@ 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
import org.mozilla.fenix.ui.robots.navigationToolbar
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 verifyCookieBannerReductionTest() {
fun verifyCookieBannerReductionFunctionalityTest() {
val webSite = "startsiden.no"
homeScreen {
@ -69,55 +69,4 @@ class CookieBannerReductionTest {
verifyCookieBannerExists(exists = false)
}
}
// Bug causing flakiness https://bugzilla.mozilla.org/show_bug.cgi?id=1807440
@SmokeTest
@Test
fun verifyCookieBannerReductionInPrivateBrowsingTest() {
val webSite = "startsiden.no"
homeScreen {
}.togglePrivateBrowsingMode()
navigationToolbar {
}.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)
homeScreen {
}.openTabDrawer {
}.openTab("Startsiden.no") {
verifyCookieBannerExists(exists = false)
}.openThreeDotMenu {
}.openSettings {
}.openCookieBannerReductionSubMenu {
clickCookieBannerReductionToggle()
verifyCheckedCookieBannerReductionToggle(false)
exitMenu()
}
browserScreen {
waitForPageToLoad()
}.openThreeDotMenu {
}.refreshPage {
verifyCookieBannerExists(exists = false)
}
}
}

@ -62,6 +62,7 @@ class CreditCardAutofillTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1512792
@SmokeTest
@Test
fun verifyCreditCardAutofillTest() {
@ -99,32 +100,10 @@ class CreditCardAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1512798
@SmokeTest
@Test
fun deleteSavedCreditCardUsingToolbarButtonTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
clickAddCreditCardButton()
fillAndSaveCreditCard(
MockCreditCard1.MOCK_CREDIT_CARD_NUMBER,
MockCreditCard1.MOCK_NAME_ON_CARD,
MockCreditCard1.MOCK_EXPIRATION_MONTH,
MockCreditCard1.MOCK_EXPIRATION_YEAR,
)
clickManageSavedCreditCardsButton()
clickSecuredCreditCardsLaterButton()
clickSavedCreditCard()
clickDeleteCreditCardToolbarButton()
clickConfirmDeleteCreditCardButton()
verifyAddCreditCardsButton()
}
}
@SmokeTest
@Test
fun cancelDeleteSavedCreditCardUsingToolbarButtonTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -142,35 +121,16 @@ class CreditCardAutofillTest {
clickDeleteCreditCardToolbarButton()
clickCancelDeleteCreditCardButton()
verifyEditCreditCardToolbarTitle()
}
}
@SmokeTest
@Test
fun deleteSavedCreditCardUsingMenuButtonTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
clickAddCreditCardButton()
fillAndSaveCreditCard(
MockCreditCard1.MOCK_CREDIT_CARD_NUMBER,
MockCreditCard1.MOCK_NAME_ON_CARD,
MockCreditCard1.MOCK_EXPIRATION_MONTH,
MockCreditCard1.MOCK_EXPIRATION_YEAR,
)
clickManageSavedCreditCardsButton()
clickSecuredCreditCardsLaterButton()
clickSavedCreditCard()
clickDeleteCreditCardMenuButton()
clickDeleteCreditCardToolbarButton()
clickConfirmDeleteCreditCardButton()
verifyAddCreditCardsButton()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2271192
@SmokeTest
@Test
fun cancelDeleteSavedCreditCardUsingMenuButtonTest() {
fun deleteSavedCreditCardUsingMenuButtonTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -188,9 +148,13 @@ class CreditCardAutofillTest {
clickDeleteCreditCardMenuButton()
clickCancelDeleteCreditCardButton()
verifyEditCreditCardToolbarTitle()
clickDeleteCreditCardMenuButton()
clickConfirmDeleteCreditCardButton()
verifyAddCreditCardsButton()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1512788
@Test
fun verifyCreditCardsSectionTest() {
homeScreen {
@ -214,6 +178,7 @@ class CreditCardAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1859917
@Test
fun verifyManageCreditCardsPromptOptionTest() {
val creditCardFormPage = TestAssetHelper.getCreditCardFormAsset(mockWebServer)
@ -243,6 +208,7 @@ class CreditCardAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1512790
@Test
fun verifyCreditCardsAutofillToggleTest() {
val creditCardFormPage = TestAssetHelper.getCreditCardFormAsset(mockWebServer)
@ -283,6 +249,7 @@ class CreditCardAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1512795
@Test
fun verifyEditCardsViewTest() {
homeScreen {
@ -318,6 +285,7 @@ class CreditCardAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1512796
@Test
fun verifyEditedCardIsSavedTest() {
val creditCardFormPage = TestAssetHelper.getCreditCardFormAsset(mockWebServer)
@ -365,8 +333,9 @@ class CreditCardAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1512797
@Test
fun verifyCreditCardCannotBeSavedWithoutCardNumberTest() {
fun verifyCreditCardCannotBeSavedWithoutCardNumberOrNameTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -390,29 +359,7 @@ class CreditCardAutofillTest {
clickSaveCreditCardToolbarButton()
verifyEditCreditCardToolbarTitle()
verifyCreditCardNumberErrorMessage()
}
}
@Test
fun verifyCreditCardCannotBeSavedWithoutNameOnCardTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
verifyCreditCardsAutofillSection(true, false)
clickAddCreditCardButton()
fillAndSaveCreditCard(
MockCreditCard1.MOCK_CREDIT_CARD_NUMBER,
MockCreditCard1.MOCK_NAME_ON_CARD,
MockCreditCard1.MOCK_EXPIRATION_MONTH,
MockCreditCard1.MOCK_EXPIRATION_YEAR,
)
clickManageSavedCreditCardsButton()
clickSecuredCreditCardsLaterButton()
verifySavedCreditCardsSection(
MockCreditCard1.MOCK_LAST_CARD_DIGITS,
MockCreditCard1.MOCK_EXPIRATION_MONTH_AND_YEAR,
)
}.goBackToSavedCreditCards {
clickSavedCreditCard()
clearNameOnCreditCard()
clickSaveCreditCardToolbarButton()
@ -421,8 +368,9 @@ class CreditCardAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1512794
@Test
fun verifyMultipleCreditCardsCanBeSavedTest() {
fun verifyMultipleCreditCardsCanBeAddedTest() {
val creditCardFormPage = TestAssetHelper.getCreditCardFormAsset(mockWebServer)
homeScreen {
@ -476,8 +424,9 @@ class CreditCardAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2271304
@Test
fun verifyDoNotSaveCreditCardFromFormTest() {
fun verifyDoNotSaveCreditCardFromPromptTest() {
val creditCardFormPage = TestAssetHelper.getCreditCardFormAsset(mockWebServer)
navigationToolbar {
@ -496,8 +445,9 @@ class CreditCardAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1779194
@Test
fun verifySaveCreditCardFromFormTest() {
fun verifySaveCreditCardFromPromptTest() {
val creditCardFormPage = TestAssetHelper.getCreditCardFormAsset(mockWebServer)
navigationToolbar {
@ -522,6 +472,7 @@ class CreditCardAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2271305
@Test
fun verifyCancelCreditCardUpdatePromptTest() {
val creditCardFormPage = TestAssetHelper.getCreditCardFormAsset(mockWebServer)
@ -572,6 +523,7 @@ class CreditCardAutofillTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1779195
@Test
fun verifyConfirmCreditCardUpdatePromptTest() {
val creditCardFormPage = TestAssetHelper.getCreditCardFormAsset(mockWebServer)
@ -622,9 +574,10 @@ class CreditCardAutofillTest {
}
}
@Ignore("Failing, see https://bugzilla.mozilla.org/show_bug.cgi?id=1847774")
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1512791
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1854566")
@Test
fun verifySavedCreditCardsRedirectionToAutofillAfterInterruptionTest() {
fun verifyCreditCardRedirectionsToAutofillSectionAfterInterruptionTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -639,33 +592,15 @@ class CreditCardAutofillTest {
)
clickManageSavedCreditCardsButton()
clickSecuredCreditCardsLaterButton()
verifySavedCreditCardsSection(
MockCreditCard1.MOCK_LAST_CARD_DIGITS,
MockCreditCard1.MOCK_EXPIRATION_MONTH_AND_YEAR,
)
clickSavedCreditCard()
putAppToBackground()
bringAppToForeground()
verifyAutofillToolbarTitle()
}
}
@Test
fun verifyEditCreditCardRedirectionToAutofillAfterInterruptionTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
verifyCreditCardsAutofillSection(true, false)
clickAddCreditCardButton()
fillAndSaveCreditCard(
MockCreditCard1.MOCK_CREDIT_CARD_NUMBER,
MockCreditCard1.MOCK_NAME_ON_CARD,
MockCreditCard1.MOCK_EXPIRATION_MONTH,
MockCreditCard1.MOCK_EXPIRATION_YEAR,
)
clickManageSavedCreditCardsButton()
clickSecuredCreditCardsLaterButton()
clickSavedCreditCard()
verifySavedCreditCardsSection(
MockCreditCard1.MOCK_LAST_CARD_DIGITS,
MockCreditCard1.MOCK_EXPIRATION_MONTH_AND_YEAR,
)
putAppToBackground()
bringAppToForeground()
verifyAutofillToolbarTitle()

@ -206,7 +206,7 @@ class CustomTabsTest {
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
verifyDownloadNotificationPopup()
verifyDownloadCompleteNotificationPopup()
}
mDevice.openNotification()
notificationShade {

@ -91,7 +91,6 @@ class DeepLinkTest {
@Test
fun openCollections() {
robot.openHomeScreen { /* do nothing */ }.dismissOnboarding()
robot.openCollections {
verifyCollectionsHeader()
}

@ -41,18 +41,20 @@ class DownloadFileTypesTest(fileName: String) {
"videoSample.webm",
"CSVfile.csv",
"XMLfile.xml",
"tAJwqaWjJsXS8AhzSninBMCfIZbHBGgcc001lx5DIdDwIcfEgQ6vE5Gb5VgAled17DFZ2A7ZDOHA0NpQPHXXFt.svg",
)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/251028&group_by=cases:section_id&group_id=31659&group_order=asc
@SmokeTest
@Test
fun downloadMultipleFileTypesTest() {
fun allFilesAppearInDownloadsMenuTest() {
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
verifyDownloadNotificationPopup()
verifyDownloadCompleteNotificationPopup()
}.closeCompletedDownloadPrompt {
}.openThreeDotMenu {
}.openDownloadsManager {

@ -13,6 +13,7 @@ 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.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
@ -20,6 +21,7 @@ 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
@ -72,8 +74,9 @@ class DownloadTest {
setNetworkEnabled(enabled = true)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243844
@Test
fun testDownloadPrompt() {
fun verifyTheDownloadPromptsTest() {
downloadFile = "web_icon.png"
navigationToolbar {
@ -82,7 +85,7 @@ class DownloadTest {
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
verifyDownloadNotificationPopup()
verifyDownloadCompleteNotificationPopup()
}.clickOpen("image/png") {}
downloadRobot {
verifyPhotosAppOpens()
@ -91,25 +94,34 @@ class DownloadTest {
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2299405
@Test
fun testCloseDownloadPrompt() {
downloadFile = "smallZip.zip"
fun verifyTheDownloadFailedNotificationsTest() {
downloadFile = "1GB.zip"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.closePrompt {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyEmptyDownloadsList()
}.clickDownload {
setNetworkEnabled(enabled = false)
verifyDownloadFailedPrompt(downloadFile)
setNetworkEnabled(enabled = true)
clickTryAgainButton()
}
mDevice.openNotification()
notificationShade {
verifySystemNotificationDoesNotExist("Download failed")
verifySystemNotificationExists(downloadFile)
}.closeNotificationTray {}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2298616
@Test
fun testDownloadCompleteNotification() {
downloadFile = "smallZip.zip"
fun verifyDownloadCompleteNotificationTest() {
downloadFile = "web_icon.png"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
@ -117,15 +129,26 @@ class DownloadTest {
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
verifyDownloadNotificationPopup()
verifyDownloadCompleteNotificationPopup()
}
mDevice.openNotification()
notificationShade {
verifySystemNotificationExists("Download completed")
}
clickNotification("Download completed")
assertExternalAppOpens(GOOGLE_APPS_PHOTOS)
mDevice.pressBack()
mDevice.openNotification()
swipeDownloadNotification(
direction = "Left",
shouldDismissNotification = true,
canExpandNotification = false,
)
verifySystemNotificationDoesNotExist("Firefox Fenix")
}.closeNotificationTray {}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/451563
@Ignore("Failing: Bug https://bugzilla.mozilla.org/show_bug.cgi?id=1813521")
@SmokeTest
@Test
@ -148,8 +171,10 @@ class DownloadTest {
verifySystemNotificationExists("Firefox Fenix")
expandNotificationMessage()
clickDownloadNotificationControlButton("PAUSE")
verifySystemNotificationExists("Download paused")
clickDownloadNotificationControlButton("RESUME")
clickDownloadNotificationControlButton("CANCEL")
verifySystemNotificationDoesNotExist(downloadFile)
mDevice.pressBack()
}
browserScreen {
@ -160,42 +185,9 @@ class DownloadTest {
deleteDownloadedFileOnStorage(downloadFile)
}
/* Verifies downloads in the Downloads Menu:
- downloads appear in the list
- deleting a download from device storage, removes it from the Downloads Menu too
*/
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2301474
@Test
fun manageDownloadsInDownloadsMenuTest() {
// a long filename to verify it's correctly displayed on the prompt and in the Downloads menu
downloadFile =
"tAJwqaWjJsXS8AhzSninBMCfIZbHBGgcc001lx5DIdDwIcfEgQ6vE5Gb5VgAled17DFZ2A7ZDOHA0NpQPHXXFt.svg"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
verifyDownloadNotificationPopup()
}
browserScreen {
}.openThreeDotMenu {
}.openDownloadsManager {
waitForDownloadsListToExist()
verifyDownloadedFileName(downloadFile)
verifyDownloadedFileIcon()
deleteDownloadedFileOnStorage(downloadFile)
}.exitDownloadsManagerToBrowser {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyEmptyDownloadsList()
}
}
@SmokeTest
@Test
fun openDownloadedFileTest() {
fun openDownloadedFileFromDownloadsMenuTest() {
downloadFile = "web_icon.png"
navigationToolbar {
@ -204,7 +196,7 @@ class DownloadTest {
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
verifyDownloadNotificationPopup()
verifyDownloadCompleteNotificationPopup()
}
browserScreen {
}.openThreeDotMenu {
@ -239,32 +231,11 @@ class DownloadTest {
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)
}
browserScreen {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyDownloadedFileName(downloadFile)
deleteDownloadedItem(downloadFile)
verifyEmptyDownloadsList()
}
deleteDownloadedFileOnStorage(downloadFile)
}
@Test
fun undoDeleteDownloadedFileTest() {
downloadFile = "smallZip.zip"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
@ -280,10 +251,13 @@ class DownloadTest {
deleteDownloadedItem(downloadFile)
clickSnackbarButton("UNDO")
verifyDownloadedFileName(downloadFile)
deleteDownloadedItem(downloadFile)
verifyEmptyDownloadsList()
}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2302662
@Test
fun deleteMultipleDownloadedFilesTest() {
val firstDownloadedFile = "smallZip.zip"
@ -305,6 +279,13 @@ class DownloadTest {
browserScreen {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyDownloadedFileName(firstDownloadedFile)
verifyDownloadedFileName(secondDownloadedFile)
longClickDownloadedItem(firstDownloadedFile)
selectDownloadedItem(secondDownloadedFile)
openMultiSelectMoreOptionsMenu()
clickMultiSelectRemoveButton()
clickSnackbarButton("UNDO")
verifyDownloadedFileName(firstDownloadedFile)
verifyDownloadedFileName(secondDownloadedFile)
longClickDownloadedItem(firstDownloadedFile)
@ -317,70 +298,52 @@ class DownloadTest {
deleteDownloadedFileOnStorage(secondDownloadedFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2301537
@Test
fun undoDeleteMultipleDownloadedFilesTest() {
val firstDownloadedFile = "smallZip.zip"
val secondDownloadedFile = "textfile.txt"
fun fileDeletedFromStorageIsDeletedEverywhereTest() {
val downloadFile = "smallZip.zip"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(firstDownloadedFile) {
verifyDownloadPrompt(firstDownloadedFile)
}.clickDownload {
verifyDownloadedFileName(firstDownloadedFile)
}.closeCompletedDownloadPrompt {
}.clickDownloadLink(secondDownloadedFile) {
verifyDownloadPrompt(secondDownloadedFile)
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
verifyDownloadedFileName(secondDownloadedFile)
verifyDownloadCompleteNotificationPopup()
}
browserScreen {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyDownloadedFileName(firstDownloadedFile)
verifyDownloadedFileName(secondDownloadedFile)
longClickDownloadedItem(firstDownloadedFile)
selectDownloadedItem(secondDownloadedFile)
openMultiSelectMoreOptionsMenu()
clickMultiSelectRemoveButton()
clickSnackbarButton("UNDO")
verifyDownloadedFileName(firstDownloadedFile)
verifyDownloadedFileName(secondDownloadedFile)
}
deleteDownloadedFileOnStorage(firstDownloadedFile)
deleteDownloadedFileOnStorage(secondDownloadedFile)
}
@Ignore("Failing: https://bugzilla.mozilla.org/show_bug.cgi?id=1840994")
@Test
fun systemNotificationCantBeDismissedWhileDownloadingTest() {
// Clear the "Firefox Fenix default browser notification"
notificationShade {
cancelAllShownNotifications()
waitForDownloadsListToExist()
verifyDownloadedFileName(downloadFile)
deleteDownloadedFileOnStorage(downloadFile)
}.exitDownloadsManagerToBrowser {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyEmptyDownloadsList()
exitMenu()
}
downloadFile = "1GB.zip"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
verifyDownloadCompleteNotificationPopup()
}
browserScreen {
}.openNotificationShade {
verifySystemNotificationExists("Firefox Fenix")
expandNotificationMessage()
swipeDownloadNotification("Left", false)
clickDownloadNotificationControlButton("CANCEL")
}.openThreeDotMenu {
}.openDownloadsManager {
waitForDownloadsListToExist()
verifyDownloadedFileName(downloadFile)
}
deleteDownloadedFileOnStorage(downloadFile)
}
@Ignore("Failing: https://bugzilla.mozilla.org/show_bug.cgi?id=1840994")
@Test
fun systemNotificationCantBeDismissedWhileDownloadIsPausedTest() {
fun systemNotificationCantBeDismissedWhileInProgressTest() {
// Clear the "Firefox Fenix default browser notification"
notificationShade {
cancelAllShownNotifications()
@ -399,15 +362,9 @@ class DownloadTest {
}.openNotificationShade {
verifySystemNotificationExists("Firefox Fenix")
expandNotificationMessage()
swipeDownloadNotification(direction = "Left", shouldDismissNotification = false)
clickDownloadNotificationControlButton("PAUSE")
swipeDownloadNotification("Left", false)
verifySystemNotificationExists("Firefox Fenix")
}.closeNotificationTray {
}.openNotificationShade {
verifySystemNotificationExists("Firefox Fenix")
expandNotificationMessage()
swipeDownloadNotification("Right", false)
verifySystemNotificationExists("Firefox Fenix")
swipeDownloadNotification(direction = "Right", shouldDismissNotification = false)
clickDownloadNotificationControlButton("CANCEL")
}
deleteDownloadedFileOnStorage(downloadFile)
@ -427,8 +384,7 @@ class DownloadTest {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
}
}.clickDownload {}
setNetworkEnabled(enabled = false)
@ -438,8 +394,7 @@ class DownloadTest {
expandNotificationMessage()
swipeDownloadNotification("Left", true)
verifySystemNotificationDoesNotExist("Firefox Fenix")
}.closeNotificationTray {
}
}.closeNotificationTray {}
downloadRobot {
}.closeDownloadPrompt {
@ -449,56 +404,22 @@ class DownloadTest {
}
@Test
fun notificationCanBeDismissedIfDownloadIsCompletedTest() {
// Clear the "Firefox Fenix default browser notification"
notificationShade {
cancelAllShownNotifications()
}
downloadFile = "smallZip.zip"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
}
browserScreen {
}.openNotificationShade {
verifySystemNotificationExists("Download completed")
swipeDownloadNotification("Left", true, false)
verifySystemNotificationDoesNotExist("Firefox Fenix")
}.closeNotificationTray {
}
downloadRobot {
}.closeDownloadPrompt {
verifyDownloadPromptIsDismissed()
}
deleteDownloadedFileOnStorage(downloadFile)
}
fun warningWhenClosingPrivateTabsWhileDownloadingTest() {
downloadFile = "1GB.zip"
@Test
fun stayInPrivateBrowsingPromptTest() {
// Clear the "Firefox Fenix default browser notification"
notificationShade {
cancelAllShownNotifications()
}
downloadFile = "1GB.zip"
homeScreen {
}.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
}
}.clickDownload {}
browserScreen {
}.openTabDrawer {
closeTab()
@ -512,15 +433,16 @@ class DownloadTest {
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2302663
@Test
fun cancelActiveDownloadsFromPrivateBrowsingPromptTest() {
fun cancelActivePrivateBrowsingDownloadsTest() {
downloadFile = "1GB.zip"
// Clear the "Firefox Fenix default browser notification"
notificationShade {
cancelAllShownNotifications()
}
downloadFile = "1GB.zip"
homeScreen {
}.togglePrivateBrowsingMode()
@ -529,8 +451,7 @@ class DownloadTest {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
}
}.clickDownload {}
browserScreen {
}.openTabDrawer {
closeTab()

@ -63,6 +63,7 @@ class EnhancedTrackingProtectionTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416046
@Test
fun testETPSettingsItemsAndSubMenus() {
homeScreen {
@ -97,30 +98,9 @@ class EnhancedTrackingProtectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1514599
@Test
fun testETPSettingsSummaryChange() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
verifyEnhancedTrackingProtectionButton()
verifySettingsOptionSummary("Enhanced Tracking Protection", "Standard")
}.openEnhancedTrackingProtectionSubMenu {
selectTrackingProtectionOption("Strict")
}.goBack {
verifySettingsOptionSummary("Enhanced Tracking Protection", "Strict")
}.openEnhancedTrackingProtectionSubMenu {
selectTrackingProtectionOption("Custom")
}.goBack {
verifySettingsOptionSummary("Enhanced Tracking Protection", "Custom")
}.openEnhancedTrackingProtectionSubMenu {
switchEnhancedTrackingProtectionToggle()
}.goBack {
verifySettingsOptionSummary("Enhanced Tracking Protection", "Off")
}
}
@Test
fun testETPOffGlobally() {
fun verifyETPStateIsReflectedInTPSheetTest() {
val genericPage = getGenericAsset(mockWebServer, 1)
homeScreen {
@ -129,6 +109,8 @@ class EnhancedTrackingProtectionTest {
}.openEnhancedTrackingProtectionSubMenu {
switchEnhancedTrackingProtectionToggle()
verifyEnhancedTrackingProtectionOptionsEnabled(false)
}.goBack {
verifySettingsOptionSummary("Enhanced Tracking Protection", "Off")
exitMenu()
}
@ -151,10 +133,11 @@ class EnhancedTrackingProtectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/339712
// Tests adding ETP exceptions to websites and keeping that preference after restart
@SmokeTest
@Test
fun testDisableETPExceptionToggle() {
fun disablingETPOnAWebsiteAddsItToExceptionListTest() {
val firstPage = getGenericAsset(mockWebServer, 1)
val secondPage = "example.com"
@ -182,8 +165,9 @@ class EnhancedTrackingProtectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/339714
@Test
fun trackingProtectionSwitchEnabledRemovesExceptionTest() {
fun enablingETPOnAWebsiteRemovesItFromTheExceptionListTest() {
val trackingPage = getEnhancedTrackingProtectionAsset(mockWebServer)
navigationToolbar {
@ -212,9 +196,10 @@ class EnhancedTrackingProtectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/339713
// Tests removing TP exceptions individually or all at once
@Test
fun clearTrackingProtectionExceptionsTest() {
fun clearWebsitesFromTPExceptionListTest() {
val firstPage = getGenericAsset(mockWebServer, 1)
val secondPage = "example.com"
@ -249,11 +234,20 @@ class EnhancedTrackingProtectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/417444
@Test
fun testStandardETPVisitSheetDetails() {
fun verifyTrackersBlockedWithStandardTPTest() {
val genericPage = getGenericAsset(mockWebServer, 1)
val trackingProtectionTest = getEnhancedTrackingProtectionAsset(mockWebServer).url
homeScreen {
}.openThreeDotMenu {
}.openSettings {
verifyEnhancedTrackingProtectionButton()
verifySettingsOptionSummary("Enhanced Tracking Protection", "Standard")
exitMenu()
}
// browsing a generic page to allow GV to load on a fresh run
navigationToolbar {
}.enterURLAndEnterToBrowser(genericPage.url) {
@ -280,12 +274,21 @@ class EnhancedTrackingProtectionTest {
}.closeEnhancedTrackingProtectionSheet {}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/417441
@Test
fun testStrictVisitSheetDetails() {
fun verifyTrackersBlockedWithStrictTPTest() {
appContext.settings().setStrictETP()
val genericPage = getGenericAsset(mockWebServer, 1)
val trackingProtectionTest = getEnhancedTrackingProtectionAsset(mockWebServer).url
homeScreen {
}.openThreeDotMenu {
}.openSettings {
verifyEnhancedTrackingProtectionButton()
verifySettingsOptionSummary("Enhanced Tracking Protection", "Strict")
exitMenu()
}
// browsing a generic page to allow GV to load on a fresh run
navigationToolbar {
}.enterURLAndEnterToBrowser(genericPage.url) {
@ -316,9 +319,10 @@ class EnhancedTrackingProtectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/561637
@SmokeTest
@Test
fun defaultCustomTrackingProtectionSettingsTest() {
fun verifyTrackersBlockedWithCustomTPTest() {
val genericWebPage = getGenericAsset(mockWebServer, 1)
val trackingPage = getEnhancedTrackingProtectionAsset(mockWebServer)
@ -328,9 +332,12 @@ class EnhancedTrackingProtectionTest {
}.openEnhancedTrackingProtectionSubMenu {
selectTrackingProtectionOption("Custom")
verifyCustomTrackingProtectionSettings()
}.goBackToHomeScreen {
}.openNavigationToolbar {
// browsing a basic page to allow GV to load on a fresh run
}.goBack {
verifySettingsOptionSummary("Enhanced Tracking Protection", "Custom")
exitMenu()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(genericWebPage.url) {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(trackingPage.url) {
@ -355,6 +362,7 @@ class EnhancedTrackingProtectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/562710
// Tests the trackers blocked with the following Custom TP set up:
// - Cookies set to "All cookies"
// - Tracking content option OFF
@ -398,8 +406,9 @@ class EnhancedTrackingProtectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/562709
@Test
fun disableCustomTrackingProtectionOptionsTest() {
fun verifyTrackersBlockedWithCustomTPOptionsDisabledTest() {
val genericWebPage = getGenericAsset(mockWebServer, 1)
val trackingPage = getEnhancedTrackingProtectionAsset(mockWebServer)
@ -430,8 +439,9 @@ class EnhancedTrackingProtectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2106997
@Test
fun testTrackingContentBlockedOnlyInPrivateTabs() {
fun verifyTrackingContentBlockedOnlyInPrivateTabsTest() {
val genericWebPage = getGenericAsset(mockWebServer, 1)
val trackingPage = getEnhancedTrackingProtectionAsset(mockWebServer)
@ -480,6 +490,7 @@ class EnhancedTrackingProtectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2285368
@SmokeTest
@Test
fun blockCookiesStorageAccessTest() {
@ -502,6 +513,7 @@ class EnhancedTrackingProtectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2285369
@SmokeTest
@Test
fun allowCookiesStorageAccessTest() {

@ -73,8 +73,9 @@ class HistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243285
@Test
fun noHistoryItemsInCacheTest() {
fun verifyEmptyHistoryMenuTest() {
homeScreen {
}.openThreeDotMenu {
verifyHistoryButton()
@ -84,10 +85,12 @@ class HistoryTest {
}
}
// 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
@Test
fun visitedUrlHistoryTest() {
fun verifyHistoryMenuWithHistoryItemsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -103,34 +106,16 @@ class HistoryTest {
verifyVisitedTimeTitle()
verifyFirstTestPageTitle("Test_Page_1")
verifyTestPageUrl(firstWebPage.url)
verifyDeleteHistoryItemButton("Test_Page_1")
}
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243288
@Test
fun deleteHistoryItemTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1),
) {
clickDeleteHistoryButton(firstWebPage.url.toString())
}
verifyDeleteSnackbarText("Deleted")
verifyEmptyHistoryView()
}
}
@Test
fun undoDeleteHistoryItemTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
mDevice.waitForIdle()
@ -145,12 +130,16 @@ class HistoryTest {
verifyUndoDeleteSnackBarButton()
clickUndoDeleteButton()
verifyHistoryItemExists(true, firstWebPage.url.toString())
clickDeleteHistoryButton(firstWebPage.url.toString())
verifyDeleteSnackbarText("Deleted")
verifyEmptyHistoryView()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1848881
@SmokeTest
@Test
fun cancelDeleteAllHistoryTest() {
fun deleteAllHistoryTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -168,25 +157,7 @@ class HistoryTest {
selectEverythingOption()
cancelDeleteHistory()
verifyHistoryItemExists(true, firstWebPage.url.toString())
}
}
@SmokeTest
@Test
fun deleteAllHistoryTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1),
) {
clickDeleteAllHistoryButton()
}
clickDeleteAllHistoryButton()
verifyDeleteConfirmationMessage()
selectEverythingOption()
confirmDeleteAllHistory()
@ -195,7 +166,7 @@ class HistoryTest {
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/339690
@Test
fun historyMultiSelectionToolbarItemsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -223,9 +194,10 @@ class HistoryTest {
}
}
// 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 openHistoryInNewTabTest() {
fun openMultipleSelectedHistoryItemsInANewTabTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -253,8 +225,9 @@ class HistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/346098
@Test
fun openHistoryInPrivateTabTest() {
fun openMultipleSelectedHistoryItemsInPrivateTabTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -278,8 +251,9 @@ class HistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/346099
@Test
fun deleteMultipleSelectionTest() {
fun deleteMultipleSelectedHistoryItemsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
@ -312,8 +286,9 @@ class HistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/339701
@Test
fun shareButtonTest() {
fun shareMultipleSelectedHistoryItemsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -338,6 +313,7 @@ class HistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715627
@Test
fun verifySearchHistoryViewTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -380,6 +356,7 @@ class HistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715631
@Test
fun verifyVoiceSearchInHistoryTest() {
homeScreen {
@ -392,6 +369,7 @@ class HistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715632
@Test
fun verifySearchForHistoryItemsTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -407,13 +385,13 @@ class HistoryTest {
// Search for a valid term
typeSearch("generic")
verifySearchEngineSuggestionResults(activityTestRule, firstWebPage.url.toString(), searchTerm = "generic")
verifyNoSuggestionsAreDisplayed(activityTestRule, secondWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, secondWebPage.url.toString())
}.dismissSearchBar {}
historyMenu {
}.clickSearchButton {
// Search for invalid term
typeSearch("Android")
verifyNoSuggestionsAreDisplayed(
verifySuggestionsAreNotDisplayed(
activityTestRule,
firstWebPage.url.toString(),
secondWebPage.url.toString(),
@ -421,6 +399,7 @@ class HistoryTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1715634
@Test
fun verifyDeletedHistoryItemsCanNotBeSearchedTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -448,8 +427,8 @@ class HistoryTest {
}.clickSearchButton {
// Search for a valid term
typeSearch("generic")
verifyNoSuggestionsAreDisplayed(activityTestRule, firstWebPage.url.toString())
verifyNoSuggestionsAreDisplayed(activityTestRule, secondWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, firstWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, secondWebPage.url.toString())
verifySearchEngineSuggestionResults(
activityTestRule,
thirdWebPage.url.toString(),
@ -463,7 +442,7 @@ class HistoryTest {
}.clickSearchButton {
// Search for a valid term
typeSearch("generic")
verifyNoSuggestionsAreDisplayed(activityTestRule, thirdWebPage.url.toString())
verifySuggestionsAreNotDisplayed(activityTestRule, thirdWebPage.url.toString())
}
}
}

@ -57,8 +57,11 @@ class HomeScreenTest {
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/235396
@Test
fun homeScreenItemsTest() {
homeScreen {}.dismissOnboarding()
// Workaround to make sure the Pocket articles are populated before starting the test.
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.goBack {
verifyHomeWordmark()
verifyHomePrivateBrowsingButton()
verifyExistingTopSitesTabs("Wikipedia")
@ -80,7 +83,6 @@ class HomeScreenTest {
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/244199
@Test
fun privateBrowsingHomeScreenItemsTest() {
homeScreen { }.dismissOnboarding()
homeScreen { }.togglePrivateBrowsingMode()
homeScreen {

@ -67,6 +67,7 @@ class LoginsTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2092713
// Tests the Logins and passwords menu items and default values
@Test
fun loginsAndPasswordsSettingsItemsTest() {
@ -82,10 +83,11 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/517816
// Tests only for initial state without signing in.
// For tests after signing in, see SyncIntegration test suite
@Test
fun savedLoginsMenuItemsTest() {
fun verifySavedLoginsListTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -101,8 +103,9 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2092925
@Test
fun syncLoginsMenuItemsTest() {
fun verifySyncLoginsOptionsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -115,8 +118,12 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/523839
@Test
fun saveLoginsAndPasswordsOptionsItemsTest() {
fun saveLoginFromPromptTest() {
val saveLoginTest =
TestAssetHelper.getSaveLoginAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -124,12 +131,8 @@ class LoginsTest {
}.openSaveLoginsAndPasswordsOptions {
verifySaveLoginsOptionsView()
}
}
@Test
fun saveLoginFromPromptTest() {
val saveLoginTest =
TestAssetHelper.getSaveLoginAsset(mockWebServer)
exitMenu()
navigationToolbar {
}.enterURLAndEnterToBrowser(saveLoginTest.url) {
@ -152,8 +155,9 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/960412
@Test
fun openWebsiteForSavedLoginTest() {
fun openLoginWebsiteInBrowserTest() {
val loginPage = "https://mozilla-mobile.github.io/testapp/loginForm"
val originWebsite = "mozilla-mobile.github.io"
val userName = "test"
@ -179,6 +183,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/517817
@Test
fun neverSaveLoginFromPromptTest() {
val saveLoginTest = TestAssetHelper.getSaveLoginAsset(mockWebServer)
@ -206,9 +211,10 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1508171
@SmokeTest
@Test
fun updateSavedLoginTest() {
fun verifyUpdatedLoginIsSavedTest() {
val saveLoginTest =
TestAssetHelper.getSaveLoginAsset(mockWebServer)
@ -241,6 +247,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1049971
@SmokeTest
@Test
fun verifyMultipleLoginsSelectionsTest() {
@ -277,6 +284,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/875849
@Test
fun verifyEditLoginsViewTest() {
val loginPage = "https://mozilla-mobile.github.io/testapp/loginForm"
@ -305,6 +313,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/875851
@Test
fun verifyEditedLoginsAreSavedTest() {
val loginPage = "https://mozilla-mobile.github.io/testapp/v2.0/loginForm.html"
@ -342,6 +351,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2266452
@Test
fun verifyLoginWithNoUserNameCanNotBeSavedTest() {
val loginPage = "https://mozilla-mobile.github.io/testapp/loginForm"
@ -371,6 +381,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2266453
@Test
fun verifyLoginWithoutPasswordCanNotBeSavedTest() {
val loginPage = "https://mozilla-mobile.github.io/testapp/loginForm"
@ -401,6 +412,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/876531
@Test
fun verifyEditModeDismissalDoesNotSaveLoginCredentialsTest() {
val loginPage = "https://mozilla-mobile.github.io/testapp/loginForm"
@ -431,6 +443,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/876532
@Test
fun verifyDeleteLoginButtonTest() {
val loginPage = TestAssetHelper.getSaveLoginAsset(mockWebServer)
@ -461,6 +474,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/517818
@SmokeTest
@Test
fun verifyNeverSaveLoginOptionTest() {
@ -484,6 +498,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/517819
@Test
fun verifyAutofillToggleTest() {
val loginPage = "https://mozilla-mobile.github.io/testapp/v2.0/loginForm.html"
@ -524,9 +539,10 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/593768
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1812995")
@Test
fun verifyLoginIsNotUpdatedTest() {
fun doNotSaveOptionWillNotUpdateALoginTest() {
val loginPage = "https://mozilla-mobile.github.io/testapp/v2.0/loginForm.html"
val originWebsite = "mozilla-mobile.github.io"
@ -572,6 +588,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2090455
@Test
fun searchLoginsByUsernameTest() {
val firstLoginPage = TestAssetHelper.getSaveLoginAsset(mockWebServer)
@ -618,6 +635,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/608834
@Test
fun searchLoginsByUrlTest() {
val firstLoginPage = TestAssetHelper.getSaveLoginAsset(mockWebServer)
@ -664,6 +682,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2266441
@Test
fun verifyLastUsedLoginSortingOptionTest() {
val firstLoginPage = TestAssetHelper.getSaveLoginAsset(mockWebServer)
@ -710,6 +729,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2266442
@Test
fun verifyAlphabeticalLoginSortingOptionTest() {
val firstLoginPage = TestAssetHelper.getSaveLoginAsset(mockWebServer)
@ -754,6 +774,7 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1518435
@Test
fun verifyAddLoginManuallyTest() {
val loginPage = "https://mozilla-mobile.github.io/testapp/v2.0/loginForm.html"
@ -792,8 +813,9 @@ class LoginsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2068215
@Test
fun verifyCopyUsernameTest() {
fun verifyCopyLoginCredentialsToClipboardTest() {
val firstLoginPage = TestAssetHelper.getSaveLoginAsset(mockWebServer)
navigationToolbar {
@ -809,24 +831,6 @@ class LoginsTest {
viewSavedLoginDetails("test@example.com")
clickCopyUserNameButton()
verifySnackBarText("Username copied to clipboard")
}
}
@Test
fun verifyCopyPasswordTest() {
val firstLoginPage = TestAssetHelper.getSaveLoginAsset(mockWebServer)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstLoginPage.url) {
clickSubmitLoginButton()
verifySaveLoginPromptIsDisplayed()
clickPageObject(itemWithText("Save"))
}.openThreeDotMenu {
}.openSettings {
}.openLoginsAndPasswordSubMenu {
}.openSavedLogins {
tapSetupLater()
viewSavedLoginDetails("test@example.com")
clickCopyPasswordButton()
verifySnackBarText("Password copied to clipboard")
}

@ -4,6 +4,7 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import mozilla.components.concept.engine.utils.EngineReleaseChannel
@ -12,15 +13,20 @@ import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
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
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.longClickPageObject
import org.mozilla.fenix.ui.robots.navigationToolbar
class MainMenuTest {
@ -28,7 +34,7 @@ class MainMenuTest {
private lateinit var mockWebServer: MockWebServer
@get:Rule
val activityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides()
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
@Before
fun setUp() {
@ -44,9 +50,9 @@ class MainMenuTest {
mockWebServer.shutdown()
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/233849
@Test
fun verifyPageMainMenuItemsTest() {
fun verifyTabMainMenuItemsTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -57,109 +63,182 @@ class MainMenuTest {
}
}
// Verifies the list of items in the homescreen's 3 dot main menu
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/233848
@SmokeTest
@Test
fun openMainMenuNewTabItemTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
fun homeMainMenuItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.clickNewTabButton {
verifySearchView()
verifyHomeThreeDotMainMenuItems(isRequestDesktopSiteEnabled = false)
}.openBookmarks {
verifyBookmarksMenuView()
}.goBack {
}.openThreeDotMenu {
}.openHistory {
verifyHistoryMenuView()
}.goBack {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyEmptyDownloadsList()
}.goBack {
}.openThreeDotMenu {
}.openAddonsManagerMenu {
verifyAddonsListIsDisplayed(true)
}.goBack {
}.openThreeDotMenu {
}.openSyncSignIn {
verifyTurnOnSyncMenu()
}.goBack {}
homeScreen {
}.openThreeDotMenu {
}.openWhatsNew {
verifyWhatsNewURL()
}.goToHomescreen {
}.openThreeDotMenu {
}.openHelp {
verifyHelpUrl()
}.goToHomescreen {
}.openThreeDotMenu {
}.openCustomizeHome {
verifyHomePageView()
}.goBackToHomeScreen {
}.openThreeDotMenu {
}.openSettings {
verifySettingsView()
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2284134
@Test
fun openMainMenuBookmarksItemTest() {
fun openNewTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
}.openBookmarks {
verifyBookmarksMenuView()
}.clickNewTabButton {
verifySearchView()
}.submitQuery("test") {
verifyTabCounter("2")
}
}
// Device or AVD requires a Google Services Android OS installation with Play Store installed
// Verifies the Open in app button when an app is installed
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/387756
@SmokeTest
@Test
fun openMainMenuHistoryItemTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
fun openInAppFunctionalityTest() {
val youtubeURL = "vnd.youtube://".toUri()
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.enterURLAndEnterToBrowser(youtubeURL) {
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
}.clickOpenInApp {
assertYoutubeAppOpens()
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2284323
@Test
fun openMainMenuAddonsTest() {
fun openSyncAndSaveDataTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openAddonsManagerMenu {
TestHelper.registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(
activityTestRule.activity.findViewById(R.id.add_ons_list),
1,
),
) {
verifyAddonsItems()
}
}.openSyncSignIn {
verifyTurnOnSyncMenu()
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243840
@Test
fun openMainMenuSyncItemTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
fun findInPageTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 3)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openSyncSignIn {
verifyTurnOnSyncMenu()
verifyThreeDotMenuExists()
verifyFindInPageButton()
}.openFindInPage {
verifyFindInPageNextButton()
verifyFindInPagePrevButton()
verifyFindInPageCloseButton()
enterFindInPageQuery("a")
verifyFindNextInPageResult("1/3")
clickFindInPageNextButton()
verifyFindNextInPageResult("2/3")
clickFindInPageNextButton()
verifyFindNextInPageResult("3/3")
clickFindInPagePrevButton()
verifyFindPrevInPageResult("2/3")
clickFindInPagePrevButton()
verifyFindPrevInPageResult("1/3")
}.closeFindInPageWithCloseButton {
verifyFindInPageBar(false)
}.openThreeDotMenu {
}.openFindInPage {
enterFindInPageQuery("3")
verifyFindNextInPageResult("1/1")
}.closeFindInPageWithBackButton {
verifyFindInPageBar(false)
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2283303
@Test
fun openMainMenuFindInPageTest() {
fun switchDesktopSiteModeOnOffTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
}.openFindInPage {
verifyFindInPageSearchBarItems()
}.switchDesktopSiteMode {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(true)
}.switchDesktopSiteMode {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(false)
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1314137
@Test
fun mainMenuDesktopSiteTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
fun setDesktopSiteBeforePageLoadTest() {
val webPage = TestAssetHelper.getGenericAsset(mockWebServer, 4)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
homeScreen {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(false)
}.switchDesktopSiteMode {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(true)
}.closeBrowserMenuToBrowser {
clickPageObject(MatcherHelper.itemContainingText("Link 1"))
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(true)
}.closeBrowserMenuToBrowser {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
longClickPageObject(MatcherHelper.itemWithText("Link 2"))
clickContextMenuItem("Open link in new tab")
TestHelper.clickSnackbarButton("SWITCH")
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(false)
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2283302
@Test
fun mainMenuReportSiteIssueTest() {
fun reportSiteIssueTest() {
runWithCondition(
// This test will not run on RC builds because the "Report site issue button" is not available.
activityTestRule.activity.components.core.engine.version.releaseChannel !== EngineReleaseChannel.RELEASE,
@ -175,50 +254,77 @@ class MainMenuTest {
}
}
// Verifies the Add to home screen option in a tab's 3 dot menu
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/410724
@SmokeTest
@Test
fun openMainMenuAddToCollectionTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
fun addPageShortcutToHomeScreenTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val shortcutTitle = TestHelper.generateRandomString(5)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
}.openThreeDotMenu {
expandMenu()
}.openAddToHomeScreen {
clickCancelShortcutButton()
}
browserScreen {
}.openThreeDotMenu {
}.openSaveToCollection {
verifyCollectionNameTextField()
expandMenu()
}.openAddToHomeScreen {
verifyShortcutTextFieldTitle("Test_Page_1")
addShortcutName(shortcutTitle)
clickAddShortcutButton()
clickAddAutomaticallyButton()
}.openHomeScreenShortcut(shortcutTitle) {
verifyUrl(website.url.toString())
verifyTabCounter("1")
}
}
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/329893
@SmokeTest
@Test
fun openMainMenuSettingsItemTest() {
fun mainMenuShareButtonTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
}.openSettings {
verifySettingsView()
}.clickShareButton {
verifyShareTabLayout()
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/233604
@Test
fun mainMenuShareButtonTest() {
fun navigateBackAndForwardTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val nextWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(nextWebPage.url) {
verifyUrl(nextWebPage.url.toString())
}.openThreeDotMenu {
}.clickShareButton {
verifyShareTabLayout()
}.goToPreviousPage {
mDevice.waitForIdle()
verifyUrl(defaultWebPage.url.toString())
}.openThreeDotMenu {
}.goForward {
verifyUrl(nextWebPage.url.toString())
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2195819
@SmokeTest
@Test
fun mainMenuRefreshButtonTest() {
fun refreshPageButtonTest() {
val refreshWebPage = TestAssetHelper.getRefreshAsset(mockWebServer)
navigationToolbar {
@ -231,9 +337,9 @@ class MainMenuTest {
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2265657
@Test
fun mainMenuForceRefreshTest() {
fun forceRefreshPageTest() {
val refreshWebPage = TestAssetHelper.getRefreshAsset(mockWebServer)
navigationToolbar {

@ -15,10 +15,8 @@ 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.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import java.util.Locale
@ -54,51 +52,7 @@ class NavigationToolbarTest {
mockWebServer.shutdown()
}
@Test
fun goBackTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val nextWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(nextWebPage.url) {
verifyUrl(nextWebPage.url.toString())
}.openThreeDotMenu {
}.goToPreviousPage {
mDevice.waitForIdle()
verifyUrl(defaultWebPage.url.toString())
}
}
@Test
fun goForwardTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val nextWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(nextWebPage.url) {
mDevice.waitForIdle()
verifyUrl(nextWebPage.url.toString())
}.openThreeDotMenu {
}.goToPreviousPage {
mDevice.waitForIdle()
verifyUrl(defaultWebPage.url.toString())
}
// Re-open the three-dot menu for verification
navigationToolbar {
}.openThreeDotMenu {
verifyThreeDotMenuExists()
}.goForward {
verifyUrl(nextWebPage.url.toString())
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/987326
// Swipes the nav bar left/right to switch between tabs
@SmokeTest
@Test
@ -118,6 +72,7 @@ class NavigationToolbarTest {
}
}
// 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() {
@ -139,85 +94,7 @@ class NavigationToolbarTest {
}
}
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@Test
fun visitURLTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
verifyUrl(defaultWebPage.url.toString())
}
}
@Test
fun findInPageTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 3)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
verifyThreeDotMenuExists()
verifyFindInPageButton()
}.openFindInPage {
verifyFindInPageNextButton()
verifyFindInPagePrevButton()
verifyFindInPageCloseButton()
enterFindInPageQuery("a")
verifyFindNextInPageResult("1/3")
clickFindInPageNextButton()
verifyFindNextInPageResult("2/3")
clickFindInPageNextButton()
verifyFindNextInPageResult("3/3")
clickFindInPagePrevButton()
verifyFindPrevInPageResult("2/3")
clickFindInPagePrevButton()
verifyFindPrevInPageResult("1/3")
}.closeFindInPageWithCloseButton {
verifyFindInPageBar(false)
}.openThreeDotMenu {
}.openFindInPage {
enterFindInPageQuery("3")
verifyFindNextInPageResult("1/1")
}.closeFindInPageWithBackButton {
verifyFindInPageBar(false)
}
}
@Test
fun pdfFindInPageTest() {
val genericURL =
TestAssetHelper.getGenericAsset(mockWebServer, 3)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
clickPageObject(itemWithText("PDF form file"))
}.openThreeDotMenu {
verifyThreeDotMenuExists()
verifyFindInPageButton()
}.openFindInPage {
verifyFindInPageNextButton()
verifyFindInPagePrevButton()
verifyFindInPageCloseButton()
enterFindInPageQuery("l")
verifyFindNextInPageResult("1/2")
clickFindInPageNextButton()
verifyFindNextInPageResult("2/2")
clickFindInPagePrevButton()
verifyFindPrevInPageResult("1/2")
}.closeFindInPageWithCloseButton {
verifyFindInPageBar(false)
}.openThreeDotMenu {
}.openFindInPage {
enterFindInPageQuery("p")
verifyFindNextInPageResult("1/1")
}.closeFindInPageWithBackButton {
verifyFindInPageBar(false)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2265279
@SmokeTest
@Test
fun verifySecurePageSecuritySubMenuTest() {
@ -233,6 +110,7 @@ class NavigationToolbarTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2265280
@SmokeTest
@Test
fun verifyInsecurePageSecuritySubMenuTest() {
@ -248,6 +126,8 @@ class NavigationToolbarTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1661318
@SmokeTest
@Test
fun verifyClearCookiesFromQuickSettingsTest() {
val helpPageUrl = "mozilla.org"
@ -260,4 +140,36 @@ class NavigationToolbarTest {
verifyClearSiteDataPrompt(helpPageUrl)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1360555
@SmokeTest
@Test
fun goToHomeScreenTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
mDevice.waitForIdle()
}.goToHomescreen {
verifyHomeScreen()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2256552
@SmokeTest
@Test
fun goToHomeScreenInPrivateModeTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
togglePrivateBrowsingModeOnOff()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
mDevice.waitForIdle()
}.goToHomescreen {
verifyHomeScreen()
}
}
}

@ -22,7 +22,6 @@ import org.mozilla.fenix.helpers.Experimentation
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.ui.robots.homeScreen
class NimbusEventTest {
private lateinit var mDevice: UiDevice
@ -56,8 +55,6 @@ class NimbusEventTest {
@Test
fun homeScreenNimbusEventsTest() {
homeScreen { }.dismissOnboarding()
Experimentation.withHelper {
assertTrue(evalJexl("'app_opened'|eventSum('Days', 28, 0) > 0"))
}

@ -43,8 +43,6 @@ class NoNetworkAccessStartupTests {
activityTestRule.launchActivity(null)
homeScreen {
}.dismissOnboarding()
homeScreen {
verifyHomeScreen()
}

@ -4,6 +4,7 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
@ -15,10 +16,10 @@ import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_DOCS
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper
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
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.TestHelper.deleteDownloadedFileOnStorage
@ -28,6 +29,11 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
class PDFViewerTest {
private lateinit var mockWebServer: MockWebServer
private val downloadTestPage =
"https://storage.googleapis.com/mobile_test_assets/test_app/downloads.html"
private val pdfFileName = "washington.pdf"
private val pdfFileURL = "storage.googleapis.com/mobile_test_assets/public/washington.pdf"
private val pdfFileContent = "Washington Crossing the Delaware"
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
@ -50,7 +56,7 @@ class PDFViewerTest {
@Test
fun openPDFInBrowserTest() {
val genericURL =
TestAssetHelper.getGenericAsset(mockWebServer, 3)
getGenericAsset(mockWebServer, 3)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
@ -88,4 +94,55 @@ class PDFViewerTest {
}
deleteDownloadedFileOnStorage(downloadFile)
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2283305
@Test
fun pdfFindInPageTest() {
val genericURL = getGenericAsset(mockWebServer, 3)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
clickPageObject(MatcherHelper.itemWithText("PDF form file"))
}.openThreeDotMenu {
verifyThreeDotMenuExists()
verifyFindInPageButton()
}.openFindInPage {
verifyFindInPageNextButton()
verifyFindInPagePrevButton()
verifyFindInPageCloseButton()
enterFindInPageQuery("l")
verifyFindNextInPageResult("1/2")
clickFindInPageNextButton()
verifyFindNextInPageResult("2/2")
clickFindInPagePrevButton()
verifyFindPrevInPageResult("1/2")
}.closeFindInPageWithCloseButton {
verifyFindInPageBar(false)
}.openThreeDotMenu {
}.openFindInPage {
enterFindInPageQuery("p")
verifyFindNextInPageResult("1/1")
}.closeFindInPageWithBackButton {
verifyFindInPageBar(false)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2284297
@Test
fun addPDFToHomeScreenTest() {
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
clickPageObject(MatcherHelper.itemContainingText(pdfFileName))
verifyUrl(pdfFileURL)
verifyPageContent(pdfFileContent)
}.openThreeDotMenu {
expandMenu()
}.openAddToHomeScreen {
verifyShortcutTextFieldTitle(pdfFileName)
clickAddShortcutButton()
clickAddAutomaticallyButton()
}.openHomeScreenShortcut(pdfFileName) {
verifyUrl(pdfFileURL)
}
}
}

@ -30,6 +30,12 @@ class PocketTest {
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
// Workaround to make sure the Pocket articles are populated before starting the tests.
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.goBack {}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2252509
@ -40,9 +46,6 @@ class PocketTest {
it.isRecentlyVisitedFeatureEnabled = false
}
homeScreen {
}.dismissOnboarding()
homeScreen {
verifyThoughtProvokingStories(true)
scrollToPocketProvokingStories()
@ -70,9 +73,6 @@ class PocketTest {
it.isRecentlyVisitedFeatureEnabled = false
}
homeScreen {
}.dismissOnboarding()
homeScreen {
verifyThoughtProvokingStories(true)
scrollToPocketProvokingStories()
@ -90,9 +90,6 @@ class PocketTest {
it.isRecentlyVisitedFeatureEnabled = false
}
homeScreen {
}.dismissOnboarding()
homeScreen {
scrollToPocketProvokingStories()
verifyDiscoverMoreStoriesButton()
@ -109,9 +106,6 @@ class PocketTest {
it.isRecentlyVisitedFeatureEnabled = false
}
homeScreen {
}.dismissOnboarding()
homeScreen {
verifyStoriesByTopicItemState(activityTestRule, false, 1)
clickStoriesByTopicItem(activityTestRule, 1)
@ -127,9 +121,6 @@ class PocketTest {
it.isRecentlyVisitedFeatureEnabled = false
}
homeScreen {
}.dismissOnboarding()
homeScreen {
verifyPoweredByPocket()
}.clickPocketLearnMoreLink(activityTestRule) {

@ -16,6 +16,7 @@ import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.TestHelper.assertNativeAppOpens
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.ui.robots.addToHomeScreen
@ -58,7 +59,6 @@ class PwaTest {
}
}
@Ignore("Failing, see https://bugzilla.mozilla.org/show_bug.cgi?id=1807275")
@Test
fun emailLinkPWATest() {
navigationToolbar {
@ -71,7 +71,7 @@ class PwaTest {
}.openHomeScreenShortcut(shortcutTitle) {
clickPageObject(itemContainingText("Email link"))
clickPageObject(itemWithResIdAndText("android:id/button1", "OPEN"))
assertNativeAppOpens(GMAIL_APP, emailLink)
assertExternalAppOpens(GMAIL_APP)
}
}

@ -20,11 +20,13 @@ import org.junit.Rule
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.Constants.PackageName.ANDROID_SETTINGS
import org.mozilla.fenix.helpers.Constants.searchEngineCodes
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.MockBrowserDataHelper.createBookmarkItem
import org.mozilla.fenix.helpers.MockBrowserDataHelper.createHistoryItem
import org.mozilla.fenix.helpers.MockBrowserDataHelper.createTabItem
import org.mozilla.fenix.helpers.MockBrowserDataHelper.setCustomSearchEngine
@ -647,7 +649,7 @@ class SearchTest {
clickSearchSelectorButton()
selectTemporarySearchMethod(searchEngineName = "History")
typeSearch(searchTerm = "Mozilla")
verifyNoSuggestionsAreDisplayed(rule = activityTestRule, "Mozilla")
verifySuggestionsAreNotDisplayed(rule = activityTestRule, "Mozilla")
clickClearButton()
typeSearch(searchTerm = "generic")
verifyTypedToolbarText("generic")
@ -684,7 +686,7 @@ class SearchTest {
clickSearchSelectorButton()
selectTemporarySearchMethod(searchEngineName = "Tabs")
typeSearch(searchTerm = "Mozilla")
verifyNoSuggestionsAreDisplayed(rule = activityTestRule, "Mozilla")
verifySuggestionsAreNotDisplayed(rule = activityTestRule, "Mozilla")
clickClearButton()
typeSearch(searchTerm = "generic")
verifyTypedToolbarText("generic")
@ -705,4 +707,50 @@ class SearchTest {
}
}
}
@SmokeTest
@Test
fun searchHistoryNotRememberedInPrivateBrowsingTest() {
appContext.settings().shouldShowSearchSuggestionsInPrivate = true
val firstPageUrl = getGenericAsset(searchMockServer, 1)
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
createBookmarkItem(firstPageUrl.url.toString(), firstPageUrl.title, 1u)
homeScreen {
}.openNavigationToolbar {
}.clickUrlbar {
}.submitQuery("test page 1") {
}.goToHomescreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openNavigationToolbar {
}.clickUrlbar {
}.submitQuery("test page 2") {
}.openNavigationToolbar {
}.clickUrlbar {
typeSearch(searchTerm = "test page")
verifySearchEngineSuggestionResults(
rule = activityTestRule,
searchSuggestions = arrayOf(
"TestSearchEngine search",
"test page 1",
"Firefox Suggest",
firstPageUrl.url.toString(),
),
searchTerm = "test page 1",
)
// 2 search engine suggestions and 2 browser suggestions (1 history, 1 bookmark)
verifySearchSuggestionsCount(activityTestRule, numberOfSuggestions = 4, searchTerm = "test page")
verifySuggestionsAreNotDisplayed(
activityTestRule,
searchSuggestions = arrayOf(
"test page 2",
),
)
}
}
}

@ -49,23 +49,22 @@ class SettingsAboutTest {
mockWebServer.shutdown()
}
// Walks through settings menu and sub-menus to ensure all items are present
// Walks through the About settings menu to ensure all items are present
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2092700
@Test
fun settingsAboutItemsTest() {
// ABOUT
fun verifyAboutSettingsItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
// ABOUT
verifyAboutHeading()
verifyRateOnGooglePlay()
verifyAboutFirefoxPreview()
}
}
// ABOUT
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/246966
@Test
fun verifyRateOnGooglePlayRedirect() {
fun verifyRateOnGooglePlayButton() {
activityIntentTestRule.applySettingsExceptions {
it.isTCPCFREnabled = false
}
@ -81,8 +80,9 @@ class SettingsAboutTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/246961
@Test
fun verifyAboutFirefoxPreview() {
fun verifyAboutFirefoxMenuItems() {
activityIntentTestRule.applySettingsExceptions {
it.isJumpBackInCFREnabled = false
it.isTCPCFREnabled = false
@ -91,7 +91,7 @@ class SettingsAboutTest {
}.openThreeDotMenu {
}.openSettings {
}.openAboutFirefoxPreview {
verifyAboutFirefoxPreview()
verifyAboutFirefoxPreviewInfo()
}
}
}

@ -47,9 +47,10 @@ class SettingsAddonsTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/875780
// Walks through settings add-ons menu to ensure all items are present
@Test
fun settingsAddonsItemsTest() {
fun verifyAddonsListItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -64,9 +65,10 @@ class SettingsAddonsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/875781
// Installs an add-on from the Add-ons menu and verifies the prompts
@Test
fun installAddonTest() {
fun installAddonFromMainMenuTest() {
val addonName = "uBlock Origin"
homeScreen {}
@ -92,9 +94,10 @@ class SettingsAddonsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/561597
// Installs an addon, then uninstalls it
@Test
fun verifyAddonsCanBeUninstalled() {
fun verifyAddonsCanBeUninstalledTest() {
val addonName = "uBlock Origin"
addonsMenu {
@ -112,6 +115,7 @@ class SettingsAddonsTest {
}
}
// 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
@SmokeTest
@Test
@ -133,9 +137,10 @@ class SettingsAddonsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/561594
@SmokeTest
@Test
fun useAddonsInPrivateModeTest() {
fun verifyUBlockWorksInPrivateModeTest() {
val addonName = "uBlock Origin"
val genericPage = getGenericAsset(mockWebServer, 1)

@ -32,6 +32,11 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
class SettingsAdvancedTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
private val youTubeSchemaLink = itemContainingText("Youtube schema link")
private val youTubeFullLink = itemContainingText("Youtube full link")
private val playStoreLink = itemContainingText("Playstore link")
private val playStoreUrl = "play.google.com"
private val youTubePage = "vnd.youtube://".toUri()
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
@ -50,9 +55,10 @@ class SettingsAdvancedTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2092699
// Walks through settings menu and sub-menus to ensure all items are present
@Test
fun settingsAdvancedItemsTest() {
fun verifyAdvancedSettingsSectionItemsTest() {
// ADVANCED
homeScreen {
}.openThreeDotMenu {
@ -71,24 +77,12 @@ class SettingsAdvancedTest {
}
}
@SmokeTest
@Test
fun verifyOpenLinkInAppViewTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
verifyOpenLinksInAppsButton()
verifySettingsOptionSummary("Open links in apps", "Never")
}.openOpenLinksInAppsMenu {
verifyOpenLinksInAppsView("Never")
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2121046
// Assumes Youtube is installed and enabled
@SmokeTest
@Test
fun neverOpenLinkInAppTest() {
val defaultWebPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
val externalLinksPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
@ -102,17 +96,18 @@ class SettingsAdvancedTest {
exitMenu()
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
clickPageObject(itemContainingText("Youtube link"))
}.enterURLAndEnterToBrowser(externalLinksPage.url) {
clickPageObject(playStoreLink)
waitForPageToLoad()
verifyUrl("youtube.com")
verifyUrl(playStoreUrl)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2121052
// Assumes Youtube is installed and enabled
@Test
fun privateBrowsingNeverOpenLinkInAppTest() {
val defaultWebPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
val externalLinksPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
homeScreen {
}.togglePrivateBrowsingMode()
@ -129,18 +124,19 @@ class SettingsAdvancedTest {
exitMenu()
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
clickPageObject(itemContainingText("Youtube link"))
}.enterURLAndEnterToBrowser(externalLinksPage.url) {
clickPageObject(playStoreLink)
waitForPageToLoad()
verifyUrl("youtube.com")
verifyUrl(playStoreUrl)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2121045
// Assumes Youtube is installed and enabled
@SmokeTest
@Test
fun askBeforeOpeningLinkInAppCancelTest() {
val defaultWebPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
val externalLinksPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
@ -158,20 +154,21 @@ class SettingsAdvancedTest {
exitMenu()
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
clickPageObject(itemContainingText("Youtube link"))
}.enterURLAndEnterToBrowser(externalLinksPage.url) {
clickPageObject(youTubeFullLink)
verifyOpenLinkInAnotherAppPrompt()
clickPageObject(itemWithResIdAndText("android:id/button2", "CANCEL"))
waitForPageToLoad()
verifyUrl("youtube.com")
verifyUrl("youtube")
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2288347
// Assumes Youtube is installed and enabled
@SmokeTest
@Test
fun askBeforeOpeningLinkInAppOpenTest() {
val defaultWebPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
val externalLinksPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
@ -189,8 +186,8 @@ class SettingsAdvancedTest {
exitMenu()
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
clickPageObject(itemContainingText("Youtube link"))
}.enterURLAndEnterToBrowser(externalLinksPage.url) {
clickPageObject(youTubeSchemaLink)
verifyOpenLinkInAnotherAppPrompt()
clickPageObject(itemWithResIdAndText("android:id/button1", "OPEN"))
mDevice.waitForIdle()
@ -198,10 +195,11 @@ class SettingsAdvancedTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2121051
// Assumes Youtube is installed and enabled
@Test
fun privateBrowsingAskBeforeOpeningLinkInAppCancelTest() {
val defaultWebPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
val externalLinksPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
homeScreen {
}.togglePrivateBrowsingMode()
@ -222,19 +220,20 @@ class SettingsAdvancedTest {
exitMenu()
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
clickPageObject(itemContainingText("Youtube link"))
verifyPrivateBrowsingOpenLinkInAnotherAppPrompt("youtube.com")
}.enterURLAndEnterToBrowser(externalLinksPage.url) {
clickPageObject(youTubeFullLink)
verifyPrivateBrowsingOpenLinkInAnotherAppPrompt("youtube")
clickPageObject(itemWithResIdAndText("android:id/button2", "CANCEL"))
waitForPageToLoad()
verifyUrl("youtube.com")
verifyUrl("youtube")
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2288350
// Assumes Youtube is installed and enabled
@Test
fun privateBrowsingAskBeforeOpeningLinkInAppOpenTest() {
val defaultWebPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
val externalLinksPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
homeScreen {
}.togglePrivateBrowsingMode()
@ -255,19 +254,20 @@ class SettingsAdvancedTest {
exitMenu()
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
clickPageObject(itemContainingText("Youtube link"))
verifyPrivateBrowsingOpenLinkInAnotherAppPrompt("youtube.com")
}.enterURLAndEnterToBrowser(externalLinksPage.url) {
clickPageObject(youTubeSchemaLink)
verifyPrivateBrowsingOpenLinkInAnotherAppPrompt("youtube")
clickPageObject(itemWithResIdAndText("android:id/button1", "OPEN"))
mDevice.waitForIdle()
assertYoutubeAppOpens()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1058618
// Assumes Youtube is installed and enabled
@Test
fun alwaysOpenLinkInAppTest() {
val defaultWebPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
val externalLinksPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
@ -285,22 +285,22 @@ class SettingsAdvancedTest {
exitMenu()
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
clickPageObject(itemContainingText("Youtube link"))
}.enterURLAndEnterToBrowser(externalLinksPage.url) {
clickPageObject(youTubeSchemaLink)
mDevice.waitForIdle()
assertYoutubeAppOpens()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1058617
@Test
fun dismissOpenLinksInAppCFRTest() {
activityIntentTestRule.applySettingsExceptions {
it.isOpenInAppBannerEnabled = true
}
val defaultWebPage = "https://m.youtube.com/"
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.toUri()) {
}.enterURLAndEnterToBrowser(youTubePage) {
waitForPageToLoad()
verifyOpenLinksInAppsCFRExists(true)
clickOpenLinksInAppsDismissCFRButton()
@ -308,15 +308,15 @@ class SettingsAdvancedTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2288331
@Test
fun goToSettingsFromOpenLinksInAppCFRTest() {
activityIntentTestRule.applySettingsExceptions {
it.isOpenInAppBannerEnabled = true
}
val defaultWebPage = "https://m.youtube.com/"
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.toUri()) {
}.enterURLAndEnterToBrowser(youTubePage) {
waitForPageToLoad()
verifyOpenLinksInAppsCFRExists(true)
}.clickOpenLinksInAppsGoToSettingsCFRButton {

@ -49,8 +49,9 @@ class SettingsCustomizeTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/344212
@Test
fun changeThemeSettingTest() {
fun changeThemeOfTheAppTest() {
// Goes through the settings and changes the default search engine, then verifies it changes.
homeScreen {
}.openThreeDotMenu {
@ -64,6 +65,7 @@ class SettingsCustomizeTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/466571
@Test
fun setToolbarPositionTest() {
homeScreen {
@ -88,8 +90,9 @@ class SettingsCustomizeTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1058682
@Test
fun swipeToolbarGesturePreferenceOffTest() {
fun turnOffSwipeToSwitchTabsPreferenceTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
@ -114,6 +117,7 @@ class SettingsCustomizeTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1992289
@Test
fun pullToRefreshPreferenceTest() {
homeScreen {

@ -60,8 +60,9 @@ class SettingsDeleteBrowsingDataOnQuitTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416048
@Test
fun deleteBrowsingDataOnQuitSettingsItemsTest() {
fun deleteBrowsingDataOnQuitSettingTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -88,6 +89,7 @@ class SettingsDeleteBrowsingDataOnQuitTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416049
@Test
fun deleteOpenTabsOnQuitTest() {
val testPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -112,8 +114,9 @@ class SettingsDeleteBrowsingDataOnQuitTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416050
@Test
fun deleteHistoryOnQuitTest() {
fun deleteBrowsingHistoryOnQuitTest() {
val genericPage =
getStorageTestAsset(mockWebServer, "generic1.html")
@ -140,6 +143,7 @@ class SettingsDeleteBrowsingDataOnQuitTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416051
@Test
fun deleteCookiesAndSiteDataOnQuitTest() {
val storageWritePage =
@ -174,6 +178,7 @@ class SettingsDeleteBrowsingDataOnQuitTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1243096
@SmokeTest
@Test
fun deleteDownloadsOnQuitTest() {
@ -191,7 +196,7 @@ class SettingsDeleteBrowsingDataOnQuitTest {
}.clickDownloadLink("smallZip.zip") {
verifyDownloadPrompt("smallZip.zip")
}.clickDownload {
verifyDownloadNotificationPopup()
verifyDownloadCompleteNotificationPopup()
}.closeCompletedDownloadPrompt {
}.goToHomescreen {
}.openThreeDotMenu {
@ -207,6 +212,7 @@ class SettingsDeleteBrowsingDataOnQuitTest {
deleteDownloadedFileOnStorage("smallZip.zip")
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416053
@SmokeTest
@Test
fun deleteSitePermissionsOnQuitTest() {
@ -242,6 +248,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)

@ -7,6 +7,7 @@ package org.mozilla.fenix.ui
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.R
@ -51,6 +52,7 @@ class SettingsDeleteBrowsingDataTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/937561
@Test
fun deleteBrowsingDataOptionStatesTest() {
homeScreen {
@ -109,8 +111,9 @@ class SettingsDeleteBrowsingDataTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/517811
@Test
fun deleteTabsDataWithNoOpenTabsTest() {
fun deleteOpenTabsBrowsingDataWithNoOpenTabsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -126,9 +129,10 @@ class SettingsDeleteBrowsingDataTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/353531
@SmokeTest
@Test
fun deleteTabsDataTest() {
fun deleteOpenTabsBrowsingDataTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -158,6 +162,7 @@ class SettingsDeleteBrowsingDataTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/378864
@SmokeTest
@Test
fun deleteBrowsingHistoryTest() {
@ -188,6 +193,7 @@ class SettingsDeleteBrowsingDataTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416041
@SmokeTest
@Test
fun deleteCookiesAndSiteDataTest() {
@ -226,6 +232,8 @@ class SettingsDeleteBrowsingDataTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416042
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1807268")
@SmokeTest
@Test
fun deleteCachedFilesTest() {

@ -53,8 +53,9 @@ class SettingsGeneralTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2092697
@Test
fun settingsGeneralItemsTests() {
fun verifyGeneralSettingsItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -76,9 +77,10 @@ class SettingsGeneralTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/344213
@SmokeTest
@Test
fun changeAccessibiltySettings() {
fun verifyFontSizingChangeTest() {
// Goes through the settings and changes the default text on a webpage, then verifies if the text has changed.
val fenixApp = activityIntentTestRule.activity.applicationContext as FenixApplication
val webpage = getLoremIpsumAsset(mockWebServer).url
@ -107,9 +109,10 @@ class SettingsGeneralTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/516079
@SmokeTest
@Test
fun switchLanguageTest() {
fun setAppLanguageDifferentThanSystemLanguageTest() {
val enLanguageHeaderText = getStringResource(R.string.preferences_language)
homeScreen {
@ -132,6 +135,7 @@ class SettingsGeneralTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/516080
@Test
fun searchInLanguagesListTest() {
val systemLocaleDefault = getStringResource(R.string.default_locale_text)
@ -153,10 +157,11 @@ class SettingsGeneralTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/516078
// Because it requires changing system prefs, this test will run only on Debug builds
@Ignore("Failing due to app translation bug, see: https://github.com/mozilla-mobile/fenix/issues/26729")
@Test
fun frenchSystemLocaleTest() {
fun verifyFollowDeviceLanguageTest() {
val frenchLocale = Locale("fr", "FR")
runWithSystemLocaleChanged(frenchLocale, activityIntentTestRule) {
@ -172,47 +177,18 @@ class SettingsGeneralTest {
}
}
@SmokeTest
@Test
fun verifyHomepageOptionSummaryUpdatesTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
verifySettingsOptionSummary("Homepage", "Open on homepage after four hours")
}.openHomepageSubMenu {
verifySelectedOpeningScreenOption("Homepage after four hours of inactivity")
clickOpeningScreenOption("Homepage")
verifySelectedOpeningScreenOption("Homepage")
}.goBack {
verifySettingsOptionSummary("Homepage", "Open on homepage")
}.openHomepageSubMenu {
clickOpeningScreenOption("Last tab")
verifySelectedOpeningScreenOption("Last tab")
}.goBack {
verifySettingsOptionSummary("Homepage", "Open on last tab")
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1360557
@Test
fun tabsSettingsMenuItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
verifyTabsButton()
verifySettingsOptionSummary("Tabs", "Close manually")
}.openTabsSubMenu {
verifyTabViewOptions()
verifyCloseTabsOptions()
verifyMoveOldTabsToInactiveOptions()
}
}
@Test
fun verifyTabsOptionSummaryUpdatesTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
verifyTabsButton()
verifySettingsOptionSummary("Tabs", "Close manually")
}.openTabsSubMenu {
verifySelectedCloseTabsOption("Never")
clickClosedTabsOption("After one day")
verifySelectedCloseTabsOption("After one day")
@ -230,4 +206,21 @@ class SettingsGeneralTest {
verifySettingsOptionSummary("Tabs", "Close after one month")
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243583
// For API>23
// Verifies the default browser switch opens the system default apps menu.
@SmokeTest
@Test
fun changeDefaultBrowserSetting() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
verifyDefaultBrowserToggle(false)
clickDefaultBrowserSwitch()
verifyAndroidDefaultAppsMenuAppears()
}
// Dismiss the request
mDevice.pressBack()
}
}

@ -32,6 +32,7 @@ class SettingsHTTPSOnlyModeTest {
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1724825
@Test
fun httpsOnlyModeMenuItemsTest() {
homeScreen {
@ -58,6 +59,7 @@ class SettingsHTTPSOnlyModeTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1724827
@SmokeTest
@Test
fun httpsOnlyModeEnabledInNormalBrowsingTest() {
@ -93,8 +95,9 @@ class SettingsHTTPSOnlyModeTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2091057
@Test
fun httpsOnlyModeExceptionPersistsForCurrentSession() {
fun httpsOnlyModeExceptionPersistsForCurrentSessionTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -120,6 +123,7 @@ class SettingsHTTPSOnlyModeTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1724828
@Test
fun httpsOnlyModeEnabledOnlyInPrivateBrowsingTest() {
homeScreen {
@ -159,6 +163,7 @@ class SettingsHTTPSOnlyModeTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2091058
@Test
fun turnOffHttpsOnlyModeTest() {
homeScreen {

@ -49,6 +49,7 @@ class SettingsHomepageTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1564843
@Test
fun verifyHomepageSettingsTest() {
homeScreen {
@ -59,6 +60,7 @@ class SettingsHomepageTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1564859
@Test
fun verifyShortcutOptionTest() {
// en-US defaults
@ -90,6 +92,7 @@ class SettingsHomepageTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1565003
@Test
fun verifyRecentlyVisitedOptionTest() {
activityIntentTestRule.applySettingsExceptions {
@ -109,26 +112,7 @@ class SettingsHomepageTest {
}
}
@Test
fun verifyPocketOptionTest() {
activityIntentTestRule.applySettingsExceptions {
it.isRecentTabsFeatureEnabled = false
it.isRecentlyVisitedFeatureEnabled = false
}
val genericURL = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.goToHomescreen {
verifyPocketSectionIsDisplayed()
}.openThreeDotMenu {
}.openCustomizeHome {
clickPocketButton()
}.goBackToHomeScreen {
verifyPocketSectionIsNotDisplayed()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1564999
@SmokeTest
@Test
fun jumpBackInOptionTest() {
@ -146,6 +130,7 @@ class SettingsHomepageTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1565000
@SmokeTest
@Test
fun recentBookmarksOptionTest() {
@ -165,48 +150,47 @@ class SettingsHomepageTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1569831
@SmokeTest
@Test
fun startOnHomepageTest() {
fun verifyOpeningScreenOptionsTest() {
val genericURL = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openThreeDotMenu {
}.openSettings {
verifySettingsOptionSummary("Homepage", "Open on homepage after four hours")
}.openHomepageSubMenu {
verifySelectedOpeningScreenOption("Homepage after four hours of inactivity")
clickOpeningScreenOption("Homepage")
verifySelectedOpeningScreenOption("Homepage")
}
restartApp(activityIntentTestRule)
homeScreen {
verifyHomeScreen()
}
}
@SmokeTest
@Test
fun startOnLastTabTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
}.goToHomescreen {
}.openThreeDotMenu {
}.openCustomizeHome {
}.openSettings {
verifySettingsOptionSummary("Homepage", "Open on homepage")
}.openHomepageSubMenu {
clickOpeningScreenOption("Last tab")
verifySelectedOpeningScreenOption("Last tab")
}.goBack {
verifySettingsOptionSummary("Homepage", "Open on last tab")
}
restartApp(activityIntentTestRule)
browserScreen {
verifyUrl(firstWebPage.url.toString())
verifyUrl(genericURL.url.toString())
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1569843
@Test
fun ignoreStartOnHomeWhenLaunchedByExternalLinkTest() {
fun verifyOpeningScreenAfterLaunchingExternalLinkTest() {
val genericPage = getGenericAsset(mockWebServer, 1)
homeScreen {
@ -230,9 +214,10 @@ class SettingsHomepageTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1676359
@Ignore("Intermittent test: https://github.com/mozilla-mobile/fenix/issues/26559")
@Test
fun setWallpaperTest() {
fun verifyWallpaperChangeTest() {
val wallpapers = listOf(
"Wallpaper Item: amethyst",
"Wallpaper Item: cerulean",

@ -44,6 +44,7 @@ class SettingsPrivacyTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2092698
@Test
fun settingsPrivacyItemsTest() {
homeScreen {
@ -68,8 +69,9 @@ class SettingsPrivacyTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243362
@Test
fun verifyDataCollectionTest() {
fun verifyDataCollectionSettingsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -79,44 +81,14 @@ class SettingsPrivacyTest {
true,
"On",
)
}
}
@Test
fun verifyUsageAndTechnicalDataToggleTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSettingsSubMenuDataCollection {
verifyUsageAndTechnicalDataToggle(true)
clickUsageAndTechnicalDataToggle()
verifyUsageAndTechnicalDataToggle(false)
}
}
@Test
fun verifyMarketingDataToggleTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSettingsSubMenuDataCollection {
verifyMarketingDataToggle(true)
clickUsageAndTechnicalDataToggle()
verifyUsageAndTechnicalDataToggle(true)
clickMarketingDataToggle()
verifyMarketingDataToggle(false)
}
}
@Test
fun verifyStudiesToggleTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSettingsSubMenuDataCollection {
verifyDataCollectionView(
true,
true,
"On",
)
clickMarketingDataToggle()
verifyMarketingDataToggle(true)
clickStudiesOption()
verifyStudiesToggle(true)
clickStudiesToggle()
@ -126,26 +98,7 @@ class SettingsPrivacyTest {
}
}
@Test
fun sitePermissionsItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSettingsSubMenuSitePermissions {
verifySitePermissionsToolbarTitle()
verifyToolbarGoBackButton()
verifySitePermissionOption("Autoplay", "Block audio only")
verifySitePermissionOption("Camera", "Blocked by Android")
verifySitePermissionOption("Location", "Blocked by Android")
verifySitePermissionOption("Microphone", "Blocked by Android")
verifySitePermissionOption("Notification", "Ask to allow")
verifySitePermissionOption("Persistent Storage", "Ask to allow")
verifySitePermissionOption("Cross-site cookies", "Ask to allow")
verifySitePermissionOption("DRM-controlled content", "Ask to allow")
verifySitePermissionOption("Exceptions")
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1024594
@Test
fun verifyNotificationsSettingsTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)

@ -39,6 +39,7 @@ class SettingsPrivateBrowsingTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/555822
@Test
fun verifyPrivateBrowsingMenuItemsTest() {
homeScreen {
@ -145,8 +146,9 @@ class SettingsPrivateBrowsingTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/414583
@Test
fun addPrivateBrowsingShortcut() {
fun addPrivateBrowsingShortcutFromSettingsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {

@ -160,7 +160,7 @@ class SettingsSearchTest {
homeScreen {
}.openSearch {
typeSearch("test")
verifyNoSuggestionsAreDisplayed(
verifySuggestionsAreNotDisplayed(
activityTestRule,
"Firefox Suggest",
websiteURL,
@ -188,7 +188,7 @@ class SettingsSearchTest {
homeScreen {
}.openSearch {
typeSearch("test")
verifyNoSuggestionsAreDisplayed(
verifySuggestionsAreNotDisplayed(
activityTestRule,
"Firefox Suggest",
website.title,
@ -426,7 +426,7 @@ class SettingsSearchTest {
}.goBack {
}.openSearch {
typeSearch("mozilla")
verifyNoSuggestionsAreDisplayed(activityTestRule, "mozilla firefox")
verifySuggestionsAreNotDisplayed(activityTestRule, "mozilla firefox")
}
}
@ -439,7 +439,7 @@ class SettingsSearchTest {
typeSearch("mozilla")
verifyAllowSuggestionsInPrivateModeDialog()
denySuggestionsInPrivateMode()
verifyNoSuggestionsAreDisplayed(activityTestRule, "mozilla firefox")
verifySuggestionsAreNotDisplayed(activityTestRule, "mozilla firefox")
}
}
@ -466,7 +466,7 @@ class SettingsSearchTest {
}.goBack {
}.openSearch {
typeSearch("mozilla")
verifyNoSuggestionsAreDisplayed(activityTestRule, "mozilla firefox")
verifySuggestionsAreNotDisplayed(activityTestRule, "mozilla firefox")
}
}

@ -69,11 +69,33 @@ class SettingsSitePermissionsTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/246974
@Test
fun sitePermissionsItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSettingsSubMenuSitePermissions {
verifySitePermissionsToolbarTitle()
verifyToolbarGoBackButton()
verifySitePermissionOption("Autoplay", "Block audio only")
verifySitePermissionOption("Camera", "Blocked by Android")
verifySitePermissionOption("Location", "Blocked by Android")
verifySitePermissionOption("Microphone", "Blocked by Android")
verifySitePermissionOption("Notification", "Ask to allow")
verifySitePermissionOption("Persistent Storage", "Ask to allow")
verifySitePermissionOption("Cross-site cookies", "Ask to allow")
verifySitePermissionOption("DRM-controlled content", "Ask to allow")
verifySitePermissionOption("Exceptions")
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/247680
// Verifies that you can go to System settings and change app's permissions from inside the app
@SmokeTest
@Test
@SdkSuppress(minSdkVersion = 29)
fun redirectToAppPermissionsSystemSettingsTest() {
fun systemBlockedPermissionsRedirectToSystemAppSettingsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -108,9 +130,10 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2095125
@SmokeTest
@Test
fun verifyAutoplayBlockAudioOnlySettingTest() {
fun verifyAutoplayBlockAudioOnlySettingOnNotMutedVideoTest() {
val genericPage = getGenericAsset(mockWebServer, 1)
val videoTestPage = getVideoPageAsset(mockWebServer)
@ -146,6 +169,7 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2286807
@Ignore("Failing, see https://bugzilla.mozilla.org/show_bug.cgi?id=1827599")
@SmokeTest
@Test
@ -173,8 +197,9 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2095124
@Test
fun verifyAutoplayAllowAudioVideoSettingTest() {
fun verifyAutoplayAllowAudioVideoSettingOnNotMutedVideoTestTest() {
val genericPage = getGenericAsset(mockWebServer, 1)
val videoTestPage = getVideoPageAsset(mockWebServer)
@ -208,6 +233,7 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2286806
@Ignore("Failing, see https://bugzilla.mozilla.org/show_bug.cgi?id=1827599")
@Test
fun verifyAutoplayAllowAudioVideoSettingOnMutedVideoTest() {
@ -235,8 +261,9 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2095126
@Test
fun verifyAutoplayBlockAudioAndVideoSettingTest() {
fun verifyAutoplayBlockAudioAndVideoSettingOnNotMutedVideoTest() {
val videoTestPage = getVideoPageAsset(mockWebServer)
homeScreen {
@ -265,6 +292,7 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2286808
@Test
fun verifyAutoplayBlockAudioAndVideoSettingOnMutedVideoTest() {
val mutedVideoTestPage = getMutedVideoPageAsset(mockWebServer)
@ -294,6 +322,7 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/247362
@Test
fun verifyCameraPermissionSettingsTest() {
navigationToolbar {
@ -319,6 +348,7 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/247364
@Test
fun verifyMicrophonePermissionSettingsTest() {
navigationToolbar {
@ -344,6 +374,7 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/247363
@Test
fun verifyLocationPermissionSettingsTest() {
navigationToolbar {
@ -368,6 +399,7 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/247365
@Test
fun verifyNotificationsPermissionSettingsTest() {
navigationToolbar {
@ -392,6 +424,7 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1923415
@Test
fun verifyPersistentStoragePermissionSettingsTest() {
navigationToolbar {
@ -416,6 +449,7 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1923417
@Ignore("Flaky, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1829889")
@Test
fun verifyDRMControlledContentPermissionSettingsTest() {
@ -454,6 +488,7 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/246976
@SmokeTest
@Test
fun clearAllSitePermissionsExceptionsTest() {
@ -476,8 +511,9 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/247007
@Test
fun clearOneSiteAllPermissionsExceptionsTest() {
fun addAndClearOneWebPagePermission() {
navigationToolbar {
}.enterURLAndEnterToBrowser(permissionsTestPage.toUri()) {
}.clickOpenNotificationButton {
@ -498,8 +534,9 @@ class SettingsSitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/326477
@Test
fun clearOneSiteOnePermissionExceptionTest() {
fun clearIndividuallyAWebPagePermission() {
navigationToolbar {
}.enterURLAndEnterToBrowser(permissionsTestPage.toUri()) {
}.clickOpenNotificationButton {

@ -1,380 +1,236 @@
/* 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.ui
import android.view.View
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.core.net.toUri
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.uiautomator.UiDevice
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.mediasession.MediaSession
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.IntentReceiverActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
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.assertYoutubeAppOpens
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.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
/**
* Test Suite that contains a part of the Smoke and Sanity tests defined in TestRail:
* https://testrail.stage.mozaws.net/index.php?/suites/view/3192
* Other smoke tests have been marked with the @SmokeTest annotation throughout the ui package in order to limit this class expansion.
* These tests will verify different functionalities of the app as a way to quickly detect regressions in main areas
*/
@Suppress("ForbiddenComment")
@SmokeTest
class SmokeTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
private lateinit var browserStore: BrowserStore
@get:Rule(order = 0)
val activityTestRule = AndroidComposeTestRule(
HomeActivityIntentTestRule.withDefaultSettingsOverrides(),
{ it.activity },
)
@get: Rule(order = 1)
val intentReceiverActivityTestRule = ActivityTestRule(
IntentReceiverActivity::class.java,
true,
false,
)
@Rule(order = 2)
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
// Initializing this as part of class construction, below the rule would throw a NPE
// So we are initializing this here instead of in all related tests.
browserStore = activityTestRule.activity.components.core.store
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// Device or AVD requires a Google Services Android OS installation with Play Store installed
// Verifies the Open in app button when an app is installed
@Test
fun mainMenuOpenInAppTest() {
val youtubeURL = "vnd.youtube://".toUri()
navigationToolbar {
}.enterURLAndEnterToBrowser(youtubeURL) {
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.clickOpenInApp {
assertYoutubeAppOpens()
}
}
// Verifies that deleting a Bookmarks folder also removes the item from inside it.
@Test
fun deleteNonEmptyBookmarkFolderTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
createBookmark(website.url)
}.openThreeDotMenu {
}.openBookmarks {
verifyBookmarkTitle("Test_Page_1")
createFolder("My Folder")
verifyFolderTitle("My Folder")
}.openThreeDotMenu("Test_Page_1") {
}.clickEdit {
clickParentFolderSelector()
selectFolder("My Folder")
navigateUp()
saveEditBookmark()
createFolder("My Folder 2")
verifyFolderTitle("My Folder 2")
}.openThreeDotMenu("My Folder 2") {
}.clickEdit {
clickParentFolderSelector()
selectFolder("My Folder")
navigateUp()
saveEditBookmark()
}.openThreeDotMenu("My Folder") {
}.clickDelete {
cancelFolderDeletion()
verifyFolderTitle("My Folder")
}.openThreeDotMenu("My Folder") {
}.clickDelete {
confirmDeletion()
verifyDeleteSnackBarText()
verifyBookmarkIsDeleted("My Folder")
verifyBookmarkIsDeleted("My Folder 2")
verifyBookmarkIsDeleted("Test_Page_1")
navigateUp()
}
browserScreen {
}.openThreeDotMenu {
verifyAddBookmarkButton()
}
}
@Test
fun shareTabsFromTabsTrayTest() {
val firstWebsite = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebsite = TestAssetHelper.getGenericAsset(mockWebServer, 2)
val firstWebsiteTitle = firstWebsite.title
val secondWebsiteTitle = secondWebsite.title
val sharingApp = "Gmail"
val sharedUrlsString = "${firstWebsite.url}\n\n${secondWebsite.url}"
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(firstWebsite.url) {
verifyPageContent(firstWebsite.content)
}.openTabDrawer {
}.openNewTab {
}.submitQuery(secondWebsite.url.toString()) {
verifyPageContent(secondWebsite.content)
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
verifyExistingOpenTabs("Test_Page_2")
}.openTabsListThreeDotMenu {
verifyShareAllTabsButton()
}.clickShareAllTabsButton {
verifyShareTabsOverlay(firstWebsiteTitle, secondWebsiteTitle)
verifySharingWithSelectedApp(
sharingApp,
sharedUrlsString,
"$firstWebsiteTitle, $secondWebsiteTitle",
)
}
}
@Test
fun privateTabsTrayWithOpenedTabTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
}.openTabDrawer {
verifyNormalBrowsingButtonIsSelected(false)
verifyPrivateBrowsingButtonIsSelected(true)
verifySyncedTabsButtonIsSelected(false)
verifyTabTrayOverflowMenu(true)
verifyTabsTrayCounter()
verifyExistingTabList()
verifyExistingOpenTabs(website.title)
verifyCloseTabsButton(website.title)
verifyOpenedTabThumbnail()
verifyPrivateBrowsingNewTabButton()
}
}
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@Test
fun noHistoryInPrivateBrowsingTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openHistory {
verifyEmptyHistoryView()
}
}
@Test
fun mainMenuInstallPWATest() {
val pwaPage = "https://mozilla-mobile.github.io/testapp/"
navigationToolbar {
}.enterURLAndEnterToBrowser(pwaPage.toUri()) {
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.clickInstall {
clickAddAutomaticallyButton()
}.openHomeScreenShortcut("TEST_APP") {
mDevice.waitForIdle()
verifyNavURLBarHidden()
}
}
// Verifies that reader mode is detected and the custom appearance controls are displayed
@Test
fun verifyReaderViewAppearanceUI() {
val readerViewPage =
TestAssetHelper.getLoremIpsumAsset(mockWebServer)
val estimatedReadingTime = "1 - 2 minutes"
navigationToolbar {
}.enterURLAndEnterToBrowser(readerViewPage.url) {
mDevice.waitForIdle()
}
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE,
),
) {}
navigationToolbar {
verifyReaderViewDetected(true)
toggleReaderView()
}
browserScreen {
waitForPageToLoad()
verifyPageContent(estimatedReadingTime)
}.openThreeDotMenu {
verifyReaderViewAppearance(true)
}.openReaderViewAppearance {
verifyAppearanceFontGroup(true)
verifyAppearanceFontSansSerif(true)
verifyAppearanceFontSerif(true)
verifyAppearanceFontIncrease(true)
verifyAppearanceFontDecrease(true)
verifyAppearanceColorGroup(true)
verifyAppearanceColorDark(true)
verifyAppearanceColorLight(true)
verifyAppearanceColorSepia(true)
}
}
@Test
fun tabMediaControlButtonTest() {
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
navigationToolbar {
}.enterURLAndEnterToBrowser(audioTestPage.url) {
mDevice.waitForIdle()
clickPageObject(itemWithText("Play"))
assertPlaybackState(browserStore, MediaSession.PlaybackState.PLAYING)
}.openTabDrawer {
verifyTabMediaControlButtonState("Pause")
clickTabMediaControlButton("Pause")
verifyTabMediaControlButtonState("Play")
}.openTab(audioTestPage.title) {
assertPlaybackState(browserStore, MediaSession.PlaybackState.PAUSED)
}
}
// For API>23
// Verifies the default browser switch opens the system default apps menu.
@Test
fun changeDefaultBrowserSetting() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
verifyDefaultBrowserToggle(false)
clickDefaultBrowserSwitch()
verifyAndroidDefaultAppsMenuAppears()
}
// Dismiss the request
mDevice.pressBack()
}
@Test
fun goToHomeScreenBottomToolbarTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
mDevice.waitForIdle()
}.goToHomescreen {
verifyHomeScreen()
}
}
@Test
fun goToHomeScreenTopToolbarTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openCustomizeSubMenu {
clickTopToolbarToggle()
}.goBack {
}.goBack {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
mDevice.waitForIdle()
}.goToHomescreen {
verifyHomeScreen()
}
}
@Test
fun goToHomeScreenBottomToolbarPrivateModeTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
togglePrivateBrowsingModeOnOff()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
mDevice.waitForIdle()
}.goToHomescreen {
verifyHomeScreen()
}
}
@Test
fun goToHomeScreenTopToolbarPrivateModeTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
togglePrivateBrowsingModeOnOff()
}.openThreeDotMenu {
}.openSettings {
}.openCustomizeSubMenu {
clickTopToolbarToggle()
}.goBack {
}.goBack {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
mDevice.waitForIdle()
}.goToHomescreen {
verifyHomeScreen()
}
}
}
/* 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.ui
import android.view.View
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.core.net.toUri
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.uiautomator.UiDevice
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.mediasession.MediaSession
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.IntentReceiverActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
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.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.ViewVisibilityIdlingResource
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
/**
* Test Suite that contains a part of the Smoke and Sanity tests defined in TestRail:
* https://testrail.stage.mozaws.net/index.php?/suites/view/3192
* Other smoke tests have been marked with the @SmokeTest annotation throughout the ui package in order to limit this class expansion.
* These tests will verify different functionalities of the app as a way to quickly detect regressions in main areas
*/
@Suppress("ForbiddenComment")
@SmokeTest
class SmokeTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
private lateinit var browserStore: BrowserStore
@get:Rule(order = 0)
val activityTestRule = AndroidComposeTestRule(
HomeActivityIntentTestRule.withDefaultSettingsOverrides(),
{ it.activity },
)
@get: Rule(order = 1)
val intentReceiverActivityTestRule = ActivityTestRule(
IntentReceiverActivity::class.java,
true,
false,
)
@Rule(order = 2)
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
// Initializing this as part of class construction, below the rule would throw a NPE
// So we are initializing this here instead of in all related tests.
browserStore = activityTestRule.activity.components.core.store
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
@Test
fun shareTabsFromTabsTrayTest() {
val firstWebsite = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebsite = TestAssetHelper.getGenericAsset(mockWebServer, 2)
val firstWebsiteTitle = firstWebsite.title
val secondWebsiteTitle = secondWebsite.title
val sharingApp = "Gmail"
val sharedUrlsString = "${firstWebsite.url}\n\n${secondWebsite.url}"
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(firstWebsite.url) {
verifyPageContent(firstWebsite.content)
}.openTabDrawer {
}.openNewTab {
}.submitQuery(secondWebsite.url.toString()) {
verifyPageContent(secondWebsite.content)
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
verifyExistingOpenTabs("Test_Page_2")
}.openTabsListThreeDotMenu {
verifyShareAllTabsButton()
}.clickShareAllTabsButton {
verifyShareTabsOverlay(firstWebsiteTitle, secondWebsiteTitle)
verifySharingWithSelectedApp(
sharingApp,
sharedUrlsString,
"$firstWebsiteTitle, $secondWebsiteTitle",
)
}
}
@Test
fun privateTabsTrayWithOpenedTabTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
}.openTabDrawer {
verifyNormalBrowsingButtonIsSelected(false)
verifyPrivateBrowsingButtonIsSelected(true)
verifySyncedTabsButtonIsSelected(false)
verifyTabTrayOverflowMenu(true)
verifyTabsTrayCounter()
verifyExistingTabList()
verifyExistingOpenTabs(website.title)
verifyCloseTabsButton(website.title)
verifyOpenedTabThumbnail()
verifyPrivateBrowsingNewTabButton()
}
}
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@Test
fun noHistoryInPrivateBrowsingTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openHistory {
verifyEmptyHistoryView()
}
}
@Test
fun mainMenuInstallPWATest() {
val pwaPage = "https://mozilla-mobile.github.io/testapp/"
navigationToolbar {
}.enterURLAndEnterToBrowser(pwaPage.toUri()) {
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.clickInstall {
clickAddAutomaticallyButton()
}.openHomeScreenShortcut("TEST_APP") {
mDevice.waitForIdle()
verifyNavURLBarHidden()
}
}
// Verifies that reader mode is detected and the custom appearance controls are displayed
@Test
fun verifyReaderViewAppearanceUI() {
val readerViewPage =
TestAssetHelper.getLoremIpsumAsset(mockWebServer)
val estimatedReadingTime = "1 - 2 minutes"
navigationToolbar {
}.enterURLAndEnterToBrowser(readerViewPage.url) {
mDevice.waitForIdle()
}
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE,
),
) {}
navigationToolbar {
verifyReaderViewDetected(true)
toggleReaderView()
}
browserScreen {
waitForPageToLoad()
verifyPageContent(estimatedReadingTime)
}.openThreeDotMenu {
verifyReaderViewAppearance(true)
}.openReaderViewAppearance {
verifyAppearanceFontGroup(true)
verifyAppearanceFontSansSerif(true)
verifyAppearanceFontSerif(true)
verifyAppearanceFontIncrease(true)
verifyAppearanceFontDecrease(true)
verifyAppearanceColorGroup(true)
verifyAppearanceColorDark(true)
verifyAppearanceColorLight(true)
verifyAppearanceColorSepia(true)
}
}
@Test
fun tabMediaControlButtonTest() {
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
navigationToolbar {
}.enterURLAndEnterToBrowser(audioTestPage.url) {
mDevice.waitForIdle()
clickPageObject(itemWithText("Play"))
assertPlaybackState(browserStore, MediaSession.PlaybackState.PLAYING)
}.openTabDrawer {
verifyTabMediaControlButtonState("Pause")
clickTabMediaControlButton("Pause")
verifyTabMediaControlButtonState("Play")
}.openTab(audioTestPage.title) {
assertPlaybackState(browserStore, MediaSession.PlaybackState.PAUSED)
}
}
}

@ -49,6 +49,7 @@ class SponsoredShortcutsTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1729331
// Expected for en-us defaults
@SmokeTest
@Test
@ -67,6 +68,7 @@ class SponsoredShortcutsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1729338
@Test
fun openSponsoredShortcutTest() {
homeScreen {
@ -76,8 +78,9 @@ class SponsoredShortcutsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1729334
@Test
fun openSponsoredShortcutInPrivateBrowsingTest() {
fun openSponsoredShortcutInPrivateTabTest() {
homeScreen {
sponsoredShortcutTitle = getSponsoredShortcutTitle(2)
}.openContextMenuOnSponsoredShortcut(sponsoredShortcutTitle) {
@ -86,9 +89,10 @@ class SponsoredShortcutsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1729335
@Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/25926")
@Test
fun verifySponsorsAndPrivacyLinkTest() {
fun openSponsorsAndYourPrivacyOptionTest() {
homeScreen {
sponsoredShortcutTitle = getSponsoredShortcutTitle(2)
}.openContextMenuOnSponsoredShortcut(sponsoredShortcutTitle) {
@ -97,9 +101,10 @@ class SponsoredShortcutsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1729336
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1807268")
@Test
fun verifySponsoredShortcutsSettingsOptionTest() {
fun openSponsoredShortcutsSettingsOptionTest() {
homeScreen {
sponsoredShortcutTitle = getSponsoredShortcutTitle(2)
}.openContextMenuOnSponsoredShortcut(sponsoredShortcutTitle) {
@ -108,6 +113,7 @@ class SponsoredShortcutsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1729337
@Test
fun verifySponsoredShortcutsDetailsTest() {
homeScreen {
@ -119,6 +125,7 @@ class SponsoredShortcutsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1729328
// 1 sponsored shortcut should be displayed if there are 7 pinned top sites
@Test
fun verifySponsoredShortcutsListWithSevenPinnedSitesTest() {
@ -169,6 +176,7 @@ class SponsoredShortcutsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1729329
// No sponsored shortcuts should be displayed if there are 8 pinned top sites
@Test
fun verifySponsoredShortcutsListWithEightPinnedSitesTest() {

@ -1,203 +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 okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.ui.robots.clickContextMenuItem
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.longClickPageObject
/**
* Tests for verifying the main three dot menu options
*
*/
class ThreeDotMenuMainTest {
private lateinit var mockWebServer: MockWebServer
@get:Rule
val activityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides()
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// Verifies the list of items in the homescreen's 3 dot main menu
@Test
fun homeThreeDotMenuItemsTest() {
homeScreen {
}.openThreeDotMenu {
verifyHomeThreeDotMainMenuItems(isRequestDesktopSiteEnabled = false)
}.openBookmarks {
verifyBookmarksMenuView()
}.goBack {
}.openThreeDotMenu {
}.openHistory {
verifyHistoryMenuView()
}.goBack {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyEmptyDownloadsList()
}.goBack {
}.openThreeDotMenu {
}.openAddonsManagerMenu {
verifyAddonsItems()
}.goBack {
}.openThreeDotMenu {
}.openSyncSignIn {
verifyTurnOnSyncMenu()
}.goBack {
// Desktop toggle
}.openThreeDotMenu {
}.switchDesktopSiteMode {
}
homeScreen {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(isRequestDesktopSiteEnabled = true)
}.openWhatsNew {
verifyWhatsNewURL()
}.goToHomescreen {
}.openThreeDotMenu {
}.openHelp {
verifyHelpUrl()
}.goToHomescreen {
}.openThreeDotMenu {
}.openCustomizeHome {
verifyHomePageView()
}.goBackToHomeScreen {
}.openThreeDotMenu {
}.openSettings {
verifySettingsView()
}
}
// Verifies the list of items in the homescreen's 3 dot main menu in private browsing
@Test
fun privateHomeThreeDotMenuItemsTest() {
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openThreeDotMenu {
verifyHomeThreeDotMainMenuItems(isRequestDesktopSiteEnabled = false)
}.openBookmarks {
verifyBookmarksMenuView()
}.goBack {
}.openThreeDotMenu {
}.openHistory {
verifyHistoryMenuView()
}.goBack {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyEmptyDownloadsList()
}.goBack {
}.openThreeDotMenu {
}.openAddonsManagerMenu {
verifyAddonsItems()
}.goBack {
}.openThreeDotMenu {
}.openSyncSignIn {
verifyTurnOnSyncMenu()
}.goBack {
// Desktop toggle
}.openThreeDotMenu {
}.switchDesktopSiteMode {
}
homeScreen {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(isRequestDesktopSiteEnabled = true)
}.openWhatsNew {
verifyWhatsNewURL()
}.goToHomescreen {
}.openThreeDotMenu {
}.openHelp {
verifyHelpUrl()
}.goToHomescreen {
}.openThreeDotMenu {
}.openCustomizeHome {
verifyHomePageView()
}.goBackToHomeScreen {
}.openThreeDotMenu {
}.openSettings {
verifySettingsView()
}
}
@Test
fun setDesktopSiteBeforePageLoadTest() {
val webPage = TestAssetHelper.getGenericAsset(mockWebServer, 4)
homeScreen {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(false)
}.switchDesktopSiteMode {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(true)
}.closeBrowserMenuToBrowser {
clickPageObject(itemContainingText("Link 1"))
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(true)
}.closeBrowserMenuToBrowser {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
longClickPageObject(itemWithText("Link 2"))
clickContextMenuItem("Open link in new tab")
clickSnackbarButton("SWITCH")
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(false)
}
}
@Test
fun privateBrowsingSetDesktopSiteBeforePageLoadTest() {
val webPage = TestAssetHelper.getGenericAsset(mockWebServer, 4)
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(false)
}.switchDesktopSiteMode {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(true)
}.closeBrowserMenuToBrowser {
clickPageObject(itemContainingText("Link 1"))
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(true)
}.closeBrowserMenuToBrowser {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
longClickPageObject(itemWithText("Link 2"))
clickContextMenuItem("Open link in private tab")
clickSnackbarButton("SWITCH")
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(false)
}
}
}

@ -16,7 +16,6 @@ import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.Constants.defaultTopSitesList
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.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.generateRandomString
@ -42,9 +41,6 @@ class TopSitesTest {
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@get:Rule
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@ -218,8 +214,6 @@ class TopSitesTest {
// Expected for en-us defaults
@Test
fun verifyDefaultTopSitesList() {
homeScreen { }.dismissOnboarding()
homeScreen {
verifyExistingTopSitesList()
defaultTopSitesList.values.forEach { value ->

@ -4,19 +4,16 @@
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.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithDescription
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.navigationToolbar
/**
@ -24,17 +21,16 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* Note: This involves setting the feature flags On for CFRs which are disabled elsewhere.
*
*/
class ContextualHintsTest {
class TotalCookieProtectionTest {
private lateinit var mockWebServer: MockWebServer
@get:Rule
val activityTestRule = HomeActivityTestRule(
isJumpBackInCFREnabled = true,
isTCPCFREnabled = true,
isPocketEnabled = false,
isRecentlyVisitedFeatureEnabled = false,
isCookieBannerReductionDialogEnabled = false,
)
val composeTestRule = AndroidComposeTestRule(
HomeActivityTestRule(
isTCPCFREnabled = true,
isCookieBannerReductionDialogEnabled = false,
),
) { it.activity }
@Before
fun setUp() {
@ -49,27 +45,33 @@ class ContextualHintsTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2260552
@Test
fun openTotalCookieProtectionLearnMoreLinkTest() {
val genericPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericPage.url) {
verifyCookiesProtectionHintIsDisplayed(true)
clickPageObject(itemContainingText(getStringResource(R.string.tcp_cfr_learn_more)))
}.enterURLAndEnterToBrowserForTCPCFR(genericPage.url) {
waitForPageToLoad()
verifyCookiesProtectionHintIsDisplayed(composeTestRule, true)
clickTCPCFRLearnMore(composeTestRule)
verifyUrl("support.mozilla.org/en-US/kb/enhanced-tracking-protection-firefox-android")
verifyShouldShowCFRTCP(false, composeTestRule.activity.settings())
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1913589
@Test
fun dismissTotalCookieProtectionHintTest() {
val genericPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericPage.url) {
verifyCookiesProtectionHintIsDisplayed(true)
clickPageObject(itemWithDescription(getStringResource(R.string.mozac_cfr_dismiss_button_content_description)))
verifyCookiesProtectionHintIsDisplayed(false)
}.enterURLAndEnterToBrowserForTCPCFR(genericPage.url) {
waitForPageToLoad()
verifyCookiesProtectionHintIsDisplayed(composeTestRule, true)
dismissTCPCFRPopup(composeTestRule)
verifyCookiesProtectionHintIsDisplayed(composeTestRule, false)
verifyShouldShowCFRTCP(false, composeTestRule.activity.settings())
}
}
}

@ -5,23 +5,21 @@
package org.mozilla.fenix.ui.robots
import android.os.Build
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.ComposeTestRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
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.R
import org.mozilla.fenix.helpers.MatcherHelper.assertItemContainingTextExists
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.click
import java.util.regex.Pattern
/**
@ -29,11 +27,14 @@ import java.util.regex.Pattern
*/
class AddToHomeScreenRobot {
fun verifyAddPrivateBrowsingShortcutButton() = assertAddPrivateBrowsingShortcutButton()
fun verifyAddPrivateBrowsingShortcutButton(composeTestRule: ComposeTestRule) =
composeTestRule.onNodeWithTag("private.add").assertIsDisplayed()
fun verifyNoThanksPrivateBrowsingShortcutButton() = assertNoThanksPrivateBrowsingShortcutButton()
fun verifyNoThanksPrivateBrowsingShortcutButton(composeTestRule: ComposeTestRule) =
composeTestRule.onNodeWithTag("private.cancel").assertIsDisplayed()
fun clickAddPrivateBrowsingShortcutButton() = addPrivateBrowsingShortcutButton().click()
fun clickAddPrivateBrowsingShortcutButton(composeTestRule: ComposeTestRule) =
composeTestRule.onNodeWithTag("private.add").performClick()
fun addShortcutName(title: String) = shortcutTextField.setText(title)
@ -104,16 +105,6 @@ fun addToHomeScreen(interact: AddToHomeScreenRobot.() -> Unit): AddToHomeScreenR
private fun addAutomaticallyButton() =
mDevice.findObject(UiSelector().textContains("add automatically"))
private fun addPrivateBrowsingShortcutButton() = onView(withId(R.id.cfr_pos_button))
private fun assertAddPrivateBrowsingShortcutButton() = addPrivateBrowsingShortcutButton()
.check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
private fun noThanksPrivateBrowsingShortcutButton() = onView(withId(R.id.cfr_neg_button))
private fun assertNoThanksPrivateBrowsingShortcutButton() = noThanksPrivateBrowsingShortcutButton()
.check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
private val cancelAddToHomeScreenButton =
itemWithResId("$packageName:id/cancel_button")
private val confirmAddToHomeScreenButton =

@ -188,6 +188,13 @@ class BookmarksRobot {
addFolderButton().click()
}
fun clickAddNewFolderButtonFromSelectFolderView() =
itemWithResId("$packageName:id/add_folder_button")
.also {
it.waitForExists(waitingTime)
it.click()
}
fun addNewFolderName(name: String) {
addFolderTitleField()
.click()

@ -11,7 +11,9 @@ import android.net.Uri
import android.os.SystemClock
import android.util.Log
import android.widget.TimePicker
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.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
@ -41,7 +43,6 @@ import org.mozilla.fenix.helpers.Constants.LONG_CLICK_DURATION
import org.mozilla.fenix.helpers.Constants.RETRY_COUNT
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.itemContainingText
@ -60,6 +61,7 @@ import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.waitForObjects
import org.mozilla.fenix.helpers.ext.waitNotNull
import org.mozilla.fenix.tabstray.TabsTrayTestTag
import org.mozilla.fenix.utils.Settings
import java.time.LocalDate
class BrowserRobot {
@ -190,11 +192,11 @@ class BrowserRobot {
)
}
fun verifyContextMenuForLinksToOtherApps(containsURL: Uri) {
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(
contextMenuLinkUrl(containsURL.toString()),
contextMenuLinkUrl(containsURL),
contextMenuOpenLinkInNewTab,
contextMenuOpenLinkInPrivateTab,
contextMenuCopyLink,
@ -249,15 +251,6 @@ class BrowserRobot {
fun verifyMenuButton() = threeDotButton().check(matches(isDisplayed()))
fun verifyNavURLBarItems() {
navURLBar().waitForExists(waitingTime)
verifyMenuButton()
verifyTabCounter("1")
verifySearchBar()
verifySecureConnectionLockIcon()
verifyHomeScreenButton()
}
fun verifyNoLinkImageContextMenuItems(containsURL: Uri) {
mDevice.waitNotNull(Until.findObject(By.textContains(containsURL.toString())))
mDevice.waitNotNull(
@ -590,16 +583,32 @@ class BrowserRobot {
}
}
fun verifyCookiesProtectionHintIsDisplayed(isDisplayed: Boolean) {
assertItemContainingTextExists(
totalCookieProtectionHintMessage,
totalCookieProtectionHintLearnMoreLink,
exists = isDisplayed,
)
assertItemWithDescriptionExists(
totalCookieProtectionHintCloseButton,
exists = isDisplayed,
)
fun verifyCookiesProtectionHintIsDisplayed(composeTestRule: HomeActivityComposeTestRule, isDisplayed: Boolean) {
if (isDisplayed) {
composeTestRule.onNodeWithTag("tcp_cfr.message").assertIsDisplayed()
composeTestRule.onNodeWithTag("tcp_cfr.action").assertIsDisplayed()
composeTestRule.onNodeWithTag("cfr.dismiss").assertIsDisplayed()
} else {
composeTestRule.onNodeWithTag("tcp_cfr.message").assertDoesNotExist()
composeTestRule.onNodeWithTag("tcp_cfr.action").assertDoesNotExist()
composeTestRule.onNodeWithTag("cfr.dismiss").assertDoesNotExist()
}
}
fun clickTCPCFRLearnMore(composeTestRule: HomeActivityComposeTestRule) {
composeTestRule.onNodeWithTag("tcp_cfr.action").performClick()
}
fun dismissTCPCFRPopup(composeTestRule: HomeActivityComposeTestRule) {
composeTestRule.onNodeWithTag("cfr.dismiss").performClick()
}
fun verifyShouldShowCFRTCP(shouldShow: Boolean, settings: Settings) {
if (shouldShow) {
assertTrue(settings.shouldShowTotalCookieProtectionCFR)
} else {
assertFalse(settings.shouldShowTotalCookieProtectionCFR)
}
}
fun selectTime(hour: Int, minute: Int) =
@ -873,6 +882,17 @@ class BrowserRobot {
assertTrue(button.waitForExists(waitingTime))
}
fun verifySurveyNoThanksButton() {
val button = mDevice.findObject(
UiSelector().text(
getStringResource(
R.string.preferences_not_take_survey,
),
),
)
assertTrue(button.waitForExists(waitingTime))
}
fun clickOpenLinksInAppsDismissCFRButton() =
itemWithResIdContainingText(
"$packageName:id/dismiss",
@ -891,6 +911,18 @@ class BrowserRobot {
button.click()
}
fun clickNoThanksSurveyButton() {
val button = mDevice.findObject(
UiSelector().text(
getStringResource(
R.string.preferences_not_take_survey,
),
),
)
button.waitForExists(waitingTime)
button.click()
}
fun longClickToolbar() = mDevice.findObject(By.res("$packageName:id/mozac_browser_toolbar_url_view")).click(LONG_CLICK_DURATION)
fun verifyDownloadPromptIsDismissed() =
@ -1066,6 +1098,21 @@ class BrowserRobot {
return HomeScreenRobot.Transition()
}
fun goToHomescreenWithComposeTopSites(composeTestRule: HomeActivityComposeTestRule, interact: ComposeTopSitesRobot.() -> Unit): ComposeTopSitesRobot.Transition {
clickPageObject(itemWithDescription("Home screen"))
mDevice.findObject(UiSelector().resourceId("$packageName:id/homeLayout"))
.waitForExists(waitingTime) ||
mDevice.findObject(
UiSelector().text(
getStringResource(R.string.onboarding_home_screen_jump_back_contextual_hint_2),
),
).waitForExists(waitingTime)
ComposeTopSitesRobot(composeTestRule).interact()
return ComposeTopSitesRobot.Transition(composeTestRule)
}
fun goBack(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
mDevice.pressBack()
@ -1211,6 +1258,14 @@ class BrowserRobot {
BrowserRobot().interact()
return Transition()
}
fun clickNoThanksSurveyButton(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
surveyNoThanksButton.waitForExists(waitingTime)
surveyNoThanksButton.click()
BrowserRobot().interact()
return Transition()
}
}
}
@ -1331,12 +1386,6 @@ private val currentDay = currentDate.dayOfMonth
private val currentMonth = currentDate.month
private val currentYear = currentDate.year
private val cookieBanner = itemWithResId("startsiden-gdpr-disclaimer")
private val totalCookieProtectionHintMessage =
itemContainingText(getStringResource(R.string.tcp_cfr_message))
private val totalCookieProtectionHintLearnMoreLink =
itemContainingText(getStringResource(R.string.tcp_cfr_learn_more))
private val totalCookieProtectionHintCloseButton =
itemWithDescription(getStringResource(R.string.mozac_cfr_dismiss_button_content_description))
// Context menu items
// Link URL
@ -1369,3 +1418,6 @@ private val contextMenuOpenInExternalApp =
private val surveyButton =
itemContainingText(getStringResource(R.string.preferences_take_survey))
private val surveyNoThanksButton =
itemContainingText(getStringResource(R.string.preferences_not_take_survey))

@ -14,6 +14,7 @@ import androidx.compose.ui.test.assertIsNotSelected
import androidx.compose.ui.test.assertIsSelected
import androidx.compose.ui.test.filter
import androidx.compose.ui.test.hasAnyChild
import androidx.compose.ui.test.hasContentDescription
import androidx.compose.ui.test.hasParent
import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.hasText
@ -272,7 +273,9 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest
/**
* Verifies a tab's media button matches [action] when there is only one tab with media.
*/
@OptIn(ExperimentalTestApi::class)
fun verifyTabMediaControlButtonState(action: String) {
composeTestRule.waitUntilAtLeastOneExists(hasContentDescription(action), waitingTime)
composeTestRule.tabMediaControlButton(action)
.assertExists()
}
@ -280,7 +283,9 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest
/**
* Clicks a tab's media button when there is only one tab with media.
*/
@OptIn(ExperimentalTestApi::class)
fun clickTabMediaControlButton(action: String) {
composeTestRule.waitUntilAtLeastOneExists(hasContentDescription(action), waitingTime)
composeTestRule.tabMediaControlButton(action)
.performClick()
}

@ -0,0 +1,164 @@
/* 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.robots
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.filter
import androidx.compose.ui.test.hasAnyChild
import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.ComposeTestRule
import androidx.compose.ui.test.longClick
import androidx.compose.ui.test.onAllNodesWithTag
import androidx.compose.ui.test.onFirst
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
import androidx.compose.ui.test.performTouchInput
import org.mozilla.fenix.helpers.HomeActivityComposeTestRule
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.packageName
import org.mozilla.fenix.home.topsites.TopSitesTestTag
/**
* Implementation of Robot Pattern for the Compose Top Sites.
*/
class ComposeTopSitesRobot(private val composeTestRule: HomeActivityComposeTestRule) {
fun verifyExistingTopSitesList() =
composeTestRule.onNodeWithTag(TopSitesTestTag.topSites).assertExists()
@OptIn(ExperimentalTestApi::class)
fun verifyExistingTopSiteItem(vararg titles: String) {
titles.forEach { title ->
composeTestRule.waitUntilAtLeastOneExists(hasText(title), waitingTime)
composeTestRule.topSiteItem(title).assertExists()
}
}
fun verifyNotExistingTopSiteItem(vararg titles: String) {
titles.forEach { title ->
itemContainingText(title).waitForExists(waitingTime)
composeTestRule.topSiteItem(title).assertDoesNotExist()
}
}
fun verifyTopSiteContextMenuItems() {
verifyTopSiteContextMenuOpenInPrivateTabButton()
verifyTopSiteContextMenuRemoveButton()
verifyTopSiteContextMenuRenameButton()
}
fun verifyTopSiteContextMenuOpenInPrivateTabButton() {
composeTestRule.contextMenuItemOpenInPrivateTab().assertExists()
}
fun verifyTopSiteContextMenuRenameButton() {
composeTestRule.contextMenuItemRename().assertExists()
}
fun verifyTopSiteContextMenuRemoveButton() {
composeTestRule.contextMenuItemRemove().assertExists()
}
class Transition(private val composeTestRule: HomeActivityComposeTestRule) {
fun openTopSiteTabWithTitle(
title: String,
interact: BrowserRobot.() -> Unit,
): BrowserRobot.Transition {
composeTestRule.topSiteItem(title).performScrollTo().performClick()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun openTopSiteInPrivate(
interact: BrowserRobot.() -> Unit,
): BrowserRobot.Transition {
composeTestRule.contextMenuItemOpenInPrivateTab().performClick()
composeTestRule.waitForIdle()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun openContextMenuOnTopSitesWithTitle(
title: String,
interact: ComposeTopSitesRobot.() -> Unit,
): Transition {
composeTestRule.topSiteItem(title).performScrollTo().performTouchInput {
longClick()
}
ComposeTopSitesRobot(composeTestRule).interact()
return Transition(composeTestRule)
}
fun renameTopSite(
title: String,
interact: ComposeTopSitesRobot.() -> Unit,
): Transition {
composeTestRule.contextMenuItemRename().performClick()
itemWithResId("$packageName:id/top_site_title")
.also {
it.waitForExists(waitingTimeShort)
it.setText(title)
}
itemWithResIdContainingText("android:id/button1", "OK").click()
ComposeTopSitesRobot(composeTestRule).interact()
return Transition(composeTestRule)
}
@OptIn(ExperimentalTestApi::class)
fun removeTopSite(
interact: ComposeTopSitesRobot.() -> Unit,
): Transition {
composeTestRule.contextMenuItemRemove().performClick()
composeTestRule.waitUntilDoesNotExist(hasTestTag(TopSitesTestTag.remove), waitingTime)
ComposeTopSitesRobot(composeTestRule).interact()
return Transition(composeTestRule)
}
@OptIn(ExperimentalTestApi::class)
fun deleteTopSiteFromHistory(
interact: BrowserRobot.() -> Unit,
): BrowserRobot.Transition {
composeTestRule.contextMenuItemRemove().performClick()
composeTestRule.waitUntilDoesNotExist(hasTestTag(TopSitesTestTag.remove), waitingTime)
BrowserRobot().interact()
return BrowserRobot.Transition()
}
}
}
/**
* Obtains the top site with the provided [title].
*/
private fun ComposeTestRule.topSiteItem(title: String) =
onAllNodesWithTag(TopSitesTestTag.topSiteItemRoot).filter(hasAnyChild(hasText(title))).onFirst()
/**
* Obtains the option to open in private tab the top site
*/
private fun ComposeTestRule.contextMenuItemOpenInPrivateTab() =
onAllNodesWithTag(TopSitesTestTag.openInPrivateTab).onFirst()
/**
* Obtains the option to rename the top site
*/
private fun ComposeTestRule.contextMenuItemRename() = onAllNodesWithTag(TopSitesTestTag.rename).onFirst()
/**
* Obtains the option to remove the top site
*/
private fun ComposeTestRule.contextMenuItemRemove() = onAllNodesWithTag(TopSitesTestTag.remove).onFirst()

@ -167,13 +167,6 @@ class CustomTabRobot {
ShareOverlayRobot().interact()
return ShareOverlayRobot.Transition()
}
fun goBackToOnboardingScreen(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
mDevice.pressBack()
HomeScreenRobot().interact()
return HomeScreenRobot.Transition()
}
}
}

@ -29,6 +29,7 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_APPS_PHOTOS
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
@ -48,7 +49,58 @@ class DownloadRobot {
fun verifyDownloadPrompt(fileName: String) = assertDownloadPrompt(fileName)
fun verifyDownloadNotificationPopup() = assertDownloadNotificationPopup()
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 verifyDownloadFailedPrompt(fileName: String) {
assertTrue(
itemWithResId("$packageName:id/download_dialog_icon")
.waitForExists(waitingTime),
)
assertTrue(
"Download dialog title not displayed",
itemWithResIdAndText(
"$packageName:id/download_dialog_title",
"Download failed",
).waitForExists(waitingTime),
)
assertTrue(
"Download file name not displayed",
itemWithResIdContainingText(
"$packageName:id/download_dialog_filename",
fileName,
).waitForExists(waitingTime),
)
assertTrue(
"Try again button not displayed",
itemWithResIdAndText(
"$packageName:id/download_dialog_action_button",
"Try Again",
).waitForExists(waitingTime),
)
}
fun clickTryAgainButton() {
itemWithResIdAndText(
"$packageName:id/download_dialog_action_button",
"Try Again",
).click()
}
fun verifyPhotosAppOpens() = assertExternalAppOpens(GOOGLE_APPS_PHOTOS)
@ -126,13 +178,6 @@ class DownloadRobot {
return BrowserRobot.Transition()
}
fun closePrompt(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
closePromptButton().click()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun closeDownloadPrompt(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
itemWithResId("$packageName:id/download_dialog_close_button").click()
@ -216,24 +261,6 @@ private fun assertDownloadPrompt(fileName: String) {
}
}
private fun assertDownloadNotificationPopup() {
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),
)
}
private fun closeCompletedDownloadButton() =
onView(withId(R.id.download_dialog_close_button))

@ -82,6 +82,9 @@ class HistoryRobot {
deleteButton(item).click()
}
fun verifyDeleteHistoryItemButton(historyItemTitle: String) =
deleteButton(historyItemTitle).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
fun clickDeleteAllHistoryButton() = deleteButton().click()
fun selectEverythingOption() = deleteHistoryEverythingOption().click()

@ -494,10 +494,6 @@ class HomeScreenRobot {
return SearchRobot.Transition()
}
fun dismissOnboarding() {
openThreeDotMenu { }.openSettings { }.goBack { }
}
fun clickUpgradingUserOnboardingSignInButton(
testRule: ComposeTestRule,
interact: SyncSignInRobot.() -> Unit,
@ -785,6 +781,11 @@ fun homeScreen(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition
return HomeScreenRobot.Transition()
}
fun homeScreenWithComposeTopSites(composeTestRule: HomeActivityComposeTestRule, interact: ComposeTopSitesRobot.() -> Unit): ComposeTopSitesRobot.Transition {
ComposeTopSitesRobot(composeTestRule).interact()
return ComposeTopSitesRobot.Transition(composeTestRule)
}
private fun homeScreenList() =
UiScrollable(
UiSelector()

@ -191,6 +191,19 @@ class NavigationToolbarRobot {
return BrowserRobot.Transition()
}
fun enterURLAndEnterToBrowserForTCPCFR(
url: Uri,
interact: BrowserRobot.() -> Unit,
): BrowserRobot.Transition {
openEditURLView()
awesomeBar().setText(url.toString())
mDevice.pressEnter()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun openTabCrashReporter(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
val crashUrl = "about:crashcontent"

@ -165,6 +165,11 @@ class NotificationRobot {
}
}
fun clickNotification(notificationMessage: String) {
mDevice.findObject(UiSelector().text(notificationMessage)).waitForExists(waitingTime)
mDevice.findObject(UiSelector().text(notificationMessage)).click()
}
class Transition {
fun clickClosePrivateTabsNotification(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {

@ -6,7 +6,11 @@
package org.mozilla.fenix.ui.robots
import androidx.compose.ui.test.ComposeTimeoutException
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.assertAny
import androidx.compose.ui.test.assertCountEquals
import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.ComposeTestRule
import androidx.compose.ui.test.onAllNodesWithTag
@ -117,7 +121,7 @@ class SearchRobot {
}
}
fun verifyNoSuggestionsAreDisplayed(rule: ComposeTestRule, vararg searchSuggestions: String) {
fun verifySuggestionsAreNotDisplayed(rule: ComposeTestRule, vararg searchSuggestions: String) {
rule.waitForIdle()
for (searchSuggestion in searchSuggestions) {
rule.onAllNodesWithTag("mozac.awesomebar.suggestions")
@ -128,6 +132,28 @@ class SearchRobot {
}
}
@OptIn(ExperimentalTestApi::class)
fun verifySearchSuggestionsCount(rule: ComposeTestRule, numberOfSuggestions: Int, searchTerm: String) {
for (i in 1..RETRY_COUNT) {
try {
rule.waitUntilNodeCount(hasTestTag("mozac.awesomebar.suggestion"), numberOfSuggestions, waitingTime)
rule.onAllNodesWithTag("mozac.awesomebar.suggestion").assertCountEquals(numberOfSuggestions)
break
} catch (e: ComposeTimeoutException) {
if (i == RETRY_COUNT) {
throw e
} else {
mDevice.pressBack()
homeScreen {
}.openSearch {
typeSearch(searchTerm)
}
}
}
}
}
fun verifyAllowSuggestionsInPrivateModeDialog() {
assertTrue(
mDevice.findObject(

@ -35,7 +35,6 @@ 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.helpers.click
import org.mozilla.fenix.settings.SupportUtils
import java.text.SimpleDateFormat
import java.time.LocalDateTime
@ -48,8 +47,12 @@ import java.util.Date
* Implementation of Robot Pattern for the settings search sub menu.
*/
class SettingsSubMenuAboutRobot {
fun verifyAboutFirefoxPreview() = assertFirefoxPreviewPage()
fun verifyAboutFirefoxPreviewInfo() {
assertVersionNumber()
assertProductCompany()
assertCurrentTimestamp()
verifyTheLinksList()
}
class Transition {
fun goBack(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition {
@ -61,13 +64,6 @@ class SettingsSubMenuAboutRobot {
}
}
private fun assertFirefoxPreviewPage() {
assertVersionNumber()
assertProductCompany()
assertCurrentTimestamp()
verifyListElements()
}
private fun navigateBackToAboutPage(itemToInteract: () -> Unit) {
navigationToolbar {
}.openThreeDotMenu {
@ -77,7 +73,7 @@ private fun navigateBackToAboutPage(itemToInteract: () -> Unit) {
}
}
private fun verifyListElements() {
private fun verifyTheLinksList() {
assertAboutToolbar()
assertWhatIsNewInFirefoxPreview()
navigateBackToAboutPage(::assertSupport)

@ -41,6 +41,7 @@ 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.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText
import org.mozilla.fenix.helpers.click
@ -51,6 +52,22 @@ import org.mozilla.fenix.helpers.ext.waitNotNull
*/
class SettingsSubMenuAddonsManagerRobot {
fun verifyAddonsListIsDisplayed(shouldBeDisplayed: Boolean) {
if (shouldBeDisplayed) {
assertTrue(
mDevice.findObject(
UiSelector().resourceId("$packageName:id/add_ons_list"),
).waitForExists(waitingTime),
)
} else {
assertTrue(
mDevice.findObject(
UiSelector().resourceId("$packageName:id/add_ons_list"),
).waitUntilGone(waitingTime),
)
}
}
fun verifyAddonPermissionPrompt(addonName: String) {
mDevice.waitNotNull(Until.findObject(By.text("Add $addonName?")), waitingTime)

@ -40,7 +40,6 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.Constants.LONG_CLICK_DURATION
import org.mozilla.fenix.helpers.Constants.RETRY_COUNT
import org.mozilla.fenix.helpers.MatcherHelper.assertItemContainingTextExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdAndDescriptionExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdAndTextExists
import org.mozilla.fenix.helpers.MatcherHelper.assertItemWithResIdExists
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
@ -297,12 +296,6 @@ class TabDrawerRobot {
itemContainingText(getStringResource(R.string.synced_tabs_sign_in_message)),
itemContainingText(getStringResource(R.string.sync_sign_in)),
)
assertItemWithResIdAndDescriptionExists(
itemWithResIdAndDescription(
"$packageName:id/new_tab_button",
getStringResource(R.string.resync_button_content_description),
),
)
}
class Transition {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 63 KiB

@ -1,3 +1,6 @@
<!-- 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/. -->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt" >
<aapt:attr name="android:drawable">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

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

Loading…
Cancel
Save