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

pull/700/head
akliuxingyuan 7 months ago
commit dd9f0b7833

@ -78,6 +78,7 @@ projects:
- support-images
- support-ktx
- support-locale
- support-remotesettings
- support-rusterrors
- support-rusthttp
- support-rustlog

@ -28,6 +28,9 @@ glean:
hasExposure: true
exposureDescription: ""
variables:
enable-event-timestamps:
type: boolean
description: Enables precise event timestamps for Glean events
metrics-enabled:
type: json
description: "A map of metric base-identifiers to booleans representing the state of the 'enabled' flag for that metric."

@ -247,6 +247,14 @@ android {
targetCompatibility JavaVersion.VERSION_17
}
bundle {
language {
// Because we have runtime language selection we will keep all strings and languages
// in the base APKs.
enableSplit = false
}
}
lint {
lintConfig file("lint.xml")
baseline file("lint-baseline.xml")
@ -313,9 +321,10 @@ android.applicationVariants.configureEach { variant ->
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
def aab = project.hasProperty("aab")
// We use the same version code generator, that we inherited from Fennec, across all channels - even on
// channels that never shipped a Fennec build.
def versionCodeOverride = Config.generateFennecVersionCode(arch)
def versionCodeOverride = Config.generateFennecVersionCode(arch, aab)
println("versionCode for $abi = $versionCodeOverride, isMozillaOnline = $isMozillaOnline")
@ -477,6 +486,23 @@ android.applicationVariants.configureEach { variant ->
buildConfigField 'String', 'POCKET_CONSUMER_KEY', '""'
println("--")
}
// -------------------------------------------------------------------------------------------------
// BuildConfig: Set flag to disable LeakCanary in debug (on CI builds)
// -------------------------------------------------------------------------------------------------
if (isDebug) {
if (project.hasProperty("disableLeakCanary") || gradle.hasProperty("localProperties.disableLeakCanary")) {
buildConfigField "boolean", "LEAKCANARY", "false"
println("LeakCanary enabled in debug: false")
} else {
buildConfigField "boolean", "LEAKCANARY", "true"
println("LeakCanary enabled in debug: true")
}
} else {
buildConfigField "boolean", "LEAKCANARY", "false"
}
}
// Generate Kotlin code for the Fenix Glean metrics.
@ -503,6 +529,8 @@ nimbus {
// It will be fetched by Experimenter (the Nimbus experiment website)
// and used to inform experiment configuration.
experimenterManifest = ".experimenter.yaml"
applicationServicesDir = gradle.hasProperty('localProperties.autoPublish.application-services.dir')
? gradle.getProperty('localProperties.autoPublish.application-services.dir') : null
}
tasks.withType(KotlinCompile).configureEach {
@ -681,7 +709,7 @@ dependencies {
androidTestImplementation ComponentsDependencies.androidx_test_junit
androidTestImplementation ComponentsDependencies.androidx_work_testing
androidTestImplementation FenixDependencies.androidx_benchmark_junit4
androidTestImplementation FenixDependencies.mockwebserver
androidTestImplementation ComponentsDependencies.testing_mockwebserver
testImplementation project(':support-test')
testImplementation project(':support-test-libstate')
testImplementation ComponentsDependencies.androidx_test_junit

File diff suppressed because it is too large Load Diff

@ -245,7 +245,8 @@ features:
{
"feature-ui": 0,
"feature-setting-value": 0,
"dialog-re-engage-time": 4
"dialog-re-engage-time": 4,
"feature-setting-value-pbm": 0
}
defaults:
- channel: developer
@ -253,7 +254,8 @@ features:
"sections-enabled": {
"feature-ui": 1,
"feature-setting-value": 0,
"dialog-re-engage-time": 4
"dialog-re-engage-time": 4,
"feature-setting-value-pbm": 0
}
}
- channel: nightly
@ -261,7 +263,8 @@ features:
"sections-enabled": {
"feature-ui": 1,
"feature-setting-value": 0,
"dialog-re-engage-time": 4
"dialog-re-engage-time": 4,
"feature-setting-value-pbm": 0
}
}
unified-search:
@ -278,7 +281,7 @@ features:
enabled:
description: If true, the extensions process is enabled.
type: Boolean
default: false
default: true
growth-data:
description: A feature measuring campaign growth data
@ -328,6 +331,10 @@ features:
description: "A map of metric base-identifiers to booleans representing the state of the 'enabled' flag for that metric."
type: Map<String, Boolean>
default: {}
enable-event-timestamps:
description: "Enables precise event timestamps for Glean events"
type: Boolean
default: false
splash-screen:
description: "A feature that extends splash screen duration, allowing additional data fetching time for the app's initial run."
@ -406,6 +413,9 @@ features:
- channel: developer
value:
enabled: true
- channel: nightly
value:
enabled: true
types:
objects: {}
@ -455,6 +465,9 @@ types:
description: An integer indicating the number of hours that needs to happen before
the re-engagement dialog shows again since the last seen, for example if set to 4
that means if the users has seen the dialog, it will see it 4 hours later.
feature-setting-value-pbm:
description: An integer either 0 or 1 indicating if cookie banner setting should be enabled or disabled,
0 for setting the value to disabled, 1 for enabling the setting with the value reject_all.
OnboardingPanel:
description: The types of onboarding panels in the onboarding page
variants:

@ -11,9 +11,9 @@ features:
default:
default-browser:
card-type: default-browser
title: juno_onboarding_default_browser_title_nimbus
title: juno_onboarding_default_browser_title_nimbus_2
ordering: 10
body: juno_onboarding_default_browser_description_nimbus
body: juno_onboarding_default_browser_description_nimbus_2
link-text: juno_onboarding_default_browser_description_link_text
image-res: ic_onboarding_welcome
primary-button-label: juno_onboarding_default_browser_positive_button
@ -31,8 +31,8 @@ features:
sync-sign-in:
card-type: sync-sign-in
title: juno_onboarding_sign_in_title
body: juno_onboarding_sign_in_description
title: juno_onboarding_sign_in_title_2
body: juno_onboarding_sign_in_description_2
image-res: ic_onboarding_sync
ordering: 20
primary-button-label: juno_onboarding_sign_in_positive_button
@ -40,8 +40,8 @@ features:
notification-permission:
card-type: notification-permission
title: juno_onboarding_enable_notifications_title_nimbus
body: juno_onboarding_enable_notifications_description_nimbus
title: juno_onboarding_enable_notifications_title_nimbus_2
body: juno_onboarding_enable_notifications_description_nimbus_2
image-res: ic_notification_permission
ordering: 30
primary-button-label: juno_onboarding_enable_notifications_positive_button

@ -77,3 +77,17 @@ cookie-banner-report-site:
- https://github.com/mozilla-mobile/firefox-android/pull/1298#pullrequestreview-1350344223
notification_emails:
- android-probes@mozilla.com
fx-suggest:
description: |
A ping representing a single event occurring with or to a Firefox Suggestion.
Distinguishable by its `ping_type`.
Does not contain a `client_id`, preferring a `context_id` instead.
include_client_id: false
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1857092
data_reviews:
- https://github.com/mozilla-mobile/firefox-android/pull/3958#issuecomment-1758607927
notification_emails:
- lina@mozilla.com
- ttran@mozilla.com
- najiang@mozilla.com

@ -55,11 +55,6 @@ class AppRequestInterceptor(
)?.let { response ->
return response
}
interceptAmoRequest(uri, isSameDomain, hasUserGesture)?.let { response ->
return response
}
return context.components.services.appLinksInterceptor
.onLoadRequest(
engineSession,
@ -95,40 +90,6 @@ class AppRequestInterceptor(
return RequestInterceptor.ErrorResponse(errorPageUri)
}
/**
* Checks if the provided [uri] is a request to install an add-on from addons.mozilla.org and
* redirects to Add-ons Manager to trigger installation if needed.
*
* @return [RequestInterceptor.InterceptionResponse.Deny] when installation was triggered and
* the original request can be skipped, otherwise null to continue loading the page.
*/
private fun interceptAmoRequest(
uri: String,
isSameDomain: Boolean,
hasUserGesture: Boolean,
): RequestInterceptor.InterceptionResponse? {
// First we execute a quick check to see if this is a request we're interested in i.e. a
// request triggered by the user and coming from AMO.
if (hasUserGesture && isSameDomain && uri.startsWith(AMO_BASE_URL)) {
// Check if this is a request to install an add-on.
val matchResult = AMO_INSTALL_URL_REGEX.toRegex().matchEntire(uri)
if (matchResult != null) {
// Navigate and trigger add-on installation.
matchResult.groupValues.getOrNull(1)?.let { addonId ->
navController?.get()?.navigate(
NavGraphDirections.actionGlobalAddonsManagementFragment(addonId),
)
// We've redirected to the add-ons management fragment, skip original request.
return RequestInterceptor.InterceptionResponse.Deny
}
}
}
// In all other case we let the original request proceed.
return null
}
// This method is the only difference from the production code.
// Otherwise the code should be kept identical
@Suppress("LongParameterList")
@ -236,7 +197,5 @@ class AppRequestInterceptor(
companion object {
internal const val LOW_AND_MEDIUM_RISK_ERROR_PAGES = "low_and_medium_risk_error_pages.html"
internal const val HIGH_RISK_ERROR_PAGES = "high_risk_error_pages.html"
internal const val AMO_BASE_URL = BuildConfig.AMO_BASE_URL
internal const val AMO_INSTALL_URL_REGEX = "$AMO_BASE_URL/android/downloads/file/([^\\s]+)/([^\\s]+\\.xpi)"
}
}

@ -0,0 +1,74 @@
/* 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.experimentintegration
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.ui.robots.homeScreen
class GenericExperimentIntegrationTest {
private val experimentName = "Viewpoint"
@get:Rule
val activityTestRule = HomeActivityTestRule(
isJumpBackInCFREnabled = false,
isPWAsPromptEnabled = false,
isTCPCFREnabled = false,
)
@Before
fun setUp() {
TestHelper.appContext.settings().showSecretDebugMenuThisSession = true
}
@After
fun tearDown() {
TestHelper.appContext.settings().showSecretDebugMenuThisSession = false
}
private fun disableStudiesViaStudiesToggle() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openExperimentsMenu {
verifyExperimentEnrolled(experimentName)
}.goBack {
}.openSettingsSubMenuDataCollection {
clickStudiesOption()
verifyStudiesToggle(true)
clickStudiesToggle()
clickStudiesDialogOkButton()
}
}
@Test
fun testExperimentUnenrolled() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openExperimentsMenu {
verifyExperimentExists(experimentName)
verifyExperimentNotEnrolled(experimentName)
}
}
@Test
fun testExperimentUnenrolledViaSecretMenu() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openExperimentsMenu {
verifyExperimentExists(experimentName)
verifyExperimentEnrolled(experimentName)
unenrollfromExperiment(experimentName)
verifyExperimentNotEnrolled(experimentName)
}
}
}

@ -26,84 +26,99 @@
},
"charset-normalizer": {
"hashes": [
"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"
"sha256:02673e456dc5ab13659f85196c534dc596d4ef260e4d86e856c3b2773ce09843",
"sha256:02af06682e3590ab952599fbadac535ede5d60d78848e555aa58d0c0abbde786",
"sha256:03680bb39035fbcffe828eae9c3f8afc0428c91d38e7d61aa992ef7a59fb120e",
"sha256:0570d21da019941634a531444364f2482e8db0b3425fcd5ac0c36565a64142c8",
"sha256:09c77f964f351a7369cc343911e0df63e762e42bac24cd7d18525961c81754f4",
"sha256:0d3d5b7db9ed8a2b11a774db2bbea7ba1884430a205dbd54a32d61d7c2a190fa",
"sha256:1063da2c85b95f2d1a430f1c33b55c9c17ffaf5e612e10aeaad641c55a9e2b9d",
"sha256:12ebea541c44fdc88ccb794a13fe861cc5e35d64ed689513a5c03d05b53b7c82",
"sha256:153e7b6e724761741e0974fc4dcd406d35ba70b92bfe3fedcb497226c93b9da7",
"sha256:15b26ddf78d57f1d143bdf32e820fd8935d36abe8a25eb9ec0b5a71c82eb3895",
"sha256:1872d01ac8c618a8da634e232f24793883d6e456a66593135aeafe3784b0848d",
"sha256:187d18082694a29005ba2944c882344b6748d5be69e3a89bf3cc9d878e548d5a",
"sha256:1b2919306936ac6efb3aed1fbf81039f7087ddadb3160882a57ee2ff74fd2382",
"sha256:232ac332403e37e4a03d209a3f92ed9071f7d3dbda70e2a5e9cff1c4ba9f0678",
"sha256:23e8565ab7ff33218530bc817922fae827420f143479b753104ab801145b1d5b",
"sha256:24817cb02cbef7cd499f7c9a2735286b4782bd47a5b3516a0e84c50eab44b98e",
"sha256:249c6470a2b60935bafd1d1d13cd613f8cd8388d53461c67397ee6a0f5dce741",
"sha256:24a91a981f185721542a0b7c92e9054b7ab4fea0508a795846bc5b0abf8118d4",
"sha256:2502dd2a736c879c0f0d3e2161e74d9907231e25d35794584b1ca5284e43f596",
"sha256:250c9eb0f4600361dd80d46112213dff2286231d92d3e52af1e5a6083d10cad9",
"sha256:278c296c6f96fa686d74eb449ea1697f3c03dc28b75f873b65b5201806346a69",
"sha256:2935ffc78db9645cb2086c2f8f4cfd23d9b73cc0dc80334bc30aac6f03f68f8c",
"sha256:2f4a0033ce9a76e391542c182f0d48d084855b5fcba5010f707c8e8c34663d77",
"sha256:30a85aed0b864ac88309b7d94be09f6046c834ef60762a8833b660139cfbad13",
"sha256:380c4bde80bce25c6e4f77b19386f5ec9db230df9f2f2ac1e5ad7af2caa70459",
"sha256:3ae38d325b512f63f8da31f826e6cb6c367336f95e418137286ba362925c877e",
"sha256:3b447982ad46348c02cb90d230b75ac34e9886273df3a93eec0539308a6296d7",
"sha256:3debd1150027933210c2fc321527c2299118aa929c2f5a0a80ab6953e3bd1908",
"sha256:4162918ef3098851fcd8a628bf9b6a98d10c380725df9e04caf5ca6dd48c847a",
"sha256:468d2a840567b13a590e67dd276c570f8de00ed767ecc611994c301d0f8c014f",
"sha256:4cc152c5dd831641e995764f9f0b6589519f6f5123258ccaca8c6d34572fefa8",
"sha256:542da1178c1c6af8873e143910e2269add130a299c9106eef2594e15dae5e482",
"sha256:557b21a44ceac6c6b9773bc65aa1b4cc3e248a5ad2f5b914b91579a32e22204d",
"sha256:5707a746c6083a3a74b46b3a631d78d129edab06195a92a8ece755aac25a3f3d",
"sha256:588245972aca710b5b68802c8cad9edaa98589b1b42ad2b53accd6910dad3545",
"sha256:5adf257bd58c1b8632046bbe43ee38c04e1038e9d37de9c57a94d6bd6ce5da34",
"sha256:619d1c96099be5823db34fe89e2582b336b5b074a7f47f819d6b3a57ff7bdb86",
"sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6",
"sha256:67b8cc9574bb518ec76dc8e705d4c39ae78bb96237cb533edac149352c1f39fe",
"sha256:6a685067d05e46641d5d1623d7c7fdf15a357546cbb2f71b0ebde91b175ffc3e",
"sha256:70f1d09c0d7748b73290b29219e854b3207aea922f839437870d8cc2168e31cc",
"sha256:750b446b2ffce1739e8578576092179160f6d26bd5e23eb1789c4d64d5af7dc7",
"sha256:7966951325782121e67c81299a031f4c115615e68046f79b85856b86ebffc4cd",
"sha256:7b8b8bf1189b3ba9b8de5c8db4d541b406611a71a955bbbd7385bbc45fcb786c",
"sha256:7f5d10bae5d78e4551b7be7a9b29643a95aded9d0f602aa2ba584f0388e7a557",
"sha256:805dfea4ca10411a5296bcc75638017215a93ffb584c9e344731eef0dcfb026a",
"sha256:81bf654678e575403736b85ba3a7867e31c2c30a69bc57fe88e3ace52fb17b89",
"sha256:82eb849f085624f6a607538ee7b83a6d8126df6d2f7d3b319cb837b289123078",
"sha256:85a32721ddde63c9df9ebb0d2045b9691d9750cb139c161c80e500d210f5e26e",
"sha256:86d1f65ac145e2c9ed71d8ffb1905e9bba3a91ae29ba55b4c46ae6fc31d7c0d4",
"sha256:86f63face3a527284f7bb8a9d4f78988e3c06823f7bea2bd6f0e0e9298ca0403",
"sha256:8eaf82f0eccd1505cf39a45a6bd0a8cf1c70dcfc30dba338207a969d91b965c0",
"sha256:93aa7eef6ee71c629b51ef873991d6911b906d7312c6e8e99790c0f33c576f89",
"sha256:96c2b49eb6a72c0e4991d62406e365d87067ca14c1a729a870d22354e6f68115",
"sha256:9cf3126b85822c4e53aa28c7ec9869b924d6fcfb76e77a45c44b83d91afd74f9",
"sha256:9fe359b2e3a7729010060fbca442ca225280c16e923b37db0e955ac2a2b72a05",
"sha256:a0ac5e7015a5920cfce654c06618ec40c33e12801711da6b4258af59a8eff00a",
"sha256:a3f93dab657839dfa61025056606600a11d0b696d79386f974e459a3fbc568ec",
"sha256:a4b71f4d1765639372a3b32d2638197f5cd5221b19531f9245fcc9ee62d38f56",
"sha256:aae32c93e0f64469f74ccc730a7cb21c7610af3a775157e50bbd38f816536b38",
"sha256:aaf7b34c5bc56b38c931a54f7952f1ff0ae77a2e82496583b247f7c969eb1479",
"sha256:abecce40dfebbfa6abf8e324e1860092eeca6f7375c8c4e655a8afb61af58f2c",
"sha256:abf0d9f45ea5fb95051c8bfe43cb40cda383772f7e5023a83cc481ca2604d74e",
"sha256:ac71b2977fb90c35d41c9453116e283fac47bb9096ad917b8819ca8b943abecd",
"sha256:ada214c6fa40f8d800e575de6b91a40d0548139e5dc457d2ebb61470abf50186",
"sha256:b09719a17a2301178fac4470d54b1680b18a5048b481cb8890e1ef820cb80455",
"sha256:b1121de0e9d6e6ca08289583d7491e7fcb18a439305b34a30b20d8215922d43c",
"sha256:b3b2316b25644b23b54a6f6401074cebcecd1244c0b8e80111c9a3f1c8e83d65",
"sha256:b3d9b48ee6e3967b7901c052b670c7dda6deb812c309439adaffdec55c6d7b78",
"sha256:b5bcf60a228acae568e9911f410f9d9e0d43197d030ae5799e20dca8df588287",
"sha256:b8f3307af845803fb0b060ab76cf6dd3a13adc15b6b451f54281d25911eb92df",
"sha256:c2af80fb58f0f24b3f3adcb9148e6203fa67dd3f61c4af146ecad033024dde43",
"sha256:c350354efb159b8767a6244c166f66e67506e06c8924ed74669b2c70bc8735b1",
"sha256:c5a74c359b2d47d26cdbbc7845e9662d6b08a1e915eb015d044729e92e7050b7",
"sha256:c71f16da1ed8949774ef79f4a0260d28b83b3a50c6576f8f4f0288d109777989",
"sha256:d47ecf253780c90ee181d4d871cd655a789da937454045b17b5798da9393901a",
"sha256:d7eff0f27edc5afa9e405f7165f85a6d782d308f3b6b9d96016c010597958e63",
"sha256:d97d85fa63f315a8bdaba2af9a6a686e0eceab77b3089af45133252618e70884",
"sha256:db756e48f9c5c607b5e33dd36b1d5872d0422e960145b08ab0ec7fd420e9d649",
"sha256:dc45229747b67ffc441b3de2f3ae5e62877a282ea828a5bdb67883c4ee4a8810",
"sha256:e0fc42822278451bc13a2e8626cf2218ba570f27856b536e00cfa53099724828",
"sha256:e39c7eb31e3f5b1f88caff88bcff1b7f8334975b46f6ac6e9fc725d829bc35d4",
"sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2",
"sha256:e5c1502d4ace69a179305abb3f0bb6141cbe4714bc9b31d427329a95acfc8bdd",
"sha256:edfe077ab09442d4ef3c52cb1f9dab89bff02f4524afc0acf2d46be17dc479f5",
"sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe",
"sha256:f0d1e3732768fecb052d90d62b220af62ead5748ac51ef61e7b32c266cac9293",
"sha256:f5969baeaea61c97efa706b9b107dcba02784b1601c74ac84f2a532ea079403e",
"sha256:f8888e31e3a85943743f8fc15e71536bda1c81d5aa36d014a3c0c44481d7db6e",
"sha256:fc52b79d83a3fe3a360902d3f5d79073a993597d48114c29485e9431092905d8"
],
"markers": "python_full_version >= '3.7.0'",
"version": "==3.2.0"
"version": "==3.3.0"
},
"idna": {
"hashes": [
@ -135,8 +150,11 @@
"sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e",
"sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431",
"sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686",
"sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c",
"sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559",
"sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc",
"sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb",
"sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939",
"sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c",
"sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0",
"sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4",
@ -144,6 +162,7 @@
"sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575",
"sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba",
"sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d",
"sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd",
"sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3",
"sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00",
"sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155",
@ -152,6 +171,7 @@
"sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f",
"sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8",
"sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b",
"sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007",
"sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24",
"sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea",
"sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198",
@ -159,9 +179,12 @@
"sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee",
"sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be",
"sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2",
"sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1",
"sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707",
"sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6",
"sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c",
"sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58",
"sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823",
"sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779",
"sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636",
"sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c",
@ -180,18 +203,20 @@
"sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9",
"sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57",
"sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc",
"sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"
"sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc",
"sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2",
"sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"
],
"markers": "python_version >= '3.7'",
"version": "==2.1.3"
},
"packaging": {
"hashes": [
"sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61",
"sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"
"sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5",
"sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"
],
"markers": "python_version >= '3.7'",
"version": "==23.1"
"version": "==23.2"
},
"pluggy": {
"hashes": [
@ -207,6 +232,7 @@
"sha256:460c9a59b14e27c602eb5ece2e47bec99dc5fc5f6513cf924a7d03a578991b1f"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==7.4.1"
},
"pytest-html": {
@ -215,6 +241,7 @@
"sha256:79c4677ed6196417bf290d8b81f706342ae49f726f623728efa3f7dfff09f8eb"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==4.0.0"
},
"pytest-metadata": {
@ -223,6 +250,7 @@
"sha256:a17b1e40080401dc23177599208c52228df463db191c1a573ccdffacd885e190"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==3.0.0"
},
"pytest-variables": {
@ -231,6 +259,7 @@
"sha256:ab84235417afac5a0a7dd4c3918287d9c7329d2e16d570d6e943f8d8e02533b9"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==3.0.0"
},
"pyyaml": {
@ -287,6 +316,7 @@
"sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"
],
"index": "pypi",
"markers": "python_version >= '3.6'",
"version": "==6.0.1"
},
"requests": {
@ -295,15 +325,17 @@
"sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==2.31.0"
},
"urllib3": {
"hashes": [
"sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11",
"sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"
"sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84",
"sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==2.0.4"
"version": "==2.0.7"
}
},
"develop": {
@ -333,6 +365,7 @@
"sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==23.7.0"
},
"click": {
@ -349,6 +382,7 @@
"sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"
],
"index": "pypi",
"markers": "python_full_version >= '3.8.1'",
"version": "==6.1.0"
},
"mccabe": {
@ -369,11 +403,11 @@
},
"packaging": {
"hashes": [
"sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61",
"sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"
"sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5",
"sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"
],
"markers": "python_version >= '3.7'",
"version": "==23.1"
"version": "==23.2"
},
"pathspec": {
"hashes": [
@ -385,19 +419,19 @@
},
"platformdirs": {
"hashes": [
"sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d",
"sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"
"sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3",
"sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"
],
"markers": "python_version >= '3.7'",
"version": "==3.10.0"
"version": "==3.11.0"
},
"pycodestyle": {
"hashes": [
"sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0",
"sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8"
"sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f",
"sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"
],
"markers": "python_version >= '3.8'",
"version": "==2.11.0"
"version": "==2.11.1"
},
"pyflakes": {
"hashes": [

@ -4,6 +4,7 @@
package org.mozilla.fenix.experimentintegration
import android.content.pm.ActivityInfo
import org.junit.After
import org.junit.Before
import org.junit.Rule
@ -26,6 +27,7 @@ class SurveyExperimentIntegrationTest {
isJumpBackInCFREnabled = false,
isPWAsPromptEnabled = false,
isTCPCFREnabled = false,
isDeleteSitePermissionsEnabled = true,
)
@Before
@ -38,6 +40,15 @@ class SurveyExperimentIntegrationTest {
TestHelper.appContext.settings().showSecretDebugMenuThisSession = false
}
fun checkExperimentExists() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openExperimentsMenu {
verifyExperimentExists(experimentName)
}
}
@Test
fun checkSurveyNavigatesCorrectly() {
browserScreen {
@ -46,12 +57,7 @@ class SurveyExperimentIntegrationTest {
verifyUrl(surveyURL)
}
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openExperimentsMenu {
verifyExperimentExists(experimentName)
}
checkExperimentExists()
}
@Test
@ -62,11 +68,29 @@ class SurveyExperimentIntegrationTest {
verifyTabCounter("0")
}
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openExperimentsMenu {
verifyExperimentExists(experimentName)
checkExperimentExists()
}
@Test
fun checkHomescreenSurveyDismissesCorrectly() {
browserScreen {
verifyHomeScreenSurveyCloseButton()
}.clickHomeScreenSurveyCloseButton {
verifyTabCounter("0")
verifySurveyButtonDoesNotExist()
}
checkExperimentExists()
}
@Test
fun checkSurveyLandscapeLooksCorrect() {
activityTestRule.activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
browserScreen {
verifySurveyNoThanksButton()
verifySurveyButton()
}
checkExperimentExists()
}
}

@ -64,6 +64,8 @@ def gradlewbuild(gradlewbuild_log):
def fixture_experiment_data(experiment_url):
data = requests.get(experiment_url).json()
for item in data["branches"][0]["features"][0]["value"]["messages"].values():
item["surface"] = "homescreen"
item["style"] = "URGENT"
for count, trigger in enumerate(item["trigger"]):
if "USER_EN_SPEAKER" not in trigger:
del(item["trigger"][count])
@ -160,6 +162,7 @@ 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"
logging.info(f"Running command {command}")
try:
out = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:

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

@ -10,3 +10,13 @@ def test_survey_navigates_correctly(setup_experiment, gradlewbuild, load_branche
def test_survey_no_thanks_navigates_correctly(setup_experiment, gradlewbuild, load_branches):
setup_experiment(load_branches)
gradlewbuild.test("SurveyExperimentIntegrationTest#checkSurveyNoThanksNavigatesCorrectly")
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True)
def test_homescreen_survey_dismisses_correctly(setup_experiment, gradlewbuild, load_branches):
setup_experiment(load_branches)
gradlewbuild.test("SurveyExperimentIntegrationTest#checkHomescreenSurveyDismissesCorrectly")
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True)
def test_survey_landscape_looks_correct(setup_experiment, gradlewbuild, load_branches):
setup_experiment(load_branches)
gradlewbuild.test("SurveyExperimentIntegrationTest#checkSurveyLandscapeLooksCorrect")

@ -32,13 +32,13 @@ class ExtensionProcessTest {
}
@Test
fun test_extension_process_can_be_controlled_by_nimbus() {
fun test_extension_process_can_be_enabled_by_nimbus() {
val hardcodedNimbus = HardcodedNimbusFeatures(
context,
"extensions-process" to JSONObject(
"""
{
"enabled":true
"enabled": true
}
""".trimIndent(),
),
@ -53,7 +53,20 @@ class ExtensionProcessTest {
}
@Test
fun test_extension_process_must_be_disabled_by_default() {
fun test_extension_process_can_be_disabled_by_nimbus() {
val hardcodedNimbus = HardcodedNimbusFeatures(
context,
"extensions-process" to JSONObject(
"""
{
"enabled": false
}
""".trimIndent(),
),
)
hardcodedNimbus.connectWith(FxNimbus)
val runtime = GeckoProvider.createRuntimeSettings(context, policy)
assertFalse(FxNimbus.features.extensionsProcess.value().enabled)

@ -42,182 +42,186 @@
},
"cffi": {
"hashes": [
"sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5",
"sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef",
"sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104",
"sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426",
"sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405",
"sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375",
"sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a",
"sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e",
"sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc",
"sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf",
"sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185",
"sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497",
"sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3",
"sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35",
"sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c",
"sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83",
"sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21",
"sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca",
"sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984",
"sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac",
"sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd",
"sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee",
"sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a",
"sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2",
"sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192",
"sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7",
"sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585",
"sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f",
"sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e",
"sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27",
"sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b",
"sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e",
"sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e",
"sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d",
"sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c",
"sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415",
"sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82",
"sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02",
"sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314",
"sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325",
"sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c",
"sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3",
"sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914",
"sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045",
"sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d",
"sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9",
"sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5",
"sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2",
"sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c",
"sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3",
"sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2",
"sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8",
"sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d",
"sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d",
"sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9",
"sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162",
"sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76",
"sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4",
"sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e",
"sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9",
"sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6",
"sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b",
"sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01",
"sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"
],
"version": "==1.15.1"
"sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc",
"sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a",
"sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417",
"sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab",
"sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520",
"sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36",
"sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743",
"sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8",
"sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed",
"sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684",
"sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56",
"sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324",
"sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d",
"sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235",
"sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e",
"sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088",
"sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000",
"sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7",
"sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e",
"sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673",
"sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c",
"sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe",
"sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2",
"sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098",
"sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8",
"sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a",
"sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0",
"sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b",
"sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896",
"sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e",
"sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9",
"sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2",
"sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b",
"sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6",
"sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404",
"sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f",
"sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0",
"sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4",
"sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc",
"sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936",
"sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba",
"sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872",
"sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb",
"sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614",
"sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1",
"sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d",
"sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969",
"sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b",
"sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4",
"sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627",
"sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956",
"sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"
],
"markers": "python_version >= '3.8'",
"version": "==1.16.0"
},
"charset-normalizer": {
"hashes": [
"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_version >= '3.7'",
"version": "==3.2.0"
"sha256:02673e456dc5ab13659f85196c534dc596d4ef260e4d86e856c3b2773ce09843",
"sha256:02af06682e3590ab952599fbadac535ede5d60d78848e555aa58d0c0abbde786",
"sha256:03680bb39035fbcffe828eae9c3f8afc0428c91d38e7d61aa992ef7a59fb120e",
"sha256:0570d21da019941634a531444364f2482e8db0b3425fcd5ac0c36565a64142c8",
"sha256:09c77f964f351a7369cc343911e0df63e762e42bac24cd7d18525961c81754f4",
"sha256:0d3d5b7db9ed8a2b11a774db2bbea7ba1884430a205dbd54a32d61d7c2a190fa",
"sha256:1063da2c85b95f2d1a430f1c33b55c9c17ffaf5e612e10aeaad641c55a9e2b9d",
"sha256:12ebea541c44fdc88ccb794a13fe861cc5e35d64ed689513a5c03d05b53b7c82",
"sha256:153e7b6e724761741e0974fc4dcd406d35ba70b92bfe3fedcb497226c93b9da7",
"sha256:15b26ddf78d57f1d143bdf32e820fd8935d36abe8a25eb9ec0b5a71c82eb3895",
"sha256:1872d01ac8c618a8da634e232f24793883d6e456a66593135aeafe3784b0848d",
"sha256:187d18082694a29005ba2944c882344b6748d5be69e3a89bf3cc9d878e548d5a",
"sha256:1b2919306936ac6efb3aed1fbf81039f7087ddadb3160882a57ee2ff74fd2382",
"sha256:232ac332403e37e4a03d209a3f92ed9071f7d3dbda70e2a5e9cff1c4ba9f0678",
"sha256:23e8565ab7ff33218530bc817922fae827420f143479b753104ab801145b1d5b",
"sha256:24817cb02cbef7cd499f7c9a2735286b4782bd47a5b3516a0e84c50eab44b98e",
"sha256:249c6470a2b60935bafd1d1d13cd613f8cd8388d53461c67397ee6a0f5dce741",
"sha256:24a91a981f185721542a0b7c92e9054b7ab4fea0508a795846bc5b0abf8118d4",
"sha256:2502dd2a736c879c0f0d3e2161e74d9907231e25d35794584b1ca5284e43f596",
"sha256:250c9eb0f4600361dd80d46112213dff2286231d92d3e52af1e5a6083d10cad9",
"sha256:278c296c6f96fa686d74eb449ea1697f3c03dc28b75f873b65b5201806346a69",
"sha256:2935ffc78db9645cb2086c2f8f4cfd23d9b73cc0dc80334bc30aac6f03f68f8c",
"sha256:2f4a0033ce9a76e391542c182f0d48d084855b5fcba5010f707c8e8c34663d77",
"sha256:30a85aed0b864ac88309b7d94be09f6046c834ef60762a8833b660139cfbad13",
"sha256:380c4bde80bce25c6e4f77b19386f5ec9db230df9f2f2ac1e5ad7af2caa70459",
"sha256:3ae38d325b512f63f8da31f826e6cb6c367336f95e418137286ba362925c877e",
"sha256:3b447982ad46348c02cb90d230b75ac34e9886273df3a93eec0539308a6296d7",
"sha256:3debd1150027933210c2fc321527c2299118aa929c2f5a0a80ab6953e3bd1908",
"sha256:4162918ef3098851fcd8a628bf9b6a98d10c380725df9e04caf5ca6dd48c847a",
"sha256:468d2a840567b13a590e67dd276c570f8de00ed767ecc611994c301d0f8c014f",
"sha256:4cc152c5dd831641e995764f9f0b6589519f6f5123258ccaca8c6d34572fefa8",
"sha256:542da1178c1c6af8873e143910e2269add130a299c9106eef2594e15dae5e482",
"sha256:557b21a44ceac6c6b9773bc65aa1b4cc3e248a5ad2f5b914b91579a32e22204d",
"sha256:5707a746c6083a3a74b46b3a631d78d129edab06195a92a8ece755aac25a3f3d",
"sha256:588245972aca710b5b68802c8cad9edaa98589b1b42ad2b53accd6910dad3545",
"sha256:5adf257bd58c1b8632046bbe43ee38c04e1038e9d37de9c57a94d6bd6ce5da34",
"sha256:619d1c96099be5823db34fe89e2582b336b5b074a7f47f819d6b3a57ff7bdb86",
"sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6",
"sha256:67b8cc9574bb518ec76dc8e705d4c39ae78bb96237cb533edac149352c1f39fe",
"sha256:6a685067d05e46641d5d1623d7c7fdf15a357546cbb2f71b0ebde91b175ffc3e",
"sha256:70f1d09c0d7748b73290b29219e854b3207aea922f839437870d8cc2168e31cc",
"sha256:750b446b2ffce1739e8578576092179160f6d26bd5e23eb1789c4d64d5af7dc7",
"sha256:7966951325782121e67c81299a031f4c115615e68046f79b85856b86ebffc4cd",
"sha256:7b8b8bf1189b3ba9b8de5c8db4d541b406611a71a955bbbd7385bbc45fcb786c",
"sha256:7f5d10bae5d78e4551b7be7a9b29643a95aded9d0f602aa2ba584f0388e7a557",
"sha256:805dfea4ca10411a5296bcc75638017215a93ffb584c9e344731eef0dcfb026a",
"sha256:81bf654678e575403736b85ba3a7867e31c2c30a69bc57fe88e3ace52fb17b89",
"sha256:82eb849f085624f6a607538ee7b83a6d8126df6d2f7d3b319cb837b289123078",
"sha256:85a32721ddde63c9df9ebb0d2045b9691d9750cb139c161c80e500d210f5e26e",
"sha256:86d1f65ac145e2c9ed71d8ffb1905e9bba3a91ae29ba55b4c46ae6fc31d7c0d4",
"sha256:86f63face3a527284f7bb8a9d4f78988e3c06823f7bea2bd6f0e0e9298ca0403",
"sha256:8eaf82f0eccd1505cf39a45a6bd0a8cf1c70dcfc30dba338207a969d91b965c0",
"sha256:93aa7eef6ee71c629b51ef873991d6911b906d7312c6e8e99790c0f33c576f89",
"sha256:96c2b49eb6a72c0e4991d62406e365d87067ca14c1a729a870d22354e6f68115",
"sha256:9cf3126b85822c4e53aa28c7ec9869b924d6fcfb76e77a45c44b83d91afd74f9",
"sha256:9fe359b2e3a7729010060fbca442ca225280c16e923b37db0e955ac2a2b72a05",
"sha256:a0ac5e7015a5920cfce654c06618ec40c33e12801711da6b4258af59a8eff00a",
"sha256:a3f93dab657839dfa61025056606600a11d0b696d79386f974e459a3fbc568ec",
"sha256:a4b71f4d1765639372a3b32d2638197f5cd5221b19531f9245fcc9ee62d38f56",
"sha256:aae32c93e0f64469f74ccc730a7cb21c7610af3a775157e50bbd38f816536b38",
"sha256:aaf7b34c5bc56b38c931a54f7952f1ff0ae77a2e82496583b247f7c969eb1479",
"sha256:abecce40dfebbfa6abf8e324e1860092eeca6f7375c8c4e655a8afb61af58f2c",
"sha256:abf0d9f45ea5fb95051c8bfe43cb40cda383772f7e5023a83cc481ca2604d74e",
"sha256:ac71b2977fb90c35d41c9453116e283fac47bb9096ad917b8819ca8b943abecd",
"sha256:ada214c6fa40f8d800e575de6b91a40d0548139e5dc457d2ebb61470abf50186",
"sha256:b09719a17a2301178fac4470d54b1680b18a5048b481cb8890e1ef820cb80455",
"sha256:b1121de0e9d6e6ca08289583d7491e7fcb18a439305b34a30b20d8215922d43c",
"sha256:b3b2316b25644b23b54a6f6401074cebcecd1244c0b8e80111c9a3f1c8e83d65",
"sha256:b3d9b48ee6e3967b7901c052b670c7dda6deb812c309439adaffdec55c6d7b78",
"sha256:b5bcf60a228acae568e9911f410f9d9e0d43197d030ae5799e20dca8df588287",
"sha256:b8f3307af845803fb0b060ab76cf6dd3a13adc15b6b451f54281d25911eb92df",
"sha256:c2af80fb58f0f24b3f3adcb9148e6203fa67dd3f61c4af146ecad033024dde43",
"sha256:c350354efb159b8767a6244c166f66e67506e06c8924ed74669b2c70bc8735b1",
"sha256:c5a74c359b2d47d26cdbbc7845e9662d6b08a1e915eb015d044729e92e7050b7",
"sha256:c71f16da1ed8949774ef79f4a0260d28b83b3a50c6576f8f4f0288d109777989",
"sha256:d47ecf253780c90ee181d4d871cd655a789da937454045b17b5798da9393901a",
"sha256:d7eff0f27edc5afa9e405f7165f85a6d782d308f3b6b9d96016c010597958e63",
"sha256:d97d85fa63f315a8bdaba2af9a6a686e0eceab77b3089af45133252618e70884",
"sha256:db756e48f9c5c607b5e33dd36b1d5872d0422e960145b08ab0ec7fd420e9d649",
"sha256:dc45229747b67ffc441b3de2f3ae5e62877a282ea828a5bdb67883c4ee4a8810",
"sha256:e0fc42822278451bc13a2e8626cf2218ba570f27856b536e00cfa53099724828",
"sha256:e39c7eb31e3f5b1f88caff88bcff1b7f8334975b46f6ac6e9fc725d829bc35d4",
"sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2",
"sha256:e5c1502d4ace69a179305abb3f0bb6141cbe4714bc9b31d427329a95acfc8bdd",
"sha256:edfe077ab09442d4ef3c52cb1f9dab89bff02f4524afc0acf2d46be17dc479f5",
"sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe",
"sha256:f0d1e3732768fecb052d90d62b220af62ead5748ac51ef61e7b32c266cac9293",
"sha256:f5969baeaea61c97efa706b9b107dcba02784b1601c74ac84f2a532ea079403e",
"sha256:f8888e31e3a85943743f8fc15e71536bda1c81d5aa36d014a3c0c44481d7db6e",
"sha256:fc52b79d83a3fe3a360902d3f5d79073a993597d48114c29485e9431092905d8"
],
"markers": "python_full_version >= '3.7.0'",
"version": "==3.3.0"
},
"cryptography": {
"hashes": [
"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"
"sha256:004b6ccc95943f6a9ad3142cfabcc769d7ee38a3f60fb0dddbfb431f818c3a67",
"sha256:047c4603aeb4bbd8db2756e38f5b8bd7e94318c047cfe4efeb5d715e08b49311",
"sha256:0d9409894f495d465fe6fda92cb70e8323e9648af912d5b9141d616df40a87b8",
"sha256:23a25c09dfd0d9f28da2352503b23e086f8e78096b9fd585d1d14eca01613e13",
"sha256:2ed09183922d66c4ec5fdaa59b4d14e105c084dd0febd27452de8f6f74704143",
"sha256:35c00f637cd0b9d5b6c6bd11b6c3359194a8eba9c46d4e875a3660e3b400005f",
"sha256:37480760ae08065437e6573d14be973112c9e6dcaf5f11d00147ee74f37a3829",
"sha256:3b224890962a2d7b57cf5eeb16ccaafba6083f7b811829f00476309bce2fe0fd",
"sha256:5a0f09cefded00e648a127048119f77bc2b2ec61e736660b5789e638f43cc397",
"sha256:5b72205a360f3b6176485a333256b9bcd48700fc755fef51c8e7e67c4b63e3ac",
"sha256:7e53db173370dea832190870e975a1e09c86a879b613948f09eb49324218c14d",
"sha256:7febc3094125fc126a7f6fb1f420d0da639f3f32cb15c8ff0dc3997c4549f51a",
"sha256:80907d3faa55dc5434a16579952ac6da800935cd98d14dbd62f6f042c7f5e839",
"sha256:86defa8d248c3fa029da68ce61fe735432b047e32179883bdb1e79ed9bb8195e",
"sha256:8ac4f9ead4bbd0bc8ab2d318f97d85147167a488be0e08814a37eb2f439d5cf6",
"sha256:93530900d14c37a46ce3d6c9e6fd35dbe5f5601bf6b3a5c325c7bffc030344d9",
"sha256:9eeb77214afae972a00dee47382d2591abe77bdae166bda672fb1e24702a3860",
"sha256:b5f4dfe950ff0479f1f00eda09c18798d4f49b98f4e2006d644b3301682ebdca",
"sha256:c3391bd8e6de35f6f1140e50aaeb3e2b3d6a9012536ca23ab0d9c35ec18c8a91",
"sha256:c880eba5175f4307129784eca96f4e70b88e57aa3f680aeba3bab0e980b0f37d",
"sha256:cecfefa17042941f94ab54f769c8ce0fe14beff2694e9ac684176a2535bf9714",
"sha256:e40211b4923ba5a6dc9769eab704bdb3fbb58d56c5b336d30996c24fcf12aadb",
"sha256:efc8ad4e6fc4f1752ebfb58aefece8b4e3c4cae940b0994d43649bdfce8d0d4f"
],
"index": "pypi",
"version": "==41.0.3"
"markers": "python_version >= '3.7'",
"version": "==41.0.4"
},
"distro": {
"hashes": [
@ -357,19 +361,19 @@
},
"outcome": {
"hashes": [
"sha256:6f82bd3de45da303cf1f771ecafa1633750a358436a8bb60e06a1ceb745d2672",
"sha256:c4ab89a56575d6d38a05aa16daeaa333109c1f96167aba8901ab18b6b5e0f7f5"
"sha256:588ef4dc10b64e8df160d8d1310c44e1927129a66d6d2ef86845cef512c5f24c",
"sha256:7b688fd82db72f4b0bc9e883a00359d4d4179cd97d27f09c9644d0c842ba7786"
],
"markers": "python_version >= '3.7'",
"version": "==1.2.0"
"version": "==1.3.0"
},
"packaging": {
"hashes": [
"sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61",
"sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"
"sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5",
"sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"
],
"markers": "python_version >= '3.7'",
"version": "==23.1"
"version": "==23.2"
},
"pluggy": {
"hashes": [
@ -384,7 +388,7 @@
"sha256:1393922fcb64598944ad457569fbeb4b3ac189ef50b5adb9cef3284e87e394ce",
"sha256:1a8e201211f99a85df55f720b3b6da7fb5c8cdef56792c4547205be2de5ea606"
],
"markers": "python_version >= '3.7'",
"markers": "python_full_version >= '3.7.0'",
"version": "==4.2.0"
},
"py": {
@ -444,6 +448,7 @@
"sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==7.1.2"
},
"pytest-fxa": {
@ -460,6 +465,7 @@
"sha256:b7f82f123936a3f4d2950bc993c2c1ca09ce262c9ae12f9ac763a2401380b455"
],
"index": "pypi",
"markers": "python_version >= '3.6'",
"version": "==3.1.1"
},
"pytest-metadata": {
@ -468,15 +474,16 @@
"sha256:fcd2f416f15be295943527b3c8ba16a44ae5a7141939c90c3dc5ce9d167cf2a5"
],
"index": "pypi",
"markers": "python_version >= '3.7' and python_version < '4.0'",
"version": "==2.0.2"
},
"python-utils": {
"hashes": [
"sha256:1970468fff1c0adbd60b9a751e6a786223a9f0373c954571912d9cf4be49b552",
"sha256:e31c1187168c314c984932e99c2d3f973465443493869ae041dd9e2e18e998aa"
"sha256:ec3a672465efb6c673845a43afcfafaa23d2594c24324a40ec18a0c59478dc0b",
"sha256:efdf31c8154667d7dc0317547c8e6d3b506c5d4b6e360e0c89662306262fc0ab"
],
"markers": "python_version >= '3.9'",
"version": "==3.7.0"
"version": "==3.8.1"
},
"redo": {
"hashes": [
@ -491,23 +498,24 @@
"sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==2.31.0"
},
"selenium": {
"hashes": [
"sha256:95be6aa449a0ab4ac1198bb9de71bbe9170405e04b9752f4b450dc7292a21828",
"sha256:b2c48b1440db54a0653300d9955f5421390723d53b36ec835e18de8e13bbd401"
"sha256:0d14b0d9842366f38fb5f8f842cf7c042bcfa062affc6a0a86e4d634bdd0fe54",
"sha256:be9824a9354a7fe288e3fad9ceb6a9c65ddc7c44545d23ad0ebf4ce202b19893"
],
"markers": "python_version >= '3.8'",
"version": "==4.12.0"
"version": "==4.14.0"
},
"setuptools": {
"hashes": [
"sha256:00478ca80aeebeecb2f288d3206b0de568df5cd2b8fada1209843cc9a8d88a48",
"sha256:af3d5949030c3f493f550876b2fd1dd5ec66689c4ee5d5344f009746f71fd5a8"
"sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87",
"sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"
],
"markers": "python_version >= '3.8'",
"version": "==68.2.0"
"version": "==68.2.2"
},
"six": {
"hashes": [
@ -557,34 +565,35 @@
},
"trio-websocket": {
"hashes": [
"sha256:c7a620c4013c34b7e4477d89fe76695da1e455e4510a8d7ae13f81c632bdce1d",
"sha256:e66b3db3e2453017431dfbd352081006654e1241c2a6800dc2f43d7df54d55c5"
"sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f",
"sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638"
],
"markers": "python_version >= '3.7'",
"version": "==0.10.4"
"version": "==0.11.1"
},
"typing-extensions": {
"hashes": [
"sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36",
"sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"
"sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0",
"sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"
],
"markers": "python_version >= '3.7'",
"version": "==4.7.1"
"markers": "python_version >= '3.8'",
"version": "==4.8.0"
},
"urllib3": {
"hashes": [
"sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11",
"sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"
"sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84",
"sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==2.0.4"
"version": "==2.0.7"
},
"wcwidth": {
"hashes": [
"sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e",
"sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"
"sha256:77f719e01648ed600dfa5402c347481c0992263b81a027344f3e1ba25493a704",
"sha256:8705c569999ffbb4f6a87c6d1b80f324bd6db952f5eb0b95bc07517f4c1813d4"
],
"version": "==0.2.6"
"version": "==0.2.8"
},
"webob": {
"hashes": [
@ -599,7 +608,7 @@
"sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065",
"sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"
],
"markers": "python_version >= '3.7'",
"markers": "python_full_version >= '3.7.0'",
"version": "==1.2.0"
},
"zope.component": {
@ -620,81 +629,87 @@
},
"zope.hookable": {
"hashes": [
"sha256:0054539ed839751b7f511193912cba393f0b8b5f7dfe9f3601c65b2d3b74e731",
"sha256:049ef54de127236e555d0864ad3b950b2b6e5048cdf1098cf340c6fb108104c7",
"sha256:06570ed57b22624c7673ff203801bbdece14d2d42dc5d9879c24ef5612c53456",
"sha256:0e9e5adc24954e157e084bee97362346470a06d0305cb095118367a8a776dce4",
"sha256:2e8fd79437c2007020d3faac41e13c49bcbaa6a0738e4142b996c656dcb5bb69",
"sha256:4313b3d282c1c26fcb69569b7988bc2de0b6dc59238ae7189b6b7b29503d47cb",
"sha256:448ca90d78bd3aef75fe5d55d19f5d05a217193738b7a8d5fd9e93ecf2c02c84",
"sha256:4b2fd781571336b0b7655826d9a052379a06b62af138085409b2e3fef1e6fb3d",
"sha256:5215355203b9583b7f2a8f06fa7df272562cc12bf5be1a960a45ea49c3294426",
"sha256:5cb0e4a23588435c6911bde300158d31e47c73c469fbf59d927e801e1cb457ef",
"sha256:71bff8f7c2e223f92a218b0909ccc6f612c075cc3b5ed164cf152f1537cae2ca",
"sha256:7241ab28df7288d9a8bf49339a0aabfbf035b93d6a2a843af13d13dfa735c46a",
"sha256:7269a0fbcd7c5901e255679f8dac835b628eab58d5490c38cf2b15508f181e64",
"sha256:7401bd6138e58231aef751c63718726259a7aa6875d746d8a87bba70271b9cff",
"sha256:761c9bf1b8df6e2b2d5ae87cda27b8e82c33e2f328750e039de4f6f7f35b73cd",
"sha256:78c51f04aabd3b77ba8d3b2c2abaff8b7598376fea7bd1af9929e90549f6dd4c",
"sha256:93cfda0663d4d3db6b1818619fbc14e3df2e703454983c841b3b95894d559f86",
"sha256:9af06ca83ff1ef9f94a98d08095dd8960fc5b71ffc7ed7db05988dc493e148a1",
"sha256:9cffa01d8ef1172492fd6df0113ff5432006129b9bd6e8265e1e4985362b973d",
"sha256:9d398b1de407a5908c8e5f55fb7a26fa177916b1203e697ef0b4c3389dd28e14",
"sha256:9f447ecaf7741257333f4b1cc215de633daaf147dbc87133638142ed88492617",
"sha256:9f5d425eb57dee785e4d32703e45c5d6cf2b9fa7ad37c10214593b5f62daa60b",
"sha256:9f7dd1b45cd13976f49ad21f48a8253628c74ad5eefe3f6e14d50f38cc45f613",
"sha256:9fd11381ec66a8569f999dbe11c94870ddf8aecd591300f203a927f18e938a24",
"sha256:acec917178af910959205f98f48bcd0a165bdcd6b4d8b3f4baf06fa393ac5ff5",
"sha256:b65e86a5cb8244d83eabd021f70968d4a80fac01edc99f6e35d29e5458a128bb",
"sha256:bad033b8adfe71f650fef2d4fc33452b3310a0e53139a530dbffbcf9fe08c8c8",
"sha256:c39ffe1b1ef7543e8efafdc6472d7b9ece8ed1ebe20be261522346463aa2c8c0",
"sha256:c79da9673a7d704f6ea2a4bbef6e5e161adbba9d8371476de28a0e3416510cc1",
"sha256:d06da931ac88ebb4c02ac89d0b6fdb2e4fff130901edf9c6e7ea0338a2edf6bd",
"sha256:d44229a0aa8d3587491f359d7326c55b5db6379f68656785dece792afbcfcbae",
"sha256:d5e50bfbcde1afe32f9cf7fa5e8ea42e218090ecb989c31164d708d0491134b7",
"sha256:d822b7ec71ebb5c96df000e2180127e94ba49258335ae796dc4b6201259b2502",
"sha256:eeb4042f9b1771a1dd8377cb1cb307c4a4f5821d1491becbdc69bc9de66d3918",
"sha256:fb601f00ac87e5aa582a81315ed96768ce3513280729d3f51f79312e2b8b94ac",
"sha256:fd49da3340339b8aeef31153ce898e93867ee5a7ffcf685e903ceae6717f0cc2"
"sha256:070776c9f36b99fb0df5af2a762a4d4f77e568df36637797e2e8a41c9d8d290d",
"sha256:12959a3d70c35a6b835e69d9f70008d3a31e324d2f2d13536c8533f648fa8a96",
"sha256:1668993d40a7cfdc867843dd5725929e7f83a5b0c195c709af1daef8274f43cb",
"sha256:1a97f4a46d87ee726d48f3058062e2a1570f136ba9aa788e9c0bcdd5e511609d",
"sha256:20936873c8b17f903bc8b63ca13ec6c492665b48067988e4359ddd5d1c5b6f2f",
"sha256:2968b37457079678a9d1bd9ef09ff1a224d4234e02120792a9e4e00117193df3",
"sha256:2d7bfcb11356e4dbb3e24943f0055819ff264dada4dc0b68ca012e5a1ff5b474",
"sha256:2d7c782bbfed7aa4846af2a67269718563daa904b33077d97665e5644b08ce2b",
"sha256:351cc91c0bc4c9a6d537c033179be22b613e3a60be42ba08f863490c32f736cf",
"sha256:3875bfb6d113ecb41c07dee67be16f5a0bbbae13199b9979e2bbeec97d97ec4b",
"sha256:4d3200d955c4182223f04593fef4add9771d4156d4ba6f034e65396f3b132139",
"sha256:55a0a9d62ea907861fd79ae39e86f1d9e755064543e46c5430aa586c1b5a4854",
"sha256:5efffb4417604561ff0bae5c80ad3aa2ecd2145c5a8c3a4b0a4a1f55017e95a2",
"sha256:6cd064359ba8c356b1bdb6c84df028ce2f6402f3703a930c4e1bab25d3ff7fff",
"sha256:6d5f83e626caa7ed2814609b446dcc6a3abb19db729bc67671c3eef2265006fd",
"sha256:6f4d8b99c1d52e3da1b122e42e7c07eb02f6468cd315f0b6811f426586b7aa8c",
"sha256:6ff30e7b24859974f2ff3f00b4564c4c8692730690c4c46f0019ef9b42b1f795",
"sha256:7761c5fdf97a274ce8576002a2444ff45645327179ee1bafde5d5d743d0d3556",
"sha256:78e4953334592c42aefa3e74f74d4c5b168a70d2c2d8cd945eb1a2f442eebee5",
"sha256:7c5a8204992fe677bffa0e5e190cb031aef74994c658a0402a338eed7b58fe8d",
"sha256:7ca296b1fb0c5f69e8c0e5a90a5a953e456931016fd1f8c513b3baa3751b0640",
"sha256:86bc17b6b3d1d9274168318cf171d509cbe6c8a8bdd8be0282291dac4a768de0",
"sha256:968f196347fa1bd9ffc15e1d1c9d250f46137d36b75bdd2a482c51c5fc314402",
"sha256:aaac43ac9bf9359db5170627f645c6442e9cf74414f8299ee217e4cfb259bc5c",
"sha256:ad48a4db8d12701759b93f3cec55aff9f53626dff12ec415144c2d0ee719b965",
"sha256:b99ddae52522dce614a0323812df944b1835d97f254f81c46b33c3bcf82dadf5",
"sha256:ba0e86642d5b33b5edf39d28da26ed34545780a2720aa79e6dda94402c3fc457",
"sha256:c0db442d2e78d5ea1afa5f1c2537bf7201155ec8963abc8d0f3b9257b52caffb",
"sha256:c2cf62d40f689d4bfbe733e3ed41ed2b557d011d9050185abb2bc3e96130677d",
"sha256:cd6fb03c174a4e20f4faec9ff22bace922bb59adb44078aebec862605bbcee92",
"sha256:e21dc34ba2453d798cf3cab92efb4994e55659c19a1f77d4cf0c2a0067e78583",
"sha256:ee1e32f54db69abfb6c7e227e65452d2b92e1cefae93a51106419ec623a845ff",
"sha256:ee7ff109b2b4793137b6bd82ddc3516cbd643e67813e11e31e0bf613b387d2ec",
"sha256:f2eeba6e2fd69e9e72a003edcceed7ce4614ad1c1e866bf168c92540c3658343",
"sha256:f58a129a63289c44ba84ae951019f8a60d34c4d948350be7fa2abda5106f8498",
"sha256:ff5ee2df0dc3ccc524772e00d5a1991c3b8d942cc12fd503a7bf9dc35a040779"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==5.4"
"markers": "python_version >= '3.7'",
"version": "==6.0"
},
"zope.interface": {
"hashes": [
"sha256:042f2381118b093714081fd82c98e3b189b68db38ee7d35b63c327c470ef8373",
"sha256:0ec9653825f837fbddc4e4b603d90269b501486c11800d7c761eee7ce46d1bbb",
"sha256:12175ca6b4db7621aedd7c30aa7cfa0a2d65ea3a0105393e05482d7a2d367446",
"sha256:1592f68ae11e557b9ff2bc96ac8fc30b187e77c45a3c9cd876e3368c53dc5ba8",
"sha256:23ac41d52fd15dd8be77e3257bc51bbb82469cf7f5e9a30b75e903e21439d16c",
"sha256:424d23b97fa1542d7be882eae0c0fc3d6827784105264a8169a26ce16db260d8",
"sha256:4407b1435572e3e1610797c9203ad2753666c62883b921318c5403fb7139dec2",
"sha256:48f4d38cf4b462e75fac78b6f11ad47b06b1c568eb59896db5b6ec1094eb467f",
"sha256:4c3d7dfd897a588ec27e391edbe3dd320a03684457470415870254e714126b1f",
"sha256:5171eb073474a5038321409a630904fd61f12dd1856dd7e9d19cd6fe092cbbc5",
"sha256:5a158846d0fca0a908c1afb281ddba88744d403f2550dc34405c3691769cdd85",
"sha256:6ee934f023f875ec2cfd2b05a937bd817efcc6c4c3f55c5778cbf78e58362ddc",
"sha256:790c1d9d8f9c92819c31ea660cd43c3d5451df1df61e2e814a6f99cebb292788",
"sha256:809fe3bf1a91393abc7e92d607976bbb8586512913a79f2bf7d7ec15bd8ea518",
"sha256:87b690bbee9876163210fd3f500ee59f5803e4a6607d1b1238833b8885ebd410",
"sha256:89086c9d3490a0f265a3c4b794037a84541ff5ffa28bb9c24cc9f66566968464",
"sha256:99856d6c98a326abbcc2363827e16bd6044f70f2ef42f453c0bd5440c4ce24e5",
"sha256:aab584725afd10c710b8f1e6e208dbee2d0ad009f57d674cb9d1b3964037275d",
"sha256:af169ba897692e9cd984a81cb0f02e46dacdc07d6cf9fd5c91e81f8efaf93d52",
"sha256:b39b8711578dcfd45fc0140993403b8a81e879ec25d53189f3faa1f006087dca",
"sha256:b3f543ae9d3408549a9900720f18c0194ac0fe810cecda2a584fd4dca2eb3bb8",
"sha256:d0583b75f2e70ec93f100931660328965bb9ff65ae54695fb3fa0a1255daa6f2",
"sha256:dfbbbf0809a3606046a41f8561c3eada9db811be94138f42d9135a5c47e75f6f",
"sha256:e538f2d4a6ffb6edfb303ce70ae7e88629ac6e5581870e66c306d9ad7b564a58",
"sha256:eba51599370c87088d8882ab74f637de0c4f04a6d08a312dce49368ba9ed5c2a",
"sha256:ee4b43f35f5dc15e1fec55ccb53c130adb1d11e8ad8263d68b1284b66a04190d",
"sha256:f2363e5fd81afb650085c6686f2ee3706975c54f331b426800b53531191fdf28",
"sha256:f299c020c6679cb389814a3b81200fe55d428012c5e76da7e722491f5d205990",
"sha256:f72f23bab1848edb7472309e9898603141644faec9fd57a823ea6b4d1c4c8995",
"sha256:fa90bac61c9dc3e1a563e5babb3fd2c0c1c80567e815442ddbe561eadc803b30"
"sha256:0c8cf55261e15590065039696607f6c9c1aeda700ceee40c70478552d323b3ff",
"sha256:13b7d0f2a67eb83c385880489dbb80145e9d344427b4262c49fbf2581677c11c",
"sha256:1f294a15f7723fc0d3b40701ca9b446133ec713eafc1cc6afa7b3d98666ee1ac",
"sha256:239a4a08525c080ff833560171d23b249f7f4d17fcbf9316ef4159f44997616f",
"sha256:2f8d89721834524a813f37fa174bac074ec3d179858e4ad1b7efd4401f8ac45d",
"sha256:2fdc7ccbd6eb6b7df5353012fbed6c3c5d04ceaca0038f75e601060e95345309",
"sha256:34c15ca9248f2e095ef2e93af2d633358c5f048c49fbfddf5fdfc47d5e263736",
"sha256:387545206c56b0315fbadb0431d5129c797f92dc59e276b3ce82db07ac1c6179",
"sha256:43b576c34ef0c1f5a4981163b551a8781896f2a37f71b8655fd20b5af0386abb",
"sha256:57d0a8ce40ce440f96a2c77824ee94bf0d0925e6089df7366c2272ccefcb7941",
"sha256:5a804abc126b33824a44a7aa94f06cd211a18bbf31898ba04bd0924fbe9d282d",
"sha256:67be3ca75012c6e9b109860820a8b6c9a84bfb036fbd1076246b98e56951ca92",
"sha256:6af47f10cfc54c2ba2d825220f180cc1e2d4914d783d6fc0cd93d43d7bc1c78b",
"sha256:6dc998f6de015723196a904045e5a2217f3590b62ea31990672e31fbc5370b41",
"sha256:70d2cef1bf529bff41559be2de9d44d47b002f65e17f43c73ddefc92f32bf00f",
"sha256:7ebc4d34e7620c4f0da7bf162c81978fce0ea820e4fa1e8fc40ee763839805f3",
"sha256:964a7af27379ff4357dad1256d9f215047e70e93009e532d36dcb8909036033d",
"sha256:97806e9ca3651588c1baaebb8d0c5ee3db95430b612db354c199b57378312ee8",
"sha256:9b9bc671626281f6045ad61d93a60f52fd5e8209b1610972cf0ef1bbe6d808e3",
"sha256:9ffdaa5290422ac0f1688cb8adb1b94ca56cee3ad11f29f2ae301df8aecba7d1",
"sha256:a0da79117952a9a41253696ed3e8b560a425197d4e41634a23b1507efe3273f1",
"sha256:a41f87bb93b8048fe866fa9e3d0c51e27fe55149035dcf5f43da4b56732c0a40",
"sha256:aa6fd016e9644406d0a61313e50348c706e911dca29736a3266fc9e28ec4ca6d",
"sha256:ad54ed57bdfa3254d23ae04a4b1ce405954969c1b0550cc2d1d2990e8b439de1",
"sha256:b012d023b4fb59183909b45d7f97fb493ef7a46d2838a5e716e3155081894605",
"sha256:b51b64432eed4c0744241e9ce5c70dcfecac866dff720e746d0a9c82f371dfa7",
"sha256:bbe81def9cf3e46f16ce01d9bfd8bea595e06505e51b7baf45115c77352675fd",
"sha256:c9559138690e1bd4ea6cd0954d22d1e9251e8025ce9ede5d0af0ceae4a401e43",
"sha256:e30506bcb03de8983f78884807e4fd95d8db6e65b69257eea05d13d519b83ac0",
"sha256:e33e86fd65f369f10608b08729c8f1c92ec7e0e485964670b4d2633a4812d36b",
"sha256:e441e8b7d587af0414d25e8d05e27040d78581388eed4c54c30c0c91aad3a379",
"sha256:e8bb9c990ca9027b4214fa543fd4025818dc95f8b7abce79d61dc8a2112b561a",
"sha256:ef43ee91c193f827e49599e824385ec7c7f3cd152d74cb1dfe02cb135f264d83",
"sha256:ef467d86d3cfde8b39ea1b35090208b0447caaabd38405420830f7fd85fbdd56",
"sha256:f89b28772fc2562ed9ad871c865f5320ef761a7fcc188a935e21fe8b31a38ca9",
"sha256:fddbab55a2473f1d3b8833ec6b7ac31e8211b0aa608df5ab09ce07f3727326de"
],
"markers": "python_version >= '3.7'",
"version": "==6.0"
"version": "==6.1"
}
},
"develop": {}

@ -70,10 +70,11 @@ class AddToHomeScreenTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/414970
@Ignore("Failure, more details at: https://bugzilla.mozilla.org/show_bug.cgi?id=1830005")
@SmokeTest
@Test
fun addPrivateBrowsingShortcutTest() {
fun addPrivateBrowsingShortcutFromHomeScreenCFRTest() {
homeScreen {
}.triggerPrivateBrowsingShortcutPrompt {
verifyNoThanksPrivateBrowsingShortcutButton(composeTestRule)

@ -56,9 +56,10 @@ class BrowsingErrorPagesTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326774
@SmokeTest
@Test
fun blockMalwarePageTest() {
fun verifyMalwareWebsiteWarningMessageTest() {
val malwareURl = "http://itisatrap.org/firefox/its-an-attack.html"
navigationToolbar {
@ -67,9 +68,10 @@ class BrowsingErrorPagesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326773
@SmokeTest
@Test
fun blockPhishingPageTest() {
fun verifyPhishingWebsiteWarningMessageTest() {
val phishingURl = "http://itisatrap.org/firefox/its-a-trap.html"
navigationToolbar {
@ -78,9 +80,10 @@ class BrowsingErrorPagesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326772
@SmokeTest
@Test
fun blockUnwantedSoftwarePageTest() {
fun verifyUnwantedSoftwareWebsiteWarningMessageTest() {
val unwantedURl = "http://itisatrap.org/firefox/unwanted.html"
navigationToolbar {
@ -89,9 +92,10 @@ class BrowsingErrorPagesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/329877
@SmokeTest
@Test
fun blockHarmfulPageTest() {
fun verifyHarmfulWebsiteWarningMessageTest() {
val harmfulURl = "https://itisatrap.org/firefox/harmful.html"
navigationToolbar {
@ -100,10 +104,11 @@ class BrowsingErrorPagesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/329882
// Failing with network interruption, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1833874
// This tests the server ERROR_CONNECTION_REFUSED
@Test
fun connectionRefusedErrorMessageTest() {
fun verifyConnectionInterruptedErrorMessageTest() {
val testUrl = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -119,8 +124,9 @@ class BrowsingErrorPagesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/329881
@Test
fun addressNotFoundErrorMessageTest() {
fun verifyAddressNotFoundErrorMessageTest() {
val url = "ww.example.com"
navigationToolbar {
@ -132,8 +138,9 @@ class BrowsingErrorPagesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2140588
@Test
fun noInternetConnectionErrorMessageTest() {
fun verifyNoInternetConnectionErrorMessageTest() {
val url = "www.example.com"
setNetworkEnabled(false)

@ -64,9 +64,10 @@ class CollectionTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/353823
@SmokeTest
@Test
fun createFirstCollectionTest() {
fun createFirstCollectionUsingHomeScreenButtonTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
val secondWebPage = getGenericAsset(mockWebServer, 2)
@ -108,6 +109,7 @@ class CollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343422
@SmokeTest
@Test
fun verifyExpandedCollectionItemsTest() {
@ -158,9 +160,10 @@ class CollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343425
@SmokeTest
@Test
fun openAllTabsInCollectionTest() {
fun openAllTabsFromACollectionTest() {
val firstTestPage = getGenericAsset(mockWebServer, 1)
val secondTestPage = getGenericAsset(mockWebServer, 2)
@ -191,9 +194,10 @@ class CollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343426
@SmokeTest
@Test
fun shareCollectionTest() {
fun shareAllTabsFromACollectionTest() {
val firstWebsite = getGenericAsset(mockWebServer, 1)
val secondWebsite = getGenericAsset(mockWebServer, 2)
val sharingApp = "Gmail"
@ -218,6 +222,7 @@ class CollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343428
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@SmokeTest
@ -239,15 +244,29 @@ class CollectionTest {
selectDeleteCollection(composeTestRule)
}
homeScreen {
verifySnackBarText("Collection deleted")
clickSnackbarButton("UNDO")
verifyCollectionIsDisplayed(collectionName, true)
}
homeScreen {
verifyCollectionIsDisplayed(collectionName)
}.expandCollection(collectionName) {
clickCollectionThreeDotButton(composeTestRule)
selectDeleteCollection(composeTestRule)
}
homeScreen {
verifySnackBarText("Collection deleted")
verifyNoCollectionsText()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2319453
// open a webpage, and add currently opened tab to existing collection
@Test
fun mainMenuSaveToExistingCollection() {
fun saveTabToExistingCollectionFromMainMenuTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
val secondWebPage = getGenericAsset(mockWebServer, 2)
@ -273,8 +292,9 @@ class CollectionTest {
}
}
// Testrail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343423
@Test
fun verifyAddTabButtonOfCollectionMenu() {
fun saveTabToExistingCollectionUsingTheAddTabButtonTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
val secondWebPage = getGenericAsset(mockWebServer, 2)
@ -300,6 +320,7 @@ class CollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343424
@Test
fun renameCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
@ -322,30 +343,32 @@ class CollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/991248
@Test
fun createSecondCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
fun createCollectionUsingSelectTabsButtonTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
val secondWebPage = getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
}.openTabDrawer {
}.openNewTab {
}.submitQuery(secondWebPage.url.toString()) {
}.openTabDrawer {
createCollection(webPage.title, collectionName = firstCollectionName)
verifySnackBarText("Collection saved!")
createCollection(
webPage.title,
collectionName = secondCollectionName,
firstCollection = false,
tabTitles = arrayOf(firstWebPage.title, secondWebPage.title),
collectionName = firstCollectionName,
)
verifySnackBarText("Collection saved!")
}.closeTabDrawer {
}.goToHomescreen {
verifyCollectionIsDisplayed(firstCollectionName)
verifyCollectionIsDisplayed(secondCollectionName)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2319455
@Test
fun removeTabFromCollectionTest() {
fun removeTabFromCollectionUsingTheCloseButtonTest() {
val webPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -360,40 +383,24 @@ class CollectionTest {
}.expandCollection(collectionName) {
verifyTabSavedInCollection(webPage.title, true)
removeTabFromCollection(webPage.title)
verifyTabSavedInCollection(webPage.title, false)
}
homeScreen {
verifyCollectionIsDisplayed(collectionName, false)
}
}
@Test
fun undoTabRemovalFromCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openTabDrawer {
createCollection(webPage.title, collectionName = collectionName)
closeTab()
}
homeScreen {
verifySnackBarText("Collection deleted")
clickSnackbarButton("UNDO")
verifyCollectionIsDisplayed(collectionName)
}.expandCollection(collectionName) {
verifyTabSavedInCollection(webPage.title, true)
removeTabFromCollection(webPage.title)
verifyTabSavedInCollection(webPage.title, false)
}
homeScreen {
verifySnackBarText("Collection deleted")
clickSnackbarButton("UNDO")
verifyCollectionIsDisplayed(collectionName, true)
verifyCollectionIsDisplayed(collectionName, true)
verifyCollectionIsDisplayed(collectionName, false)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/343427
@Test
fun swipeLeftToRemoveTabFromCollectionTest() {
fun removeTabFromCollectionUsingSwipeLeftActionTest() {
val testPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -415,13 +422,21 @@ class CollectionTest {
}
homeScreen {
verifySnackBarText("Collection deleted")
verifySnackBarText("UNDO")
clickSnackbarButton("UNDO")
verifyCollectionIsDisplayed(collectionName)
}.expandCollection(collectionName) {
verifyTabSavedInCollection(testPage.title, true)
swipeTabLeft(testPage.title, composeTestRule)
verifyTabSavedInCollection(testPage.title, false)
}
homeScreen {
verifyCollectionIsDisplayed(collectionName, false)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/991278
@Test
fun swipeRightToRemoveTabFromCollectionTest() {
fun removeTabFromCollectionUsingSwipeRightActionTest() {
val testPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -443,13 +458,21 @@ class CollectionTest {
}
homeScreen {
verifySnackBarText("Collection deleted")
verifySnackBarText("UNDO")
clickSnackbarButton("UNDO")
verifyCollectionIsDisplayed(collectionName)
}.expandCollection(collectionName) {
verifyTabSavedInCollection(testPage.title, true)
swipeTabRight(testPage.title, composeTestRule)
verifyTabSavedInCollection(testPage.title, false)
}
homeScreen {
verifyCollectionIsDisplayed(collectionName, false)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/991276
@Test
fun selectTabOnLongTapTest() {
fun createCollectionByLongPressingOpenTabsTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
val secondWebPage = getGenericAsset(mockWebServer, 2)
@ -479,6 +502,7 @@ class CollectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/344897
@Test
fun navigateBackInCollectionFlowTest() {
val webPage = getGenericAsset(mockWebServer, 1)
@ -510,30 +534,4 @@ class CollectionTest {
verifyMenuButton()
}
}
@SmokeTest
@Test
fun undoDeleteCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openTabDrawer {
createCollection(webPage.title, collectionName = collectionName)
snackBarButtonClick("VIEW")
}
homeScreen {
verifyCollectionIsDisplayed(collectionName)
}.expandCollection(collectionName) {
clickCollectionThreeDotButton(composeTestRule)
selectDeleteCollection(composeTestRule)
}
homeScreen {
verifySnackBarText("Collection deleted")
clickSnackbarButton("UNDO")
verifyCollectionIsDisplayed(collectionName, true)
}
}
}

@ -67,7 +67,7 @@ class ComposeCollectionTest {
@SmokeTest
@Test
fun createFirstCollectionTest() {
fun createFirstCollectionUsingHomeScreenButtonTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
val secondWebPage = getGenericAsset(mockWebServer, 2)
@ -149,7 +149,7 @@ class ComposeCollectionTest {
@SmokeTest
@Test
fun openAllTabsInCollectionTest() {
fun openAllTabsFromACollectionTest() {
val firstTestPage = getGenericAsset(mockWebServer, 1)
val secondTestPage = getGenericAsset(mockWebServer, 2)
@ -183,7 +183,7 @@ class ComposeCollectionTest {
@SmokeTest
@Test
fun shareCollectionTest() {
fun shareAllTabsFromACollectionTest() {
val firstWebsite = getGenericAsset(mockWebServer, 1)
val secondWebsite = getGenericAsset(mockWebServer, 2)
val sharingApp = "Gmail"
@ -229,6 +229,19 @@ class ComposeCollectionTest {
selectDeleteCollection(composeTestRule)
}
homeScreen {
verifySnackBarText("Collection deleted")
clickSnackbarButton("UNDO")
verifyCollectionIsDisplayed(collectionName, true)
}
homeScreen {
verifyCollectionIsDisplayed(collectionName)
}.expandCollection(collectionName) {
clickCollectionThreeDotButton(composeTestRule)
selectDeleteCollection(composeTestRule)
}
homeScreen {
verifySnackBarText("Collection deleted")
verifyNoCollectionsText()
@ -237,7 +250,7 @@ class ComposeCollectionTest {
// open a webpage, and add currently opened tab to existing collection
@Test
fun mainMenuSaveToExistingCollection() {
fun saveTabToExistingCollectionFromMainMenuTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
val secondWebPage = getGenericAsset(mockWebServer, 2)
@ -313,29 +326,29 @@ class ComposeCollectionTest {
}
@Test
fun createSecondCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
fun createCollectionUsingSelectTabsButtonTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
val secondWebPage = getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
}.openComposeTabDrawer(composeTestRule) {
}.openNewTab {
}.submitQuery(secondWebPage.url.toString()) {
}.openComposeTabDrawer(composeTestRule) {
createCollection(webPage.title, collectionName = firstCollectionName)
verifySnackBarText("Collection saved!")
createCollection(
webPage.title,
collectionName = secondCollectionName,
firstCollection = false,
tabTitles = arrayOf(firstWebPage.title, secondWebPage.title),
collectionName = firstCollectionName,
)
verifySnackBarText("Collection saved!")
}.closeTabDrawer {
}.goToHomescreen {
verifyCollectionIsDisplayed(firstCollectionName)
verifyCollectionIsDisplayed(secondCollectionName)
}
}
@Test
fun removeTabFromCollectionTest() {
fun removeTabFromCollectionUsingTheCloseButtonTest() {
val webPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -350,40 +363,23 @@ class ComposeCollectionTest {
}.expandCollection(collectionName) {
verifyTabSavedInCollection(webPage.title, true)
removeTabFromCollection(webPage.title)
verifyTabSavedInCollection(webPage.title, false)
}
homeScreen {
verifyCollectionIsDisplayed(collectionName, false)
}
}
@Test
fun undoTabRemovalFromCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openComposeTabDrawer(composeTestRule) {
createCollection(webPage.title, collectionName = collectionName)
closeTab()
}
homeScreen {
verifySnackBarText("Collection deleted")
clickSnackbarButton("UNDO")
verifyCollectionIsDisplayed(collectionName)
}.expandCollection(collectionName) {
verifyTabSavedInCollection(webPage.title, true)
removeTabFromCollection(webPage.title)
verifyTabSavedInCollection(webPage.title, false)
}
homeScreen {
verifySnackBarText("Collection deleted")
clickSnackbarButton("UNDO")
verifyCollectionIsDisplayed(collectionName, true)
verifyCollectionIsDisplayed(collectionName, true)
verifyCollectionIsDisplayed(collectionName, false)
}
}
@Test
fun swipeLeftToRemoveTabFromCollectionTest() {
fun removeTabFromCollectionUsingSwipeLeftActionTest() {
val testPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -405,13 +401,17 @@ class ComposeCollectionTest {
}
homeScreen {
verifySnackBarText("Collection deleted")
verifySnackBarText("UNDO")
verifyCollectionIsDisplayed(collectionName, false)
clickSnackbarButton("UNDO")
verifyCollectionIsDisplayed(collectionName)
}.expandCollection(collectionName) {
verifyTabSavedInCollection(testPage.title, true)
swipeTabLeft(testPage.title, composeTestRule)
verifyTabSavedInCollection(testPage.title, false)
}
}
@Test
fun swipeRightToRemoveTabFromCollectionTest() {
fun removeTabFromCollectionUsingSwipeRightActionTest() {
val testPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -433,13 +433,17 @@ class ComposeCollectionTest {
}
homeScreen {
verifySnackBarText("Collection deleted")
verifySnackBarText("UNDO")
verifyCollectionIsDisplayed(collectionName, false)
clickSnackbarButton("UNDO")
verifyCollectionIsDisplayed(collectionName)
}.expandCollection(collectionName) {
verifyTabSavedInCollection(testPage.title, true)
swipeTabRight(testPage.title, composeTestRule)
verifyTabSavedInCollection(testPage.title, false)
}
}
@Test
fun selectTabOnLongTapTest() {
fun createCollectionByLongPressingOpenTabsTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
val secondWebPage = getGenericAsset(mockWebServer, 2)
@ -501,30 +505,4 @@ class ComposeCollectionTest {
verifyMenuButton()
}
}
@SmokeTest
@Test
fun undoDeleteCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openComposeTabDrawer(composeTestRule) {
createCollection(webPage.title, collectionName = collectionName)
clickSnackbarButton("VIEW")
}
homeScreen {
verifyCollectionIsDisplayed(collectionName)
}.expandCollection(collectionName) {
clickCollectionThreeDotButton(composeTestRule)
selectDeleteCollection(composeTestRule)
}
homeScreen {
verifySnackBarText("Collection deleted")
clickSnackbarButton("UNDO")
verifyCollectionIsDisplayed(collectionName, true)
}
}
}

@ -76,7 +76,7 @@ class ComposeContextMenusTest {
}
@Test
fun verifyContextOpenLinkNewTab() {
fun verifyOpenLinkNewTabContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val genericURL =
@ -99,7 +99,7 @@ class ComposeContextMenusTest {
}
@Test
fun verifyContextOpenLinkPrivateTab() {
fun verifyOpenLinkInNewPrivateTabContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val genericURL =
@ -121,7 +121,7 @@ class ComposeContextMenusTest {
}
@Test
fun verifyContextCopyLink() {
fun verifyCopyLinkContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val genericURL =
@ -141,29 +141,7 @@ class ComposeContextMenusTest {
}
@Test
fun verifyContextCopyLinkNotDisplayedAfterApplied() {
val pageLinks = TestAssetHelper.getGenericAsset(mockWebServer, 4)
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 3)
navigationToolbar {
}.enterURLAndEnterToBrowser(pageLinks.url) {
longClickPageObject(itemWithText("Link 3"))
verifyContextMenuForLocalHostLinks(genericURL.url)
clickContextMenuItem("Copy link")
verifySnackBarText("Link copied to clipboard")
}.openNavigationToolbar {
}.visitLinkFromClipboard {
verifyUrl(genericURL.url.toString())
}.openComposeTabDrawer(composeTestRule) {
}.openNewTab {
}
navigationToolbar {
verifyClipboardSuggestionsAreDisplayed(shouldBeDisplayed = false)
}
}
@Test
fun verifyContextShareLink() {
fun verifyShareLinkContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val genericURL =
@ -182,7 +160,7 @@ class ComposeContextMenusTest {
}
@Test
fun verifyContextOpenImageNewTab() {
fun verifyOpenImageNewTabContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val imageResource =
@ -201,7 +179,7 @@ class ComposeContextMenusTest {
}
@Test
fun verifyContextCopyImageLocation() {
fun verifyCopyImageLocationContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val imageResource =
@ -221,7 +199,7 @@ class ComposeContextMenusTest {
}
@Test
fun verifyContextSaveImage() {
fun verifySaveImageContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val imageResource =
@ -244,7 +222,7 @@ class ComposeContextMenusTest {
}
@Test
fun verifyContextMixedVariations() {
fun verifyContextMenuLinkVariationsTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val genericURL =
@ -267,7 +245,7 @@ class ComposeContextMenusTest {
}
@Test
fun verifyContextMixedVariationsInPDFTest() {
fun verifyPDFContextMenuLinkVariationsTest() {
val genericURL =
TestAssetHelper.getGenericAsset(mockWebServer, 3)
@ -287,7 +265,7 @@ class ComposeContextMenusTest {
}
@Test
fun verifyContextOpenLinkInAppTest() {
fun verifyOpenLinkInAppContextMenuOptionTest() {
val defaultWebPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
navigationToolbar {

@ -417,4 +417,24 @@ class ComposeHistoryTest {
verifySuggestionsAreNotDisplayed(activityTestRule, thirdWebPage.url.toString())
}
}
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@SmokeTest
@Test
fun noHistoryInPrivateBrowsingTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openHistory {
verifyEmptyHistoryView()
}
}
}

@ -88,7 +88,7 @@ class ComposeHomeScreenTest {
homeScreen { }.togglePrivateBrowsingMode()
homeScreen {
verifyPrivateBrowsingHomeScreen()
verifyPrivateBrowsingHomeScreenItems()
}.openCommonMythsLink {
verifyUrl("common-myths-about-private-browsing")
}

@ -69,9 +69,10 @@ class ComposeMediaNotificationTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1347033
@SmokeTest
@Test
fun videoPlaybackSystemNotificationTest() {
fun verifyVideoPlaybackSystemNotificationTest() {
val videoTestPage = TestAssetHelper.getVideoPageAsset(mockWebServer)
navigationToolbar {
@ -103,9 +104,10 @@ class ComposeMediaNotificationTest {
mDevice.pressBack()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2316010
@SmokeTest
@Test
fun audioPlaybackSystemNotificationTest() {
fun verifyAudioPlaybackSystemNotificationTest() {
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
navigationToolbar {
@ -137,6 +139,7 @@ class ComposeMediaNotificationTest {
mDevice.pressBack()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903595
@Test
fun mediaSystemNotificationInPrivateModeTest() {
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)

@ -80,7 +80,7 @@ class ComposeSearchTest {
}
@Test
fun searchBarItemsTest() {
fun verifySearchBarItemsTest() {
navigationToolbar {
verifyDefaultSearchEngine("Google")
verifySearchBarPlaceholder("Search or enter address")
@ -96,7 +96,7 @@ class ComposeSearchTest {
}
@Test
fun searchSelectorMenuItemsTest() {
fun verifySearchSelectorMenuItemsTest() {
homeScreen {
}.openSearch {
verifySearchView()
@ -110,7 +110,7 @@ class ComposeSearchTest {
}
@Test
fun searchPlaceholderForDefaultEnginesTest() {
fun verifySearchPlaceholderForGeneralDefaultSearchEnginesTest() {
generalEnginesList.forEach {
homeScreen {
}.openSearch {
@ -127,7 +127,7 @@ class ComposeSearchTest {
}
@Test
fun searchPlaceholderForOtherGeneralSearchEnginesTest() {
fun verifySearchPlaceholderForNotDefaultGeneralSearchEnginesTest() {
val generalEnginesList = listOf("DuckDuckGo", "Bing")
generalEnginesList.forEach {
@ -141,7 +141,7 @@ class ComposeSearchTest {
}
@Test
fun searchPlaceholderForTopicSearchEngineTest() {
fun verifySearchPlaceholderForTopicSpecificSearchEnginesTest() {
val topicEnginesList = listOf("Amazon.com", "Wikipedia", "eBay")
topicEnginesList.forEach {
@ -156,7 +156,7 @@ class ComposeSearchTest {
@SmokeTest
@Test
fun scanButtonDenyPermissionTest() {
fun verifyQRScanningCameraAccessDialogTest() {
val cameraManager = TestHelper.appContext.getSystemService(Context.CAMERA_SERVICE) as CameraManager
Assume.assumeTrue(cameraManager.cameraIdList.isNotEmpty())
@ -177,7 +177,7 @@ class ComposeSearchTest {
@SmokeTest
@Test
fun scanButtonAllowPermissionTest() {
fun scanQRCodeToOpenAWebpageTest() {
val cameraManager = TestHelper.appContext.getSystemService(Context.CAMERA_SERVICE) as CameraManager
Assume.assumeTrue(cameraManager.cameraIdList.isNotEmpty())
@ -190,7 +190,7 @@ class ComposeSearchTest {
}
@Test
fun scanButtonAvailableOnlyForGeneralSearchEnginesTest() {
fun verifyScanButtonAvailableOnlyForGeneralSearchEnginesTest() {
generalEnginesList.forEach {
homeScreen {
}.openSearch {
@ -213,7 +213,7 @@ class ComposeSearchTest {
// Verifies a temporary change of search engine from the Search shortcut menu
@SmokeTest
@Test
fun selectSearchEnginesShortcutTest() {
fun searchEnginesCanBeChangedTemporarilyFromSearchSelectorMenuTest() {
val enginesList = listOf("DuckDuckGo", "Google", "Amazon.com", "Wikipedia", "Bing", "eBay")
enginesList.forEach {
@ -230,7 +230,7 @@ class ComposeSearchTest {
}
@Test
fun accessSearchSettingFromSearchSelectorMenuTest() {
fun defaultSearchEnginesCanBeSetFromSearchSelectorMenuTest() {
searchScreen {
clickSearchSelectorButton()
}.clickSearchEngineSettings {
@ -247,7 +247,7 @@ class ComposeSearchTest {
}
@Test
fun clearSearchTest() {
fun verifyClearSearchButtonTest() {
homeScreen {
}.openSearch {
typeSearch(queryString)
@ -259,7 +259,7 @@ class ComposeSearchTest {
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@SmokeTest
@Test
fun searchGroupShowsInRecentlyVisitedTest() {
fun searchResultsOpenedInNewTabsGenerateSearchGroupsTest() {
val searchEngineName = "TestSearchEngine"
// setting our custom mockWebServer search URL
setCustomSearchEngine(searchMockServer, searchEngineName)
@ -286,7 +286,7 @@ class ComposeSearchTest {
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun verifySearchGroupHistoryWithNoDuplicatesTest() {
fun verifyAPageIsAddedToASearchGroupOnlyOnceTest() {
val firstPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 1).url
val secondPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 2).url
val originPageUrl =
@ -331,7 +331,7 @@ class ComposeSearchTest {
@Ignore("Failing due to known bug, see https://github.com/mozilla-mobile/fenix/issues/23818")
@Test
fun searchGroupGeneratedInTheSameTabTest() {
fun searchGroupIsGeneratedWhenNavigatingInTheSameTabTest() {
// setting our custom mockWebServer search URL
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
@ -354,7 +354,7 @@ class ComposeSearchTest {
@SmokeTest
@Test
fun noSearchGroupFromPrivateBrowsingTest() {
fun searchGroupIsNotGeneratedForLinksOpenedInPrivateTabsTest() {
// setting our custom mockWebServer search URL
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
@ -386,7 +386,7 @@ class ComposeSearchTest {
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@SmokeTest
@Test
fun deleteItemsFromSearchGroupHistoryTest() {
fun deleteIndividualHistoryItemsFromSearchGroupTest() {
val firstPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 1).url
val secondPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 2).url
// setting our custom mockWebServer search URL
@ -427,7 +427,7 @@ class ComposeSearchTest {
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun deleteSearchGroupFromHistoryTest() {
fun deleteSearchGroupFromHomeScreenTest() {
val firstPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 1).url
// setting our custom mockWebServer search URL
val searchEngineName = "TestSearchEngine"
@ -467,7 +467,7 @@ class ComposeSearchTest {
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun reopenTabsFromSearchGroupTest() {
fun openAPageFromHomeScreenSearchGroupTest() {
val firstPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 1).url
val secondPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 2).url
@ -515,7 +515,7 @@ class ComposeSearchTest {
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun sharePageFromASearchGroupTest() {
fun shareAPageFromHomeScreenSearchGroupTest() {
val firstPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 1).url
// setting our custom mockWebServer search URL
val searchEngineName = "TestSearchEngine"
@ -590,7 +590,13 @@ class ComposeSearchTest {
}.openThreeDotMenu {
}.openHistory {
// Full URL no longer visible in the nav bar, so we'll check the history record
verifyHistoryItemExists(shouldExist = true, Constants.searchEngineCodes["Bing"]!!)
// A search group is sometimes created when searching with Bing (probably redirects)
try {
verifyHistoryItemExists(shouldExist = true, Constants.searchEngineCodes["Bing"]!!)
} catch (e: AssertionError) {
openSearchGroup(queryString)
verifyHistoryItemExists(shouldExist = true, Constants.searchEngineCodes["Bing"]!!)
}
}
}
@ -622,9 +628,10 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1850517
// Test that verifies the Firefox Suggest results in a general search context
@Test
fun firefoxSuggestHeaderForBrowsingDataSuggestionsTest() {
fun verifyFirefoxSuggestHeaderForBrowsingDataSuggestionsTest() {
val firstPage = TestAssetHelper.getGenericAsset(searchMockServer, 1)
val secondPage = TestAssetHelper.getGenericAsset(searchMockServer, 2)
@ -646,8 +653,9 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154197
@Test
fun verifySearchTabsItemsTest() {
fun verifyTabsSearchItemsTest() {
navigationToolbar {
}.clickUrlbar {
clickSearchSelectorButton()
@ -659,8 +667,9 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154198
@Test
fun verifySearchTabsWithoutOpenTabsTest() {
fun verifyTabsSearchWithoutOpenTabsTest() {
navigationToolbar {
}.clickUrlbar {
clickSearchSelectorButton()
@ -672,9 +681,10 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154199
@SmokeTest
@Test
fun verifySearchTabsWithOpenTabsTest() {
fun verifyTabsSearchWithOpenTabsTest() {
val firstPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 1)
val secondPageUrl = TestAssetHelper.getGenericAsset(searchMockServer, 2)
@ -707,8 +717,9 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154203
@Test
fun verifySearchForBookmarksUITest() {
fun verifyBookmarksSearchItemsTest() {
navigationToolbar {
}.clickSearchSelectorButton {
selectTemporarySearchMethod("Bookmarks")
@ -719,8 +730,9 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154204
@Test
fun bookmarkSearchWithNoBookmarksTest() {
fun verifyBookmarkSearchWithNoBookmarksTest() {
navigationToolbar {
}.clickSearchSelectorButton {
selectTemporarySearchMethod("Bookmarks")
@ -729,8 +741,9 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154206
@Test
fun bookmarkSearchWhenBookmarksExistTest() {
fun verifyBookmarksSearchForBookmarkedItemsTest() {
createBookmarkItem(url = "https://bookmarktest1.com", title = "Test1", position = 1u)
createBookmarkItem(url = "https://bookmarktest2.com", title = "Test2", position = 2u)
@ -756,8 +769,9 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154212
@Test
fun verifySearchHistoryItemsTest() {
fun verifyHistorySearchItemsTest() {
navigationToolbar {
}.clickUrlbar {
clickSearchSelectorButton()
@ -769,8 +783,9 @@ class ComposeSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154213
@Test
fun verifySearchHistoryWithoutBrowsingDataTest() {
fun verifyHistorySearchWithoutBrowsingHistoryTest() {
navigationToolbar {
}.clickUrlbar {
clickSearchSelectorButton()

@ -1,238 +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/. */
@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)
}
}
}

