Compare commits

..

68 Commits

Author SHA1 Message Date
runner dbc6b319b8 Strings - app/src/main/res/values-uk/strings.xml 2022-07-16 23:49:40 -04:00
runner ccb3d86a7d Strings - app/src/main/res/values-pl/strings.xml 2022-07-16 23:49:40 -04:00
runner 23a8fe907d Strings - app/src/main/res/values-oc/strings.xml 2022-07-16 23:49:40 -04:00
runner 7a3ab8eb1b Strings - app/src/main/res/values-ka/strings.xml 2022-07-16 23:49:40 -04:00
runner a775df7f4a Strings - app/src/main/res/values-it/strings.xml 2022-07-16 23:49:40 -04:00
runner 03174492af Strings - app/src/main/res/values-eo/strings.xml 2022-07-16 23:49:40 -04:00
runner c9999c9a08 Strings - app/src/main/res/values-el/strings.xml 2022-07-16 23:49:40 -04:00
runner 8416c7624b Strings - app/src/main/res/values-zh-rCN/strings.xml 2022-07-16 13:25:44 -04:00
runner 0d1fbec00a Strings - app/src/main/res/values-vi/strings.xml 2022-07-16 13:25:44 -04:00
runner 326c54362a Strings - app/src/main/res/values-nb-rNO/strings.xml 2022-07-16 13:25:44 -04:00
runner 614b6b3ee2 Strings - app/src/main/res/values-eu/strings.xml 2022-07-16 13:25:44 -04:00
runner 938883e589 Strings - app/src/main/res/values-da/strings.xml 2022-07-16 13:25:44 -04:00
runner fc471fd653 Strings - app/src/main/res/values-be/strings.xml 2022-07-16 13:25:44 -04:00
runner 7dc5b50559 Strings - app/src/main/res/values-ja/strings.xml 2022-07-15 10:22:35 +03:00
runner 8031115eab Strings - app/src/main/res/values-es-rAR/strings.xml 2022-07-15 10:22:35 +03:00
Mozilla Releng Treescript b5da40cc0d Automatic version bump CLOSED TREE NO BUG a=release 2022-07-15 04:03:03 +00:00
github-actions[bot] ea47fd8cb0
Update to Android-Components 103.0.8. (#26035)
Co-authored-by: MickeyMoz <sebastian@mozilla.com>
2022-07-14 23:38:37 -04:00
runner 1aee502270 Strings - app/src/main/res/values-sv-rSE/strings.xml 2022-07-14 13:44:59 +03:00
runner e973baafa6 Strings - app/src/main/res/values-nl/strings.xml 2022-07-14 13:44:59 +03:00
runner 553ccbc2d4 Strings - app/src/main/res/values-is/strings.xml 2022-07-14 13:44:59 +03:00
runner 65aac1f1ee Strings - app/src/main/res/values-gn/strings.xml 2022-07-14 13:44:59 +03:00
runner f712a3137d Strings - app/src/main/res/values-fy-rNL/strings.xml 2022-07-14 13:44:59 +03:00
runner 27a5dbf43a Strings - app/src/main/res/values-cy/strings.xml 2022-07-14 13:44:59 +03:00
runner 402be76d8a Strings - app/src/main/res/values-zh-rTW/strings.xml 2022-07-13 00:02:29 -04:00
runner 683be63691 Strings - app/src/main/res/values-tr/strings.xml 2022-07-13 00:02:29 -04:00
runner 3b94b67039 Strings - app/src/main/res/values-pt-rPT/strings.xml 2022-07-13 00:02:29 -04:00
runner d9cfb825af Strings - app/src/main/res/values-pt-rBR/strings.xml 2022-07-13 00:02:29 -04:00
runner c9c2ac96e1 Strings - app/src/main/res/values-in/strings.xml 2022-07-13 00:02:29 -04:00
runner e27ea84e56 Strings - app/src/main/res/values-fr/strings.xml 2022-07-13 00:02:29 -04:00
runner b77fe0d294 Strings - app/src/main/res/values-fi/strings.xml 2022-07-13 00:02:29 -04:00
runner 8a341fd621 Strings - app/src/main/res/values-en-rGB/strings.xml 2022-07-13 00:02:29 -04:00
github-actions[bot] a354b73d8f
Update to Android-Components 103.0.7. (#26005)
Co-authored-by: MickeyMoz <sebastian@mozilla.com>
2022-07-12 22:37:47 -04:00
runner 4c5cb92fdf Strings - app/src/main/res/values-uk/strings.xml 2022-07-12 12:55:00 -04:00
runner 444437cd27 Strings - app/src/main/res/values-tg/strings.xml 2022-07-12 12:55:00 -04:00
runner 1f093c4585 Strings - app/src/main/res/values-sk/strings.xml 2022-07-12 12:55:00 -04:00
runner b645315a5c Strings - app/src/main/res/values-ru/strings.xml 2022-07-12 12:55:00 -04:00
runner 3c6c4c3b4e Strings - app/src/main/res/values-ko/strings.xml 2022-07-12 12:55:00 -04:00
runner e63880796b Strings - app/src/main/res/values-it/strings.xml 2022-07-12 12:55:00 -04:00
runner cbab3912e4 Strings - app/src/main/res/values-ia/strings.xml 2022-07-12 12:55:00 -04:00
runner 89acc2f92d Strings - app/src/main/res/values-hu/strings.xml 2022-07-12 12:55:00 -04:00
runner e58398fb77 Strings - app/src/main/res/values-hsb/strings.xml 2022-07-12 12:55:00 -04:00
runner 55bf1f6389 Strings - app/src/main/res/values-iw/strings.xml 2022-07-12 12:55:00 -04:00
runner 46533ac4d8 Strings - app/src/main/res/values-fr/strings.xml 2022-07-12 12:55:00 -04:00
runner 69353cf813 Strings - app/src/main/res/values-es-rMX/strings.xml 2022-07-12 12:55:00 -04:00
runner 857a87f3db Strings - app/src/main/res/values-es-rCL/strings.xml 2022-07-12 12:55:00 -04:00
runner 8858e3c445 Strings - app/src/main/res/values-en-rCA/strings.xml 2022-07-12 12:55:00 -04:00
runner bb157fa317 Strings - app/src/main/res/values-dsb/strings.xml 2022-07-12 12:55:00 -04:00
runner c4523feba7 Strings - app/src/main/res/values-de/strings.xml 2022-07-12 12:55:00 -04:00
Arturo Mejia 9aa86cd7bb For #25938: Address MessageCard text not adapting to the dark theme
(cherry picked from commit e1b7262ca8)
2022-07-11 14:58:34 -04:00
runner 7d343dee3f Strings - app/src/main/res/values-pa-rIN/strings.xml 2022-07-10 22:23:06 -04:00
Mozilla Releng Treescript 39cfc131d1 Automatic version bump CLOSED TREE NO BUG a=release 2022-07-11 01:11:21 +00:00
github-actions[bot] 9df4e7a39d
Update to Android-Components 103.0.6. (#25968)
Co-authored-by: MickeyMoz <sebastian@mozilla.com>
2022-07-10 20:42:23 -04:00
runner 8db9993500 Strings - app/src/main/res/values-en-rCA/strings.xml 2022-07-08 22:56:48 -04:00
mergify[bot] 9ea848b543
For #25933 - Ensure sponsored tiles are enable if enrolled in active experiment (#25947)
(cherry picked from commit 1207180aa8)

Co-authored-by: Gabriel Luong <gabriel.luong@gmail.com>
2022-07-08 10:35:03 -04:00
rxu 6904f4ecd5 Disable marketing telemetry until privacy pop window approved in Mozillaonline builds
(cherry picked from commit f7826c41bf)
2022-07-08 10:40:28 +03:00
Mozilla Releng Treescript 95fb1e7395 Automatic version bump CLOSED TREE NO BUG a=release 2022-07-08 01:20:58 +00:00
github-actions[bot] 4e393a9230
Update to Android-Components 103.0.5. (#25940)
Co-authored-by: MickeyMoz <sebastian@mozilla.com>
2022-07-07 20:51:49 -04:00
Arturo Mejia 280c0eb2bc For #25736: Add experiment for Total cookie protection.
(cherry picked from commit 8c752c3be1)
2022-07-06 15:56:37 -04:00
runner 1008d7d754 Strings - app/src/main/res/values-sat/strings.xml 2022-07-06 00:26:57 -04:00
github-actions[bot] bf028904e5
Update to Android-Components 103.0.4. (#25896)
Co-authored-by: MickeyMoz <sebastian@mozilla.com>
2022-07-05 23:53:30 -04:00
Mozilla Releng Treescript a3dae43b3c Automatic version bump CLOSED TREE NO BUG a=release 2022-07-04 08:31:04 +00:00
github-actions[bot] 3d8e729195
Update to Android-Components 103.0.3. (#25870)
Co-authored-by: MickeyMoz <sebastian@mozilla.com>
2022-07-03 20:34:17 -04:00
github-actions[bot] d0471d167f
Update to Android-Components 103.0.2. (#25850)
Co-authored-by: MickeyMoz <sebastian@mozilla.com>
2022-07-01 05:29:07 -04:00
runner 5495a39ee4 Strings - app/src/main/res/values-da/strings.xml 2022-06-29 15:36:26 -04:00
github-actions[bot] 53f0887225
Update to Android-Components 103.0.1. (#25793)
Co-authored-by: MickeyMoz <sebastian@mozilla.com>
2022-06-28 23:30:40 -04:00
runner 455b1e98f2 Strings - app/src/main/res/values-nn-rNO/strings.xml 2022-06-28 11:24:41 -04:00
Mozilla Releng Treescript cdbe5fee57 Automatic version bump CLOSED TREE NO BUG a=release 2022-06-27 23:01:09 +00:00
Donal Meehan 6e0ad035e3
Set version to 103.0.0 2022-06-27 17:57:26 -04:00
1437 changed files with 27788 additions and 62228 deletions

View File

@ -12,28 +12,21 @@ jobs:
when:
- {hour: 5, minute: 0}
- {hour: 17, minute: 0}
- name: nightly-test
job:
type: decision-task
treeherder-symbol: Nt
target-tasks-method: nightly-test
when:
- {hour: 5, minute: 0}
- name: fennec-production
job:
type: decision-task
treeherder-symbol: fennec-production
target-tasks-method: fennec-production
when: [] # Force hook only
- name: bump-android-components
job:
type: decision-task
treeherder-symbol: bump-ac
target-tasks-method: bump_android_components
when: [{hour: 15, minute: 30}]
- name: screenshots
job:
type: decision-task
treeherder-symbol: screenshots-D
target-tasks-method: screenshots
when: [{weekday: 'Monday', hour: 10, minute: 0}]
- name: legacy-api-ui-tests
job:
type: decision-task
treeherder-symbol: legacy-api-ui
target-tasks-method: legacy_api_ui_tests
when: [] # temporarily unscheduled

View File

@ -1,6 +1,4 @@
[*.{kt,kts}]
ij_kotlin_allow_trailing_comma_on_call_site=true
ij_kotlin_allow_trailing_comma=true
[*]
insert_final_newline = true
# Disabling rules that were added in the latest versions of ktlint
# tracking here: https://github.com/mozilla-mobile/fenix/issues/4861
disabled_rules=import-ordering

View File

@ -1,20 +1,23 @@
---
cookie-banners:
description: Features for cookie banner handling.
default-browser-message:
description: A small feature allowing experiments on the placement of a default browser message.
hasExposure: true
exposureDescription: ""
variables:
sections-enabled:
type: json
description: This property provides a lookup table of whether or not the given section should be enabled.
growth-data:
description: A feature measuring campaign growth data
message-location:
type: string
description: Where is the message to be put.
engine-settings:
description: Contains a set of settings for controlling the web engine configurations.
hasExposure: true
exposureDescription: ""
variables:
enabled:
tabs-prioritization-enabled:
type: boolean
description: "If true, the feature is active"
description: "If true, enables tabs prioritization feature."
total-cookie-protection-enabled:
type: boolean
description: "If true, enables the total cookie protection in all browsing modes."
homescreen:
description: The homescreen that the user goes to when they press home or new tab.
hasExposure: true
@ -37,9 +40,6 @@ messaging:
messages:
type: json
description: A growable collection of messages
notification-config:
type: json
description: Configuration of the notification worker for all notification messages.
on-control:
type: string
description: What should be displayed when a control message is selected.
@ -52,14 +52,6 @@ messaging:
triggers:
type: json
description: "A collection of out the box trigger expressions. Each entry maps to a valid JEXL expression.\n"
mr2022:
description: Features for MR 2022.
hasExposure: true
exposureDescription: ""
variables:
sections-enabled:
type: json
description: This property provides a lookup table of whether or not the given section should be enabled.
nimbus-validation:
description: A feature that does not correspond to an application feature suitable for showing that Nimbus is working. This should never be used in production.
hasExposure: true
@ -74,22 +66,14 @@ nimbus-validation:
settings-title:
type: string
description: The title of displayed in the Settings screen and app menu.
pre-permission-notification-prompt:
description: A feature that shows the pre-permission notification prompt.
pocket-sponsored-stories:
description: A feature showing sponsored stories in between the other Pocket recommended stories on homescreen.
hasExposure: true
exposureDescription: ""
variables:
enabled:
type: boolean
description: "if true, the pre-permission notification prompt is shown to the user."
re-engagement-notification:
description: A feature that shows the re-enagement notification if the user is inactive.
hasExposure: true
exposureDescription: ""
variables:
enabled:
type: boolean
description: "If true, the re-engagement notification is shown to the inactive user."
description: "If true, the Pocket stories shown on homescreen should contain sponsored stories also."
search-term-groups:
description: A feature allowing the grouping of URLs around the search term that it came from.
hasExposure: true

View File

@ -1,5 +0,0 @@
# .git-blame-ignore-revs
# For #27667 - Remove import-ordering from the list of disabled ktlint rules (#27680)
9654b4dfb122b54b04369fe80a2f9c95811478e8
# For #26844: Fix ktlint issues and remove them from baseline. (#26901)
ffcef5ff2e3f78b6972dd16551f3f653b7035ccc

View File

@ -1,13 +0,0 @@
---
name: "\U0001F6A8 Intermittent Unit Test Issue"
about: Create an issue to help log a Unit Test failure
labels: "eng:intermittent-test"
title: "Intermittent Unit Test failure - <Classname.testName>"
assignees: ''
---
### Test Run:
Provide a test run report link here showcasing the problem (e.g, Taskcluster), and a link to the source Github event
### Stacktrace:
### Build:

View File

@ -6,18 +6,8 @@
- [ ] **Screenshots**: This PR includes screenshots or GIFs of the changes made or an explanation of why it does not
- [ ] **Accessibility**: The code in this PR follows [accessibility best practices](https://github.com/mozilla-mobile/shared-docs/blob/master/android/accessibility_guide.md) or does not include any user facing features. In addition, it includes a screenshot of a successful [accessibility scan](https://play.google.com/store/apps/details?id=com.google.android.apps.accessibility.auditor&hl=en_US) to ensure no new defects are added to the product.
### QA
<!-- Before submitting the PR, please address each item -->
- [x] **QA Needed**
### To download an APK when reviewing a PR (after all CI tasks finished running):
1. Click on `Checks` at the top of the PR page.
2. Click on the `firefoxci-taskcluster` group on the left to expand all tasks.
3. Click on the `build-debug` task.
4. Click on `View task in Taskcluster` in the new `DETAILS` section.
5. The APK links should be on the right side of the screen, named for each CPU architecture.
### GitHub Automation
<!-- Do not add anything below this line -->
Used by GitHub Actions.
### To download an APK when reviewing a PR:
1. click on Show All Checks,
2. click Details next to "Taskcluster (pull_request)" after it appears and then finishes with a green checkmark,
3. click on the "Fenix - assemble" task, then click "Run Artifacts".
4. the APK links should be on the left side of the screen, named for each CPU architecture

View File

@ -3,7 +3,7 @@ on: [pull_request]
jobs:
run-build:
runs-on: ubuntu-20.04
if: ${{ false }}
if: github.event.pull_request.head.repo.full_name != github.repository && github.actor != 'MickeyMoz'
steps:
- name: Checkout repository
uses: actions/checkout@v2
@ -108,6 +108,7 @@ jobs:
run-ui:
runs-on: macos-11
if: ${{ false }}
timeout-minutes: 60
strategy:
matrix:

View File

@ -1,42 +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/
name: "Fenix - Update Nimbus Experiments"
on:
schedule:
- cron: '*/30 * * * *'
workflow_dispatch: {}
jobs:
update-nimbus-experiments:
name: "Update Nimbus Experiments"
runs-on: ubuntu-latest
steps:
- name: "Checkout Main Branch"
uses: actions/checkout@v2
with:
path: fenix
ref: main
fetch-depth: 0
- name: "Update Experiments JSON"
id: update-experiments-json
uses: mozilla-mobile/update-experiments@v2
with:
repo-path: fenix
output-path: app/src/main/res/raw/initial_experiments.json
experimenter-url: https://experimenter.services.mozilla.com/api/v6/experiments-first-run/
app-name: fenix
branch: automation/update-nimbus-experiments
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
if: steps.update-experiments-json.outputs.changed == 1 && steps.update-experiments-json.outputs.changed-branch == 1
with:
token: ${{ secrets.GITHUB_TOKEN }}
path: fenix
branch: automation/update-nimbus-experiments
commit-message: "update initial_experiments.json based on the current first-run experiments in experimenter"
title: "Update initial experiments JSON for Nimbus"
body: "This (automated) PR updates the initial_experiments.json on the `main` branch"
delete-branch: true

View File

@ -1,10 +0,0 @@
---
name: Glean probe-scraper
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
glean-probe-scraper:
uses: mozilla/probe-scraper/.github/workflows/glean.yaml@main

View File

@ -1,21 +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/
name: Issue Linker
on:
pull_request_target:
branches:
- main
jobs:
issue_linker:
runs-on: ubuntu-latest
steps:
- name: Issue Linker
uses: gabrielluong/issue-linker@1.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
commit-regexp: "#(\\d+)+"
section: "### GitHub Automation"

View File

@ -1,20 +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/
name: Tag Milestone
on:
issues:
types:
- closed
jobs:
milestone:
runs-on: ubuntu-latest
if: github.actor == 'mergify[bot]'
steps:
- name: Tag Milestone
uses: gabrielluong/milestone@1.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,22 +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/
name: QA Needed
on:
pull_request_target:
branches:
- main
jobs:
qa_needed:
runs-on: ubuntu-latest
steps:
- name: QA Needed
uses: gabrielluong/qa-needed@1.0.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
label: "eng:reopen-for-qa"
check-regexp: "- \\[([ xX]?)\\] \\*\\*QA Needed\\*\\*"
commit-regexp: "#(\\d+)+"

View File

@ -1,21 +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/
name: Reopen for QA Needed
on:
issues:
types:
- closed
jobs:
reopen_qa_needed:
runs-on: ubuntu-latest
steps:
- name: Reopen for QA Needed
uses: gabrielluong/reopen-for-qa-needed@1.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
reopen-label: "eng:reopen-for-qa"
qa-label: "eng:qa:needed"

View File

@ -2,7 +2,7 @@
# 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/
name: "Fenix - Sync Strings"
name: "Sync Strings"
on:
schedule:
@ -15,10 +15,10 @@ jobs:
steps:
- name: "Discover Fenix Beta Version"
id: fenix-beta-version
uses: mozilla-mobile/fenix-beta-version@4.1.0
uses: mozilla-mobile/fenix-beta-version@2.0.0
- name: "Skip non-beta versions"
uses: andymckay/cancel-action@0.2
if: ${{ steps.fenix-beta-version.outputs.beta_version == '' }}
if: ${{ steps.fenix-beta-version.outputs.fenix-beta-version == '' }}
- name: "Checkout Master Branch"
uses: actions/checkout@v2
with:
@ -28,7 +28,7 @@ jobs:
uses: actions/checkout@v2
with:
path: beta
ref: "releases_v${{ steps.fenix-beta-version.outputs.beta_version }}.0.0"
ref: "releases_v${{ steps.fenix-beta-version.outputs.fenix-beta-version }}.0.0"
- name: "Sync Strings"
uses: mozilla-mobile/sync-strings-action@1.0.1
with:
@ -39,6 +39,7 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
path: beta
branch: automation/sync-strings-${{ steps.fenix-beta-version.outputs.beta_version }}
title: "Sync Strings from main to releases_${{steps.fenix-beta-version.outputs.beta_version}}.0"
body: "This (automated) PR syncs strings from `main` to `releases_${{steps.fenix-beta-version.outputs.beta_version}}.0.0`"
branch: automation/sync-strings-${{ steps.fenix-beta-version.outputs.major-beta-version }}
title: "Sync Strings from main to releases_${{steps.fenix-beta-version.outputs.fenix-beta-version}}.0"
body: "This (automated) PR syncs strings from `main` to `releases_${{steps.fenix-beta-version.outputs.fenix-beta-version}}.0.0`"
labels: needs:review

View File

@ -2,7 +2,7 @@
# 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/
name: "Fenix - Update Android-Components"
name: "Update Android-Components"
on:
schedule:
@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: "Update Android-Components"
uses: mozilla-mobile/relbot@5.0.2
uses: mozilla-mobile/relbot@master
if: github.repository == 'mozilla-mobile/fenix'
with:
project: fenix

View File

@ -1,9 +1,7 @@
queue_rules:
- name: default
conditions:
- or:
- status-success=complete-pr
- status-success=complete-push
- status-success=pr-complete
pull_request_rules:
- name: Resolve conflict
conditions:
@ -11,20 +9,50 @@ pull_request_rules:
actions:
comment:
message: This pull request has conflicts when rebasing. Could you fix it @{{author}}? 🙏
- name: Android-Components bump - Auto Merge
- name: MickeyMoz - Auto Merge
conditions:
- and:
- files=buildSrc/src/main/java/AndroidComponents.kt
- -files~=^(?!buildSrc/src/main/java/AndroidComponents.kt).+$
- author=github-actions[bot]
- status-success=complete-push
- or:
- and:
- base=main
- head~=^relbot/AC-Nightly-.+
- and:
- base~=^releases[_/].*
- head~=^relbot/fenix-\d+
- author=MickeyMoz
- status-success=pr-complete
- files~=(Gecko.kt|AndroidComponents.kt)
actions:
review:
type: APPROVE
message: MickeyMoz 💪
queue:
method: rebase
name: default
rebase_fallback: none
- name: L10N - Auto Merge
conditions:
- author=mozilla-l10n-automation-bot
- status-success=pr-complete
- files~=(strings.xml|l10n.toml)
actions:
review:
type: APPROVE
message: LGTM 😎
queue:
method: rebase
name: default
rebase_fallback: none
- name: Release automation (Old)
conditions:
- base~=releases[_/].*
- author=github-actions[bot]
# Listing checks manually beause we do not have a "push complete" check yet.
- check-success=build-android-test-debug
- check-success=build-debug
- check-success=build-nightly-simulation
- check-success=lint-compare-locales
- check-success=lint-detekt
- check-success=lint-ktlint
- check-success=lint-lint
- check-success=signing-android-test-debug
- check-success=signing-debug
- check-success=signing-nightly-simulation
- check-success=test-debug
- check-success=ui-test-x86-debug
- files~=(AndroidComponents.kt)
actions:
review:
type: APPROVE
@ -33,42 +61,41 @@ pull_request_rules:
method: rebase
name: default
rebase_fallback: none
- name: L10N - Auto Merge
delete_head_branch:
force: false
- name: Release automation (New)
conditions:
- and:
- files~=^(l10n.toml|app/src/main/res/values[A-Za-z-]*/strings\.xml)$
# /!\ The line above doesn't prevent random files to be changed alongside
# l10n ones. That's why the additional condition exists below. For more
# information: https://docs.mergify.com/conditions/#how-to-match-lists
- -files~=^(?!(l10n.toml|app/src/main/res/values[A-Za-z-]*/strings\.xml)).+$
- or:
- and:
- author=mozilla-l10n-automation-bot
- base=main
- head=import-l10n
- status-success=complete-pr
- and:
- author=github-actions[bot]
- base~=^releases[_/].*
- head~=^automation/sync-strings-\d+
- status-success=complete-push
# Taskcluster only runs on git-push events because github-actions[bot] is not considered
# a collaborator, so pull request events are triggered. That said, github-actions[bot]
# doesn't create the PR on a separate fork (unlike mozilla-l10n-automation-bot). That's
# why git-push events are taken into account
- base~=releases[_/].*
- author=github-actions[bot]
# Listing checks manually beause we do not have a "push complete" check yet.
- check-success=build-android-test-beta
- check-success=build-android-test-debug
- check-success=build-beta-firebase
- check-success=build-debug
- check-success=build-nightly-simulation
- check-success=lint-compare-locales
- check-success=lint-detekt
- check-success=lint-ktlint
- check-success=lint-lint
- check-success=signing-android-test-beta
- check-success=signing-beta-firebase
- check-success=signing-nightly-simulation
- check-success=test-debug
- check-success=ui-test-x86-beta
- files~=(AndroidComponents.kt)
actions:
review:
type: APPROVE
message: LGTM 😎
message: 🚢
queue:
method: squash
method: rebase
name: default
rebase_fallback: none
delete_head_branch:
force: false
- name: Needs landing - Rebase
conditions:
- or:
- check-success=complete-pr
- check-success=complete-push
- check-success=pr-complete
- label=pr:needs-landing
- "#approved-reviews-by>=1"
- -draft
@ -81,10 +108,8 @@ pull_request_rules:
rebase_fallback: none
- name: Needs landing - Squash
conditions:
- or:
- check-success=complete-pr
- check-success=complete-push
- label=pr:needs-landing-squashed
- check-success=pr-complete
- label=pr:needs-landing-squashed
- "#approved-reviews-by>=1"
- -draft
- label!=pr:work-in-progress

View File

@ -13,14 +13,14 @@ tasks:
$if: 'tasks_for in ["cron", "action"]'
then: '${tasks_for}@noreply.mozilla.org'
else:
$if: 'tasks_for == "github-push"'
then:
$if: 'event.pusher.email'
then: '${event.pusher.email}'
else: '${event.pusher.name}@users.noreply.github.com'
$if: 'event.sender.login == "bors[bot]"'
then: 'skaspari+mozlando@mozilla.com' # It must match what's in bors.toml
else:
$if: 'tasks_for == "github-pull-request"'
then: '${event.pull_request.user.login}@users.noreply.github.com'
$if: 'tasks_for == "github-push"'
then: '${event.pusher.email}'
else:
$if: 'tasks_for == "github-pull-request"'
then: '${event.pull_request.user.login}@users.noreply.github.com'
baseRepoUrl:
$if: 'tasks_for == "github-push"'
then: '${event.repository.html_url}'
@ -122,7 +122,7 @@ tasks:
name: "Decision Task for cron job ${cron.job_name}"
description: 'Created by a [cron task](https://firefox-ci-tc.services.mozilla.com/tasks/${cron.task_id})'
provisionerId: "${trustDomain}-${level}"
workerType: "decision-gcp"
workerType: "decision"
tags:
$if: 'tasks_for in ["github-push", "github-pull-request"]'
then:
@ -203,7 +203,7 @@ tasks:
chainOfTrust: true
# Note: This task is built server side without the context or tooling that
# exist in tree so we must hard code the hash
image: mozillareleases/taskgraph:decision-mobile-625975b642c148be4c6f1d8ee5cedf7399f5d0dd33d275ff69d5934e3082d4a9@sha256:bfb26700182486e1c6c52701baea6f386fa39e5e25417423c27845933605ad43
image: mozillareleases/taskgraph:decision-mobile-7e11b0cc3966ad9729e08b19551399b3343d3b385eac067b6335d4c34431a899@sha256:b309fa59efd59991ba286a326cb43b724c38e6f3872c52d0f85e96428899c2fc
maxRunTime: 1800
@ -215,7 +215,7 @@ tasks:
- bash
- -cx
- $let:
extraArgs:
extraArgs:
$if: 'tasks_for == "cron"'
then: '${cron.quoted_args}'
else: ''
@ -247,7 +247,7 @@ tasks:
'public':
type: 'directory'
path: '/builds/worker/artifacts'
expires:
expires:
$fromNow: '1 year'
'public/docker-contexts':
type: 'directory'
@ -256,7 +256,7 @@ tasks:
# decision task + the docker-image task deadlines.
# It is set to a week to allow for some time for
# debugging, but they are not useful long-term.
expires:
expires:
$fromNow: '7 day'
extra:

View File

@ -23,7 +23,7 @@ Please read the [Community Participation Guidelines](https://www.mozilla.org/en-
* Check out the [project wiki](https://github.com/mozilla-mobile/fenix/wiki) for more information.
* See [our guide on Writing Custom Lint Rules](https://github.com/mozilla-mobile/shared-docs/blob/master/android/writing_lint_rules.md).
* Localization happens on [Pontoon](https://pontoon.mozilla.org/projects/firefox-for-android/). Please get in touch with delphine (at) mozilla (dot) com directly for more information.
* Localization happens on [Pontoon](https://pontoon.mozilla.org/projects/android-l10n/). Please get in touch with delphine (at) mozilla (dot) com directly for more information.
**Beginners!** - Watch out for [Issues with the "Good First Issue" label](https://github.com/mozilla-mobile/fenix/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22). These are easy bugs that have been left for first timers to have a go, get involved and make a positive contribution to the project!
@ -199,12 +199,10 @@ raptorEnabled
If you're making changes to these projects and want to test them in Fenix, auto-publication workflow is the fastest, most reliable
way to do that.
In `local.properties`, specify a relative path to your local `android-components` and/or `application-services` projects. E.g.:
- `autoPublish.android-components.dir=../firefox-android/android-components`
In `local.properties`, specify a relative path to your local `android-components` and/or `application-services` checkouts. E.g.:
- `autoPublish.android-components.dir=../android-components`
- `autoPublish.application-services.dir=../application-services`
*Note that the Android Components project was already migrated to the new [firefox-android](https://github.com/mozilla-mobile/firefox-android) repository. Therefore, this auto publication workflow won't be neccessary for Android Components once Fenix is integrated in the new repository as well.*
Once these flags are set, your Fenix builds will include any local modifications present in these projects.
See a [demo of auto-publication workflow in action](https://www.youtube.com/watch?v=qZKlBzVvQGc).
@ -224,11 +222,6 @@ If you wish to use a Nimbus server during local development, you can add a `http
Testing experimental branches should be possible without a server.
### Using custom Glean servers during local development
If you wish to use a custom Glean server during local development, you can add a `https://` endpoint to the `local.properties` file.
- `glean.custom.server.url`
### GeckoView
Specify a relative path to your local `mozilla-central` checkout via `dependencySubstitutions.geckoviewTopsrcdir`,
and optional a path to m-c object directory via `dependencySubstitutions.geckoviewTopobjdir`.

View File

@ -2,7 +2,7 @@ import org.mozilla.fenix.gradle.tasks.ApkSizeTask
plugins {
id "com.jetbrains.python.envs" version "0.0.26"
id "com.google.protobuf" version "0.8.19"
id "com.google.protobuf" version "0.8.17"
}
apply plugin: 'com.android.application'
@ -47,7 +47,7 @@ android {
buildConfigField "String", "GIT_HASH", "\"\"" // see override in release builds for why it's blank.
// This should be the "public" base URL of AMO.
buildConfigField "String", "AMO_BASE_URL", "\"https://addons.mozilla.org\""
buildConfigField "String", "AMO_COLLECTION_NAME", "\"Extensions-for-Android\""
buildConfigField "String", "AMO_COLLECTION_NAME", "\"7dfae8669acc4312a65e8ba5553036\""
buildConfigField "String", "AMO_COLLECTION_USER", "\"mozilla\""
// These add-ons should be excluded for Mozilla Online builds.
buildConfigField "String[]", "MOZILLA_ONLINE_ADDON_EXCLUSIONS",
@ -59,8 +59,7 @@ android {
"\"foxyproxy@eric.h.jung\"," +
"\"{73a6fe31-595d-460b-a920-fcc0f8843232}\"," +
"\"jid1-BoFifL9Vbdl2zQ@jetpack\"," +
"\"woop-NoopscooPsnSXQ@jetpack\"," +
"\"adnauseam@rednoise.org\"" +
"\"woop-NoopscooPsnSXQ@jetpack\"" +
"}"
// This should be the base URL used to call the AMO API.
buildConfigField "String", "AMO_SERVER_URL", "\"https://services.addons.mozilla.org\""
@ -225,7 +224,7 @@ android {
}
composeOptions {
kotlinCompilerExtensionVersion = FenixVersions.androidx_compose_compiler
kotlinCompilerExtensionVersion = Versions.androidx_compose
}
}
@ -236,7 +235,7 @@ android.applicationVariants.all { variant ->
// Generate version codes for builds
// -------------------------------------------------------------------------------------------------
def isDebug = variant.buildType.resValues['bool/IS_DEBUG']?.value ?: false
def isDebug = variant.buildType.resValues['IS_DEBUG']?.value ?: false
def useReleaseVersioning = variant.buildType.buildConfigFields['USE_RELEASE_VERSIONING']?.value ?: false
println("----------------------------------------------")
@ -366,21 +365,6 @@ android.applicationVariants.all { variant ->
println("--")
}
// -------------------------------------------------------------------------------------------------
// Glean: Read custom server URL from local.properties of a local file if it exists
// -------------------------------------------------------------------------------------------------
print("Glean custom server URL: ")
if (gradle.hasProperty("localProperties.glean.custom.server.url")) {
def url=gradle.getProperty("localProperties.glean.custom.server.url")
buildConfigField 'String', 'GLEAN_CUSTOM_URL', url
println "(Added from local.properties file)"
} else {
buildConfigField 'String', 'GLEAN_CUSTOM_URL', 'null'
println("--")
}
// -------------------------------------------------------------------------------------------------
// BuildConfig: Set flag for official builds; similar to MOZILLA_OFFICIAL in mozilla-central.
// -------------------------------------------------------------------------------------------------
@ -465,164 +449,159 @@ configurations {
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
freeCompilerArgs += "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
freeCompilerArgs += "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
}
}
dependencies {
jnaForTest FenixDependencies.jna
jnaForTest Deps.jna
testImplementation files(configurations.jnaForTest.copyRecursive().files)
implementation FenixDependencies.mozilla_browser_engine_gecko
implementation Deps.mozilla_browser_engine_gecko
implementation FenixDependencies.kotlin_stdlib
implementation FenixDependencies.kotlin_coroutines
implementation FenixDependencies.kotlin_coroutines_android
testImplementation FenixDependencies.kotlin_coroutines_test
implementation FenixDependencies.androidx_appcompat
implementation FenixDependencies.androidx_constraintlayout
implementation FenixDependencies.androidx_coordinatorlayout
implementation FenixDependencies.google_accompanist_drawablepainter
implementation FenixDependencies.google_accompanist_insets
implementation Deps.kotlin_stdlib
implementation Deps.kotlin_coroutines
implementation Deps.kotlin_coroutines_android
testImplementation Deps.kotlin_coroutines_test
implementation Deps.androidx_appcompat
implementation Deps.androidx_constraintlayout
implementation Deps.androidx_coordinatorlayout
implementation FenixDependencies.sentry
implementation Deps.sentry
implementation FenixDependencies.mozilla_compose_awesomebar
implementation Deps.mozilla_compose_awesomebar
implementation FenixDependencies.mozilla_concept_awesomebar
implementation FenixDependencies.mozilla_concept_base
implementation FenixDependencies.mozilla_concept_engine
implementation FenixDependencies.mozilla_concept_menu
implementation FenixDependencies.mozilla_concept_push
implementation FenixDependencies.mozilla_concept_storage
implementation FenixDependencies.mozilla_concept_sync
implementation FenixDependencies.mozilla_concept_toolbar
implementation FenixDependencies.mozilla_concept_tabstray
implementation Deps.mozilla_concept_awesomebar
implementation Deps.mozilla_concept_base
implementation Deps.mozilla_concept_engine
implementation Deps.mozilla_concept_menu
implementation Deps.mozilla_concept_push
implementation Deps.mozilla_concept_storage
implementation Deps.mozilla_concept_sync
implementation Deps.mozilla_concept_toolbar
implementation Deps.mozilla_concept_tabstray
implementation FenixDependencies.mozilla_browser_domains
implementation FenixDependencies.mozilla_browser_icons
implementation FenixDependencies.mozilla_browser_menu
implementation FenixDependencies.mozilla_browser_menu2
implementation FenixDependencies.mozilla_browser_session_storage
implementation FenixDependencies.mozilla_browser_state
implementation FenixDependencies.mozilla_browser_storage_sync
implementation FenixDependencies.mozilla_browser_tabstray
implementation FenixDependencies.mozilla_browser_thumbnails
implementation FenixDependencies.mozilla_browser_toolbar
implementation Deps.mozilla_browser_domains
implementation Deps.mozilla_browser_icons
implementation Deps.mozilla_browser_menu
implementation Deps.mozilla_browser_menu2
implementation Deps.mozilla_browser_session_storage
implementation Deps.mozilla_browser_state
implementation Deps.mozilla_browser_storage_sync
implementation Deps.mozilla_browser_tabstray
implementation Deps.mozilla_browser_thumbnails
implementation Deps.mozilla_browser_toolbar
implementation FenixDependencies.mozilla_feature_addons
implementation FenixDependencies.mozilla_feature_accounts
implementation FenixDependencies.mozilla_feature_app_links
implementation FenixDependencies.mozilla_feature_autofill
implementation FenixDependencies.mozilla_feature_awesomebar
implementation FenixDependencies.mozilla_feature_contextmenu
implementation FenixDependencies.mozilla_feature_customtabs
implementation FenixDependencies.mozilla_feature_downloads
implementation FenixDependencies.mozilla_feature_intent
implementation FenixDependencies.mozilla_feature_media
implementation FenixDependencies.mozilla_feature_prompts
implementation FenixDependencies.mozilla_feature_push
implementation FenixDependencies.mozilla_feature_privatemode
implementation FenixDependencies.mozilla_feature_pwa
implementation FenixDependencies.mozilla_feature_qr
implementation FenixDependencies.mozilla_feature_search
implementation FenixDependencies.mozilla_feature_session
implementation FenixDependencies.mozilla_feature_syncedtabs
implementation FenixDependencies.mozilla_feature_toolbar
implementation FenixDependencies.mozilla_feature_tabs
implementation FenixDependencies.mozilla_feature_findinpage
implementation FenixDependencies.mozilla_feature_logins
implementation FenixDependencies.mozilla_feature_site_permissions
implementation FenixDependencies.mozilla_feature_readerview
implementation FenixDependencies.mozilla_feature_tab_collections
implementation FenixDependencies.mozilla_feature_recentlyclosed
implementation FenixDependencies.mozilla_feature_top_sites
implementation FenixDependencies.mozilla_feature_share
implementation FenixDependencies.mozilla_feature_accounts_push
implementation FenixDependencies.mozilla_feature_webauthn
implementation FenixDependencies.mozilla_feature_webcompat
implementation FenixDependencies.mozilla_feature_webnotifications
implementation FenixDependencies.mozilla_feature_webcompat_reporter
implementation Deps.mozilla_feature_addons
implementation Deps.mozilla_feature_accounts
implementation Deps.mozilla_feature_app_links
implementation Deps.mozilla_feature_autofill
implementation Deps.mozilla_feature_awesomebar
implementation Deps.mozilla_feature_contextmenu
implementation Deps.mozilla_feature_customtabs
implementation Deps.mozilla_feature_downloads
implementation Deps.mozilla_feature_intent
implementation Deps.mozilla_feature_media
implementation Deps.mozilla_feature_prompts
implementation Deps.mozilla_feature_push
implementation Deps.mozilla_feature_privatemode
implementation Deps.mozilla_feature_pwa
implementation Deps.mozilla_feature_qr
implementation Deps.mozilla_feature_search
implementation Deps.mozilla_feature_session
implementation Deps.mozilla_feature_syncedtabs
implementation Deps.mozilla_feature_toolbar
implementation Deps.mozilla_feature_tabs
implementation Deps.mozilla_feature_findinpage
implementation Deps.mozilla_feature_logins
implementation Deps.mozilla_feature_site_permissions
implementation Deps.mozilla_feature_readerview
implementation Deps.mozilla_feature_tab_collections
implementation Deps.mozilla_feature_recentlyclosed
implementation Deps.mozilla_feature_top_sites
implementation Deps.mozilla_feature_share
implementation Deps.mozilla_feature_accounts_push
implementation Deps.mozilla_feature_webauthn
implementation Deps.mozilla_feature_webcompat
implementation Deps.mozilla_feature_webnotifications
implementation Deps.mozilla_feature_webcompat_reporter
implementation FenixDependencies.mozilla_service_pocket
implementation FenixDependencies.mozilla_service_contile
implementation FenixDependencies.mozilla_service_digitalassetlinks
implementation FenixDependencies.mozilla_service_sync_autofill
implementation FenixDependencies.mozilla_service_sync_logins
implementation FenixDependencies.mozilla_service_firefox_accounts
implementation(FenixDependencies.mozilla_service_glean)
implementation FenixDependencies.mozilla_service_location
implementation FenixDependencies.mozilla_service_nimbus
implementation Deps.mozilla_service_pocket
implementation Deps.mozilla_service_contile
implementation Deps.mozilla_service_digitalassetlinks
implementation Deps.mozilla_service_sync_autofill
implementation Deps.mozilla_service_sync_logins
implementation Deps.mozilla_service_firefox_accounts
implementation(Deps.mozilla_service_glean)
implementation Deps.mozilla_service_location
implementation Deps.mozilla_service_nimbus
implementation FenixDependencies.mozilla_support_extensions
implementation FenixDependencies.mozilla_support_base
implementation FenixDependencies.mozilla_support_rusterrors
implementation FenixDependencies.mozilla_support_images
implementation FenixDependencies.mozilla_support_ktx
implementation FenixDependencies.mozilla_support_rustlog
implementation FenixDependencies.mozilla_support_utils
implementation FenixDependencies.mozilla_support_locale
implementation Deps.mozilla_support_extensions
implementation Deps.mozilla_support_base
implementation Deps.mozilla_support_rusterrors
implementation Deps.mozilla_support_images
implementation Deps.mozilla_support_ktx
implementation Deps.mozilla_support_rustlog
implementation Deps.mozilla_support_utils
implementation Deps.mozilla_support_locale
implementation FenixDependencies.mozilla_ui_colors
implementation FenixDependencies.mozilla_ui_icons
implementation FenixDependencies.mozilla_lib_publicsuffixlist
implementation FenixDependencies.mozilla_ui_widgets
implementation FenixDependencies.mozilla_ui_tabcounter
implementation Deps.mozilla_ui_colors
implementation Deps.mozilla_ui_icons
implementation Deps.mozilla_lib_publicsuffixlist
implementation Deps.mozilla_ui_widgets
implementation Deps.mozilla_ui_tabcounter
implementation FenixDependencies.mozilla_lib_crash
implementation FenixDependencies.lib_crash_sentry
implementation FenixDependencies.mozilla_lib_push_firebase
implementation FenixDependencies.mozilla_lib_state
implementation FenixDependencies.mozilla_lib_dataprotect
debugImplementation FenixDependencies.leakcanary
implementation Deps.mozilla_lib_crash
implementation Deps.lib_crash_sentry
implementation Deps.mozilla_lib_push_firebase
implementation Deps.mozilla_lib_state
implementation Deps.mozilla_lib_dataprotect
debugImplementation Deps.leakcanary
implementation FenixDependencies.androidx_annotation
implementation FenixDependencies.androidx_compose_ui
implementation FenixDependencies.androidx_compose_ui_tooling
implementation FenixDependencies.androidx_compose_foundation
implementation FenixDependencies.androidx_compose_material
implementation FenixDependencies.androidx_legacy
implementation FenixDependencies.androidx_biometric
implementation FenixDependencies.androidx_paging
implementation FenixDependencies.androidx_preference
implementation FenixDependencies.androidx_fragment
implementation FenixDependencies.androidx_navigation_fragment
implementation FenixDependencies.androidx_navigation_ui
implementation FenixDependencies.androidx_recyclerview
implementation FenixDependencies.androidx_lifecycle_common
implementation FenixDependencies.androidx_lifecycle_livedata
implementation FenixDependencies.androidx_lifecycle_process
implementation FenixDependencies.androidx_lifecycle_runtime
implementation FenixDependencies.androidx_lifecycle_viewmodel
implementation FenixDependencies.androidx_core
implementation FenixDependencies.androidx_core_ktx
implementation FenixDependencies.androidx_transition
implementation FenixDependencies.androidx_work_ktx
implementation FenixDependencies.androidx_datastore
implementation FenixDependencies.protobuf_javalite
implementation FenixDependencies.google_material
implementation Deps.androidx_compose_ui
implementation Deps.androidx_compose_ui_tooling
implementation Deps.androidx_compose_foundation
implementation Deps.androidx_compose_material
implementation Deps.androidx_legacy
implementation Deps.androidx_biometric
implementation Deps.androidx_paging
implementation Deps.androidx_preference
implementation Deps.androidx_fragment
implementation Deps.androidx_navigation_fragment
implementation Deps.androidx_navigation_ui
implementation Deps.androidx_recyclerview
implementation Deps.androidx_lifecycle_common
implementation Deps.androidx_lifecycle_livedata
implementation Deps.androidx_lifecycle_process
implementation Deps.androidx_lifecycle_runtime
implementation Deps.androidx_lifecycle_viewmodel
implementation Deps.androidx_core
implementation Deps.androidx_core_ktx
implementation Deps.androidx_transition
implementation Deps.androidx_work_ktx
implementation Deps.androidx_datastore
implementation Deps.protobuf_javalite
implementation Deps.google_material
implementation FenixDependencies.adjust
implementation FenixDependencies.installreferrer // Required by Adjust
implementation Deps.adjust
implementation Deps.installreferrer // Required by Adjust
implementation FenixDependencies.google_ads_id // Required for the Google Advertising ID
implementation Deps.google_ads_id // Required for the Google Advertising ID
// Required for in-app reviews
implementation FenixDependencies.google_play_review
implementation FenixDependencies.google_play_review_ktx
implementation Deps.google_play_store // Required for in-app reviews
androidTestImplementation FenixDependencies.uiautomator
androidTestImplementation Deps.uiautomator
androidTestImplementation "tools.fastlane:screengrab:2.0.0"
// This Falcon version is added to maven central now required for Screengrab
implementation 'com.jraska:falcon:2.2.0'
androidTestImplementation FenixDependencies.androidx_compose_ui_test
androidTestImplementation Deps.androidx_compose_ui_test
androidTestImplementation FenixDependencies.espresso_core, {
androidTestImplementation Deps.espresso_core, {
exclude group: 'com.android.support', module: 'support-annotations'
}
androidTestImplementation(FenixDependencies.espresso_contrib) {
androidTestImplementation(Deps.espresso_contrib) {
exclude module: 'appcompat-v7'
exclude module: 'support-v4'
exclude module: 'support-annotations'
@ -632,36 +611,35 @@ dependencies {
exclude module: 'protobuf-lite'
}
androidTestImplementation FenixDependencies.androidx_test_core
androidTestImplementation FenixDependencies.espresso_idling_resources
androidTestImplementation FenixDependencies.espresso_intents
androidTestImplementation Deps.androidx_test_core
androidTestImplementation Deps.espresso_idling_resources
androidTestImplementation Deps.espresso_intents
androidTestImplementation FenixDependencies.tools_test_runner
androidTestImplementation FenixDependencies.tools_test_rules
androidTestUtil FenixDependencies.orchestrator
androidTestImplementation FenixDependencies.espresso_core, {
androidTestImplementation Deps.tools_test_runner
androidTestImplementation Deps.tools_test_rules
androidTestUtil Deps.orchestrator
androidTestImplementation Deps.espresso_core, {
exclude group: 'com.android.support', module: 'support-annotations'
}
androidTestImplementation FenixDependencies.androidx_junit
androidTestImplementation FenixDependencies.androidx_test_extensions
androidTestImplementation FenixDependencies.androidx_work_testing
androidTestImplementation FenixDependencies.androidx_benchmark_junit4
androidTestImplementation FenixDependencies.mockwebserver
testImplementation FenixDependencies.mozilla_support_test
testImplementation FenixDependencies.mozilla_support_test_libstate
testImplementation FenixDependencies.androidx_junit
testImplementation FenixDependencies.androidx_test_extensions
testImplementation FenixDependencies.androidx_work_testing
testImplementation (FenixDependencies.robolectric) {
androidTestImplementation Deps.androidx_junit
androidTestImplementation Deps.androidx_test_extensions
androidTestImplementation Deps.androidx_work_testing
androidTestImplementation Deps.androidx_benchmark_junit4
androidTestImplementation Deps.mockwebserver
testImplementation Deps.mozilla_support_test
testImplementation Deps.mozilla_support_test_libstate
testImplementation Deps.androidx_junit
testImplementation Deps.androidx_test_extensions
testImplementation Deps.androidx_work_testing
testImplementation (Deps.robolectric) {
exclude group: 'org.apache.maven'
}
testImplementation 'org.apache.maven:maven-ant-tasks:2.1.3'
implementation FenixDependencies.mozilla_support_rusthttp
implementation Deps.mozilla_support_rusthttp
androidTestImplementation FenixDependencies.mockk_android
testImplementation FenixDependencies.mockk
testImplementation Deps.mockk
// For the initial release of Glean 19, we require consumer applications to
// depend on a separate library for unit tests. This will be removed in future releases.
@ -675,9 +653,9 @@ protobuf {
// See https://github.com/mozilla-mobile/fenix/issues/22321
protoc {
if (osdetector.os == "osx") {
artifact = "${FenixDependencies.protobuf_compiler}:osx-x86_64"
artifact = "${Deps.protobuf_compiler}:osx-x86_64"
} else {
artifact = FenixDependencies.protobuf_compiler
artifact = Deps.protobuf_compiler
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -43,22 +43,3 @@ topsites-impression:
- https://github.com/mozilla-mobile/fenix/pull/23945
notification_emails:
- android-probes@mozilla.com
spoc:
description: |
Contains data identifying with which Pocket sponsored story the user
interacted with and the type of interaction: story impression or click.
include_client_id: false
reasons:
impression: |
A sponsored story had more than 50% of it's content visible
on the screen.
click: |
A sponsored story was clicked by the user.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/27549
- https://mozilla-hub.atlassian.net/browse/FNXV2-21791
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/27550#issuecomment-1295027631
notification_emails:
- android-probes@mozilla.com

View File

@ -1,16 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width">
<title>Address_Form</title>
</head>
<body>
<form>
<p>Street Address: <input id="streetAddress" type="text"></p>
<p>City: <input id="city" type="text"></p>
<p>Zip Code: <input id="zipCode" type="text"></p>
<p>Country: <input id="country" type="text"></p>
<p>Telephone: <input id="telephone" type="text"></p>
<p>Email: <input id="email" type="text"></p>
</form>
</body>
</html>

View File

@ -1,13 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width">
<title>Credit_Card_Form</title>
</head>
<body>
<form>
<p>Card information</p>
<p>Card Number: <input id="cardNumber" type="text" placeholder="1234 1234 1234 1234"></p>
<p>Name on card: <input id="nameOnCard"type="text" placeholder="Name on card"></p>
</form>
</body>
</html>

View File

@ -1,8 +0,0 @@
<html>
<body>
<h2>Cross-site cookies storage access test</h2>
<h3>anti-tracker-test.com</h3>
<h4>different site, cross-origin iframe</h4>
<iframe width=500 height=1000 src="https://mozilla-mobile.github.io/testapp/anti-tracker-test_set_storage_with_sa_api.html"></iframe>
</body>
</html>

View File

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Html_Control_Form</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<p>Misc Link Types</p>
<section>
<a href="https://duckduckgo.com/">External link</a>
</section>
<section>
<a href="mailto://example@example.com">Email link</a>
</section>
<section>
<a href="tel://1234567890">Telephone link</a>
</section>
</html>

View File

@ -1,74 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Html_Control_Form</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<p>Calendar Form</p>
<section>
<input type="date" id="calendar">
<button onclick="printDate()" id="submitDate"> Submit date </button>
<div id="displayDate"></div>
</section>
<p>Clock Form</p>
<section>
<input type="time" id="clock">
<button onclick="printTime()" id="submitTime"> Submit time </button>
<div id="displayTime"></div>
</section>
<p>Color Form</p>
<section>
<input type="color" id="colorPicker">
<button onclick="printColor()" id="submitColor"> Submit color </button>
<div id="displayColor"></div>
</section>
<p>Drop-down Form</p>
<select id="dropDown">
<option type="text" text="The Only Ones">The Only Ones</option>
<option type="text" text="The National">The National</option>
</select>
<button onclick="printOption()" id="submitOption"> Submit drop down option </button>
<div id="displayOption"></div>
<script>
function printOption() {
let dropDown = document.querySelector("#dropDown");
let displayOption = document.querySelector("#displayOption");
displayOption.innerHTML = "Selected option is: " + dropDown.value;
}
</script>
<script>
function printDate() {
let calendar = document.querySelector("#calendar");
let displayDate = document.querySelector("#displayDate");
displayDate.innerHTML = "Selected date is: " + calendar.value;
}
</script>
<script>
function printTime() {
let time = document.querySelector("#clock");
let displayTime = document.querySelector("#displayTime");
displayTime.innerHTML = "Selected time is: " + time.value;
}
</script>
<script>
function printColor() {
let colorPicker = document.querySelector("#colorPicker");
let displayColor = document.querySelector("#displayColor");
displayColor.innerHTML = "Selected color is: " + colorPicker.value;
}
</script>
</html>

View File

@ -1,23 +0,0 @@
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width">
<body>
<h1>Storage check</h1>
<script type="text/javascript">
if (sessionStorage.getItem('sessionTest') == 'session storage') {
document.write('<p>Session storage has value</p>');
} else {
document.write('<p>Session storage empty</p>');
}
if (localStorage.getItem('localTest') == 'local storage') {
document.write('<p>Local storage has value</p>');
} else {
document.write('<p>Local storage empty</p>');
}
</script>
</body>
</html>

View File

@ -1,28 +0,0 @@
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width">
<body>
<h1>Storage Write</h1>
<p id="cookies"></p>
<button id="setCookies">Set cookies</button>
<script type="text/javascript">
(function() {
document.getElementById("cookies").textContent = document.cookie?document.cookie:"No cookies set";
})();
document.getElementById("setCookies").addEventListener("click", function() {
document.cookie = "user=android";
document.getElementById("cookies").textContent = document.cookie;
});
sessionStorage.setItem('sessionTest', 'session storage');
localStorage.setItem('localTest', 'local storage');
document.write('<p>Values written to storage</p>');
</script>
</body>
</html>

View File

@ -13,31 +13,31 @@
<h3>Level 1 (Basic) List</h3>
<p>social-track-digest256:</p>
<img
src="https://social-track-digest256.dummytracker.org/test_not_blocked.png" alt="social not blocked"
onerror="this.onerror=null;this.src='https://not-a-tracker.dummytracker.org/test_blocked.png';this.alt='social blocked'">
src="https://social-track-digest256.dummytracker.org/test_not_blocked.png"
onerror="this.onerror=null;this.src='https://not-a-tracker.dummytracker.org/test_blocked.png'">
<br/>
<p>ads-track-digest256:</p>
<img
src="https://ads-track-digest256.dummytracker.org/test_not_blocked.png"
onerror="this.onerror=null;this.src='https://not-a-tracker.dummytracker.org/test_blocked.png';this.alt='ads blocked'">
onerror="this.onerror=null;this.src='https://not-a-tracker.dummytracker.org/test_blocked.png'">
<br/>
<p>analytics-track-digest256:</p>
<img
src="https://analytics-track-digest256.dummytracker.org/test_not_blocked.png"
onerror="this.onerror=null;this.src='https://not-a-tracker.dummytracker.org/test_blocked.png';this.alt='analytics blocked'">
onerror="this.onerror=null;this.src='https://not-a-tracker.dummytracker.org/test_blocked.png'">
<br/>
<p>Fingerprinting:
<pre id="result">test not run</pre>
<script src="https://base-fingerprinting-track-digest256.dummytracker.org/tracker.js"
onerror="this.onerror=null;var result=document.getElementById('result');result.innerHTML='Fingerprinting blocked';"
onload="this.onload=null;var result=document.getElementById('result');result.innerHTML='Fingerprinting NOT blocked';"
onerror="this.onerror=null;var result=document.getElementById('result');result.innerHTML='blocked';"
onload="this.onload=null;var result=document.getElementById('result');result.innerHTML='NOT blocked';"
></script>
</p>
<br/>
<p>Cryptomining:
<img
src="https://base-cryptomining-track-digest256.dummytracker.org/test_not_blocked.png" alt="Cryptomining not blocked"
onerror="this.onerror=null;this.src='https://not-a-tracker.dummytracker.org/test_blocked.png';this.alt='Cryptomining blocked'">
src="https://base-cryptomining-track-digest256.dummytracker.org/test_not_blocked.png" alt="not blocked"
onerror="this.onerror=null;this.src='https://not-a-tracker.dummytracker.org/test_blocked.png';this.alt='blocked'">
</p>
<p><b>Cookie blocking</b>

View File

@ -39,8 +39,9 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
isSameDomain: Boolean,
isRedirect: Boolean,
isDirectNavigation: Boolean,
isSubframeRequest: Boolean,
isSubframeRequest: Boolean
): RequestInterceptor.InterceptionResponse? {
interceptFxaRequest(
engineSession,
uri,
@ -49,7 +50,7 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
isSameDomain,
isRedirect,
isDirectNavigation,
isSubframeRequest,
isSubframeRequest
)?.let { response ->
return response
}
@ -67,14 +68,14 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
isSameDomain,
isRedirect,
isDirectNavigation,
isSubframeRequest,
isSubframeRequest
)
}
override fun onErrorRequest(
session: EngineSession,
errorType: ErrorType,
uri: String?,
uri: String?
): RequestInterceptor.ErrorResponse? {
val improvedErrorType = improveErrorType(errorType)
val riskLevel = getRiskLevel(improvedErrorType)
@ -85,7 +86,7 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
context = context,
errorType = improvedErrorType,
uri = uri,
htmlResource = riskLevel.htmlRes,
htmlResource = riskLevel.htmlRes
)
return RequestInterceptor.ErrorResponse(errorPageUri)
@ -101,18 +102,20 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
private fun interceptAmoRequest(
uri: String,
isSameDomain: Boolean,
hasUserGesture: 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),
NavGraphDirections.actionGlobalAddonsManagementFragment(addonId)
)
// We've redirected to the add-ons management fragment, skip original request.
@ -134,7 +137,7 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
isSameDomain: Boolean,
isRedirect: Boolean,
isDirectNavigation: Boolean,
isSubframeRequest: Boolean,
isSubframeRequest: Boolean
): RequestInterceptor.InterceptionResponse? {
return appContext.components.services.accountsAuthFeature.interceptor.onLoadRequest(
engineSession,
@ -144,7 +147,7 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
isSameDomain,
isRedirect,
isDirectNavigation,
isSubframeRequest,
isSubframeRequest
)
}
@ -186,19 +189,16 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
ErrorType.ERROR_NO_INTERNET,
ErrorType.ERROR_HTTPS_ONLY,
ErrorType.ERROR_BAD_HSTS_CERT,
ErrorType.ERROR_UNKNOWN_PROTOCOL,
-> RiskLevel.Low
ErrorType.ERROR_UNKNOWN_PROTOCOL -> RiskLevel.Low
ErrorType.ERROR_SECURITY_BAD_CERT,
ErrorType.ERROR_SECURITY_SSL,
ErrorType.ERROR_PORT_BLOCKED,
-> RiskLevel.Medium
ErrorType.ERROR_PORT_BLOCKED -> RiskLevel.Medium
ErrorType.ERROR_SAFEBROWSING_HARMFUL_URI,
ErrorType.ERROR_SAFEBROWSING_MALWARE_URI,
ErrorType.ERROR_SAFEBROWSING_PHISHING_URI,
ErrorType.ERROR_SAFEBROWSING_UNWANTED_URI,
-> RiskLevel.High
ErrorType.ERROR_SAFEBROWSING_UNWANTED_URI -> RiskLevel.High
}
internal enum class RiskLevel(val htmlRes: String) {

View File

@ -5,8 +5,8 @@
package org.mozilla.fenix.components
import android.content.Context
import mozilla.components.service.fxa.ServerConfig
import mozilla.components.service.fxa.ServerConfig.Server
import mozilla.components.service.fxa.ServerConfig
/**
* Utility to configure Firefox Account stage servers.

View File

@ -24,11 +24,9 @@ import mozilla.components.service.glean.net.ConceptFetchHttpUploader
import mozilla.components.service.glean.testing.GleanTestLocalServer
import okhttp3.mockwebserver.RecordedRequest
import org.json.JSONObject
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Assert.assertFalse
import org.junit.BeforeClass
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -37,9 +35,9 @@ import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MockWebServerHelper
import java.util.concurrent.TimeUnit
import java.io.BufferedReader
import java.io.ByteArrayInputStream
import java.util.concurrent.TimeUnit
import java.util.zip.GZIPInputStream
/**
@ -71,7 +69,6 @@ fun RecordedRequest.getPlainBody(): String {
@RunWith(AndroidJUnit4::class)
class BaselinePingTest {
private val server = MockWebServerHelper.createAlwaysOkMockWebServer()
private lateinit var mDevice: UiDevice
@get:Rule
val activityRule: ActivityTestRule<HomeActivity> = HomeActivityTestRule()
@ -79,11 +76,6 @@ class BaselinePingTest {
@get:Rule
val gleanRule = GleanTestLocalServer(ApplicationProvider.getApplicationContext(), server.port)
@Before
fun setup() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
}
companion object {
@BeforeClass
@JvmStatic
@ -92,7 +84,7 @@ class BaselinePingTest {
val httpClient = ConceptFetchHttpUploader(
lazy {
GeckoViewFetchClient(ApplicationProvider.getApplicationContext())
},
}
)
// Fenix does not initialize the Glean SDK in tests/debug builds, but this test
@ -103,7 +95,7 @@ class BaselinePingTest {
applicationContext = ApplicationProvider.getApplicationContext(),
uploadEnabled = true,
configuration = Configuration(httpClient = httpClient),
buildInfo = GleanBuildInfo.buildInfo,
buildInfo = GleanBuildInfo.buildInfo
)
}
}
@ -120,7 +112,7 @@ class BaselinePingTest {
private fun waitForPingContent(
pingName: String,
pingReason: String?,
maxAttempts: Int = 3,
maxAttempts: Int = 3
): JSONObject? {
var attempts = 0
do {
@ -144,29 +136,29 @@ class BaselinePingTest {
return null
}
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1807288")
@Test
fun validateBaselinePing() {
// Wait for the app to be idle/ready.
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
mDevice.waitForIdle()
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
device.waitForIdle()
// Wait for 1 second: this should guarantee we have some valid duration in the
// ping.
Thread.sleep(1000)
// Move it to background.
mDevice.pressHome()
device.pressHome()
// Due to bug 1632184, we need move the activity to foreground again, in order
// for a 'background' ping with reason 'foreground' to be generated and also trigger
// sending the ping that was submitted on background. This can go away once bug 1634375
// is fixed.
mDevice.pressRecentApps()
mDevice.findObject(
device.pressRecentApps()
device.findObject(
UiSelector().descriptionContains(
ApplicationProvider.getApplicationContext<Context>().getString(R.string.app_name),
),
ApplicationProvider.getApplicationContext<Context>().getString(R.string.app_name)
)
)
.click()

View File

@ -5,6 +5,11 @@
package org.mozilla.fenix.helpers
import android.graphics.Bitmap
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import android.graphics.Color
import org.junit.Assert.assertEquals

View File

@ -4,8 +4,6 @@
package org.mozilla.fenix.helpers
import org.mozilla.fenix.helpers.TestHelper.getSponsoredShortcutTitle
object Constants {
// Device or AVD requires a Google Services Android OS installation
@ -16,32 +14,10 @@ object Constants {
const val YOUTUBE_APP = "com.google.android.youtube"
const val GMAIL_APP = "com.google.android.gm"
const val PHONE_APP = "com.android.dialer"
const val ANDROID_SETTINGS = "com.android.settings"
}
const val SPEECH_RECOGNITION = "android.speech.action.RECOGNIZE_SPEECH"
const val POCKET_RECOMMENDED_STORIES_UTM_PARAM = "utm_source=pocket-newtab-android"
const val LONG_CLICK_DURATION: Long = 5000
const val LISTS_MAXSWIPES: Int = 3
const val RETRY_COUNT = 3
val searchEngineCodes = mapOf(
"Google" to "client=firefox-b-m",
"Bing" to "firefox&pc=MOZB&form=MOZMBA",
"DuckDuckGo" to "t=fpas",
)
val firstSponsoredShortcutTitle by lazy { getSponsoredShortcutTitle(2) }
val secondSponsoredShortcutTitle by lazy { getSponsoredShortcutTitle(3) }
// Expected for en-us defaults
val defaultTopSitesList by lazy {
mapOf(
"Google" to "Google",
"First sponsored shortcut" to firstSponsoredShortcutTitle,
"Second sponsored shortcut" to secondSponsoredShortcutTitle,
"Top Articles" to "Top Articles",
"Wikipedia" to "Wikipedia",
)
}
}

View File

@ -1,19 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.helpers
import org.mozilla.experiments.nimbus.GleanPlumbMessageHelper
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.TestHelper.appContext
object Experimentation {
val experiments =
appContext.components.analytics.experiments
fun withHelper(block: GleanPlumbMessageHelper.() -> Unit) {
val helper = experiments.createMessageHelper()
block(helper)
}
}

View File

@ -4,84 +4,57 @@
package org.mozilla.fenix.helpers
import android.content.Context
import androidx.test.platform.app.InstrumentationRegistry
import org.mozilla.fenix.ext.settings
/**
* Helper for querying the status and modifying various features and settings in the application.
*/
interface FeatureSettingsHelper {
/**
* Whether the onboarding for existing users should be shown or not.
* It should appear only once on the first visit to homescreen.
*/
var isHomeOnboardingDialogEnabled: Boolean
class FeatureSettingsHelper {
private val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
private val settings = context.settings()
/**
* Whether the Pocket stories feature is enabled or not.
*/
var isPocketEnabled: Boolean
// saving default values of feature flags
private var isPocketEnabled: Boolean = settings.showPocketRecommendationsFeature
private var isJumpBackInCFREnabled: Boolean = settings.shouldShowJumpBackInCFR
private var isRecentTabsFeatureEnabled: Boolean = settings.showRecentTabsFeature
private var isRecentlyVisitedFeatureEnabled: Boolean = settings.historyMetadataUIFeature
private var isUserKnowsAboutPwasTrue: Boolean = settings.userKnowsAboutPwas
/**
* Whether the "Jump back in" CFR should be shown or not.
* It should appear on the first visit to homescreen given that there is a tab opened.
*/
var isJumpBackInCFREnabled: Boolean
fun setPocketEnabled(enabled: Boolean) {
settings.showPocketRecommendationsFeature = enabled
}
/**
* Whether the onboarding dialog for choosing wallpapers should be shown or not.
*/
var isWallpaperOnboardingEnabled: Boolean
fun setJumpBackCFREnabled(enabled: Boolean) {
settings.shouldShowJumpBackInCFR = enabled
}
/**
* Whether the "Jump back in" homescreen section is enabled or not.
* It shows the last visited tab on this device and on other synced devices.
*/
var isRecentTabsFeatureEnabled: Boolean
fun setRecentTabsFeatureEnabled(enabled: Boolean) {
settings.showRecentTabsFeature = enabled
}
/**
* Whether the "Recently visited" homescreen section is enabled or not.
* It can show up to 9 history highlights and history groups.
*/
var isRecentlyVisitedFeatureEnabled: Boolean
fun setRecentlyVisitedFeatureEnabled(enabled: Boolean) {
settings.historyMetadataUIFeature = enabled
}
/**
* Whether the onboarding dialog for PWAs should be shown or not.
* It can show the first time a website that can be installed as a PWA is accessed.
*/
var isPWAsPromptEnabled: Boolean
fun setStrictETPEnabled() {
settings.setStrictETP()
}
/**
* Whether the "Site permissions" option is checked in the "Delete browsing data" screen or not.
*/
var isDeleteSitePermissionsEnabled: Boolean
fun disablePwaCFR(disable: Boolean) {
settings.userKnowsAboutPwas = disable
}
/**
* Enable or disable showing the TCP CFR when accessing a webpage for the first time.
*/
var isTCPCFREnabled: Boolean
fun deleteSitePermissions(delete: Boolean) {
settings.deleteSitePermissions = delete
}
/**
* The current "Enhanced Tracking Protection" policy.
* @see ETPPolicy
*/
var etpPolicy: ETPPolicy
fun applyFlagUpdates()
fun resetAllFeatureFlags()
companion object {
val settings = InstrumentationRegistry.getInstrumentation().targetContext.settings()
// Important:
// Use this after each test if you have modified these feature settings
// to make sure the app goes back to the default state
fun resetAllFeatureFlags() {
settings.showPocketRecommendationsFeature = isPocketEnabled
settings.shouldShowJumpBackInCFR = isJumpBackInCFREnabled
settings.showRecentTabsFeature = isRecentTabsFeatureEnabled
settings.historyMetadataUIFeature = isRecentlyVisitedFeatureEnabled
settings.userKnowsAboutPwas = isUserKnowsAboutPwasTrue
}
}
/**
* All "Enhanced Tracking Protection" modes.
*/
enum class ETPPolicy {
STANDARD,
STRICT,
CUSTOM,
;
}

View File

@ -1,159 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.helpers
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.getPreferenceKey
import org.mozilla.fenix.helpers.ETPPolicy.CUSTOM
import org.mozilla.fenix.helpers.ETPPolicy.STANDARD
import org.mozilla.fenix.helpers.ETPPolicy.STRICT
import org.mozilla.fenix.helpers.FeatureSettingsHelper.Companion.settings
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.onboarding.FenixOnboarding
import org.mozilla.fenix.utils.Settings
/**
* Helper for querying the status and modifying various features and settings in the application.
*/
class FeatureSettingsHelperDelegate : FeatureSettingsHelper {
/**
* The current feature flags used inside the app before the tests start.
* These will be restored when the tests end.
*/
private val initialFeatureFlags = FeatureFlags(
isHomeOnboardingDialogEnabled = settings.showHomeOnboardingDialog,
homeOnboardingDialogVersion = getHomeOnboardingVersion(),
isPocketEnabled = settings.showPocketRecommendationsFeature,
isJumpBackInCFREnabled = settings.shouldShowJumpBackInCFR,
isRecentTabsFeatureEnabled = settings.showRecentTabsFeature,
isRecentlyVisitedFeatureEnabled = settings.historyMetadataUIFeature,
isPWAsPromptEnabled = !settings.userKnowsAboutPwas,
isTCPCFREnabled = settings.shouldShowTotalCookieProtectionCFR,
isWallpaperOnboardingEnabled = settings.showWallpaperOnboarding,
isDeleteSitePermissionsEnabled = settings.deleteSitePermissions,
etpPolicy = getETPPolicy(settings),
)
/**
* The current feature flags updated in tests.
*/
private var updatedFeatureFlags = initialFeatureFlags.copy()
override var isHomeOnboardingDialogEnabled: Boolean
get() = updatedFeatureFlags.isHomeOnboardingDialogEnabled &&
FenixOnboarding(appContext).userHasBeenOnboarded()
set(value) {
updatedFeatureFlags.isHomeOnboardingDialogEnabled = value
updatedFeatureFlags.homeOnboardingDialogVersion = when (value) {
true -> FenixOnboarding.CURRENT_ONBOARDING_VERSION
false -> 0
}
}
override var isPocketEnabled: Boolean by updatedFeatureFlags::isPocketEnabled
override var isJumpBackInCFREnabled: Boolean by updatedFeatureFlags::isJumpBackInCFREnabled
override var isWallpaperOnboardingEnabled: Boolean by updatedFeatureFlags::isWallpaperOnboardingEnabled
override var isRecentTabsFeatureEnabled: Boolean by updatedFeatureFlags::isRecentTabsFeatureEnabled
override var isRecentlyVisitedFeatureEnabled: Boolean by updatedFeatureFlags::isRecentlyVisitedFeatureEnabled
override var isPWAsPromptEnabled: Boolean by updatedFeatureFlags::isPWAsPromptEnabled
override var isTCPCFREnabled: Boolean by updatedFeatureFlags::isTCPCFREnabled
override var etpPolicy: ETPPolicy by updatedFeatureFlags::etpPolicy
override fun applyFlagUpdates() {
applyFeatureFlags(updatedFeatureFlags)
}
override fun resetAllFeatureFlags() {
applyFeatureFlags(initialFeatureFlags)
}
override var isDeleteSitePermissionsEnabled: Boolean by updatedFeatureFlags::isDeleteSitePermissionsEnabled
private fun applyFeatureFlags(featureFlags: FeatureFlags) {
settings.showHomeOnboardingDialog = featureFlags.isHomeOnboardingDialogEnabled
setHomeOnboardingVersion(featureFlags.homeOnboardingDialogVersion)
settings.showPocketRecommendationsFeature = featureFlags.isPocketEnabled
settings.shouldShowJumpBackInCFR = featureFlags.isJumpBackInCFREnabled
settings.showRecentTabsFeature = featureFlags.isRecentTabsFeatureEnabled
settings.historyMetadataUIFeature = featureFlags.isRecentlyVisitedFeatureEnabled
settings.userKnowsAboutPwas = !featureFlags.isPWAsPromptEnabled
settings.shouldShowTotalCookieProtectionCFR = featureFlags.isTCPCFREnabled
settings.showWallpaperOnboarding = featureFlags.isWallpaperOnboardingEnabled
settings.deleteSitePermissions = featureFlags.isDeleteSitePermissionsEnabled
setETPPolicy(featureFlags.etpPolicy)
}
}
private data class FeatureFlags(
var isHomeOnboardingDialogEnabled: Boolean,
var homeOnboardingDialogVersion: Int,
var isPocketEnabled: Boolean,
var isJumpBackInCFREnabled: Boolean,
var isRecentTabsFeatureEnabled: Boolean,
var isRecentlyVisitedFeatureEnabled: Boolean,
var isPWAsPromptEnabled: Boolean,
var isTCPCFREnabled: Boolean,
var isWallpaperOnboardingEnabled: Boolean,
var isDeleteSitePermissionsEnabled: Boolean,
var etpPolicy: ETPPolicy,
)
internal fun getETPPolicy(settings: Settings): ETPPolicy {
return when {
settings.useStrictTrackingProtection -> STRICT
settings.useCustomTrackingProtection -> CUSTOM
else -> STANDARD
}
}
private fun setETPPolicy(policy: ETPPolicy) {
when (policy) {
STRICT -> settings.setStrictETP()
// The following two cases update ETP in the same way "setStrictETP" does.
STANDARD -> {
settings.preferences.edit()
.putBoolean(
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_strict_default),
false,
)
.putBoolean(
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_custom_option),
false,
)
.putBoolean(
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_standard_option),
true,
)
.commit()
}
CUSTOM -> {
settings.preferences.edit()
.putBoolean(
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_strict_default),
false,
)
.putBoolean(
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_standard_option),
true,
)
.putBoolean(
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_custom_option),
true,
)
.commit()
}
}
}
private fun getHomeOnboardingVersion(): Int {
return FenixOnboarding(appContext)
.preferences
.getInt(FenixOnboarding.LAST_VERSION_ONBOARDING_KEY, 0)
}
private fun setHomeOnboardingVersion(version: Int) {
FenixOnboarding(appContext)
.preferences.edit()
.putInt(FenixOnboarding.LAST_VERSION_ONBOARDING_KEY, version)
.commit()
}

View File

@ -6,15 +6,14 @@
package org.mozilla.fenix.helpers
import android.content.Intent
import android.view.ViewConfiguration.getLongPressTimeout
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiSelector
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.helpers.FeatureSettingsHelper.Companion.settings
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.onboarding.FenixOnboarding
/**
@ -27,92 +26,22 @@ import org.mozilla.fenix.onboarding.FenixOnboarding
class HomeActivityTestRule(
initialTouchMode: Boolean = false,
launchActivity: Boolean = true,
private val skipOnboarding: Boolean = false,
) : ActivityTestRule<HomeActivity>(HomeActivity::class.java, initialTouchMode, launchActivity),
FeatureSettingsHelper by FeatureSettingsHelperDelegate() {
// Using a secondary constructor allows us to easily delegate the settings to FeatureSettingsHelperDelegate.
// Otherwise if wanting to use the same names we would have to override these settings in the primary
// constructor and in that elide the FeatureSettingsHelperDelegate.
constructor(
initialTouchMode: Boolean = false,
launchActivity: Boolean = true,
skipOnboarding: Boolean = false,
isHomeOnboardingDialogEnabled: Boolean = settings.showHomeOnboardingDialog &&
FenixOnboarding(appContext).userHasBeenOnboarded(),
isPocketEnabled: Boolean = settings.showPocketRecommendationsFeature,
isJumpBackInCFREnabled: Boolean = settings.shouldShowJumpBackInCFR,
isRecentTabsFeatureEnabled: Boolean = settings.showRecentTabsFeature,
isRecentlyVisitedFeatureEnabled: Boolean = settings.historyMetadataUIFeature,
isPWAsPromptEnabled: Boolean = !settings.userKnowsAboutPwas,
isTCPCFREnabled: Boolean = settings.shouldShowTotalCookieProtectionCFR,
isWallpaperOnboardingEnabled: Boolean = settings.showWallpaperOnboarding,
isDeleteSitePermissionsEnabled: Boolean = settings.deleteSitePermissions,
etpPolicy: ETPPolicy = getETPPolicy(settings),
) : this(initialTouchMode, launchActivity, skipOnboarding) {
this.isHomeOnboardingDialogEnabled = isHomeOnboardingDialogEnabled
this.isPocketEnabled = isPocketEnabled
this.isJumpBackInCFREnabled = isJumpBackInCFREnabled
this.isRecentTabsFeatureEnabled = isRecentTabsFeatureEnabled
this.isRecentlyVisitedFeatureEnabled = isRecentlyVisitedFeatureEnabled
this.isPWAsPromptEnabled = isPWAsPromptEnabled
this.isTCPCFREnabled = isTCPCFREnabled
this.isWallpaperOnboardingEnabled = isWallpaperOnboardingEnabled
this.isDeleteSitePermissionsEnabled = isDeleteSitePermissionsEnabled
this.etpPolicy = etpPolicy
}
/**
* Update settings after the activity was created.
*/
fun applySettingsExceptions(settings: (FeatureSettingsHelper) -> Unit) {
FeatureSettingsHelperDelegate().also {
settings(it)
applyFlagUpdates()
}
}
private val skipOnboarding: Boolean = false
) :
ActivityTestRule<HomeActivity>(HomeActivity::class.java, initialTouchMode, launchActivity) {
private val longTapUserPreference = getLongPressTimeout()
override fun beforeActivityLaunched() {
super.beforeActivityLaunched()
setLongTapTimeout(3000)
applyFlagUpdates()
if (skipOnboarding) { skipOnboardingBeforeLaunch() }
}
override fun afterActivityFinished() {
super.afterActivityFinished()
setLongTapTimeout(longTapUserPreference)
resetAllFeatureFlags()
closeNotificationShade()
}
companion object {
/**
* Create a new instance of [HomeActivityTestRule] which by default will disable specific
* app features that would otherwise negatively impact most tests.
*
* The disabled features are:
* - the Jump back in CFR,
* - the Total Cookie Protection CFR,
* - the PWA prompt dialog,
* - the wallpaper onboarding.
*/
fun withDefaultSettingsOverrides(
initialTouchMode: Boolean = false,
launchActivity: Boolean = true,
skipOnboarding: Boolean = false,
) = HomeActivityTestRule(
initialTouchMode = initialTouchMode,
launchActivity = launchActivity,
skipOnboarding = skipOnboarding,
isJumpBackInCFREnabled = false,
isPWAsPromptEnabled = false,
isTCPCFREnabled = false,
isWallpaperOnboardingEnabled = false,
)
}
}
/**
@ -123,74 +52,17 @@ class HomeActivityTestRule(
* @param launchActivity See [IntentsTestRule]
*/
class HomeActivityIntentTestRule internal constructor(
class HomeActivityIntentTestRule(
initialTouchMode: Boolean = false,
launchActivity: Boolean = true,
private val skipOnboarding: Boolean = false,
) : IntentsTestRule<HomeActivity>(HomeActivity::class.java, initialTouchMode, launchActivity),
FeatureSettingsHelper by FeatureSettingsHelperDelegate() {
// Using a secondary constructor allows us to easily delegate the settings to FeatureSettingsHelperDelegate.
// Otherwise if wanting to use the same names we would have to override these settings in the primary
// constructor and in that elide the FeatureSettingsHelperDelegate.
constructor(
initialTouchMode: Boolean = false,
launchActivity: Boolean = true,
skipOnboarding: Boolean = false,
isHomeOnboardingDialogEnabled: Boolean = settings.showHomeOnboardingDialog &&
FenixOnboarding(appContext).userHasBeenOnboarded(),
isPocketEnabled: Boolean = settings.showPocketRecommendationsFeature,
isJumpBackInCFREnabled: Boolean = settings.shouldShowJumpBackInCFR,
isRecentTabsFeatureEnabled: Boolean = settings.showRecentTabsFeature,
isRecentlyVisitedFeatureEnabled: Boolean = settings.historyMetadataUIFeature,
isPWAsPromptEnabled: Boolean = !settings.userKnowsAboutPwas,
isTCPCFREnabled: Boolean = settings.shouldShowTotalCookieProtectionCFR,
isWallpaperOnboardingEnabled: Boolean = settings.showWallpaperOnboarding,
isDeleteSitePermissionsEnabled: Boolean = settings.deleteSitePermissions,
etpPolicy: ETPPolicy = getETPPolicy(settings),
) : this(initialTouchMode, launchActivity, skipOnboarding) {
this.isHomeOnboardingDialogEnabled = isHomeOnboardingDialogEnabled
this.isPocketEnabled = isPocketEnabled
this.isJumpBackInCFREnabled = isJumpBackInCFREnabled
this.isRecentTabsFeatureEnabled = isRecentTabsFeatureEnabled
this.isRecentlyVisitedFeatureEnabled = isRecentlyVisitedFeatureEnabled
this.isPWAsPromptEnabled = isPWAsPromptEnabled
this.isTCPCFREnabled = isTCPCFREnabled
this.isWallpaperOnboardingEnabled = isWallpaperOnboardingEnabled
this.isDeleteSitePermissionsEnabled = isDeleteSitePermissionsEnabled
this.etpPolicy = etpPolicy
}
private val skipOnboarding: Boolean = false
) :
IntentsTestRule<HomeActivity>(HomeActivity::class.java, initialTouchMode, launchActivity) {
private val longTapUserPreference = getLongPressTimeout()
private lateinit var intent: Intent
/**
* Update settings after the activity was created.
*/
fun applySettingsExceptions(settings: (FeatureSettingsHelper) -> Unit) {
FeatureSettingsHelperDelegate().apply {
settings(this)
applyFlagUpdates()
}
}
override fun getActivityIntent(): Intent? {
return if (this::intent.isInitialized) {
this.intent
} else {
super.getActivityIntent()
}
}
fun withIntent(intent: Intent): HomeActivityIntentTestRule {
this.intent = intent
return this
}
override fun beforeActivityLaunched() {
super.beforeActivityLaunched()
setLongTapTimeout(3000)
applyFlagUpdates()
if (skipOnboarding) { skipOnboardingBeforeLaunch() }
}
@ -198,53 +70,6 @@ class HomeActivityIntentTestRule internal constructor(
super.afterActivityFinished()
setLongTapTimeout(longTapUserPreference)
closeNotificationShade()
resetAllFeatureFlags()
}
/**
* Update the settings values from when this rule was first instantiated to account for any changes
* done while running the tests.
* Useful in the scenario about the activity being restarted which would otherwise set the initial
* settings and override any changes made in the meantime.
*/
fun updateCachedSettings() {
isHomeOnboardingDialogEnabled =
settings.showHomeOnboardingDialog && FenixOnboarding(appContext).userHasBeenOnboarded()
isPocketEnabled = settings.showPocketRecommendationsFeature
isJumpBackInCFREnabled = settings.shouldShowJumpBackInCFR
isRecentTabsFeatureEnabled = settings.showRecentTabsFeature
isRecentlyVisitedFeatureEnabled = settings.historyMetadataUIFeature
isPWAsPromptEnabled = !settings.userKnowsAboutPwas
isTCPCFREnabled = settings.shouldShowTotalCookieProtectionCFR
isWallpaperOnboardingEnabled = settings.showWallpaperOnboarding
isDeleteSitePermissionsEnabled = settings.deleteSitePermissions
etpPolicy = getETPPolicy(settings)
}
companion object {
/**
* Create a new instance of [HomeActivityIntentTestRule] which by default will disable specific
* app features that would otherwise negatively impact most tests.
*
* The disabled features are:
* - the Jump back in CFR,
* - the Total Cookie Protection CFR,
* - the PWA prompt dialog,
* - the wallpaper onboarding.
*/
fun withDefaultSettingsOverrides(
initialTouchMode: Boolean = false,
launchActivity: Boolean = true,
skipOnboarding: Boolean = false,
) = HomeActivityIntentTestRule(
initialTouchMode = initialTouchMode,
launchActivity = launchActivity,
skipOnboarding = skipOnboarding,
isJumpBackInCFREnabled = false,
isPWAsPromptEnabled = false,
isTCPCFREnabled = false,
isWallpaperOnboardingEnabled = false,
)
}
}
@ -254,6 +79,7 @@ fun setLongTapTimeout(delay: Int) {
var attempts = 0
while (attempts++ < 3) {
try {
val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mDevice.executeShellCommand("settings put secure long_press_timeout $delay")
break
} catch (e: RuntimeException) {
@ -269,8 +95,9 @@ private fun skipOnboardingBeforeLaunch() {
}
private fun closeNotificationShade() {
val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
if (mDevice.findObject(
UiSelector().resourceId("com.android.systemui:id/notification_stack_scroller"),
UiSelector().resourceId("com.android.systemui:id/notification_stack_scroller")
).exists()
) {
mDevice.pressHome()

View File

@ -17,16 +17,16 @@ object IdlingResourceHelper {
fun registerAddonInstallingIdlingResource(activityTestRule: ActivityTestRule<HomeActivity>) {
IdlingRegistry.getInstance().register(
AddonsInstallingIdlingResource(
activityTestRule.activity.supportFragmentManager,
),
activityTestRule.activity.supportFragmentManager
)
)
}
fun unregisterAddonInstallingIdlingResource(activityTestRule: ActivityTestRule<HomeActivity>) {
IdlingRegistry.getInstance().unregister(
AddonsInstallingIdlingResource(
activityTestRule.activity.supportFragmentManager,
),
activityTestRule.activity.supportFragmentManager
)
)
}

View File

@ -1,85 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.helpers
import androidx.test.uiautomator.UiObject
import androidx.test.uiautomator.UiSelector
import org.junit.Assert.assertTrue
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestHelper.mDevice
/**
* Helper for querying and interacting with items based on their matchers.
*/
object MatcherHelper {
fun itemWithResId(resourceId: String) =
mDevice.findObject(UiSelector().resourceId(resourceId))
fun itemContainingText(itemText: String) =
mDevice.findObject(UiSelector().textContains(itemText))
fun itemWithDescription(description: String) =
mDevice.findObject(UiSelector().descriptionContains(description))
fun checkedItemWithResId(resourceId: String, isChecked: Boolean) =
mDevice.findObject(UiSelector().resourceId(resourceId).checked(isChecked))
fun checkedItemWithResIdAndText(resourceId: String, text: String, isChecked: Boolean) =
mDevice.findObject(
UiSelector()
.resourceId(resourceId)
.textContains(text)
.checked(isChecked),
)
fun itemWithResIdAndDescription(resourceId: String, description: String) =
mDevice.findObject(UiSelector().resourceId(resourceId).descriptionContains(description))
fun itemWithResIdAndText(resourceId: String, text: String) =
mDevice.findObject(UiSelector().resourceId(resourceId).text(text))
fun assertItemWithResIdExists(vararg appItems: UiObject) {
for (appItem in appItems) {
assertTrue(appItem.waitForExists(waitingTime))
}
}
fun assertItemContainingTextExists(vararg appItems: UiObject) {
for (appItem in appItems) {
assertTrue(appItem.waitForExists(waitingTime))
}
}
fun assertItemWithDescriptionExists(vararg appItems: UiObject) {
for (appItem in appItems) {
assertTrue(appItem.waitForExists(waitingTime))
}
}
fun assertCheckedItemWithResIdExists(vararg appItems: UiObject) {
for (appItem in appItems) {
assertTrue(appItem.waitForExists(waitingTime))
}
}
fun assertCheckedItemWithResIdAndTextExists(vararg appItems: UiObject) {
for (appItem in appItems) {
assertTrue(appItem.waitForExists(waitingTime))
}
}
fun assertItemWithResIdAndDescriptionExists(vararg appItems: UiObject) {
for (appItem in appItems) {
assertTrue(appItem.waitForExists(waitingTime))
}
}
fun assertItemWithResIdAndTextExists(vararg appItems: UiObject) {
for (appItem in appItems) {
assertTrue(appItem.waitForExists(waitingTime))
}
}
}

View File

@ -44,7 +44,7 @@ fun withBitmapDrawable(bitmap: Bitmap, name: String): Matcher<View>? = BitmapDra
fun nthChildOf(
parentMatcher: Matcher<View>,
childPosition: Int,
childPosition: Int
): Matcher<View> {
return object : TypeSafeMatcher<View>() {
override fun describeTo(description: Description) {

View File

@ -1,111 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.helpers
import android.content.Context
import android.location.Location
import android.location.LocationManager
import android.os.Build
import android.os.SystemClock
import android.util.Log
import androidx.test.core.app.ApplicationProvider
import org.junit.rules.ExternalResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import java.util.Date
import kotlin.random.Random
private const val mockProviderName = LocationManager.GPS_PROVIDER
/**
* Rule that sets up a mock location provider that can inject location samples
* straight to the device that the test is running on.
*
* Credit to the mapbox team
* https://github.com/mapbox/mapbox-navigation-android/blob/87fab7ea1152b29533ee121eaf6c05bc202adf02/libtesting-ui/src/main/java/com/mapbox/navigation/testing/ui/MockLocationUpdatesRule.kt
*
*/
class MockLocationUpdatesRule : ExternalResource() {
private val appContext = (ApplicationProvider.getApplicationContext() as Context)
val latitude = Random.nextDouble(-90.0, 90.0)
val longitude = Random.nextDouble(-180.0, 180.0)
private val locationManager: LocationManager by lazy {
(appContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager)
}
override fun before() {
/* ADB command to enable the mock location setting on the device.
* Will not be turned back off due to limitations on knowing its initial state.
*/
mDevice.executeShellCommand(
"appops set " +
appContext.packageName +
" android:mock_location allow",
)
// To mock locations we need a location provider, so we generate and set it here.
try {
locationManager.addTestProvider(
mockProviderName,
false,
false,
false,
false,
true,
true,
true,
3,
2,
)
} catch (ex: Exception) {
// unstable
Log.w("MockLocationUpdatesRule", "addTestProvider failed")
}
locationManager.setTestProviderEnabled(mockProviderName, true)
}
// Cleaning up the location provider after the test.
override fun after() {
locationManager.setTestProviderEnabled(mockProviderName, false)
locationManager.removeTestProvider(mockProviderName)
}
/**
* Generate a valid mock location data and set with the help of a test provider.
*
* @param modifyLocation optional callback for modifying the constructed location before setting it.
*/
fun setMockLocation(modifyLocation: (Location.() -> Unit)? = null) {
check(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
"MockLocationUpdatesRule is supported only on Android devices " +
"running version >= Build.VERSION_CODES.M"
}
val location = Location(mockProviderName)
location.time = Date().time
location.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos()
location.accuracy = 5f
location.altitude = 0.0
location.bearing = 0f
location.speed = 5f
location.latitude = latitude
location.longitude = longitude
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
location.verticalAccuracyMeters = 5f
location.bearingAccuracyDegrees = 5f
location.speedAccuracyMetersPerSecond = 5f
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
location.elapsedRealtimeUncertaintyNanos = 0.0
}
modifyLocation?.let {
location.apply(it)
}
locationManager.setTestProviderLocation(mockProviderName, location)
}
}

View File

@ -8,23 +8,12 @@ import androidx.test.espresso.IdlingResourceTimeoutException
import androidx.test.espresso.NoMatchingViewException
import androidx.test.uiautomator.UiObjectNotFoundException
import junit.framework.AssertionFailedError
import kotlinx.coroutines.runBlocking
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
import org.mozilla.fenix.components.PermissionStorage
import org.mozilla.fenix.helpers.IdlingResourceHelper.unregisterAllIdlingResources
import org.mozilla.fenix.helpers.TestHelper.appContext
/**
* Rule to retry flaky tests for a given number of times, catching some of the more common exceptions.
* The Rule doesn't clear the app state in between retries, so we are doing some cleanup here.
* The @Before and @After methods are not called between retries.
*
*/
class RetryTestRule(private val retryCount: Int = 5) : TestRule {
// Used for clearing all permission data after each test try
private val permissionStorage = PermissionStorage(appContext.applicationContext)
@Suppress("TooGenericExceptionCaught", "ComplexMethod")
override fun apply(base: Statement, description: Description): Statement {
@ -35,57 +24,36 @@ class RetryTestRule(private val retryCount: Int = 5) : TestRule {
break
} catch (t: AssertionError) {
unregisterAllIdlingResources()
runBlocking {
permissionStorage.deleteAllSitePermissions()
}
if (i == retryCount) {
throw t
}
} catch (t: AssertionFailedError) {
unregisterAllIdlingResources()
runBlocking {
permissionStorage.deleteAllSitePermissions()
}
if (i == retryCount) {
throw t
}
} catch (t: UiObjectNotFoundException) {
unregisterAllIdlingResources()
runBlocking {
permissionStorage.deleteAllSitePermissions()
}
if (i == retryCount) {
throw t
}
} catch (t: NoMatchingViewException) {
unregisterAllIdlingResources()
runBlocking {
permissionStorage.deleteAllSitePermissions()
}
if (i == retryCount) {
throw t
}
} catch (t: IdlingResourceTimeoutException) {
unregisterAllIdlingResources()
runBlocking {
permissionStorage.deleteAllSitePermissions()
}
if (i == retryCount) {
throw t
}
} catch (t: RuntimeException) {
unregisterAllIdlingResources()
runBlocking {
permissionStorage.deleteAllSitePermissions()
}
if (i == retryCount) {
throw t
}
} catch (t: NullPointerException) {
unregisterAllIdlingResources()
runBlocking {
permissionStorage.deleteAllSitePermissions()
}
if (i == retryCount) {
throw t
}

View File

@ -7,14 +7,14 @@ package org.mozilla.fenix.helpers
import android.os.Handler
import android.os.Looper
import androidx.test.platform.app.InstrumentationRegistry
import java.io.IOException
import java.io.InputStream
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import okhttp3.mockwebserver.RecordedRequest
import okio.Buffer
import okio.source
import java.io.IOException
import java.io.InputStream
/**
* A [MockWebServer] [Dispatcher] that will return a generic search results page in the body of

View File

@ -34,7 +34,7 @@ object TestAssetHelper {
TestAsset(
server.url("pages/generic$it.html").toString().toUri()!!,
"Page content: $it",
"",
""
)
}
}
@ -87,30 +87,6 @@ object TestAssetHelper {
return TestAsset(url, "", "")
}
fun getAddressFormAsset(server: MockWebServer): TestAsset {
val url = server.url("pages/addressForm.html").toString().toUri()!!
return TestAsset(url, "", "")
}
fun getCreditCardFormAsset(server: MockWebServer): TestAsset {
val url = server.url("pages/creditCardForm.html").toString().toUri()!!
return TestAsset(url, "", "")
}
fun getHTMLControlsFormAsset(server: MockWebServer): TestAsset {
val url = server.url("pages/htmlControls.html").toString().toUri()!!
return TestAsset(url, "", "")
}
fun getExternalLinksAsset(server: MockWebServer): TestAsset {
val url = server.url("pages/externalLinks.html").toString().toUri()!!
return TestAsset(url, "", "")
}
fun getAudioPageAsset(server: MockWebServer): TestAsset {
val url = server.url("pages/audioMediaPage.html").toString().toUri()!!
val title = "Audio_Test_Page"
@ -126,10 +102,4 @@ object TestAssetHelper {
return TestAsset(url, content, title)
}
fun getStorageTestAsset(server: MockWebServer, pageAsset: String): TestAsset {
val url = server.url("pages/$pageAsset").toString().toUri()!!
return TestAsset(url, "", "")
}
}

View File

@ -2,36 +2,23 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@file:Suppress("DEPRECATION")
package org.mozilla.fenix.helpers
import android.Manifest
import android.app.ActivityManager
import android.app.PendingIntent
import android.content.ActivityNotFoundException
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.storage.StorageManager
import android.os.storage.StorageVolume
import android.provider.Settings
import android.util.Log
import android.view.View
import androidx.annotation.RequiresApi
import androidx.browser.customtabs.CustomTabsIntent
import androidx.test.espresso.Espresso
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.IdlingResource
import androidx.test.espresso.action.ViewActions.longClick
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.intent.Intents.intended
@ -42,11 +29,10 @@ import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withParent
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.runner.permission.PermissionRequester
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject
import androidx.test.uiautomator.UiObjectNotFoundException
import androidx.test.uiautomator.UiScrollable
import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
@ -57,30 +43,23 @@ import org.hamcrest.CoreMatchers
import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.Matcher
import org.junit.Assert
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.mozilla.fenix.Config
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_APPS_PHOTOS
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.ext.waitNotNull
import org.mozilla.fenix.helpers.idlingresource.NetworkConnectionIdlingResource
import org.mozilla.fenix.ui.robots.BrowserRobot
import org.mozilla.fenix.ui.robots.mDevice
import org.mozilla.fenix.utils.IntentUtils
import org.mozilla.gecko.util.ThreadUtils
import java.io.File
import java.util.Locale
import java.util.regex.Pattern
object TestHelper {
val appContext: Context = InstrumentationRegistry.getInstrumentation().targetContext
val appName = appContext.appName
var mDevice: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
val packageName: String = appContext.packageName
val appName = appContext.appName
fun scrollToElementByText(text: String): UiScrollable {
val appView = UiScrollable(UiSelector().scrollable(true))
@ -92,19 +71,18 @@ object TestHelper {
fun longTapSelectItem(url: Uri) {
mDevice.waitNotNull(
Until.findObject(By.text(url.toString())),
waitingTime,
waitingTime
)
onView(
allOf(
withId(R.id.url),
withText(url.toString()),
),
withText(url.toString())
)
).perform(longClick())
}
fun restartApp(activity: HomeActivityIntentTestRule) {
with(activity) {
updateCachedSettings()
finishActivity()
mDevice.waitForIdle()
launchActivity(null)
@ -122,16 +100,10 @@ object TestHelper {
fun waitUntilObjectIsFound(resourceName: String) {
mDevice.waitNotNull(
Until.findObjects(By.res(resourceName)),
waitingTime,
waitingTime
)
}
fun waitUntilSnackbarGone() {
mDevice.findObject(
UiSelector().resourceId("$packageName:id/snackbar_layout"),
).waitUntilGone(waitingTime)
}
fun verifyUrl(urlSubstring: String, resourceName: String, resId: Int) {
waitUntilObjectIsFound(resourceName)
mDevice.findObject(UiSelector().text(urlSubstring)).waitForExists(waitingTime)
@ -154,24 +126,25 @@ object TestHelper {
}
}
@RequiresApi(Build.VERSION_CODES.R)
fun deleteDownloadedFileOnStorage(fileName: String) {
val storageManager: StorageManager? = appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager?
val storageVolumes = storageManager!!.storageVolumes
val storageVolume: StorageVolume = storageVolumes[0]
val file = File(storageVolume.directory!!.path + "/Download/" + fileName)
// Remove test file from Google Photos (AOSP) on Firebase
fun deleteDownloadFromStorage() {
val deleteButton = mDevice.findObject(UiSelector().resourceId("$GOOGLE_APPS_PHOTOS:id/trash"))
deleteButton.click()
// Sometimes there's a secondary confirmation
try {
file.delete()
Log.d("TestLog", "File delete try 1")
assertFalse("The file was not deleted", file.exists())
} catch (e: AssertionError) {
file.delete()
Log.d("TestLog", "File delete retried")
assertFalse("The file was not deleted", file.exists())
val deleteConfirm = mDevice.findObject(UiSelector().text("Got it"))
deleteConfirm.click()
} catch (e: UiObjectNotFoundException) {
// Do nothing
}
val trashIt = mDevice.findObject(UiSelector().resourceId("$GOOGLE_APPS_PHOTOS:id/move_to_trash"))
trashIt.click()
}
fun setNetworkEnabled(enabled: Boolean) {
val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
val networkDisconnectedIdlingResource = NetworkConnectionIdlingResource(false)
val networkConnectedIdlingResource = NetworkConnectionIdlingResource(true)
@ -203,7 +176,7 @@ object TestHelper {
fun createCustomTabIntent(
pageUrl: String,
customMenuItemLabel: String = "",
customActionButtonDescription: String = "",
customActionButtonDescription: String = ""
): Intent {
val appContext = InstrumentationRegistry.getInstrumentation()
.targetContext
@ -214,9 +187,7 @@ object TestHelper {
.setShareState(CustomTabsIntent.SHARE_STATE_ON)
.setActionButton(
createTestBitmap(),
customActionButtonDescription,
pendingIntent,
true,
customActionButtonDescription, pendingIntent, true
)
.build()
customTabsIntent.intent.data = Uri.parse(pageUrl)
@ -247,73 +218,23 @@ object TestHelper {
e.printStackTrace()
}
} else {
val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mDevice.waitNotNull(
Until.findObject(By.text("Could not open file")),
waitingTime,
waitingTime
)
}
}
fun assertNativeAppOpens(appPackageName: String, url: String = "") {
fun assertNativeAppOpens(appPackageName: String, url: String) {
if (isPackageInstalled(appPackageName)) {
mDevice.waitForIdle(waitingTimeShort)
assertTrue(
mDevice.findObject(UiSelector().packageName(appPackageName))
.waitForExists(waitingTime),
)
intended(toPackage(appPackageName))
} else {
BrowserRobot().verifyUrl(url)
}
}
fun assertPlayStoreOpens() {
if (isPackageInstalled(Constants.PackageName.GOOGLE_PLAY_SERVICES)) {
try {
intended(toPackage(Constants.PackageName.GOOGLE_PLAY_SERVICES))
} catch (e: AssertionFailedError) {
BrowserRobot().verifyRateOnGooglePlayURL()
}
} else {
BrowserRobot().verifyRateOnGooglePlayURL()
}
}
/**
* Checks whether the latest activity of the application is used for custom tabs or PWAs.
*
* @return Boolean value that helps us know if the current activity supports custom tabs or PWAs.
*/
fun isExternalAppBrowserActivityInCurrentTask(): Boolean {
val activityManager = appContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
mDevice.waitForIdle(waitingTimeShort)
return activityManager.appTasks[0].taskInfo.topActivity!!.className == ExternalAppBrowserActivity::class.java.name
}
/**
* Run test with automatically registering idling resources and cleanup.
*
* @param idlingResources zero or more [IdlingResource] to be used when running [testBlock].
* @param testBlock test code to execute.
*/
fun registerAndCleanupIdlingResources(
vararg idlingResources: IdlingResource,
testBlock: () -> Unit,
) {
idlingResources.forEach {
IdlingRegistry.getInstance().register(it)
}
try {
testBlock()
} finally {
idlingResources.forEach {
IdlingRegistry.getInstance().unregister(it)
}
}
}
// exit from Menus to home screen or browser
fun exitMenu() {
val toolbar =
@ -332,9 +253,9 @@ object TestHelper {
return withParent(
hasSibling(
withChild(
matcher,
),
),
matcher
)
)
)
}
@ -348,117 +269,34 @@ object TestHelper {
}
fun grantPermission() {
val instrumentation = InstrumentationRegistry.getInstrumentation()
if (Build.VERSION.SDK_INT >= 23) {
mDevice.findObject(
UiDevice.getInstance(instrumentation).findObject(
By.text(
when (Build.VERSION.SDK_INT) {
Build.VERSION_CODES.R -> Pattern.compile(
"WHILE USING THE APP",
Pattern.CASE_INSENSITIVE,
"WHILE USING THE APP", Pattern.CASE_INSENSITIVE
)
else -> Pattern.compile("Allow", Pattern.CASE_INSENSITIVE)
},
),
}
)
).click()
}
}
fun denyPermission() {
val instrumentation = InstrumentationRegistry.getInstrumentation()
if (Build.VERSION.SDK_INT >= 23) {
mDevice.findObject(
UiDevice.getInstance(instrumentation).findObject(
By.text(
when (Build.VERSION.SDK_INT) {
Build.VERSION_CODES.R -> Pattern.compile(
"DENY",
Pattern.CASE_INSENSITIVE,
"DENY", Pattern.CASE_INSENSITIVE
)
else -> Pattern.compile("Deny", Pattern.CASE_INSENSITIVE)
},
),
}
)
).click()
}
}
fun isTestLab(): Boolean {
return Settings.System.getString(appContext.contentResolver, "firebase.test.lab").toBoolean()
}
private val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
fun generateRandomString(stringLength: Int) =
(1..stringLength)
.map { kotlin.random.Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("")
/**
* Changes the default language of the entire device, not just the app.
* Runs on Debug variant as we don't want to adjust Release permission manifests
* Runs the test in its testBlock.
* Cleans up and sets the default locale after it's done.
*/
fun runWithSystemLocaleChanged(locale: Locale, testRule: ActivityTestRule<HomeActivity>, testBlock: () -> Unit) {
if (Config.channel.isDebug) {
/* Sets permission to change device language */
PermissionRequester().apply {
addPermissions(
Manifest.permission.CHANGE_CONFIGURATION,
)
requestPermissions()
}
val defaultLocale = Locale.getDefault()
try {
setSystemLocale(locale)
testBlock()
ThreadUtils.runOnUiThread { testRule.activity.recreate() }
} catch (e: Exception) {
e.printStackTrace()
} finally {
setSystemLocale(defaultLocale)
}
}
}
/**
* Changes the default language of the entire device, not just the app.
*/
private fun setSystemLocale(locale: Locale) {
val activityManagerNative = Class.forName("android.app.ActivityManagerNative")
val am = activityManagerNative.getMethod("getDefault", *arrayOfNulls(0))
.invoke(activityManagerNative, *arrayOfNulls(0))
val config = InstrumentationRegistry.getInstrumentation().context.resources.configuration
config.javaClass.getDeclaredField("locale")[config] = locale
config.javaClass.getDeclaredField("userSetLocale").setBoolean(config, true)
am.javaClass.getMethod(
"updateConfiguration",
Configuration::class.java,
).invoke(am, config)
}
/**
* Creates clipboard data.
*/
fun setTextToClipBoard(context: Context, message: String) {
val clipBoard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipData = ClipData.newPlainText("label", message)
clipBoard.setPrimaryClip(clipData)
}
/**
* Returns sponsored shortcut title based on the index.
*/
fun getSponsoredShortcutTitle(position: Int): String {
val sponsoredShortcut = mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/top_site_item")
.index(position - 1),
).getChild(
UiSelector()
.resourceId("$packageName:id/top_site_title"),
).text
return sponsoredShortcut
}
}

View File

@ -9,7 +9,7 @@ import androidx.test.espresso.IdlingResource
class ViewVisibilityIdlingResource(
private val view: View,
private val expectedVisibility: Int,
private val expectedVisibility: Int
) : IdlingResource {
private var resourceCallback: IdlingResource.ResourceCallback? = null
private var isIdle: Boolean = false

View File

@ -43,6 +43,6 @@ fun ViewInteraction.clickAtLocationInView(locationInView: GeneralLocation): View
locationInView,
Press.FINGER,
InputDevice.SOURCE_UNKNOWN,
MotionEvent.BUTTON_PRIMARY,
),
MotionEvent.BUTTON_PRIMARY
)
)

View File

@ -16,5 +16,5 @@ import org.mozilla.fenix.helpers.TestAssetHelper
*/
fun UiDevice.waitNotNull(
searchCondition: SearchCondition<*>,
waitTime: Long = TestAssetHelper.waitingTime,
waitTime: Long = TestAssetHelper.waitingTime
) = assertNotNull(wait(searchCondition, waitTime))

View File

@ -10,7 +10,7 @@ import androidx.test.espresso.IdlingResource
import mozilla.components.feature.addons.ui.AddonInstallationDialogFragment
class AddonsInstallingIdlingResource(
private val fragmentManager: FragmentManager,
private val fragmentManager: FragmentManager
) :
IdlingResource {
private var resourceCallback: IdlingResource.ResourceCallback? = null
@ -25,9 +25,8 @@ class AddonsInstallingIdlingResource(
}
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {
if (callback != null) {
if (callback != null)
resourceCallback = callback
}
}
private fun isInstalledAddonDialogShown(): Boolean {

View File

@ -20,16 +20,14 @@ class AddonsLoadingIdlingResource(val fragmentManager: FragmentManager) : Idling
override fun isIdleNow(): Boolean {
val idle = addonsFinishedLoading()
if (idle) {
if (idle)
resourceCallback?.onTransitionToIdle()
}
return idle
}
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {
if (callback != null) {
if (callback != null)
resourceCallback = callback
}
}
private fun addonsFinishedLoading(): Boolean {
@ -39,9 +37,8 @@ class AddonsLoadingIdlingResource(val fragmentManager: FragmentManager) : Idling
addonsManagementFragment.view?.findViewById<View>(R.id.add_ons_progress_bar)
} ?: return true
if (progressbar.visibility == VISIBLE) {
if (progressbar.visibility == VISIBLE)
return false
}
return true
}

View File

@ -32,16 +32,14 @@ class NetworkConnectionIdlingResource(private val networkConnected: Boolean) : I
} else {
!isOnline()
}
if (idle) {
if (idle)
resourceCallback?.onTransitionToIdle()
}
return idle
}
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {
if (callback != null) {
if (callback != null)
resourceCallback = callback
}
}
private fun isOnline(): Boolean {

View File

@ -5,13 +5,13 @@
package org.mozilla.fenix.helpers.matchers
import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.StateListDrawable
import android.view.View
import android.widget.ImageView
import androidx.test.espresso.matcher.BoundedMatcher
import org.hamcrest.Description
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.StateListDrawable
import android.graphics.drawable.Drawable
class BitmapDrawableMatcher(private val bitmap: Bitmap, private val name: String) :
BoundedMatcher<View, ImageView>(ImageView::class.java) {

View File

@ -28,7 +28,7 @@ class BottomSheetBehaviorHalfExpandedMaxRatioMatcher(private val maxHalfExpanded
override fun describeTo(description: Description?) {
description?.appendText(
"BottomSheetBehavior with an at max halfExpandedRation: " +
"$maxHalfExpandedRatio",
"$maxHalfExpandedRatio"
)
}

View File

@ -6,6 +6,7 @@ package org.mozilla.fenix.perf
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.children
import androidx.recyclerview.widget.RecyclerView
@ -15,6 +16,7 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.HomeActivityTestRule
@ -33,7 +35,7 @@ import org.mozilla.fenix.helpers.HomeActivityTestRule
*
* Say no to main thread IO! 🙅
*/
private const val EXPECTED_SUPPRESSION_COUNT = 18
private const val EXPECTED_SUPPRESSION_COUNT = 19
/**
* The number of times we call the `runBlocking` coroutine method on the main thread during this
@ -46,7 +48,7 @@ private const val EXPECTED_SUPPRESSION_COUNT = 18
* generally be replaced with a slow operation on a background thread launching onto the main thread
* when completed. However, in a very small number of cases, blocking may be impossible to avoid.
*/
private val EXPECTED_RUNBLOCKING_RANGE = 0..2 // CI has +1 counts compared to local runs: increment these together
private val EXPECTED_RUNBLOCKING_RANGE = 0..1 // CI has +1 counts compared to local runs: increment these together
/**
* The number of `ConstraintLayout`s we inflate that are children of a `RecyclerView` during this
@ -61,7 +63,7 @@ private val EXPECTED_RUNBLOCKING_RANGE = 0..2 // CI has +1 counts compared to lo
* If the view hierarchy uses Jetpack Compose, switching to that is also an option.
*/
private val EXPECTED_RECYCLER_VIEW_CONSTRAINT_LAYOUT_CHILDREN =
4..6 // The messaging framework is not deterministic and could add to the count.
3..4 // The messaging framework is not deterministic and could add a +1 to the count
/**
* The number of layouts we inflate during this start up scenario. Incrementing the expected value
@ -79,7 +81,7 @@ private val EXPECTED_NUMBER_OF_INFLATION =
private val failureMsgStrictMode = getErrorMessage("StrictMode suppression")
private val failureMsgRunBlocking = getErrorMessage("runBlockingIncrement")
private val failureMsgRecyclerViewConstraintLayoutChildren = getErrorMessage(
"ConstraintLayout being a common direct descendant of a RecyclerView",
"ConstraintLayout being a common direct descendant of a RecyclerView"
)
private val failureMsgNumberOfInflation = getErrorMessage("start up inflation")
@ -114,24 +116,21 @@ class StartupExcessiveResourceUseTest {
val actualSuppresionCount = activityTestRule.activity.components.strictMode.suppressionCount.get().toInt()
val actualRunBlocking = RunBlockingCounter.count.get()
val rootView = activityTestRule.activity.findViewById<LinearLayout>(R.id.rootContainer)
val actualRecyclerViewConstraintLayoutChildren = countRecyclerViewConstraintLayoutChildren(rootView, null)
val actualNumberOfInflations = InflationCounter.inflationCount.get()
assertEquals(failureMsgStrictMode, EXPECTED_SUPPRESSION_COUNT, actualSuppresionCount)
assertTrue(failureMsgRunBlocking + "actual: $actualRunBlocking", actualRunBlocking in EXPECTED_RUNBLOCKING_RANGE)
// This below asserts fail in Firebase with different values for
// "actualRecyclerViewConstraintLayoutChildren" or "actualNumberOfInflations"
// See https://github.com/mozilla-mobile/fenix/pull/26512 and https://github.com/mozilla-mobile/fenix/issues/25142
//
// val rootView = activityTestRule.activity.findViewById<LinearLayout>(R.id.rootContainer)
// val actualRecyclerViewConstraintLayoutChildren = countRecyclerViewConstraintLayoutChildren(rootView, null)
// assertTrue(
// failureMsgRecyclerViewConstraintLayoutChildren + "actual: $actualRecyclerViewConstraintLayoutChildren",
// actualRecyclerViewConstraintLayoutChildren in EXPECTED_RECYCLER_VIEW_CONSTRAINT_LAYOUT_CHILDREN,
// )
// val actualNumberOfInflations = InflationCounter.inflationCount.get()
// assertTrue(
// failureMsgNumberOfInflation + "actual: $actualNumberOfInflations",
// actualNumberOfInflations in EXPECTED_NUMBER_OF_INFLATION,
// )
assertTrue(
failureMsgRecyclerViewConstraintLayoutChildren + "actual: $actualRecyclerViewConstraintLayoutChildren",
actualRecyclerViewConstraintLayoutChildren in EXPECTED_RECYCLER_VIEW_CONSTRAINT_LAYOUT_CHILDREN,
)
assertTrue(
failureMsgNumberOfInflation + "actual: $actualNumberOfInflations",
actualNumberOfInflations in EXPECTED_NUMBER_OF_INFLATION,
)
}
}

View File

@ -7,34 +7,24 @@
package org.mozilla.fenix.screenshots
import android.os.SystemClock
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.uiautomator.UiDevice
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.mDevice
import tools.fastlane.screengrab.Screengrab
import tools.fastlane.screengrab.locale.LocaleTestRule
class DefaultHomeScreenTest : ScreenshotTest() {
private lateinit var mDevice: UiDevice
@Rule @JvmField
val localeTestRule = LocaleTestRule()
@get:Rule
var mActivityTestRule: ActivityTestRule<HomeActivity> = HomeActivityTestRule()
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
}
@After
fun tearDown() {
mActivityTestRule.getActivity().finishAndRemoveTask()
@ -43,6 +33,7 @@ class DefaultHomeScreenTest : ScreenshotTest() {
@Test
fun showDefaultHomeScreen() {
homeScreen {
swipeToBottom()
verifyAccountsSignInButton()
Screengrab.screenshot("HomeScreenRobot_home-screen-scroll")
TestAssetHelper.waitingTime

View File

@ -10,24 +10,24 @@ import android.os.SystemClock
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.click
import org.mozilla.fenix.helpers.ext.waitNotNull
import org.mozilla.fenix.ui.robots.bookmarksMenu
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.mDevice
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.swipeToBottom
import tools.fastlane.screengrab.Screengrab
@ -35,18 +35,15 @@ import tools.fastlane.screengrab.locale.LocaleTestRule
class MenuScreenShotTest : ScreenshotTest() {
private lateinit var mockWebServer: MockWebServer
private lateinit var mDevice: UiDevice
@Rule
@JvmField
val localeTestRule = LocaleTestRule()
@get:Rule
var mActivityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides()
var mActivityTestRule: ActivityTestRule<HomeActivity> = HomeActivityTestRule()
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -201,7 +198,7 @@ fun deleteBookmarkFolder() = onView(withText(R.string.bookmark_menu_delete_butto
fun tapOnTabCounter() = onView(withId(R.id.counter_text)).click()
fun settingsAccountPreferences() = onView(withText(R.string.preferences_sync_2)).click()
fun settingsAccountPreferences() = onView(withText(R.string.preferences_sync)).click()
fun settingsSearch() = onView(withText(R.string.preferences_search)).click()

View File

@ -19,4 +19,4 @@ requests = "*"
[dev-packages]
[requires]
python_version = "3.10"
python_version = "2.7"

View File

@ -1,11 +1,11 @@
{
"_meta": {
"hash": {
"sha256": "cf743d605ee37525af06865c7961ee99f1720fa9d6352eedc4bbfa5fa78f75ef"
"sha256": "112a12fa2e9e8117b399b60a49b4c8799a614ef655992640c95149bf95f33e8b"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.10"
"python_version": "2.7"
},
"sources": [
{
@ -16,21 +16,27 @@
]
},
"default": {
"async-generator": {
"atomicwrites": {
"hashes": [
"sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b",
"sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"
"sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197",
"sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"
],
"markers": "python_version >= '3.5'",
"version": "==1.10"
"version": "==1.4.0"
},
"attrs": {
"hashes": [
"sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6",
"sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"
"sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6",
"sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"
],
"markers": "python_version >= '3.5'",
"version": "==22.1.0"
"version": "==20.3.0"
},
"backports.functools-lru-cache": {
"hashes": [
"sha256:0bada4c2f8a43d533e4ecb7a12214d9420e66eb206d54bf2d682581ca4b80848",
"sha256:8fde5f188da2d593bd5bc0be98d9abc46c95bb8a9dde93429570192ee6cc2d4a"
],
"markers": "python_version < '3.2'",
"version": "==1.6.1"
},
"blessings": {
"hashes": [
@ -38,127 +44,130 @@
"sha256:b1fdd7e7a675295630f9ae71527a8ebc10bfefa236b3d6aa4932ee4462c17ba3",
"sha256:caad5211e7ba5afe04367cdd4cfc68fa886e2e08f6f35e76b7387d2109ccea6e"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.7"
},
"certifi": {
"hashes": [
"sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d",
"sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"
"sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c",
"sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"
],
"version": "==2022.6.15"
"version": "==2020.12.5"
},
"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"
"sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e",
"sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d",
"sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a",
"sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec",
"sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362",
"sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668",
"sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c",
"sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b",
"sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06",
"sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698",
"sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2",
"sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c",
"sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7",
"sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009",
"sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03",
"sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b",
"sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909",
"sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53",
"sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35",
"sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26",
"sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b",
"sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01",
"sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb",
"sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293",
"sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd",
"sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d",
"sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3",
"sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d",
"sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e",
"sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca",
"sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d",
"sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775",
"sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375",
"sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b",
"sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b",
"sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f"
],
"version": "==1.15.1"
"version": "==1.14.4"
},
"charset-normalizer": {
"chardet": {
"hashes": [
"sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5",
"sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413"
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
],
"markers": "python_version >= '3.6'",
"version": "==2.1.0"
"version": "==3.0.4"
},
"configparser": {
"hashes": [
"sha256:254c1d9c79f60c45dfde850850883d5aaa7f19a23f13561243a050d5a7c3fe4c",
"sha256:c7d282687a5308319bf3d2e7706e575c635b0a470342641c93bea0ea3b5331df"
],
"markers": "python_version < '3'",
"version": "==4.0.2"
},
"contextlib2": {
"hashes": [
"sha256:01f490098c18b19d2bd5bb5dc445b2054d2fa97f09a4280ba2c5f3c394c8162e",
"sha256:3355078a159fbb44ee60ea80abd0d87b80b78c248643b49aa6d94673b413609b"
],
"markers": "python_version < '3.4'",
"version": "==0.6.0.post1"
},
"cryptography": {
"hashes": [
"sha256:190f82f3e87033821828f60787cfa42bff98404483577b591429ed99bed39d59",
"sha256:2be53f9f5505673eeda5f2736bea736c40f051a739bfae2f92d18aed1eb54596",
"sha256:30788e070800fec9bbcf9faa71ea6d8068f5136f60029759fd8c3efec3c9dcb3",
"sha256:3d41b965b3380f10e4611dbae366f6dc3cefc7c9ac4e8842a806b9672ae9add5",
"sha256:4c590ec31550a724ef893c50f9a97a0c14e9c851c85621c5650d699a7b88f7ab",
"sha256:549153378611c0cca1042f20fd9c5030d37a72f634c9326e225c9f666d472884",
"sha256:63f9c17c0e2474ccbebc9302ce2f07b55b3b3fcb211ded18a42d5764f5c10a82",
"sha256:6bc95ed67b6741b2607298f9ea4932ff157e570ef456ef7ff0ef4884a134cc4b",
"sha256:7099a8d55cd49b737ffc99c17de504f2257e3787e02abe6d1a6d136574873441",
"sha256:75976c217f10d48a8b5a8de3d70c454c249e4b91851f6838a4e48b8f41eb71aa",
"sha256:7bc997818309f56c0038a33b8da5c0bfbb3f1f067f315f9abd6fc07ad359398d",
"sha256:80f49023dd13ba35f7c34072fa17f604d2f19bf0989f292cedf7ab5770b87a0b",
"sha256:91ce48d35f4e3d3f1d83e29ef4a9267246e6a3be51864a5b7d2247d5086fa99a",
"sha256:a958c52505c8adf0d3822703078580d2c0456dd1d27fabfb6f76fe63d2971cd6",
"sha256:b62439d7cd1222f3da897e9a9fe53bbf5c104fff4d60893ad1355d4c14a24157",
"sha256:b7f8dd0d4c1f21759695c05a5ec8536c12f31611541f8904083f3dc582604280",
"sha256:d204833f3c8a33bbe11eda63a54b1aad7aa7456ed769a982f21ec599ba5fa282",
"sha256:e007f052ed10cc316df59bc90fbb7ff7950d7e2919c9757fd42a2b8ecf8a5f67",
"sha256:f2dcb0b3b63afb6df7fd94ec6fbddac81b5492513f7b0436210d390c14d46ee8",
"sha256:f721d1885ecae9078c3f6bbe8a88bc0786b6e749bf32ccec1ef2b18929a05046",
"sha256:f7a6de3e98771e183645181b3627e2563dcde3ce94a9e42a3f427d2255190327",
"sha256:f8c0a6e9e1dd3eb0414ba320f85da6b0dcbd543126e30fcc546e7372a7fbf3b9"
"sha256:22f8251f68953553af4f9c11ec5f191198bc96cff9f0ac5dd5ff94daede0ee6d",
"sha256:284e275e3c099a80831f9898fb5c9559120d27675c3521278faba54e584a7832",
"sha256:3e17d02941c0f169c5b877597ca8be895fca0e5e3eb882526a74aa4804380a98",
"sha256:52a47e60953679eea0b4d490ca3c241fb1b166a7b161847ef4667dfd49e7699d",
"sha256:57b8c1ed13b8aa386cabbfde3be175d7b155682470b0e259fecfe53850967f8a",
"sha256:6a8f64ed096d13f92d1f601a92d9fd1f1025dc73a2ca1ced46dcf5e0d4930943",
"sha256:6e8a3c7c45101a7eeee93102500e1b08f2307c717ff553fcb3c1127efc9b6917",
"sha256:7ef41304bf978f33cfb6f43ca13bb0faac0c99cda33693aa20ad4f5e34e8cb8f",
"sha256:87c2fffd61e934bc0e2c927c3764c20b22d7f5f7f812ee1a477de4c89b044ca6",
"sha256:88069392cd9a1e68d2cfd5c3a2b0d72a44ef3b24b8977a4f7956e9e3c4c9477a",
"sha256:8a0866891326d3badb17c5fd3e02c926b635e8923fa271b4813cd4d972a57ff3",
"sha256:8f0fd8b0751d75c4483c534b209e39e918f0d14232c0d8a2a76e687f64ced831",
"sha256:9a07e6d255053674506091d63ab4270a119e9fc83462c7ab1dbcb495b76307af",
"sha256:9a8580c9afcdcddabbd064c0a74f337af74ff4529cdf3a12fa2e9782d677a2e5",
"sha256:bd80bc156d3729b38cb227a5a76532aef693b7ac9e395eea8063ee50ceed46a5",
"sha256:d1cbc3426e6150583b22b517ef3720036d7e3152d428c864ff0f3fcad2b97591",
"sha256:e15ac84dcdb89f92424cbaca4b0b34e211e7ce3ee7b0ec0e4f3c55cee65fae5a",
"sha256:e4789b84f8dedf190148441f7c5bfe7244782d9cbb194a36e17b91e7d3e1cca9",
"sha256:f01c9116bfb3ad2831e125a73dcd957d173d6ddca7701528eff1e7d97972872c",
"sha256:f0e3986f6cce007216b23c490f093f35ce2068f3c244051e559f647f6731b7ae",
"sha256:f2aa3f8ba9e2e3fd49bd3de743b976ab192fbf0eb0348cebde5d2a9de0090a9f",
"sha256:fb70a4cedd69dc52396ee114416a3656e011fb0311fca55eb55c7be6ed9c8aef"
],
"version": "==37.0.4"
"index": "pypi",
"version": "==3.2"
},
"distro": {
"hashes": [
"sha256:151aeccf60c216402932b52e40ee477a939f8d58898927378a02abbe852c1c39",
"sha256:d596311d707e692c2160c37807f83e3820c5d539d5a83e87cfb6babd8ba3a06b"
"sha256:0e58756ae38fbd8fc3020d54badb8eae17c5b9dcbed388b17bb55b8a5928df92",
"sha256:df74eed763e18d10d0da624258524ae80486432cd17392d9c3d96f5e83cd2799"
],
"markers": "python_version >= '3.6'",
"version": "==1.7.0"
"version": "==1.5.0"
},
"enum34": {
"hashes": [
"sha256:a98a201d6de3f2ab3db284e70a33b0f896fbf35f8086594e8c9e74b909058d53",
"sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328",
"sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248"
],
"markers": "python_version < '3'",
"version": "==1.1.10"
},
"funcsigs": {
"hashes": [
"sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
"sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"
],
"markers": "python_version < '3.0'",
"version": "==1.0.2"
},
"fxapom": {
"hashes": [
@ -168,14 +177,6 @@
"index": "pypi",
"version": "==1.10.2"
},
"h11": {
"hashes": [
"sha256:70813c1135087a248a4d38cc0e1a0181ffab2188141a93eaf567940c3957ff06",
"sha256:8ddd78563b633ca55346c8cd41ec0af27d3c79931828beffb46ce70a379e7442"
],
"markers": "python_version >= '3.6'",
"version": "==0.13.0"
},
"hawkauthlib": {
"hashes": [
"sha256:935878d3a75832aa76f78ddee13491f1466cbd69a8e7e4248902763cf9953ba9",
@ -185,17 +186,35 @@
},
"idna": {
"hashes": [
"sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff",
"sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"
"sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
"sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
],
"version": "==3.3"
"version": "==2.10"
},
"iniconfig": {
"importlib-metadata": {
"hashes": [
"sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
"sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"
"sha256:b8de9eff2b35fb037368f28a7df1df4e6436f578fa74423505b6c6a778d5b5dd",
"sha256:c2d6341ff566f609e89a2acb2db190e5e1d23d5409d6cc8d2fe34d72443876d4"
],
"version": "==1.1.1"
"markers": "python_version < '3.8'",
"version": "==2.1.1"
},
"ipaddress": {
"hashes": [
"sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc",
"sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2"
],
"markers": "python_version < '3'",
"version": "==1.0.23"
},
"more-itertools": {
"hashes": [
"sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4",
"sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc",
"sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9"
],
"markers": "python_version <= '2.7'",
"version": "==5.0.0"
},
"mozdevice": {
"hashes": [
@ -226,24 +245,25 @@
},
"mozinstall": {
"hashes": [
"sha256:0b14000a88d6a45c37b877eedf897655f665e89410ca629dd500415406ed465e",
"sha256:ec364cfefd3435fb155edd48be9e71819834e4dcacc6c3294c7f2452e200095b"
"sha256:219ba7c51308433487b4f30a2615cb9b3ecd40a76b9faf41cf1b1b005bb5dda7",
"sha256:bbc31a18ee8a1fbec74b67b99c6c0289ffc7daf39eb5b5ff7dc99f1be687eb08"
],
"index": "pypi",
"version": "==2.0.1"
"version": "==2.0.0"
},
"mozlog": {
"hashes": [
"sha256:54b9a1e781ce31fc10079dc8aec509fff7feca83714edeae6c981e279ceb796f"
"sha256:4719d3d00bf1a0b77285d306eb3180f9c1311fffae9640a423fad9d80170e43d",
"sha256:d035f722c15d700e4a7b48b90bdda0a6ad83e25482760949d1abd73468bad07f"
],
"version": "==7.1.0"
"version": "==7.0.1"
},
"mozprocess": {
"hashes": [
"sha256:e64591d02899f6fd50fe391f5635236c5c604d8faae08ab4aafed9c3a66e3966",
"sha256:e8093fe990bafd4ff3e2e49641b182c8085ea9cee2a28c7bdf9fabc2ff9f618f"
"sha256:08e1036b53819fd144331f6dfbbb17fc8ca782bbed2e28b4aa771b8b91f7dffb",
"sha256:54dc59e7f5a9c2c2930bffb7935f36dddd1d94c9fc6ed179e893d2dff353995a"
],
"version": "==1.3.0"
"version": "==1.2.1"
},
"mozprofile": {
"hashes": [
@ -255,11 +275,11 @@
},
"mozrunner": {
"hashes": [
"sha256:35a7d2cf3abee1d8651e92f870f75159605810ba8ea442defae41a5eec462c29",
"sha256:4ee4d44123c1daa7f3648e8b3b0e3a8c1712b3e1ea254d9a4bf80295ea795d41"
"sha256:5e1bdf1709b4b8cb86b3daf3dbc9352d2abfc8428e26cc75a68ce87a565f4f25",
"sha256:f223e9ca7f0acd3f93d4c30760f8d976d41da81edf686cd5063d2973ebbebcfb"
],
"index": "pypi",
"version": "==8.2.1"
"version": "==7.8.0"
},
"mozterm": {
"hashes": [
@ -276,45 +296,41 @@
"index": "pypi",
"version": "==2.3.0"
},
"outcome": {
"hashes": [
"sha256:6f82bd3de45da303cf1f771ecafa1633750a358436a8bb60e06a1ceb745d2672",
"sha256:c4ab89a56575d6d38a05aa16daeaa333109c1f96167aba8901ab18b6b5e0f7f5"
],
"markers": "python_version >= '3.7'",
"version": "==1.2.0"
},
"packaging": {
"hashes": [
"sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
"sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"
"sha256:05af3bb85d320377db281cf254ab050e1a7ebcbf5410685a9a407e18a1f81236",
"sha256:eb41423378682dadb7166144a4926e443093863024de508ca5c9737d6bc08376"
],
"markers": "python_version >= '3.6'",
"version": "==21.3"
"version": "==20.7"
},
"pathlib2": {
"hashes": [
"sha256:0ec8205a157c80d7acc301c0b18fbd5d44fe655968f5d947b6ecef5290fc35db",
"sha256:6cd9a47b597b37cc57de1c05e56fb1a1c9cc9fab04fe78c29acd090418529868"
],
"markers": "python_version < '3.6'",
"version": "==2.3.5"
},
"pluggy": {
"hashes": [
"sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159",
"sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"
"sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0",
"sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"
],
"markers": "python_version >= '3.6'",
"version": "==1.0.0"
"version": "==0.13.1"
},
"progressbar2": {
"hashes": [
"sha256:14d3165a1781d053ffaa117daf27cc706128d2ec1d2977fdb05b6bb079888013",
"sha256:2562ba3e554433f08e81fb7b786208b19de135f3ca1c5da1787d9b05558e6247"
"sha256:ef72be284e7f2b61ac0894b44165926f13f5d995b2bf3cd8a8dedc6224b255a7",
"sha256:fe2738e7ecb7df52ad76307fe610c460c52b50f5335fd26c3ab80ff7655ba1e0"
],
"markers": "python_version >= '3.7'",
"version": "==4.0.0"
"version": "==3.53.1"
},
"py": {
"hashes": [
"sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719",
"sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"
"sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2",
"sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==1.11.0"
"version": "==1.9.0"
},
"pybrowserid": {
"hashes": [
@ -325,10 +341,10 @@
},
"pycparser": {
"hashes": [
"sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9",
"sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"
"sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
"sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
],
"version": "==2.21"
"version": "==2.20"
},
"pyfxa": {
"hashes": [
@ -338,49 +354,32 @@
},
"pyjwt": {
"hashes": [
"sha256:72d1d253f32dbd4f5c88eaf1fdc62f3a19f676ccbadb9dbc5d07e951b2b26daf",
"sha256:d42908208c699b3b973cbeb01a969ba6a96c821eefb1c5bfe4c390c01d67abba"
],
"markers": "python_version >= '3.6'",
"version": "==2.4.0"
},
"pyopenssl": {
"hashes": [
"sha256:660b1b1425aac4a1bea1d94168a85d99f0b3144c869dd4390d27629d0087f1bf",
"sha256:ea252b38c87425b64116f808355e8da644ef9b07e429398bfece610f893ee2e0"
],
"version": "==22.0.0"
},
"pyparsing": {
"hashes": [
"sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb",
"sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"
],
"markers": "python_full_version >= '3.6.8'",
"version": "==3.0.9"
},
"pypom": {
"hashes": [
"sha256:6f56888d25c1faf8fa0d53ef8a4ba1d7dc828e57212f7fe04e8cd21b5eaa924e",
"sha256:a65297125c498c4e9cee99de9b2ddf5b908d0041ee1fc1e90956d3750483fa3d"
],
"version": "==2.2.3"
},
"pysocks": {
"hashes": [
"sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299",
"sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5",
"sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"
"sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e",
"sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96"
],
"version": "==1.7.1"
},
"pyparsing": {
"hashes": [
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
],
"version": "==2.4.7"
},
"pypom": {
"hashes": [
"sha256:4bdd57fceb72d7e6a3645cf6c9322f490d9cfb5d777eac2c851a3b658b813939",
"sha256:6772ec99f0a21a5bdc8c092007a8c813ed18359e67ed70258bbb233df5e28829"
],
"version": "==2.2.0"
},
"pytest": {
"hashes": [
"sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c",
"sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"
"sha256:19e8f75eac01dd3f211edd465b39efbcbdc8fc5f7866d7dd49fedb30d8adf339",
"sha256:c77a5f30a90e0ce24db9eaa14ddfd38d4afb5ea159309bdd2dae55b931bc9324"
],
"index": "pypi",
"version": "==7.1.2"
"version": "==4.6.9"
},
"pytest-fxa": {
"hashes": [
@ -392,27 +391,26 @@
},
"pytest-html": {
"hashes": [
"sha256:3ee1cf319c913d19fe53aeb0bc400e7b0bc2dbeb477553733db1dad12eb75ee3",
"sha256:b7f82f123936a3f4d2950bc993c2c1ca09ce262c9ae12f9ac763a2401380b455"
"sha256:06e7e13131649b4fe522cf04054efb7b4749ff2c7160755e4acfd8e89a7e5955",
"sha256:f0fae6de71f02f62f9460f628d0c5f70b0cdc86bb393239860c7dec70fd2973d"
],
"index": "pypi",
"version": "==3.1.1"
"version": "==1.22.1"
},
"pytest-metadata": {
"hashes": [
"sha256:39261ee0086f17649b180baf2a8633e1922a4c4b6fcc28a2de7d8127a82541bf",
"sha256:fcd2f416f15be295943527b3c8ba16a44ae5a7141939c90c3dc5ce9d167cf2a5"
"sha256:2071a59285de40d7541fde1eb9f1ddea1c9db165882df82781367471238b66ba",
"sha256:c29a1fb470424926c63154c1b632c02585f2ba4282932058a71d35295ff8c96d"
],
"index": "pypi",
"version": "==2.0.2"
"version": "==1.8.0"
},
"python-utils": {
"hashes": [
"sha256:3b1c8b706e40e91280eec5fa72ea730880a166cee99afa5555b863d55664478d",
"sha256:5cb9cf295018202fb4d6abdd694a33a7f08bc0ce1bf1eab8cce80ab2cde35c07"
"sha256:ebaadab29d0cb9dca0a82eab9c405f5be5125dbbff35b8f32cc433fa498dbaa7",
"sha256:f21fc09ff58ea5ebd1fd2e8ef7f63e39d456336900f26bdc9334a03a3f7d8089"
],
"markers": "python_version >= '3.7'",
"version": "==3.3.3"
"version": "==2.4.0"
},
"redo": {
"hashes": [
@ -423,49 +421,42 @@
},
"requests": {
"hashes": [
"sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983",
"sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"
"sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee",
"sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"
],
"index": "pypi",
"version": "==2.28.1"
"version": "==2.23.0"
},
"scandir": {
"hashes": [
"sha256:2586c94e907d99617887daed6c1d102b5ca28f1085f90446554abf1faf73123e",
"sha256:2ae41f43797ca0c11591c0c35f2f5875fa99f8797cb1a1fd440497ec0ae4b022",
"sha256:2b8e3888b11abb2217a32af0766bc06b65cc4a928d8727828ee68af5a967fa6f",
"sha256:2c712840c2e2ee8dfaf36034080108d30060d759c7b73a01a52251cc8989f11f",
"sha256:4d4631f6062e658e9007ab3149a9b914f3548cb38bfb021c64f39a025ce578ae",
"sha256:67f15b6f83e6507fdc6fca22fedf6ef8b334b399ca27c6b568cbfaa82a364173",
"sha256:7d2d7a06a252764061a020407b997dd036f7bd6a175a5ba2b345f0a357f0b3f4",
"sha256:8c5922863e44ffc00c5c693190648daa6d15e7c1207ed02d6f46a8dcc2869d32",
"sha256:92c85ac42f41ffdc35b6da57ed991575bdbe69db895507af88b9f499b701c188",
"sha256:b24086f2375c4a094a6b51e78b4cf7ca16c721dcee2eddd7aa6494b42d6d519d",
"sha256:cb925555f43060a1745d0a321cca94bcea927c50114b623d73179189a4e100ac"
],
"markers": "python_version < '3.5'",
"version": "==1.10.0"
},
"selenium": {
"hashes": [
"sha256:61c8b02788b66f08f2e61d5295afc956991e394815e33573072e68402ed4e8d5"
"sha256:2d7131d7bc5a5b99a2d9b04aaf2612c411b03b8ca1b1ee8d3de5845a9be2cb3c",
"sha256:deaf32b60ad91a4611b98d8002757f29e6f2c2d5fcaf202e1c9ad06d6772300d"
],
"markers": "python_version ~= '3.7'",
"version": "==4.4.0"
"version": "==3.141.0"
},
"six": {
"hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0"
},
"sniffio": {
"hashes": [
"sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663",
"sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"
],
"markers": "python_version >= '3.5'",
"version": "==1.2.0"
},
"sortedcontainers": {
"hashes": [
"sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88",
"sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"
],
"version": "==2.4.0"
},
"tomli": {
"hashes": [
"sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
"sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
],
"markers": "python_version >= '3.7'",
"version": "==2.0.1"
"version": "==1.15.0"
},
"treeherder-client": {
"hashes": [
@ -474,57 +465,54 @@
],
"version": "==5.0.0"
},
"trio": {
"hashes": [
"sha256:4dc0bf9d5cc78767fc4516325b6d80cc0968705a31d0eec2ecd7cdda466265b0",
"sha256:523f39b7b69eef73501cebfe1aafd400a9aad5b03543a0eded52952488ff1c13"
],
"markers": "python_version >= '3.7'",
"version": "==0.21.0"
},
"trio-websocket": {
"hashes": [
"sha256:5b558f6e83cc20a37c3b61202476c5295d1addf57bd65543364e0337e37ed2bc",
"sha256:a3d34de8fac26023eee701ed1e7bf4da9a8326b61a62934ec9e53b64970fd8fe"
],
"markers": "python_version >= '3.5'",
"version": "==0.9.2"
},
"urllib3": {
"extras": [
"secure",
"socks"
],
"hashes": [
"sha256:c33ccba33c819596124764c23a97d25f32b28433ba0dedeb77d873a38722c9bc",
"sha256:ea6e8fb210b19d950fab93b60c9009226c63a28808bc8386e05301e25883ac0a"
"sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2",
"sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' and python_version < '4.0'",
"version": "==1.26.11"
"version": "==1.25.11"
},
"wcwidth": {
"hashes": [
"sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784",
"sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"
],
"version": "==0.2.5"
},
"webob": {
"hashes": [
"sha256:73aae30359291c14fa3b956f8b5ca31960e420c28c1bec002547fb04928cf89b",
"sha256:b64ef5141be559cfade448f044fa45c2260351edcb6a8ef6b7e00c7dcef0c323"
"sha256:a3c89a8e9ba0aeb17382836cdb73c516d0ecf6630ec40ec28288f3ed459ce87b",
"sha256:aa3a917ed752ba3e0b242234b2a373f9c4e2a75d35291dcbe977649bd21fd108"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.8.7"
"version": "==1.8.6"
},
"wsproto": {
"zipp": {
"hashes": [
"sha256:2218cb57952d90b9fca325c0dcfb08c3bda93e8fd8070b0a17f048e2e47a521b",
"sha256:a2e56bfd5c7cd83c1369d83b5feccd6d37798b74872866e62616e0ecf111bda8"
"sha256:c70410551488251b0fee67b460fb9a536af8d6f9f008ad10ac51f615b6a521b1",
"sha256:e0d9e63797e483a30d27e09fffd308c59a700d365ec34e93cc100844168bf921"
],
"markers": "python_version >= '3.7'",
"version": "==1.1.0"
"version": "==1.2.0"
},
"zope.component": {
"hashes": [
"sha256:32cbe426ba8fa7b62ce5b211f80f0718a0c749cc7ff09e3f4b43a57f7ccdf5e5",
"sha256:e955eb9f1e55d30e2d8097c8baa9ee012c356887eef3b0d43e6bfcd4868221e5"
"sha256:607628e4c84f7887a69a958542b5c304663e726b73aba0882e3a3f059bff14f3",
"sha256:91628918218b3e6f6323de2a7b845e09ddc5cae131c034896c051b084bba3c92"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==5.0.1"
"version": "==4.6.2"
},
"zope.deferredimport": {
"hashes": [
"sha256:57b2345e7b5eef47efcd4f634ff16c93e4265de3dcf325afc7315ade48d909e1",
"sha256:9a0c211df44aa95f1c4e6d2626f90b400f56989180d3ef96032d708da3d23e0a"
],
"version": "==4.3.1"
},
"zope.deprecation": {
"hashes": [
"sha256:0d453338f04bacf91bbfba545d8bcdf529aa829e67b705eac8c1a7fdce66e2df",
"sha256:f1480b74995958b24ce37b0ef04d3663d2683e5d6debc96726eff18acf4ea113"
],
"version": "==4.4.0"
},
"zope.event": {
"hashes": [
@ -535,96 +523,150 @@
},
"zope.hookable": {
"hashes": [
"sha256:031e7672540685dc9d07565f2b968c6e21c7899c9391da58a23e63f229a8fdcd",
"sha256:14bac9afd00e9577227749b37dfc3b9fe4f4fb855923262fc016be47baa42712",
"sha256:16c0748438f716894cb61f3ed00adaa65359a5abe7a12bb44d7133d4b0cd3453",
"sha256:1da8d3386238983e97302b2cbdb510e126968e65e3cb8a8745da9744655001fc",
"sha256:24e4489ccf0dbd4c0e9d2d8b845b46994debb30cc22f96da76e973f9cb582799",
"sha256:3111fbc3ddae5d98655691ff81b1c71bd7ad0c3bcf2c2ef659fdc8e66f664603",
"sha256:34a84e15f2e6a3b2e372a67f7d845a372e3f0438319f26dfe9b7cb66ab75be44",
"sha256:35320d283a364c42dbf91694066bc1e7f07628bbd5ec87c1ae08143036e1de49",
"sha256:43855fbab9fb949fa14b5bbcf4c471e4d359428c2196061efe0d82fe3b387101",
"sha256:4711443b964bf7ace58780a3473f520151de8d441e57583b8d8cd8a231fb7656",
"sha256:49427208d9f65e5aa7df5c1be4dc818c51da34e261f4e52fe944a695ae90e3b3",
"sha256:4dbdfe522741effbb507d55354664c93c81db6db66ca124c981d1e3a41e5a31b",
"sha256:4dc9693fa28a238f063ba169110ef4199e0f86f9f976b57824c1d742eb21ad2e",
"sha256:64337672794b01d039e2380d11dd895ab17043530f27b5e3e0709a11fbe5b532",
"sha256:7067a450b15c8d41d00060890573ddc06f3414e62173dac55b38f6683920c20e",
"sha256:7091df7b4d6d897dd00e8717f0fa62b020e28aabe54a92005df22130ed204f6f",
"sha256:7b63de104e531109f606d4e3765b82fa3364e387d63b71a02460d321e24b33c8",
"sha256:7ef3128b5bcb97029c19df95126f57638afe6d2aca0ffede989149fa0bbd744a",
"sha256:800f93479202b05e46ba7696a2dd5411cfdd9d87c47a7d2b6fcda5394a5f9042",
"sha256:84dfb4f5189c8a3b70dfdf0d268840d5dce69048d4767120910f4665fa5ee2f3",
"sha256:8cf9982d43f6a732d041cf68b08fa969e5bcf090212ab519a637c8a393015eda",
"sha256:8fc3e6cd0486c6af48e3317c299def719b57538332a194e0b3bc6a772f4faa0e",
"sha256:a766186b97e493928dfac4a4b6c7508e47411e78c6f3be9846e8981eb91542d4",
"sha256:bfd1b1107a51ddfbd628c1ff884c6a67e92519b23012563b6082d438dbd16b9d",
"sha256:cbcbf6d31092caafb40ab26d07c065bf4f60f3ba7925d23d51a4e19469034544",
"sha256:cf27270212fa51005162d75cae83bb943c84ece7c7f8d30d68efebfad2f469d9",
"sha256:cf7f1f973aeced06ab1a245faa71e867cec6a053b807c2aad4c1728964aac071",
"sha256:de77a946ef020d08643647e417713ed753a2eed1f4495259c38a241c8eb31dbf",
"sha256:e3b01e7cf16b4a3257ee05e4c354737a4f64af302846826c46a296a7944b8da9",
"sha256:ff08276e555f2ef262fd03d872cca130e7ee376b87d7651a5595aae2fa5b2425"
"sha256:0194b9b9e7f614abba60c90b231908861036578297515d3d6508eb10190f266d",
"sha256:0c2977473918bdefc6fa8dfb311f154e7f13c6133957fe649704deca79b92093",
"sha256:17b8bdb3b77e03a152ca0d5ca185a7ae0156f5e5a2dbddf538676633a1f7380f",
"sha256:29d07681a78042cdd15b268ae9decffed9ace68a53eebeb61d65ae931d158841",
"sha256:36fb1b35d1150267cb0543a1ddd950c0bc2c75ed0e6e92e3aaa6ac2e29416cb7",
"sha256:3aed60c2bb5e812bbf9295c70f25b17ac37c233f30447a96c67913ba5073642f",
"sha256:3cac1565cc768911e72ca9ec4ddf5c5109e1fef0104f19f06649cf1874943b60",
"sha256:3d4bc0cc4a37c3cd3081063142eeb2125511db3c13f6dc932d899c512690378e",
"sha256:3f73096f27b8c28be53ffb6604f7b570fbbb82f273c6febe5f58119009b59898",
"sha256:522d1153d93f2d48aa0bd9fb778d8d4500be2e4dcf86c3150768f0e3adbbc4ef",
"sha256:523d2928fb7377bbdbc9af9c0b14ad73e6eaf226349f105733bdae27efd15b5a",
"sha256:5848309d4fc5c02150a45e8f8d2227e5bfda386a508bbd3160fed7c633c5a2fa",
"sha256:6781f86e6d54a110980a76e761eb54590630fd2af2a17d7edf02a079d2646c1d",
"sha256:6fd27921ebf3aaa945fa25d790f1f2046204f24dba4946f82f5f0a442577c3e9",
"sha256:70d581862863f6bf9e175e85c9d70c2d7155f53fb04dcdb2f73cf288ca559a53",
"sha256:81867c23b0dc66c8366f351d00923f2bc5902820a24c2534dfd7bf01a5879963",
"sha256:81db29edadcbb740cd2716c95a297893a546ed89db1bfe9110168732d7f0afdd",
"sha256:86bd12624068cea60860a0759af5e2c3adc89c12aef6f71cf12f577e28deefe3",
"sha256:9c184d8f9f7a76e1ced99855ccf390ffdd0ec3765e5cbf7b9cada600accc0a1e",
"sha256:acc789e8c29c13555e43fe4bf9fcd15a65512c9645e97bbaa5602e3201252b02",
"sha256:afaa740206b7660d4cc3b8f120426c85761f51379af7a5b05451f624ad12b0af",
"sha256:b5f5fa323f878bb16eae68ea1ba7f6c0419d4695d0248bed4b18f51d7ce5ab85",
"sha256:bd89e0e2c67bf4ac3aca2a19702b1a37269fb1923827f68324ac2e7afd6e3406",
"sha256:c212de743283ec0735db24ec6ad913758df3af1b7217550ff270038062afd6ae",
"sha256:ca553f524293a0bdea05e7f44c3e685e4b7b022cb37d87bc4a3efa0f86587a8d",
"sha256:cab67065a3db92f636128d3157cc5424a145f82d96fb47159c539132833a6d36",
"sha256:d3b3b3eedfdbf6b02898216e85aa6baf50207f4378a2a6803d6d47650cd37031",
"sha256:d9f4a5a72f40256b686d31c5c0b1fde503172307beb12c1568296e76118e402c",
"sha256:df5067d87aaa111ed5d050e1ee853ba284969497f91806efd42425f5348f1c06",
"sha256:e2587644812c6138f05b8a41594a8337c6790e3baf9a01915e52438c13fc6bef",
"sha256:e27fd877662db94f897f3fd532ef211ca4901eb1a70ba456f15c0866a985464a",
"sha256:e427ebbdd223c72e06ba94c004bb04e996c84dec8a0fa84e837556ae145c439e",
"sha256:e583ad4309c203ef75a09d43434cf9c2b4fa247997ecb0dcad769982c39411c7",
"sha256:e760b2bc8ece9200804f0c2b64d10147ecaf18455a2a90827fbec4c9d84f3ad5",
"sha256:ea9a9cc8bcc70e18023f30fa2f53d11ae069572a162791224e60cd65df55fb69",
"sha256:ecb3f17dce4803c1099bd21742cd126b59817a4e76a6544d31d2cca6e30dbffd",
"sha256:ed794e3b3de42486d30444fb60b5561e724ee8a2d1b17b0c2e0f81e3ddaf7a87",
"sha256:ee885d347279e38226d0a437b6a932f207f691c502ee565aba27a7022f1285df",
"sha256:fd5e7bc5f24f7e3d490698f7b854659a9851da2187414617cd5ed360af7efd63",
"sha256:fe45f6870f7588ac7b2763ff1ce98cce59369717afe70cc353ec5218bc854bcc"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==5.1.0"
"version": "==5.0.1"
},
"zope.interface": {
"hashes": [
"sha256:08f9636e99a9d5410181ba0729e0408d3d8748026ea938f3b970a0249daa8192",
"sha256:0b465ae0962d49c68aa9733ba92a001b2a0933c317780435f00be7ecb959c702",
"sha256:0cba8477e300d64a11a9789ed40ee8932b59f9ee05f85276dbb4b59acee5dd09",
"sha256:0cee5187b60ed26d56eb2960136288ce91bcf61e2a9405660d271d1f122a69a4",
"sha256:0ea1d73b7c9dcbc5080bb8aaffb776f1c68e807767069b9ccdd06f27a161914a",
"sha256:0f91b5b948686659a8e28b728ff5e74b1be6bf40cb04704453617e5f1e945ef3",
"sha256:15e7d1f7a6ee16572e21e3576d2012b2778cbacf75eb4b7400be37455f5ca8bf",
"sha256:17776ecd3a1fdd2b2cd5373e5ef8b307162f581c693575ec62e7c5399d80794c",
"sha256:194d0bcb1374ac3e1e023961610dc8f2c78a0f5f634d0c737691e215569e640d",
"sha256:1c0e316c9add0db48a5b703833881351444398b04111188069a26a61cfb4df78",
"sha256:205e40ccde0f37496904572035deea747390a8b7dc65146d30b96e2dd1359a83",
"sha256:273f158fabc5ea33cbc936da0ab3d4ba80ede5351babc4f577d768e057651531",
"sha256:2876246527c91e101184f63ccd1d716ec9c46519cc5f3d5375a3351c46467c46",
"sha256:2c98384b254b37ce50eddd55db8d381a5c53b4c10ee66e1e7fe749824f894021",
"sha256:2e5a26f16503be6c826abca904e45f1a44ff275fdb7e9d1b75c10671c26f8b94",
"sha256:334701327f37c47fa628fc8b8d28c7d7730ce7daaf4bda1efb741679c2b087fc",
"sha256:3748fac0d0f6a304e674955ab1365d515993b3a0a865e16a11ec9d86fb307f63",
"sha256:3c02411a3b62668200910090a0dff17c0b25aaa36145082a5a6adf08fa281e54",
"sha256:3dd4952748521205697bc2802e4afac5ed4b02909bb799ba1fe239f77fd4e117",
"sha256:3f24df7124c323fceb53ff6168da70dbfbae1442b4f3da439cd441681f54fe25",
"sha256:469e2407e0fe9880ac690a3666f03eb4c3c444411a5a5fddfdabc5d184a79f05",
"sha256:4de4bc9b6d35c5af65b454d3e9bc98c50eb3960d5a3762c9438df57427134b8e",
"sha256:5208ebd5152e040640518a77827bdfcc73773a15a33d6644015b763b9c9febc1",
"sha256:52de7fc6c21b419078008f697fd4103dbc763288b1406b4562554bd47514c004",
"sha256:5bb3489b4558e49ad2c5118137cfeaf59434f9737fa9c5deefc72d22c23822e2",
"sha256:5dba5f530fec3f0988d83b78cc591b58c0b6eb8431a85edd1569a0539a8a5a0e",
"sha256:5dd9ca406499444f4c8299f803d4a14edf7890ecc595c8b1c7115c2342cadc5f",
"sha256:5f931a1c21dfa7a9c573ec1f50a31135ccce84e32507c54e1ea404894c5eb96f",
"sha256:63b82bb63de7c821428d513607e84c6d97d58afd1fe2eb645030bdc185440120",
"sha256:66c0061c91b3b9cf542131148ef7ecbecb2690d48d1612ec386de9d36766058f",
"sha256:6f0c02cbb9691b7c91d5009108f975f8ffeab5dff8f26d62e21c493060eff2a1",
"sha256:71aace0c42d53abe6fc7f726c5d3b60d90f3c5c055a447950ad6ea9cec2e37d9",
"sha256:7d97a4306898b05404a0dcdc32d9709b7d8832c0c542b861d9a826301719794e",
"sha256:7df1e1c05304f26faa49fa752a8c690126cf98b40b91d54e6e9cc3b7d6ffe8b7",
"sha256:8270252effc60b9642b423189a2fe90eb6b59e87cbee54549db3f5562ff8d1b8",
"sha256:867a5ad16892bf20e6c4ea2aab1971f45645ff3102ad29bd84c86027fa99997b",
"sha256:877473e675fdcc113c138813a5dd440da0769a2d81f4d86614e5d62b69497155",
"sha256:8892f89999ffd992208754851e5a052f6b5db70a1e3f7d54b17c5211e37a98c7",
"sha256:9a9845c4c6bb56e508651f005c4aeb0404e518c6f000d5a1123ab077ab769f5c",
"sha256:a1e6e96217a0f72e2b8629e271e1b280c6fa3fe6e59fa8f6701bec14e3354325",
"sha256:a8156e6a7f5e2a0ff0c5b21d6bcb45145efece1909efcbbbf48c56f8da68221d",
"sha256:a9506a7e80bcf6eacfff7f804c0ad5350c8c95b9010e4356a4b36f5322f09abb",
"sha256:af310ec8335016b5e52cae60cda4a4f2a60a788cbb949a4fbea13d441aa5a09e",
"sha256:b0297b1e05fd128d26cc2460c810d42e205d16d76799526dfa8c8ccd50e74959",
"sha256:bf68f4b2b6683e52bec69273562df15af352e5ed25d1b6641e7efddc5951d1a7",
"sha256:d0c1bc2fa9a7285719e5678584f6b92572a5b639d0e471bb8d4b650a1a910920",
"sha256:d4d9d6c1a455d4babd320203b918ccc7fcbefe308615c521062bc2ba1aa4d26e",
"sha256:db1fa631737dab9fa0b37f3979d8d2631e348c3b4e8325d6873c2541d0ae5a48",
"sha256:dd93ea5c0c7f3e25335ab7d22a507b1dc43976e1345508f845efc573d3d779d8",
"sha256:f44e517131a98f7a76696a7b21b164bcb85291cee106a23beccce454e1f433a4",
"sha256:f7ee479e96f7ee350db1cf24afa5685a5899e2b34992fb99e1f7c1b0b758d263"
"sha256:05a97ba92c1c7c26f25c9f671aa1ef85ffead6cdad13770e5b689cf983adc7e1",
"sha256:07d61722dd7d85547b7c6b0f5486b4338001fab349f2ac5cabc0b7182eb3425d",
"sha256:0a990dcc97806e5980bbb54b2e46b9cde9e48932d8e6984daf71ef1745516123",
"sha256:150e8bcb7253a34a4535aeea3de36c0bb3b1a6a47a183a95d65a194b3e07f232",
"sha256:1743bcfe45af8846b775086471c28258f4c6e9ee8ef37484de4495f15a98b549",
"sha256:1b5f6c8fff4ed32aa2dd43e84061bc8346f32d3ba6ad6e58f088fe109608f102",
"sha256:21e49123f375703cf824214939d39df0af62c47d122d955b2a8d9153ea08cfd5",
"sha256:21f579134a47083ffb5ddd1307f0405c91aa8b61ad4be6fd5af0171474fe0c45",
"sha256:27c267dc38a0f0079e96a2945ee65786d38ef111e413c702fbaaacbab6361d00",
"sha256:299bde0ab9e5c4a92f01a152b7fbabb460f31343f1416f9b7b983167ab1e33bc",
"sha256:2ab88d8f228f803fcb8cb7d222c579d13dab2d3622c51e8cf321280da01102a7",
"sha256:2ced4c35061eea623bc84c7711eedce8ecc3c2c51cd9c6afa6290df3bae9e104",
"sha256:2dcab01c660983ba5e5a612e0c935141ccbee67d2e2e14b833e01c2354bd8034",
"sha256:32546af61a9a9b141ca38d971aa6eb9800450fa6620ce6323cc30eec447861f3",
"sha256:32b40a4c46d199827d79c86bb8cb88b1bbb764f127876f2cb6f3a47f63dbada3",
"sha256:3cc94c69f6bd48ed86e8e24f358cb75095c8129827df1298518ab860115269a4",
"sha256:42b278ac0989d6f5cf58d7e0828ea6b5951464e3cf2ff229dd09a96cb6ba0c86",
"sha256:495b63fd0302f282ee6c1e6ea0f1c12cb3d1a49c8292d27287f01845ff252a96",
"sha256:4af87cdc0d4b14e600e6d3d09793dce3b7171348a094ba818e2a68ae7ee67546",
"sha256:4b94df9f2fdde7b9314321bab8448e6ad5a23b80542dcab53e329527d4099dcb",
"sha256:4c48ddb63e2b20fba4c6a2bf81b4d49e99b6d4587fb67a6cd33a2c1f003af3e3",
"sha256:4df9afd17bd5477e9f8c8b6bb8507e18dd0f8b4efe73bb99729ff203279e9e3b",
"sha256:518950fe6a5d56f94ba125107895f938a4f34f704c658986eae8255edb41163b",
"sha256:538298e4e113ccb8b41658d5a4b605bebe75e46a30ceca22a5a289cf02c80bec",
"sha256:55465121e72e208a7b69b53de791402affe6165083b2ea71b892728bd19ba9ae",
"sha256:588384d70a0f19b47409cfdb10e0c27c20e4293b74fc891df3d8eb47782b8b3e",
"sha256:6278c080d4afffc9016e14325f8734456831124e8c12caa754fd544435c08386",
"sha256:64ea6c221aeee4796860405e1aedec63424cda4202a7ad27a5066876db5b0fd2",
"sha256:681dbb33e2b40262b33fd383bae63c36d33fd79fa1a8e4092945430744ffd34a",
"sha256:6936aa9da390402d646a32a6a38d5409c2d2afb2950f045a7d02ab25a4e7d08d",
"sha256:778d0ec38bbd288b150a3ae363c8ffd88d2207a756842495e9bffd8a8afbc89a",
"sha256:8251f06a77985a2729a8bdbefbae79ee78567dddc3acbd499b87e705ca59fe24",
"sha256:83b4aa5344cce005a9cff5d0321b2e318e871cc1dfc793b66c32dd4f59e9770d",
"sha256:844fad925ac5c2ad4faaceb3b2520ad016b5280105c6e16e79838cf951903a7b",
"sha256:8ceb3667dd13b8133f2e4d637b5b00f240f066448e2aa89a41f4c2d78a26ce50",
"sha256:92dc0fb79675882d0b6138be4bf0cec7ea7c7eede60aaca78303d8e8dbdaa523",
"sha256:9789bd945e9f5bd026ed3f5b453d640befb8b1fc33a779c1fe8d3eb21fe3fb4a",
"sha256:a2b6d6eb693bc2fc6c484f2e5d93bd0b0da803fa77bf974f160533e555e4d095",
"sha256:aab9f1e34d810feb00bf841993552b8fcc6ae71d473c505381627143d0018a6a",
"sha256:abb61afd84f23099ac6099d804cdba9bd3b902aaaded3ffff47e490b0a495520",
"sha256:adf9ee115ae8ff8b6da4b854b4152f253b390ba64407a22d75456fe07dcbda65",
"sha256:aedc6c672b351afe6dfe17ff83ee5e7eb6ed44718f879a9328a68bdb20b57e11",
"sha256:b7a00ecb1434f8183395fac5366a21ee73d14900082ca37cf74993cf46baa56c",
"sha256:ba32f4a91c1cb7314c429b03afbf87b1fff4fb1c8db32260e7310104bd77f0c7",
"sha256:cbd0f2cbd8689861209cd89141371d3a22a11613304d1f0736492590aa0ab332",
"sha256:e4bc372b953bf6cec65a8d48482ba574f6e051621d157cf224227dbb55486b1e",
"sha256:eccac3d9aadc68e994b6d228cb0c8919fc47a5350d85a1b4d3d81d1e98baf40c",
"sha256:efd550b3da28195746bb43bd1d815058181a7ca6d9d6aa89dd37f5eefe2cacb7",
"sha256:efef581c8ba4d990770875e1a2218e856849d32ada2680e53aebc5d154a17e20",
"sha256:f057897711a630a0b7a6a03f1acf379b6ba25d37dc5dc217a97191984ba7f2fc",
"sha256:f37d45fab14ffef9d33a0dc3bc59ce0c5313e2253323312d47739192da94f5fd",
"sha256:f44906f70205d456d503105023041f1e63aece7623b31c390a0103db4de17537"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==5.4.0"
"version": "==5.2.0"
},
"zope.proxy": {
"hashes": [
"sha256:00573dfa755d0703ab84bb23cb6ecf97bb683c34b340d4df76651f97b0bab068",
"sha256:092049280f2848d2ba1b57b71fe04881762a220a97b65288bcb0968bb199ec30",
"sha256:0cbd27b4d3718b5ec74fc65ffa53c78d34c65c6fd9411b8352d2a4f855220cf1",
"sha256:17fc7e16d0c81f833a138818a30f366696653d521febc8e892858041c4d88785",
"sha256:19577dfeb70e8a67249ba92c8ad20589a1a2d86a8d693647fa8385408a4c17b0",
"sha256:207aa914576b1181597a1516e1b90599dc690c095343ae281b0772e44945e6a4",
"sha256:219a7db5ed53e523eb4a4769f13105118b6d5b04ed169a283c9775af221e231f",
"sha256:2b50ea79849e46b5f4f2b0247a3687505d32d161eeb16a75f6f7e6cd81936e43",
"sha256:5903d38362b6c716e66bbe470f190579c530a5baf03dbc8500e5c2357aa569a5",
"sha256:5c24903675e271bd688c6e9e7df5775ac6b168feb87dbe0e4bcc90805f21b28f",
"sha256:5ef6bc5ed98139e084f4e91100f2b098a0cd3493d4e76f9d6b3f7b95d7ad0f06",
"sha256:61b55ae3c23a126a788b33ffb18f37d6668e79a05e756588d9e4d4be7246ab1c",
"sha256:63ddb992931a5e616c87d3d89f5a58db086e617548005c7f9059fac68c03a5cc",
"sha256:6943da9c09870490dcfd50c4909c0cc19f434fa6948f61282dc9cb07bcf08160",
"sha256:6ad40f85c1207803d581d5d75e9ea25327cd524925699a83dfc03bf8e4ba72b7",
"sha256:6b44433a79bdd7af0e3337bd7bbcf53dd1f9b0fa66bf21bcb756060ce32a96c1",
"sha256:6bbaa245015d933a4172395baad7874373f162955d73612f0b66b6c2c33b6366",
"sha256:7007227f4ea85b40a2f5e5a244479f6a6dfcf906db9b55e812a814a8f0e2c28d",
"sha256:74884a0aec1f1609190ec8b34b5d58fb3b5353cf22b96161e13e0e835f13518f",
"sha256:7d25fe5571ddb16369054f54cdd883f23de9941476d97f2b92eb6d7d83afe22d",
"sha256:7e162bdc5e3baad26b2262240be7d2bab36991d85a6a556e48b9dfb402370261",
"sha256:814d62678dc3a30f4aa081982d830b7c342cf230ffc9d030b020cb154eeebf9e",
"sha256:8878a34c5313ee52e20aa50b03138af8d472bae465710fb954d133a9bfd3c38d",
"sha256:a66a0d94e5b081d5d695e66d6667e91e74d79e273eee95c1747717ba9cb70792",
"sha256:a69f5cbf4addcfdf03dda564a671040127a6b7c34cf9fe4973582e68441b63fa",
"sha256:b00f9f0c334d07709d3f73a7cb8ae63c6ca1a90c790a63b5e7effa666ef96021",
"sha256:b6ed71e4a7b4690447b626f499d978aa13197a0e592950e5d7020308f6054698",
"sha256:bdf5041e5851526e885af579d2f455348dba68d74f14a32781933569a327fddf",
"sha256:be034360dd34e62608419f86e799c97d389c10a0e677a25f236a971b2f40dac9",
"sha256:cc8f590a5eed30b314ae6b0232d925519ade433f663de79cc3783e4b10d662ba",
"sha256:cd7a318a15fe6cc4584bf3c4426f092ed08c0fd012cf2a9173114234fe193e11",
"sha256:cf19b5f63a59c20306e034e691402b02055c8f4e38bf6792c23cad489162a642",
"sha256:cfc781ce442ec407c841e9aa51d0e1024f72b6ec34caa8fdb6ef9576d549acf2",
"sha256:dea9f6f8633571e18bc20cad83603072e697103a567f4b0738d52dd0211b4527",
"sha256:e4a86a1d5eb2cce83c5972b3930c7c1eac81ab3508464345e2b8e54f119d5505",
"sha256:e7106374d4a74ed9ff00c46cc00f0a9f06a0775f8868e423f85d4464d2333679",
"sha256:e98a8a585b5668aa9e34d10f7785abf9545fe72663b4bfc16c99a115185ae6a5",
"sha256:f64840e68483316eb58d82c376ad3585ca995e69e33b230436de0cdddf7363f9",
"sha256:f8f4b0a9e6683e43889852130595c8854d8ae237f2324a053cdd884de936aa9b",
"sha256:fc45a53219ed30a7f670a6d8c98527af0020e6fd4ee4c0a8fb59f147f06d816c"
],
"version": "==4.3.5"
}
},
"develop": {}

View File

@ -34,7 +34,7 @@ import org.mozilla.fenix.ui.robots.settingsSubMenuLoginsAndPassword
@Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
class SyncIntegrationTest {
private lateinit var mDevice: UiDevice
val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private lateinit var mockWebServer: MockWebServer
@get:Rule
@ -42,7 +42,6 @@ class SyncIntegrationTest {
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -177,7 +176,7 @@ class SyncIntegrationTest {
val emailInput = mDevice.findObject(
UiSelector()
.instance(0)
.className(EditText::class.java),
.className(EditText::class.java)
)
emailInput.waitForExists(TestAssetHelper.waitingTime)
@ -194,7 +193,7 @@ class SyncIntegrationTest {
val passwordInput = mDevice.findObject(
UiSelector()
.instance(0)
.className(EditText::class.java),
.className(EditText::class.java)
)
val passwordValue = javaClass.classLoader!!.getResource("password.txt").readText()

View File

@ -11,8 +11,8 @@ import mozversion
import pytest
import requests
from .tps import TPS
from .gradlewbuild import GradlewBuild
from tps import TPS
from gradlewbuild import GradlewBuild
here = os.path.dirname(__file__)

View File

@ -2,7 +2,7 @@ import logging
import os
import subprocess
from .adbrun import ADBrun
from adbrun import ADBrun
here = os.path.dirname(__file__)
logging.getLogger(__name__).addHandler(logging.NullHandler())
@ -40,4 +40,4 @@ class GradlewBuild(object):
os.chdir(testsPath)
with open(self.log, 'w') as f:
f.write(str(out))
f.write(out)

View File

@ -5,9 +5,8 @@
package org.mozilla.fenix.ui
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.espresso.IdlingRegistry
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.uiautomator.UiDevice
import kotlinx.coroutines.runBlocking
import mozilla.appservices.places.BookmarkRoot
import okhttp3.mockwebserver.MockWebServer
@ -18,17 +17,17 @@ import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.bookmarkStorage
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.ui.robots.bookmarksMenu
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.mDevice
import org.mozilla.fenix.ui.robots.multipleSelectionToolbar
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -39,15 +38,15 @@ class BookmarksTest {
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
private lateinit var mockWebServer: MockWebServer
private lateinit var mDevice: UiDevice
private val bookmarksFolderName = "New Folder"
private val testBookmark = object {
var title: String = "Bookmark title"
var url: String = "https://www.test.com"
}
private var bookmarksListIdlingResource: RecyclerViewIdlingResource? = null
@get:Rule
val activityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides()
val activityTestRule = HomeActivityTestRule()
@Rule
@JvmField
@ -55,11 +54,12 @@ class BookmarksTest {
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
val settings = activityTestRule.activity.settings()
settings.shouldShowJumpBackInCFR = false
}
@After
@ -71,6 +71,10 @@ class BookmarksTest {
val bookmarks = bookmarksStorage?.getTree(BookmarkRoot.Mobile.id)?.children
bookmarks?.forEach { bookmarksStorage.deleteNode(it.guid) }
}
if (bookmarksListIdlingResource != null) {
IdlingRegistry.getInstance().unregister(bookmarksListIdlingResource!!)
}
}
@Test
@ -78,14 +82,17 @@ class BookmarksTest {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 1),
) {
verifyBookmarksMenuView()
verifyAddFolderButton()
verifyCloseButton()
verifyBookmarkTitle("Desktop Bookmarks")
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(
activityTestRule.activity.findViewById(R.id.bookmark_list),
1
)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
verifyBookmarksMenuView()
verifyAddFolderButton()
verifyCloseButton()
verifyBookmarkTitle("Desktop Bookmarks")
}
}
@ -94,15 +101,15 @@ class BookmarksTest {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 1),
) {
selectFolder("Desktop Bookmarks")
verifyFolderTitle("Bookmarks Menu")
verifyFolderTitle("Bookmarks Toolbar")
verifyFolderTitle("Other Bookmarks")
verifySyncSignInButton()
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 1)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
selectFolder("Desktop Bookmarks")
verifyFolderTitle("Bookmarks Menu")
verifyFolderTitle("Bookmarks Toolbar")
verifyFolderTitle("Other Bookmarks")
verifySignInToSyncButton()
}.clickSingInToSyncButton {
verifyTurnOnSyncToolbarTitle()
}
@ -129,12 +136,12 @@ class BookmarksTest {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {
verifyBookmarkedURL(defaultWebPage.url.toString())
verifyBookmarkFavicon(defaultWebPage.url)
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
verifyBookmarkedURL(defaultWebPage.url.toString())
verifyBookmarkFavicon(defaultWebPage.url)
}
}
@ -143,16 +150,16 @@ class BookmarksTest {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 1),
) {
clickAddFolderButton()
verifyKeyboardVisible()
addNewFolderName(bookmarksFolderName)
saveNewFolder()
verifyFolderTitle(bookmarksFolderName)
verifyKeyboardHidden()
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 1)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
clickAddFolderButton()
verifyKeyboardVisible()
addNewFolderName(bookmarksFolderName)
saveNewFolder()
verifyFolderTitle(bookmarksFolderName)
verifyKeyboardHidden()
}
}
@ -178,9 +185,9 @@ class BookmarksTest {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
}.openThreeDotMenu(defaultWebPage.url) {
}.clickEdit {
verifyEditBookmarksView()
@ -204,9 +211,9 @@ class BookmarksTest {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
}.openThreeDotMenu(defaultWebPage.url) {
}.clickCopy {
verifyCopySnackBarText()
@ -218,7 +225,7 @@ class BookmarksTest {
clickClearButton()
longClickToolbar()
clickPasteText()
verifyTypedToolbarText(defaultWebPage.url.toString())
verifyPastedToolbarText(defaultWebPage.url.toString())
}
}
@ -230,9 +237,9 @@ class BookmarksTest {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
}.openThreeDotMenu(defaultWebPage.url) {
}.clickShare {
verifyShareOverlay()
@ -250,9 +257,9 @@ class BookmarksTest {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
}.openThreeDotMenu(defaultWebPage.url) {
}.clickOpenInNewTab {
verifyTabTrayIsOpened()
@ -260,83 +267,6 @@ class BookmarksTest {
}
}
@Test
fun openAllInTabsTest() {
val webPages = listOf(
TestAssetHelper.getGenericAsset(mockWebServer, 1),
TestAssetHelper.getGenericAsset(mockWebServer, 2),
TestAssetHelper.getGenericAsset(mockWebServer, 3),
TestAssetHelper.getGenericAsset(mockWebServer, 4),
)
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
createFolder("root")
createFolder("sub", "root")
createFolder("empty", "root")
}.closeMenu {
}
browserScreen {
createBookmark(webPages[0].url)
createBookmark(webPages[1].url, "root")
createBookmark(webPages[2].url, "root")
createBookmark(webPages[3].url, "sub")
}.openTabDrawer {
closeTab()
}
browserScreen {
}.openThreeDotMenu {
}.openBookmarks {
}.openThreeDotMenu("root") {
}.clickOpenAllInTabs {
verifyTabTrayIsOpened()
verifyNormalModeSelected()
verifyExistingOpenTabs("Test_Page_2", "Test_Page_3", "Test_Page_4")
// Bookmark that is not under the root folder should not be opened
verifyNoExistingOpenTabs("Test_Page_1")
}
}
@Test
fun openAllInPrivateTabsTest() {
val webPages = listOf(
TestAssetHelper.getGenericAsset(mockWebServer, 1),
TestAssetHelper.getGenericAsset(mockWebServer, 2),
)
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
createFolder("root")
createFolder("sub", "root")
createFolder("empty", "root")
}.closeMenu {
}
browserScreen {
createBookmark(webPages[0].url, "root")
createBookmark(webPages[1].url, "sub")
}.openTabDrawer {
closeTab()
}
browserScreen {
}.openThreeDotMenu {
}.openBookmarks {
}.openThreeDotMenu("root") {
}.clickOpenAllInPrivateTabs {
verifyTabTrayIsOpened()
verifyPrivateModeSelected()
verifyExistingOpenTabs("Test_Page_1", "Test_Page_2")
}
}
@Test
fun openBookmarkInPrivateTabTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -345,9 +275,9 @@ class BookmarksTest {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
}.openThreeDotMenu(defaultWebPage.url) {
}.clickOpenInPrivateTab {
verifyTabTrayIsOpened()
@ -364,10 +294,11 @@ class BookmarksTest {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
}.openThreeDotMenu(defaultWebPage.url) {
IdlingRegistry.getInstance().unregister(bookmarksListIdlingResource!!)
}.clickDelete {
verifyDeleteSnackBarText()
verifyUndoDeleteSnackBarButton()
@ -383,19 +314,19 @@ class BookmarksTest {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
}.openThreeDotMenu(defaultWebPage.url) {
IdlingRegistry.getInstance().unregister(bookmarksListIdlingResource!!)
}.clickDelete {
verifyUndoDeleteSnackBarButton()
clickUndoDeleteButton()
verifySnackBarHidden()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {
verifyBookmarkedURL(defaultWebPage.url.toString())
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
verifyBookmarkedURL(defaultWebPage.url.toString())
}
}
@ -408,11 +339,11 @@ class BookmarksTest {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {
longTapSelectItem(defaultWebPage.url)
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
longTapSelectItem(defaultWebPage.url)
}
multipleSelectionToolbar {
@ -428,6 +359,8 @@ class BookmarksTest {
@SmokeTest
@Test
fun openSelectionInNewTabTest() {
val settings = activityTestRule.activity.applicationContext.settings()
settings.shouldShowJumpBackInCFR = false
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
browserScreen {
@ -439,12 +372,12 @@ class BookmarksTest {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {
longTapSelectItem(defaultWebPage.url)
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
longTapSelectItem(defaultWebPage.url)
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
}
multipleSelectionToolbar {
@ -463,12 +396,12 @@ class BookmarksTest {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {
longTapSelectItem(defaultWebPage.url)
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
longTapSelectItem(defaultWebPage.url)
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
}
multipleSelectionToolbar {
@ -489,12 +422,13 @@ class BookmarksTest {
createBookmark(secondWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 3),
) {
longTapSelectItem(firstWebPage.url)
longTapSelectItem(secondWebPage.url)
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 3)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
longTapSelectItem(firstWebPage.url)
longTapSelectItem(secondWebPage.url)
IdlingRegistry.getInstance().unregister(bookmarksListIdlingResource!!)
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
}
@ -518,12 +452,13 @@ class BookmarksTest {
createBookmark(secondWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 3),
) {
longTapSelectItem(firstWebPage.url)
longTapSelectItem(secondWebPage.url)
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 3)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
longTapSelectItem(firstWebPage.url)
longTapSelectItem(secondWebPage.url)
IdlingRegistry.getInstance().unregister(bookmarksListIdlingResource!!)
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
}
@ -547,11 +482,11 @@ class BookmarksTest {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {
longTapSelectItem(defaultWebPage.url)
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
longTapSelectItem(defaultWebPage.url)
}
multipleSelectionToolbar {
@ -585,8 +520,6 @@ class BookmarksTest {
confirmDeletion()
verifyDeleteSnackBarText()
verifyFolderTitle("3")
// On some devices we need to wait for the Snackbar to be gone before continuing
TestHelper.waitUntilSnackbarGone()
}.closeMenu {
}
@ -606,19 +539,27 @@ class BookmarksTest {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {
createFolder(bookmarksFolderName)
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
createFolder(bookmarksFolderName)
IdlingRegistry.getInstance().unregister(bookmarksListIdlingResource!!)
}.openThreeDotMenu(defaultWebPage.title) {
}.clickEdit {
clickParentFolderSelector()
selectFolder(bookmarksFolderName)
navigateUp()
saveEditBookmark()
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
selectFolder(bookmarksFolderName)
verifyBookmarkedURL(defaultWebPage.url.toString())
IdlingRegistry.getInstance().unregister(bookmarksListIdlingResource!!)
}
}
@ -650,12 +591,12 @@ class BookmarksTest {
homeScreen {
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list)),
) {
longTapDesktopFolder("Desktop Bookmarks")
verifySelectDefaultFolderSnackBarText()
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list))
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
longTapDesktopFolder("Desktop Bookmarks")
verifySelectDefaultFolderSnackBarText()
}
}
@ -677,10 +618,11 @@ class BookmarksTest {
createBookmark(defaultWebPage.url)
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2),
) {}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 2)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
}.openThreeDotMenu(defaultWebPage.url) {
IdlingRegistry.getInstance().unregister(bookmarksListIdlingResource!!)
}.clickEdit {
clickDeleteInEditModeButton()
cancelDeletion()
@ -694,15 +636,16 @@ class BookmarksTest {
@SmokeTest
@Test
fun undoDeleteBookmarkFolderTest() {
browserScreen {
}.openThreeDotMenu {
}.openBookmarks {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 1),
) {
createFolder("My Folder")
verifyFolderTitle("My Folder")
}
bookmarksListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list), 1)
IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!)
createFolder("My Folder")
verifyFolderTitle("My Folder")
IdlingRegistry.getInstance().unregister(bookmarksListIdlingResource!!)
}.openThreeDotMenu("My Folder") {
}.clickDelete {
cancelFolderDeletion()

View File

@ -5,10 +5,13 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestHelper.getStringResource
@ -23,14 +26,26 @@ class BrowsingErrorPagesTest {
private val unwantedSoftwareWarning =
getStringResource(R.string.mozac_browser_errorpages_safe_browsing_unwanted_uri_title)
private val harmfulSiteWarning = getStringResource(R.string.mozac_browser_errorpages_safe_harmful_uri_title)
private val featureSettingsHelper = FeatureSettingsHelper()
@get: Rule
val mActivityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides()
val mActivityTestRule = HomeActivityTestRule()
@Rule
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
// disabling the jump-back-in pop-up that interferes with the tests.
featureSettingsHelper.setJumpBackCFREnabled(false)
}
@After
fun tearDown() {
featureSettingsHelper.resetAllFeatureFlags()
}
@SmokeTest
@Test
fun blockMalwarePageTest() {

View File

@ -10,11 +10,11 @@ import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.ui.robots.browserScreen
@ -29,29 +29,28 @@ import org.mozilla.fenix.ui.robots.tabDrawer
*/
class CollectionTest {
private lateinit var mDevice: UiDevice
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private lateinit var mockWebServer: MockWebServer
private val firstCollectionName = "testcollection_1"
private val secondCollectionName = "testcollection_2"
private val collectionName = "First Collection"
private val featureSettingsHelper = FeatureSettingsHelper()
@get:Rule
val composeTestRule =
AndroidComposeTestRule(
HomeActivityIntentTestRule(
isHomeOnboardingDialogEnabled = false,
isJumpBackInCFREnabled = false,
isRecentTabsFeatureEnabled = false,
isRecentlyVisitedFeatureEnabled = false,
isPocketEnabled = false,
isWallpaperOnboardingEnabled = false,
isTCPCFREnabled = false,
),
) { it.activity }
val composeTestRule = AndroidComposeTestRule(
HomeActivityIntentTestRule(),
{ it.activity }
)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
// disabling these features to have better visibility of Collections,
// and to avoid multiple matches on tab items
featureSettingsHelper.setRecentTabsFeatureEnabled(false)
featureSettingsHelper.setPocketEnabled(false)
featureSettingsHelper.setJumpBackCFREnabled(false)
featureSettingsHelper.setRecentlyVisitedFeatureEnabled(false)
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -61,6 +60,9 @@ class CollectionTest {
@After
fun tearDown() {
mockWebServer.shutdown()
// resetting modified features enabled setting to default
featureSettingsHelper.resetAllFeatureFlags()
}
@SmokeTest
@ -77,6 +79,7 @@ class CollectionTest {
}.submitQuery(secondWebPage.url.toString()) {
mDevice.waitForIdle()
}.goToHomescreen {
swipeToBottom()
}.clickSaveTabsToCollectionButton {
longClickTab(firstWebPage.title)
selectTab(secondWebPage.title, numOfTabs = 2)
@ -160,7 +163,7 @@ class CollectionTest {
createCollection(
firstTestPage.title,
secondTestPage.title,
collectionName = collectionName,
collectionName = collectionName
)
closeTab()
}
@ -201,10 +204,10 @@ class CollectionTest {
}
}
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@SmokeTest
@Test
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
fun deleteCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
@ -227,8 +230,8 @@ class CollectionTest {
}
}
// open a webpage, and add currently opened tab to existing collection
@Test
// open a webpage, and add currently opened tab to existing collection
fun mainMenuSaveToExistingCollection() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
val secondWebPage = getGenericAsset(mockWebServer, 2)
@ -310,9 +313,8 @@ class CollectionTest {
createCollection(webPage.title, collectionName = firstCollectionName)
verifySnackBarText("Collection saved!")
createCollection(
webPage.title,
collectionName = secondCollectionName,
firstCollection = false,
webPage.title, collectionName = secondCollectionName,
firstCollection = false
)
verifySnackBarText("Collection saved!")
}.closeTabDrawer {
@ -354,7 +356,7 @@ class CollectionTest {
}.openTabDrawer {
createCollection(
testPage.title,
collectionName = collectionName,
collectionName = collectionName
)
closeTab()
}
@ -380,7 +382,7 @@ class CollectionTest {
}.openTabDrawer {
createCollection(
testPage.title,
collectionName = collectionName,
collectionName = collectionName
)
closeTab()
}
@ -397,7 +399,6 @@ class CollectionTest {
}
@Test
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
fun selectTabOnLongTapTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
val secondWebPage = getGenericAsset(mockWebServer, 2)
@ -429,7 +430,6 @@ class CollectionTest {
}
@Test
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
fun navigateBackInCollectionFlowTest() {
val webPage = getGenericAsset(mockWebServer, 1)
@ -463,7 +463,6 @@ class CollectionTest {
@SmokeTest
@Test
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
fun undoDeleteCollectionTest() {
val webPage = getGenericAsset(mockWebServer, 1)
@ -482,7 +481,7 @@ class CollectionTest {
homeScreen {
verifySnackBarText("Collection deleted")
clickUndoSnackBarButton()
clickUndoCollectionDeletion("UNDO")
verifyCollectionIsDisplayed(collectionName, true)
}
}

View File

@ -9,6 +9,7 @@ import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
@ -36,11 +37,11 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
*/
class ContextMenusTest {
private lateinit var mDevice: UiDevice
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private lateinit var mockWebServer: MockWebServer
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
val activityIntentTestRule = HomeActivityIntentTestRule()
@Rule
@JvmField
@ -49,7 +50,6 @@ class ContextMenusTest {
@Before
fun setUp() {
activityIntentTestRule.activity.applicationContext.settings().shouldShowJumpBackInCFR = false
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -72,7 +72,7 @@ class ContextMenusTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(pageLinks.url) {
mDevice.waitForIdle()
longClickLink("Link 1")
longClickMatchingText("Link 1")
verifyLinkContextMenuItems(genericURL.url)
clickContextOpenLinkInNewTab()
verifySnackBarText("New tab opened")
@ -96,7 +96,7 @@ class ContextMenusTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(pageLinks.url) {
mDevice.waitForIdle()
longClickLink("Link 2")
longClickMatchingText("Link 2")
verifyLinkContextMenuItems(genericURL.url)
clickContextOpenLinkInPrivateTab()
verifySnackBarText("New private tab opened")
@ -118,23 +118,6 @@ class ContextMenusTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(pageLinks.url) {
mDevice.waitForIdle()
longClickLink("Link 3")
verifyLinkContextMenuItems(genericURL.url)
clickContextCopyLink()
verifySnackBarText("Link copied to clipboard")
}.openNavigationToolbar {
}.visitLinkFromClipboard {
verifyUrl(genericURL.url.toString())
}
}
@Test
fun verifyContextCopyLinkNotDisplayedAfterApplied() {
val pageLinks = TestAssetHelper.getGenericAsset(mockWebServer, 4)
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 3)
navigationToolbar {
}.enterURLAndEnterToBrowser(pageLinks.url) {
longClickMatchingText("Link 3")
verifyLinkContextMenuItems(genericURL.url)
clickContextCopyLink()
@ -142,11 +125,6 @@ class ContextMenusTest {
}.openNavigationToolbar {
}.visitLinkFromClipboard {
verifyUrl(genericURL.url.toString())
}.openTabDrawer {
}.openNewTab {
}
navigationToolbar {
verifyClipboardSuggestionsAreDisplayed(shouldBeDisplayed = false)
}
}
@ -160,7 +138,7 @@ class ContextMenusTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(pageLinks.url) {
mDevice.waitForIdle()
longClickLink("Link 1")
longClickMatchingText("Link 1")
verifyLinkContextMenuItems(genericURL.url)
clickContextShareLink(genericURL.url) // verify share intent is matched with associated URL
}
@ -176,7 +154,7 @@ class ContextMenusTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(pageLinks.url) {
mDevice.waitForIdle()
longClickLink("test_link_image")
longClickMatchingText("test_link_image")
verifyLinkImageContextMenuItems(imageResource.url)
clickContextOpenImageNewTab()
verifySnackBarText("New tab opened")
@ -195,7 +173,7 @@ class ContextMenusTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(pageLinks.url) {
mDevice.waitForIdle()
longClickLink("test_link_image")
longClickMatchingText("test_link_image")
verifyLinkImageContextMenuItems(imageResource.url)
clickContextCopyImageLocation()
verifySnackBarText("Link copied to clipboard")
@ -215,7 +193,7 @@ class ContextMenusTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(pageLinks.url) {
mDevice.waitForIdle()
longClickLink("test_link_image")
longClickMatchingText("test_link_image")
verifyLinkImageContextMenuItems(imageResource.url)
clickContextSaveImage()
}
@ -228,6 +206,7 @@ class ContextMenusTest {
}
}
@Ignore("Failing with frequent ANR: https://bugzilla.mozilla.org/show_bug.cgi?id=1764605")
@Test
fun verifyContextMixedVariations() {
val pageLinks =
@ -240,13 +219,13 @@ class ContextMenusTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(pageLinks.url) {
mDevice.waitForIdle()
longClickLink("Link 1")
longClickMatchingText("Link 1")
verifyLinkContextMenuItems(genericURL.url)
dismissContentContextMenu(genericURL.url)
longClickLink("test_link_image")
longClickMatchingText("test_link_image")
verifyLinkImageContextMenuItems(imageResource.url)
dismissContentContextMenu(imageResource.url)
longClickLink("test_no_link_image")
longClickMatchingText("test_no_link_image")
verifyNoLinkImageContextMenuItems(imageResource.url)
}
}
@ -258,12 +237,13 @@ class ContextMenusTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
longClickLink(genericURL.content)
longClickMatchingText(genericURL.content)
}.clickShareSelectedText {
verifyAndroidShareLayout()
}
}
@Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/24457")
@SmokeTest
@Test
fun selectAndSearchTextTest() {

View File

@ -1,70 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.ui
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.ui.robots.navigationToolbar
/**
* Tests for verifying the new Cookie protection & homescreen feature hints.
* Note: This involves setting the feature flags On for CFRs which are disabled elsewhere.
*
*/
class ContextualHintsTest {
private lateinit var mockWebServer: MockWebServer
@get:Rule
val activityTestRule = HomeActivityTestRule(
isJumpBackInCFREnabled = true,
isTCPCFREnabled = true,
isPocketEnabled = false,
isRecentlyVisitedFeatureEnabled = false,
)
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
@Test
fun jumpBackInCFRTest() {
val genericPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericPage.url) {
verifyCookiesProtectionHint()
// One back press to dismiss the TCP hint
mDevice.pressBack()
}.goToHomescreen {
verifyJumpBackInMessage()
}
}
@Test
fun cookieProtectionHintTest() {
val genericPage = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericPage.url) {
verifyCookiesProtectionHint()
}
}
}

View File

@ -1,8 +1,6 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
@ -12,30 +10,31 @@ 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.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.mDevice
import org.mozilla.fenix.ui.robots.navigationToolbar
class CrashReportingTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
private val featureSettingsHelper = FeatureSettingsHelper()
private val tabCrashMessage = getStringResource(R.string.tab_crash_title_2)
@get:Rule
val activityTestRule = AndroidComposeTestRule(
HomeActivityIntentTestRule(
isPocketEnabled = false,
isJumpBackInCFREnabled = false,
isWallpaperOnboardingEnabled = false,
isTCPCFREnabled = false,
),
) { it.activity }
HomeActivityIntentTestRule(),
{ it.activity }
)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
featureSettingsHelper.setJumpBackCFREnabled(false)
featureSettingsHelper.setPocketEnabled(false)
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -45,6 +44,7 @@ class CrashReportingTest {
@After
fun tearDown() {
mockWebServer.shutdown()
featureSettingsHelper.resetAllFeatureFlags()
}
@Test
@ -74,6 +74,7 @@ class CrashReportingTest {
}
}
@Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/25029")
@SmokeTest
@Test
fun useAppWhileTabIsCrashedTest() {
@ -119,6 +120,7 @@ class CrashReportingTest {
}.openNewTab {
}.submitQuery(secondWebPage.url.toString()) {
waitForPageToLoad()
verifyPageContent("Page content: 2")
}
navigationToolbar {

View File

@ -3,9 +3,7 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
@ -14,23 +12,21 @@ import org.junit.Test
import org.mozilla.fenix.IntentReceiverActivity
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.FeatureSettingsHelperDelegate
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.createCustomTabIntent
import org.mozilla.fenix.helpers.TestHelper.openAppFromExternalLink
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.customTabScreen
import org.mozilla.fenix.ui.robots.mDevice
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.notificationShade
import org.mozilla.fenix.ui.robots.openEditURLView
import org.mozilla.fenix.ui.robots.searchScreen
class CustomTabsTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
private val customMenuItem = "TestMenuItem"
/* Updated externalLinks.html to v2.0,
changed the hypertext reference to mozilla-mobile.github.io/testapp/downloads for "External link"
*/
@ -42,30 +38,20 @@ class CustomTabsTest {
@get: Rule
val intentReceiverActivityTestRule = ActivityTestRule(
IntentReceiverActivity::class.java,
true,
false,
IntentReceiverActivity::class.java, true, false
)
private val featureSettingsHelper = FeatureSettingsHelperDelegate()
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
featureSettingsHelper.apply {
isTCPCFREnabled = false
}.applyFlagUpdates()
}
@After
fun tearDown() {
mockWebServer.shutdown()
featureSettingsHelper.resetAllFeatureFlags()
}
@SmokeTest
@ -76,8 +62,8 @@ class CustomTabsTest {
intentReceiverActivityTestRule.launchActivity(
createCustomTabIntent(
externalLinksPWAPage.toUri().toString(),
customMenuItem,
),
customMenuItem
)
)
customTabScreen {
@ -91,11 +77,12 @@ class CustomTabsTest {
@SmokeTest
@Test
fun customTabsSaveLoginTest() {
intentReceiverActivityTestRule.launchActivity(
createCustomTabIntent(
loginPage.toUri().toString(),
customMenuItem,
),
customMenuItem
)
)
customTabScreen {
@ -129,8 +116,8 @@ class CustomTabsTest {
intentReceiverActivityTestRule.launchActivity(
createCustomTabIntent(
customTabPage.url.toString(),
customMenuItem,
),
customMenuItem
)
)
customTabScreen {
@ -147,7 +134,7 @@ class CustomTabsTest {
clickClearButton()
longClickToolbar()
clickPasteText()
verifyTypedToolbarText(customTabPage.url.toString())
verifyPastedToolbarText(customTabPage.url.toString())
}
}
@ -159,8 +146,8 @@ class CustomTabsTest {
intentReceiverActivityTestRule.launchActivity(
createCustomTabIntent(
customTabPage.url.toString(),
customMenuItem,
),
customMenuItem
)
)
customTabScreen {
@ -183,8 +170,8 @@ class CustomTabsTest {
intentReceiverActivityTestRule.launchActivity(
createCustomTabIntent(
customTabPage.toUri().toString(),
customMenuItem,
),
customMenuItem
)
)
customTabScreen {

View File

@ -32,7 +32,7 @@ import org.mozilla.fenix.ui.robots.DeepLinkRobot
@Ignore("All tests perma-failing, see: https://github.com/mozilla-mobile/fenix/issues/13491")
class DeepLinkTest {
private lateinit var mDevice: UiDevice
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private lateinit var mockWebServer: MockWebServer
private val robot = DeepLinkRobot()
@ -42,7 +42,6 @@ class DeepLinkTest {
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()

View File

@ -5,11 +5,14 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -24,9 +27,10 @@ class DownloadFileTypesTest(fileName: String) {
/* Remote test page managed by Mozilla Mobile QA team at https://github.com/mozilla-mobile/testapp */
private val downloadTestPage = "https://storage.googleapis.com/mobile_test_assets/test_app/downloads.html"
private var downloadFile: String = fileName
private val featureSettingsHelper = FeatureSettingsHelper()
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
val activityTestRule = HomeActivityIntentTestRule()
companion object {
// Creating test data. The test will take each file name as a parameter and run it individually.
@ -40,10 +44,23 @@ class DownloadFileTypesTest(fileName: String) {
"web_icon.png",
"videoSample.webm",
"CSVfile.csv",
"XMLfile.xml",
"XMLfile.xml"
)
}
@Before
fun setUp() {
// disabling the jump-back-in pop-up that interferes with the tests.
featureSettingsHelper.setJumpBackCFREnabled(false)
// disabling the PWA CFR on 3rd visit
featureSettingsHelper.disablePwaCFR(true)
}
@After
fun tearDown() {
featureSettingsHelper.resetAllFeatureFlags()
}
@SmokeTest
@Test
fun downloadMultipleFileTypesTest() {

View File

@ -5,14 +5,17 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestHelper.deleteDownloadedFileOnStorage
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.deleteDownloadFromStorage
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.downloadRobot
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -27,15 +30,21 @@ import org.mozilla.fenix.ui.robots.notificationShade
* - Verifies managing downloads inside the Downloads listing.
**/
class DownloadTest {
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private val featureSettingsHelper = FeatureSettingsHelper()
/* Remote test page managed by Mozilla Mobile QA team at https://github.com/mozilla-mobile/testapp */
private val downloadTestPage = "https://storage.googleapis.com/mobile_test_assets/test_app/downloads.html"
private var downloadFile: String = ""
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
val activityTestRule = HomeActivityIntentTestRule()
@Before
fun setUp() {
// disabling the jump-back-in pop-up that interferes with the tests.
featureSettingsHelper.setJumpBackCFREnabled(false)
// disabling the PWA CFR on 3rd visit
featureSettingsHelper.disablePwaCFR(true)
// clear all existing notifications
notificationShade {
mDevice.openNotification()
@ -45,6 +54,7 @@ class DownloadTest {
@After
fun tearDown() {
featureSettingsHelper.resetAllFeatureFlags()
notificationShade {
cancelAllShownNotifications()
}
@ -102,6 +112,7 @@ class DownloadTest {
}
}
@Ignore("Intermittent: https://github.com/mozilla-mobile/fenix/issues/23434")
@SmokeTest
@Test
fun pauseResumeCancelDownloadTest() {
@ -129,16 +140,16 @@ class DownloadTest {
}
}
/* Verifies downloads in the Downloads Menu:
- downloads appear in the list
- deleting a download from device storage, removes it from the Downloads Menu too
*/
@Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/17485")
@SmokeTest
@Test
/* Verifies downloads in the Downloads Menu:
- downloads appear in the list
- deleting a download from device storage, removes it from the Downloads Menu too
*/
fun manageDownloadsInDownloadsMenuTest() {
// a long filename to verify it's correctly displayed on the prompt and in the Downloads menu
downloadFile =
"tAJwqaWjJsXS8AhzSninBMCfIZbHBGgcc001lx5DIdDwIcfEgQ6vE5Gb5VgAled17DFZ2A7ZDOHA0NpQPHXXFt.svg"
downloadFile = "tAJwqaWjJsXS8AhzSninBMCfIZbHBGgcc001lx5DIdDwIcfEgQ6vE5Gb5VgAled17DFZ2A7ZDOHA0NpQPHXXFt.svg"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
@ -154,34 +165,14 @@ class DownloadTest {
waitForDownloadsListToExist()
verifyDownloadedFileName(downloadFile)
verifyDownloadedFileIcon()
deleteDownloadedFileOnStorage(downloadFile)
openDownloadedFile(downloadFile)
verifyPhotosAppOpens()
deleteDownloadFromStorage()
waitForDownloadsListToExist()
}.exitDownloadsManagerToBrowser {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyEmptyDownloadsList()
}
}
@SmokeTest
@Test
fun openDownloadedFileTest() {
downloadFile = "web_icon.png"
navigationToolbar {
}.enterURLAndEnterToBrowser(downloadTestPage.toUri()) {
waitForPageToLoad()
}.clickDownloadLink(downloadFile) {
verifyDownloadPrompt(downloadFile)
}.clickDownload {
verifyDownloadNotificationPopup()
}
browserScreen {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyDownloadedFileName(downloadFile)
openDownloadedFile(downloadFile)
verifyPhotosAppOpens()
mDevice.pressBack()
}
}
}

View File

@ -6,8 +6,8 @@ package org.mozilla.fenix.ui
import android.content.Context
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import androidx.test.espresso.IdlingRegistry
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import kotlinx.coroutines.runBlocking
import mozilla.components.browser.storage.sync.PlacesHistoryStorage
import okhttp3.mockwebserver.MockWebServer
@ -23,9 +23,9 @@ import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.ui.robots.historyMenu
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.mDevice
import org.mozilla.fenix.ui.robots.multipleSelectionToolbar
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -36,17 +36,17 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
class HistoryTest {
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
private lateinit var mockWebServer: MockWebServer
private lateinit var mDevice: UiDevice
private var historyListIdlingResource: RecyclerViewIdlingResource? = null
private var recentlyClosedTabsListIdlingResource: RecyclerViewIdlingResource? = null
@get:Rule
val activityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides()
val activityTestRule = HomeActivityTestRule()
@Before
fun setUp() {
InstrumentationRegistry.getInstrumentation().targetContext.settings()
.shouldShowJumpBackInCFR = false
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -63,6 +63,14 @@ class HistoryTest {
runBlocking {
historyStorage.deleteEverything()
}
if (historyListIdlingResource != null) {
IdlingRegistry.getInstance().unregister(historyListIdlingResource!!)
}
if (recentlyClosedTabsListIdlingResource != null) {
IdlingRegistry.getInstance().unregister(recentlyClosedTabsListIdlingResource!!)
}
}
@Test
@ -76,9 +84,9 @@ class HistoryTest {
}
}
@Test
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@Test
fun visitedUrlHistoryTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -88,14 +96,13 @@ class HistoryTest {
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1),
) {
verifyHistoryMenuView()
verifyVisitedTimeTitle()
verifyFirstTestPageTitle("Test_Page_1")
verifyTestPageUrl(firstWebPage.url)
}
historyListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1)
IdlingRegistry.getInstance().register(historyListIdlingResource!!)
verifyHistoryMenuView()
verifyVisitedTimeTitle()
verifyFirstTestPageTitle("Test_Page_1")
verifyTestPageUrl(firstWebPage.url)
}
}
@ -109,61 +116,16 @@ class HistoryTest {
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1),
) {
clickDeleteHistoryButton(firstWebPage.url.toString())
}
historyListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1)
IdlingRegistry.getInstance().register(historyListIdlingResource!!)
clickDeleteHistoryButton(firstWebPage.url.toString())
IdlingRegistry.getInstance().unregister(historyListIdlingResource!!)
verifyDeleteSnackbarText("Deleted")
verifyEmptyHistoryView()
}
}
@Test
fun undoDeleteHistoryItemTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1),
) {
clickDeleteHistoryButton(firstWebPage.url.toString())
}
verifyUndoDeleteSnackBarButton()
clickUndoDeleteButton()
verifyHistoryItemExists(true, firstWebPage.url.toString())
}
}
@SmokeTest
@Test
fun cancelDeleteAllHistoryTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1),
) {
clickDeleteAllHistoryButton()
}
verifyDeleteConfirmationMessage()
selectEverythingOption()
cancelDeleteHistory()
verifyHistoryItemExists(true, firstWebPage.url.toString())
}
}
@SmokeTest
@Test
fun deleteAllHistoryTest() {
@ -175,13 +137,12 @@ class HistoryTest {
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1),
) {
clickDeleteAllHistoryButton()
}
historyListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1)
IdlingRegistry.getInstance().register(historyListIdlingResource!!)
clickDeleteAllHistoryButton()
IdlingRegistry.getInstance().unregister(historyListIdlingResource!!)
verifyDeleteConfirmationMessage()
selectEverythingOption()
confirmDeleteAllHistory()
verifyDeleteSnackbarText("Browsing data deleted")
verifyEmptyHistoryView()
@ -199,11 +160,10 @@ class HistoryTest {
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1),
) {
longTapSelectItem(firstWebPage.url)
}
historyListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1)
IdlingRegistry.getInstance().register(historyListIdlingResource!!)
longTapSelectItem(firstWebPage.url)
}
multipleSelectionToolbar {
@ -230,12 +190,11 @@ class HistoryTest {
homeScreen { }.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1),
) {
longTapSelectItem(firstWebPage.url)
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
}
historyListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1)
IdlingRegistry.getInstance().register(historyListIdlingResource!!)
longTapSelectItem(firstWebPage.url)
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
}
multipleSelectionToolbar {
@ -255,12 +214,11 @@ class HistoryTest {
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1),
) {
longTapSelectItem(firstWebPage.url)
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
}
historyListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1)
IdlingRegistry.getInstance().register(historyListIdlingResource!!)
longTapSelectItem(firstWebPage.url)
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
}
multipleSelectionToolbar {
@ -284,15 +242,15 @@ class HistoryTest {
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 2),
) {
verifyHistoryItemExists(true, firstWebPage.url.toString())
verifyHistoryItemExists(true, secondWebPage.url.toString())
longTapSelectItem(firstWebPage.url)
longTapSelectItem(secondWebPage.url)
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
}
historyListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 2)
IdlingRegistry.getInstance().register(historyListIdlingResource!!)
verifyHistoryItemExists(true, firstWebPage.url.toString())
verifyHistoryItemExists(true, secondWebPage.url.toString())
longTapSelectItem(firstWebPage.url)
longTapSelectItem(secondWebPage.url)
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
IdlingRegistry.getInstance().unregister(historyListIdlingResource!!)
}
multipleSelectionToolbar {
@ -314,11 +272,10 @@ class HistoryTest {
}.openThreeDotMenu {
}.openHistory {
verifyHistoryListExists()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1),
) {
longTapSelectItem(firstWebPage.url)
}
historyListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.history_list), 1)
IdlingRegistry.getInstance().register(historyListIdlingResource!!)
longTapSelectItem(firstWebPage.url)
}
multipleSelectionToolbar {
@ -330,8 +287,8 @@ class HistoryTest {
}
}
// This test verifies the Recently Closed Tabs List and items
@Test
// This test verifies the Recently Closed Tabs List and items
fun verifyRecentlyClosedTabsListTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -344,11 +301,11 @@ class HistoryTest {
}.openTabDrawer {
}.openRecentlyClosedTabs {
waitForListToExist()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1),
) {
verifyRecentlyClosedTabsMenuView()
}
recentlyClosedTabsListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1)
IdlingRegistry.getInstance().register(recentlyClosedTabsListIdlingResource!!)
verifyRecentlyClosedTabsMenuView()
IdlingRegistry.getInstance().unregister(recentlyClosedTabsListIdlingResource!!)
verifyRecentlyClosedTabsPageTitle("Test_Page_1")
verifyRecentlyClosedTabsUrl(website.url)
}

View File

@ -4,26 +4,19 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.Constants.POCKET_RECOMMENDED_STORIES_UTM_PARAM
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.ext.waitNotNull
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
/**
* Tests for verifying the presence of home screen and first-run homescreen elements
@ -35,58 +28,35 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
class HomeScreenTest {
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
private lateinit var firstPocketStoryPublisher: String
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@get:Rule(order = 0)
val activityTestRule =
AndroidComposeTestRule(HomeActivityTestRule.withDefaultSettingsOverrides()) { it.activity }
@get:Rule
val activityTestRule = HomeActivityTestRule()
@Rule(order = 1)
@Rule
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
@Test
fun homeScreenItemsTest() {
homeScreen { }.dismissOnboarding()
homeScreen {
verifyHomeWordmark()
verifyHomeScreen()
verifyNavigationToolbar()
verifyHomePrivateBrowsingButton()
verifyHomeMenu()
verifyHomeWordmark()
verifyTabButton()
verifyCollectionsHeader()
verifyHomeToolbar()
verifyHomeComponent()
// Verify Top Sites
verifyExistingTopSitesList()
verifyExistingTopSitesTabs("Wikipedia")
verifyExistingTopSitesTabs("Top Articles")
verifyExistingTopSitesTabs("Google")
verifyCollectionsHeader()
verifyNoCollectionsText()
scrollToPocketProvokingStories()
swipePocketProvokingStories()
verifyPocketRecommendedStoriesItems(activityTestRule, 1, 3, 4, 5, 6, 7)
verifyPocketSponsoredStoriesItems(activityTestRule, 2, 8)
verifyDiscoverMoreStoriesButton(activityTestRule, 9)
verifyStoriesByTopicItems()
verifyPoweredByPocket(activityTestRule)
verifyCustomizeHomepageButton(true)
verifyNavigationToolbar()
verifyDefaultSearchEngine("Google")
verifyHomeMenuButton()
verifyTabButton()
verifyTabCounter("0")
}
}
@ -99,11 +69,11 @@ class HomeScreenTest {
verifyHomeScreen()
verifyNavigationToolbar()
verifyHomePrivateBrowsingButton()
verifyHomeMenuButton()
verifyHomeMenu()
verifyHomeWordmark()
verifyTabButton()
verifyPrivateSessionMessage()
verifyNavigationToolbar()
verifyHomeToolbar()
verifyHomeComponent()
}.openCommonMythsLink {
verifyUrl("common-myths-about-private-browsing")
@ -117,47 +87,15 @@ class HomeScreenTest {
verifyHomeScreen()
verifyNavigationToolbar()
verifyHomePrivateBrowsingButton()
verifyHomeMenuButton()
verifyHomeMenu()
verifyHomeWordmark()
verifyTabButton()
verifyPrivateSessionMessage()
verifyNavigationToolbar()
verifyHomeToolbar()
verifyHomeComponent()
}
}
@Test
fun verifyJumpBackInSectionTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 4)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
}.goToHomescreen {
verifyJumpBackInSectionIsDisplayed()
verifyJumpBackInItemTitle(firstWebPage.title)
verifyJumpBackInItemWithUrl(firstWebPage.url.toString())
verifyJumpBackInShowAllButton()
}.clickJumpBackInShowAllButton {
verifyExistingOpenTabs(firstWebPage.title)
}.closeTabDrawer() {
}
homeScreen {
}.clickJumpBackInItemWithTitle(firstWebPage.title) {
verifyUrl(firstWebPage.url.toString())
clickLinkMatchingText("Link 1")
}.goToHomescreen {
verifyJumpBackInSectionIsDisplayed()
verifyJumpBackInItemTitle(secondWebPage.title)
verifyJumpBackInItemWithUrl(secondWebPage.url.toString())
}.openTabDrawer {
closeTab()
}
homeScreen {
verifyJumpBackInSectionIsNotDisplayed()
}
}
@Test
fun dismissOnboardingUsingSettingsTest() {
homeScreen {
@ -186,11 +124,8 @@ class HomeScreenTest {
@Test
fun dismissOnboardingUsingHelpTest() {
activityTestRule.activityRule.applySettingsExceptions {
it.isJumpBackInCFREnabled = false
it.isWallpaperOnboardingEnabled = false
}
val settings = activityTestRule.activity.applicationContext.settings()
settings.shouldShowJumpBackInCFR = false
homeScreen {
verifyWelcomeHeader()
}.openThreeDotMenu {
@ -201,25 +136,6 @@ class HomeScreenTest {
}
}
@Test
fun dismissOnboardingWithPageLoadTest() {
activityTestRule.activityRule.applySettingsExceptions {
it.isJumpBackInCFREnabled = false
it.isWallpaperOnboardingEnabled = false
}
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
homeScreen {
verifyWelcomeHeader()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.goToHomescreen {
verifyExistingTopSitesList()
}
}
@Test
fun toolbarTapDoesntDismissOnboardingTest() {
homeScreen {
@ -233,125 +149,18 @@ class HomeScreenTest {
}
}
@SmokeTest
@Test
fun verifyPocketHomepageStoriesTest() {
activityTestRule.activityRule.applySettingsExceptions {
it.isRecentTabsFeatureEnabled = false
it.isRecentlyVisitedFeatureEnabled = false
}
fun tapLogoToChangeWallpaperTest() {
homeScreen {
}.dismissOnboarding()
homeScreen {
verifyThoughtProvokingStories(true)
scrollToPocketProvokingStories()
swipePocketProvokingStories()
verifyPocketRecommendedStoriesItems(activityTestRule, 1, 3, 4, 5, 6, 7)
verifyPocketSponsoredStoriesItems(activityTestRule, 2, 8)
verifyDiscoverMoreStoriesButton(activityTestRule, 9)
verifyStoriesByTopic(true)
}.openThreeDotMenu {
}.openCustomizeHome {
clickPocketButton()
}.goBack {
verifyThoughtProvokingStories(false)
verifyStoriesByTopic(false)
}
}
@Test
fun openPocketStoryItemTest() {
activityTestRule.activityRule.applySettingsExceptions {
it.isRecentTabsFeatureEnabled = false
it.isRecentlyVisitedFeatureEnabled = false
}
homeScreen {
}.dismissOnboarding()
homeScreen {
verifyThoughtProvokingStories(true)
scrollToPocketProvokingStories()
firstPocketStoryPublisher = getProvokingStoryPublisher(1)
}.clickPocketStoryItem(firstPocketStoryPublisher, 1) {
verifyUrl(POCKET_RECOMMENDED_STORIES_UTM_PARAM)
}
}
@Ignore("Failed, see: https://github.com/mozilla-mobile/fenix/issues/28098")
@Test
fun openPocketDiscoverMoreTest() {
activityTestRule.activityRule.applySettingsExceptions {
it.isRecentTabsFeatureEnabled = false
it.isRecentlyVisitedFeatureEnabled = false
}
homeScreen {
}.dismissOnboarding()
homeScreen {
scrollToPocketProvokingStories()
swipePocketProvokingStories()
verifyDiscoverMoreStoriesButton(activityTestRule, 9)
}.clickPocketDiscoverMoreButton(activityTestRule, 9) {
verifyUrl("getpocket.com/explore")
}
}
@Test
fun selectStoriesByTopicItemTest() {
activityTestRule.activityRule.applySettingsExceptions {
it.isRecentTabsFeatureEnabled = false
it.isRecentlyVisitedFeatureEnabled = false
}
homeScreen {
}.dismissOnboarding()
homeScreen {
verifyStoriesByTopicItemState(activityTestRule, false, 1)
clickStoriesByTopicItem(activityTestRule, 1)
verifyStoriesByTopicItemState(activityTestRule, true, 1)
}
}
@Test
fun verifyPocketLearnMoreLinkTest() {
activityTestRule.activityRule.applySettingsExceptions {
it.isRecentTabsFeatureEnabled = false
it.isRecentlyVisitedFeatureEnabled = false
}
homeScreen {
}.dismissOnboarding()
homeScreen {
verifyPoweredByPocket(activityTestRule)
}.clickPocketLearnMoreLink(activityTestRule) {
verifyUrl("mozilla.org/en-US/firefox/pocket")
}
}
@Test
fun verifyCustomizeHomepageTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.goToHomescreen {
}.openCustomizeHomepage {
clickJumpBackInButton()
clickRecentBookmarksButton()
clickRecentSearchesButton()
clickPocketButton()
}.goBack {
verifyCustomizeHomepageButton(false)
}.openThreeDotMenu {
}.openCustomizeHome {
clickJumpBackInButton()
}.goBack {
verifyCustomizeHomepageButton(true)
clickFirefoxLogo()
verifyWallpaperImageApplied(true)
clickFirefoxLogo()
verifyWallpaperImageApplied(true)
clickFirefoxLogo()
verifyWallpaperImageApplied(true)
clickFirefoxLogo()
verifyWallpaperImageApplied(false)
}
}
}

View File

@ -4,13 +4,12 @@
package org.mozilla.fenix.ui
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.mediasession.MediaSession
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.ext.components
@ -20,6 +19,7 @@ import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.mDevice
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.notificationShade
@ -33,10 +33,9 @@ class MediaNotificationTest {
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
private lateinit var mockWebServer: MockWebServer
private lateinit var mDevice: UiDevice
@get:Rule
val activityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides()
val activityTestRule = HomeActivityTestRule()
private lateinit var browserStore: BrowserStore
@Rule
@ -49,7 +48,6 @@ class MediaNotificationTest {
// So we are initializing this here instead of in all tests.
browserStore = activityTestRule.activity.components.core.store
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -61,6 +59,7 @@ class MediaNotificationTest {
mockWebServer.shutdown()
}
@Ignore("Failing with ANR: https://github.com/mozilla-mobile/fenix/issues/15754")
@Test
fun videoPlaybackSystemNotificationTest() {
val videoTestPage = TestAssetHelper.getVideoPageAsset(mockWebServer)
@ -94,6 +93,7 @@ class MediaNotificationTest {
mDevice.pressBack()
}
@Ignore("Failing with frequent ANR: https://bugzilla.mozilla.org/show_bug.cgi?id=1764605")
@Test
fun mediaSystemNotificationInPrivateModeTest() {
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)

View File

@ -4,22 +4,19 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import java.util.Locale
/**
* Tests for verifying basic functionality of browser navigation and page related interactions
@ -32,20 +29,21 @@ import java.util.Locale
*/
class NavigationToolbarTest {
private lateinit var mDevice: UiDevice
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private lateinit var mockWebServer: MockWebServer
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
@get:Rule
val activityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides()
val activityTestRule = HomeActivityTestRule()
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
val settings = activityTestRule.activity.settings()
settings.shouldShowJumpBackInCFR = false
}
@After
@ -65,7 +63,7 @@ class NavigationToolbarTest {
}.enterURLAndEnterToBrowser(nextWebPage.url) {
verifyUrl(nextWebPage.url.toString())
}.openThreeDotMenu {
}.goToPreviousPage {
}.goBack {
mDevice.waitForIdle()
verifyUrl(defaultWebPage.url.toString())
}
@ -84,7 +82,7 @@ class NavigationToolbarTest {
mDevice.waitForIdle()
verifyUrl(nextWebPage.url.toString())
}.openThreeDotMenu {
}.goToPreviousPage {
}.goBack {
mDevice.waitForIdle()
verifyUrl(defaultWebPage.url.toString())
}
@ -98,49 +96,9 @@ class NavigationToolbarTest {
}
}
// Swipes the nav bar left/right to switch between tabs
@SmokeTest
@Test
fun swipeToSwitchTabTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
}.openTabDrawer {
}.openNewTab {
}.submitQuery(secondWebPage.url.toString()) {
swipeNavBarRight(secondWebPage.url.toString())
verifyUrl(firstWebPage.url.toString())
swipeNavBarLeft(firstWebPage.url.toString())
verifyUrl(secondWebPage.url.toString())
}
}
// Because it requires changing system prefs, this test will run only on Debug builds
@Test
fun swipeToSwitchTabInRTLTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
val arabicLocale = Locale("ar", "AR")
runWithSystemLocaleChanged(arabicLocale, activityTestRule) {
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
}.openTabDrawer {
}.openNewTab {
}.submitQuery(secondWebPage.url.toString()) {
swipeNavBarLeft(secondWebPage.url.toString())
verifyUrl(firstWebPage.url.toString())
swipeNavBarRight(firstWebPage.url.toString())
verifyUrl(secondWebPage.url.toString())
}
}
}
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
@Test
fun visitURLTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -150,13 +108,17 @@ class NavigationToolbarTest {
}
}
@Ignore("Temp disable broken test - see: https://github.com/mozilla-mobile/fenix/issues/5534")
@Test
fun findInPageTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 3)
val loremIpsumWebPage = TestAssetHelper.getLoremIpsumAsset(mockWebServer)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.enterURLAndEnterToBrowser(loremIpsumWebPage.url) {
mDevice.waitForIdle()
}
navigationToolbar {
}.openThreeDotMenu {
verifyThreeDotMenuExists()
verifyFindInPageButton()
@ -164,58 +126,19 @@ class NavigationToolbarTest {
verifyFindInPageNextButton()
verifyFindInPagePrevButton()
verifyFindInPageCloseButton()
enterFindInPageQuery("a")
enterFindInPageQuery("lab")
verifyFindNextInPageResult("1/3")
clickFindInPageNextButton()
verifyFindNextInPageResult("2/3")
clickFindInPageNextButton()
verifyFindNextInPageResult("3/3")
clickFindInPagePrevButton()
verifyFindPrevInPageResult("2/3")
clickFindInPagePrevButton()
verifyFindPrevInPageResult("1/3")
enterFindInPageQuery("3")
verifyFindNextInPageResult("1/1")
verifyFindPrevInPageResult("3/3")
verifyFindPrevInPageResult("2/3")
enterFindInPageQuery("in")
verifyFindNextInPageResult("3/7")
verifyFindNextInPageResult("4/7")
verifyFindNextInPageResult("5/7")
verifyFindNextInPageResult("6/7")
verifyFindNextInPageResult("7/7")
}.closeFindInPage { }
}
@Test
fun verifySecurePageSecuritySubMenuTest() {
val defaultWebPage = "https://mozilla-mobile.github.io/testapp/loginForm"
val defaultWebPageTitle = "Login_form"
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.toUri()) {
}.openSiteSecuritySheet {
verifyQuickActionSheet(defaultWebPage, true)
openSecureConnectionSubMenu(true)
verifySecureConnectionSubMenu(defaultWebPageTitle, defaultWebPage, true)
}
}
@Test
fun verifyInsecurePageSecuritySubMenuTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openSiteSecuritySheet {
verifyQuickActionSheet(defaultWebPage.url.toString(), false)
openSecureConnectionSubMenu(false)
verifySecureConnectionSubMenu(defaultWebPage.title, defaultWebPage.url.toString(), false)
}
}
@Test
fun verifyClearCookiesFromQuickSettingsTest() {
val helpPageUrl = "mozilla.org"
homeScreen {
}.openThreeDotMenu {
}.openHelp {
}.openSiteSecuritySheet {
clickQuickActionSheetClearSiteData()
verifyClearSiteDataPrompt(helpPageUrl)
}
}
}

View File

@ -1,74 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.ui
import android.content.Intent
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import io.mockk.mockk
import mozilla.components.concept.sync.AuthType
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.components.TelemetryAccountObserver
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.Experimentation
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.ui.robots.homeScreen
class NimbusEventTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
@get:Rule
val homeActivityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
.withIntent(
Intent().apply {
action = Intent.ACTION_VIEW
},
)
@Rule
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
@Test
fun homeScreenNimbusEventsTest() {
homeScreen { }.dismissOnboarding()
Experimentation.withHelper {
assertTrue(evalJexl("'app_opened'|eventSum('Days', 28, 0) > 0"))
}
}
@Test
fun telemetryAccountObserverTest() {
val observer = TelemetryAccountObserver(appContext)
observer.onAuthenticated(mockk(), AuthType.Signin)
Experimentation.withHelper {
assertTrue(evalJexl("'sync_auth.sign_in'|eventSum('Days', 28, 0) > 0"))
}
}
}

View File

@ -5,10 +5,13 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.After
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.setNetworkEnabled
@ -25,7 +28,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
class NoNetworkAccessStartupTests {
@get:Rule
val activityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides(launchActivity = false)
val activityTestRule = HomeActivityTestRule(launchActivity = false)
@After
fun tearDown() {
@ -33,10 +36,10 @@ class NoNetworkAccessStartupTests {
setNetworkEnabled(true)
}
@Test
// 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
@Test
fun noNetworkConnectionStartupTest() {
setNetworkEnabled(false)
@ -49,10 +52,12 @@ class NoNetworkAccessStartupTests {
}
}
// Based on STR from https://github.com/mozilla-mobile/fenix/issues/16886
@Test
// Based on STR from https://github.com/mozilla-mobile/fenix/issues/16886
fun networkInterruptedFromBrowserToHomeTest() {
val url = "example.com"
val settings = InstrumentationRegistry.getInstrumentation().targetContext.settings()
settings.shouldShowJumpBackInCFR = false
activityTestRule.launchActivity(null)
@ -83,6 +88,7 @@ class NoNetworkAccessStartupTests {
}.refreshPage { }
}
@Ignore("Failing with frequent ANR: https://bugzilla.mozilla.org/show_bug.cgi?id=1764605")
@Test
fun testSignInPageWithNoNetworkConnection() {
setNetworkEnabled(false)
@ -97,7 +103,7 @@ class NoNetworkAccessStartupTests {
verifyUrl(
"firefox.com",
"$packageName:id/mozac_browser_toolbar_url_view",
R.id.mozac_browser_toolbar_url_view,
R.id.mozac_browser_toolbar_url_view
)
}
}

View File

@ -1,53 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.ui.robots.homeScreen
/**
* Tests for verifying the new onboarding features.
* Note: This involves setting the feature flag On for the onboarding dialog
*
*/
class OnboardingFeaturesTest {
@get:Rule
val activityTestRule = AndroidComposeTestRule(
HomeActivityTestRule(isHomeOnboardingDialogEnabled = true),
) { it.activity }
@SmokeTest
@Test
fun upgradingUsersOnboardingScreensTest() {
homeScreen {
verifyUpgradingUserOnboardingFirstScreen(activityTestRule)
clickGetStartedButton(activityTestRule)
verifyUpgradingUserOnboardingSecondScreen(activityTestRule)
clickSkipButton(activityTestRule)
verifyHomeScreen()
}
}
@Test
fun upgradingUsersOnboardingSignInButtonTest() {
homeScreen {
verifyUpgradingUserOnboardingFirstScreen(activityTestRule)
clickGetStartedButton(activityTestRule)
verifyUpgradingUserOnboardingSecondScreen(activityTestRule)
}.clickUpgradingUserOnboardingSignInButton(activityTestRule) {
verifyTurnOnSyncMenu()
mDevice.pressBack()
}
homeScreen {
verifyHomeScreen()
}
}
}

View File

@ -1,19 +1,21 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import org.junit.Ignore
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.helpers.Constants.PackageName.GMAIL_APP
import org.mozilla.fenix.helpers.Constants.PackageName.PHONE_APP
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestHelper.assertNativeAppOpens
import org.mozilla.fenix.ui.robots.customTabScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.pwaScreen
class PwaTest {
private val featureSettingsHelper = FeatureSettingsHelper()
/* Updated externalLinks.html to v2.0,
changed the hypertext reference to mozilla-mobile.github.io/testapp/downloads for "External link"
*/
@ -23,7 +25,17 @@ class PwaTest {
private val shortcutTitle = "TEST_APP"
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
val activityTestRule = HomeActivityIntentTestRule()
@Before
fun setUp() {
featureSettingsHelper.disablePwaCFR(true)
}
@After
fun tearDown() {
featureSettingsHelper.resetAllFeatureFlags()
}
@SmokeTest
@Test
@ -32,8 +44,6 @@ class PwaTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(externalLinksPWAPage.toUri()) {
waitForPageToLoad()
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.clickInstall {
clickAddAutomaticallyButton()
@ -46,14 +56,13 @@ class PwaTest {
}
}
@Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/28212")
@SmokeTest
@Test
fun emailLinkPWATest() {
navigationToolbar {
}.enterURLAndEnterToBrowser(externalLinksPWAPage.toUri()) {
waitForPageToLoad()
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.clickInstall {
clickAddAutomaticallyButton()
@ -66,10 +75,10 @@ class PwaTest {
@SmokeTest
@Test
fun telephoneLinkPWATest() {
navigationToolbar {
}.enterURLAndEnterToBrowser(externalLinksPWAPage.toUri()) {
waitForPageToLoad()
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.clickInstall {
clickAddAutomaticallyButton()
@ -78,23 +87,4 @@ class PwaTest {
assertNativeAppOpens(PHONE_APP, phoneLink)
}
}
@SmokeTest
@Test
fun appLikeExperiencePWATest() {
navigationToolbar {
}.enterURLAndEnterToBrowser(externalLinksPWAPage.toUri()) {
waitForPageToLoad()
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.clickInstall {
clickAddAutomaticallyButton()
}.openHomeScreenShortcut(shortcutTitle) {
}
pwaScreen {
verifyCustomTabToolbarIsNotDisplayed()
verifyPwaActivityInCurrentTask()
}
}
}

View File

@ -5,8 +5,7 @@
package org.mozilla.fenix.ui
import android.view.View
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import androidx.test.espresso.IdlingRegistry
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
@ -17,9 +16,9 @@ import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.ViewVisibilityIdlingResource
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.mDevice
import org.mozilla.fenix.ui.robots.navigationToolbar
/**
@ -33,11 +32,11 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
class ReaderViewTest {
private lateinit var mockWebServer: MockWebServer
private lateinit var mDevice: UiDevice
private var readerViewNotification: ViewVisibilityIdlingResource? = null
private val estimatedReadingTime = "1 - 2 minutes"
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
val activityIntentTestRule = HomeActivityIntentTestRule()
@Rule
@JvmField
@ -45,7 +44,6 @@ class ReaderViewTest {
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -55,6 +53,7 @@ class ReaderViewTest {
@After
fun tearDown() {
mockWebServer.shutdown()
IdlingRegistry.getInstance().unregister(readerViewNotification)
}
/**
@ -73,12 +72,12 @@ class ReaderViewTest {
mDevice.waitForIdle()
}
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE,
),
) {}
readerViewNotification = ViewVisibilityIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE
)
IdlingRegistry.getInstance().register(readerViewNotification)
navigationToolbar {
verifyReaderViewDetected(true)
@ -116,12 +115,12 @@ class ReaderViewTest {
mDevice.waitForIdle()
}
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE,
),
) {}
readerViewNotification = ViewVisibilityIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE
)
IdlingRegistry.getInstance().register(readerViewNotification)
navigationToolbar {
verifyReaderViewDetected(true)
@ -141,7 +140,7 @@ class ReaderViewTest {
verifyReaderViewDetected(true)
}.openThreeDotMenu {
verifyReaderViewAppearance(false)
}.closeBrowserMenuToBrowser { }
}.close { }
}
@Test
@ -154,12 +153,12 @@ class ReaderViewTest {
mDevice.waitForIdle()
}
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE,
),
) {}
readerViewNotification = ViewVisibilityIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE
)
IdlingRegistry.getInstance().register(readerViewNotification)
navigationToolbar {
verifyReaderViewDetected(true)
@ -194,12 +193,12 @@ class ReaderViewTest {
mDevice.waitForIdle()
}
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE,
),
) {}
readerViewNotification = ViewVisibilityIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE
)
IdlingRegistry.getInstance().register(readerViewNotification)
navigationToolbar {
verifyReaderViewDetected(true)
@ -240,12 +239,12 @@ class ReaderViewTest {
mDevice.waitForIdle()
}
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE,
),
) {}
readerViewNotification = ViewVisibilityIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE
)
IdlingRegistry.getInstance().register(readerViewNotification)
navigationToolbar {
verifyReaderViewDetected(true)

View File

@ -4,36 +4,27 @@
package org.mozilla.fenix.ui
import android.content.Context
import android.hardware.camera2.CameraManager
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.core.net.toUri
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import androidx.test.espresso.Espresso.pressBack
import mozilla.components.browser.icons.IconRequest
import mozilla.components.browser.icons.generator.DefaultIconGenerator
import mozilla.components.feature.search.ext.createSearchEngine
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.Constants.PackageName.ANDROID_SETTINGS
import org.mozilla.fenix.helpers.Constants.searchEngineCodes
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.SearchDispatcher
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.assertNativeAppOpens
import org.mozilla.fenix.helpers.TestHelper.denyPermission
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.grantPermission
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.setCustomSearchEngine
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.multipleSelectionToolbar
@ -48,20 +39,14 @@ import org.mozilla.fenix.ui.robots.multipleSelectionToolbar
*/
class SearchTest {
private val featureSettingsHelper = FeatureSettingsHelper()
lateinit var searchMockServer: MockWebServer
lateinit var queryString: String
@get:Rule
val activityTestRule = AndroidComposeTestRule(
HomeActivityTestRule(
skipOnboarding = true,
isPocketEnabled = false,
isJumpBackInCFREnabled = false,
isRecentTabsFeatureEnabled = false,
isTCPCFREnabled = false,
isWallpaperOnboardingEnabled = false,
),
) { it.activity }
HomeActivityTestRule(),
{ it.activity }
)
@Before
fun setUp() {
@ -69,11 +54,14 @@ class SearchTest {
dispatcher = SearchDispatcher()
start()
}
featureSettingsHelper.setJumpBackCFREnabled(false)
featureSettingsHelper.setPocketEnabled(false)
}
@After
fun tearDown() {
searchMockServer.shutdown()
featureSettingsHelper.resetAllFeatureFlags()
}
@Test
@ -88,271 +76,206 @@ class SearchTest {
}
@SmokeTest
@Ignore("This test cannot run on virtual devices due to camera permissions being required")
@Test
fun scanButtonDenyPermissionTest() {
val cameraManager = appContext.getSystemService(Context.CAMERA_SERVICE) as CameraManager
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
fun scanButtonTest() {
homeScreen {
}.openSearch {
clickScanButton()
denyPermission()
clickDenyPermission()
clickScanButton()
clickDismissPermissionRequiredDialog()
}
homeScreen {
}.openSearch {
clickScanButton()
clickGoToPermissionsSettings()
assertNativeAppOpens(ANDROID_SETTINGS)
}
}
@SmokeTest
@Test
fun scanButtonAllowPermissionTest() {
val cameraManager = appContext.getSystemService(Context.CAMERA_SERVICE) as CameraManager
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
homeScreen {
}.openSearch {
clickScanButton()
grantPermission()
verifyScannerOpen()
clickAllowPermission()
}
}
@Test
fun setDefaultSearchEngineFromShortcutsTest() {
queryString = "firefox"
fun shortcutButtonTest() {
val searchEngineURL = "bing.com/search?q=mozilla%20firefox"
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
toggleShowSearchShortcuts()
enableShowSearchShortcuts()
}.goBack {
}.goBack {
}.openSearch {
verifySearchBarEmpty()
clickSearchEngineButton(activityTestRule, "Bing")
typeSearch("mozilla")
verifySearchEngineResults(activityTestRule, "mozilla firefox", "Bing")
clickSearchEngineResult(activityTestRule, "mozilla firefox")
}
browserScreen {
waitForPageToLoad()
verifyUrl(searchEngineURL)
}
}
@Test
fun shortcutSearchEngineSettingsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
enableShowSearchShortcuts()
}.goBack {
}.goBack {
}.openSearch {
scrollToSearchEngineSettings(activityTestRule)
}.clickSearchEngineSettings(activityTestRule) {
changeDefaultSearchEngine("DuckDuckGo")
}
exitMenu()
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
verifyUrl("duckduckgo.com/?q=firefox")
clickSearchEngineSettings(activityTestRule)
verifySearchSettings()
}
}
@Test
fun clearSearchTest() {
queryString = "test"
homeScreen {
}.openSearch {
typeSearch(queryString)
typeSearch("test")
clickClearButton()
verifySearchBarEmpty()
}
}
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Ignore("Failure caused by bugs: https://github.com/mozilla-mobile/fenix/issues/23818")
@SmokeTest
@Test
fun searchGroupShowsInRecentlyVisitedTest() {
queryString = "test search"
val firstPage = searchMockServer.url("generic1.html").toString()
val secondPage = searchMockServer.url("generic2.html").toString()
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val searchString = "http://localhost:${searchMockServer.port}/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap
)
setCustomSearchEngine(customSearchEngine)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
longClickLink("Link 1")
}.submitQuery("test search") {
longClickMatchingText("Link 1")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
pressBack()
longClickLink("Link 2")
longClickMatchingText("Link 2")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
}.goToHomescreen {
verifyJumpBackInSectionIsDisplayed()
verifyCurrentSearchGroupIsDisplayed(true, "test search", 3)
verifyRecentlyVisitedSearchGroupDisplayed(false, "test search", 3)
}.openTabDrawer {
}.openTabFromGroup(firstPage) {
}.openTabDrawer {
}.openTabFromGroup(secondPage) {
}.openTabDrawer {
}.openTabsListThreeDotMenu {
}.closeAllTabs {
verifyRecentlyVisitedSearchGroupDisplayed(true, queryString, 3)
verifyRecentlyVisitedSearchGroupDisplayed(true, "test search", 3)
}
}
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun verifySearchGroupHistoryWithNoDuplicatesTest() {
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
val secondPageUrl = getGenericAsset(searchMockServer, 2).url
val originPageUrl =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search=test%20search".toUri()
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
setCustomSearchEngine(customSearchEngine)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
longClickLink("Link 1")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
pressBack()
longClickLink("Link 1")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
pressBack()
longClickLink("Link 2")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
pressBack()
longClickLink("Link 1")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
}.openTabDrawer {
}.openTabsListThreeDotMenu {
}.closeAllTabs {
verifyRecentlyVisitedSearchGroupDisplayed(true, queryString, 3)
}.openRecentlyVisitedSearchGroupHistoryList(queryString) {
verifyTestPageUrl(firstPageUrl)
verifyTestPageUrl(secondPageUrl)
verifyTestPageUrl(originPageUrl)
}
}
@Ignore("Failing due to known bug, see https://github.com/mozilla-mobile/fenix/issues/23818")
@Test
fun searchGroupGeneratedInTheSameTabTest() {
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
setCustomSearchEngine(customSearchEngine)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
clickLinkMatchingText("Link 1")
waitForPageToLoad()
pressBack()
clickLinkMatchingText("Link 2")
waitForPageToLoad()
}.openTabDrawer {
}.openTabsListThreeDotMenu {
}.closeAllTabs {
verifyRecentlyVisitedSearchGroupDisplayed(true, queryString, 3)
}
}
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@SmokeTest
@Test
fun noSearchGroupFromPrivateBrowsingTest() {
queryString = "test search"
fun noCurrentSearchGroupFromPrivateBrowsingTest() {
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val searchString = "http://localhost:${searchMockServer.port}/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap
)
setCustomSearchEngine(customSearchEngine)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
longClickLink("Link 1")
}.submitQuery("test search") {
longClickMatchingText("Link 1")
clickContextOpenLinkInPrivateTab()
longClickLink("Link 2")
longClickMatchingText("Link 2")
clickContextOpenLinkInPrivateTab()
}.openTabDrawer {
}.toggleToPrivateTabs {
}.openTabWithIndex(0) {
}.openTabDrawer {
}.openTabWithIndex(1) {
}.openTabDrawer {
}.openTabsListThreeDotMenu {
}.closeAllTabs {
togglePrivateBrowsingModeOnOff()
verifyRecentlyVisitedSearchGroupDisplayed(false, queryString, 3)
}.goToHomescreen {
verifyCurrentSearchGroupIsDisplayed(false, "test search", 3)
}.openThreeDotMenu {
}.openHistory {
verifyHistoryItemExists(false, "3 sites")
}
}
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@SmokeTest
@Test
fun deleteItemsFromSearchGroupHistoryTest() {
queryString = "test search"
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
val secondPageUrl = getGenericAsset(searchMockServer, 2).url
fun noRecentlyVisitedSearchGroupInPrivateBrowsingTest() {
val firstPage = searchMockServer.url("generic1.html").toString()
val secondPage = searchMockServer.url("generic2.html").toString()
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val searchString = "http://localhost:${searchMockServer.port}/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap
)
setCustomSearchEngine(customSearchEngine)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openSearch {
}.submitQuery("test search") {
longClickMatchingText("Link 1")
clickContextOpenLinkInPrivateTab()
longClickMatchingText("Link 2")
clickContextOpenLinkInPrivateTab()
}.openTabDrawer {
}.openTab(firstPage) {
}.openTabDrawer {
}.openTab(secondPage) {
}.openTabDrawer {
}.openTabsListThreeDotMenu {
}.closeAllTabs {
homeScreen {
}.togglePrivateBrowsingMode()
verifyRecentlyVisitedSearchGroupDisplayed(false, "test search", 3)
}
}
@Ignore("Failure caused by bugs: https://github.com/mozilla-mobile/fenix/issues/23818")
@SmokeTest
@Test
fun deleteItemsFromSearchGroupsHistoryTest() {
val firstPage = searchMockServer.url("generic1.html").toString()
val secondPage = searchMockServer.url("generic2.html").toString()
// setting our custom mockWebServer search URL
val searchString = "http://localhost:${searchMockServer.port}/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap
)
setCustomSearchEngine(customSearchEngine)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
longClickLink("Link 1")
}.submitQuery("test search") {
longClickMatchingText("Link 1")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
mDevice.pressBack()
longClickLink("Link 2")
longClickMatchingText("Link 2")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
}.openTabDrawer {
}.openTabFromGroup(firstPage) {
}.openTabDrawer {
}.openTabFromGroup(secondPage) {
}.openTabDrawer {
}.openTabsListThreeDotMenu {
}.closeAllTabs {
verifyRecentlyVisitedSearchGroupDisplayed(true, queryString, 3)
}.openRecentlyVisitedSearchGroupHistoryList(queryString) {
clickDeleteHistoryButton(firstPageUrl.toString())
longTapSelectItem(secondPageUrl)
verifyRecentlyVisitedSearchGroupDisplayed(true, "test search", 3)
}.openRecentlyVisitedSearchGroupHistoryList("test search") {
clickDeleteHistoryButton(firstPage)
longTapSelectItem(secondPage.toUri())
multipleSelectionToolbar {
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
clickMultiSelectionDelete()
@ -361,207 +284,7 @@ class SearchTest {
}
homeScreen {
// checking that the group is removed when only 1 item is left
verifyRecentlyVisitedSearchGroupDisplayed(false, queryString, 1)
}
}
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun deleteSearchGroupFromHistoryTest() {
queryString = "test search"
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
setCustomSearchEngine(customSearchEngine)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
longClickLink("Link 1")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
mDevice.pressBack()
longClickLink("Link 2")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
}.openTabDrawer {
}.openTabsListThreeDotMenu {
}.closeAllTabs {
verifyRecentlyVisitedSearchGroupDisplayed(true, queryString, 3)
}.openRecentlyVisitedSearchGroupHistoryList(queryString) {
clickDeleteAllHistoryButton()
confirmDeleteAllHistory()
verifyDeleteSnackbarText("Group deleted")
verifyHistoryItemExists(false, firstPageUrl.toString())
}.goBack {}
homeScreen {
verifyRecentlyVisitedSearchGroupDisplayed(false, queryString, 3)
}.openThreeDotMenu {
}.openHistory {
verifySearchGroupDisplayed(false, queryString, 3)
verifyEmptyHistoryView()
}
}
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun reopenTabsFromSearchGroupTest() {
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
val secondPageUrl = getGenericAsset(searchMockServer, 2).url
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
setCustomSearchEngine(customSearchEngine)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
longClickLink("Link 1")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
mDevice.pressBack()
longClickLink("Link 2")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
}.openTabDrawer {
}.openTabsListThreeDotMenu {
}.closeAllTabs {
verifyRecentlyVisitedSearchGroupDisplayed(true, queryString, 3)
}.openRecentlyVisitedSearchGroupHistoryList(queryString) {
}.openWebsite(firstPageUrl) {
verifyUrl(firstPageUrl.toString())
}.goToHomescreen {
}.openRecentlyVisitedSearchGroupHistoryList(queryString) {
longTapSelectItem(firstPageUrl)
longTapSelectItem(secondPageUrl)
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
}
multipleSelectionToolbar {
}.clickOpenNewTab {
verifyNormalModeSelected()
}.closeTabDrawer {}
openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
multipleSelectionToolbar {
}.clickOpenPrivateTab {
verifyPrivateModeSelected()
}
}
@Ignore("Test run timing out: https://github.com/mozilla-mobile/fenix/issues/27704")
@Test
fun sharePageFromASearchGroupTest() {
val firstPageUrl = getGenericAsset(searchMockServer, 1).url
queryString = "test search"
// setting our custom mockWebServer search URL
val searchString =
"http://localhost:${searchMockServer.port}/pages/searchResults.html?search={searchTerms}"
val customSearchEngine = createSearchEngine(
name = "TestSearchEngine",
url = searchString,
icon = DefaultIconGenerator().generate(appContext, IconRequest(searchString)).bitmap,
)
setCustomSearchEngine(customSearchEngine)
// Performs a search and opens 2 dummy search results links to create a search group
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
longClickLink("Link 1")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
mDevice.pressBack()
longClickLink("Link 2")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
waitForPageToLoad()
}.openTabDrawer {
}.openTabsListThreeDotMenu {
}.closeAllTabs {
verifyRecentlyVisitedSearchGroupDisplayed(true, queryString, 3)
}.openRecentlyVisitedSearchGroupHistoryList(queryString) {
longTapSelectItem(firstPageUrl)
}
multipleSelectionToolbar {
clickShareHistoryButton()
verifyShareOverlay()
verifyShareTabFavicon()
verifyShareTabTitle()
verifyShareTabUrl()
}
}
// Default search code for Google-US
@Test
fun defaultSearchCodeGoogleUS() {
queryString = "firefox"
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
verifyUrl(searchEngineCodes["Google"]!!)
}
}
// Default search code for Bing-US
@Test
fun defaultSearchCodeBingUS() {
queryString = "firefox"
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
changeDefaultSearchEngine("Bing")
}
exitMenu()
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
verifyUrl(searchEngineCodes["Bing"]!!)
}
}
// Default search code for DuckDuckGo-US
@Test
fun defaultSearchCodeDuckDuckGoUS() {
queryString = "firefox"
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
changeDefaultSearchEngine("DuckDuckGo")
}
exitMenu()
homeScreen {
}.openSearch {
}.submitQuery(queryString) {
verifyUrl(searchEngineCodes["DuckDuckGo"]!!)
verifyRecentlyVisitedSearchGroupDisplayed(false, "test search", 1)
}
}
}

View File

@ -10,14 +10,16 @@ import androidx.test.uiautomator.UiSelector
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
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.ui.robots.clickRateButtonGooglePlay
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.mDevice
/**
* Tests for verifying the main three dot menu options
@ -27,7 +29,7 @@ import org.mozilla.fenix.ui.robots.homeScreen
class SettingsAboutTest {
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
private lateinit var mDevice: UiDevice
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private lateinit var mockWebServer: MockWebServer
@get:Rule
@ -39,7 +41,6 @@ class SettingsAboutTest {
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -51,8 +52,8 @@ class SettingsAboutTest {
mockWebServer.shutdown()
}
// Walks through settings menu and sub-menus to ensure all items are present
@Test
// Walks through settings menu and sub-menus to ensure all items are present
fun settingsAboutItemsTest() {
// ABOUT
homeScreen {
@ -68,10 +69,6 @@ class SettingsAboutTest {
// ABOUT
@Test
fun verifyRateOnGooglePlayRedirect() {
activityIntentTestRule.applySettingsExceptions {
it.isTCPCFREnabled = false
}
homeScreen {
}.openThreeDotMenu {
}.openSettings {
@ -83,12 +80,11 @@ class SettingsAboutTest {
}
}
@Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/25355")
@Test
fun verifyAboutFirefoxPreview() {
activityIntentTestRule.applySettingsExceptions {
it.isJumpBackInCFREnabled = false
it.isTCPCFREnabled = false
}
val settings = activityIntentTestRule.activity.settings()
settings.shouldShowJumpBackInCFR = false
homeScreen {
}.openThreeDotMenu {
}.openSettings {

View File

@ -5,6 +5,7 @@
package org.mozilla.fenix.ui
import android.view.View
import androidx.test.espresso.IdlingRegistry
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
@ -18,7 +19,6 @@ import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper.getEnhancedTrackingProtectionAsset
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.ViewVisibilityIdlingResource
import org.mozilla.fenix.ui.robots.addonsMenu
import org.mozilla.fenix.ui.robots.homeScreen
@ -30,9 +30,11 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
*/
class SettingsAddonsTest {
private lateinit var mockWebServer: MockWebServer
private var addonsListIdlingResource: RecyclerViewIdlingResource? = null
private var addonContainerIdlingResource: ViewVisibilityIdlingResource? = null
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
val activityTestRule = HomeActivityIntentTestRule()
@Before
fun setUp() {
@ -45,6 +47,14 @@ class SettingsAddonsTest {
@After
fun tearDown() {
mockWebServer.shutdown()
if (addonsListIdlingResource != null) {
IdlingRegistry.getInstance().unregister(addonsListIdlingResource!!)
}
if (addonContainerIdlingResource != null) {
IdlingRegistry.getInstance().unregister(addonContainerIdlingResource!!)
}
}
// Walks through settings add-ons menu to ensure all items are present
@ -56,11 +66,10 @@ class SettingsAddonsTest {
verifyAdvancedHeading()
verifyAddons()
}.openAddonsManagerMenu {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.add_ons_list), 1),
) {
verifyAddonsItems()
}
addonsListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.add_ons_list), 1)
IdlingRegistry.getInstance().register(addonsListIdlingResource!!)
verifyAddonsItems()
}
}
@ -72,14 +81,14 @@ class SettingsAddonsTest {
homeScreen {}
.openThreeDotMenu {}
.openAddonsManagerMenu {
registerAndCleanupIdlingResources(
addonsListIdlingResource =
RecyclerViewIdlingResource(
activityTestRule.activity.findViewById(R.id.add_ons_list),
1,
),
) {
clickInstallAddon(addonName)
}
1
)
IdlingRegistry.getInstance().register(addonsListIdlingResource!!)
clickInstallAddon(addonName)
IdlingRegistry.getInstance().unregister(addonsListIdlingResource!!)
verifyAddonPermissionPrompt(addonName)
cancelInstallAddon()
clickInstallAddon(addonName)
@ -102,20 +111,20 @@ class SettingsAddonsTest {
verifyAddonInstallCompleted(addonName, activityTestRule)
closeAddonInstallCompletePrompt()
}.openDetailedMenuForAddon(addonName) {
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityTestRule.activity.findViewById(R.id.addon_container),
View.VISIBLE,
),
) {}
addonContainerIdlingResource = ViewVisibilityIdlingResource(
activityTestRule.activity.findViewById(R.id.addon_container),
View.VISIBLE
)
IdlingRegistry.getInstance().register(addonContainerIdlingResource!!)
}.removeAddon {
IdlingRegistry.getInstance().unregister(addonContainerIdlingResource!!)
verifyAddonCanBeInstalled(addonName)
}
}
// Installs uBlock add-on and checks that the app doesn't crash while loading pages with trackers
@SmokeTest
@Test
// Installs uBlock add-on and checks that the app doesn't crash while loading pages with trackers
fun noCrashWithAddonInstalledTest() {
// setting ETP to Strict mode to test it works with add-ons
activityTestRule.activity.settings().setStrictETP()

View File

@ -9,13 +9,17 @@ import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_PLAY_SERVICES
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.assertNativeAppOpens
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -27,31 +31,35 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
class SettingsAdvancedTest {
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
private lateinit var mDevice: UiDevice
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private lateinit var mockWebServer: MockWebServer
private val featureSettingsHelper = FeatureSettingsHelper()
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule(
isPocketEnabled = false,
isTCPCFREnabled = false,
)
val activityIntentTestRule = HomeActivityIntentTestRule()
@Rule
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
featureSettingsHelper.setPocketEnabled(false)
}
@After
fun tearDown() {
mockWebServer.shutdown()
featureSettingsHelper.resetAllFeatureFlags()
}
// Walks through settings menu and sub-menus to ensure all items are present
@Test
// Walks through settings menu and sub-menus to ensure all items are present
fun settingsAboutItemsTest() {
// ADVANCED
homeScreen {
@ -67,11 +75,13 @@ class SettingsAdvancedTest {
}
}
// Assumes Play Store is installed and enabled
@Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/25551")
@SmokeTest
@Test
// Assumes Play Store is installed and enabled
fun openLinkInAppTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 3)
val playStoreUrl = "play.google.com/store/apps/details?id=org.mozilla.fenix"
homeScreen {
}.openThreeDotMenu {
@ -86,7 +96,7 @@ class SettingsAdvancedTest {
mDevice.waitForIdle()
clickLinkMatchingText("Mozilla Playstore link")
mDevice.waitForIdle()
TestHelper.assertPlayStoreOpens()
assertNativeAppOpens(GOOGLE_PLAY_SERVICES, playStoreUrl)
}
}
}

View File

@ -4,39 +4,19 @@
package org.mozilla.fenix.ui
import android.content.res.Configuration
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.FenixApplication
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestAssetHelper.getLoremIpsumAsset
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeLong
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.TestHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.ui.SettingsBasicsTest.CreditCard.MOCK_CREDIT_CARD_NUMBER
import org.mozilla.fenix.ui.SettingsBasicsTest.CreditCard.MOCK_EXPIRATION_MONTH
import org.mozilla.fenix.ui.SettingsBasicsTest.CreditCard.MOCK_EXPIRATION_YEAR
import org.mozilla.fenix.ui.SettingsBasicsTest.CreditCard.MOCK_LAST_CARD_DIGITS
import org.mozilla.fenix.ui.SettingsBasicsTest.CreditCard.MOCK_NAME_ON_CARD
import org.mozilla.fenix.ui.robots.checkTextSizeOnWebsite
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.util.FRENCH_LANGUAGE_HEADER
import org.mozilla.fenix.ui.util.FRENCH_SYSTEM_LOCALE_OPTION
import org.mozilla.fenix.ui.util.FR_SETTINGS
import org.mozilla.fenix.ui.util.ROMANIAN_LANGUAGE_HEADER
import java.time.LocalDate
import java.util.Locale
/**
* Tests for verifying the General section of the Settings menu
@ -45,17 +25,10 @@ import java.util.Locale
class SettingsBasicsTest {
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
private lateinit var mockWebServer: MockWebServer
object CreditCard {
const val MOCK_CREDIT_CARD_NUMBER = "5555555555554444"
const val MOCK_LAST_CARD_DIGITS = "4444"
const val MOCK_NAME_ON_CARD = "Mastercard"
const val MOCK_EXPIRATION_MONTH = "February"
val MOCK_EXPIRATION_YEAR = (LocalDate.now().year + 1).toString()
}
private val featureSettingsHelper = FeatureSettingsHelper()
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
val activityIntentTestRule = HomeActivityIntentTestRule()
@Before
fun setUp() {
@ -63,11 +36,27 @@ class SettingsBasicsTest {
dispatcher = AndroidAssetDispatcher()
start()
}
featureSettingsHelper.setJumpBackCFREnabled(false)
}
@After
fun tearDown() {
mockWebServer.shutdown()
// resetting modified features enabled setting to default
featureSettingsHelper.resetAllFeatureFlags()
}
private fun getUiTheme(): Boolean {
val mode =
activityIntentTestRule.activity.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK)
return when (mode) {
Configuration.UI_MODE_NIGHT_YES -> true // dark theme is set
Configuration.UI_MODE_NIGHT_NO -> false // dark theme is not set, using light theme
else -> false // default option is light theme
}
}
@Test
@ -82,13 +71,28 @@ class SettingsBasicsTest {
verifyHomepageButton()
verifyCustomizeButton()
verifyLoginsAndPasswordsButton()
verifyAutofillButton()
verifyCreditCardsButton()
verifyAccessibilityButton()
verifyLanguageButton()
verifySetAsDefaultBrowserButton()
}
}
@Test
fun changeThemeSetting() {
// Goes through the settings and changes the default search engine, then verifies it changes.
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openCustomizeSubMenu {
verifyThemes()
selectDarkMode()
verifyDarkThemeApplied(getUiTheme())
selectLightMode()
verifyLightThemeApplied(getUiTheme())
}
}
@Test
fun changeAccessibiltySettings() {
// Goes through the settings and changes the default text on a webpage, then verifies if the text has changed.
@ -118,179 +122,4 @@ class SettingsBasicsTest {
verifyMenuItemsAreDisabled()
}
}
@SmokeTest
@Test
fun verifyAddressAutofillTest() {
val addressFormPage =
TestAssetHelper.getAddressFormAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
clickAddAddressButton()
fillAndSaveAddress(
"Mozilla",
"Fenix",
"Firefox",
"Harrison Street",
"San Francisco",
"Alaska",
"94105",
"United States",
"555-5555",
"foo@bar.com",
)
}.goBack {
}.goBack {
}
navigationToolbar {
}.enterURLAndEnterToBrowser(addressFormPage.url) {
clickStreetAddressTextBox()
clickSelectAddressButton()
clickAddressSuggestion("Harrison Street")
verifyAutofilledAddress("Harrison Street")
}
}
@SmokeTest
@Test
fun deleteSavedAddressTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
clickAddAddressButton()
fillAndSaveAddress(
"Mozilla",
"Fenix",
"Firefox",
"Harrison Street",
"San Francisco",
"Alaska",
"94105",
"United States",
"555-5555",
"foo@bar.com",
)
clickManageAddressesButton()
clickSavedAddress("Mozilla")
clickDeleteAddressButton()
clickCancelDeleteAddressButton()
clickDeleteAddressButton()
clickConfirmDeleteAddressButton()
verifyAddAddressButton()
}
}
@SmokeTest
@Test
fun verifyCreditCardAutofillTest() {
val creditCardFormPage = TestAssetHelper.getCreditCardFormAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
clickAddCreditCardButton()
fillAndSaveCreditCard(MOCK_CREDIT_CARD_NUMBER, MOCK_NAME_ON_CARD, MOCK_EXPIRATION_MONTH, MOCK_EXPIRATION_YEAR)
// Opening Manage saved cards to dismiss here the Secure your credit prompt
clickManageSavedCardsButton()
clickSecuredCreditCardsLaterButton()
}.goBackToAutofillSettings {
}.goBack {
}.goBack {
}
navigationToolbar {
}.enterURLAndEnterToBrowser(creditCardFormPage.url) {
clickCardNumberTextBox()
clickSelectCreditCardButton()
clickCreditCardSuggestion(MOCK_LAST_CARD_DIGITS)
verifyAutofilledCreditCard(MOCK_CREDIT_CARD_NUMBER)
}
}
@SmokeTest
@Test
fun deleteSavedCreditCardTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openAutofillSubMenu {
clickAddCreditCardButton()
fillAndSaveCreditCard(MOCK_CREDIT_CARD_NUMBER, MOCK_NAME_ON_CARD, MOCK_EXPIRATION_MONTH, MOCK_EXPIRATION_YEAR)
clickManageSavedCardsButton()
clickSecuredCreditCardsLaterButton()
clickSavedCreditCard()
clickDeleteCreditCardButton()
clickConfirmDeleteCreditCardButton()
verifyAddCreditCardsButton()
}
}
@SmokeTest
@Test
fun switchLanguageTest() {
val enLanguageHeaderText = getStringResource(R.string.preferences_language)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openLanguageSubMenu {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(
activityIntentTestRule.activity.findViewById(R.id.locale_list),
2,
),
) {
selectLanguage("Romanian")
verifyLanguageHeaderIsTranslated(ROMANIAN_LANGUAGE_HEADER)
selectLanguage("Français")
verifyLanguageHeaderIsTranslated(FRENCH_LANGUAGE_HEADER)
selectLanguage(FRENCH_SYSTEM_LOCALE_OPTION)
verifyLanguageHeaderIsTranslated(enLanguageHeaderText)
}
}
}
@Test
fun searchInLanguagesListTest() {
val systemLocaleDefault = getStringResource(R.string.default_locale_text)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openLanguageSubMenu {
verifyLanguageListIsDisplayed()
openSearchBar()
typeInSearchBar("French")
verifySearchResultsContains(systemLocaleDefault)
clearSearchBar()
typeInSearchBar("French")
selectLanguageSearchResult("Français")
verifyLanguageHeaderIsTranslated(FRENCH_LANGUAGE_HEADER)
// Add this step when https://github.com/mozilla-mobile/fenix/issues/26733 is fixed
// verifyLanguageListIsDisplayed()
}
}
// Because it requires changing system prefs, this test will run only on Debug builds
@Ignore("Failing due to app translation bug, see: https://github.com/mozilla-mobile/fenix/issues/26729")
@Test
fun frenchSystemLocaleTest() {
val frenchLocale = Locale("fr", "FR")
runWithSystemLocaleChanged(frenchLocale, activityIntentTestRule) {
mDevice.waitForIdle(waitingTimeLong)
homeScreen {
}.openThreeDotMenu {
}.openSettings(localizedText = FR_SETTINGS) {
}.openLanguageSubMenu(localizedText = FRENCH_LANGUAGE_HEADER) {
verifyLanguageHeaderIsTranslated(FRENCH_LANGUAGE_HEADER)
verifySelectedLanguage(FRENCH_SYSTEM_LOCALE_OPTION)
}
}
}
}

View File

@ -1,122 +0,0 @@
package org.mozilla.fenix.ui
import android.content.res.Configuration
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
class SettingsCustomizeTest {
private lateinit var mockWebServer: MockWebServer
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
private fun getUiTheme(): Boolean {
val mode =
activityIntentTestRule.activity.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK)
return when (mode) {
Configuration.UI_MODE_NIGHT_YES -> true // dark theme is set
Configuration.UI_MODE_NIGHT_NO -> false // dark theme is not set, using light theme
else -> false // default option is light theme
}
}
@Test
fun changeThemeSettingTest() {
// Goes through the settings and changes the default search engine, then verifies it changes.
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openCustomizeSubMenu {
verifyThemes()
selectDarkMode()
verifyDarkThemeApplied(getUiTheme())
selectLightMode()
verifyLightThemeApplied(getUiTheme())
}
}
@Test
fun setToolbarPositionTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openCustomizeSubMenu {
verifyToolbarPositionPreference("Bottom")
clickTopToolbarToggle()
verifyToolbarPositionPreference("Top")
}.goBack {
}.goBack {
verifyToolbarPosition(defaultPosition = false)
}.openThreeDotMenu {
}.openSettings {
}.openCustomizeSubMenu {
clickBottomToolbarToggle()
verifyToolbarPositionPreference("Bottom")
exitMenu()
}
homeScreen {
verifyToolbarPosition(defaultPosition = true)
}
}
@Test
fun swipeToolbarGesturePreferenceOffTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openCustomizeSubMenu {
verifySwipeToolbarGesturePrefState(true)
clickSwipeToolbarToSwitchTabToggle()
verifySwipeToolbarGesturePrefState(false)
exitMenu()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
}.openTabDrawer {
}.openNewTab {
}.submitQuery(secondWebPage.url.toString()) {
swipeNavBarRight(secondWebPage.url.toString())
verifyUrl(secondWebPage.url.toString())
swipeNavBarLeft(secondWebPage.url.toString())
verifyUrl(secondWebPage.url.toString())
}
}
@Test
fun pullToRefreshPreferenceTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openCustomizeSubMenu {
verifyPullToRefreshGesturePrefState(isEnabled = true)
clickPullToRefreshToggle()
verifyPullToRefreshGesturePrefState(isEnabled = false)
}
}
}

View File

@ -7,10 +7,10 @@ package org.mozilla.fenix.ui
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Before
import org.junit.After
import org.junit.Ignore
import org.junit.Test
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
@ -24,7 +24,7 @@ import org.mozilla.fenix.ui.robots.homeScreen
class SettingsDeveloperToolsTest {
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
private lateinit var mDevice: UiDevice
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private lateinit var mockWebServer: MockWebServer
@get:Rule
@ -32,7 +32,6 @@ class SettingsDeveloperToolsTest {
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -44,8 +43,8 @@ class SettingsDeveloperToolsTest {
mockWebServer.shutdown()
}
// Walks through settings developer tools menu and sub-menus to ensure all items are present
@Test
// Walks through settings developer tools menu and sub-menus to ensure all items are present
fun settingsDeveloperToolsItemsTest() {
homeScreen {
}.openThreeDotMenu {

View File

@ -7,16 +7,14 @@ package org.mozilla.fenix.ui
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.openAppFromExternalLink
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
@ -28,9 +26,10 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
*/
class SettingsHomepageTest {
private lateinit var mockWebServer: MockWebServer
private val featureSettingsHelper = FeatureSettingsHelper()
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
val activityIntentTestRule = HomeActivityIntentTestRule(skipOnboarding = true)
@Rule
@JvmField
@ -42,83 +41,15 @@ class SettingsHomepageTest {
dispatcher = AndroidAssetDispatcher()
start()
}
featureSettingsHelper.setJumpBackCFREnabled(false)
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
@Test
fun verifyHomepageSettingsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openHomepageSubMenu {
verifyHomePageView()
}
}
@Test
fun verifyShortcutOptionTest() {
// en-US defaults
val defaultTopSites = arrayOf(
"Top Articles",
"Wikipedia",
"Google",
)
homeScreen {
defaultTopSites.forEach { item ->
verifyExistingTopSitesTabs(item)
}
}.openThreeDotMenu {
}.openCustomizeHome {
clickShortcutsButton()
}.goBack {
defaultTopSites.forEach { item ->
verifyNotExistingTopSitesList(item)
}
}
}
@Test
fun verifyRecentlyVisitedOptionTest() {
activityIntentTestRule.applySettingsExceptions {
it.isRecentTabsFeatureEnabled = false
}
val genericURL = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.goToHomescreen {
verifyRecentlyVisitedSectionIsDisplayed()
}.openThreeDotMenu {
}.openCustomizeHome {
clickRecentlyVisited()
}.goBack {
verifyRecentlyVisitedSectionIsNotDisplayed()
}
}
@Test
fun verifyPocketOptionTest() {
activityIntentTestRule.applySettingsExceptions {
it.isRecentTabsFeatureEnabled = false
it.isRecentlyVisitedFeatureEnabled = false
}
val genericURL = getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.goToHomescreen {
verifyPocketSectionIsDisplayed()
}.openThreeDotMenu {
}.openCustomizeHome {
clickPocketButton()
}.goBack {
verifyPocketSectionIsNotDisplayed()
}
// resetting modified features enabled setting to default
featureSettingsHelper.resetAllFeatureFlags()
}
@SmokeTest
@ -182,6 +113,19 @@ class SettingsHomepageTest {
fun startOnLastTabTest() {
val firstWebPage = getGenericAsset(mockWebServer, 1)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openHomepageSubMenu {
clickStartOnHomepageButton()
}
restartApp(activityIntentTestRule)
homeScreen {
verifyHomeScreen()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
}.goToHomescreen {
@ -197,39 +141,13 @@ class SettingsHomepageTest {
}
}
@Test
fun ignoreStartOnHomeWhenLaunchedByExternalLinkTest() {
val genericPage = getGenericAsset(mockWebServer, 1)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openHomepageSubMenu {
clickStartOnHomepageButton()
}.goBack {}
with(activityIntentTestRule) {
finishActivity()
mDevice.waitForIdle()
this.applySettingsExceptions {
it.isTCPCFREnabled = false
}
openAppFromExternalLink(genericPage.url.toString())
}
browserScreen {
verifyPageContent(genericPage.content)
}
}
@SmokeTest
@Test
@Ignore("Intermittent test: https://github.com/mozilla-mobile/fenix/issues/26559")
fun setWallpaperTest() {
val wallpapers = listOf(
"Wallpaper Item: amethyst",
"Wallpaper Item: cerulean",
"Wallpaper Item: sunrise",
"Wallpaper Item: sunrise"
)
for (wallpaper in wallpapers) {

View File

@ -7,29 +7,24 @@ package org.mozilla.fenix.ui
import android.os.Build
import android.view.autofill.AutofillManager
import androidx.core.net.toUri
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestAssetHelper.getStorageTestAsset
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.generateRandomString
import org.mozilla.fenix.helpers.TestHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.openAppFromExternalLink
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.setNetworkEnabled
import org.mozilla.fenix.ui.robots.addToHomeScreen
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
@ -44,22 +39,24 @@ import org.mozilla.fenix.ui.robots.settingsScreen
class SettingsPrivacyTest {
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
private lateinit var mDevice: UiDevice
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private lateinit var mockWebServer: MockWebServer
private val pageShortcutName = generateRandomString(5)
private val pageShortcutName = "TestShortcut"
private val featureSettingsHelper = FeatureSettingsHelper()
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
val activityTestRule = HomeActivityIntentTestRule()
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
appContext.settings().userOptOutOfReEngageCookieBannerDialog = true
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
featureSettingsHelper.setJumpBackCFREnabled(false)
featureSettingsHelper.disablePwaCFR(true)
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) {
val autofillManager: AutofillManager =
appContext.getSystemService(AutofillManager::class.java)
@ -72,8 +69,8 @@ class SettingsPrivacyTest {
mockWebServer.shutdown()
}
// Walks through settings privacy menu and sub-menus to ensure all items are present
@Test
// Walks through settings privacy menu and sub-menus to ensure all items are present
fun settingsPrivacyItemsTest() {
homeScreen {
}.openThreeDotMenu {
@ -103,6 +100,7 @@ class SettingsPrivacyTest {
verifyEnhancedTrackingProtectionProtectionExceptionsSubMenuItems()
}.goBack {
}.goBack {
// SITE PERMISSIONS
verifySitePermissionsButton()
}.openSettingsSubMenuSitePermissions {
@ -114,46 +112,54 @@ class SettingsPrivacyTest {
verifyNavigationToolBarHeader("Autoplay")
verifySitePermissionsAutoPlaySubMenuItems()
}.goBack {
// SITE PERMISSIONS CAMERA
}.openCamera {
verifyNavigationToolBarHeader("Camera")
verifySitePermissionsCommonSubMenuItems()
verifyToggleNameToON("3. Toggle Camera to ON")
}.goBack {
// SITE PERMISSIONS LOCATION
}.openLocation {
verifyNavigationToolBarHeader("Location")
verifySitePermissionsCommonSubMenuItems()
verifyToggleNameToON("3. Toggle Location to ON")
}.goBack {
// SITE PERMISSIONS MICROPHONE
}.openMicrophone {
verifyNavigationToolBarHeader("Microphone")
verifySitePermissionsCommonSubMenuItems()
verifyToggleNameToON("3. Toggle Microphone to ON")
}.goBack {
// SITE PERMISSIONS NOTIFICATION
}.openNotification {
verifyNavigationToolBarHeader("Notification")
verifySitePermissionsNotificationSubMenuItems()
}.goBack {
// SITE PERMISSIONS PERSISTENT STORAGE
}.openPersistentStorage {
verifyNavigationToolBarHeader("Persistent Storage")
verifySitePermissionsPersistentStorageSubMenuItems()
}.goBack {
// SITE PERMISSIONS EXCEPTIONS
}.openExceptions {
verifyNavigationToolBarHeader()
verifySitePermissionsExceptionSubMenuItems()
}.goBack {
}.goBack {
// DELETE BROWSING DATA
verifyDeleteBrowsingDataButton()
}.openSettingsSubMenuDeleteBrowsingData {
verifyNavigationToolBarHeader()
verifyDeleteBrowsingDataSubMenuItems()
}.goBack {
// DELETE BROWSING DATA ON QUIT
verifyDeleteBrowsingDataOnQuitButton()
verifyDeleteBrowsingDataOnQuitState("Off")
@ -161,11 +167,13 @@ class SettingsPrivacyTest {
verifyNavigationToolBarHeader()
verifyDeleteBrowsingDataOnQuitSubMenuItems()
}.goBack {
// NOTIFICATIONS
verifyNotificationsButton()
}.openSettingsSubMenuNotifications {
verifySystemNotificationsView()
}.goBack {
// DATA COLLECTION
verifyDataCollectionButton()
}.openSettingsSubMenuDataCollection {
@ -231,6 +239,8 @@ class SettingsPrivacyTest {
@Test
fun neverSaveLoginFromPromptTest() {
val saveLoginTest = TestAssetHelper.getSaveLoginAsset(mockWebServer)
val settings = activityTestRule.activity.settings()
settings.shouldShowJumpBackInCFR = false
navigationToolbar {
}.enterURLAndEnterToBrowser(saveLoginTest.url) {
@ -322,6 +332,7 @@ class SettingsPrivacyTest {
}
}
@Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/24573")
@Test
fun openExternalLinksInPrivateTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -332,7 +343,6 @@ class SettingsPrivacyTest {
openAppFromExternalLink(firstWebPage.url.toString())
browserScreen {
verifyUrl(firstWebPage.url.toString())
}.openTabDrawer {
verifyPrivateModeSelected()
}.closeTabDrawer {
@ -344,7 +354,6 @@ class SettingsPrivacyTest {
openAppFromExternalLink(secondWebPage.url.toString())
browserScreen {
verifyUrl(secondWebPage.url.toString())
}.openTabDrawer {
verifyNormalModeSelected()
}
@ -381,8 +390,11 @@ class SettingsPrivacyTest {
}
}
@Ignore("Failing with frequent ANR: https://bugzilla.mozilla.org/show_bug.cgi?id=1764605")
@Test
fun launchLinksInPrivateToggleOffStateDoesntChangeTest() {
val settings = activityTestRule.activity.applicationContext.settings()
settings.shouldShowJumpBackInCFR = false
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
setOpenLinksInPrivateOn()
@ -431,45 +443,6 @@ class SettingsPrivacyTest {
}
}
// Verifies that you can go to System settings and change app's permissions from inside the app
@SmokeTest
@Test
@SdkSuppress(minSdkVersion = 29)
fun redirectToAppPermissionsSystemSettingsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSettingsSubMenuSitePermissions {
}.openCamera {
verifyBlockedByAndroid()
}.goBack {
}.openLocation {
verifyBlockedByAndroid()
}.goBack {
}.openMicrophone {
verifyBlockedByAndroid()
clickGoToSettingsButton()
openAppSystemPermissionsSettings()
switchAppPermissionSystemSetting("Camera", "Allow")
goBackToSystemAppPermissionSettings()
verifySystemGrantedPermission("Camera")
switchAppPermissionSystemSetting("Location", "Allow")
goBackToSystemAppPermissionSettings()
verifySystemGrantedPermission("Location")
switchAppPermissionSystemSetting("Microphone", "Allow")
goBackToSystemAppPermissionSettings()
verifySystemGrantedPermission("Microphone")
goBackToPermissionsSettingsSubMenu()
verifyUnblockedByAndroid()
}.goBack {
}.openLocation {
verifyUnblockedByAndroid()
}.goBack {
}.openCamera {
verifyUnblockedByAndroid()
}
}
@Test
fun deleteBrowsingDataOptionStatesTest() {
homeScreen {
@ -576,16 +549,16 @@ class SettingsPrivacyTest {
@SmokeTest
@Test
fun deleteBrowsingHistoryAndSiteDataTest() {
val storageWritePage = getStorageTestAsset(mockWebServer, "storage_write.html").url
val storageCheckPage = getStorageTestAsset(mockWebServer, "storage_check.html").url
fun deleteDeleteBrowsingHistoryDataTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(storageWritePage) {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
mDevice.waitForIdle()
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(storageCheckPage) {
verifyPageContent("Session storage has value")
verifyPageContent("Local storage has value")
}.enterURLAndEnterToBrowser(secondWebPage.url) {
mDevice.waitForIdle()
}.openThreeDotMenu {
}.openSettings {
}.openSettingsSubMenuDeleteBrowsingData {
@ -597,79 +570,15 @@ class SettingsPrivacyTest {
clickDeleteBrowsingDataButton()
confirmDeletionAndAssertSnackbar()
verifyBrowsingHistoryDetails("0")
exitMenu()
}.goBack {
verifyGeneralHeading()
}.goBack {
}
navigationToolbar {
}.openThreeDotMenu {
}.openHistory {
verifyEmptyHistoryView()
mDevice.pressBack()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(storageCheckPage) {
verifyPageContent("Session storage empty")
verifyPageContent("Local storage empty")
}
}
@SmokeTest
@Test
fun deleteCookiesTest() {
val genericPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val cookiesTestPage = getStorageTestAsset(mockWebServer, "storage_write.html").url
// Browsing a generic page to allow GV to load on a fresh run
navigationToolbar {
}.enterURLAndEnterToBrowser(genericPage.url) {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(cookiesTestPage) {
verifyPageContent("No cookies set")
clickSetCookiesButton()
verifyPageContent("user=android")
}.openThreeDotMenu {
}.openSettings {
}.openSettingsSubMenuDeleteBrowsingData {
selectOnlyCookiesCheckBox()
clickDeleteBrowsingDataButton()
confirmDeletionAndAssertSnackbar()
exitMenu()
}
browserScreen {
}.openThreeDotMenu {
}.refreshPage {
verifyPageContent("No cookies set")
}
}
@SmokeTest
@Test
fun deleteCachedFilesTest() {
val pocketTopArticles = getStringResource(R.string.pocket_pinned_top_articles)
homeScreen {
verifyExistingTopSitesTabs(pocketTopArticles)
}.openTopSiteTabWithTitle(pocketTopArticles) {
waitForPageToLoad()
}.openTabDrawer {
}.openNewTab {
}.submitQuery("about:cache") {
// disabling wifi to prevent downloads in the background
setNetworkEnabled(enabled = false)
}.openThreeDotMenu {
}.openSettings {
}.openSettingsSubMenuDeleteBrowsingData {
selectOnlyCachedFilesCheckBox()
clickDeleteBrowsingDataButton()
confirmDeletionAndAssertSnackbar()
exitMenu()
}
browserScreen {
}.openThreeDotMenu {
}.refreshPage {
verifyNetworkCacheIsEmpty("memory")
verifyNetworkCacheIsEmpty("disk")
}
setNetworkEnabled(enabled = true)
}
@SmokeTest

View File

@ -7,28 +7,24 @@ import org.junit.Before
import org.junit.Ignore
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.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
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.exitMenu
import org.mozilla.fenix.helpers.TestHelper.setTextToClipBoard
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.util.ARABIC_LANGUAGE_HEADER
class SettingsSearchTest {
private lateinit var mockWebServer: MockWebServer
private lateinit var searchMockServer: MockWebServer
private val featureSettingsHelper = FeatureSettingsHelper()
@get:Rule
val activityTestRule = AndroidComposeTestRule(
HomeActivityIntentTestRule.withDefaultSettingsOverrides(),
HomeActivityIntentTestRule()
) { it.activity }
@Before
@ -37,11 +33,15 @@ class SettingsSearchTest {
dispatcher = AndroidAssetDispatcher()
start()
}
featureSettingsHelper.setJumpBackCFREnabled(false)
}
@After
fun tearDown() {
mockWebServer.shutdown()
// resetting modified features enabled setting to default
featureSettingsHelper.resetAllFeatureFlags()
}
@Test
@ -53,11 +53,6 @@ class SettingsSearchTest {
verifySearchToolbar()
verifyDefaultSearchEngineHeader()
verifySearchEngineList()
verifyShowSearchSuggestions()
verifyShowSearchShortcuts()
verifySearchBrowsingHistory()
verifySearchBookmarks()
verifyShowClipboardSuggestionsDefault()
}
}
@ -75,27 +70,6 @@ class SettingsSearchTest {
}
}
@Test
fun toggleSearchAutocomplete() {
homeScreen {
}.openSearch {
typeSearch("mo")
verifyTypedToolbarText("monster.com")
typeSearch("moz")
verifyTypedToolbarText("mozilla.org")
}.dismissSearchBar {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
toggleAutocomplete()
}.goBack {
}.goBack {
}.openSearch {
typeSearch("moz")
verifyTypedToolbarText("moz")
}
}
@Test
fun toggleSearchBookmarksAndHistoryTest() {
// Bookmarks 2 websites, toggles the bookmarks and history search settings off,
@ -124,9 +98,8 @@ class SettingsSearchTest {
}.openSearch {
typeSearch("test")
expandSearchSuggestionsList()
verifyFirefoxSuggestResults(activityTestRule, "Firefox Suggest")
verifyFirefoxSuggestResults(activityTestRule, "Test_Page_1")
verifyFirefoxSuggestResults(activityTestRule, "Test_Page_2")
verifySearchEngineSuggestionResults(activityTestRule, "Test_Page_1")
verifySearchEngineSuggestionResults(activityTestRule, "Test_Page_2")
}.dismissSearchBar {
}.openThreeDotMenu {
}.openSettings {
@ -142,15 +115,14 @@ class SettingsSearchTest {
}.openSearch {
typeSearch("test")
expandSearchSuggestionsList()
verifyNoSuggestionsAreDisplayed(activityTestRule, "Firefox Suggest")
verifyNoSuggestionsAreDisplayed(activityTestRule, "Test_Page_1")
verifyNoSuggestionsAreDisplayed(activityTestRule, "Test_Page_2")
}
}
// Ads a new search engine from the list of custom engines
@SmokeTest
@Test
// Ads a new search engine from the list of custom engines
fun addPredefinedSearchEngineTest() {
val searchEngine = "Reddit"
@ -174,9 +146,9 @@ class SettingsSearchTest {
}
}
// Verifies setting as default a customized search engine name and URL
@SmokeTest
@Test
// Verifies setting as default a customized search engine name and URL
fun editCustomSearchEngineTest() {
searchMockServer = MockWebServer().apply {
dispatcher = SearchDispatcher()
@ -210,13 +182,14 @@ class SettingsSearchTest {
}
}
// 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
// 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.
fun toggleSearchSuggestionsTest() {
homeScreen {
}.openSearch {
typeSearch("mozilla")
@ -225,48 +198,7 @@ class SettingsSearchTest {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
toggleShowSearchSuggestions()
}.goBack {
}.goBack {
}.openSearch {
typeSearch("mozilla")
verifyNoSuggestionsAreDisplayed(activityTestRule, "mozilla firefox")
}
}
// Tests the "Don't allow" option from private mode search suggestions onboarding dialog
@Test
fun blockSearchSuggestionsInPrivateModeOnboardingTest() {
homeScreen {
togglePrivateBrowsingModeOnOff()
}.openSearch {
typeSearch("mozilla")
verifyAllowSuggestionsInPrivateModeDialog()
denySuggestionsInPrivateMode()
verifyNoSuggestionsAreDisplayed(activityTestRule, "mozilla firefox")
}.dismissSearchBar {
togglePrivateBrowsingModeOnOff()
}.openSearch {
typeSearch("mozilla")
verifySearchEngineSuggestionResults(activityTestRule, "mozilla firefox")
}
}
// Tests the "Allow" option from private mode search suggestions onboarding dialog
@Test
fun allowSearchSuggestionsInPrivateModeOnboardingTest() {
homeScreen {
togglePrivateBrowsingModeOnOff()
}.openSearch {
typeSearch("mozilla")
verifyAllowSuggestionsInPrivateModeDialog()
allowSuggestionsInPrivateMode()
verifySearchEngineSuggestionResults(activityTestRule, "mozilla firefox")
}.dismissSearchBar {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
toggleShowSuggestionsInPrivateSessions()
disableShowSearchSuggestions()
}.goBack {
}.goBack {
}.openSearch {
@ -294,194 +226,4 @@ class SettingsSearchTest {
verifyVoiceSearchButtonVisibility(false)
}
}
@Test
fun toggleShowClipboardSuggestionsTest() {
val link = "https://www.mozilla.org/en-US/"
setTextToClipBoard(appContext, link)
homeScreen {
}.openNavigationToolbar {
verifyClipboardSuggestionsAreDisplayed(link, true)
}.visitLinkFromClipboard {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
verifyShowClipboardSuggestionsDefault()
toggleClipboardSuggestion()
exitMenu()
}
homeScreen {
}.openNavigationToolbar {
verifyClipboardSuggestionsAreDisplayed(link, false)
}
}
// Expected for en-us defaults
@Test
fun undoDeleteSearchEngineTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
verifyEngineListContains("Bing")
openEngineOverflowMenu("Bing")
clickDeleteSearchEngine()
clickUndoSnackBarButton()
verifyEngineListContains("Bing")
}
}
// Expected for en-us defaults
@Test
fun deleteDefaultSearchEngineTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
verifyEngineListContains("Google")
verifyDefaultSearchEngine("Google")
openEngineOverflowMenu("Google")
clickDeleteSearchEngine()
verifyEngineListDoesNotContain("Google")
verifyDefaultSearchEngine("Bing")
}
}
// Expected for en-us defaults
@Test
fun deleteAllSearchEnginesTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
deleteMultipleSearchEngines(
"Google",
"Bing",
"Amazon.com",
"DuckDuckGo",
"eBay",
)
verifyDefaultSearchEngine("Wikipedia")
verifyThreeDotButtonIsNotDisplayed("Wikipedia")
openAddSearchEngineMenu()
verifyAddSearchEngineListContains(
"Google",
"Bing",
"Amazon.com",
"DuckDuckGo",
"eBay",
)
}
}
// Expected for en-us defaults
@Test
fun changeSearchEnginesBasedOnTextTest() {
homeScreen {
}.openSearch {
typeSearch("D")
verifySearchEnginePrompt(activityTestRule, "DuckDuckGo")
clickSearchEnginePrompt(activityTestRule, "DuckDuckGo")
}.submitQuery("firefox") {
verifyUrl("duckduckgo.com/?q=firefox")
}
}
// Expected for app language set to Arabic
@Test
fun verifySearchEnginesWithRTLLocale() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
toggleShowSearchShortcuts()
}.goBack {
}.openLanguageSubMenu {
TestHelper.registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(
activityTestRule.activity.findViewById(R.id.locale_list),
2,
),
) {
selectLanguage("Arabic")
verifyLanguageHeaderIsTranslated(ARABIC_LANGUAGE_HEADER)
}
}
exitMenu()
homeScreen {
}.openSearch {
verifyTranslatedFocusedNavigationToolbar("ابحث أو أدخِل عنوانا")
verifySearchEngineShortcuts(
activityTestRule,
"Google",
"Bing",
"Amazon.com",
"DuckDuckGo",
"ويكيبيديا (ar)",
)
changeDefaultSearchEngine(activityTestRule, "ويكيبيديا (ar)")
}.submitQuery("firefox") {
verifyUrl("ar.m.wikipedia.org")
}
}
// Expected for en-us defaults
@Test
fun toggleSearchEnginesShortcutListTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
verifyShowSearchEnginesToggleState(false)
toggleShowSearchShortcuts()
verifyShowSearchEnginesToggleState(true)
}
exitMenu()
homeScreen {
}.openSearch {
verifySearchEngineShortcuts(
activityTestRule,
"Google",
"Bing",
"Amazon.com",
"DuckDuckGo",
"eBay",
"Wikipedia",
)
scrollToSearchEngineSettings(activityTestRule)
}.clickSearchEngineSettings(activityTestRule) {
toggleShowSearchShortcuts()
verifyShowSearchEnginesToggleState(false)
}
exitMenu()
homeScreen {
}.openSearch {
verifySearchEngineShortcutsAreNotDisplayed(
activityTestRule,
"Google",
"Bing",
"Amazon.com",
"DuckDuckGo",
"eBay",
"Wikipedia",
)
clickSearchEngineShortcutButton()
verifySearchEngineShortcuts(
activityTestRule,
"Google",
"Bing",
"Amazon.com",
"DuckDuckGo",
"eBay",
"Wikipedia",
)
}
}
}

View File

@ -7,10 +7,10 @@ package org.mozilla.fenix.ui
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Before
import org.junit.After
import org.junit.Ignore
import org.junit.Test
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
@ -23,7 +23,7 @@ import org.mozilla.fenix.helpers.HomeActivityTestRule
class SettingsSyncTest {
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
private lateinit var mDevice: UiDevice
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private lateinit var mockWebServer: MockWebServer
@get:Rule
@ -31,7 +31,6 @@ class SettingsSyncTest {
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -43,9 +42,9 @@ class SettingsSyncTest {
mockWebServer.shutdown()
}
// Walks through settings sync menu and sub-menus to ensure all items are present
@Ignore("This is a stub test, ignore for now")
@Test
// Walks through settings sync menu and sub-menus to ensure all items are present
fun settingsSyncItemsTest() {
// SYNC

View File

@ -7,10 +7,10 @@ package org.mozilla.fenix.ui
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Before
import org.junit.After
import org.junit.Ignore
import org.junit.Test
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
@ -23,7 +23,7 @@ import org.mozilla.fenix.helpers.HomeActivityTestRule
class SettingsTest {
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
private lateinit var mDevice: UiDevice
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private lateinit var mockWebServer: MockWebServer
@get:Rule
@ -31,7 +31,6 @@ class SettingsTest {
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -43,9 +42,9 @@ class SettingsTest {
mockWebServer.shutdown()
}
// Walks through settings menu and sub-menus to ensure all items are present
@Ignore("This is a stub test, ignore for now")
@Test
// Walks through settings menu and sub-menus to ensure all items are present
fun settingsMenusItemsTest() {
// SYNC

View File

@ -6,20 +6,18 @@ package org.mozilla.fenix.ui
import android.Manifest
import android.content.Context
import android.hardware.camera2.CameraManager
import android.media.AudioManager
import android.os.Build
import androidx.core.net.toUri
import androidx.test.filters.SdkSuppress
import androidx.test.rule.GrantPermissionRule
import org.junit.Assume.assumeTrue
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.components.PermissionStorage
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MockLocationUpdatesRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -31,36 +29,39 @@ class SitePermissionsTest {
/* Test page created and handled by the Mozilla mobile test-eng team */
private val testPage = "https://mozilla-mobile.github.io/testapp/permissions"
private val testPageSubstring = "https://mozilla-mobile.github.io:443"
private val cameraManager = appContext.getSystemService(Context.CAMERA_SERVICE) as CameraManager
private val micManager = appContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager
private val featureSettingsHelper = FeatureSettingsHelper()
@get:Rule
val activityTestRule = HomeActivityTestRule(
isJumpBackInCFREnabled = false,
isPWAsPromptEnabled = false,
isTCPCFREnabled = false,
isDeleteSitePermissionsEnabled = true,
)
val activityTestRule = HomeActivityTestRule()
@get:Rule
val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.CAMERA
)
@get: Rule
val mockLocationUpdatesRule = MockLocationUpdatesRule()
@Before
fun setUp() {
// disabling the new homepage pop-up that interferes with the tests.
featureSettingsHelper.setJumpBackCFREnabled(false)
featureSettingsHelper.deleteSitePermissions(true)
}
@get: Rule
val retryTestRule = RetryTestRule(3)
@After
fun tearDown() {
// Clearing all permission data after each test to avoid overlapping data
val applicationContext: Context = activityTestRule.activity.applicationContext
val permissionStorage = PermissionStorage(applicationContext)
runBlocking {
permissionStorage.deleteAllSitePermissions()
}
}
@SdkSuppress(maxSdkVersion = Build.VERSION_CODES.P, codeName = "P")
@SmokeTest
@Test
@Ignore("Firebase - No camera and microphone on AVD")
fun audioVideoPermissionChoiceOnEachRequestTest() {
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.toUri()) {
waitForPageToLoad()
@ -76,10 +77,8 @@ class SitePermissionsTest {
@SmokeTest
@Test
@Ignore("Firebase - No camera and microphone on AVD, see also https://github.com/mozilla-mobile/fenix/issues/23298")
fun rememberBlockAudioVideoPermissionChoiceTest() {
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
assumeTrue(micManager.microphones.isNotEmpty())
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.toUri()) {
waitForPageToLoad()
@ -97,12 +96,10 @@ class SitePermissionsTest {
}
}
@Ignore("Firebase - No camera and microphone on AVD, see also https://github.com/mozilla-mobile/fenix/issues/23298")
@SmokeTest
@Test
fun rememberAllowAudioVideoPermissionChoiceTest() {
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
assumeTrue(micManager.microphones.isNotEmpty())
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.toUri()) {
waitForPageToLoad()
@ -121,9 +118,8 @@ class SitePermissionsTest {
}
@Test
@Ignore("Firebase - No camera and microphone on AVD")
fun microphonePermissionChoiceOnEachRequestTest() {
assumeTrue(micManager.microphones.isNotEmpty())
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.toUri()) {
waitForPageToLoad()
@ -138,9 +134,8 @@ class SitePermissionsTest {
}
@Test
@Ignore("Firebase - No camera and microphone on AVD")
fun rememberBlockMicrophonePermissionChoiceTest() {
assumeTrue(micManager.microphones.isNotEmpty())
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.toUri()) {
waitForPageToLoad()
@ -158,10 +153,9 @@ class SitePermissionsTest {
}
}
@Ignore("Flaky, needs investigation: https://github.com/mozilla-mobile/fenix/issues/23298")
@Test
fun rememberAllowMicrophonePermissionChoiceTest() {
assumeTrue(micManager.microphones.isNotEmpty())
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.toUri()) {
waitForPageToLoad()
@ -180,9 +174,8 @@ class SitePermissionsTest {
}
@Test
@Ignore("Firebase - No camera and microphone on AVD")
fun cameraPermissionChoiceOnEachRequestTest() {
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.toUri()) {
waitForPageToLoad()
@ -197,9 +190,8 @@ class SitePermissionsTest {
}
@Test
@Ignore("Firebase - No camera and microphone on AVD")
fun rememberBlockCameraPermissionChoiceTest() {
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.toUri()) {
waitForPageToLoad()
@ -218,9 +210,8 @@ class SitePermissionsTest {
}
@Test
@Ignore("Firebase - No camera and microphone on AVD")
fun rememberAllowCameraPermissionChoiceTest() {
assumeTrue(cameraManager.cameraIdList.isNotEmpty())
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.toUri()) {
waitForPageToLoad()
@ -265,20 +256,20 @@ class SitePermissionsTest {
}
}
@Ignore("Needs mocking location for Firebase - to do: https://github.com/mozilla-mobile/mobile-test-eng/issues/585")
@Test
fun allowLocationPermissionsTest() {
mockLocationUpdatesRule.setMockLocation()
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.toUri()) {
}.clickGetLocationButton {
verifyLocationPermissionPrompt(testPageSubstring)
}.clickPagePermissionButton(true) {
verifyPageContent("${mockLocationUpdatesRule.latitude}")
verifyPageContent("${mockLocationUpdatesRule.longitude}")
verifyPageContent("longitude")
verifyPageContent("latitude")
}
}
@Ignore("Needs mocking location for Firebase - to do: https://github.com/mozilla-mobile/mobile-test-eng/issues/585")
@Test
fun blockLocationPermissionsTest() {
navigationToolbar {

View File

@ -9,6 +9,8 @@ package org.mozilla.fenix.ui
import android.view.View
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.core.net.toUri
import androidx.test.espresso.IdlingRegistry
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.uiautomator.UiDevice
@ -17,6 +19,7 @@ import mozilla.components.concept.engine.mediasession.MediaSession
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.IntentReceiverActivity
@ -24,8 +27,8 @@ 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.Constants.PackageName.YOUTUBE_APP
import org.mozilla.fenix.helpers.FeatureSettingsHelperDelegate
import org.mozilla.fenix.helpers.Constants
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.RetryTestRule
@ -34,16 +37,20 @@ import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.appName
import org.mozilla.fenix.helpers.TestHelper.assertNativeAppOpens
import org.mozilla.fenix.helpers.TestHelper.createCustomTabIntent
import org.mozilla.fenix.helpers.TestHelper.generateRandomString
import org.mozilla.fenix.helpers.TestHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText
import org.mozilla.fenix.helpers.ViewVisibilityIdlingResource
import org.mozilla.fenix.ui.robots.browserScreen
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.navigationToolbar
import org.mozilla.fenix.ui.robots.notificationShade
import org.mozilla.fenix.ui.robots.openEditURLView
import org.mozilla.fenix.ui.robots.searchScreen
import org.mozilla.fenix.ui.util.FRENCH_LANGUAGE_HEADER
import org.mozilla.fenix.ui.util.FRENCH_SYSTEM_LOCALE_OPTION
import org.mozilla.fenix.ui.util.ROMANIAN_LANGUAGE_HEADER
import org.mozilla.fenix.ui.util.STRING_ONBOARDING_TRACKING_PROTECTION_HEADER
/**
* Test Suite that contains a part of the Smoke and Sanity tests defined in TestRail:
@ -54,26 +61,30 @@ import org.mozilla.fenix.ui.robots.searchScreen
@Suppress("ForbiddenComment")
@SmokeTest
class SmokeTest {
private lateinit var mDevice: UiDevice
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private lateinit var mockWebServer: MockWebServer
private var awesomeBar: ViewVisibilityIdlingResource? = null
private var addonsListIdlingResource: RecyclerViewIdlingResource? = null
private var recentlyClosedTabsListIdlingResource: RecyclerViewIdlingResource? = null
private var readerViewNotification: ViewVisibilityIdlingResource? = null
private var bookmarksListIdlingResource: RecyclerViewIdlingResource? = null
private var localeListIdlingResource: RecyclerViewIdlingResource? = null
private val customMenuItem = "TestMenuItem"
private lateinit var browserStore: BrowserStore
private val featureSettingsHelper = FeatureSettingsHelperDelegate()
private val featureSettingsHelper = FeatureSettingsHelper()
@get:Rule(order = 0)
@get:Rule
val activityTestRule = AndroidComposeTestRule(
HomeActivityIntentTestRule(),
{ it.activity },
{ it.activity }
)
@get: Rule(order = 1)
@get: Rule
val intentReceiverActivityTestRule = ActivityTestRule(
IntentReceiverActivity::class.java,
true,
false,
IntentReceiverActivity::class.java, true, false
)
@Rule(order = 2)
@Rule
@JvmField
val retryTestRule = RetryTestRule(3)
@ -84,13 +95,8 @@ class SmokeTest {
browserStore = activityTestRule.activity.components.core.store
// disabling the new homepage pop-up that interferes with the tests.
featureSettingsHelper.apply {
isJumpBackInCFREnabled = false
isTCPCFREnabled = false
isWallpaperOnboardingEnabled = false
}.applyFlagUpdates()
featureSettingsHelper.setJumpBackCFREnabled(false)
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -101,6 +107,30 @@ class SmokeTest {
fun tearDown() {
mockWebServer.shutdown()
if (awesomeBar != null) {
IdlingRegistry.getInstance().unregister(awesomeBar!!)
}
if (addonsListIdlingResource != null) {
IdlingRegistry.getInstance().unregister(addonsListIdlingResource!!)
}
if (recentlyClosedTabsListIdlingResource != null) {
IdlingRegistry.getInstance().unregister(recentlyClosedTabsListIdlingResource!!)
}
if (bookmarksListIdlingResource != null) {
IdlingRegistry.getInstance().unregister(bookmarksListIdlingResource!!)
}
if (readerViewNotification != null) {
IdlingRegistry.getInstance().unregister(readerViewNotification)
}
if (localeListIdlingResource != null) {
IdlingRegistry.getInstance().unregister(localeListIdlingResource)
}
// resetting modified features enabled setting to default
featureSettingsHelper.resetAllFeatureFlags()
}
@ -109,24 +139,46 @@ class SmokeTest {
@Test
fun firstRunScreenTest() {
homeScreen {
verifyHomeScreenAppBarItems()
verifyHomeScreenWelcomeItems()
verifyChooseYourThemeCard(
isDarkThemeChecked = false,
isLightThemeChecked = false,
isAutomaticThemeChecked = true,
)
verifyToolbarPlacementCard(isBottomChecked = true, isTopChecked = false)
verifySignInToSyncCard()
verifyPrivacyProtectionCard(isStandardChecked = true, isStrictChecked = false)
verifyPrivacyNoticeCard()
verifyStartBrowsingSection()
verifyNavigationToolbarItems("0")
verifyHomeScreen()
verifyNavigationToolbar()
verifyHomePrivateBrowsingButton()
verifyHomeMenu()
verifyHomeWordmark()
verifyWelcomeHeader()
// Sign in to Firefox
verifyStartSyncHeader()
verifyAccountsSignInButton()
// Always-on privacy
scrollToElementByText(STRING_ONBOARDING_TRACKING_PROTECTION_HEADER)
verifyAutomaticPrivacyHeader()
verifyAutomaticPrivacyText()
// Choose your theme
verifyChooseThemeHeader()
verifyChooseThemeText()
verifyDarkThemeDescription()
verifyDarkThemeToggle()
verifyLightThemeDescription()
verifyLightThemeToggle()
// Pick your toolbar placement
verifyTakePositionHeader()
verifyTakePositionElements()
// Your privacy
verifyYourPrivacyHeader()
verifyYourPrivacyText()
verifyPrivacyNoticeButton()
// Start Browsing
verifyStartBrowsingButton()
}
}
// Verifies the functionality of the onboarding Start Browsing button
@Test
// Verifies the functionality of the onboarding Start Browsing button
fun startBrowsingButtonTest() {
homeScreen {
verifyStartBrowsingButton()
@ -135,6 +187,7 @@ class SmokeTest {
}
}
@Test
/* Verifies the nav bar:
- opening a web page
- the existence of nav bar items
@ -142,7 +195,6 @@ class SmokeTest {
- the tab drawer button
- opening a new search and dismissing the nav bar
*/
@Test
fun verifyBasicNavigationToolbarFunctionality() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -162,22 +214,21 @@ class SmokeTest {
}
}
// Verifies the list of items in a tab's 3 dot menu
@Test
// Verifies the list of items in a tab's 3 dot menu
fun verifyPageMainMenuItemsTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
waitForPageToLoad()
}.openThreeDotMenu {
verifyPageThreeDotMainMenuItems(isRequestDesktopSiteEnabled = false)
verifyPageThreeDotMainMenuItems()
}
}
// Could be removed when more smoke tests from the History category are added
// Verifies the History menu opens from a tab's 3 dot menu
@Test
// Verifies the History menu opens from a tab's 3 dot menu
fun openMainMenuHistoryItemTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -190,8 +241,8 @@ class SmokeTest {
}
// Could be removed when more smoke tests from the Bookmarks category are added
// Verifies the Bookmarks menu opens from a tab's 3 dot menu
@Test
// Verifies the Bookmarks menu opens from a tab's 3 dot menu
fun openMainMenuBookmarksItemTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -203,8 +254,8 @@ class SmokeTest {
}
}
// Verifies the Add-ons menu opens from a tab's 3 dot menu
@Test
// Verifies the Add-ons menu opens from a tab's 3 dot menu
fun openMainMenuAddonsTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -212,17 +263,20 @@ class SmokeTest {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
}.openThreeDotMenu {
}.openAddonsManagerMenu {
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.add_ons_list), 1),
) {
verifyAddonsItems()
}
addonsListIdlingResource =
RecyclerViewIdlingResource(
activityTestRule.activity.findViewById(R.id.add_ons_list),
1
)
IdlingRegistry.getInstance().register(addonsListIdlingResource!!)
verifyAddonsItems()
IdlingRegistry.getInstance().unregister(addonsListIdlingResource!!)
}
}
@Test
// Verifies the Synced tabs menu or Sync Sign In menu opens from a tab's 3 dot menu.
// The test is assuming we are NOT signed in.
@Test
fun openMainMenuSyncItemTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -235,10 +289,10 @@ class SmokeTest {
}
}
@Test
// Test running on beta/release builds in CI:
// caution when making changes to it, so they don't block the builds
// Verifies the Settings menu opens from a tab's 3 dot menu
@Test
fun openMainMenuSettingsItemTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -250,8 +304,8 @@ class SmokeTest {
}
}
// Verifies the Find in page option in a tab's 3 dot menu
@Test
// Verifies the Find in page option in a tab's 3 dot menu
fun openMainMenuFindInPageTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -263,11 +317,10 @@ class SmokeTest {
}
}
// Verifies the Add to home screen option in a tab's 3 dot menu
@Test
// Verifies the Add to home screen option in a tab's 3 dot menu
fun mainMenuAddToHomeScreenTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val shortcutTitle = generateRandomString(5)
homeScreen {
}.openNavigationToolbar {
@ -282,18 +335,18 @@ class SmokeTest {
}.openThreeDotMenu {
expandMenu()
}.openAddToHomeScreen {
verifyShortcutTextFieldTitle("Test_Page_1")
addShortcutName(shortcutTitle)
verifyShortcutNameField("Test_Page_1")
addShortcutName("Test Page")
clickAddShortcutButton()
clickAddAutomaticallyButton()
}.openHomeScreenShortcut(shortcutTitle) {
}.openHomeScreenShortcut("Test Page") {
verifyUrl(website.url.toString())
verifyTabCounter("1")
}
}
// Verifies the Add to collection option in a tab's 3 dot menu
@Test
// Verifies the Add to collection option in a tab's 3 dot menu
fun openMainMenuAddToCollectionTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -305,8 +358,8 @@ class SmokeTest {
}
}
// Verifies the Bookmark button in a tab's 3 dot menu
@Test
// Verifies the Bookmark button in a tab's 3 dot menu
fun mainMenuBookmarkButtonTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -318,23 +371,23 @@ class SmokeTest {
}
}
@Test
// Device or AVD requires a Google Services Android OS installation with Play Store installed
// Verifies the Open in app button when an app is installed
@Test
fun mainMenuOpenInAppTest() {
val youtubeURL = "https://m.youtube.com/user/mozilla?cbrd=1"
val playStoreUrl = "play.google.com/store/apps/details?id=org.mozilla.fenix"
navigationToolbar {
}.enterURLAndEnterToBrowser(youtubeURL.toUri()) {
}.enterURLAndEnterToBrowser(playStoreUrl.toUri()) {
verifyNotificationDotOnMainMenu()
}.openThreeDotMenu {
}.clickOpenInApp {
assertNativeAppOpens(YOUTUBE_APP, youtubeURL)
assertNativeAppOpens(Constants.PackageName.GOOGLE_PLAY_SERVICES, playStoreUrl)
}
}
// Verifies the Desktop site toggle in a tab's 3 dot menu
@Test
// Verifies the Desktop site toggle in a tab's 3 dot menu
fun mainMenuDesktopSiteTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -347,8 +400,8 @@ class SmokeTest {
}
}
// Verifies the Share button in a tab's 3 dot menu
@Test
// Verifies the Share button in a tab's 3 dot menu
fun mainMenuShareButtonTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -362,8 +415,8 @@ class SmokeTest {
}
}
// Verifies the refresh button in a tab's 3 dot menu
@Test
// Verifies the refresh button in a tab's 3 dot menu
fun mainMenuRefreshButtonTest() {
val refreshWebPage = TestAssetHelper.getRefreshAsset(mockWebServer)
@ -377,8 +430,40 @@ class SmokeTest {
}
}
// Verifies changing the default engine from the Search Shortcut menu
@Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/25345")
@Test
fun customTrackingProtectionSettingsTest() {
val genericWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val trackingPage = TestAssetHelper.getEnhancedTrackingProtectionAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openEnhancedTrackingProtectionSubMenu {
verifyEnhancedTrackingProtectionOptionsEnabled()
selectTrackingProtectionOption("Custom")
verifyCustomTrackingProtectionSettings()
}.goBackToHomeScreen {}
navigationToolbar {
// browsing a basic page to allow GV to load on a fresh run
}.enterURLAndEnterToBrowser(genericWebPage.url) {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(trackingPage.url) {}
enhancedTrackingProtection {
}.openEnhancedTrackingProtectionSheet {
}.openDetails {
verifyTrackingCookiesBlocked()
verifyCryptominersBlocked()
verifyFingerprintersBlocked()
verifyTrackingContentBlocked()
viewTrackingContentBlockList()
}
}
@Test
// Verifies changing the default engine from the Search Shortcut menu
fun selectSearchEnginesShortcutTest() {
val enginesList = listOf("DuckDuckGo", "Google", "Amazon.com", "Wikipedia", "Bing", "eBay")
@ -396,8 +481,26 @@ class SmokeTest {
}
}
// Saves a login, then changes it and verifies the update
@Test
// Swipes the nav bar left/right to switch between tabs
fun swipeToSwitchTabTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
navigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
}.openTabDrawer {
}.openNewTab {
}.submitQuery(secondWebPage.url.toString()) {
swipeNavBarRight(secondWebPage.url.toString())
verifyUrl(firstWebPage.url.toString())
swipeNavBarLeft(firstWebPage.url.toString())
verifyUrl(secondWebPage.url.toString())
}
}
@Test
// Saves a login, then changes it and verifies the update
fun updateSavedLoginTest() {
val saveLoginTest =
TestAssetHelper.getSaveLoginAsset(mockWebServer)
@ -428,8 +531,45 @@ class SmokeTest {
}
}
// Verifies that a recently closed item is properly opened
@Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/25034")
@Test
@SdkSuppress(minSdkVersion = 29)
// Verifies that you can go to System settings and change app's permissions from inside the app
fun redirectToAppPermissionsSystemSettingsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSettingsSubMenuSitePermissions {
}.openCamera {
verifyBlockedByAndroid()
}.goBack {
}.openLocation {
verifyBlockedByAndroid()
}.goBack {
}.openMicrophone {
verifyBlockedByAndroid()
clickGoToSettingsButton()
openAppSystemPermissionsSettings()
switchAppPermissionSystemSetting("Camera", "Allow")
mDevice.pressBack()
switchAppPermissionSystemSetting("Location", "Allow")
mDevice.pressBack()
switchAppPermissionSystemSetting("Microphone", "Allow")
mDevice.pressBack()
mDevice.pressBack()
mDevice.pressBack()
verifyUnblockedByAndroid()
}.goBack {
}.openLocation {
verifyUnblockedByAndroid()
}.goBack {
}.openCamera {
verifyUnblockedByAndroid()
}
}
@Test
// Verifies that a recently closed item is properly opened
fun openRecentlyClosedItemTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -442,18 +582,18 @@ class SmokeTest {
}.openTabDrawer {
}.openRecentlyClosedTabs {
waitForListToExist()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1),
) {
verifyRecentlyClosedTabsMenuView()
}
recentlyClosedTabsListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1)
IdlingRegistry.getInstance().register(recentlyClosedTabsListIdlingResource!!)
verifyRecentlyClosedTabsMenuView()
IdlingRegistry.getInstance().unregister(recentlyClosedTabsListIdlingResource!!)
}.clickRecentlyClosedItem("Test_Page_1") {
verifyUrl(website.url.toString())
}
}
// Verifies that tapping the "x" button removes a recently closed item from the list
@Test
// Verifies that tapping the "x" button removes a recently closed item from the list
fun deleteRecentlyClosedTabsItemTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -466,18 +606,18 @@ class SmokeTest {
}.openTabDrawer {
}.openRecentlyClosedTabs {
waitForListToExist()
registerAndCleanupIdlingResources(
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1),
) {
verifyRecentlyClosedTabsMenuView()
}
recentlyClosedTabsListIdlingResource =
RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.recently_closed_list), 1)
IdlingRegistry.getInstance().register(recentlyClosedTabsListIdlingResource!!)
verifyRecentlyClosedTabsMenuView()
IdlingRegistry.getInstance().unregister(recentlyClosedTabsListIdlingResource!!)
clickDeleteRecentlyClosedTabs()
verifyEmptyRecentlyClosedTabsList()
}
}
// Verifies that deleting a Bookmarks folder also removes the item from inside it.
@Test
// Verifies that deleting a Bookmarks folder also removes the item from inside it.
fun deleteNonEmptyBookmarkFolderTest() {
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -547,9 +687,8 @@ class SmokeTest {
}.clickShareAllTabsButton {
verifyShareTabsOverlay(firstWebsiteTitle, secondWebsiteTitle)
verifySharingWithSelectedApp(
sharingApp,
sharedUrlsString,
"$firstWebsiteTitle, $secondWebsiteTitle",
sharingApp, sharedUrlsString,
"$firstWebsiteTitle, $secondWebsiteTitle"
)
}
}
@ -579,6 +718,7 @@ class SmokeTest {
homeScreen {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(website.url) {
mDevice.waitForIdle()
}.openTabDrawer {
verifyNormalBrowsingButtonIsSelected(false)
verifyPrivateBrowsingButtonIsSelected(true)
@ -588,15 +728,17 @@ class SmokeTest {
verifyExistingTabList()
verifyExistingOpenTabs(website.title)
verifyCloseTabsButton(website.title)
// Disabled step due to ongoing tabs tray compose refactoring, see: https://github.com/mozilla-mobile/fenix/issues/21318
// verifyOpenedTabThumbnail()
verifyOpenedTabThumbnail()
verifyPrivateBrowsingNewTabButton()
}.openTab(website.title) {
verifyUrl(website.url.toString())
verifyTabCounter("1")
}
}
@Test
// 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)
@ -648,8 +790,8 @@ class SmokeTest {
}
}
// Verifies that reader mode is detected and the custom appearance controls are displayed
@Test
// Verifies that reader mode is detected and the custom appearance controls are displayed
fun verifyReaderViewAppearanceUI() {
val readerViewPage =
TestAssetHelper.getLoremIpsumAsset(mockWebServer)
@ -657,15 +799,15 @@ class SmokeTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(readerViewPage.url) {
mDevice.waitForIdle()
org.mozilla.fenix.ui.robots.mDevice.waitForIdle()
}
registerAndCleanupIdlingResources(
ViewVisibilityIdlingResource(
activityTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE,
),
) {}
readerViewNotification = ViewVisibilityIdlingResource(
activityTestRule.activity.findViewById(R.id.mozac_browser_toolbar_page_actions),
View.VISIBLE
)
IdlingRegistry.getInstance().register(readerViewNotification)
navigationToolbar {
verifyReaderViewDetected(true)
@ -690,16 +832,16 @@ class SmokeTest {
}
}
// Verifies the main menu of a custom tab with a custom menu item
@Test
// Verifies the main menu of a custom tab with a custom menu item
fun customTabMenuItemsTest() {
val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
intentReceiverActivityTestRule.launchActivity(
createCustomTabIntent(
customTabPage.url.toString(),
customMenuItem,
),
customMenuItem
)
)
customTabScreen {
@ -716,15 +858,15 @@ class SmokeTest {
}
}
// The test opens a link in a custom tab then sends it to the browser
@Test
// The test opens a link in a custom tab then sends it to the browser
fun openCustomTabInBrowserTest() {
val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
intentReceiverActivityTestRule.launchActivity(
createCustomTabIntent(
customTabPage.url.toString(),
),
customTabPage.url.toString()
)
)
customTabScreen {
@ -735,6 +877,7 @@ class SmokeTest {
}
}
@Ignore("Failing with frequent ANR: https://bugzilla.mozilla.org/show_bug.cgi?id=1764605")
@Test
fun audioPlaybackSystemNotificationTest() {
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
@ -786,9 +929,9 @@ class SmokeTest {
}
}
@Test
// For API>23
// Verifies the default browser switch opens the system default apps menu.
@Test
fun changeDefaultBrowserSetting() {
homeScreen {
}.openThreeDotMenu {
@ -816,7 +959,7 @@ class SmokeTest {
clickClearButton()
longClickToolbar()
clickPasteText()
verifyTypedToolbarText("content")
verifyPastedToolbarText("content")
}
}
@ -835,8 +978,29 @@ class SmokeTest {
clickClearButton()
longClickToolbar()
clickPasteText()
// with Select all, some white space is copied over, so we need to include that too
verifyTypedToolbarText(" Page content: 1 ")
verifyPastedToolbarText("Page content: 1")
}
}
@Test
fun switchLanguageTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openLanguageSubMenu {
localeListIdlingResource =
RecyclerViewIdlingResource(
activityTestRule.activity.findViewById(R.id.locale_list),
2
)
IdlingRegistry.getInstance().register(localeListIdlingResource)
selectLanguage("Romanian")
verifyLanguageHeaderIsTranslated(ROMANIAN_LANGUAGE_HEADER)
selectLanguage("Français")
verifyLanguageHeaderIsTranslated(FRENCH_LANGUAGE_HEADER)
selectLanguage(FRENCH_SYSTEM_LOCALE_OPTION)
verifyLanguageHeaderIsTranslated("Language")
IdlingRegistry.getInstance().unregister(localeListIdlingResource)
}
}

View File

@ -1,252 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.ui
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.Constants.defaultTopSitesList
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.getSponsoredShortcutTitle
import org.mozilla.fenix.ui.robots.homeScreen
/**
* Tests Sponsored shortcuts functionality
*/
class SponsoredShortcutsTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
private val defaultSearchEngine = "Amazon.com"
private lateinit var sponsoredShortcutTitle: String
private lateinit var sponsoredShortcutTitle2: String
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@Before
fun setUp() {
TestHelper.appContext.settings().userOptOutOfReEngageCookieBannerDialog = true
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// Expected for en-us defaults
@SmokeTest
@Test
fun verifySponsoredShortcutsListTest() {
homeScreen {
defaultTopSitesList.values.forEach { value ->
verifyExistingTopSitesTabs(value)
}
}.openThreeDotMenu {
}.openCustomizeHome {
verifySponsoredShortcutsCheckBox(true)
clickSponsoredShortcuts()
verifySponsoredShortcutsCheckBox(false)
}.goBack {
verifyNotExistingSponsoredTopSitesList()
}
}
@Test
fun openSponsoredShortcutTest() {
homeScreen {
sponsoredShortcutTitle = getSponsoredShortcutTitle(2)
}.openSponsoredShortcut(sponsoredShortcutTitle) {
verifyUrl(sponsoredShortcutTitle)
}
}
@Test
fun openSponsoredShortcutInPrivateBrowsingTest() {
homeScreen {
sponsoredShortcutTitle = getSponsoredShortcutTitle(2)
}.openContextMenuOnSponsoredShortcut(sponsoredShortcutTitle) {
}.openTopSiteInPrivateTab {
verifyUrl(sponsoredShortcutTitle)
}
}
@Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/25926")
@Test
fun verifySponsorsAndPrivacyLinkTest() {
homeScreen {
sponsoredShortcutTitle = getSponsoredShortcutTitle(2)
}.openContextMenuOnSponsoredShortcut(sponsoredShortcutTitle) {
}.clickSponsorsAndPrivacyButton {
verifyUrl("support.mozilla.org/en-US/kb/sponsor-privacy")
}
}
@Test
fun verifySponsoredShortcutsSettingsOptionTest() {
homeScreen {
sponsoredShortcutTitle = getSponsoredShortcutTitle(2)
}.openContextMenuOnSponsoredShortcut(sponsoredShortcutTitle) {
}.clickSponsoredShortcutsSettingsButton {
verifyHomePageView()
}
}
@Test
fun verifySponsoredShortcutsDetailsTest() {
homeScreen {
sponsoredShortcutTitle = getSponsoredShortcutTitle(2)
sponsoredShortcutTitle2 = getSponsoredShortcutTitle(3)
verifySponsoredShortcutDetails(sponsoredShortcutTitle, 2)
verifySponsoredShortcutDetails(sponsoredShortcutTitle2, 3)
}
}
// The default search engine should not be displayed as a sponsored shortcut
@Test
fun defaultSearchEngineIsNotDisplayedAsSponsoredShortcutTest() {
val sponsoredShortcutTitle = "Amazon"
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openSearchSubMenu {
changeDefaultSearchEngine(defaultSearchEngine)
}
exitMenu()
homeScreen {
verifySponsoredShortcutDoesNotExist(sponsoredShortcutTitle, 2)
verifySponsoredShortcutDoesNotExist(sponsoredShortcutTitle, 3)
}
}
// 1 sponsored shortcut should be displayed if there are 7 pinned top sites
@Test
fun verifySponsoredShortcutsListWithSevenPinnedSitesTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
val thirdWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 3)
val fourthWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 4)
homeScreen {
sponsoredShortcutTitle = getSponsoredShortcutTitle(2)
sponsoredShortcutTitle2 = getSponsoredShortcutTitle(3)
verifySponsoredShortcutDetails(sponsoredShortcutTitle, 2)
verifySponsoredShortcutDetails(sponsoredShortcutTitle2, 3)
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
verifyPageContent(firstWebPage.content)
}.openThreeDotMenu {
expandMenu()
}.addToFirefoxHome {
}.goToHomescreen {
verifyExistingTopSitesTabs(firstWebPage.title)
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(secondWebPage.url) {
verifyPageContent(secondWebPage.content)
}.openThreeDotMenu {
expandMenu()
}.addToFirefoxHome {
}.goToHomescreen {
verifyExistingTopSitesTabs(secondWebPage.title)
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(thirdWebPage.url) {
verifyPageContent(thirdWebPage.content)
}.openThreeDotMenu {
expandMenu()
}.addToFirefoxHome {
}.goToHomescreen {
verifyExistingTopSitesTabs(thirdWebPage.title)
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(fourthWebPage.url) {
verifyPageContent(fourthWebPage.content)
}.openThreeDotMenu {
expandMenu()
}.addToFirefoxHome {
}.goToHomescreen {
verifySponsoredShortcutDetails(sponsoredShortcutTitle, 2)
verifySponsoredShortcutDoesNotExist(sponsoredShortcutTitle2, 3)
}
}
// No sponsored shortcuts should be displayed if there are 8 pinned top sites
@Test
fun verifySponsoredShortcutsListWithEightPinnedSitesTest() {
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
val thirdWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 3)
val fourthWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 4)
val fifthWebPage = TestAssetHelper.getLoremIpsumAsset(mockWebServer)
homeScreen {
sponsoredShortcutTitle = getSponsoredShortcutTitle(2)
sponsoredShortcutTitle2 = getSponsoredShortcutTitle(3)
verifySponsoredShortcutDetails(sponsoredShortcutTitle, 2)
verifySponsoredShortcutDetails(sponsoredShortcutTitle2, 3)
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(firstWebPage.url) {
verifyPageContent(firstWebPage.content)
}.openThreeDotMenu {
expandMenu()
}.addToFirefoxHome {
}.goToHomescreen {
verifyExistingTopSitesTabs(firstWebPage.title)
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(secondWebPage.url) {
verifyPageContent(secondWebPage.content)
}.openThreeDotMenu {
expandMenu()
}.addToFirefoxHome {
}.goToHomescreen {
verifyExistingTopSitesTabs(secondWebPage.title)
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(thirdWebPage.url) {
verifyPageContent(thirdWebPage.content)
}.openThreeDotMenu {
expandMenu()
}.addToFirefoxHome {
}.goToHomescreen {
verifyExistingTopSitesTabs(thirdWebPage.title)
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(fourthWebPage.url) {
verifyPageContent(fourthWebPage.content)
}.openThreeDotMenu {
expandMenu()
}.addToFirefoxHome {
}.goToHomescreen {
verifyExistingTopSitesTabs(fourthWebPage.title)
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(fifthWebPage.url) {
verifyPageContent(fifthWebPage.content)
}.openThreeDotMenu {
expandMenu()
}.addToFirefoxHome {
}.goToHomescreen {
verifySponsoredShortcutDoesNotExist(sponsoredShortcutTitle, 2)
verifySponsoredShortcutDoesNotExist(sponsoredShortcutTitle2, 3)
}
}
}

View File

@ -4,19 +4,17 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.ui.robots.enhancedTrackingProtection
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -35,15 +33,12 @@ import org.mozilla.fenix.ui.robots.settingsSubMenuEnhancedTrackingProtection
* - Verifying Enhanced Tracking Protection site exceptions
*/
class EnhancedTrackingProtectionTest {
class StrictEnhancedTrackingProtectionTest {
private lateinit var mockWebServer: MockWebServer
private val featureSettingsHelper = FeatureSettingsHelper()
@get:Rule
val activityTestRule = HomeActivityTestRule(
isJumpBackInCFREnabled = false,
isTCPCFREnabled = false,
isWallpaperOnboardingEnabled = false,
)
val activityTestRule = HomeActivityTestRule()
@Before
fun setUp() {
@ -51,11 +46,14 @@ class EnhancedTrackingProtectionTest {
dispatcher = AndroidAssetDispatcher()
start()
}
featureSettingsHelper.setStrictETPEnabled()
featureSettingsHelper.setJumpBackCFREnabled(false)
}
@After
fun tearDown() {
mockWebServer.shutdown()
featureSettingsHelper.resetAllFeatureFlags()
}
@Test
@ -85,8 +83,8 @@ class EnhancedTrackingProtectionTest {
}.openEnhancedTrackingProtectionSubMenu {
switchEnhancedTrackingProtectionToggle()
verifyEnhancedTrackingProtectionOptionsEnabled(false)
exitMenu()
}
}.goBack {
}.goBack { }
navigationToolbar {
}.enterURLAndEnterToBrowser(genericPage.url) { }
@ -109,7 +107,6 @@ class EnhancedTrackingProtectionTest {
@Test
fun testStrictVisitProtectionSheet() {
appContext.settings().setStrictETP()
val genericPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val trackingProtectionTest =
TestAssetHelper.getEnhancedTrackingProtectionAsset(mockWebServer)
@ -129,9 +126,9 @@ class EnhancedTrackingProtectionTest {
}
}
@Ignore("Failing with frequent ANR: https://bugzilla.mozilla.org/show_bug.cgi?id=1764605")
@Test
fun testStrictVisitDisableExceptionToggle() {
appContext.settings().setStrictETP()
val genericPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val trackingProtectionTest =
TestAssetHelper.getEnhancedTrackingProtectionAsset(mockWebServer)
@ -166,7 +163,6 @@ class EnhancedTrackingProtectionTest {
@Test
fun testStrictVisitSheetDetails() {
appContext.settings().setStrictETP()
val genericPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val trackingProtectionTest =
TestAssetHelper.getEnhancedTrackingProtectionAsset(mockWebServer)
@ -180,11 +176,7 @@ class EnhancedTrackingProtectionTest {
navigationToolbar {
}.enterURLAndEnterToBrowser(trackingProtectionTest.url) {
verifyTrackingProtectionWebContent("social blocked")
verifyTrackingProtectionWebContent("ads blocked")
verifyTrackingProtectionWebContent("analytics blocked")
verifyTrackingProtectionWebContent("Fingerprinting blocked")
verifyTrackingProtectionWebContent("Cryptomining blocked")
verifyTrackingProtectionWebContent("blocked")
}
enhancedTrackingProtection {
}.openEnhancedTrackingProtectionSheet {
@ -198,76 +190,4 @@ class EnhancedTrackingProtectionTest {
viewTrackingContentBlockList()
}
}
@SmokeTest
@Test
fun customTrackingProtectionSettingsTest() {
val genericWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
val trackingPage = TestAssetHelper.getEnhancedTrackingProtectionAsset(mockWebServer)
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openEnhancedTrackingProtectionSubMenu {
verifyEnhancedTrackingProtectionOptionsEnabled()
selectTrackingProtectionOption("Custom")
verifyCustomTrackingProtectionSettings()
}.goBackToHomeScreen {}
navigationToolbar {
// browsing a basic page to allow GV to load on a fresh run
}.enterURLAndEnterToBrowser(genericWebPage.url) {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(trackingPage.url) {
verifyTrackingProtectionWebContent("social blocked")
verifyTrackingProtectionWebContent("ads blocked")
verifyTrackingProtectionWebContent("analytics blocked")
verifyTrackingProtectionWebContent("Fingerprinting blocked")
verifyTrackingProtectionWebContent("Cryptomining blocked")
}
enhancedTrackingProtection {
}.openEnhancedTrackingProtectionSheet {
}.openDetails {
verifyTrackingCookiesBlocked()
verifyCryptominersBlocked()
verifyFingerprintersBlocked()
verifyTrackingContentBlocked()
viewTrackingContentBlockList()
}
}
@SmokeTest
@Test
fun blockCookiesStorageAccessTest() {
// With Standard TrackingProtection settings
val page = mockWebServer.url("pages/cross-site-cookies.html").toString().toUri()
val originSite = "https://mozilla-mobile.github.io"
val currentSite = "http://localhost:${mockWebServer.port}"
navigationToolbar {
}.enterURLAndEnterToBrowser(page) {
}.clickRequestStorageAccessButton {
verifyCrossOriginCookiesPermissionPrompt(originSite, currentSite)
}.clickPagePermissionButton(allow = false) {
verifyPageContent("access denied")
}
}
@SmokeTest
@Test
fun allowCookiesStorageAccessTest() {
// With Standard TrackingProtection settings
val page = mockWebServer.url("pages/cross-site-cookies.html").toString().toUri()
val originSite = "https://mozilla-mobile.github.io"
val currentSite = "http://localhost:${mockWebServer.port}"
navigationToolbar {
}.enterURLAndEnterToBrowser(page) {
}.clickRequestStorageAccessButton {
verifyCrossOriginCookiesPermissionPrompt(originSite, currentSite)
}.clickPagePermissionButton(allow = true) {
verifyPageContent("access granted")
}
}
}

View File

@ -10,10 +10,10 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
@ -40,12 +40,13 @@ import org.mozilla.fenix.ui.robots.notificationShade
*/
class TabbedBrowsingTest {
private lateinit var mDevice: UiDevice
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private lateinit var mockWebServer: MockWebServer
private val featureSettingsHelper = FeatureSettingsHelper()
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
@get:Rule
val activityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides()
val activityTestRule = HomeActivityTestRule()
@Rule
@JvmField
@ -53,7 +54,9 @@ class TabbedBrowsingTest {
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
// disabling the new homepage pop-up that interferes with the tests.
featureSettingsHelper.setJumpBackCFREnabled(false)
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -63,6 +66,7 @@ class TabbedBrowsingTest {
@After
fun tearDown() {
mockWebServer.shutdown()
featureSettingsHelper.resetAllFeatureFlags()
}
@Test
@ -122,7 +126,7 @@ class TabbedBrowsingTest {
verifyShareTabButton()
verifySelectTabs()
}.closeAllTabs {
verifyTabCounter("0")
verifyNoTabsOpened()
}
// Repeat for Private Tabs
@ -137,12 +141,11 @@ class TabbedBrowsingTest {
}.openTabsListThreeDotMenu {
verifyCloseAllTabsButton()
}.closeAllTabs {
verifyTabCounter("0")
verifyNoTabsOpened()
}
}
@Test
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
fun closeTabTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -153,7 +156,7 @@ class TabbedBrowsingTest {
closeTab()
}
homeScreen {
verifyTabCounter("0")
verifyNoTabsOpened()
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openTabDrawer {
@ -161,7 +164,7 @@ class TabbedBrowsingTest {
swipeTabRight("Test_Page_1")
}
homeScreen {
verifyTabCounter("0")
verifyNoTabsOpened()
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openTabDrawer {
@ -169,17 +172,15 @@ class TabbedBrowsingTest {
swipeTabLeft("Test_Page_1")
}
homeScreen {
verifyTabCounter("0")
verifyNoTabsOpened()
}
}
@Test
fun verifyUndoSnackBarTest() {
// disabling these features because they interfere with the snackbar visibility
activityTestRule.applySettingsExceptions {
it.isPocketEnabled = false
it.isRecentTabsFeatureEnabled = false
}
featureSettingsHelper.setPocketEnabled(false)
featureSettingsHelper.setRecentTabsFeatureEnabled(false)
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -200,7 +201,6 @@ class TabbedBrowsingTest {
}
@Test
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
fun closePrivateTabTest() {
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
@ -213,7 +213,7 @@ class TabbedBrowsingTest {
closeTab()
}
homeScreen {
verifyTabCounter("0")
verifyNoTabsOpened()
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openTabDrawer {
@ -221,7 +221,7 @@ class TabbedBrowsingTest {
swipeTabRight("Test_Page_1")
}
homeScreen {
verifyTabCounter("0")
verifyNoTabsOpened()
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
}.openTabDrawer {
@ -229,7 +229,7 @@ class TabbedBrowsingTest {
swipeTabLeft("Test_Page_1")
}
homeScreen {
verifyTabCounter("0")
verifyNoTabsOpened()
}
}
@ -277,6 +277,7 @@ class TabbedBrowsingTest {
@Test
fun verifyTabTrayNotShowingStateHalfExpanded() {
navigationToolbar {
}.openTabTray {
verifyNoOpenTabsInNormalBrowsing()
@ -326,8 +327,7 @@ class TabbedBrowsingTest {
verifyTabsTrayCounter()
verifyExistingTabList()
verifyNormalBrowsingNewTabButton()
// Disabled step due to ongoing tabs tray compose refactoring, see: https://github.com/mozilla-mobile/fenix/issues/21318
// verifyOpenedTabThumbnail()
verifyOpenedTabThumbnail()
verifyExistingOpenTabs(defaultWebPage.title)
verifyCloseTabsButton(defaultWebPage.title)
}.openTab(defaultWebPage.title) {
@ -353,7 +353,7 @@ class TabbedBrowsingTest {
// dismiss search dialog
homeScreen { }.pressBack()
verifyPrivateSessionMessage()
verifyNavigationToolbar()
verifyHomeToolbar()
}
navigationToolbar {
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
@ -364,7 +364,7 @@ class TabbedBrowsingTest {
// dismiss search dialog
homeScreen { }.pressBack()
verifyHomeWordmark()
verifyNavigationToolbar()
verifyHomeToolbar()
}
}
}

View File

@ -7,11 +7,12 @@ package org.mozilla.fenix.ui
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.ui.robots.homeScreen
/**
@ -25,10 +26,11 @@ class ThreeDotMenuMainTest {
private lateinit var mockWebServer: MockWebServer
@get:Rule
val activityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides()
val activityTestRule = HomeActivityTestRule()
@Before
fun setUp() {
activityTestRule.activity.applicationContext.settings().shouldShowJumpBackInCFR = false
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
@ -41,159 +43,54 @@ class ThreeDotMenuMainTest {
}
// Verifies the list of items in the homescreen's 3 dot main menu
@Ignore("Failing with frequent ANR: https://bugzilla.mozilla.org/show_bug.cgi?id=1764605")
@Test
fun homeThreeDotMenuItemsTest() {
homeScreen {
}.openThreeDotMenu {
verifyHomeThreeDotMainMenuItems(isRequestDesktopSiteEnabled = false)
}.openBookmarks {
verifyBookmarksMenuView()
verifyBookmarksButton()
verifyHistoryButton()
verifyDownloadsButton()
verifyAddOnsButton()
verifySyncSignInButton()
verifyDesktopSite()
verifyWhatsNewButton()
verifyHelpButton()
verifyCustomizeHomeButton()
verifySettingsButton()
}.openSettings {
verifySettingsView()
}.goBack {
}.openThreeDotMenu {
}.openHistory {
verifyHistoryMenuView()
}.goBack {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyEmptyDownloadsList()
}.goBack {
}.openThreeDotMenu {
}.openAddonsManagerMenu {
verifyAddonsItems()
}.goBack {
}.openThreeDotMenu {
}.openSyncSignIn {
verifyTurnOnSyncMenu()
}.goBack {
// Desktop toggle
}.openThreeDotMenu {
}.switchDesktopSiteMode {
}
homeScreen {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(isRequestDesktopSiteEnabled = true)
}.openWhatsNew {
verifyWhatsNewURL()
}.goToHomescreen {
}.openThreeDotMenu {
}.openHelp {
verifyHelpUrl()
}.goToHomescreen {
}.openThreeDotMenu {
}.openCustomizeHome {
verifyHomePageView()
}.goBack {
}.openThreeDotMenu {
}.openSettings {
verifySettingsView()
}.openHelp {
verifyHelpUrl()
}.openTabDrawer {
closeTab()
}
homeScreen {
}.openThreeDotMenu {
}.openWhatsNew {
verifyWhatsNewURL()
}.openTabDrawer {
closeTab()
}
}
// Verifies the list of items in the homescreen's 3 dot main menu in private browsing
@Test
fun privateHomeThreeDotMenuItemsTest() {
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openThreeDotMenu {
verifyHomeThreeDotMainMenuItems(isRequestDesktopSiteEnabled = false)
}.openBookmarks {
verifyBookmarksMenuView()
}.goBack {
}.closeMenu {
}
homeScreen {
}.openThreeDotMenu {
}.openHistory {
verifyHistoryMenuView()
}.goBack {
}.openThreeDotMenu {
}.openDownloadsManager {
verifyEmptyDownloadsList()
}.goBack {
}.openThreeDotMenu {
}.openAddonsManagerMenu {
verifyAddonsItems()
}.goBack {
}.openThreeDotMenu {
}.openSyncSignIn {
verifyTurnOnSyncMenu()
}.goBack {
// Desktop toggle
}.openThreeDotMenu {
}.switchDesktopSiteMode {
}
homeScreen {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(isRequestDesktopSiteEnabled = true)
}.openWhatsNew {
verifyWhatsNewURL()
}.goToHomescreen {
}.openThreeDotMenu {
}.openHelp {
verifyHelpUrl()
}.goToHomescreen {
}.openThreeDotMenu {
}.openCustomizeHome {
verifyHomePageView()
}.goBack {
}.openThreeDotMenu {
}.openSettings {
verifySettingsView()
}
}
@Test
fun setDesktopSiteBeforePageLoadTest() {
val webPage = TestAssetHelper.getGenericAsset(mockWebServer, 4)
homeScreen {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(false)
}.switchDesktopSiteMode {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(true)
}.closeBrowserMenuToBrowser {
clickLinkMatchingText("Link 1")
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(true)
}.closeBrowserMenuToBrowser {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
longClickLink("Link 2")
clickContextOpenLinkInNewTab()
snackBarButtonClick()
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(false)
}
}
@Test
fun privateBrowsingSetDesktopSiteBeforePageLoadTest() {
val webPage = TestAssetHelper.getGenericAsset(mockWebServer, 4)
homeScreen {
}.togglePrivateBrowsingMode()
homeScreen {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(false)
}.switchDesktopSiteMode {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(true)
}.closeBrowserMenuToBrowser {
clickLinkMatchingText("Link 1")
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(true)
}.closeBrowserMenuToBrowser {
}.openNavigationToolbar {
}.enterURLAndEnterToBrowser(webPage.url) {
longClickLink("Link 2")
clickContextOpenLinkInPrivateTab()
snackBarButtonClick()
}.openThreeDotMenu {
verifyDesktopSiteModeEnabled(false)
}
}
}

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