@ -8,14 +8,18 @@ import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.google.android.material.bottomsheet.BottomSheetBehavior
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.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
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
@ -24,6 +28,7 @@ import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.verifyKeyboardVisibility
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.notificationShade
@ -48,6 +53,7 @@ import org.mozilla.fenix.ui.robots.notificationShade
class ComposeTabbedBrowsingTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
private lateinit var browserStore: BrowserStore
@get:Rule(order = 0)
val composeTestRule =
@ -64,6 +70,10 @@ class ComposeTabbedBrowsingTest {
@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 = composeTestRule.activity.components.core.store
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
@ -76,52 +86,7 @@ class ComposeTabbedBrowsingTest {
mockWebServer.shutdown()
}
@Test
fun openNewTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
verifyTabCounter("1")
}.openComposeTabDrawer(composeTestRule) {
verifyNormalBrowsingButtonIsSelected()
verifyExistingOpenTabs("Test_Page_1")
closeTab()
}
homeScreen {
}.openComposeTabDrawer(composeTestRule) {
verifyNoOpenTabsInNormalBrowsing()
}.openNewTab {
}.submitQuery(defaultWebPage.url.toString()) {
verifyPageContent(defaultWebPage.content)
verifyTabCounter("1")
}.openComposeTabDrawer(composeTestRule) {
verifyNormalBrowsingButtonIsSelected()
verifyExistingOpenTabs("Test_Page_1")
}
}
@Test
fun openNewPrivateTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
verifyTabCounter("1")
}.openComposeTabDrawer(composeTestRule) {
verifyPrivateTabsList()
verifyPrivateBrowsingButtonIsSelected()
}.toggleToNormalTabs {
verifyNoOpenTabsInNormalBrowsing()
}.toggleToPrivateTabs {
verifyPrivateTabsList()
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903599
@Test
fun closeAllTabsTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -153,8 +118,9 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903604
@Test
fun closeTabTest() {
fun closingTabsMethodsTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -162,6 +128,13 @@ class ComposeTabbedBrowsingTest {
}.openComposeTabDrawer(composeTestRule) {
verifyExistingOpenTabs("Test_Page_1")
closeTab()
verifySnackBarText("Tab closed")
clickSnackbarButton("UNDO")
}
browserScreen {
verifyTabCounter("1")
}.openComposeTabDrawer(composeTestRule) {
closeTab()
}
homeScreen {
verifyTabCounter("0")
@ -184,42 +157,23 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903591
@Test
fun verifyUndoSnackBarTest() {
// disabling these features because they interfere with the snackbar visibility
composeTestRule.activityRule.applySettingsExceptions {
it.isPocketEnabled = false
it.isRecentTabsFeatureEnabled = false
it.isRecentlyVisitedFeatureEnabled = false
}
fun closingPrivateTabsMethodsTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen { }.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openComposeTabDrawer(composeTestRule) {
verifyExistingOpenTabs("Test_Page_1")
closeTab()
verifySnackBarText("Tab closed")
verifySnackBarText("Private tab closed")
clickSnackbarButton("UNDO")
}
browserScreen {
verifyTabCounter("1")
}.openComposeTabDrawer(composeTestRule) {
verifyExistingOpenTabs("Test_Page_1")
}
}
@Test
fun closePrivateTabTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen { }.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openComposeTabDrawer(composeTestRule) {
verifyExistingOpenTabs("Test_Page_1")
closeTab()
}
homeScreen {
@ -229,6 +183,7 @@ class ComposeTabbedBrowsingTest {
}.openComposeTabDrawer(composeTestRule) {
verifyExistingOpenTabs("Test_Page_1")
swipeTabRight("Test_Page_1")
verifySnackBarText("Private tab closed")
}
homeScreen {
verifyTabCounter("0")
@ -237,39 +192,37 @@ class ComposeTabbedBrowsingTest {
}.openComposeTabDrawer(composeTestRule) {
verifyExistingOpenTabs("Test_Page_1")
swipeTabLeft("Test_Page_1")
verifySnackBarText("Private tab closed")
}
homeScreen {
verifyTabCounter("0")
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903606
@SmokeTest
@Test
fun verifyPrivateTabUndoSnackBarTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
fun tabMediaControlButtonTest() {
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
homeScreen { }.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
verifyPageContent(genericURL.content)
}.openComposeTabDrawer(composeTestRule) {
verifyExistingOpenTabs("Test_Page_1")
closeTab()
verifySnackBarText("Private tab closed")
clickSnackbarButton("UNDO")
}
browserScreen {
verifyPageContent(genericURL.content)
verifyTabCounter("1")
}.enterURLAndEnterToBrowser(audioTestPage.url) {
mDevice.waitForIdle()
clickPageObject(MatcherHelper.itemWithText("Play"))
assertPlaybackState(browserStore, MediaSession.PlaybackState.PLAYING)
}.openComposeTabDrawer(composeTestRule) {
verifyExistingOpenTabs("Test_Page_1")
verifyPrivateBrowsingButtonIsSelected()
verifyTabMediaControlButtonState("Pause")
clickTabMediaControlButton("Pause")
verifyTabMediaControlButtonState("Play")
}.openTab(audioTestPage.title) {
assertPlaybackState(browserStore, MediaSession.PlaybackState.PAUSED)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903592
@SmokeTest
@Test
fun closePrivateTabsNotificationTest() {
fun verifyCloseAllPrivateTabsNotificationTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
@ -310,6 +263,7 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903600
@Test
fun verifyEmptyTabTray() {
homeScreen {
@ -326,8 +280,9 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903585
@Test
fun emptyTabsTrayViewPrivateBrowsingTest() {
fun verifyEmptyPrivateTabsTrayTest() {
homeScreen {
}.openComposeTabDrawer(composeTestRule) {
}.toggleToPrivateTabs {
@ -343,8 +298,9 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903601
@Test
fun verifyOpenTabDetails() {
fun verifyTabsTrayWithOpenTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -366,29 +322,57 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903587
@SmokeTest
@Test
fun verifyPrivateTabsTrayWithOpenTabTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.openComposeTabDrawer(composeTestRule) {
}.toggleToPrivateTabs {
}.openNewTab {
}.submitQuery(website.url.toString()) {
}.openComposeTabDrawer(composeTestRule) {
verifyNormalBrowsingButtonIsSelected(false)
verifyPrivateBrowsingButtonIsSelected(true)
verifySyncedTabsButtonIsSelected(false)
verifyThreeDotButton()
verifyNormalTabCounter()
verifyPrivateTabsList()
verifyExistingOpenTabs(website.title)
verifyTabCloseButton()
verifyTabThumbnail()
verifyFab()
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/927314
@Test
fun verifyContextMenuShortcuts() {
fun tabsCounterShortcutMenuTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
verifyTabButtonShortcutMenuItems()
}.closeTabFromShortcutsMenu {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewPrivateTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
}.dismissSearchBar {
verifyCommonMythsLink()
verifyNavigationToolbar()
verifyPrivateBrowsingHomeScreenItems()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openTabFromShortcutsMenu {
}.openNewTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
@ -398,6 +382,43 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/927314
@Test
fun privateTabsCounterShortcutMenuTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {}.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
verifyTabButtonShortcutMenuItems()
}.closeTabFromShortcutsMenu {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewPrivateTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
}.dismissSearchBar {
verifyCommonMythsLink()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
}.dismissSearchBar {
// Verify normal browsing homescreen
verifyExistingTopSitesList()
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/1046683
@Test
fun verifySyncedTabsWhenUserIsNotSignedInTest() {
navigationToolbar {
@ -411,6 +432,41 @@ class ComposeTabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903598
@SmokeTest
@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(composeTestRule) {
}.openNewTab {
}.submitQuery(secondWebsite.url.toString()) {
verifyPageContent(secondWebsite.content)
}.openComposeTabDrawer(composeTestRule) {
verifyExistingOpenTabs("Test_Page_1")
verifyExistingOpenTabs("Test_Page_2")
}.openThreeDotMenu {
verifyShareAllTabsButton()
}.clickShareAllTabsButton {
verifyShareTabsOverlay(firstWebsiteTitle, secondWebsiteTitle)
verifySharingWithSelectedApp(
sharingApp,
sharedUrlsString,
"$firstWebsiteTitle, $secondWebsiteTitle",
)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/526244
@Test
fun privateModeStaysAsDefaultAfterRestartTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -424,13 +480,14 @@ class ComposeTabbedBrowsingTest {
restartApp(composeTestRule.activityRule)
homeScreen {
verifyPrivateBrowsingHomeScreen()
verifyPrivateBrowsingHomeScreenItems()
}.openComposeTabDrawer(composeTestRule) {
}.toggleToNormalTabs {
verifyExistingOpenTabs(defaultWebPage.title)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2228470
@SmokeTest
@Test
fun privateTabsDoNotPersistAfterClosingAppTest() {
@ -449,7 +506,7 @@ class ComposeTabbedBrowsingTest {
closeApp(composeTestRule.activityRule)
restartApp(composeTestRule.activityRule)
homeScreen {
verifyPrivateBrowsingHomeScreen()
verifyPrivateBrowsingHomeScreenItems()
}.openComposeTabDrawer(composeTestRule) {
verifyNoOpenTabsInPrivateBrowsing()
}

@ -62,7 +62,7 @@ class ComposeTopSitesTest {
@SmokeTest
@Test
fun verifyAddToFirefoxHome() {
fun addAWebsiteAsATopSiteTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -79,7 +79,7 @@ class ComposeTopSitesTest {
}
@Test
fun verifyOpenTopSiteNormalTab() {
fun openTopSiteInANewTabTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -106,7 +106,7 @@ class ComposeTopSitesTest {
}
@Test
fun verifyOpenTopSitePrivateTab() {
fun openTopSiteInANewPrivateTabTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -127,7 +127,7 @@ class ComposeTopSitesTest {
}
@Test
fun verifyRenameTopSite() {
fun renameATopSiteTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
val newPageTitle = generateRandomString(5)
@ -151,7 +151,7 @@ class ComposeTopSitesTest {
}
@Test
fun verifyRemoveTopSite() {
fun removeTopSiteUsingMenuButtonTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -167,34 +167,17 @@ class ComposeTopSitesTest {
}.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()
clickSnackbarButton("UNDO")
verifyExistingTopSiteItem(defaultWebPage.title)
}.openContextMenuOnTopSitesWithTitle(defaultWebPage.title) {
verifyTopSiteContextMenuItems()
}.removeTopSite {
clickSnackbarButton("UNDO")
verifyExistingTopSiteItem(defaultWebPage.title)
verifyNotExistingTopSiteItem(defaultWebPage.title)
}
}
@Test
fun verifyRemoveTopSiteFromMainMenu() {
fun removeTopSiteFromMainMenuTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -218,7 +201,7 @@ class ComposeTopSitesTest {
// Expected for en-us defaults
@Test
fun verifyDefaultTopSitesList() {
fun verifyENLocalesDefaultTopSitesListTest() {
homeScreenWithComposeTopSites(composeTestRule) {
verifyExistingTopSitesList()
val topSitesTitles = arrayListOf("Google", "Top Articles", "Wikipedia")

@ -10,7 +10,6 @@ import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.ext.settings
@ -70,8 +69,9 @@ class ContextMenusTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243837
@Test
fun verifyContextOpenLinkNewTab() {
fun verifyOpenLinkNewTabContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val genericURL =
@ -93,8 +93,9 @@ class ContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/244655
@Test
fun verifyContextOpenLinkPrivateTab() {
fun verifyOpenLinkInNewPrivateTabContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val genericURL =
@ -115,8 +116,9 @@ class ContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243832
@Test
fun verifyContextCopyLink() {
fun verifyCopyLinkContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val genericURL =
@ -135,31 +137,9 @@ class ContextMenusTest {
}
}
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1807268")
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243838
@Test
fun verifyContextCopyLinkNotDisplayedAfterApplied() {
val pageLinks = TestAssetHelper.getGenericAsset(mockWebServer, 4)
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 3)
navigationToolbar {
}.enterURLAndEnterToBrowser(pageLinks.url) {
longClickPageObject(itemWithText("Link 3"))
verifyContextMenuForLocalHostLinks(genericURL.url)
clickContextMenuItem("Copy link")
verifySnackBarText("Link copied to clipboard")
}.openNavigationToolbar {
}.visitLinkFromClipboard {
verifyUrl(genericURL.url.toString())
}.openTabDrawer {
}.openNewTab {
}
navigationToolbar {
verifyClipboardSuggestionsAreDisplayed(shouldBeDisplayed = false)
}
}
@Test
fun verifyContextShareLink() {
fun verifyShareLinkContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val genericURL =
@ -177,8 +157,9 @@ class ContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243833
@Test
fun verifyContextOpenImageNewTab() {
fun verifyOpenImageNewTabContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val imageResource =
@ -196,8 +177,9 @@ class ContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243834
@Test
fun verifyContextCopyImageLocation() {
fun verifyCopyImageLocationContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val imageResource =
@ -216,8 +198,9 @@ class ContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243835
@Test
fun verifyContextSaveImage() {
fun verifySaveImageContextMenuOptionTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val imageResource =
@ -239,8 +222,9 @@ class ContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/352050
@Test
fun verifyContextMixedVariations() {
fun verifyContextMenuLinkVariationsTest() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
val genericURL =
@ -262,8 +246,9 @@ class ContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2333840
@Test
fun verifyContextMixedVariationsInPDFTest() {
fun verifyPDFContextMenuLinkVariationsTest() {
val genericURL =
TestAssetHelper.getGenericAsset(mockWebServer, 3)
@ -282,8 +267,9 @@ class ContextMenusTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/832094
@Test
fun verifyContextOpenLinkInAppTest() {
fun verifyOpenLinkInAppContextMenuOptionTest() {
val defaultWebPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
navigationToolbar {

@ -54,8 +54,9 @@ class CrashReportingTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/308906
@Test
fun closeTabCrashedReporterTest() {
fun closeTabFromCrashedTabReporterTest() {
homeScreen {
}.openNavigationToolbar {
}.openTabCrashReporter {
@ -65,9 +66,10 @@ class CrashReportingTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2336134
@Ignore("Test failure caused by: https://github.com/mozilla-mobile/fenix/issues/19964")
@Test
fun restoreTabCrashedReporterTest() {
fun restoreTabFromTabCrashedReporterTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
@ -81,6 +83,7 @@ class CrashReportingTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1681928
@SmokeTest
@Test
fun useAppWhileTabIsCrashedTest() {
@ -110,35 +113,4 @@ class CrashReportingTest {
verifySettingsButton()
}
}
@SmokeTest
@Test
fun privateBrowsingUseAppWhileTabIsCrashedTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
homeScreen {
togglePrivateBrowsingModeOnOff()
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
mDevice.waitForIdle()
}.openTabDrawer {
}.openNewTab {
}.submitQuery(secondWebPage.url.toString()) {
waitForPageToLoad()
}
navigationToolbar {
}.openTabCrashReporter {
verifyPageContent(tabCrashMessage)
}.openTabDrawer {
verifyExistingOpenTabs(firstWebPage.title)
verifyExistingOpenTabs(secondWebPage.title)
}.closeTabDrawer {
}.goToHomescreen {
verifyCommonMythsLink()
}.openThreeDotMenu {
verifySettingsButton()
}
}
}

@ -88,7 +88,7 @@ class CreditCardAutofillTest {
}
navigationToolbar {
}.enterURLAndEnterToBrowser(creditCardFormPage.url) {
clickPageObject(itemWithResId("cardNumber"))
clickCreditCardNumberTextBox()
clickPageObject(itemWithResId("$packageName:id/select_credit_card_header"))
clickPageObject(
itemWithResIdContainingText(
@ -200,7 +200,7 @@ class CreditCardAutofillTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(creditCardFormPage.url) {
clickPageObject(itemWithResId("cardNumber"))
clickCreditCardNumberTextBox()
clickPageObject(itemWithResId("$packageName:id/select_credit_card_header"))
}.clickManageCreditCardsButton {
}.goBackToBrowser {
@ -231,7 +231,7 @@ class CreditCardAutofillTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(creditCardFormPage.url) {
clickPageObject(itemWithResId("cardNumber"))
clickCreditCardNumberTextBox()
verifySelectCreditCardPromptExists(true)
}.openThreeDotMenu {
}.openSettings {
@ -244,7 +244,7 @@ class CreditCardAutofillTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(creditCardFormPage.url) {
clickPageObject(itemWithResId("cardNumber"))
clickCreditCardNumberTextBox()
verifySelectCreditCardPromptExists(false)
}
}
@ -321,7 +321,7 @@ class CreditCardAutofillTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(creditCardFormPage.url) {
clickPageObject(itemWithResId("cardNumber"))
clickCreditCardNumberTextBox()
clickPageObject(itemWithResId("$packageName:id/select_credit_card_header"))
clickPageObject(
itemWithResIdContainingText(
@ -408,7 +408,7 @@ class CreditCardAutofillTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(creditCardFormPage.url) {
clickPageObject(itemWithResId("cardNumber"))
clickCreditCardNumberTextBox()
clickPageObject(itemWithResId("$packageName:id/select_credit_card_header"))
verifyCreditCardSuggestion(
MockCreditCard1.MOCK_LAST_CARD_DIGITS,
@ -498,7 +498,7 @@ class CreditCardAutofillTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(creditCardFormPage.url) {
clickPageObject(itemWithResId("cardNumber"))
clickCreditCardNumberTextBox()
clickPageObject(itemWithResId("$packageName:id/select_credit_card_header"))
clickPageObject(
itemWithResIdContainingText(
@ -549,7 +549,7 @@ class CreditCardAutofillTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(creditCardFormPage.url) {
clickPageObject(itemWithResId("cardNumber"))
clickCreditCardNumberTextBox()
clickPageObject(itemWithResId("$packageName:id/select_credit_card_header"))
clickPageObject(
itemWithResIdContainingText(

@ -21,7 +21,6 @@ import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.FeatureSettingsHelperDelegate
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper
@ -33,7 +32,6 @@ import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.customTabScreen
import org.mozilla.fenix.ui.robots.enhancedTrackingProtection
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.longClickPageObject
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.notificationShade
import org.mozilla.fenix.ui.robots.openEditURLView
@ -78,29 +76,10 @@ class CustomTabsTest {
featureSettingsHelper.resetAllFeatureFlags()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/249659
@SmokeTest
@Test
fun customTabsOpenExternalLinkTest() {
val externalLinkURL = "https://mozilla-mobile.github.io/testapp/downloads"
intentReceiverActivityTestRule.launchActivity(
createCustomTabIntent(
externalLinksPWAPage.toUri().toString(),
customMenuItem,
),
)
customTabScreen {
waitForPageToLoad()
clickPageObject(itemContainingText("External link"))
waitForPageToLoad()
verifyCustomTabToolbarTitle(externalLinkURL)
}
}
@SmokeTest
@Test
fun customTabsSaveLoginTest() {
fun verifyLoginSaveInCustomTabTest() {
intentReceiverActivityTestRule.launchActivity(
createCustomTabIntent(
loginPage.toUri().toString(),
@ -131,9 +110,9 @@ class CustomTabsTest {
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2334762
@Test
fun customTabCopyToolbarUrlTest() {
fun copyCustomTabToolbarUrlTest() {
val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
intentReceiverActivityTestRule.launchActivity(
@ -161,33 +140,11 @@ class CustomTabsTest {
}
}
@SmokeTest
@Test
fun customTabShareTextTest() {
val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
intentReceiverActivityTestRule.launchActivity(
createCustomTabIntent(
customTabPage.url.toString(),
customMenuItem,
),
)
customTabScreen {
waitForPageToLoad()
}
browserScreen {
longClickPageObject(itemContainingText("content"))
}.clickShareSelectedText {
verifyAndroidShareLayout()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2334761
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1807289")
@SmokeTest
@Test
fun customTabDownloadTest() {
fun verifyDownloadInACustomTabTest() {
val customTabPage = "https://storage.googleapis.com/mobile_test_assets/test_app/downloads.html"
val downloadFile = "web_icon.png"
@ -214,10 +171,11 @@ class CustomTabsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/249644
// Verifies the main menu of a custom tab with a custom menu item
@SmokeTest
@Test
fun customTabMenuItemsTest() {
fun verifyCustomTabMenuItemsTest() {
val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
intentReceiverActivityTestRule.launchActivity(
@ -241,9 +199,11 @@ class CustomTabsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/249645
// The test opens a link in a custom tab then sends it to the browser
@SmokeTest
@Test
fun openCustomTabInBrowserTest() {
fun openCustomTabInFirefoxTest() {
val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
intentReceiverActivityTestRule.launchActivity(
@ -260,8 +220,9 @@ class CustomTabsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2239548
@Test
fun shareCustomTabTest() {
fun shareCustomTabUsingToolbarButtonTest() {
val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
intentReceiverActivityTestRule.launchActivity(
@ -276,8 +237,9 @@ class CustomTabsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/249643
@Test
fun verifyCustomTabViewTest() {
fun verifyCustomTabViewItemsTest() {
val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
intentReceiverActivityTestRule.launchActivity(
@ -302,8 +264,9 @@ class CustomTabsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2239544
@Test
fun verifyPdfCustomTabViewTest() {
fun verifyPDFViewerInACustomTabTest() {
val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 3)
val pdfFormResource = TestAssetHelper.getPdfFormAsset(mockWebServer)
@ -331,8 +294,9 @@ class CustomTabsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2239117
@Test
fun verifyETPSheetAndToggleTest() {
fun verifyCustomTabETPSheetAndToggleTest() {
val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
intentReceiverActivityTestRule.launchActivity(

@ -138,6 +138,7 @@ class DownloadTest {
assertExternalAppOpens(GOOGLE_APPS_PHOTOS)
mDevice.pressBack()
mDevice.openNotification()
verifySystemNotificationExists("Download completed")
swipeDownloadNotification(
direction = "Left",
shouldDismissNotification = true,

@ -445,4 +445,25 @@ class HistoryTest {
verifySuggestionsAreNotDisplayed(activityTestRule, thirdWebPage.url.toString())
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903590
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@SmokeTest
@Test
fun noHistoryInPrivateBrowsingTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openHistory {
verifyEmptyHistoryView()
}
}
}

@ -86,7 +86,7 @@ class HomeScreenTest {
homeScreen { }.togglePrivateBrowsingMode()
homeScreen {
verifyPrivateBrowsingHomeScreen()
verifyPrivateBrowsingHomeScreenItems()
}.openCommonMythsLink {
verifyUrl("common-myths-about-private-browsing")
}

@ -62,9 +62,10 @@ class MediaNotificationTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1347033
@SmokeTest
@Test
fun videoPlaybackSystemNotificationTest() {
fun verifyVideoPlaybackSystemNotificationTest() {
val videoTestPage = TestAssetHelper.getVideoPageAsset(mockWebServer)
navigationToolbar {
@ -96,9 +97,10 @@ class MediaNotificationTest {
mDevice.pressBack()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2316010
@SmokeTest
@Test
fun audioPlaybackSystemNotificationTest() {
fun verifyAudioPlaybackSystemNotificationTest() {
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
navigationToolbar {
@ -130,6 +132,7 @@ class MediaNotificationTest {
mDevice.pressBack()
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903595
@Test
fun mediaSystemNotificationInPrivateModeTest() {
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)

@ -103,6 +103,7 @@ class NavigationToolbarTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.toUri()) {
waitForPageToLoad()
}.openSiteSecuritySheet {
verifyQuickActionSheet(defaultWebPage, true)
openSecureConnectionSubMenu(true)

@ -56,7 +56,7 @@ class NimbusMessagingHomescreenTest {
@Before
fun setUp() {
// Set up nimbus message
FxNimbusMessaging.features.messaging.withInitializer {
FxNimbusMessaging.features.messaging.withInitializer { _, _ ->
// FML generated objects.
Messaging(
messages = mapOf(
@ -82,7 +82,7 @@ class NimbusMessagingHomescreenTest {
}
// Remove some homescreen features not needed for testing
FxNimbus.features.homescreen.withInitializer {
FxNimbus.features.homescreen.withInitializer { _, _ ->
// These are FML generated objects and enums
Homescreen(
sectionsEnabled = mapOf(

@ -37,6 +37,7 @@ class NoNetworkAccessStartupTests {
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
// Based on STR from https://github.com/mozilla-mobile/fenix/issues/16886
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2240542
@Test
fun noNetworkConnectionStartupTest() {
setNetworkEnabled(false)
@ -49,6 +50,7 @@ class NoNetworkAccessStartupTests {
}
// Based on STR from https://github.com/mozilla-mobile/fenix/issues/16886
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2240722
@Test
fun networkInterruptedFromBrowserToHomeTest() {
val url = "example.com"
@ -66,6 +68,7 @@ class NoNetworkAccessStartupTests {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2240723
@Test
fun testPageReloadAfterNetworkInterrupted() {
val url = "example.com"
@ -82,6 +85,7 @@ class NoNetworkAccessStartupTests {
}.refreshPage { }
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2240721
@SmokeTest
@Test
fun testSignInPageWithNoNetworkConnection() {

@ -52,9 +52,10 @@ class PDFViewerTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2048140
@SmokeTest
@Test
fun openPDFInBrowserTest() {
fun verifyPDFFileIsOpenedInTheSameTabTest() {
val genericURL =
getGenericAsset(mockWebServer, 3)
@ -62,11 +63,13 @@ class PDFViewerTest {
}.enterURLAndEnterToBrowser(genericURL.url) {
clickPageObject(itemContainingText("PDF form file"))
verifyPageContent("Washington Crossing the Delaware")
verifyTabCounter("1")
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2159718
@Test
fun pdfViewerOpenInAppTest() {
fun verifyPDFViewerOpenInAppButtonTest() {
val genericURL = getGenericAsset(mockWebServer, 3)
navigationToolbar {
@ -78,9 +81,10 @@ class PDFViewerTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2145448
// Download PDF file using the download toolbar button
@Test
fun pdfViewerDownloadButtonTest() {
fun verifyPDFViewerDownloadButtonTest() {
val genericURL = getGenericAsset(mockWebServer, 3)
val downloadFile = "pdfForm.pdf"

@ -5,27 +5,16 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.helpers.Constants.PackageName.GMAIL_APP
import org.mozilla.fenix.helpers.Constants.PackageName.PHONE_APP
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.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
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.customTabScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.pwaScreen
import org.mozilla.fenix.ui.robots.setPageObjectText
class PwaTest {
/* Updated externalLinks.html to v2.0,
@ -39,6 +28,7 @@ class PwaTest {
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/845695
@Test
fun externalLinkPWATest() {
val externalLinkURL = "https://mozilla-mobile.github.io/testapp/downloads"
@ -59,38 +49,7 @@ class PwaTest {
}
}
@Test
fun emailLinkPWATest() {
navigationToolbar {
}.enterURLAndEnterToBrowser(externalLinksPWAPage.toUri()) {
waitForPageToLoad()
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.clickInstall {
clickAddAutomaticallyButton()
}.openHomeScreenShortcut(shortcutTitle) {
clickPageObject(itemContainingText("Email link"))
clickPageObject(itemWithResIdAndText("android:id/button1", "OPEN"))
assertExternalAppOpens(GMAIL_APP)
}
}
@Test
fun telephoneLinkPWATest() {
navigationToolbar {
}.enterURLAndEnterToBrowser(externalLinksPWAPage.toUri()) {
waitForPageToLoad()
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.clickInstall {
clickAddAutomaticallyButton()
}.openHomeScreenShortcut(shortcutTitle) {
clickPageObject(itemContainingText("Telephone link"))
clickPageObject(itemWithResIdAndText("android:id/button1", "OPEN"))
assertNativeAppOpens(PHONE_APP, phoneLink)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/845694
@Test
fun appLikeExperiencePWATest() {
navigationToolbar {
@ -109,11 +68,11 @@ class PwaTest {
}
}
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1807273")
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/834200
@SmokeTest
@Test
fun saveLoginsInPWATest() {
val pwaPage = "https://mozilla-mobile.github.io/testapp/loginForm"
val shortcutTitle = "TEST_APP"
fun installPWAFromTheMainMenuTest() {
val pwaPage = "https://mozilla-mobile.github.io/testapp/"
navigationToolbar {
}.enterURLAndEnterToBrowser(pwaPage.toUri()) {
@ -121,29 +80,9 @@ class PwaTest {
}.openThreeDotMenu {
}.clickInstall {
clickAddAutomaticallyButton()
}.openHomeScreenShortcut(shortcutTitle) {
}.openHomeScreenShortcut("TEST_APP") {
mDevice.waitForIdle()
setPageObjectText(itemWithResId("username"), "mozilla")
setPageObjectText(itemWithResId("password"), "firefox")
clickPageObject(itemWithResId("submit"))
verifySaveLoginPromptIsDisplayed()
clickPageObject(itemWithText("Save"))
TestHelper.openAppFromExternalLink(pwaPage)
browserScreen {
}.openThreeDotMenu {
}.openSettings {
}.openLoginsAndPasswordSubMenu {
}.openSavedLogins {
verifySecurityPromptForLogins()
tapSetupLater()
verifySavedLoginsSectionUsername("mozilla")
}
addToHomeScreen {
}.searchAndOpenHomeScreenShortcut(shortcutTitle) {
verifyPrefilledPWALoginCredentials("mozilla", shortcutTitle)
}
verifyNavURLBarHidden()
}
}
}

@ -13,6 +13,7 @@ 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.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RetryTestRule
@ -63,10 +64,13 @@ class ReaderViewTest {
* - Show the toggle button in the navigation bar
*
*/
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/250592
@Test
fun verifyReaderViewPageMenuDetection() {
fun verifyReaderModePageDetectionTest() {
val readerViewPage =
TestAssetHelper.getLoremIpsumAsset(mockWebServer)
val genericPage =
TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(readerViewPage.url) {
@ -82,70 +86,17 @@ class ReaderViewTest {
navigationToolbar {
verifyReaderViewDetected(true)
}
}
/**
* Verify that non Reader View capable pages
*
* - Reader View toggle should not be visible in the navigation toolbar
*
*/
@Test
fun verifyNonReaderViewPageMenuNoDetection() {
var genericPage =
TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericPage.url) {
mDevice.waitForIdle()
}
navigationToolbar {
verifyReaderViewDetected(false)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/250585
@SmokeTest
@Test
fun verifyReaderViewToggle() {
val readerViewPage =
TestAssetHelper.getLoremIpsumAsset(mockWebServer)
navigationToolbar {
}.enterURLAndEnterToBrowser(readerViewPage.url) {
mDevice.waitForIdle()
}
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE,
),
) {}
navigationToolbar {
verifyReaderViewDetected(true)
toggleReaderView()
mDevice.waitForIdle()
}
browserScreen {
verifyPageContent(estimatedReadingTime)
}.openThreeDotMenu {
verifyReaderViewAppearance(true)
}.closeBrowserMenuToBrowser { }
navigationToolbar {
verifyCloseReaderViewDetected(true)
toggleReaderView()
mDevice.waitForIdle()
verifyReaderViewDetected(true)
}.openThreeDotMenu {
verifyReaderViewAppearance(false)
}.closeBrowserMenuToBrowser { }
}
@Test
fun verifyReaderViewAppearanceFontToggle() {
fun verifyReaderModeControlsTest() {
val readerViewPage =
TestAssetHelper.getLoremIpsumAsset(mockWebServer)
@ -177,44 +128,15 @@ class ReaderViewTest {
verifyAppearanceFontSerif(true)
verifyAppearanceFontIncrease(true)
verifyAppearanceFontDecrease(true)
verifyAppearanceFontSize(3)
verifyAppearanceColorGroup(true)
verifyAppearanceColorDark(true)
verifyAppearanceColorLight(true)
verifyAppearanceColorSepia(true)
}.toggleSansSerif {
verifyAppearanceFontIsActive("SANSSERIF")
}.toggleSerif {
verifyAppearanceFontIsActive("SERIF")
}
}
@Test
fun verifyReaderViewAppearanceFontSizeToggle() {
val readerViewPage =
TestAssetHelper.getLoremIpsumAsset(mockWebServer)
navigationToolbar {
}.enterURLAndEnterToBrowser(readerViewPage.url) {
mDevice.waitForIdle()
}
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE,
),
) {}
navigationToolbar {
verifyReaderViewDetected(true)
toggleReaderView()
mDevice.waitForIdle()
}
browserScreen {
verifyPageContent(estimatedReadingTime)
}.openThreeDotMenu {
verifyReaderViewAppearance(true)
}.openReaderViewAppearance {
verifyAppearanceFontIncrease(true)
verifyAppearanceFontDecrease(true)
verifyAppearanceFontSize(3)
}.toggleFontSizeIncrease {
verifyAppearanceFontSize(4)
}.toggleFontSizeIncrease {
@ -227,46 +149,20 @@ class ReaderViewTest {
verifyAppearanceFontSize(4)
}.toggleFontSizeDecrease {
verifyAppearanceFontSize(3)
}
}
@Test
fun verifyReaderViewAppearanceColorSchemeChange() {
val readerViewPage =
TestAssetHelper.getLoremIpsumAsset(mockWebServer)
navigationToolbar {
}.enterURLAndEnterToBrowser(readerViewPage.url) {
mDevice.waitForIdle()
}
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE,
),
) {}
navigationToolbar {
verifyReaderViewDetected(true)
toggleReaderView()
mDevice.waitForIdle()
}
browserScreen {
verifyPageContent(estimatedReadingTime)
}.openThreeDotMenu {
verifyReaderViewAppearance(true)
}.openReaderViewAppearance {
verifyAppearanceColorDark(true)
verifyAppearanceColorLight(true)
verifyAppearanceColorSepia(true)
}.toggleColorSchemeChangeDark {
verifyAppearanceColorSchemeChange("DARK")
}.toggleColorSchemeChangeSepia {
verifyAppearanceColorSchemeChange("SEPIA")
}.toggleColorSchemeChangeLight {
verifyAppearanceColorSchemeChange("LIGHT")
}.closeAppearanceMenu {
}
navigationToolbar {
toggleReaderView()
mDevice.waitForIdle()
verifyReaderViewDetected(true)
}.openThreeDotMenu {
verifyReaderViewAppearance(false)
}
}
}

@ -54,36 +54,7 @@ class RecentlyClosedTabsTest {
mockWebServer.shutdown()
}
// This test verifies the Recently Closed Tabs List and items
@Test
fun verifyRecentlyClosedTabsListTest() {
val website = getGenericAsset(mockWebServer, 1)
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
mDevice.waitForIdle()
}.openComposeTabDrawer(activityTestRule) {
closeTab()
}
homeScreen {
}.openThreeDotMenu {
}.openHistory {
}.openRecentlyClosedTabs {
waitForListToExist()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(
activityTestRule.activity.findViewById(R.id.recently_closed_list),
1,
),
) {
verifyRecentlyClosedTabsMenuView()
}
verifyRecentlyClosedTabsPageTitle("Test_Page_1")
verifyRecentlyClosedTabsUrl(website.url)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1065414
// Verifies that a recently closed item is properly opened
@SmokeTest
@Test
@ -106,12 +77,15 @@ class RecentlyClosedTabsTest {
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1),
) {
verifyRecentlyClosedTabsMenuView()
verifyRecentlyClosedTabsPageTitle("Test_Page_1")
verifyRecentlyClosedTabsUrl(website.url)
}
}.clickRecentlyClosedItem("Test_Page_1") {
verifyUrl(website.url.toString())
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2195812
// Verifies that tapping the "x" button removes a recently closed item from the list
@SmokeTest
@Test
@ -140,8 +114,9 @@ class RecentlyClosedTabsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1605515
@Test
fun openInNewTabRecentlyClosedTabsTest() {
fun openMultipleRecentlyClosedTabsTest() {
val firstPage = getGenericAsset(mockWebServer, 1)
val secondPage = getGenericAsset(mockWebServer, 2)
@ -174,8 +149,9 @@ class RecentlyClosedTabsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2198690
@Test
fun openInPrivateTabRecentlyClosedTabsTest() {
fun openRecentlyClosedTabsInPrivateBrowsingTest() {
val firstPage = getGenericAsset(mockWebServer, 1)
val secondPage = getGenericAsset(mockWebServer, 2)
@ -208,6 +184,7 @@ class RecentlyClosedTabsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1605514
@Test
fun shareMultipleRecentlyClosedTabsTest() {
val firstPage = getGenericAsset(mockWebServer, 1)
@ -237,8 +214,9 @@ class RecentlyClosedTabsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1065438
@Test
fun privateBrowsingNotSavedInRecentlyClosedTabsTest() {
fun closedPrivateTabsAreNotSavedInRecentlyClosedTabsTest() {
val firstPage = getGenericAsset(mockWebServer, 1)
val secondPage = getGenericAsset(mockWebServer, 2)
@ -260,8 +238,9 @@ class RecentlyClosedTabsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1065439
@Test
fun deleteHistoryClearsRecentlyClosedTabsListTest() {
fun deletingBrowserHistoryClearsRecentlyClosedTabsListTest() {
val firstPage = getGenericAsset(mockWebServer, 1)
val secondPage = getGenericAsset(mockWebServer, 2)

@ -32,6 +32,7 @@ import org.mozilla.fenix.helpers.MockBrowserDataHelper.createTabItem
import org.mozilla.fenix.helpers.MockBrowserDataHelper.setCustomSearchEngine
import org.mozilla.fenix.helpers.SearchDispatcher
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.assertNativeAppOpens
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
@ -49,6 +50,7 @@ import org.mozilla.fenix.ui.robots.longClickPageObject
import org.mozilla.fenix.ui.robots.multipleSelectionToolbar
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.searchScreen
import java.util.Locale
/**
* Tests for verifying the search fragment
@ -93,8 +95,9 @@ class SearchTest {
searchMockServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154189
@Test
fun searchBarItemsTest() {
fun verifySearchBarItemsTest() {
navigationToolbar {
verifyDefaultSearchEngine("Google")
verifySearchBarPlaceholder("Search or enter address")
@ -109,8 +112,9 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154190
@Test
fun searchSelectorMenuItemsTest() {
fun verifySearchSelectorMenuItemsTest() {
homeScreen {
}.openSearch {
verifySearchView()
@ -123,8 +127,9 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154194
@Test
fun searchPlaceholderForDefaultEnginesTest() {
fun verifySearchPlaceholderForGeneralDefaultSearchEnginesTest() {
generalEnginesList.forEach {
homeScreen {
}.openSearch {
@ -140,8 +145,9 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154195
@Test
fun searchPlaceholderForOtherGeneralSearchEnginesTest() {
fun verifySearchPlaceholderForNotDefaultGeneralSearchEnginesTest() {
val generalEnginesList = listOf("DuckDuckGo", "Bing")
generalEnginesList.forEach {
@ -154,8 +160,9 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154196
@Test
fun searchPlaceholderForTopicSearchEngineTest() {
fun verifySearchPlaceholderForTopicSpecificSearchEnginesTest() {
val topicEnginesList = listOf("Amazon.com", "Wikipedia", "eBay")
topicEnginesList.forEach {
@ -168,9 +175,10 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1059459
@SmokeTest
@Test
fun scanButtonDenyPermissionTest() {
fun verifyQRScanningCameraAccessDialogTest() {
val cameraManager = appContext.getSystemService(Context.CAMERA_SERVICE) as CameraManager
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
@ -189,9 +197,10 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/235397
@SmokeTest
@Test
fun scanButtonAllowPermissionTest() {
fun scanQRCodeToOpenAWebpageTest() {
val cameraManager = appContext.getSystemService(Context.CAMERA_SERVICE) as CameraManager
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
@ -203,8 +212,9 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154191
@Test
fun scanButtonAvailableOnlyForGeneralSearchEnginesTest() {
fun verifyScanButtonAvailableOnlyForGeneralSearchEnginesTest() {
generalEnginesList.forEach {
homeScreen {
}.openSearch {
@ -224,10 +234,11 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/235395
// Verifies a temporary change of search engine from the Search shortcut menu
@SmokeTest
@Test
fun selectSearchEnginesShortcutTest() {
fun searchEnginesCanBeChangedTemporarilyFromSearchSelectorMenuTest() {
val enginesList = listOf("DuckDuckGo", "Google", "Amazon.com", "Wikipedia", "Bing", "eBay")
enginesList.forEach {
@ -243,8 +254,9 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/233589
@Test
fun accessSearchSettingFromSearchSelectorMenuTest() {
fun defaultSearchEnginesCanBeSetFromSearchSelectorMenuTest() {
searchScreen {
clickSearchSelectorButton()
}.clickSearchEngineSettings {
@ -260,8 +272,9 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/522918
@Test
fun clearSearchTest() {
fun verifyClearSearchButtonTest() {
homeScreen {
}.openSearch {
typeSearch(queryString)
@ -270,10 +283,11 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1623441
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@SmokeTest
@Test
fun searchGroupShowsInRecentlyVisitedTest() {
fun searchResultsOpenedInNewTabsGenerateSearchGroupsTest() {
// setting our custom mockWebServer search URL
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
@ -298,9 +312,10 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1592229
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun verifySearchGroupHistoryWithNoDuplicatesTest() {
fun verifyAPageIsAddedToASearchGroupOnlyOnceTest() {
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
val secondPageUrl = getGenericAsset(searchMockServer, 2).url
val originPageUrl =
@ -343,9 +358,10 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1591782
@Ignore("Failing due to known bug, see https://github.com/mozilla-mobile/fenix/issues/23818")
@Test
fun searchGroupGeneratedInTheSameTabTest() {
fun searchGroupIsGeneratedWhenNavigatingInTheSameTabTest() {
// setting our custom mockWebServer search URL
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
@ -366,9 +382,10 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1591781
@SmokeTest
@Test
fun noSearchGroupFromPrivateBrowsingTest() {
fun searchGroupIsNotGeneratedForLinksOpenedInPrivateTabsTest() {
// setting our custom mockWebServer search URL
val searchEngineName = "TestSearchEngine"
setCustomSearchEngine(searchMockServer, searchEngineName)
@ -397,10 +414,11 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1592269
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@SmokeTest
@Test
fun deleteItemsFromSearchGroupHistoryTest() {
fun deleteIndividualHistoryItemsFromSearchGroupTest() {
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
val secondPageUrl = getGenericAsset(searchMockServer, 2).url
// setting our custom mockWebServer search URL
@ -439,9 +457,10 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1592242
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun deleteSearchGroupFromHistoryTest() {
fun deleteSearchGroupFromHomeScreenTest() {
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
// setting our custom mockWebServer search URL
val searchEngineName = "TestSearchEngine"
@ -479,9 +498,10 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1592235
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun reopenTabsFromSearchGroupTest() {
fun openAPageFromHomeScreenSearchGroupTest() {
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
val secondPageUrl = getGenericAsset(searchMockServer, 2).url
// setting our custom mockWebServer search URL
@ -526,9 +546,10 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1592238
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun sharePageFromASearchGroupTest() {
fun shareAPageFromHomeScreenSearchGroupTest() {
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
// setting our custom mockWebServer search URL
val searchEngineName = "TestSearchEngine"
@ -564,6 +585,7 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1232633
// Default search code for Google-US
@Test
fun defaultSearchCodeGoogleUS() {
@ -584,6 +606,7 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1232637
// Default search code for Bing-US
@Test
fun defaultSearchCodeBingUS() {
@ -603,10 +626,17 @@ class SearchTest {
}.openThreeDotMenu {
}.openHistory {
// Full URL no longer visible in the nav bar, so we'll check the history record
verifyHistoryItemExists(shouldExist = true, searchEngineCodes["Bing"]!!)
// A search group is sometimes created when searching with Bing (probably redirects)
try {
verifyHistoryItemExists(shouldExist = true, searchEngineCodes["Bing"]!!)
} catch (e: AssertionError) {
openSearchGroup(queryString)
verifyHistoryItemExists(shouldExist = true, searchEngineCodes["Bing"]!!)
}
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1232638
// Default search code for DuckDuckGo-US
@Test
fun defaultSearchCodeDuckDuckGoUS() {
@ -635,9 +665,10 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154215
@SmokeTest
@Test
fun verifySearchHistoryWithBrowsingDataTest() {
fun verifyHistorySearchWithBrowsingHistoryTest() {
val firstPageUrl = getGenericAsset(searchMockServer, 1)
val secondPageUrl = getGenericAsset(searchMockServer, 2)
@ -708,6 +739,7 @@ class SearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2230212
@SmokeTest
@Test
fun searchHistoryNotRememberedInPrivateBrowsingTest() {
@ -753,4 +785,29 @@ class SearchTest {
)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1232631
// Expected for app language set to Arabic
@Test
fun verifySearchEnginesFunctionalityUsingRTLLocaleTest() {
val arabicLocale = Locale("ar", "AR")
TestHelper.runWithSystemLocaleChanged(arabicLocale, activityTestRule.activityRule) {
homeScreen {
}.openSearch {
verifyTranslatedFocusedNavigationToolbar("ابحث أو أدخِل عنوانا")
clickSearchSelectorButton()
verifySearchShortcutListContains(
"Google",
"Bing",
"Amazon.com",
"DuckDuckGo",
"ويكيبيديا (ar)",
)
selectTemporarySearchMethod("ويكيبيديا (ar)")
}.submitQuery("firefox") {
verifyUrl("firefox")
}
}
}
}

@ -71,7 +71,9 @@ class SettingsAdvancedTest {
verifyExternalDownloadManagerButton()
verifyExternalDownloadManagerToggle(false)
verifyLeakCanaryButton()
verifyLeakCanaryToggle(true)
// LeakCanary is disabled in UI tests.
// See BuildConfig.LEAKCANARY.
verifyLeakCanaryToggle(false)
verifyRemoteDebuggingButton()
verifyRemoteDebuggingToggle(false)
}
@ -222,7 +224,10 @@ class SettingsAdvancedTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(externalLinksPage.url) {
clickPageObject(youTubeFullLink)
verifyPrivateBrowsingOpenLinkInAnotherAppPrompt("youtube")
verifyPrivateBrowsingOpenLinkInAnotherAppPrompt(
url = "youtube",
pageObject = youTubeFullLink,
)
clickPageObject(itemWithResIdAndText("android:id/button2", "CANCEL"))
waitForPageToLoad()
verifyUrl("youtube")
@ -256,7 +261,10 @@ class SettingsAdvancedTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(externalLinksPage.url) {
clickPageObject(youTubeSchemaLink)
verifyPrivateBrowsingOpenLinkInAnotherAppPrompt("youtube")
verifyPrivateBrowsingOpenLinkInAnotherAppPrompt(
url = "youtube",
pageObject = youTubeSchemaLink,
)
clickPageObject(itemWithResIdAndText("android:id/button1", "OPEN"))
mDevice.waitForIdle()
assertYoutubeAppOpens()

@ -14,6 +14,7 @@ import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.ui.robots.addToHomeScreen
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
@ -54,8 +55,9 @@ class SettingsPrivateBrowsingTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/420086
@Test
fun openExternalLinksInPrivateTest() {
fun launchLinksInAPrivateTabTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
@ -82,8 +84,9 @@ class SettingsPrivateBrowsingTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/555776
@Test
fun launchPageShortcutInPrivateModeTest() {
fun launchPageShortcutInPrivateBrowsingTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
setOpenLinksInPrivateOn()
@ -100,9 +103,11 @@ class SettingsPrivateBrowsingTest {
mDevice.waitForIdle()
// We need to close the existing tab here, to open a different session
TestHelper.restartApp(activityTestRule)
restartApp(activityTestRule)
browserScreen {
}.openTabDrawer {
verifyNormalModeSelected()
closeTab()
}
@ -110,39 +115,15 @@ class SettingsPrivateBrowsingTest {
}.searchAndOpenHomeScreenShortcut(pageShortcutName) {
}.openTabDrawer {
verifyPrivateModeSelected()
closeTab()
}
}
@Test
fun launchLinksInPrivateToggleOffStateDoesntChangeTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
setOpenLinksInPrivateOn()
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
expandMenu()
}.openAddToHomeScreen {
addShortcutName(pageShortcutName)
clickAddShortcutButton()
clickAddAutomaticallyButton()
}.openHomeScreenShortcut(pageShortcutName) {
}.goToHomescreen { }
setOpenLinksInPrivateOff()
TestHelper.restartApp(activityTestRule)
mDevice.waitForIdle()
addToHomeScreen {
}.searchAndOpenHomeScreenShortcut(pageShortcutName) {
}.openTabDrawer {
verifyNormalModeSelected()
}.closeTabDrawer {
}.openThreeDotMenu {
}.openSettings {
}.openPrivateBrowsingSubMenu {
verifyOpenLinksInPrivateTabOff()
}
}

@ -29,6 +29,7 @@ import org.mozilla.fenix.helpers.TestHelper.setTextToClipBoard
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.ui.robots.EngineShortcut
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.searchScreen
import java.util.Locale
@ -65,8 +66,9 @@ class SettingsSearchTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203333
@Test
fun searchSettingsItemsTest() {
fun verifySearchSettingsMenuItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -89,8 +91,9 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203307
@Test
fun defaultSearchEnginesSettingsItemsTest() {
fun verifyDefaultSearchEnginesSettingsItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -103,9 +106,10 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203308
@SmokeTest
@Test
fun selectNewDefaultSearchEngine() {
fun verifyTheDefaultSearchEngineCanBeChangedTest() {
// Goes through the settings and changes the default search engine, then verifies it has changed.
defaultSearchEngineList.forEach {
homeScreen {
@ -122,8 +126,9 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/233586
@Test
fun toggleSearchAutocomplete() {
fun verifyUrlAutocompleteToggleTest() {
homeScreen {
}.openSearch {
typeSearch("mo")
@ -143,8 +148,9 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/361817
@Test
fun toggleOffHistorySearchSuggestionsTest() {
fun disableSearchBrowsingHistorySuggestionsToggleTest() {
val websiteURL = getGenericAsset(mockWebServer, 1).url.toString()
createHistoryItem(websiteURL)
@ -168,8 +174,9 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/412926
@Test
fun toggleOffBookmarksSearchSuggestionsTest() {
fun disableSearchBookmarksToggleTest() {
val website = getGenericAsset(mockWebServer, 1)
createBookmarkItem(website.url.toString(), website.title, 1u)
@ -196,10 +203,11 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203309
// Verifies setting as default a customized search engine name and URL
@SmokeTest
@Test
fun addCustomDefaultSearchEngineTest() {
fun verifyCustomSearchEngineCanBeAddedFromSearchEngineMenuTest() {
val customSearchEngine = object {
val title = "TestSearchEngine"
val url = "http://localhost:${searchMockServer.port}/searchResults.html?search=%s"
@ -234,8 +242,9 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203335
@Test
fun addSearchEngineToManageShortcutsListTest() {
fun addCustomSearchEngineToManageShortcutsListTest() {
val customSearchEngine = object {
val title = "TestSearchEngine"
val url = "http://localhost:${searchMockServer.port}/searchResults.html?search=%s"
@ -256,8 +265,9 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203343
@Test
fun addSearchEngineLearnMoreLinksTest() {
fun verifyLearnMoreLinksFromAddSearchEngineSectionTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -280,6 +290,7 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203310
@Test
fun editCustomSearchEngineTest() {
val customSearchEngine = object {
@ -309,9 +320,10 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203312
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1848623")
@Test
fun errorForInvalidSearchEngineStringsTest() {
fun verifyErrorMessagesForInvalidSearchEngineUrlsTest() {
val customSearchEngine = object {
val title = "TestSearchEngine"
val badTemplateUrl = "http://localhost:${searchMockServer.port}/searchResults.html?search="
@ -341,6 +353,7 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203313
@Test
fun deleteCustomSearchEngineTest() {
val customSearchEngineTitle = "TestSearchEngine"
@ -375,6 +388,7 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203339
@Test
fun deleteCustomSearchShortcutTest() {
val customSearchEngineTitle = "TestSearchEngine"
@ -402,13 +416,14 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/233588
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
// Goes through the settings and changes the search suggestion toggle, then verifies it changes.
@Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/23817")
@SmokeTest
@Test
fun toggleSearchSuggestionsTest() {
fun verifyShowSearchSuggestionsToggleTest() {
homeScreen {
}.openSearch {
typeSearch("mozilla ")
@ -430,9 +445,10 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/464420
// Tests the "Don't allow" option from private mode search suggestions onboarding dialog
@Test
fun blockSearchSuggestionsInPrivateModeOnboardingTest() {
fun doNotAllowSearchSuggestionsInPrivateBrowsingTest() {
homeScreen {
togglePrivateBrowsingModeOnOff()
}.openSearch {
@ -443,9 +459,10 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1957063
// Tests the "Allow" option from private mode search suggestions onboarding dialog
@Test
fun allowSearchSuggestionsInPrivateModeOnboardingTest() {
fun allowSearchSuggestionsInPrivateBrowsingTest() {
homeScreen {
togglePrivateBrowsingModeOnOff()
}.openSearch {
@ -470,8 +487,9 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/888673
@Test
fun toggleVoiceSearchTest() {
fun verifyShowVoiceSearchToggleTest() {
homeScreen {
}.openSearch {
verifyVoiceSearchButtonVisibility(true)
@ -489,8 +507,10 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/412927
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1807268")
@Test
fun toggleShowClipboardSuggestionsTest() {
fun verifyShowClipboardSuggestionsToggleTest() {
val link = "https://www.mozilla.org/en-US/"
setTextToClipBoard(appContext, link)
@ -498,6 +518,21 @@ class SettingsSearchTest {
}.openNavigationToolbar {
verifyClipboardSuggestionsAreDisplayed(link, true)
}.visitLinkFromClipboard {
waitForPageToLoad()
}.openTabDrawer {
}.openNewTab {
}
navigationToolbar {
// After visiting the link from clipboard it shouldn't be displayed again
verifyClipboardSuggestionsAreDisplayed(shouldBeDisplayed = false)
}.goBackToHomeScreen {
setTextToClipBoard(appContext, link)
}.openTabDrawer {
}.openNewTab {
}
navigationToolbar {
verifyClipboardSuggestionsAreDisplayed(link, true)
}.goBackToHomeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
@ -507,37 +542,17 @@ class SettingsSearchTest {
exitMenu()
}
homeScreen {
}.openNavigationToolbar {
verifyClipboardSuggestionsAreDisplayed(link, false)
}.openTabDrawer {
}.openNewTab {
}
}
// Expected for app language set to Arabic
@Test
fun verifySearchEnginesWithRTLLocale() {
val arabicLocale = Locale("ar", "AR")
runWithSystemLocaleChanged(arabicLocale, activityTestRule.activityRule) {
homeScreen {
}.openSearch {
verifyTranslatedFocusedNavigationToolbar("ابحث أو أدخِل عنوانا")
clickSearchSelectorButton()
verifySearchShortcutListContains(
"Google",
"Bing",
"Amazon.com",
"DuckDuckGo",
"ويكيبيديا (ar)",
)
selectTemporarySearchMethod("ويكيبيديا (ar)")
}.submitQuery("firefox") {
verifyUrl("firefox")
}
navigationToolbar {
verifyClipboardSuggestionsAreDisplayed(link, false)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2233337
@Test
fun searchEnginesListRespectLocaleTest() {
fun verifyTheSearchEnginesListsRespectTheLocaleTest() {
runWithSystemLocaleChanged(Locale.CHINA, activityTestRule.activityRule) {
// Checking search engines for CH locale
homeScreen {
@ -567,14 +582,15 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203334
@Test
fun manageSearchShortcutsSettingsItemsTest() {
fun verifyManageSearchShortcutsSettingsItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
openManageShortcutsMenu()
verifyToolbarText("Manage search shortcuts")
verifyToolbarText("Manage alternative search engines")
verifyEnginesShortcutsListHeader()
verifyManageShortcutsList(activityTestRule)
verifySearchShortcutChecked(
@ -590,9 +606,10 @@ class SettingsSearchTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203340
@SmokeTest
@Test
fun changeSearchShortcutsListTest() {
fun verifySearchShortcutChangesAreReflectedInSearchSelectorMenuTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {

@ -78,9 +78,10 @@ class SitePermissionsTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2334295
@SmokeTest
@Test
fun audioVideoPermissionChoiceOnEachRequestTest() {
fun audioVideoPermissionWithoutRememberingTheDecisionTest() {
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
navigationToolbar {
@ -96,10 +97,10 @@ class SitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2334294
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1815395")
@SmokeTest
@Test
fun rememberBlockAudioVideoPermissionChoiceTest() {
fun blockAudioVideoPermissionRememberingTheDecisionTest() {
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
assumeTrue(micManager.microphones.isNotEmpty())
@ -120,10 +121,10 @@ class SitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/251388
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1815395")
@SmokeTest
@Test
fun rememberAllowAudioVideoPermissionChoiceTest() {
fun allowAudioVideoPermissionRememberingTheDecisionTest() {
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
assumeTrue(micManager.microphones.isNotEmpty())
@ -144,8 +145,9 @@ class SitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2334189
@Test
fun microphonePermissionChoiceOnEachRequestTest() {
fun microphonePermissionWithoutRememberingTheDecisionTest() {
assumeTrue(micManager.microphones.isNotEmpty())
navigationToolbar {
@ -161,9 +163,10 @@ class SitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2334190
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1815395")
@Test
fun rememberBlockMicrophonePermissionChoiceTest() {
fun blockMicrophonePermissionRememberingTheDecisionTest() {
assumeTrue(micManager.microphones.isNotEmpty())
navigationToolbar {
@ -183,9 +186,10 @@ class SitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/251387
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1815395")
@Test
fun rememberAllowMicrophonePermissionChoiceTest() {
fun allowMicrophonePermissionRememberingTheDecisionTest() {
assumeTrue(micManager.microphones.isNotEmpty())
navigationToolbar {
@ -205,8 +209,9 @@ class SitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2334076
@Test
fun cameraPermissionChoiceOnEachRequestTest() {
fun cameraPermissionWithoutRememberingDecisionTest() {
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
navigationToolbar {
@ -222,9 +227,10 @@ class SitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2334077
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1815395")
@Test
fun rememberBlockCameraPermissionChoiceTest() {
fun blockCameraPermissionRememberingTheDecisionTest() {
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
navigationToolbar {
@ -244,9 +250,10 @@ class SitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/251386
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1815395")
@Test
fun rememberAllowCameraPermissionChoiceTest() {
fun allowCameraPermissionRememberingTheDecisionTest() {
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
navigationToolbar {
@ -266,8 +273,10 @@ class SitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2334074
@SmokeTest
@Test
fun blockNotificationsPermissionPromptTest() {
fun blockNotificationsPermissionTest() {
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.toUri()) {
}.clickOpenNotificationButton {
@ -282,8 +291,9 @@ class SitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/251380
@Test
fun allowNotificationsPermissionPromptTest() {
fun allowNotificationsPermissionTest() {
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.toUri()) {
}.clickOpenNotificationButton {
@ -293,6 +303,7 @@ class SitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/251385
@SmokeTest
@Test
fun allowLocationPermissionsTest() {
@ -308,7 +319,7 @@ class SitePermissionsTest {
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2334075
@Test
fun blockLocationPermissionsTest() {
navigationToolbar {
@ -320,6 +331,7 @@ class SitePermissionsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2121537
@SmokeTest
@Test
fun fileUploadPermissionTest() {

@ -1,236 +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/. */
@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)
}
}
}

@ -7,20 +7,25 @@ package org.mozilla.fenix.ui
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.google.android.material.bottomsheet.BottomSheetBehavior
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.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
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.closeApp
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.verifyKeyboardVisibility
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.notificationShade
@ -45,6 +50,7 @@ import org.mozilla.fenix.ui.robots.notificationShade
class TabbedBrowsingTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
private lateinit var browserStore: BrowserStore
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@ -55,6 +61,10 @@ class TabbedBrowsingTest {
@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()
@ -67,50 +77,7 @@ class TabbedBrowsingTest {
mockWebServer.shutdown()
}
@Test
fun openNewTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
verifyTabCounter("1")
}.openTabDrawer {
verifyNormalModeSelected()
verifyExistingOpenTabs("Test_Page_1")
closeTab()
}.openTabDrawer {
verifyNoOpenTabsInNormalBrowsing()
}.openNewTab {
}.submitQuery(defaultWebPage.url.toString()) {
mDevice.waitForIdle()
verifyTabCounter("1")
}.openTabDrawer {
verifyNormalModeSelected()
verifyExistingOpenTabs("Test_Page_1")
}
}
@Test
fun openNewPrivateTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {}.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
mDevice.waitForIdle()
verifyTabCounter("1")
}.openTabDrawer {
verifyExistingTabList()
verifyPrivateModeSelected()
}.toggleToNormalTabs {
verifyNoOpenTabsInNormalBrowsing()
}.toggleToPrivateTabs {
verifyExistingTabList()
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903599
@Test
fun closeAllTabsTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -143,8 +110,9 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903604
@Test
fun closeTabTest() {
fun closingTabsMethodsTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -152,6 +120,13 @@ class TabbedBrowsingTest {
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
closeTab()
verifySnackBarText("Tab closed")
snackBarButtonClick("UNDO")
}
browserScreen {
verifyTabCounter("1")
}.openTabDrawer {
closeTab()
}
homeScreen {
verifyTabCounter("0")
@ -160,6 +135,7 @@ class TabbedBrowsingTest {
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
swipeTabRight("Test_Page_1")
verifySnackBarText("Tab closed")
}
homeScreen {
verifyTabCounter("0")
@ -168,48 +144,31 @@ class TabbedBrowsingTest {
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
swipeTabLeft("Test_Page_1")
verifySnackBarText("Tab closed")
}
homeScreen {
verifyTabCounter("0")
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903591
@Test
fun verifyUndoSnackBarTest() {
// disabling these features because they interfere with the snackbar visibility
activityTestRule.applySettingsExceptions {
it.isPocketEnabled = false
it.isRecentTabsFeatureEnabled = false
}
fun closingPrivateTabsMethodsTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen { }.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
verifyCloseTabsButton("Test_Page_1")
closeTab()
verifySnackBarText("Tab closed")
verifySnackBarText("Private tab closed")
snackBarButtonClick("UNDO")
}
browserScreen {
verifyTabCounter("1")
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
}
}
@Test
fun closePrivateTabTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen { }.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
verifyCloseTabsButton("Test_Page_1")
closeTab()
}
homeScreen {
@ -219,6 +178,7 @@ class TabbedBrowsingTest {
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
swipeTabRight("Test_Page_1")
verifySnackBarText("Private tab closed")
}
homeScreen {
verifyTabCounter("0")
@ -227,38 +187,37 @@ class TabbedBrowsingTest {
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
swipeTabLeft("Test_Page_1")
verifySnackBarText("Private tab closed")
}
homeScreen {
verifyTabCounter("0")
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903606
@SmokeTest
@Test
fun verifyPrivateTabUndoSnackBarTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
fun tabMediaControlButtonTest() {
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
homeScreen { }.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
verifyCloseTabsButton("Test_Page_1")
closeTab()
verifySnackBarText("Private tab closed")
snackBarButtonClick("UNDO")
}
browserScreen {
verifyTabCounter("1")
}.enterURLAndEnterToBrowser(audioTestPage.url) {
mDevice.waitForIdle()
clickPageObject(MatcherHelper.itemWithText("Play"))
assertPlaybackState(browserStore, MediaSession.PlaybackState.PLAYING)
}.openTabDrawer {
verifyExistingOpenTabs("Test_Page_1")
verifyPrivateModeSelected()
verifyTabMediaControlButtonState("Pause")
clickTabMediaControlButton("Pause")
verifyTabMediaControlButtonState("Play")
}.openTab(audioTestPage.title) {
assertPlaybackState(browserStore, MediaSession.PlaybackState.PAUSED)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903592
@SmokeTest
@Test
fun closePrivateTabsNotificationTest() {
fun verifyCloseAllPrivateTabsNotificationTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
@ -276,6 +235,40 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903598
@SmokeTest
@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 verifyTabTrayNotShowingStateHalfExpanded() {
navigationToolbar {
@ -299,6 +292,7 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903600
@Test
fun verifyEmptyTabTray() {
navigationToolbar {
@ -313,8 +307,9 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903585
@Test
fun emptyTabsTrayViewPrivateBrowsingTest() {
fun verifyEmptyPrivateTabsTrayTest() {
navigationToolbar {
}.openTabTray {
}.toggleToPrivateTabs {
@ -328,12 +323,15 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903601
@Test
fun verifyOpenTabDetails() {
fun verifyTabsTrayWithOpenTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
homeScreen {
}.openTabDrawer {
}.openNewTab {
}.submitQuery(defaultWebPage.url.toString()) {
}.openTabDrawer {
verifyNormalBrowsingButtonIsSelected(true)
verifyPrivateBrowsingButtonIsSelected(false)
@ -351,29 +349,57 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/903587
@SmokeTest
@Test
fun verifyPrivateTabsTrayWithOpenTabTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
}.openTabDrawer {
}.toggleToPrivateTabs {
}.openNewTab {
}.submitQuery(website.url.toString()) {
}.openTabDrawer {
verifyNormalBrowsingButtonIsSelected(false)
verifyPrivateBrowsingButtonIsSelected(true)
verifySyncedTabsButtonIsSelected(false)
verifyTabTrayOverflowMenu(true)
verifyTabsTrayCounter()
verifyExistingTabList()
verifyExistingOpenTabs(website.title)
verifyCloseTabsButton(website.title)
verifyOpenedTabThumbnail()
verifyPrivateBrowsingNewTabButton()
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/927315
@Test
fun verifyContextMenuShortcuts() {
fun tabsCounterShortcutMenuTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
verifyTabButtonShortcutMenuItems()
}.closeTabFromShortcutsMenu {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewPrivateTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
}.dismissSearchBar {
verifyCommonMythsLink()
verifyNavigationToolbar()
verifyPrivateBrowsingHomeScreenItems()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openTabFromShortcutsMenu {
}.openNewTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
@ -383,6 +409,45 @@ class TabbedBrowsingTest {
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/927314
@Test
fun privateTabsCounterShortcutMenuTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {}.togglePrivateBrowsingMode()
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
waitForPageToLoad()
}
navigationToolbar {
}.openTabButtonShortcutsMenu {
verifyTabButtonShortcutMenuItems()
}.closeTabFromShortcutsMenu {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewPrivateTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
}.dismissSearchBar {
verifyCommonMythsLink()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {}
navigationToolbar {
}.openTabButtonShortcutsMenu {
}.openNewTabFromShortcutsMenu {
verifyKeyboardVisibility()
verifySearchBarPlaceholder("Search or enter address")
// dismiss search dialog
}.dismissSearchBar {
// Verify normal browsing homescreen
verifyExistingTopSitesList()
}
}
// TestRail: https://testrail.stage.mozaws.net/index.php?/cases/view/1046683
@Test
fun verifySyncedTabsWhenUserIsNotSignedInTest() {
navigationToolbar {
@ -397,6 +462,7 @@ class TabbedBrowsingTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/526244
@Test
fun privateModeStaysAsDefaultAfterRestartTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -408,13 +474,14 @@ class TabbedBrowsingTest {
closeApp(activityTestRule)
restartApp(activityTestRule)
homeScreen {
verifyPrivateBrowsingHomeScreen()
verifyPrivateBrowsingHomeScreenItems()
}.openTabDrawer {
}.toggleToNormalTabs {
verifyExistingOpenTabs(defaultWebPage.title)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2228470
@SmokeTest
@Test
fun privateTabsDoNotPersistAfterClosingAppTest() {
@ -435,7 +502,7 @@ class TabbedBrowsingTest {
restartApp(activityTestRule)
homeScreen {
verifyPrivateBrowsingHomeScreen()
verifyPrivateBrowsingHomeScreenItems()
}.openTabDrawer {
verifyNoOpenTabsInPrivateBrowsing()
}

@ -53,9 +53,10 @@ class TextSelectionTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326832
@SmokeTest
@Test
fun selectAllAndCopyTextTest() {
fun verifySelectAllTextOptionTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -77,9 +78,9 @@ class TextSelectionTest {
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326828
@Test
fun copyTextTest() {
fun verifyCopyTextOptionTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -98,9 +99,9 @@ class TextSelectionTest {
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326829
@Test
fun shareSelectedTextTest() {
fun verifyShareSelectedTextOptionTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -111,9 +112,9 @@ class TextSelectionTest {
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326830
@Test
fun selectAndSearchTextTest() {
fun verifySearchTextOptionTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -126,9 +127,10 @@ class TextSelectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326831
@SmokeTest
@Test
fun privateSelectAndSearchTextTest() {
fun verifyPrivateSearchTextTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
@ -144,9 +146,9 @@ class TextSelectionTest {
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326834
@Test
fun selectAllAndCopyPDFTextTest() {
fun verifySelectAllPDFTextOptionTest() {
val genericURL =
TestAssetHelper.getGenericAsset(mockWebServer, 3)
@ -168,9 +170,10 @@ class TextSelectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243839
@SmokeTest
@Test
fun copyPDFTextTest() {
fun verifyCopyPDFTextOptionTest() {
val genericURL =
TestAssetHelper.getGenericAsset(mockWebServer, 3)
@ -191,9 +194,9 @@ class TextSelectionTest {
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326835
@Test
fun shareSelectedPDFTextTest() {
fun verifyShareSelectedPDFTextOptionTest() {
val genericURL =
TestAssetHelper.getGenericAsset(mockWebServer, 3)
@ -206,9 +209,10 @@ class TextSelectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326836
@SmokeTest
@Test
fun selectAndSearchPDFTextTest() {
fun verifySearchPDFTextOptionTest() {
val genericURL =
TestAssetHelper.getGenericAsset(mockWebServer, 3)
@ -222,9 +226,9 @@ class TextSelectionTest {
}
}
@SmokeTest
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326837
@Test
fun privateSelectAndSearchPDFTextTest() {
fun verifyPrivateSearchPDFTextOptionTest() {
val genericURL =
TestAssetHelper.getGenericAsset(mockWebServer, 3)
@ -241,6 +245,7 @@ class TextSelectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326813
@Test
fun verifyUrlBarTextSelectionOptionsTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -253,8 +258,9 @@ class TextSelectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326814
@Test
fun copyUrlBarTextTest() {
fun verifyCopyUrlBarTextSelectionOptionTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -270,8 +276,9 @@ class TextSelectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326815
@Test
fun cutUrlBarTextTest() {
fun verifyCutUrlBarTextSelectionOptionTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -286,8 +293,10 @@ class TextSelectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243845
@SmokeTest
@Test
fun shareUrlBarTextTest() {
fun verifyShareUrlBarTextSelectionOptionTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -301,6 +310,7 @@ class TextSelectionTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/414316
@Test
fun urlBarQuickActionsTest() {
val firstWebsite = TestAssetHelper.getGenericAsset(mockWebServer, 1)

@ -55,9 +55,10 @@ class TopSitesTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/532598
@SmokeTest
@Test
fun verifyAddToFirefoxHome() {
fun addAWebsiteAsATopSiteTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -73,8 +74,9 @@ class TopSitesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/532599
@Test
fun verifyOpenTopSiteNormalTab() {
fun openTopSiteInANewTabTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -100,8 +102,9 @@ class TopSitesTest {
mDevice.pressBack()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/532600
@Test
fun verifyOpenTopSitePrivateTab() {
fun openTopSiteInANewPrivateTabTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -121,8 +124,9 @@ class TopSitesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1110321
@Test
fun verifyRenameTopSite() {
fun renameATopSiteTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
val newPageTitle = generateRandomString(5)
@ -145,8 +149,9 @@ class TopSitesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/532601
@Test
fun verifyRemoveTopSite() {
fun removeTopSiteUsingMenuButtonTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -162,34 +167,18 @@ class TopSitesTest {
}.openContextMenuOnTopSitesWithTitle(defaultWebPage.title) {
verifyTopSiteContextMenuItems()
}.removeTopSite {
verifyNotExistingTopSitesList(defaultWebPage.title)
}
}
@Test
fun verifyUndoRemoveTopSite() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
expandMenu()
verifyAddToShortcutsButton(shouldExist = true)
}.addToFirefoxHome {
verifySnackBarText(getStringResource(R.string.snackbar_added_to_shortcuts))
}.goToHomescreen {
verifyExistingTopSitesList()
clickSnackbarButton("UNDO")
verifyExistingTopSitesTabs(defaultWebPage.title)
}.openContextMenuOnTopSitesWithTitle(defaultWebPage.title) {
verifyTopSiteContextMenuItems()
}.removeTopSite {
clickSnackbarButton("UNDO")
verifyExistingTopSitesTabs(defaultWebPage.title)
verifyNotExistingTopSitesList(defaultWebPage.title)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2323641
@Test
fun verifyRemoveTopSiteFromMainMenu() {
fun removeTopSiteFromMainMenuTest() {
val defaultWebPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
@ -211,9 +200,10 @@ class TopSitesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/561582
// Expected for en-us defaults
@Test
fun verifyDefaultTopSitesList() {
fun verifyENLocalesDefaultTopSitesListTest() {
homeScreen {
verifyExistingTopSitesList()
defaultTopSitesList.values.forEach { value ->
@ -222,6 +212,7 @@ class TopSitesTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1050642
@SmokeTest
@Test
fun addAndRemoveMostViewedTopSiteTest() {

@ -56,21 +56,9 @@ class WebControlsTest {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2316067
@Test
fun cancelCalendarFormTest() {
val htmlControlsPage = getHTMLControlsFormAsset(mockWebServer)
navigationToolbar {
}.enterURLAndEnterToBrowser(htmlControlsPage.url) {
clickPageObject(itemWithResId("calendar"))
clickPageObject(itemContainingText("CANCEL"))
clickPageObject(itemWithResId("submitDate"))
verifyNoDateIsSelected()
}
}
@Test
fun setAndClearCalendarFormTest() {
fun verifyCalendarFormInteractionsTest() {
val currentDate = LocalDate.now()
val currentDay = currentDate.dayOfMonth
val currentMonth = currentDate.month
@ -79,6 +67,10 @@ class WebControlsTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(htmlControlsPage.url) {
clickPageObject(itemWithResId("calendar"))
clickPageObject(itemContainingText("CANCEL"))
clickPageObject(itemWithResId("submitDate"))
verifyNoDateIsSelected()
clickPageObject(itemWithResId("calendar"))
clickPageObject(itemWithDescription("$currentDay $currentMonth $currentYear"))
clickPageObject(itemContainingText("OK"))
@ -91,8 +83,9 @@ class WebControlsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2316069
@Test
fun cancelClockFormTest() {
fun verifyClockFormInteractionsTest() {
val htmlControlsPage = getHTMLControlsFormAsset(mockWebServer)
navigationToolbar {
@ -101,15 +94,6 @@ class WebControlsTest {
clickPageObject(itemContainingText("CANCEL"))
clickPageObject(itemWithResId("submitTime"))
verifyNoTimeIsSelected(hour, minute)
}
}
@Test
fun setAndClearClockFormTest() {
val htmlControlsPage = getHTMLControlsFormAsset(mockWebServer)
navigationToolbar {
}.enterURLAndEnterToBrowser(htmlControlsPage.url) {
clickPageObject(itemWithResId("clock"))
selectTime(hour, minute)
clickPageObject(itemContainingText("OK"))
@ -122,8 +106,9 @@ class WebControlsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2316068
@Test
fun cancelColorFormTest() {
fun verifyColorPickerInteractionsTest() {
val htmlControlsPage = getHTMLControlsFormAsset(mockWebServer)
navigationToolbar {
@ -133,15 +118,6 @@ class WebControlsTest {
clickPageObject(itemContainingText("CANCEL"))
clickPageObject(itemWithResId("submitColor"))
verifyColorIsNotSelected(colorHexValue)
}
}
@Test
fun setColorFormTest() {
val htmlControlsPage = getHTMLControlsFormAsset(mockWebServer)
navigationToolbar {
}.enterURLAndEnterToBrowser(htmlControlsPage.url) {
clickPageObject(itemWithResId("colorPicker"))
clickPageObject(itemWithDescription(colorHexValue))
clickPageObject(itemContainingText("SET"))
@ -150,8 +126,9 @@ class WebControlsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2316070
@Test
fun verifyDropdownMenuTest() {
fun verifyDropdownMenuInteractionsTest() {
val htmlControlsPage = getHTMLControlsFormAsset(mockWebServer)
navigationToolbar {
@ -163,8 +140,9 @@ class WebControlsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2316071
@Test
fun emailLinkTest() {
fun verifyEmailLinkTest() {
val externalLinksPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
navigationToolbar {
@ -175,8 +153,9 @@ class WebControlsTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/834205
@Test
fun telephoneLinkTest() {
fun verifyTelephoneLinkTest() {
val externalLinksPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
navigationToolbar {

@ -55,6 +55,7 @@ import org.mozilla.fenix.helpers.SessionLoadedIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeLong
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.appName
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
@ -428,6 +429,12 @@ class BrowserRobot {
fun changeCreditCardExpiryDate(expiryDate: String) =
itemWithResId("expiryMonthAndYear").setText(expiryDate)
fun clickCreditCardNumberTextBox() {
mDevice.wait(Until.findObject(By.res("cardNumber")), waitingTime)
mDevice.findObject(By.res("cardNumber")).click()
mDevice.waitForWindowUpdate(appName, waitingTimeShort)
}
fun clickCreditCardFormSubmitButton() =
itemWithResId("submit").clickAndWaitForNewWindow(waitingTime)
@ -800,13 +807,31 @@ class BrowserRobot {
)
}
fun verifyPrivateBrowsingOpenLinkInAnotherAppPrompt(url: String) =
assertItemContainingTextExists(
itemContainingText(
getStringResource(R.string.mozac_feature_applinks_confirm_dialog_title),
),
itemContainingText(url),
)
fun verifyPrivateBrowsingOpenLinkInAnotherAppPrompt(url: String, pageObject: UiObject) {
for (i in 1..RETRY_COUNT) {
try {
assertItemContainingTextExists(
itemContainingText(
getStringResource(R.string.mozac_feature_applinks_confirm_dialog_title),
),
itemContainingText(url),
)
break
} catch (e: AssertionError) {
if (i == RETRY_COUNT) {
throw e
} else {
browserScreen {
}.openThreeDotMenu {
}.refreshPage {
waitForPageToLoad()
clickPageObject(pageObject)
}
}
}
}
}
fun verifyFindInPageBar(exists: Boolean) =
assertItemWithResIdExists(
@ -882,6 +907,17 @@ class BrowserRobot {
assertTrue(button.waitForExists(waitingTime))
}
fun verifySurveyButtonDoesNotExist() {
val button = mDevice.findObject(
UiSelector().text(
getStringResource(
R.string.preferences_take_survey,
),
),
)
assertTrue(button.waitUntilGone(waitingTime))
}
fun verifySurveyNoThanksButton() {
val button = mDevice.findObject(
UiSelector().text(
@ -893,6 +929,15 @@ class BrowserRobot {
assertTrue(button.waitForExists(waitingTime))
}
fun verifyHomeScreenSurveyCloseButton() {
val button = mDevice.findObject(
UiSelector().descriptionContains(
"Close",
),
)
assertTrue(button.waitForExists(waitingTime))
}
fun clickOpenLinksInAppsDismissCFRButton() =
itemWithResIdContainingText(
"$packageName:id/dismiss",
@ -910,7 +955,6 @@ class BrowserRobot {
button.waitForExists(waitingTime)
button.click()
}
fun clickNoThanksSurveyButton() {
val button = mDevice.findObject(
UiSelector().text(
@ -1068,14 +1112,6 @@ class BrowserRobot {
return ComposeTabDrawerRobot.Transition(composeTestRule)
}
fun openTabButtonShortcutsMenu(interact: NavigationToolbarRobot.() -> Unit): NavigationToolbarRobot.Transition {
mDevice.waitNotNull(Until.findObject(By.desc("Tabs")))
tabsCounter().click(LONG_CLICK_DURATION)
NavigationToolbarRobot().interact()
return NavigationToolbarRobot.Transition()
}
fun openNotificationShade(interact: NotificationRobot.() -> Unit): NotificationRobot.Transition {
mDevice.openNotification()
@ -1263,6 +1299,13 @@ class BrowserRobot {
surveyNoThanksButton.waitForExists(waitingTime)
surveyNoThanksButton.click()
BrowserRobot().interact()
return Transition()
}
fun clickHomeScreenSurveyCloseButton(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
homescreenSurveyCloseButton.waitForExists(waitingTime)
homescreenSurveyCloseButton.click()
BrowserRobot().interact()
return Transition()
}
@ -1421,3 +1464,6 @@ private val surveyButton =
private val surveyNoThanksButton =
itemContainingText(getStringResource(R.string.preferences_not_take_survey))
private val homescreenSurveyCloseButton =
itemWithDescription("Close")

@ -17,12 +17,14 @@ 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 androidx.test.uiautomator.UiSelector
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.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.home.topsites.TopSitesTestTag
@ -37,7 +39,7 @@ class ComposeTopSitesRobot(private val composeTestRule: HomeActivityComposeTestR
@OptIn(ExperimentalTestApi::class)
fun verifyExistingTopSiteItem(vararg titles: String) {
titles.forEach { title ->
composeTestRule.waitUntilAtLeastOneExists(hasText(title), waitingTime)
mDevice.findObject(UiSelector().textContains(title)).waitForExists(waitingTimeShort)
composeTestRule.topSiteItem(title).assertExists()
}
}

@ -87,11 +87,10 @@ class HomeScreenRobot {
fun verifyHomeScreen() = assertItemWithResIdExists(homeScreen)
fun verifyPrivateBrowsingHomeScreen() {
fun verifyPrivateBrowsingHomeScreenItems() {
verifyHomeScreenAppBarItems()
assertItemContainingTextExists(itemContainingText(privateSessionMessage))
verifyCommonMythsLink()
verifyNavigationToolbarItems()
}
fun verifyHomeScreenAppBarItems() =

@ -147,23 +147,6 @@ class NavigationToolbarRobot {
class Transition {
private lateinit var sessionLoadedIdlingResource: SessionLoadedIdlingResource
fun goBackToWebsite(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
openEditURLView()
clearAddressBarButton().click()
assertTrue(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/mozac_browser_toolbar_edit_url_view")
.textContains(""),
).waitForExists(waitingTime),
)
goBackButton()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun enterURLAndEnterToBrowser(
url: Uri,
interact: BrowserRobot.() -> Unit,
@ -298,14 +281,23 @@ class NavigationToolbarRobot {
return BrowserRobot.Transition()
}
fun goBack(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
goBackButton()
fun goBackToHomeScreen(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
mDevice.pressBack()
mDevice.waitForWindowUpdate(packageName, waitingTimeShort)
HomeScreenRobot().interact()
return HomeScreenRobot.Transition()
}
fun closeTabFromShortcutsMenu(interact: NavigationToolbarRobot.() -> Unit): NavigationToolbarRobot.Transition {
fun openTabButtonShortcutsMenu(interact: NavigationToolbarRobot.() -> Unit): Transition {
mDevice.waitNotNull(Until.findObject(By.desc("Tabs")))
tabsCounter().click(LONG_CLICK_DURATION)
NavigationToolbarRobot().interact()
return Transition()
}
fun closeTabFromShortcutsMenu(interact: NavigationToolbarRobot.() -> Unit): Transition {
mDevice.waitForIdle(waitingTime)
onView(withId(R.id.mozac_browser_menu_recyclerView))
@ -319,10 +311,10 @@ class NavigationToolbarRobot {
)
NavigationToolbarRobot().interact()
return NavigationToolbarRobot.Transition()
return Transition()
}
fun openTabFromShortcutsMenu(interact: SearchRobot.() -> Unit): SearchRobot.Transition {
fun openNewTabFromShortcutsMenu(interact: SearchRobot.() -> Unit): SearchRobot.Transition {
mDevice.waitForIdle(waitingTime)
onView(withId(R.id.mozac_browser_menu_recyclerView))
@ -413,9 +405,10 @@ private fun awesomeBar() =
mDevice.findObject(UiSelector().resourceId("$packageName:id/mozac_browser_toolbar_edit_url_view"))
private fun threeDotButton() = onView(withId(R.id.mozac_browser_toolbar_menu))
private fun tabTrayButton() = onView(withId(R.id.tab_button))
private fun tabsCounter() =
mDevice.findObject(By.res("$packageName:id/counter_root"))
private fun fillLinkButton() = onView(withId(R.id.fill_link_from_clipboard))
private fun clearAddressBarButton() = itemWithResId("$packageName:id/mozac_browser_toolbar_clear_view")
private fun goBackButton() = mDevice.pressBack()
private fun readerViewToggle() =
onView(withParent(withId(R.id.mozac_browser_toolbar_page_actions)))

@ -117,23 +117,26 @@ class NotificationRobot {
shouldDismissNotification: Boolean,
canExpandNotification: Boolean = true,
) {
// In case it fails, retry max 6x the swipe action on download system notifications
for (i in 1..6) {
// In case it fails, retry max 3x the swipe action on download system notifications
for (i in 1..RETRY_COUNT) {
try {
// Swipe left the download system notification
if (direction == "Left") {
itemContainingText(appName)
.also {
it.waitForExists(waitingTime)
it.swipeLeft(3)
}
} else {
// Swipe right the download system notification
itemContainingText(appName)
.also {
it.waitForExists(waitingTime)
it.swipeRight(3)
}
var retries = 0
while (itemContainingText(appName).exists() && retries++ < 3) {
// Swipe left the download system notification
if (direction == "Left") {
itemContainingText(appName)
.also {
it.waitForExists(waitingTime)
it.swipeLeft(3)
}
} else {
// Swipe right the download system notification
itemContainingText(appName)
.also {
it.waitForExists(waitingTime)
it.swipeRight(3)
}
}
}
// Not all download related system notifications can be dismissed
if (shouldDismissNotification) {
@ -144,7 +147,7 @@ class NotificationRobot {
break
} catch (e: AssertionError) {
if (i == 6) {
if (i == RETRY_COUNT) {
throw e
} else {
notificationShade {
@ -167,7 +170,7 @@ class NotificationRobot {
fun clickNotification(notificationMessage: String) {
mDevice.findObject(UiSelector().text(notificationMessage)).waitForExists(waitingTime)
mDevice.findObject(UiSelector().text(notificationMessage)).click()
mDevice.findObject(UiSelector().text(notificationMessage)).clickAndWaitForNewWindow(waitingTimeShort)
}
class Transition {

@ -16,6 +16,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.click
/**
@ -89,6 +90,14 @@ class ReaderViewRobot {
}
class Transition {
fun closeAppearanceMenu(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
mDevice.pressBack()
BrowserRobot().interact()
return BrowserRobot.Transition()
}
fun toggleSansSerif(interact: ReaderViewRobot.() -> Unit): Transition {
fun sansSerifButton() =
onView(

@ -224,7 +224,7 @@ class SettingsSubMenuAddonsManagerRobot {
isDescendantOfA(withId(R.id.add_on_item)),
hasSibling(hasDescendant(withText(addonName))),
),
).check(matches(withEffectiveVisibility(Visibility.GONE)))
).check(matches(withEffectiveVisibility(Visibility.INVISIBLE)))
}
private fun cancelInstall() {
@ -267,7 +267,7 @@ class SettingsSubMenuAddonsManagerRobot {
hasDescendant(withText("uBlock Origin")),
hasDescendant(withText("Finally, an efficient wide-spectrum content blocker. Easy on CPU and memory.")),
hasDescendant(withId(R.id.rating)),
hasDescendant(withId(R.id.users_count)),
hasDescendant(withId(R.id.review_count)),
),
),
hasDescendant(withId(R.id.add_button)),

@ -7,7 +7,13 @@ package org.mozilla.fenix.ui.robots
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
import androidx.test.uiautomator.UiSelector
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.click
/**
@ -41,5 +47,35 @@ class SettingsSubMenuExperimentsRobot {
checkNotNull(experiment)
}
fun verifyExperimentEnrolled(title: String) {
itemContainingText(title).click()
assertTrue(
checkIcon().waitForExists(waitingTimeShort),
)
goBackButton().click()
}
fun verifyExperimentNotEnrolled(title: String) {
itemContainingText(title).click()
assertFalse(
checkIcon().waitForExists(waitingTimeShort),
)
goBackButton().click()
}
fun unenrollfromExperiment(title: String) {
val branch = itemWithResId("$packageName:id/nimbus_branch_name")
itemContainingText(title).click()
assertTrue(
checkIcon().waitForExists(waitingTimeShort),
)
branch.click()
assertFalse(
checkIcon().waitForExists(waitingTimeShort),
)
}
}
private fun goBackButton() = onView(withContentDescription(R.string.action_bar_up_description))
private fun checkIcon() = itemWithResId("$packageName:id/selected_icon")

@ -96,7 +96,7 @@ class SettingsSubMenuSearchRobot {
}
fun verifyAddressBarSectionHeader() {
onView(withText("Address bar")).check(matches(isDisplayed()))
onView(withText("Address bar - Firefox Suggest")).check(matches(isDisplayed()))
}
fun verifyDefaultSearchEngineList() {
@ -402,7 +402,7 @@ class EngineShortcut(
private val defaultSearchEngineHeader = onView(withText("Default search engine"))
private val manageSearchShortcutsHeader = onView(withText("Manage search shortcuts"))
private val manageSearchShortcutsHeader = onView(withText("Manage alternative search engines"))
private fun searchHistorySwitchButton(): ViewInteraction {
onView(withId(androidx.preference.R.id.recycler_view)).perform(

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

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

Loading…
Cancel
Save