Compare commits

...

242 Commits

Author SHA1 Message Date
akliuxingyuan 1b30ac457c remove duplicated promptToSetAsDefaultBrowser 2 weeks ago
akliuxingyuan c4f9eaf572 add jvmTargetCompatibility 2 weeks ago
akliuxingyuan d293e888f7 update components version: 125.0 2 weeks ago
akliuxingyuan f2efeaef96 Merge remote-tracking branch 'origin/fenix/125.0' into iceraven 2 weeks ago
RebecaTudor 73c9a42a83 Bug 1876719 - [a11y] Increasing contrast for collection's dialog buttons
Before the fix, Accessibility Scanner was showing the color contrast
between text color and the background color as insufficient.

  With the modification made the accessibility scanner shows the
problem as fixed. The color that was used for the fix is the closest to
the one before that can satisfy the contrast required.
1 month ago
github-actions 4b585c94d8 Import translations from android-l10n 1 month ago
rvandermeulen 1d70b74e6b Update Fenix initial_experiments.json based on the current first-run experiments in experimenter 1 month ago
github-actions 469d94d939 Import translations from android-l10n 1 month ago
github-actions dc6d72b9b3 Import translations from android-l10n 1 month ago
github-actions 06a58f40bd Import translations from android-l10n 1 month ago
github-actions 735bf563dd Import translations from android-l10n 1 month ago
t-p-white d2757cf67e Bug 1886792 - Handle install_search_widget deeplink r=android-reviewers,amejiamarmol
Differential Revision: https://phabricator.services.mozilla.com/D205477
1 month ago
t-p-white a960879c37 Bug 1886769 - Add search widget installed custom attribute. r=android-reviewers,mcarare,amejiamarmol
Differential Revision: https://phabricator.services.mozilla.com/D205337
1 month ago
github-actions d3d6c05983 Import translations from android-l10n 1 month ago
github-actions 17125f00c5 Import translations from android-l10n 1 month ago
github-actions a0a6eb46cc Import translations from android-l10n 1 month ago
github-actions 913a287e90 Import translations from android-l10n 1 month ago
github-actions aa8873741a Import translations from android-l10n 1 month ago
github-actions 0f995f8757 Import translations from android-l10n 2 months ago
github-actions 70446810cc Import translations from android-l10n 2 months ago
github-actions 6495b733ee Import translations from android-l10n 2 months ago
github-actions 3bb11846d7 Import translations from android-l10n 2 months ago
Harrison Oglesby bf8bb43b70 Bug 1858895 - Fix rotation size change for FeltPrivacyInfoCard. 2 months ago
mike a 5bffd719c3 Bug 1885399 - Fix clipping behaviour 2 months ago
William Durand 4424214894 Bug 1881676 - Unconditionally set the "Enabled" label on the toggle switch 2 months ago
Jeff Boek 3448920c7f Bug 1885348 - Update README.md to include blurb about installing Rosetta 2 months ago
AndiAJ d62b7a1edf Bug 1885329 - Add logs to MockLocationUpdatesRule 2 months ago
DreVla cf9cd2a86c Bug 1880520 - [Onboarding] Enable "Add Search Widget" card
As result of the experiment to add a new card, "Add Search Widget",
to onboarding, this new card will be now enabled by default.
2 months ago
AndiAJ db2a301ddf Bug 1885314 - Add more logs to RetryTestRule 2 months ago
AndiAJ ca4175675c Bug 1885300 - Add logs to HomeActivityTestRule 2 months ago
AndiAJ 1bf1278982 Bug 1885288 - Add logs to FeatureSettingsHelperDelegate 2 months ago
rahulsainani 96c6d08a66 Bug 1884891 - Display only private in tab strip when switched to private tab 2 months ago
AndiAJ 63ca1419c6 Bug 1885141 - Add logs to MockBrowserDataHelper 2 months ago
mike a c9422e81ea Bug 1879370 - Add a ClippingBehavior supporting multiple toolbars 2 months ago
mike a a6820d760c Bug 1879372 - Add enabled/disabled nav button states 2 months ago
ohall-m 0760ab5a58 Bug 1853058 - Remove Translations Secret Settings and Use Nimbus
* This patch removes the secret setting to turn on translations and
removes the usage.
* Nimbus feature defaults for translations are all set to false.
2 months ago
JohanLorenzo 22a7222679 Update Fenix initial_experiments.json based on the current first-run experiments in experimenter 2 months ago
oana.horvath b41b5727eb Bug 1885160 - Add logs to AppAndSystemHelper 2 months ago
Rahul Sainani 2d7942033c Revert "Bug 1867717 - Add DownloadsFeature to AddonPopupBaseFragment."
This reverts commit cc65693e4f8811906f344d0e902af0bccbb7edbf.
2 months ago
AndiAJ a878e4b3fa Bug 1885123 - Add logs to DataGenerationHelper 2 months ago
AndiAJ 8867641ffe Bug 1885108 - Add logs to TestHelper 2 months ago
github-actions 344063da4e Import translations from android-l10n 2 months ago
mike a f03a6a7215 Bug 1878827 - Add nav buttons click handling 2 months ago
JohanLorenzo f56de3bb73 Update Fenix initial_experiments.json based on the current first-run experiments in experimenter 2 months ago
AndiAJ 30c746ee99 Bug 1884918 - Add logs to MatcherHelper 2 months ago
AndiAJ 71ea2a990e Bug 1884653 - Add logs to AccountSettingsRobot 2 months ago
AndiAJ 53c0e021de Bug 1884653 - Remove redundant assertion functions from AccountSettingsRobot 2 months ago
JohanLorenzo 03231a08a1 Update Fenix initial_experiments.json based on the current first-run experiments in experimenter 2 months ago
AndiAJ 16123a7237 Bug 1884904 - Add logs to SettingsSubMenuSetDefaultBrowserRobot 2 months ago
AndiAJ f4023bad77 Bug 1884903 - Add logs to SettingsSubMenuAboutRobot 2 months ago
AndiAJ bbb3c0dfe6 Bug 1884903 - Remove redundant assertion functions from SettingsSubMenuAboutRobot 2 months ago
github-actions 03949df932 Import translations from android-l10n 2 months ago
ohall-m 98a4678305 Bug 1884390 - Adjust Unsupported Error in Translations
This patch:
* Adds an option in `LocaleUtils` to fetch language names for a given locale.
* Adjusts Translations Unsupported Error to use this option.
2 months ago
Roger Yang b71a480808 Bug 1884666 - Only add Google additional header in search, preferences and webhp urls 2 months ago
sarah541 130fecde97 Bug 1870938 - Add display/edit toolbar separator and update url bar background 2 months ago
Harrison Oglesby e1ec8d67fa Bug 1874298 - Add Reload Page action to PageActions in Toolbar 2 months ago
mike a 1d0cc1ad52 Bug 1884487 – simplify NavbarIntegration by removing viewLifecycleOwner 2 months ago
jackyzy823 ab304c5f9d Bug 1876024 - Request screenshot thumbnail when onSwipeStarted 2 months ago
t-p-white 32259c25ac Bug 1884187 - Fix Fenix night mode bug after opening a custom tab 2 months ago
ohall-m 0450b126f1 Bug 1883968 - Translations Interaction Telemetry
This patch adds:
* `translations_action` probe
    * Extras:
        * main_flow_toolbar - Interaction with toolbar button
        * main_flow_browser - Interaction with browser menu button
        * page_settings - Interaction with page settings
        * global_settings - Interaction with global settings
        * global_lang_settings - Interaction with language settings
        * global_site_settings - Interaction with site settings
        * downloads - Interaction with downloads
2 months ago
AndiAJ b260a91210 Bug 1881028 - Add logs to SettingsSubMenuEnhancedTrackingProtectionRobot 2 months ago
AndiAJ 7540671d28 Bug 1881028 - Remove redundant assertion functions from SettingsSubMenuEnhancedTrackingProtectionRobot 2 months ago
AndiAJ f9ac7cfc7d Bug 1881028 - Add logs to SettingsSubMenuEnhancedTrackingProtectionExceptionsRobot 2 months ago
AndiAJ 1daa2ba0df Bug 1881028 - Convert private variables to functions so they don't get initialised 2 months ago
AndiAJ f4cf272743 Bug 1884363 - Add logs to ThreeDotMenuMainRobot 2 months ago
AndiAJ a6755ca5df Bug 1884363 - Remove redundant assertion functions from ThreeDotMenuMainRobot 2 months ago
github-actions 2b246de4f7 Import translations from android-l10n 2 months ago
github-actions 6a2f85ae5d Import translations from android-l10n 2 months ago
Ryan VanderMeulen 2e81cf37cc Bug 1883763 - Add suppressions to firefox-android code still using the now-deprecated APIs 2 months ago
github-actions 321fa1fa10 Import translations from android-l10n 2 months ago
mike a 1d795b4372 Bug 1879377 - Hide nav bar when the toolbar becomes focused 2 months ago
mike a ebfc9edc79 Bug 1879648 - Disable menu toolbar when nav bar is enabled 2 months ago
Mark Hammond 7e7f0832db Bug 1879332 - ensure synced tabs includes the inactive property 2 months ago
JohanLorenzo 14138220ca Update Fenix initial_experiments.json based on the current first-run experiments in experimenter 2 months ago
iorgamgabriel 63d82ce203 Bug 1883465 - Bottom Sheet in landscape should span the full screen 2 months ago
rahulsainani 0b15973796 Bug 1862295 - Translations UI Integration Integrate Error States 2 months ago
Ryan VanderMeulen 06a48206e6 Revert "Bug 1876398 - Update AndroidX Compose to version 1.6.1" because it depends on the AGP 8.3.0 update
This reverts commits 256fa9607e9afdfe8567747d1c6f63cbc7bf918e,
1d08590f1813f176fcb3973443b2785640a13141, and
2ba9b2bc6eae0b6c1626eb161868b4efb495c0db
2 months ago
AndiAJ 619130843a Bug 1884329 - Add logs to TabDrawerRobot 2 months ago
AndiAJ c7631e9f90 Bug 1884329 - Remove redundant assertion functions from TabDrawerRobot 2 months ago
AndiAJ 136f00e55f Bug 1846707 - Fix closeAllTabsTest UI test 2 months ago
mike a aa289bc448 Bug 1879373 - Add nav bar to tab preview during swipe-switching 2 months ago
github-actions 3a9e1264f5 Import translations from android-l10n 2 months ago
mcarare 0ae8f720e3 Bug 1876398 - Adjust y offset for new method of positioning.
See https://android-review.googlesource.com/c/platform/frameworks/support/+/2701713.
y offsets are no longer reversed when the menu is near the bottom of the screen.
2 months ago
mcarare a25d950b21 Bug 1876398 - Suppressing deprecation for Swipeable. 2 months ago
Jackie Johnson 561ebfc2d1 Bug 1884154 - Remove openInApp Button Reference from UI Tests 2 months ago
rahulsainani 45cb24460e Bug 1883621 - Add fade edge to long titles in tab strip 2 months ago
AndiAJ 18b52086fd Bug 1833097 - Fix verifyAddAddressViewTest UI test 2 months ago
AndiAJ 03541525b1 Bug 1837569 - Fix verifyStateFieldUpdatesInAccordanceWithCountryFieldTest UI test 2 months ago
sarah541 2a5f1a8b36 Bug 1883753 - Remove menu from custom tab bar 2 months ago
github-actions f86c484851 Import translations from android-l10n 2 months ago
AndiAJ d42aca60dc Bug 1868261 - Add hiding on scroll behaviour to navbar 2 months ago
JohanLorenzo 552a96e5ae Update Fenix initial_experiments.json based on the current first-run experiments in experimenter 2 months ago
AndiAJ f0363a27bb Bug 1881349 - Fix failing Fenix UI tests 2 months ago
Ryan VanderMeulen f1fae35a87 Bug 1881349 - Remove call to removed ensureFullyVisible function 2 months ago
Ryan VanderMeulen c0a894becd Bug 1881349 - Use setText() rather than trying to directly assign the value 2 months ago
ohall-m ea3ef40d0d Bug 1882572 - Instrumenting Translations Nimbus Feature Release
This patch adds instrumentation for releasing separate sections of the
translations feature.
2 months ago
iorgamgabriel 146b63c137 Bug 1883420 - Global Automatic translation text should not be cut off 2 months ago
iorgamgabriel e18a08f88a Bug 1883418 - Translate icon is should be visible on Private Browsing Mode 2 months ago
oana.horvath a04657a0d6 Bug 1883870 - Improve test logs in bookmarks and downloads storage deletion in UI test 2 months ago
rahulsainani 8a2d4cf665 Bug 1882106 - Show undo snackbar when tab is closed via tab strip 2 months ago
t-p-white 7d42525477 Bug 1873457 - throw exception when an unsupported Activity is used in Activity ext 2 months ago
github-actions be13d13683 Import translations from android-l10n 2 months ago
Roger Yang e5e0ccb073 Bug 1875668 - Bypass cache when intercepting site in desktop mode 2 months ago
t-p-white 7146e44bad Bug 1813913 - Added support for Custom Tabs setColorScheme & setColorSchemeParams API 2 months ago
AndiAJ 2e5fc3b409 Bug 1877277 - Translations add Check for isTranslationsEngineSupported 2 months ago
James Hugman cb7afcb65c Bug 1880544 — Add action params to MessageData
This is a breaking change, for experimenter users of the messaging feature.

It tightens up the type of `action` to use the string-alias `ActionName`,
i.e. only keys of the `actions` table.

This is a large improvment in usability for message senders using the
experimenter UI.

This removes the ability to open URLs directly in the action.

For this, the new `action-params` map is used to parameterize the
action's deeplink URL.

For example, whereas before you may have said:

```json
"action": "https://example.com/survey?client={uuid}"
```

now you might write:

```json
"action": "OPEN_URL"
"action-params": {
    "private": "true",
    "url": "https://example.com/survey?client={uuid}"
}
```

`action-params` are specific to each action, and so cannot be validated by
the messsaging system.
2 months ago
rahulsainani 53e1028749 Bug 1883065 - Fix tab strip visibility issue on custom tabs 2 months ago
iorgamgabriel f8871569f8 Bug 1881831 - Translations Integration - Add "Offer to translate when possible" Connection 2 months ago
iorgamgabriel 0b6c95dfed Bug 1879868 - Translations Automatically Popup bottom sheet on Offer Translation 2 months ago
AndiAJ 422b627549 Bug 1882976 - Add logs to ShareOverlayRobot 2 months ago
AndiAJ fecf2c51a8 Bug 1883363 - Add logs to SettingsSubMenuSearchRobot 2 months ago
AndiAJ 690667f1d9 Bug 1883331 - Add logs to SitePermissionsRobot 2 months ago
AndiAJ 5473cc0881 Bug 1883331 - Convert private variables to functions so they don't get initialised 2 months ago
github-actions 7805bb5580 Import translations from android-l10n 2 months ago
AndiAJ 8575c604d2 Bug 1882987 - Add logs to SiteSecurityRobot 2 months ago
AndiAJ a7a1f3d0da Bug 1882987 - Convert private variables to functions so they don't get initialised 2 months ago
AndiAJ 0bbeb07069 Bug 1882987 - Remove redundant assertion functions from SiteSecurityRobot 2 months ago
iorgamgabriel 04d03862d2 Bug 1856986 - Translations UI Integration Preference Logic - Page Settings 2 months ago
AndiAJ fcba28732a Bug 1883021 - Add logs to ThreeDotMenuBookmarksRobot 2 months ago
AndiAJ 5278829968 Bug 1883014 - Add logs to SystemSettingsRobot 2 months ago
AndiAJ e648854b3e Bug 1883014 - Convert private variables to functions so they don't get initialised 2 months ago
AndiAJ 9bf557cf36 Bug 1883005 - Add logs to SyncSignInRobot 2 months ago
iorgamgabriel 9656f1f95e Bug 1862289 - Translations UI Integration Low Data Translate 2 months ago
github-actions 9df7a60315 Import translations from android-l10n 2 months ago
github-actions e30c602dba Import translations from android-l10n 2 months ago
github-actions 0bf41251a9 Import translations from android-l10n 2 months ago
Harrison Oglesby 56e77609ba Bug 1864760 - Hide Menu, Home, and Tab counter button from BrowserFragment Toolbar. 2 months ago
Harrison Oglesby aa8403e585 Bug 1870933 - Remove Tabs and Menu buttons from HomeFragment 2 months ago
Harrison Oglesby f686e75992 Bug 1874298 - Add Reload Page action to PageActions in Toolbar 2 months ago
Harrison Oglesby ff3f340c91 Bug 1870939 - Add Share Page to PageActions in Toolbar 2 months ago
t-p-white 1cad570d3c Bug 1882778 - Remove redundant experiment string juno_onboarding_privacy_notice_text_2 2 months ago
AndiAJ 7a0585fb75 Bug 1882768 - Add logs to SettingsTurnOnSyncRobot 2 months ago
AndiAJ bb8ea98aaa Bug 1882768 - Remove redundant assertion functions from SettingsSubMenuTabsRobot 2 months ago
AndiAJ 00ee20d00e Bug 1882740 - Add logs to SettingsSubMenuTabsRobot 2 months ago
AndiAJ faf5cfed66 Bug 1882740 - Remove redundant assertion functions from SettingsSubMenuTabsRobot 2 months ago
Noah Bond 600b78f2d1 Bug 1882914 - Add `iconOnColorDisabled` color token 2 months ago
t-p-white b4928654d2 Bug 1882308 - Updated custom tab to support private mode 2 months ago
Jonathan Almeida 674bef5781 Bug 1881571 - Add tooling-lint component to Fenix 2 months ago
Ryan VanderMeulen c7a929e411 Bug 1882560 - Update mockk to version 1.13.10 2 months ago
Ryan VanderMeulen cd45447fa5 Bug 1882566 - Update Adjust to version 4.38.2 2 months ago
oana.horvath affd8204e5 Bug 1882777 - Request permission to reset locale in UI tests 2 months ago
AndiAJ 216c8cfdb2 Bug 1882732 - Add logs to SettingsSubMenuSitePermissionsRobot 2 months ago
AndiAJ 2e45df0898 Bug 1882473 - Add logs to SettingsSubMenuSitePermissionsCommonRobot 2 months ago
AndiAJ c5b2384eef Bug 1882473 - Remove redundant assertion functions from SettingsSubMenuSitePermissionsCommonRobot 2 months ago
AndiAJ 33fede0a4b Bug 1882473 - Convert private variables to functions so they don't get initialised 2 months ago
rahulsainani 17b9528e8b Bug 1882107 - Part 2:Make tab strip tabs reorderable 2 months ago
rahulsainani 25648f80a9 Bug 1882107 - Part 1:Add support for LazyRow in ReorderedList 2 months ago
AndiAJ b39a882466 Bug 1882507 - Add logs to SettingsSubMenuSitePermissionsExceptionsRobot 2 months ago
Tif Tran 3496606afd Bug 1880004 - Add Sponsored Mobile Provider 2 months ago
sarah541 2d03674397 Bug 1877833 - Utilize new credential management strings 2 months ago
mike a 0724939144 Bug 1882196 - Adding a nav bar view 2 months ago
mike a f04a3fd90d Bug 1873991 - Fix customtab crash when nav bar is enabled 2 months ago
mike a 68ad8c148e Bug 1868262 - Add Menu button to nav bar 2 months ago
mike a fcb100da84 Bug 1868262 - Add a menu button to navigation bar 2 months ago
mike a 5bba669077 Bug 1868260 – Sync navbar position with toolbar 2 months ago
mike a 5534804101 Bug 1867698 – add a basic nav bar composable 2 months ago
Roger Yang 4e76e98717 Bug 1882123 - Message middleware use store dispatch due to possibility of dispatching in IO thread 2 months ago
DreVla d20b65c304 Bug 1857544 - [a11y]Fully expand review checker when screen reader on 2 months ago
DreVla 0e9c6b63ff Bug 1870701 - Completely Remove straight quotes from RC onboarding 2 months ago
Ryan VanderMeulen 329b360b08 Bug 1880408 - Adapt to Configuration.Provider interface changes 2 months ago
Ryan VanderMeulen 2b187014b4 Bug 1880408 - Remove uses of the deprecated ExistingPeriodicWorkPolicy.REPLACE policy 2 months ago
Issam Mani b7478dface Bug 1882204 - Update removedIn version to 125 for address name strings 2 months ago
github-actions b12c74984b Import translations from android-l10n 2 months ago
ohall-m 4bb2681d5d Bug 1880490 - Moving Translations `supportedLanguages`
This patch refactors Translations `supportedLanguages` from `[SessionState.translationsState]`
to `[BrowserState.translationEngine]`  in AC.

* Additionally adds `InitTranslationsBrowserState` to signal populating `[BrowserState.translationEngine]`.
* This patch also makes adjustments to migrates Fenix's `TranslationsDialogBinding` and `TranslationsBinding`
 to also monitor this new store location.
2 months ago
Gabriel Luong bef24c2b0e Bug 1881128 - Add additional headers for Google requests 2 months ago
Matthew Tighe 63ba218cd1 Bug 1878185 - Add ChangeDetectionMiddleware 2 months ago
Noah Bond 0c7c7a7333 Bug 1876594 - Refactor `ThumbnailStorage` to be an implicit dependency 2 months ago
oana.horvath a9b83fb300 Bug 1881041 - TestSetup helper: refactor RetryTestRule 2 months ago
Issam Mani b44e798924 Bug 1882213 - Fix address autofill view test over-scrolling. 2 months ago
oana.horvath de365d74c6 Bug 1880820 - Create TestSetup helper: Test classes S-W 2 months ago
Aaron Train d38cd687f3 Bug 1882162 - remove JQuery slim test asset 2 months ago
t-p-white 000f5e2623 Bug 1879512 - Added experimental onboarding images for Nimbus 2 months ago
AndiAJ dbf5ec4fff Bug 1882272 - Add logs to SettingsSubMenuPrivateBrowsingRobot 2 months ago
AndiAJ 39f1f91d93 Bug 1882272 - Remove redundant assertion functions from SettingsSubMenuPrivateBrowsingRobot 2 months ago
AndiAJ 5944b5b8bf Bug 1882264 - Add logs to SettingsSubMenuOpenLinksInAppsRobot 2 months ago
AndiAJ 77b69aafd7 Bug 1882264 - Convert private variables to functions so they don't get initialised 2 months ago
Ryan VanderMeulen 065f7e70fc Bug 1882134 - Use jvmToolchain for setting target JVM version 2 months ago
oana.horvath 0c13a2d516 Bug 1880797 - Create TestSetup helper: Settings Test classes 2 months ago
oana.horvath b19419224d Bug 1880796 - Create TestSetup helper: Test classes O-R 2 months ago
oana.horvath b51accb66f Bug 1880497 - Create TestSetup helper: Test classes M-N 2 months ago
oana.horvath edc60d77fd Bug 1880087 - Create TestSetup helper: Test classes D-L 2 months ago
rahulsainani 9582c71045 Bug 1875465 - Part 5: Hide tab strip when full screen 2 months ago
rahulsainani 5ea4da3abe Bug 1875465 - Part 4: Add secret setting and remove toolbar customization 2 months ago
rahulsainani 54d7785896 Bug 1875465 - Part 3: Add tab strip ui for tablets 2 months ago
rahulsainani c91378ceb7 Bug 1875465 - Part 2: Update layout and positioning logic 2 months ago
rahulsainani 8a32c516df Bug 1875465 - Part 1: Set toolbar position if tablet 2 months ago
Roger Yang 398071e988 Bug 1880284 - Show keyboard after voice input 2 months ago
github-actions 99b3abbcc9 Import translations from android-l10n 2 months ago
Jackie Johnson 314f2deed8 Bug 1882170 - Disable Auto-Fill View Tests After Address Fields Were Consolidated 2 months ago
Issam Mani e4af8643e1 Bug 1880075 - Use single name field for addresses 2 months ago
William Durand cc83d5c472 Bug 1870339 - Make list of add-ons more accessible 2 months ago
James Hugman dea7509173 Bug 1880483 — Add inverse triggers to messaging component
This is a breaking change.

This changes the `trigger` key to `trigger-if-all` to document that all
triggers in this list must evaluate to true.

It also adds `exclude-if-any`, a list of triggers which, if any are true
will exclude the message.

This will remove the need for triggers like `I_AM_NOT_BROWSER_DEFAULT`.
2 months ago
oana.horvath 7802427e22 Bug 1882035 - Disable non-sponsored suggestions UI tests in FirefoxSuggestTest 2 months ago
iorgamgabriel ddb15214df Bug 1875817 - Translations Integration Toolbar Showing 2 months ago
iorgamgabriel 936bb85d6c Bug 1878921 - Translations CouldNotLoadLanguagesError UI "Try Again" 2 months ago
oana.horvath dbb3c610a2 Bug 1879525 - Create TestSetup helper: Compose Test classes 2 months ago
rahulsainani 62dd5fe59e Bug 1881703 - Notify app store of mode change from TabsTray 2 months ago
github-actions b742795cd3 Import translations from android-l10n 2 months ago
github-actions c2ebb15742 Import translations from android-l10n 2 months ago
github-actions e76f4820cd Import translations from android-l10n 3 months ago
AndiAJ 06d8df6733 Bug 1881733 - Add logs to SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot 3 months ago
AndiAJ 352c9a64cd Bug 1881733 - Remove redundant assertion functions from SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot 3 months ago
AndiAJ 382540a0f4 Bug 1881733 - Convert private variables to functions so they don't get initialised 3 months ago
AndiAJ 89bd2fc465 Bug 1881491 - Add logs to SettingsSubMenuLoginsAndPasswordRobot 3 months ago
AndiAJ 97fd69d04e Bug 1881491 - Convert private variables to functions so they don't get initialised 3 months ago
AndiAJ cc783b64f7 Bug 1881489 - Add logs to SettingsSubMenuLoginsAndPasswordOptionsToSaveRobot 3 months ago
github-actions bb2620b9da Import translations from android-l10n 3 months ago
James Hugman 8a0b8f58c2 Bug 1880476 — Refactor onMessageDisplayed bookkeeping 3 months ago
Roger Yang 31a92ca2db Bug 1881336 - Remove telemetry probes expiring in v125 3 months ago
James Hugman b5c5527556 Bug 1880476 — Messaging: promote NimbusMessagingController to components.nimbus.messaging 3 months ago
AndiAJ f106a41c3d Bug 1881238 - Add logs to SettingsSubMenuHttpsOnlyModeRobot 3 months ago
AndiAJ 7907e8e606 Bug 1881238 - Convert private variables to functions so they don't get initialised 3 months ago
t-p-white 2dd692a682 Bug 1881016 - Added experimental onboarding strings for Nimbus 3 months ago
mcarare 31613f7088 Bug 1880077 - Switch to using Compose BOM instead of individual versioning 3 months ago
dependabot[bot] 907d1986a3 Bump cryptography
Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.2 to 42.0.4.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/42.0.2...42.0.4)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
3 months ago
github-actions 30fe200284 Import translations from android-l10n 3 months ago
James Hugman 64b636d2a9 Bug 1880476 — Move nimbus from components.analytics to components.nimbus 3 months ago
AndiAJ fc0b206d1f Bug 1881250 - Add logs to SettingsSubMenuLanguageRobot 3 months ago
AndiAJ 875e7ac399 Bug 1881250 - Convert private variables to functions so they don't get initialised 3 months ago
AndiAJ 878676dd98 Bug 1881228 - Add logs to SettingsSubMenuHomepageRobot 3 months ago
AndiAJ 260cff62bf Bug 1881228 - Remove redundant assertion functions from SettingsSubMenuHomepageRobot 3 months ago
DreVla 0b977ba6de Bug 1879507 - Show Default prompt when default-browser card disabled
As part of the Set as default optimization experiment, treatment
branch A will show the "Set as Default" System prompt when the
onboarding started, without showing the default-browser card.
This will be controlled from the experimenter and will require
disabling the default-browser card.
If the user already set Firefox as default browser, this prompt
will not be shown.
3 months ago
t-p-white 854ef2915c Bug 1881009 - Added experimental onboarding strings for Nimbus 3 months ago
github-actions 12bbe2dc36 Import translations from android-l10n 3 months ago
James Hugman 21bc23303f Bug 1880476 — Reduce visibility of fields in Message 3 months ago
James Hugman 2fd8359d30 Bug 1880476 — Rename gleanplumb to nimbus messaging 3 months ago
dependabot[bot] 1b93e27944 Bump cryptography
Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.0 to 42.0.2.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/42.0.0...42.0.2)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
3 months ago
iorgamgabriel 0505682776 Bug 1856979 - Translations UI Post-Translate Popup 3 months ago
AndiAJ 3b1aa89e19 Bug 1881010 - Add logs to SettingsSubMenuDeleteBrowsingDataRobot 3 months ago
AndiAJ 0ea68ff9fc Bug 1881010 - Remove redundant assertion functions from SettingsSubMenuDeleteBrowsingDataRobot 3 months ago
James Hugman 039c1238a8 Bug 1880476 — Remove redundant caching and destroy jexl helper after use 3 months ago
Titouan Thibaud c0111386f8 Bug 1880999 - Start the Nightly 125 development cycle 3 months ago
AndiAJ 861c384d7f Bug 1880827 - Add test logs to SettingsSubMenuDeleteBrowsingDataOnQuitRobot 3 months ago
AndiAJ 5a37a89af2 Bug 1880827 - Convert private variables to functions so they don't get initialised 3 months ago
AndiAJ d8d08dc2c4 Bug 1880821 - Add test logs to SettingsSubMenuDataCollectionRobot 3 months ago
AndiAJ cc1dbb942f Bug 1880812 - Add logs to SettingsSubMenuCustomizeRobot 3 months ago
AndiAJ d371e3bff8 Bug 1880812 - Convert private variables to functions so they don't get initialised 3 months ago
AndiAJ 4c3e3e5c2a Bug 1880808 - Add logs to SearchRobot 3 months ago
AndiAJ 7e49ba72c6 Bug 1880808 - Convert private variables to functions so they don't get initialised 3 months ago
AndiAJ e711687c54 Bug 1880640 - Add pairs of logs to SettingsSubMenuAutofillRobot 3 months ago
AndiAJ 518d89d449 Bug 1880640 - Convert private variables to functions so they don't get initialised 3 months ago
github-actions 847fa3663b Import translations from android-l10n 3 months ago

@ -83,9 +83,11 @@ projects:
- support-rusthttp
- support-rustlog
- support-test
- support-test-fakes
- support-test-libstate
- support-utils
- support-webextensions
- tooling-lint
- ui-autocomplete
- ui-colors
- ui-icons

@ -1 +1 @@
Subproject commit c3b388f801ef6764f709ca1ccc6f5d770a944376
Subproject commit 3b65f840b45fe1c0aed4e1471ffe1cf136a9460e

@ -252,11 +252,6 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
bundle {
// Profiler issues require us to temporarily package native code compressed to
// match the previous APK packaging.
@ -559,6 +554,9 @@ tasks.withType(KotlinCompile).configureEach {
}
dependencies {
implementation platform(ComponentsDependencies.androidx_compose_bom)
androidTestImplementation platform(ComponentsDependencies.androidx_compose_bom)
implementation project(':browser-engine-gecko')
implementation ComponentsDependencies.kotlin_coroutines
@ -658,6 +656,7 @@ dependencies {
implementation project(':lib-crash-sentry')
implementation project(':lib-state')
implementation project(':lib-dataprotect')
testImplementation project(':support-test-fakes')
debugImplementation ComponentsDependencies.leakcanary
forkDebugImplementation ComponentsDependencies.leakcanary
@ -753,6 +752,7 @@ dependencies {
testImplementation "org.mozilla.telemetry:glean-native-forUnitTests:${project.ext.glean_version}"
lintChecks project(":mozilla-lint-rules")
lintChecks project(':tooling-lint')
}
protobuf {

@ -29,9 +29,10 @@ import:
text: default_browser_experiment_card_text
surface: homescreen
action: "MAKE_DEFAULT_BROWSER"
trigger:
- I_AM_NOT_DEFAULT_BROWSER
trigger-if-all:
- USER_ESTABLISHED_INSTALL
exclude-if-any:
- I_AM_DEFAULT_BROWSER
style: PERSISTENT
button-label: preferences_set_as_default_browser
@ -47,7 +48,8 @@ import:
text: nimbus_notification_default_browser_text
surface: notification
style: NOTIFICATION
trigger:
- I_AM_NOT_DEFAULT_BROWSER
trigger-if-all:
- DAY_3_AFTER_INSTALL
exclude-if-any:
- I_AM_DEFAULT_BROWSER
action: MAKE_DEFAULT_BROWSER

@ -854,6 +854,29 @@ events:
notification_emails:
- android-probes@mozilla.com
expires: never
translations_action:
type: event
description: |
An area inside the translations feature was tapped.
The name of the translations area that the user tapped is stored in extras with the
key `item`.
extra_keys:
item:
description: |
A string containing the name of the item the user tapped. These items
include:
main_flow_toolbar, main_flow_browser, page_settings, global_settings,
global_lang_settings, global_site_settings, downloads
type: string
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1883968
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1883968#c6
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
splash_screen:
first_launch_extended:
@ -2654,25 +2677,6 @@ metrics:
metadata:
tags:
- Experiments
font_list_json:
type: text
lifetime: ping
description: |
A JSON blob representing the installed fonts
send_in_pings:
- font-list
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1858193
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1858193#c2
data_sensitivity:
# Text metrics are _required_ to be web_activity or highly_sensitive, so even though this
# is more like 'technical' (per the Data Review), I'm marking highly sensitive.
- highly_sensitive
notification_emails:
- android-probes@mozilla.com
- tom@mozilla.com
expires: 124
customize_home:
most_visited_sites:

@ -377,6 +377,50 @@ features:
type: Int
default: 1
translations:
description: The feature that allows on-device translations of web content.
variables:
main-flow-toolbar-enabled:
description: >
Show the primary toolbar entry point into the translations feature. (Translations icon on URL toolbar.)
type: Boolean
default: false
main-flow-browser-menu-enabled:
description: >
Show the browser menu entry point into the translations feature. ('Translate Page' on browser menu.)
type: Boolean
default: false
page-settings-enabled:
description: >
Show the page settings entry point within the translations feature. (Gear icon on the translations main flow page.)
'main-flow-toolbar-enabled' or 'main-flow-browser-menu-enabled' must also be enabled for users to access this feature.
type: Boolean
default: false
global-settings-enabled:
description: >
Show the global settings entry point within the translations feature. ('Translation Settings' on the page settings view.)
'page-settings-enabled' must also be enabled for users to access this feature.
type: Boolean
default: false
global-lang-settings-enabled:
description: >
Show the global language options entry point for automatically translating. ('Automatic Translation' on the global settings view.)
'global-settings-enabled' must also be enabled for users to access this feature.
type: Boolean
default: false
global-site-settings-enabled:
description: >
Show the global never translate this site options entry point for site management. ('Never translate these sites' on the global settings view.)
'global-settings-enabled' must also be enabled for users to access this feature.
type: Boolean
default: false
downloads-enabled:
description: >
Show the global language model download options entry point for translations. ('Download languages' on the global settings view.)
'global-settings-enabled' must also be enabled for users to access this feature.
type: Boolean
default: false
types:
objects: {}

@ -32,7 +32,6 @@ features:
add-search-widget:
card-type: add-search-widget
enabled: false
title: juno_onboarding_add_search_widget_title
body: juno_onboarding_add_search_widget_description
image-res: ic_onboarding_search_widget

File diff suppressed because one or more lines are too long

@ -1,6 +1,5 @@
<html>
<script src="jquery-3.4.1.slim.min.js"></script>
<script>
function setCookie(newVal){

@ -34,15 +34,21 @@ import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import junit.framework.AssertionFailedError
import kotlinx.coroutines.runBlocking
import mozilla.appservices.places.BookmarkRoot
import mozilla.components.browser.storage.sync.PlacesBookmarksStorage
import mozilla.components.browser.storage.sync.PlacesHistoryStorage
import org.junit.Assert
import org.junit.Assert.assertEquals
import org.mozilla.fenix.Config
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.components.PermissionStorage
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
import org.mozilla.fenix.helpers.Constants.PackageName.PIXEL_LAUNCHER
import org.mozilla.fenix.helpers.Constants.PackageName.YOUTUBE_APP
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.ext.waitNotNull
import org.mozilla.fenix.helpers.idlingresource.NetworkConnectionIdlingResource
@ -53,11 +59,20 @@ import java.util.Locale
object AppAndSystemHelper {
private val bookmarksStorage = PlacesBookmarksStorage(appContext.applicationContext)
suspend fun bookmarks() = bookmarksStorage.getTree(BookmarkRoot.Mobile.id)?.children
fun getPermissionAllowID(): String {
Log.i(TAG, "getPermissionAllowID: Trying to get the permission button resource ID based on API.")
return when
(Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
true -> "com.android.permissioncontroller"
false -> "com.android.packageinstaller"
true -> {
Log.i(TAG, "getPermissionAllowID: Getting the permission button resource ID for API ${Build.VERSION.SDK_INT}.")
"com.android.permissioncontroller"
}
false -> {
Log.i(TAG, "getPermissionAllowID: Getting the permission button resource ID for API ${Build.VERSION.SDK_INT}.")
"com.android.packageinstaller"
}
}
}
@ -69,31 +84,36 @@ object AppAndSystemHelper {
*/
fun deleteDownloadedFileOnStorage(fileName: String) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
Log.i(TAG, "deleteDownloadedFileOnStorage: Trying to delete file from API ${Build.VERSION.SDK_INT}.")
val storageManager: StorageManager? =
TestHelper.appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager?
appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager?
val storageVolumes = storageManager!!.storageVolumes
val storageVolume: StorageVolume = storageVolumes[0]
val file = File(storageVolume.directory!!.path + "/Download/" + fileName)
try {
if (file.exists()) {
Log.i(TAG, "deleteDownloadedFileOnStorage: The file exists. Trying to delete $fileName, try 1.")
file.delete()
Log.d("TestLog", "File delete try 1")
Assert.assertFalse("The file was not deleted", file.exists())
Assert.assertFalse("$TAG deleteDownloadedFileOnStorage: The $fileName file was not deleted", file.exists())
Log.i(TAG, "deleteDownloadedFileOnStorage: Verified the $fileName file was deleted.")
}
} catch (e: AssertionError) {
Log.i(TAG, "deleteDownloadedFileOnStorage: AssertionError caught. Retrying to delete the file.")
file.delete()
Log.d("TestLog", "File delete retried")
Assert.assertFalse("The file was not deleted", file.exists())
Log.i(TAG, "deleteDownloadedFileOnStorage: Retrying to delete $fileName.")
Assert.assertFalse("$TAG deleteDownloadedFileOnStorage: The file was not deleted", file.exists())
Log.i(TAG, "deleteDownloadedFileOnStorage: Verified the $fileName file was deleted, try 2.")
}
} else {
runBlocking {
Log.i(TAG, "deleteDownloadedFileOnStorage: Trying to delete file from API ${Build.VERSION.SDK_INT}.")
val downloadedFile = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
fileName,
)
if (downloadedFile.exists()) {
Log.i(TAG, "deleteDownloadedFileOnStorage: Verifying if $downloadedFile exists.")
Log.i(TAG, "deleteDownloadedFileOnStorage: The file exists. Trying to delete the file.")
downloadedFile.delete()
Log.i(TAG, "deleteDownloadedFileOnStorage: $downloadedFile deleted.")
}
@ -107,38 +127,55 @@ object AppAndSystemHelper {
* Environment.getExternalStorageDirectory() is deprecated starting with API 29.
*/
fun clearDownloadsFolder() {
Log.i(TAG, "clearDownloadsFolder: Detected API ${Build.VERSION.SDK_INT}")
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
Log.i(TAG, "clearDownloadsFolder: API > 29")
val storageManager: StorageManager? =
TestHelper.appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager?
appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager?
val storageVolumes = storageManager!!.storageVolumes
val storageVolume: StorageVolume = storageVolumes[0]
val downloadsFolder = File(storageVolume.directory!!.path + "/Download/")
// Check if the downloads folder exists
if (downloadsFolder.exists() && downloadsFolder.isDirectory) {
Log.i(TAG, "clearDownloadsFolder: Verified that \"DOWNLOADS\" folder exists")
val files = downloadsFolder.listFiles()
Log.i(TAG, "clearDownloadsFolder: Verified that \"DOWNLOADS\" folder exists.")
var files = downloadsFolder.listFiles()
// Check if the folder is not empty
if (files != null && files.isNotEmpty()) {
Log.i(
TAG,
"clearDownloadsFolder: Verified that \"DOWNLOADS\" folder is not empty",
"clearDownloadsFolder: Before cleanup: Downloads storage contains: ${files.size} file(s).",
)
// Delete all files in the folder
for (file in files) {
for (file in files!!) {
Log.i(
TAG,
"clearDownloadsFolder: Trying to delete $file from \"DOWNLOADS\" folder.",
)
file.delete()
Log.i(TAG, "clearDownloadsFolder: Deleted $file from \"DOWNLOADS\" folder")
Log.i(
TAG,
"clearDownloadsFolder: Deleted $file from \"DOWNLOADS\" folder.",
)
files = downloadsFolder.listFiles()
Log.i(
TAG,
"clearDownloadsFolder: After cleanup: Downloads storage contains: ${files?.size} file(s).",
)
}
} else {
Log.i(
TAG,
"clearDownloadsFolder: Downloads storage is empty.",
)
}
}
} else {
runBlocking {
Log.i(TAG, "clearDownloadsFolder: API <= 29")
Log.i(TAG, "clearDownloadsFolder: Verifying if any download files exist.")
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.listFiles()?.forEach {
Log.i(TAG, "clearDownloadsFolder: Trying to delete from storage: $it.")
it.delete()
Log.i(TAG, "clearDownloadsFolder: Download file $it deleted.")
}
@ -146,33 +183,106 @@ object AppAndSystemHelper {
}
}
suspend fun deleteHistoryStorage() {
val historyStorage = PlacesHistoryStorage(appContext.applicationContext)
Log.i(
TAG,
"deleteHistoryStorage before cleanup: History storage contains: ${historyStorage.getVisited()}",
)
if (historyStorage.getVisited().isNotEmpty()) {
Log.i(TAG, "deleteHistoryStorage: Trying to delete all history storage.")
historyStorage.deleteEverything()
Log.i(
TAG,
"deleteHistoryStorage after cleanup: History storage contains: ${historyStorage.getVisited()}",
)
}
}
suspend fun deleteBookmarksStorage() {
val bookmarks = bookmarks()
Log.i(TAG, "deleteBookmarksStorage before cleanup: Bookmarks storage contains: $bookmarks")
if (bookmarks?.isNotEmpty() == true) {
bookmarks.forEach {
Log.i(
TAG,
"deleteBookmarksStorage: Trying to delete $it bookmark from storage.",
)
bookmarksStorage.deleteNode(it.guid)
Log.i(
TAG,
"deleteBookmarksStorage: Bookmark deleted. Bookmarks storage contains: ${bookmarks()}",
)
}
}
}
suspend fun deletePermissionsStorage() {
val permissionStorage = PermissionStorage(appContext.applicationContext)
Log.i(
TAG,
"deletePermissionsStorage: Trying to delete permissions. Permissions storage contains: ${permissionStorage.getSitePermissionsPaged()}",
)
permissionStorage.deleteAllSitePermissions()
Log.i(
TAG,
"deletePermissionsStorage: Permissions deleted. Permissions storage contains: ${permissionStorage.getSitePermissionsPaged()}",
)
}
fun setNetworkEnabled(enabled: Boolean) {
val networkDisconnectedIdlingResource = NetworkConnectionIdlingResource(false)
val networkConnectedIdlingResource = NetworkConnectionIdlingResource(true)
when (enabled) {
true -> {
Log.i(
TAG,
"setNetworkEnabled: Trying to enable the network connection.",
)
mDevice.executeShellCommand("svc data enable")
Log.i(
TAG,
"setNetworkEnabled: Data network connection enable command sent.",
)
mDevice.executeShellCommand("svc wifi enable")
Log.i(
TAG,
"setNetworkEnabled: Wifi network connection enable command sent.",
)
// Wait for network connection to be completely enabled
Log.i(TAG, "setNetworkEnabled: Waiting for connection to be enabled.")
IdlingRegistry.getInstance().register(networkConnectedIdlingResource)
Espresso.onIdle {
IdlingRegistry.getInstance().unregister(networkConnectedIdlingResource)
}
Log.i(TAG, "setNetworkEnabled: Network connection was enabled")
Log.i(TAG, "setNetworkEnabled: Network connection was enabled.")
}
false -> {
Log.i(
TAG,
"setNetworkEnabled: Trying to disable the network connection.",
)
mDevice.executeShellCommand("svc data disable")
Log.i(
TAG,
"setNetworkEnabled: Data network connection disable command sent.",
)
mDevice.executeShellCommand("svc wifi disable")
Log.i(
TAG,
"setNetworkEnabled: Wifi network connection disable command sent.",
)
// Wait for network connection to be completely disabled
Log.i(TAG, "setNetworkEnabled: Waiting for connection to be disabled.")
IdlingRegistry.getInstance().register(networkDisconnectedIdlingResource)
Espresso.onIdle {
IdlingRegistry.getInstance().unregister(networkDisconnectedIdlingResource)
}
Log.i(TAG, "setNetworkEnabled: Network connection was disabled")
Log.i(TAG, "setNetworkEnabled: Network connection was disabled.")
}
}
}
@ -182,6 +292,8 @@ object AppAndSystemHelper {
return try {
val packageManager = InstrumentationRegistry.getInstrumentation().context.packageManager
packageManager.getApplicationInfo(packageName, 0).enabled
Log.i(TAG, "isPackageInstalled: $packageName is installed.")
true
} catch (e: PackageManager.NameNotFoundException) {
Log.i(TAG, "isPackageInstalled: $packageName is not installed - ${e.message}")
false
@ -190,18 +302,18 @@ object AppAndSystemHelper {
fun assertExternalAppOpens(appPackageName: String) {
if (isPackageInstalled(appPackageName)) {
Log.i(TAG, "assertExternalAppOpens: $appPackageName is installed on device")
try {
Log.i(TAG, "assertExternalAppOpens: Try block")
Log.i(TAG, "assertExternalAppOpens: Trying to check the intent sent.")
intended(toPackage(appPackageName))
Log.i(TAG, "assertExternalAppOpens: Matched intent to $appPackageName")
Log.i(TAG, "assertExternalAppOpens: Matched open intent to $appPackageName.")
} catch (e: AssertionFailedError) {
Log.i(TAG, "assertExternalAppOpens: Catch block - ${e.message}")
Log.i(TAG, "assertExternalAppOpens: Intent match failure. ${e.message}")
}
} else {
Log.i(TAG, "assertExternalAppOpens: Trying to verify the \"Could not open file\" message.")
mDevice.waitNotNull(
Until.findObject(By.text("Could not open file")),
TestAssetHelper.waitingTime,
waitingTime,
)
Log.i(TAG, "assertExternalAppOpens: Verified \"Could not open file\" message")
}
@ -209,17 +321,28 @@ object AppAndSystemHelper {
fun assertNativeAppOpens(appPackageName: String, url: String = "") {
if (isPackageInstalled(appPackageName)) {
mDevice.waitForIdle(TestAssetHelper.waitingTimeShort)
Log.i(TAG, "assertNativeAppOpens: Waiting for the device to be idle $waitingTimeShort ms.")
mDevice.waitForIdle(waitingTimeShort)
Log.i(TAG, "assertNativeAppOpens: Waited for the device to be idle $waitingTimeShort ms.")
Log.i(TAG, "assertNativeAppOpens: Trying to match the app package name is matched.")
Assert.assertTrue(
TestHelper.mDevice.findObject(UiSelector().packageName(appPackageName))
.waitForExists(TestAssetHelper.waitingTime),
"$TAG $appPackageName not found",
mDevice.findObject(UiSelector().packageName(appPackageName))
.waitForExists(waitingTime),
)
Log.i(TAG, "assertNativeAppOpens: App package name matched.")
} else {
Log.i(TAG, "assertNativeAppOpens: Trying to verify the page redirect URL.")
BrowserRobot().verifyUrl(url)
Log.i(TAG, "assertNativeAppOpens: Verified the page redirect URL.")
}
}
fun assertYoutubeAppOpens() = intended(toPackage(YOUTUBE_APP))
fun assertYoutubeAppOpens() {
Log.i(TAG, "assertYoutubeAppOpens: Trying to check the intent to YouTube.")
intended(toPackage(YOUTUBE_APP))
Log.i(TAG, "assertYoutubeAppOpens: Verified the intent matches YouTube.")
}
/**
* Checks whether the latest activity of the application is used for custom tabs or PWAs.
@ -227,11 +350,16 @@ object AppAndSystemHelper {
* @return Boolean value that helps us know if the current activity supports custom tabs or PWAs.
*/
fun isExternalAppBrowserActivityInCurrentTask(): Boolean {
Log.i(TAG, "Trying to verify that the latest activity of the application is used for custom tabs or PWAs")
val activityManager = TestHelper.appContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val activityManager = appContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
mDevice.waitForIdle(TestAssetHelper.waitingTimeShort)
Log.i(TAG, "isExternalAppBrowserActivityInCurrentTask: Waiting for the device to be idle for $waitingTimeShort ms")
mDevice.waitForIdle(waitingTimeShort)
Log.i(TAG, "isExternalAppBrowserActivityInCurrentTask: Waited for the device to be idle for $waitingTimeShort ms")
Log.i(
TAG,
"isExternalAppBrowserActivityInCurrentTask: Trying to verify that the latest activity of the application is used for custom tabs or PWAs",
)
return activityManager.appTasks[0].taskInfo.topActivity!!.className == ExternalAppBrowserActivity::class.java.name
}
@ -246,14 +374,18 @@ object AppAndSystemHelper {
testBlock: () -> Unit,
) {
idlingResources.forEach {
Log.i(TAG, "registerAndCleanupIdlingResources: Trying to register idling resource $it.")
IdlingRegistry.getInstance().register(it)
Log.i(TAG, "registerAndCleanupIdlingResources: Registered idling resource $it.")
}
try {
testBlock()
} finally {
idlingResources.forEach {
Log.i(TAG, "registerAndCleanupIdlingResources: Trying to unregister idling resource $it.")
IdlingRegistry.getInstance().unregister(it)
Log.i(TAG, "registerAndCleanupIdlingResources: Unregistered idling resource $it.")
}
}
}
@ -271,18 +403,26 @@ object AppAndSystemHelper {
)
if (Build.VERSION.SDK_INT >= 23) {
if (whileUsingTheAppPermissionButton.waitForExists(TestAssetHelper.waitingTimeShort)) {
if (whileUsingTheAppPermissionButton.waitForExists(waitingTimeShort)) {
Log.i(TAG, "grantSystemPermission: Trying to click the \"While using the app\" button.")
whileUsingTheAppPermissionButton.click()
} else if (allowPermissionButton.waitForExists(TestAssetHelper.waitingTimeShort)) {
Log.i(TAG, "grantSystemPermission: Clicked the \"While using the app\" button.")
} else if (allowPermissionButton.waitForExists(waitingTimeShort)) {
Log.i(TAG, "grantSystemPermission: Trying to click the \"Allow\" button.")
allowPermissionButton.click()
Log.i(TAG, "grantSystemPermission: Clicked the \"Allow\" button.")
}
}
}
// Permission deny dialogs differ on various Android APIs
fun denyPermission() {
mDevice.findObject(UiSelector().textContains("Deny")).waitForExists(TestAssetHelper.waitingTime)
Log.i(TAG, "denyPermission: Waiting $waitingTime ms for the \"Deny\" button to exist.")
mDevice.findObject(UiSelector().textContains("Deny")).waitForExists(waitingTime)
Log.i(TAG, "denyPermission: Waited for $waitingTime ms for the \"Deny\" button to exist.")
Log.i(TAG, "denyPermission: Trying to click the \"Deny\" button.")
mDevice.findObject(UiSelector().textContains("Deny")).click()
Log.i(TAG, "denyPermission: Clicked the \"Deny\" button.")
}
fun isTestLab(): Boolean {
@ -291,71 +431,76 @@ object AppAndSystemHelper {
/**
* 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.
* As a safety measure, always add the resetSystemLocaleToEnUS() method in the tearDown method of your Class.
*/
fun runWithSystemLocaleChanged(locale: Locale, testRule: ActivityTestRule<HomeActivity>, testBlock: () -> Unit) {
val defaultLocale = Locale.getDefault()
try {
Log.i(TAG, "runWithSystemLocaleChanged: Trying to set the locale.")
setSystemLocale(locale)
Log.i(TAG, "runWithSystemLocaleChanged: Running the test block.")
testBlock()
ThreadUtils.runOnUiThread { testRule.activity.recreate() }
Log.i(TAG, "runWithSystemLocaleChanged: Test block finished.")
} catch (e: Exception) {
Log.i(TAG, "runWithSystemLocaleChanged: The test block has thrown an exception.${e.message}")
e.printStackTrace()
} finally {
Log.i(TAG, "runWithSystemLocaleChanged: Trying to reset the locale to default.")
setSystemLocale(defaultLocale)
}
}
/**
* Changes the default language of the entire device, not just the app.
* We can only use this if we're running on a debug build, otherwise it will change the permission manifests in release builds.
*/
fun setSystemLocale(locale: Locale) {
if (Config.channel.isDebug) {
/* Sets permission to change device language */
Log.i(
TAG,
"setSystemLocale: Requesting permission to change system locale to $locale.",
)
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)
}
}
}
/**
* Resets the default language of the entire device back to EN-US.
* In case of a test instrumentation crash, the finally statement in the
* runWithSystemLocaleChanged(locale: Locale) method, will not be reached.
* Add this method inside the tearDown method of your test class, where the above method is used.
* Note: If set inside the ActivityTestRule's afterActivityFinished() method, this also won't work,
* as the methods inside it are not always executed: https://github.com/android/android-test/issues/498
*/
fun resetSystemLocaleToEnUS() {
if (Locale.getDefault() != Locale.US) {
Log.i(TAG, "Resetting system locale to EN US")
setSystemLocale(Locale.US)
Log.i(
TAG,
"setSystemLocale: Received permission to change system locale to $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)
}
}
/**
* Changes the default language of the entire device, not just the app.
*/
fun setSystemLocale(locale: Locale) {
val activityManagerNative = Class.forName("android.app.ActivityManagerNative")
val am = activityManagerNative.getMethod("getDefault", *arrayOfNulls(0))
.invoke(activityManagerNative, *arrayOfNulls(0))
val config = InstrumentationRegistry.getInstrumentation().context.resources.configuration
config.javaClass.getDeclaredField("locale")[config] = locale
config.javaClass.getDeclaredField("userSetLocale").setBoolean(config, true)
am.javaClass.getMethod(
"updateConfiguration",
Configuration::class.java,
).invoke(am, config)
Log.i(
TAG,
"setSystemLocale: Changed system locale to $locale.",
)
}
fun putAppToBackground() {
Log.i(TAG, "putAppToBackground: Trying to press the device Recent apps button.")
mDevice.pressRecentApps()
Log.i(TAG, "putAppToBackground: Pressed the device Recent apps button.")
Log.i(TAG, "putAppToBackground: Waiting for the app to be gone for $waitingTime ms.")
mDevice.findObject(UiSelector().resourceId("${TestHelper.packageName}:id/container")).waitUntilGone(
TestAssetHelper.waitingTime,
waitingTime,
)
Log.i(TAG, "putAppToBackground: Waited for the app to be gone for $waitingTime ms.")
}
/**
@ -364,12 +509,19 @@ object AppAndSystemHelper {
* The recent apps tray on API 30 will always display only 2 apps, even if previously were opened more.
* The index of the most recent opened app will always have index 2, meaning that the previously opened app will have index 1.
*/
fun bringAppToForeground() =
mDevice.findObject(UiSelector().index(2).packageName(PIXEL_LAUNCHER)).clickAndWaitForNewWindow(waitingTimeShort)
fun bringAppToForeground() {
Log.i(TAG, "bringAppToForeground: Trying to select the app from the recent apps tray and wait for $waitingTime ms for a new window")
mDevice.findObject(UiSelector().index(2).packageName(PIXEL_LAUNCHER))
.clickAndWaitForNewWindow(waitingTimeShort)
Log.i(TAG, "bringAppToForeground: Selected the app from the recent apps tray.")
}
fun verifyKeyboardVisibility(isExpectedToBeVisible: Boolean = true) {
Log.i(TAG, "verifyKeyboardVisibility: Waiting for the device to be idle.")
mDevice.waitForIdle()
Log.i(TAG, "verifyKeyboardVisibility: Waited for the device to be idle.")
Log.i(TAG, "verifyKeyboardVisibility: Trying to verify the keyboard is visible.")
assertEquals(
"Keyboard not shown",
isExpectedToBeVisible,
@ -377,6 +529,7 @@ object AppAndSystemHelper {
.executeShellCommand("dumpsys input_method | grep mInputShown")
.contains("mInputShown=true"),
)
Log.i(TAG, "verifyKeyboardVisibility: Verified the keyboard is visible.")
}
fun openAppFromExternalLink(url: String) {
@ -388,10 +541,14 @@ object AppAndSystemHelper {
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
try {
Log.i(TAG, "openAppFromExternalLink: Trying to start the activity from an external intent.")
context.startActivity(intent)
Log.i(TAG, "openAppFromExternalLink: Activity started from an external intent.")
} catch (ex: ActivityNotFoundException) {
Log.i(TAG, "openAppFromExternalLink: Exception caught. Trying to start the activity from a null intent.")
intent.setPackage(null)
context.startActivity(intent)
Log.i(TAG, "openAppFromExternalLink: Started the activity from a null intent.")
}
}
@ -400,6 +557,7 @@ object AppAndSystemHelper {
* For example: this method will avoid accidentally running a test on GV versions where the feature is disabled.
*/
fun runWithCondition(condition: Boolean, testBlock: () -> Unit) {
Log.i(TAG, "runWithCondition: Trying to run the test based on condition. The condition is: $condition.")
if (condition) {
testBlock()
}
@ -416,11 +574,15 @@ object AppAndSystemHelper {
addCategory(Intent.CATEGORY_LAUNCHER)
}
Log.i(TAG, "runWithLauncherIntent: Trying to launch the activity from an intent: $launcherIntent.")
activityTestRule.activityRule.withIntent(launcherIntent).launchActivity(launcherIntent)
Log.i(TAG, "runWithLauncherIntent: Launched the activity from an intent: $launcherIntent.")
try {
Log.i(TAG, "runWithLauncherIntent: Trying run the test block.")
testBlock()
Log.i(TAG, "runWithLauncherIntent: Finished running the test block.")
} catch (e: Exception) {
Log.i(TAG, "runWithLauncherIntent: Exception caught while running the test block: ${e.message}")
e.printStackTrace()
}
}

@ -6,7 +6,9 @@ package org.mozilla.fenix.helpers
import android.graphics.Bitmap
import android.graphics.Color
import android.util.Log
import org.junit.Assert.assertEquals
import org.mozilla.fenix.helpers.Constants.TAG
/**
* Asserts the two bitmaps are the same by ensuring their dimensions, config, and
@ -14,6 +16,7 @@ import org.junit.Assert.assertEquals
* [Bitmap.sameAs] uses.
*/
fun assertEqualsWithDelta(expectedB: Bitmap, actualB: Bitmap, delta: Float) {
Log.i(TAG, "assertEqualsWithDelta: Trying to verify that the Bitmap of $expectedB is equal with the Bitmap of $actualB within delta: $delta")
assertEquals("widths should be equal", expectedB.width, actualB.width)
assertEquals("heights should be equal", expectedB.height, actualB.height)
assertEquals("config should be equal", expectedB.config, actualB.config)
@ -29,4 +32,5 @@ fun assertEqualsWithDelta(expectedB: Bitmap, actualB: Bitmap, delta: Float) {
assertEquals("$warn b", Color.blue(ePx).toFloat(), Color.blue(aPx).toFloat(), delta)
}
}
Log.i(TAG, "assertEqualsWithDelta: Verified that the Bitmap of $expectedB is equal with the Bitmap of $actualB within delta: $delta")
}

@ -13,6 +13,7 @@ import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.net.Uri
import android.util.Log
import androidx.browser.customtabs.CustomTabsIntent
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiSelector
@ -20,6 +21,7 @@ import mozilla.components.browser.state.search.SearchEngine
import mozilla.components.browser.state.state.availableSearchEngines
import org.junit.Assert
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.utils.IntentUtils
import java.time.LocalDate
@ -33,6 +35,7 @@ object DataGenerationHelper {
customMenuItemLabel: String = "",
customActionButtonDescription: String = "",
): Intent {
Log.i(TAG, "createCustomTabIntent: Trying to create custom tab intent with url: $pageUrl")
val appContext = InstrumentationRegistry.getInstrumentation()
.targetContext
.applicationContext
@ -48,33 +51,44 @@ object DataGenerationHelper {
)
.build()
customTabsIntent.intent.data = Uri.parse(pageUrl)
Log.i(TAG, "createCustomTabIntent: Created custom tab intent with url: $pageUrl")
return customTabsIntent.intent
}
private fun createTestBitmap(): Bitmap {
Log.i(TAG, "createTestBitmap: Trying to create a test bitmap")
val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
canvas.drawColor(Color.GREEN)
Log.i(TAG, "createTestBitmap: Created a test bitmap")
return bitmap
}
fun getStringResource(id: Int, argument: String = TestHelper.appName) = TestHelper.appContext.resources.getString(id, argument)
private val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
fun generateRandomString(stringLength: Int) =
(1..stringLength)
.map { kotlin.random.Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("")
fun generateRandomString(stringLength: Int): String {
Log.i(TAG, "generateRandomString: Trying to generate a random string with $stringLength characters")
val randomString =
(1..stringLength)
.map { kotlin.random.Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("")
Log.i(TAG, "generateRandomString: Generated random string: $randomString")
return randomString
}
/**
* Creates clipboard data.
*/
fun setTextToClipBoard(context: Context, message: String) {
Log.i(TAG, "setTextToClipBoard: Trying to set clipboard text to: $message")
val clipBoard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipData = ClipData.newPlainText("label", message)
clipBoard.setPrimaryClip(clipData)
Log.i(TAG, "setTextToClipBoard: Clipboard text was set to: $message")
}
/**
@ -88,6 +102,7 @@ object DataGenerationHelper {
* @return A string representing the current date and time in the specified format.
*/
fun getSponsoredFxSuggestPlaceHolder(): String {
Log.i(TAG, "getSponsoredFxSuggestPlaceHolder: Trying to get the sponsored search suggestion placeholder")
val currentDate = LocalDate.now()
val currentTime = LocalTime.now()
@ -96,6 +111,8 @@ object DataGenerationHelper {
val currentYear = currentDate.year.toString()
val currentHour = currentTime.hour.toString().padStart(2, '0')
Log.i(TAG, "getSponsoredFxSuggestPlaceHolder: Got: ${currentYear + currentMonth + currentDay + currentHour} as the sponsored search suggestion placeholder")
return currentYear + currentMonth + currentDay + currentHour
}
@ -103,6 +120,7 @@ object DataGenerationHelper {
* Returns sponsored shortcut title based on the index.
*/
fun getSponsoredShortcutTitle(position: Int): String {
Log.i(TAG, "getSponsoredShortcutTitle: Trying to get the title of the sponsored shortcut at position: ${position - 1}")
val sponsoredShortcut = mDevice.findObject(
UiSelector()
.resourceId("${TestHelper.packageName}:id/top_site_item")
@ -111,7 +129,7 @@ object DataGenerationHelper {
UiSelector()
.resourceId("${TestHelper.packageName}:id/top_site_title"),
).text
Log.i(TAG, "getSponsoredShortcutTitle: The sponsored shortcut at position: ${position - 1} has title: $sponsoredShortcut")
return sponsoredShortcut
}
@ -120,8 +138,10 @@ object DataGenerationHelper {
* For en-us it will return the 6 engines selected by default: Google, Bing, DuckDuckGo, Amazon, Ebay, Wikipedia.
*/
fun getRegionSearchEnginesList(): List<SearchEngine> {
Log.i(TAG, "getRegionSearchEnginesList: Trying to get the search engines based on the region of the user")
val searchEnginesList = appContext.components.core.store.state.search.regionSearchEngines
Assert.assertTrue("Search engines list returned nothing", searchEnginesList.isNotEmpty())
Assert.assertTrue("$TAG: Search engines list returned nothing", searchEnginesList.isNotEmpty())
Log.i(TAG, "getRegionSearchEnginesList: Got $searchEnginesList based on the region of the user")
return searchEnginesList
}
@ -130,8 +150,10 @@ object DataGenerationHelper {
* For en-us it will return the 2 engines: Reddit, Youtube.
*/
fun getAvailableSearchEngines(): List<SearchEngine> {
Log.i(TAG, "getAvailableSearchEngines: Trying to get the alternative search engines based on the region of the user")
val searchEnginesList = TestHelper.appContext.components.core.store.state.search.availableSearchEngines
Assert.assertTrue("Search engines list returned nothing", searchEnginesList.isNotEmpty())
Assert.assertTrue("$TAG: Search engines list returned nothing", searchEnginesList.isNotEmpty())
Log.i(TAG, "getAvailableSearchEngines: Got $searchEnginesList based on the region of the user")
return searchEnginesList
}
}

@ -9,11 +9,8 @@ import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.TestHelper.appContext
object Experimentation {
val experiments =
appContext.components.analytics.experiments
fun withHelper(block: NimbusMessagingHelperInterface.() -> Unit) {
val helper = experiments.createMessageHelper()
val helper = appContext.components.nimbus.createJexlHelper()
block(helper)
}
}

@ -82,11 +82,6 @@ interface FeatureSettingsHelper {
*/
var composeTopSitesEnabled: Boolean
/**
* Enable or disable translations flow.
*/
var isTranslationsEnabled: Boolean
fun applyFlagUpdates()
fun resetAllFeatureFlags()

@ -4,8 +4,10 @@
package org.mozilla.fenix.helpers
import android.util.Log
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.getPreferenceKey
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.ETPPolicy.CUSTOM
import org.mozilla.fenix.helpers.ETPPolicy.STANDARD
import org.mozilla.fenix.helpers.ETPPolicy.STRICT
@ -37,7 +39,6 @@ class FeatureSettingsHelperDelegate() : FeatureSettingsHelper {
etpPolicy = getETPPolicy(settings),
tabsTrayRewriteEnabled = settings.enableTabsTrayToCompose,
composeTopSitesEnabled = settings.enableComposeTopSites,
translationsEnabled = settings.enableTranslations,
)
/**
@ -67,14 +68,17 @@ class FeatureSettingsHelperDelegate() : FeatureSettingsHelper {
override var etpPolicy: ETPPolicy by updatedFeatureFlags::etpPolicy
override var tabsTrayRewriteEnabled: Boolean by updatedFeatureFlags::tabsTrayRewriteEnabled
override var composeTopSitesEnabled: Boolean by updatedFeatureFlags::composeTopSitesEnabled
override var isTranslationsEnabled: Boolean by updatedFeatureFlags::translationsEnabled
override fun applyFlagUpdates() {
Log.i(TAG, "applyFlagUpdates: Trying to apply the updated feature flags: $updatedFeatureFlags")
applyFeatureFlags(updatedFeatureFlags)
Log.i(TAG, "applyFlagUpdates: Applied the updated feature flags: $updatedFeatureFlags")
}
override fun resetAllFeatureFlags() {
Log.i(TAG, "resetAllFeatureFlags: Trying to reset the feature flags to: $initialFeatureFlags")
applyFeatureFlags(initialFeatureFlags)
Log.i(TAG, "resetAllFeatureFlags: Performed feature flags reset to: $initialFeatureFlags")
}
override var isDeleteSitePermissionsEnabled: Boolean by updatedFeatureFlags::isDeleteSitePermissionsEnabled
@ -93,7 +97,6 @@ class FeatureSettingsHelperDelegate() : FeatureSettingsHelper {
settings.shouldShowOpenInAppBanner = featureFlags.isOpenInAppBannerEnabled
settings.enableTabsTrayToCompose = featureFlags.tabsTrayRewriteEnabled
settings.enableComposeTopSites = featureFlags.composeTopSitesEnabled
settings.enableTranslations = featureFlags.translationsEnabled
setETPPolicy(featureFlags.etpPolicy)
}
}
@ -113,7 +116,6 @@ private data class FeatureFlags(
var etpPolicy: ETPPolicy,
var tabsTrayRewriteEnabled: Boolean,
var composeTopSitesEnabled: Boolean,
var translationsEnabled: Boolean,
)
internal fun getETPPolicy(settings: Settings): ETPPolicy {
@ -126,9 +128,14 @@ internal fun getETPPolicy(settings: Settings): ETPPolicy {
private fun setETPPolicy(policy: ETPPolicy) {
when (policy) {
STRICT -> settings.setStrictETP()
STRICT -> {
Log.i(TAG, "setETPPolicy: Trying to set ETP policy to: \"Strict\"")
settings.setStrictETP()
Log.i(TAG, "setETPPolicy: ETP policy was set to: \"Strict\"")
}
// The following two cases update ETP in the same way "setStrictETP" does.
STANDARD -> {
Log.i(TAG, "setETPPolicy: Trying to set ETP policy to: \"Standard\"")
settings.preferences.edit()
.putBoolean(
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_strict_default),
@ -143,8 +150,10 @@ private fun setETPPolicy(policy: ETPPolicy) {
true,
)
.commit()
Log.i(TAG, "setETPPolicy: ETP policy was set to: \"Standard\"")
}
CUSTOM -> {
Log.i(TAG, "setETPPolicy: Trying to set ETP policy to: \"Custom\"")
settings.preferences.edit()
.putBoolean(
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_strict_default),
@ -159,19 +168,23 @@ private fun setETPPolicy(policy: ETPPolicy) {
true,
)
.commit()
Log.i(TAG, "setETPPolicy: ETP policy was set to: \"Custom\"")
}
}
}
private fun getHomeOnboardingVersion(): Int {
Log.i(TAG, "getHomeOnboardingVersion: Trying to get the onboarding version")
return FenixOnboarding(appContext)
.preferences
.getInt(FenixOnboarding.LAST_VERSION_ONBOARDING_KEY, 0)
}
private fun setHomeOnboardingVersion(version: Int) {
Log.i(TAG, "setHomeOnboardingVersion: Trying to set the onboarding version to: $version")
FenixOnboarding(appContext)
.preferences.edit()
.putInt(FenixOnboarding.LAST_VERSION_ONBOARDING_KEY, version)
.commit()
Log.i(TAG, "setHomeOnboardingVersion: Onboarding version was set to: $version")
}

@ -7,6 +7,7 @@
package org.mozilla.fenix.helpers
import android.content.Intent
import android.util.Log
import android.view.ViewConfiguration.getLongPressTimeout
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.espresso.intent.rule.IntentsTestRule
@ -14,6 +15,7 @@ import androidx.test.rule.ActivityTestRule
import androidx.test.uiautomator.UiSelector
import org.junit.rules.TestRule
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.FeatureSettingsHelper.Companion.settings
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.mDevice
@ -76,10 +78,12 @@ class HomeActivityTestRule(
* Update settings after the activity was created.
*/
fun applySettingsExceptions(settings: (FeatureSettingsHelper) -> Unit) {
Log.i(TAG, "applySettingsExceptions: Trying to update the settings after the activity was created")
FeatureSettingsHelperDelegate().also {
settings(this)
applyFlagUpdates()
}
Log.i(TAG, "applySettingsExceptions: Updated the settings after the activity was created")
}
private val longTapUserPreference = getLongPressTimeout()
@ -87,14 +91,18 @@ class HomeActivityTestRule(
override fun beforeActivityLaunched() {
super.beforeActivityLaunched()
setLongTapTimeout(3000)
Log.i(TAG, "beforeActivityLaunched: Trying to apply the feature flags updates")
applyFlagUpdates()
Log.i(TAG, "beforeActivityLaunched: Successfully applied the feature flag updates")
if (skipOnboarding) { skipOnboardingBeforeLaunch() }
}
override fun afterActivityFinished() {
super.afterActivityFinished()
setLongTapTimeout(longTapUserPreference)
Log.i(TAG, "afterActivityFinished: Trying to reset all feature flags")
resetAllFeatureFlags()
Log.i(TAG, "afterActivityFinished: Successfully performed the reset of all feature flags")
closeNotificationShade()
}
@ -165,7 +173,6 @@ class HomeActivityIntentTestRule internal constructor(
etpPolicy: ETPPolicy = getETPPolicy(settings),
tabsTrayRewriteEnabled: Boolean = false,
composeTopSitesEnabled: Boolean = false,
translationsEnabled: Boolean = false,
) : this(initialTouchMode, launchActivity, skipOnboarding) {
this.isHomeOnboardingDialogEnabled = isHomeOnboardingDialogEnabled
this.isPocketEnabled = isPocketEnabled
@ -180,7 +187,6 @@ class HomeActivityIntentTestRule internal constructor(
this.etpPolicy = etpPolicy
this.tabsTrayRewriteEnabled = tabsTrayRewriteEnabled
this.composeTopSitesEnabled = composeTopSitesEnabled
this.isTranslationsEnabled = translationsEnabled
}
private val longTapUserPreference = getLongPressTimeout()
@ -191,10 +197,12 @@ class HomeActivityIntentTestRule internal constructor(
* Update settings after the activity was created.
*/
fun applySettingsExceptions(settings: (FeatureSettingsHelper) -> Unit) {
Log.i(TAG, "applySettingsExceptions: Trying to update the settings after the activity was created")
FeatureSettingsHelperDelegate().apply {
settings(this)
applyFlagUpdates()
}
Log.i(TAG, "applySettingsExceptions: Updated the settings after the activity was created")
}
override fun getActivityIntent(): Intent? {
@ -213,7 +221,9 @@ class HomeActivityIntentTestRule internal constructor(
override fun beforeActivityLaunched() {
super.beforeActivityLaunched()
setLongTapTimeout(3000)
Log.i(TAG, "beforeActivityLaunched: Trying to apply the feature flag updates")
applyFlagUpdates()
Log.i(TAG, "beforeActivityLaunched: Successfully applied the feature flag updates")
if (skipOnboarding) { skipOnboardingBeforeLaunch() }
}
@ -221,7 +231,9 @@ class HomeActivityIntentTestRule internal constructor(
super.afterActivityFinished()
setLongTapTimeout(longTapUserPreference)
closeNotificationShade()
Log.i(TAG, "afterActivityFinished: Trying to reset all feature flags")
resetAllFeatureFlags()
Log.i(TAG, "afterActivityFinished: Successfully performed the reset of all feature flags")
}
/**
@ -262,7 +274,6 @@ class HomeActivityIntentTestRule internal constructor(
skipOnboarding: Boolean = false,
tabsTrayRewriteEnabled: Boolean = false,
composeTopSitesEnabled: Boolean = false,
translationsEnabled: Boolean = false,
) = HomeActivityIntentTestRule(
initialTouchMode = initialTouchMode,
launchActivity = launchActivity,
@ -274,7 +285,6 @@ class HomeActivityIntentTestRule internal constructor(
isWallpaperOnboardingEnabled = false,
isOpenInAppBannerEnabled = false,
composeTopSitesEnabled = composeTopSitesEnabled,
translationsEnabled = translationsEnabled,
)
}
}
@ -285,9 +295,12 @@ fun setLongTapTimeout(delay: Int) {
var attempts = 0
while (attempts++ < 3) {
try {
Log.i(TAG, "setLongTapTimeout: Trying to set the \"Touch and hold delay\" to: $delay ms")
mDevice.executeShellCommand("settings put secure long_press_timeout $delay")
Log.i(TAG, "setLongTapTimeout: Executed command \"settings put secure long_press_timeout $delay\"")
break
} catch (e: RuntimeException) {
Log.i(TAG, "setLongTapTimeout: RuntimeException caught, executing fallback methods")
e.printStackTrace()
}
}
@ -296,7 +309,9 @@ fun setLongTapTimeout(delay: Int) {
private fun skipOnboardingBeforeLaunch() {
// The production code isn't aware that we're using
// this API so it can be fragile.
Log.i(TAG, "skipOnboardingBeforeLaunch: Trying to skip the onboarding before launching the app")
FenixOnboarding(appContext).finish()
Log.i(TAG, "skipOnboardingBeforeLaunch: Successfully skipped the onboarding before launching the app")
}
private fun closeNotificationShade() {
@ -304,6 +319,8 @@ private fun closeNotificationShade() {
UiSelector().resourceId("com.android.systemui:id/notification_stack_scroller"),
).exists()
) {
Log.i(TAG, "closeNotificationShade: Trying to press device home button")
mDevice.pressHome()
Log.i(TAG, "closeNotificationShade: Pressed the device home button")
}
}

@ -6,33 +6,16 @@
package org.mozilla.fenix.helpers
import android.util.Log
import androidx.test.espresso.IdlingRegistry
import androidx.test.rule.ActivityTestRule
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.helpers.idlingresource.AddonsInstallingIdlingResource
import org.mozilla.fenix.helpers.Constants.TAG
object IdlingResourceHelper {
// Idling Resource to manage installing an addon
fun registerAddonInstallingIdlingResource(activityTestRule: ActivityTestRule<HomeActivity>) {
IdlingRegistry.getInstance().register(
AddonsInstallingIdlingResource(
activityTestRule.activity.supportFragmentManager,
),
)
}
fun unregisterAddonInstallingIdlingResource(activityTestRule: ActivityTestRule<HomeActivity>) {
IdlingRegistry.getInstance().unregister(
AddonsInstallingIdlingResource(
activityTestRule.activity.supportFragmentManager,
),
)
}
fun unregisterAllIdlingResources() {
for (resource in IdlingRegistry.getInstance().resources) {
Log.i(TAG, "unregisterAllIdlingResources: Trying to unregister ${resource.name} resource")
IdlingRegistry.getInstance().unregister(resource)
Log.i(TAG, "unregisterAllIdlingResources: Unregistered ${resource.name} resource")
}
}
}

@ -96,42 +96,48 @@ object MatcherHelper {
) {
for (appItem in appItems) {
if (exists) {
Log.i(TAG, "assertUIObjectExists: Trying to verify that ${appItem.selector} exists")
assertTrue("${appItem.selector} does not exist", appItem.waitForExists(waitingTime))
Log.i(TAG, "assertUIObjectExists: Verified ${appItem.selector} exists")
Log.i(TAG, "assertUIObjectExists: Verified that ${appItem.selector} exists")
} else {
Log.i(TAG, "assertUIObjectExists: Trying to verify that ${appItem.selector} does not exist")
assertFalse("${appItem.selector} exists", appItem.waitForExists(waitingTimeShort))
Log.i(TAG, "assertUIObjectExists: Verified ${appItem.selector} does not exist")
Log.i(TAG, "assertUIObjectExists: Verified that ${appItem.selector} does not exist")
}
}
}
fun assertUIObjectIsGone(vararg appItems: UiObject) {
for (appItem in appItems) {
Log.i(TAG, "assertUIObjectIsGone: Trying to verify that ${appItem.selector} is gone")
assertTrue("${appItem.selector} is not gone", appItem.waitUntilGone(waitingTime))
Log.i(TAG, "assertUIObjectIsGone: Verified ${appItem.selector} is gone")
Log.i(TAG, "assertUIObjectIsGone: Verified that ${appItem.selector} is gone")
}
}
fun assertItemTextEquals(vararg appItems: UiObject, expectedText: String, isEqual: Boolean = true) {
for (appItem in appItems) {
if (isEqual) {
Log.i(TAG, "assertItemTextEquals: Trying to verify that ${appItem.selector} text equals to $expectedText")
assertTrue(
"${appItem.selector} text does not equal to $expectedText",
appItem.text.equals(expectedText),
)
Log.i(TAG, "assertItemTextEquals: Verified ${appItem.selector} text equals to $expectedText")
} else {
Log.i(TAG, "assertItemTextEquals: Trying to verify that ${appItem.selector} text does not equal to $expectedText")
assertFalse(
"${appItem.selector} text equals to $expectedText",
appItem.text.equals(expectedText),
)
Log.i(TAG, "assertItemTextEquals: Verified ${appItem.selector} text does not equal to $expectedText")
Log.i(TAG, "assertItemTextEquals: Verified that ${appItem.selector} text does not equal to $expectedText")
}
}
}
fun assertItemTextContains(vararg appItems: UiObject, itemText: String) {
for (appItem in appItems) {
Log.i(TAG, "assertItemTextContains: Trying to verify that ${appItem.selector} text contains $itemText")
assertTrue(
"${appItem.selector} text does not contain $itemText",
appItem.text.contains(itemText),
@ -142,6 +148,7 @@ object MatcherHelper {
fun assertItemIsEnabledAndVisible(vararg appItems: UiObject) {
for (appItem in appItems) {
Log.i(TAG, "assertItemIsEnabledAndVisible: Trying to verify that ${appItem.selector} is visible and enabled")
assertTrue(appItem.waitForExists(waitingTime) && appItem.isEnabled)
Log.i(TAG, "assertItemIsEnabledAndVisible: Verified ${appItem.selector} is visible and enabled")
}

@ -5,6 +5,7 @@
package org.mozilla.fenix.helpers
import android.content.Context
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
import kotlinx.coroutines.runBlocking
import mozilla.appservices.places.BookmarkRoot
@ -18,6 +19,7 @@ import mozilla.components.concept.storage.VisitType
import mozilla.components.feature.search.ext.createSearchEngine
import okhttp3.mockwebserver.MockWebServer
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.search.SearchEngineSource.None.searchEngine
@ -32,6 +34,7 @@ object MockBrowserDataHelper {
* @param position Example for the position param: 1u, 2u, etc.
*/
fun createBookmarkItem(url: String, title: String, position: UInt?) {
Log.i(TAG, "createBookmarkItem: Trying to add bookmark item at position: $position, with url: $url, and with title: $title")
runBlocking {
PlacesBookmarksStorage(context)
.addItem(
@ -41,6 +44,7 @@ object MockBrowserDataHelper {
position,
)
}
Log.i(TAG, "createBookmarkItem: Added bookmark item at position: $position, with url: $url, and with title: $title")
}
/**
@ -49,6 +53,7 @@ object MockBrowserDataHelper {
* @param url The URL of the history item to add. URLs should use the "https://example.com" format.
*/
fun createHistoryItem(url: String) {
Log.i(TAG, "createHistoryItem: Trying to add history item with url: $url")
runBlocking {
PlacesHistoryStorage(appContext)
.recordVisit(
@ -56,6 +61,7 @@ object MockBrowserDataHelper {
PageVisit(VisitType.LINK),
)
}
Log.i(TAG, "createHistoryItem: Added history item with url: $url")
}
/**
@ -64,9 +70,11 @@ object MockBrowserDataHelper {
* URLs should use the "https://example.com" format.
*/
fun createTabItem(url: String) {
Log.i(TAG, "createTabItem: Trying to create a new tab with url: $url")
runBlocking {
appContext.components.useCases.tabsUseCases.addTab(url)
}
Log.i(TAG, "createTabItem: Created a new tab with url: $url")
}
/**
@ -74,7 +82,9 @@ object MockBrowserDataHelper {
*
*/
fun createSearchHistory(searchTerm: String) {
Log.i(TAG, "createSearchHistory: Trying to perform a new search with search term: $searchTerm")
appContext.components.useCases.searchUseCases.newTabSearch.invoke(searchTerm)
Log.i(TAG, "createSearchHistory: Performed a new search with search term: $searchTerm")
}
/**
@ -86,6 +96,7 @@ object MockBrowserDataHelper {
private fun createCustomSearchEngine(mockWebServer: MockWebServer, searchEngineName: String): SearchEngine {
val searchString =
"http://localhost:${mockWebServer.port}/pages/searchResults.html?search={searchTerms}"
Log.i(TAG, "createCustomSearchEngine: Trying to create a custom search engine named: $searchEngineName and search string: $searchString")
return createSearchEngine(
name = searchEngineName,
url = searchString,
@ -100,8 +111,9 @@ object MockBrowserDataHelper {
*/
fun addCustomSearchEngine(mockWebServer: MockWebServer, searchEngineName: String) {
val searchEngine = createCustomSearchEngine(mockWebServer, searchEngineName)
Log.i(TAG, "addCustomSearchEngine: Trying to add a custom search engine named: $searchEngineName")
appContext.components.useCases.searchUseCases.addSearchEngine(searchEngine)
Log.i(TAG, "addCustomSearchEngine: Added a custom search engine named: $searchEngineName")
}
/**
@ -111,10 +123,11 @@ object MockBrowserDataHelper {
*/
fun setCustomSearchEngine(mockWebServer: MockWebServer, searchEngineName: String) {
val searchEngine = createCustomSearchEngine(mockWebServer, searchEngineName)
Log.i(TAG, "setCustomSearchEngine: Trying to set a custom search engine named: $searchEngineName")
with(appContext.components.useCases.searchUseCases) {
addSearchEngine(searchEngine)
selectSearchEngine(searchEngine)
}
Log.i(TAG, "setCustomSearchEngine: A custom search engine named: $searchEngineName was set")
}
}

@ -12,6 +12,7 @@ import android.os.SystemClock
import android.util.Log
import androidx.test.core.app.ApplicationProvider
import org.junit.rules.ExternalResource
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.TestHelper.mDevice
import java.util.Date
import kotlin.random.Random
@ -36,15 +37,17 @@ class MockLocationUpdatesRule : ExternalResource() {
}
override fun before() {
Log.i(TAG, "MockLocationUpdatesRule: Trying to enable the mock location setting on the device")
/* 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.
*/
Log.i(TAG, "MockLocationUpdatesRule: Trying to execute cmd \"appops set ${appContext.packageName} android:mock_location allow\"")
mDevice.executeShellCommand(
"appops set " +
appContext.packageName +
" android:mock_location allow",
)
Log.i(TAG, "MockLocationUpdatesRule: Executed cmd \"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(
@ -61,15 +64,18 @@ class MockLocationUpdatesRule : ExternalResource() {
)
} catch (ex: Exception) {
// unstable
Log.w("MockLocationUpdatesRule", "addTestProvider failed")
Log.i(TAG, "MockLocationUpdatesRule: Exception $ex caught, addTestProvider failed")
}
locationManager.setTestProviderEnabled(mockProviderName, true)
Log.i(TAG, "MockLocationUpdatesRule: Enabled the mock location setting on the device")
}
// Cleaning up the location provider after the test.
override fun after() {
Log.i(TAG, "MockLocationUpdatesRule: Trying to clean up the location provider")
locationManager.setTestProviderEnabled(mockProviderName, false)
locationManager.removeTestProvider(mockProviderName)
Log.i(TAG, "MockLocationUpdatesRule: Cleaned up the location provider")
}
/**
@ -78,6 +84,7 @@ class MockLocationUpdatesRule : ExternalResource() {
* @param modifyLocation optional callback for modifying the constructed location before setting it.
*/
fun setMockLocation(modifyLocation: (Location.() -> Unit)? = null) {
Log.i(TAG, "setMockLocation: Trying to set the mock location")
check(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
"MockLocationUpdatesRule is supported only on Android devices " +
"running version >= Build.VERSION_CODES.M"
@ -107,5 +114,6 @@ class MockLocationUpdatesRule : ExternalResource() {
}
locationManager.setTestProviderLocation(mockProviderName, location)
Log.i(TAG, "setMockLocation: The mock location was successfully set")
}
}

@ -9,16 +9,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.ext.settings
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.IdlingResourceHelper.unregisterAllIdlingResources
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.exitMenu
/**
* Rule to retry flaky tests for a given number of times, catching some of the more common exceptions.
@ -27,9 +23,6 @@ import org.mozilla.fenix.helpers.TestHelper.appContext
*
*/
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 {
return statement {
@ -39,77 +32,57 @@ class RetryTestRule(private val retryCount: Int = 5) : TestRule {
base.evaluate()
break
} catch (t: AssertionError) {
setNetworkEnabled(true)
Log.i(TAG, "RetryTestRule: AssertionError caught, retrying the UI test")
unregisterAllIdlingResources()
runBlocking {
appContext.settings().alwaysOpenTheHomepageWhenOpeningTheApp = true
permissionStorage.deleteAllSitePermissions()
}
exitMenu()
if (i == retryCount) {
Log.i(TAG, "RetryTestRule: Max numbers of retries reached.")
throw t
}
} catch (t: AssertionFailedError) {
Log.i(TAG, "RetryTestRule: AssertionFailedError caught, retrying the UI test")
unregisterAllIdlingResources()
runBlocking {
appContext.settings().alwaysOpenTheHomepageWhenOpeningTheApp = true
permissionStorage.deleteAllSitePermissions()
}
exitMenu()
if (i == retryCount) {
Log.i(TAG, "RetryTestRule: Max numbers of retries reached.")
throw t
}
} catch (t: UiObjectNotFoundException) {
setNetworkEnabled(true)
Log.i(TAG, "RetryTestRule: UiObjectNotFoundException caught, retrying the UI test")
unregisterAllIdlingResources()
runBlocking {
appContext.settings().alwaysOpenTheHomepageWhenOpeningTheApp = true
permissionStorage.deleteAllSitePermissions()
}
exitMenu()
if (i == retryCount) {
Log.i(TAG, "RetryTestRule: Max numbers of retries reached.")
throw t
}
} catch (t: NoMatchingViewException) {
setNetworkEnabled(true)
Log.i(TAG, "RetryTestRule: NoMatchingViewException caught, retrying the UI test")
unregisterAllIdlingResources()
runBlocking {
appContext.settings().alwaysOpenTheHomepageWhenOpeningTheApp = true
permissionStorage.deleteAllSitePermissions()
}
exitMenu()
if (i == retryCount) {
Log.i(TAG, "RetryTestRule: Max numbers of retries reached.")
throw t
}
} catch (t: IdlingResourceTimeoutException) {
setNetworkEnabled(true)
Log.i(TAG, "RetryTestRule: IdlingResourceTimeoutException caught, retrying the UI test")
unregisterAllIdlingResources()
runBlocking {
appContext.settings().alwaysOpenTheHomepageWhenOpeningTheApp = true
permissionStorage.deleteAllSitePermissions()
}
exitMenu()
if (i == retryCount) {
Log.i(TAG, "RetryTestRule: Max numbers of retries reached.")
throw t
}
} catch (t: RuntimeException) {
setNetworkEnabled(true)
Log.i(TAG, "RetryTestRule: RuntimeException caught, retrying the UI test")
unregisterAllIdlingResources()
runBlocking {
appContext.settings().alwaysOpenTheHomepageWhenOpeningTheApp = true
permissionStorage.deleteAllSitePermissions()
}
exitMenu()
if (i == retryCount) {
Log.i(TAG, "RetryTestRule: Max numbers of retries reached.")
throw t
}
} catch (t: NullPointerException) {
setNetworkEnabled(true)
Log.i(TAG, "RetryTestRule: NullPointerException caught, retrying the UI test")
unregisterAllIdlingResources()
runBlocking {
appContext.settings().alwaysOpenTheHomepageWhenOpeningTheApp = true
permissionStorage.deleteAllSitePermissions()
}
exitMenu()
if (i == retryCount) {
Log.i(TAG, "RetryTestRule: Max numbers of retries reached.")
throw t

@ -8,7 +8,6 @@ import android.content.Context
import android.net.Uri
import android.util.Log
import android.view.View
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.longClick
import androidx.test.espresso.assertion.ViewAssertions
@ -52,10 +51,12 @@ object TestHelper {
fun scrollToElementByText(text: String): UiScrollable {
val appView = UiScrollable(UiSelector().scrollable(true))
Log.i(TAG, "scrollToElementByText: Waiting for app view")
Log.i(TAG, "scrollToElementByText: Waiting for $waitingTime ms for app view to exist")
appView.waitForExists(waitingTime)
Log.i(TAG, "scrollToElementByText: Waited for $waitingTime ms for app view to exist")
Log.i(TAG, "scrollToElementByText: Trying to scroll text: $text into the view")
appView.scrollTextIntoView(text)
Log.i(TAG, "scrollToElementByText: Scrolled to element with text: $text")
Log.i(TAG, "scrollToElementByText: Scrolled text: $text into the view")
return appView
}
@ -64,30 +65,45 @@ object TestHelper {
Until.findObject(By.text(url.toString())),
waitingTime,
)
Log.i(TAG, "longTapSelectItem: Trying to long click item with $url")
onView(
allOf(
withId(R.id.url),
withText(url.toString()),
),
).perform(longClick())
Log.i(TAG, "longTapSelectItem: Long clicked item with $url")
}
fun restartApp(activity: HomeActivityIntentTestRule) {
with(activity) {
updateCachedSettings()
Log.i(TAG, "restartApp: Trying to finish the current activity")
finishActivity()
Log.i(TAG, "restartApp: Finished the current activity")
Log.i(TAG, "restartApp: Waiting for device to be idle")
mDevice.waitForIdle()
Log.i(TAG, "restartApp: Waited for device to be idle")
Log.i(TAG, "restartApp: Trying to launch the activity")
launchActivity(null)
Log.i(TAG, "restartApp: Launched the activity")
}
}
fun closeApp(activity: HomeActivityIntentTestRule) =
fun closeApp(activity: HomeActivityIntentTestRule) {
Log.i(TAG, "closeApp: Trying to finish and remove the task of the current activity")
activity.activity.finishAndRemoveTask()
Log.i(TAG, "closeApp: Finished and removed the task of the current activity")
}
fun relaunchCleanApp(activity: HomeActivityIntentTestRule) {
closeApp(activity)
Log.i(TAG, "relaunchCleanApp: Trying to clear intents state")
Intents.release()
Log.i(TAG, "relaunchCleanApp: Cleared intents state")
Log.i(TAG, "relaunchCleanApp: Trying to launch the activity")
activity.launchActivity(null)
Log.i(TAG, "relaunchCleanApp: Launched the activity")
}
fun waitUntilObjectIsFound(resourceName: String) {
@ -101,32 +117,43 @@ object TestHelper {
clickPageObject(itemWithResIdAndText("$packageName:id/snackbar_btn", expectedText))
fun waitUntilSnackbarGone() {
Log.i(TAG, "waitUntilSnackbarGone: Waiting for $waitingTime ms until the snckabar is gone")
mDevice.findObject(
UiSelector().resourceId("$packageName:id/snackbar_layout"),
).waitUntilGone(waitingTime)
Log.i(TAG, "waitUntilSnackbarGone: Waited for $waitingTime ms until the snckabar was gone")
}
fun verifySnackBarText(expectedText: String) = assertUIObjectExists(itemContainingText(expectedText))
fun verifyUrl(urlSubstring: String, resourceName: String, resId: Int) {
waitUntilObjectIsFound(resourceName)
Log.i(TAG, "verifyUrl: Waiting for $waitingTime ms for url substring: $urlSubstring to exist")
mDevice.findObject(UiSelector().text(urlSubstring)).waitForExists(waitingTime)
Log.i(TAG, "verifyUrl: Waited for $waitingTime ms for url substring: $urlSubstring to exist")
Log.i(TAG, "verifyUrl: Trying to verify that item with $resId contains url substring: $urlSubstring")
onView(withId(resId)).check(ViewAssertions.matches(withText(CoreMatchers.containsString(urlSubstring))))
Log.i(TAG, "verifyUrl: Verified that item with $resId contains url substring: $urlSubstring")
}
// exit from Menus to home screen or browser
fun exitMenu() {
val toolbar =
mDevice.findObject(UiSelector().resourceId("$packageName:id/toolbar"))
while (!toolbar.waitForExists(waitingTimeShort)) {
val menuToolbar =
mDevice.findObject(UiSelector().resourceId("$packageName:id/navigationToolbar"))
while (menuToolbar.waitForExists(waitingTimeShort)) {
Log.i(TAG, "exitMenu: Trying to press the device back button to return to the app home/browser view")
mDevice.pressBack()
Log.i(TAG, "exitMenu: Exiting app settings menus using device back button")
Log.i(TAG, "exitMenu: Pressed the device back button to return to the app home/browser view")
}
}
fun UiDevice.waitForObjects(obj: UiObject, waitingTime: Long = TestAssetHelper.waitingTime) {
Log.i(TAG, "waitForObjects: Waiting for device to be idle")
this.waitForIdle()
Log.i(TAG, "waitForObjects: Waited for device to be idle")
Log.i(TAG, "waitForObjects: Waiting for $waitingTime ms to assert that ${obj.selector} is not null")
Assert.assertNotNull(obj.waitForExists(waitingTime))
Log.i(TAG, "waitForObjects: Waited for $waitingTime ms and asserted that ${obj.selector} is not null")
}
fun hasCousin(matcher: Matcher<View>): Matcher<View> {
@ -139,10 +166,17 @@ object TestHelper {
)
}
fun verifyLightThemeApplied(expected: Boolean) =
assertFalse("Light theme not selected", expected)
fun verifyLightThemeApplied(expected: Boolean) {
Log.i(TAG, "verifyLightThemeApplied: Trying to verify that that the \"Light\" theme was applied")
assertFalse("$TAG: Light theme not selected", expected)
Log.i(TAG, "verifyLightThemeApplied: Verified that that the \"Light\" theme was applied")
}
fun verifyDarkThemeApplied(expected: Boolean) = assertTrue("Dark theme not selected", expected)
fun verifyDarkThemeApplied(expected: Boolean) {
Log.i(TAG, "verifyDarkThemeApplied: Trying to verify that that the \"Dark\" theme was applied")
assertTrue("$TAG: Dark theme not selected", expected)
Log.i(TAG, "verifyDarkThemeApplied: Verified that that the \"Dark\" theme was applied")
}
fun waitForAppWindowToBeUpdated() {
Log.i(TAG, "waitForAppWindowToBeUpdated: Waiting for $waitingTimeVeryShort ms for $packageName window to be updated")

@ -1,42 +1,60 @@
/* 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.util.Log
import kotlinx.coroutines.runBlocking
import mozilla.appservices.places.BookmarkRoot
import mozilla.components.browser.storage.sync.PlacesBookmarksStorage
import mozilla.components.browser.state.store.BrowserStore
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.ui.robots.notificationShade
import java.util.Locale
/**
* Standard Test setup and tear down methods to run before each test.
* Some extra clean-up is required when we're using the org.mozilla.fenix.helpers.RetryTestRule (the instrumentation does not do that in this case).
*
*/
open class TestSetup {
lateinit var mockWebServer: MockWebServer
private val bookmarksStorage = PlacesBookmarksStorage(appContext.applicationContext)
lateinit var browserStore: BrowserStore
@Before
fun setUp() {
open fun setUp() {
Log.i(TAG, "TestSetup: Starting the @Before setup")
// Clear pre-existing notifications
notificationShade {
cancelAllShownNotifications()
}
runBlocking {
// Reset locale to EN-US if needed.
AppAndSystemHelper.resetSystemLocaleToEnUS()
// Check and clear the downloads folder
// Because of https://bugzilla.mozilla.org/show_bug.cgi?id=1812183, some items might not be updated.
if (Locale.getDefault() != Locale.US) {
AppAndSystemHelper.setSystemLocale(Locale.US)
}
// Check and clear the downloads folder, in case the tearDown method is not executed.
// This will only work in case of a RetryTestRule execution.
AppAndSystemHelper.clearDownloadsFolder()
// Make sure the Wifi and Mobile Data connections are on
// Make sure the Wifi and Mobile Data connections are on.
AppAndSystemHelper.setNetworkEnabled(true)
// Clear bookmarks left after a failed test
val bookmarks = bookmarksStorage.getTree(BookmarkRoot.Mobile.id)?.children
Log.i(TAG, "Before cleanup: Bookmarks storage contains: $bookmarks")
bookmarks?.forEach {
bookmarksStorage.deleteNode(it.guid)
// TODO: Follow-up with a method to handle the DB update; the logs will still show the bookmarks in the storage before the test starts.
Log.i(TAG, "After cleanup: Bookmarks storage contains: $bookmarks")
}
// Clear bookmarks left after a failed test, before a retry.
AppAndSystemHelper.deleteBookmarksStorage()
// Clear history left after a failed test, before a retry.
AppAndSystemHelper.deleteHistoryStorage()
// Clear permissions left after a failed test, before a retry.
AppAndSystemHelper.deletePermissionsStorage()
}
// Initializing this as part of class construction, below the rule would throw a NPE.
// So we are initializing this here instead of in all related tests.
Log.i(TAG, "TestSetup: Trying to initialize the browserStore instance")
browserStore = TestHelper.appContext.components.core.store
Log.i(TAG, "TestSetup: Initialized the browserStore instance")
// Clear pre-existing notifications.
notificationShade {
cancelAllShownNotifications()
}
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
}
@ -49,4 +67,17 @@ open class TestSetup {
mockWebServer.start()
}
}
@After
open fun tearDown() {
Log.i(TAG, "TestSetup: Starting the @After tearDown methods.")
runBlocking {
// Reset locale to EN-US if needed.
// This method is only here temporarily, to set the language before a new activity is started.
// TODO: When https://bugzilla.mozilla.org/show_bug.cgi?id=1812183 is fixed, it should be removed.
if (Locale.getDefault() != Locale.US) {
AppAndSystemHelper.setSystemLocale(Locale.US)
}
}
}
}

@ -11,7 +11,7 @@ import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.experiments.nimbus.GleanPlumbMessageHelper
import org.mozilla.experiments.nimbus.NimbusMessagingHelperInterface
import org.mozilla.experiments.nimbus.StringHolder
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
@ -28,7 +28,7 @@ class OnboardingMapperTest {
private lateinit var junoOnboardingFeature: JunoOnboarding
private lateinit var jexlConditions: Map<String, String>
private lateinit var jexlHelper: GleanPlumbMessageHelper
private lateinit var jexlHelper: NimbusMessagingHelperInterface
private lateinit var evalFunction: (String) -> Boolean
@Before

@ -196,42 +196,42 @@
},
"cryptography": {
"hashes": [
"sha256:0a68bfcf57a6887818307600c3c0ebc3f62fbb6ccad2240aa21887cda1f8df1b",
"sha256:146e971e92a6dd042214b537a726c9750496128453146ab0ee8971a0299dc9bd",
"sha256:14e4b909373bc5bf1095311fa0f7fcabf2d1a160ca13f1e9e467be1ac4cbdf94",
"sha256:206aaf42e031b93f86ad60f9f5d9da1b09164f25488238ac1dc488334eb5e221",
"sha256:3005166a39b70c8b94455fdbe78d87a444da31ff70de3331cdec2c568cf25b7e",
"sha256:324721d93b998cb7367f1e6897370644751e5580ff9b370c0a50dc60a2003513",
"sha256:33588310b5c886dfb87dba5f013b8d27df7ffd31dc753775342a1e5ab139e59d",
"sha256:35cf6ed4c38f054478a9df14f03c1169bb14bd98f0b1705751079b25e1cb58bc",
"sha256:3ca482ea80626048975360c8e62be3ceb0f11803180b73163acd24bf014133a0",
"sha256:56ce0c106d5c3fec1038c3cca3d55ac320a5be1b44bf15116732d0bc716979a2",
"sha256:5a217bca51f3b91971400890905a9323ad805838ca3fa1e202a01844f485ee87",
"sha256:678cfa0d1e72ef41d48993a7be75a76b0725d29b820ff3cfd606a5b2b33fda01",
"sha256:69fd009a325cad6fbfd5b04c711a4da563c6c4854fc4c9544bff3088387c77c0",
"sha256:6cf9b76d6e93c62114bd19485e5cb003115c134cf9ce91f8ac924c44f8c8c3f4",
"sha256:74f18a4c8ca04134d2052a140322002fef535c99cdbc2a6afc18a8024d5c9d5b",
"sha256:85f759ed59ffd1d0baad296e72780aa62ff8a71f94dc1ab340386a1207d0ea81",
"sha256:87086eae86a700307b544625e3ba11cc600c3c0ef8ab97b0fda0705d6db3d4e3",
"sha256:8814722cffcfd1fbd91edd9f3451b88a8f26a5fd41b28c1c9193949d1c689dc4",
"sha256:8fedec73d590fd30c4e3f0d0f4bc961aeca8390c72f3eaa1a0874d180e868ddf",
"sha256:9515ea7f596c8092fdc9902627e51b23a75daa2c7815ed5aa8cf4f07469212ec",
"sha256:988b738f56c665366b1e4bfd9045c3efae89ee366ca3839cd5af53eaa1401bce",
"sha256:a2a8d873667e4fd2f34aedab02ba500b824692c6542e017075a2efc38f60a4c0",
"sha256:bd7cf7a8d9f34cc67220f1195884151426ce616fdc8285df9054bfa10135925f",
"sha256:bdce70e562c69bb089523e75ef1d9625b7417c6297a76ac27b1b8b1eb51b7d0f",
"sha256:be14b31eb3a293fc6e6aa2807c8a3224c71426f7c4e3639ccf1a2f3ffd6df8c3",
"sha256:be41b0c7366e5549265adf2145135dca107718fa44b6e418dc7499cfff6b4689",
"sha256:c310767268d88803b653fffe6d6f2f17bb9d49ffceb8d70aed50ad45ea49ab08",
"sha256:c58115384bdcfe9c7f644c72f10f6f42bed7cf59f7b52fe1bf7ae0a622b3a139",
"sha256:c640b0ef54138fde761ec99a6c7dc4ce05e80420262c20fa239e694ca371d434",
"sha256:ca20550bb590db16223eb9ccc5852335b48b8f597e2f6f0878bbfd9e7314eb17",
"sha256:d97aae66b7de41cdf5b12087b5509e4e9805ed6f562406dfcf60e8481a9a28f8",
"sha256:e9326ca78111e4c645f7e49cbce4ed2f3f85e17b61a563328c85a5208cf34440"
"sha256:01911714117642a3f1792c7f376db572aadadbafcd8d75bb527166009c9f1d1b",
"sha256:0e89f7b84f421c56e7ff69f11c441ebda73b8a8e6488d322ef71746224c20fce",
"sha256:12d341bd42cdb7d4937b0cabbdf2a94f949413ac4504904d0cdbdce4a22cbf88",
"sha256:15a1fb843c48b4a604663fa30af60818cd28f895572386e5f9b8a665874c26e7",
"sha256:1cdcdbd117681c88d717437ada72bdd5be9de117f96e3f4d50dab3f59fd9ab20",
"sha256:1df6fcbf60560d2113b5ed90f072dc0b108d64750d4cbd46a21ec882c7aefce9",
"sha256:3c6048f217533d89f2f8f4f0fe3044bf0b2090453b7b73d0b77db47b80af8dff",
"sha256:3e970a2119507d0b104f0a8e281521ad28fc26f2820687b3436b8c9a5fcf20d1",
"sha256:44a64043f743485925d3bcac548d05df0f9bb445c5fcca6681889c7c3ab12764",
"sha256:4e36685cb634af55e0677d435d425043967ac2f3790ec652b2b88ad03b85c27b",
"sha256:5f8907fcf57392cd917892ae83708761c6ff3c37a8e835d7246ff0ad251d9298",
"sha256:69b22ab6506a3fe483d67d1ed878e1602bdd5912a134e6202c1ec672233241c1",
"sha256:6bfadd884e7280df24d26f2186e4e07556a05d37393b0f220a840b083dc6a824",
"sha256:6d0fbe73728c44ca3a241eff9aefe6496ab2656d6e7a4ea2459865f2e8613257",
"sha256:6ffb03d419edcab93b4b19c22ee80c007fb2d708429cecebf1dd3258956a563a",
"sha256:810bcf151caefc03e51a3d61e53335cd5c7316c0a105cc695f0959f2c638b129",
"sha256:831a4b37accef30cccd34fcb916a5d7b5be3cbbe27268a02832c3e450aea39cb",
"sha256:887623fe0d70f48ab3f5e4dbf234986b1329a64c066d719432d0698522749929",
"sha256:a0298bdc6e98ca21382afe914c642620370ce0470a01e1bef6dd9b5354c36854",
"sha256:a1327f280c824ff7885bdeef8578f74690e9079267c1c8bd7dc5cc5aa065ae52",
"sha256:c1f25b252d2c87088abc8bbc4f1ecbf7c919e05508a7e8628e6875c40bc70923",
"sha256:c3a5cbc620e1e17009f30dd34cb0d85c987afd21c41a74352d1719be33380885",
"sha256:ce8613beaffc7c14f091497346ef117c1798c202b01153a8cc7b8e2ebaaf41c0",
"sha256:d2a27aca5597c8a71abbe10209184e1a8e91c1fd470b5070a2ea60cafec35bcd",
"sha256:dad9c385ba8ee025bb0d856714f71d7840020fe176ae0229de618f14dae7a6e2",
"sha256:db4b65b02f59035037fde0998974d84244a64c3265bdef32a827ab9b63d61b18",
"sha256:e09469a2cec88fb7b078e16d4adec594414397e8879a4341c6ace96013463d5b",
"sha256:e53dc41cda40b248ebc40b83b31516487f7db95ab8ceac1f042626bc43a2f992",
"sha256:f1e85a178384bf19e36779d91ff35c7617c885da487d689b05c1366f9933ad74",
"sha256:f47be41843200f7faec0683ad751e5ef11b9a56a220d57f300376cd8aba81660",
"sha256:fb0cef872d8193e487fc6bdb08559c3aa41b659a7d9be48b2e10747f47863925",
"sha256:ffc73996c4fca3d2b6c1c8c12bfd3ad00def8621da24f547626bf06441400449"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==42.0.0"
"version": "==42.0.4"
},
"distro": {
"hashes": [

@ -133,7 +133,7 @@ class SyncIntegrationTest {
verifySavedLoginsAfterSync()
}.goBack {
// After checking the synced logins
// on Logins and Passwords menu the Sync logins option is set to On
// on Logins and Passwords menu the Sync passwords option is set to On
verifyDefaultViewAfterSync()
}
}

@ -24,9 +24,7 @@ class AddressAutofillTest : TestSetup() {
var navigateToAutofillSettings = true
var isAddressAutofillEnabled = true
var userHasSavedAddress = false
var firstName = "Mozilla"
var middleName = "Fenix"
var lastName = "Firefox"
var name = "Mozilla Fenix Firefox"
var streetAddress = "Harrison Street"
var city = "San Francisco"
var state = "Alaska"
@ -38,9 +36,7 @@ class AddressAutofillTest : TestSetup() {
object SecondAddressAutofillDetails {
var navigateToAutofillSettings = false
var firstName = "Android"
var middleName = "Test"
var lastName = "Name"
var name = "Android Test Name"
var streetAddress = "Fort Street"
var city = "San Jose"
var state = "Arizona"
@ -65,9 +61,7 @@ class AddressAutofillTest : TestSetup() {
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
name = FirstAddressAutofillDetails.name,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
@ -102,9 +96,7 @@ class AddressAutofillTest : TestSetup() {
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
name = FirstAddressAutofillDetails.name,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
@ -145,9 +137,7 @@ class AddressAutofillTest : TestSetup() {
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
name = FirstAddressAutofillDetails.name,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
@ -173,9 +163,7 @@ class AddressAutofillTest : TestSetup() {
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
name = FirstAddressAutofillDetails.name,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
@ -219,9 +207,7 @@ class AddressAutofillTest : TestSetup() {
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
name = FirstAddressAutofillDetails.name,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
@ -256,9 +242,7 @@ class AddressAutofillTest : TestSetup() {
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
name = FirstAddressAutofillDetails.name,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
@ -271,9 +255,7 @@ class AddressAutofillTest : TestSetup() {
clickAddAddressButton()
fillAndSaveAddress(
navigateToAutofillSettings = SecondAddressAutofillDetails.navigateToAutofillSettings,
firstName = SecondAddressAutofillDetails.firstName,
middleName = SecondAddressAutofillDetails.middleName,
lastName = SecondAddressAutofillDetails.lastName,
name = SecondAddressAutofillDetails.name,
streetAddress = SecondAddressAutofillDetails.streetAddress,
city = SecondAddressAutofillDetails.city,
state = SecondAddressAutofillDetails.state,
@ -319,9 +301,7 @@ class AddressAutofillTest : TestSetup() {
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
name = FirstAddressAutofillDetails.name,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
@ -334,9 +314,7 @@ class AddressAutofillTest : TestSetup() {
clickSavedAddress("Mozilla")
fillAndSaveAddress(
navigateToAutofillSettings = SecondAddressAutofillDetails.navigateToAutofillSettings,
firstName = SecondAddressAutofillDetails.firstName,
middleName = SecondAddressAutofillDetails.middleName,
lastName = SecondAddressAutofillDetails.lastName,
name = SecondAddressAutofillDetails.name,
streetAddress = SecondAddressAutofillDetails.streetAddress,
city = SecondAddressAutofillDetails.city,
state = SecondAddressAutofillDetails.state,
@ -377,9 +355,7 @@ class AddressAutofillTest : TestSetup() {
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
name = FirstAddressAutofillDetails.name,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,
@ -416,9 +392,7 @@ class AddressAutofillTest : TestSetup() {
navigateToAutofillSettings = FirstAddressAutofillDetails.navigateToAutofillSettings,
isAddressAutofillEnabled = FirstAddressAutofillDetails.isAddressAutofillEnabled,
userHasSavedAddress = FirstAddressAutofillDetails.userHasSavedAddress,
firstName = FirstAddressAutofillDetails.firstName,
middleName = FirstAddressAutofillDetails.middleName,
lastName = FirstAddressAutofillDetails.lastName,
name = FirstAddressAutofillDetails.name,
streetAddress = FirstAddressAutofillDetails.streetAddress,
city = FirstAddressAutofillDetails.city,
state = FirstAddressAutofillDetails.state,

@ -8,18 +8,10 @@ import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import androidx.test.espresso.Espresso.pressBack
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
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.bookmarkStorage
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
@ -28,7 +20,9 @@ import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.bookmarksMenu
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
@ -38,9 +32,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
/**
* Tests for verifying basic functionality of bookmarks
*/
class ComposeBookmarksTest {
private lateinit var mockWebServer: MockWebServer
private lateinit var mDevice: UiDevice
class ComposeBookmarksTest : TestSetup() {
private val bookmarksFolderName = "New Folder"
private val testBookmark = object {
var title: String = "Bookmark title"
@ -59,26 +51,6 @@ class ComposeBookmarksTest {
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
// Clearing all bookmarks data after each test to avoid overlapping data
val bookmarksStorage = activityTestRule.activity?.bookmarkStorage
runBlocking {
val bookmarks = bookmarksStorage?.getTree(BookmarkRoot.Mobile.id)?.children
bookmarks?.forEach { bookmarksStorage.deleteNode(it.guid) }
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/522919
@Test
fun verifyEmptyBookmarksMenuTest() {

@ -5,19 +5,15 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.collectionRobot
import org.mozilla.fenix.ui.robots.composeTabDrawer
@ -29,9 +25,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
*
*/
class ComposeCollectionTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class ComposeCollectionTest : TestSetup() {
private val firstCollectionName = "testcollection_1"
private val secondCollectionName = "testcollection_2"
private val collectionName = "First Collection"
@ -51,20 +45,6 @@ class ComposeCollectionTest {
),
) { it.activity }
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/353823
@SmokeTest
@Test

@ -6,15 +6,8 @@ package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.core.net.toUri
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.Constants
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
@ -23,7 +16,9 @@ import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.clickContextMenuItem
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.downloadRobot
@ -45,15 +40,14 @@ import org.mozilla.fenix.ui.robots.shareOverlay
*
*/
class ComposeContextMenusTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class ComposeContextMenusTest : TestSetup() {
@get:Rule(order = 0)
val composeTestRule =
AndroidComposeTestRule(
HomeActivityIntentTestRule.withDefaultSettingsOverrides(
HomeActivityIntentTestRule(
tabsTrayRewriteEnabled = true,
isJumpBackInCFREnabled = false,
),
) { it.activity }
@ -61,21 +55,6 @@ class ComposeContextMenusTest {
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
composeTestRule.activity.applicationContext.settings().shouldShowJumpBackInCFR = false
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243837
@Test
fun verifyOpenLinkNewTabContextMenuOptionTest() {

@ -4,31 +4,23 @@
package org.mozilla.fenix.ui
import android.content.Context
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import androidx.test.espresso.Espresso.pressBack
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
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.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.historyMenu
import org.mozilla.fenix.ui.robots.homeScreen
@ -39,42 +31,16 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* Tests for verifying basic functionality of history
*
*/
class ComposeHistoryTest {
private lateinit var mockWebServer: MockWebServer
private lateinit var mDevice: UiDevice
class ComposeHistoryTest : TestSetup() {
@get:Rule
val activityTestRule =
AndroidComposeTestRule(
HomeActivityIntentTestRule.withDefaultSettingsOverrides(
HomeActivityIntentTestRule(
tabsTrayRewriteEnabled = true,
isJumpBackInCFREnabled = false,
),
) { it.activity }
@Before
fun setUp() {
InstrumentationRegistry.getInstrumentation().targetContext.settings()
.shouldShowJumpBackInCFR = false
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
// Clearing all history data after each test to avoid overlapping data
val applicationContext: Context = activityTestRule.activity.applicationContext
val historyStorage = PlacesHistoryStorage(applicationContext)
runBlocking {
historyStorage.deleteEverything()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243285
@Test
fun verifyEmptyHistoryMenuTest() {

@ -5,19 +5,14 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -28,10 +23,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
*
*/
class ComposeHomeScreenTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class ComposeHomeScreenTest : TestSetup() {
@get:Rule(order = 0)
val activityTestRule =
AndroidComposeTestRule(
@ -44,21 +36,6 @@ class ComposeHomeScreenTest {
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/235396
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1844580")
@Test

@ -5,23 +5,17 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
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.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MatcherHelper
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -34,11 +28,7 @@ import org.mozilla.fenix.ui.robots.notificationShade
* - a media notification icon is displayed on the homescreen for the tab playing media content
* Note: this test only verifies media notifications, not media itself
*/
class ComposeMediaNotificationTest {
private lateinit var mockWebServer: MockWebServer
private lateinit var mDevice: UiDevice
private lateinit var browserStore: BrowserStore
class ComposeMediaNotificationTest : TestSetup() {
@get:Rule(order = 0)
val composeTestRule =
AndroidComposeTestRule(
@ -51,24 +41,6 @@ class ComposeMediaNotificationTest {
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
// Initializing this as part of class construction, below the rule would throw a NPE
// So we are initializing this here instead of in all tests.
browserStore = composeTestRule.activity.components.core.store
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1347033
@SmokeTest
@Test

@ -5,19 +5,13 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.resetSystemLocaleToEnUS
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.navigationToolbar
import java.util.Locale
@ -31,10 +25,7 @@ import java.util.Locale
* - Find in page
*/
class ComposeNavigationToolbarTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class ComposeNavigationToolbarTest : TestSetup() {
@get:Rule
val composeTestRule =
AndroidComposeTestRule(
@ -43,21 +34,6 @@ class ComposeNavigationToolbarTest {
),
) { it.activity }
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
resetSystemLocaleToEnUS()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/987326
// Swipes the nav bar left/right to switch between tabs
@SmokeTest

@ -32,6 +32,7 @@ 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.verifySnackBarText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.clickContextMenuItem
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -50,8 +51,8 @@ import org.mozilla.fenix.ui.robots.searchScreen
*
*/
class ComposeSearchTest {
lateinit var searchMockServer: MockWebServer
class ComposeSearchTest : TestSetup() {
private lateinit var searchMockServer: MockWebServer
private val queryString: String = "firefox"
private val generalEnginesList = listOf("DuckDuckGo", "Google", "Bing")
private val topicEnginesList = listOf("Amazon.com", "Wikipedia", "eBay")
@ -70,7 +71,8 @@ class ComposeSearchTest {
) { it.activity }
@Before
fun setUp() {
override fun setUp() {
super.setUp()
searchMockServer = MockWebServer().apply {
dispatcher = SearchDispatcher()
start()
@ -78,7 +80,8 @@ class ComposeSearchTest {
}
@After
fun tearDown() {
override fun tearDown() {
super.tearDown()
searchMockServer.shutdown()
}

@ -9,15 +9,10 @@ import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.core.net.toUri
import androidx.test.espresso.Espresso.pressBack
import androidx.test.rule.GrantPermissionRule
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.clearDownloadsFolder
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
@ -27,6 +22,7 @@ import org.mozilla.fenix.helpers.TestAssetHelper.getStorageTestAsset
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.downloadRobot
import org.mozilla.fenix.ui.robots.homeScreen
@ -37,9 +33,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* Delete Browsing Data on quit
*
*/
class ComposeSettingsDeleteBrowsingDataOnQuitTest {
private lateinit var mockWebServer: MockWebServer
class ComposeSettingsDeleteBrowsingDataOnQuitTest : TestSetup() {
@get:Rule(order = 0)
val composeTestRule =
AndroidComposeTestRule(
@ -55,22 +49,6 @@ class ComposeSettingsDeleteBrowsingDataOnQuitTest {
Manifest.permission.RECORD_AUDIO,
)
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
// Check and clear the downloads folder
clearDownloadsFolder()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416048
@Test
fun deleteBrowsingDataOnQuitSettingTest() {

@ -5,14 +5,10 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
@ -22,6 +18,7 @@ import org.mozilla.fenix.helpers.TestAssetHelper.getStorageTestAsset
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -33,9 +30,7 @@ import org.mozilla.fenix.ui.robots.settingsScreen
* Delete Browsing Data
*/
class ComposeSettingsDeleteBrowsingDataTest {
private lateinit var mockWebServer: MockWebServer
class ComposeSettingsDeleteBrowsingDataTest : TestSetup() {
@get:Rule
val composeTestRule =
AndroidComposeTestRule(
@ -45,19 +40,6 @@ class ComposeSettingsDeleteBrowsingDataTest {
),
) { it.activity }
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/937561
@Test
fun deleteBrowsingDataOptionStatesTest() {

@ -5,27 +5,21 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.google.android.material.bottomsheet.BottomSheetBehavior
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.mediasession.MediaSession
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.closeApp
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -49,11 +43,7 @@ import org.mozilla.fenix.ui.robots.notificationShade
* - Shortcut context menu navigation
*/
class ComposeTabbedBrowsingTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
private lateinit var browserStore: BrowserStore
class ComposeTabbedBrowsingTest : TestSetup() {
@get:Rule(order = 0)
val composeTestRule =
AndroidComposeTestRule(
@ -67,24 +57,6 @@ class ComposeTabbedBrowsingTest {
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
// Initializing this as part of class construction, below the rule would throw a NPE
// So we are initializing this here instead of in all related tests.
browserStore = composeTestRule.activity.components.core.store
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903599
@Test
fun closeAllTabsTest() {

@ -5,23 +5,19 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.DataGenerationHelper.generateRandomString
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestHelper.waitUntilSnackbarGone
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.homeScreenWithComposeTopSites
@ -36,10 +32,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* - Verifies existence of default top sites available on the home-screen
*/
class ComposeTopSitesTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class ComposeTopSitesTest : TestSetup() {
@get:Rule
val composeTestRule =
AndroidComposeTestRule(
@ -48,20 +41,6 @@ class ComposeTopSitesTest {
),
) { it.activity }
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/532598
@SmokeTest
@Test

@ -60,7 +60,7 @@ class CreditCardAutofillTest : TestSetup() {
MockCreditCard1.MOCK_EXPIRATION_MONTH,
MockCreditCard1.MOCK_EXPIRATION_YEAR,
)
// Opening Manage saved cards to dismiss here the Secure your credit prompt
// Opening Manage cards to dismiss here the Secure your credit prompt
clickManageSavedCreditCardsButton()
clickSecuredCreditCardsLaterButton()
}.goBackToAutofillSettings {
@ -470,7 +470,7 @@ class CreditCardAutofillTest : TestSetup() {
MockCreditCard2.MOCK_EXPIRATION_MONTH,
MockCreditCard2.MOCK_EXPIRATION_YEAR,
)
// Opening Manage saved cards to dismiss here the Secure your credit prompt
// Opening Manage cards to dismiss here the Secure your credit prompt
clickManageSavedCreditCardsButton()
clickSecuredCreditCardsLaterButton()
}
@ -521,7 +521,7 @@ class CreditCardAutofillTest : TestSetup() {
MockCreditCard2.MOCK_EXPIRATION_MONTH,
MockCreditCard2.MOCK_EXPIRATION_YEAR,
)
// Opening Manage saved cards to dismiss here the Secure your credit prompt
// Opening Manage cards to dismiss here the Secure your credit prompt
clickManageSavedCreditCardsButton()
clickSecuredCreditCardsLaterButton()
}

@ -5,16 +5,12 @@
package org.mozilla.fenix.ui
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.DeepLinkRobot
/**
@ -31,29 +27,12 @@ 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 lateinit var mockWebServer: MockWebServer
class DeepLinkTest : TestSetup() {
private val robot = DeepLinkRobot()
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule()
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
@Test
fun openHomeScreen() {
robot.openHomeScreen {

@ -5,14 +5,13 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import org.junit.After
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AppAndSystemHelper.clearDownloadsFolder
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.downloadRobot
/**
@ -22,7 +21,7 @@ import org.mozilla.fenix.ui.robots.downloadRobot
* - Verifies downloading of varying file types and the appearance inside the Downloads listing.
**/
@RunWith(Parameterized::class)
class DownloadFileTypesTest(fileName: String) {
class DownloadFileTypesTest(fileName: String) : TestSetup() {
/* 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
@ -30,12 +29,6 @@ class DownloadFileTypesTest(fileName: String) {
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
@After
fun tearDown() {
// Check and clear the downloads folder
clearDownloadsFolder()
}
companion object {
// Creating test data. The test will take each file name as a parameter and run it individually.
@JvmStatic

@ -5,16 +5,11 @@
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.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.clearDownloadsFolder
import org.mozilla.fenix.helpers.AppAndSystemHelper.deleteDownloadedFileOnStorage
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_APPS_PHOTOS
@ -25,6 +20,7 @@ import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.downloadRobot
@ -40,9 +36,7 @@ import org.mozilla.fenix.ui.robots.notificationShade
* - Verifies download notification and actions
* - Verifies managing downloads inside the Downloads listing.
**/
class DownloadTest {
private lateinit var mockWebServer: MockWebServer
class DownloadTest : TestSetup() {
/* 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 = ""
@ -50,34 +44,6 @@ class DownloadTest {
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
// clear all existing notifications
notificationShade {
mDevice.openNotification()
clearNotifications()
}
}
@After
fun tearDown() {
notificationShade {
cancelAllShownNotifications()
}
mockWebServer.shutdown()
setNetworkEnabled(enabled = true)
// Check and clear the downloads folder
clearDownloadsFolder()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243844
@Test
fun verifyTheDownloadPromptsTest() {

@ -6,14 +6,11 @@ package org.mozilla.fenix.ui
import androidx.core.net.toUri
import androidx.test.espresso.Espresso.pressBack
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.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getEnhancedTrackingProtectionAsset
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
@ -22,6 +19,7 @@ import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.enhancedTrackingProtection
import org.mozilla.fenix.ui.robots.homeScreen
@ -40,9 +38,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* - Verifying Enhanced Tracking Protection site exceptions
*/
class EnhancedTrackingProtectionTest {
private lateinit var mockWebServer: MockWebServer
class EnhancedTrackingProtectionTest : TestSetup() {
@get:Rule
val activityTestRule = HomeActivityIntentTestRule(
isJumpBackInCFREnabled = false,
@ -50,19 +46,6 @@ class EnhancedTrackingProtectionTest {
isWallpaperOnboardingEnabled = false,
)
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416046
@Test
fun testETPSettingsItemsAndSubMenus() {
@ -200,6 +183,7 @@ class EnhancedTrackingProtectionTest {
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/339713
// Tests removing TP exceptions individually or all at once
@Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1865781")
@Test
fun clearWebsitesFromTPExceptionListTest() {
val firstPage = getGenericAsset(mockWebServer, 1)

@ -14,6 +14,7 @@ import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithCondition
import org.mozilla.fenix.helpers.DataGenerationHelper.getSponsoredFxSuggestPlaceHolder
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.navigationToolbar
/**
@ -21,7 +22,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
*
*/
class FirefoxSuggestTest {
class FirefoxSuggestTest : TestSetup() {
@get:Rule
val activityTestRule = AndroidComposeTestRule(

@ -4,15 +4,13 @@
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.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.TestAsset
import org.mozilla.fenix.helpers.TestAssetHelper.getGPCTestAsset
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -20,8 +18,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* Tests for Global Privacy Control setting.
*/
class GlobalPrivacyControlTest {
private lateinit var mockWebServer: MockWebServer
class GlobalPrivacyControlTest : TestSetup() {
private lateinit var gpcPage: TestAsset
@get:Rule
@ -33,20 +30,11 @@ class GlobalPrivacyControlTest {
)
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
override fun setUp() {
super.setUp()
gpcPage = getGPCTestAsset(mockWebServer)
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2429327
@Test
fun testGPCinNormalBrowsing() {

@ -4,24 +4,14 @@
package org.mozilla.fenix.ui
import android.content.Context
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import androidx.test.espresso.Espresso.pressBack
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
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.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MockBrowserDataHelper
@ -29,7 +19,9 @@ import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.historyMenu
import org.mozilla.fenix.ui.robots.homeScreen
@ -40,40 +32,13 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* Tests for verifying basic functionality of history
*
*/
class HistoryTest {
private lateinit var mockWebServer: MockWebServer
private lateinit var mDevice: UiDevice
class HistoryTest : TestSetup() {
@get:Rule
val activityTestRule =
AndroidComposeTestRule(
HomeActivityIntentTestRule.withDefaultSettingsOverrides(),
HomeActivityIntentTestRule(isJumpBackInCFREnabled = false),
) { it.activity }
@Before
fun setUp() {
InstrumentationRegistry.getInstrumentation().targetContext.settings()
.shouldShowJumpBackInCFR = false
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
// Clearing all history data after each test to avoid overlapping data
val applicationContext: Context = activityTestRule.activity.applicationContext
val historyStorage = PlacesHistoryStorage(applicationContext)
runBlocking {
historyStorage.deleteEverything()
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243285
@Test
fun verifyEmptyHistoryMenuTest() {

@ -5,19 +5,14 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.searchScreen
@ -29,10 +24,7 @@ import org.mozilla.fenix.ui.robots.searchScreen
*
*/
class HomeScreenTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class HomeScreenTest : TestSetup() {
@get:Rule(order = 0)
val activityTestRule =
AndroidComposeTestRule(HomeActivityTestRule.withDefaultSettingsOverrides()) { it.activity }
@ -41,21 +33,6 @@ class HomeScreenTest {
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/235396
@Test
fun homeScreenItemsTest() {

@ -7,14 +7,11 @@ package org.mozilla.fenix.ui
import android.os.Build
import android.view.autofill.AutofillManager
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.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
@ -29,6 +26,7 @@ import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestHelper.waitForAppWindowToBeUpdated
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clearTextFieldItem
import org.mozilla.fenix.ui.robots.clickPageObject
@ -42,20 +40,14 @@ import org.mozilla.fenix.ui.robots.setPageObjectText
* - save login prompts.
* - saving logins based on the user's preferences.
*/
class LoginsTest {
private lateinit var mockWebServer: MockWebServer
class LoginsTest : TestSetup() {
@get:Rule
val activityTestRule =
HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
override fun setUp() {
super.setUp()
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) {
val autofillManager: AutofillManager =
TestHelper.appContext.getSystemService(AutofillManager::class.java)
@ -63,20 +55,15 @@ class LoginsTest {
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2092713
// Tests the Logins and passwords menu items and default values
// Tests the Passwords menu items and default values
@Test
fun loginsAndPasswordsSettingsItemsTest() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
// Necessary to scroll a little bit for all screen sizes
scrollToElementByText("Logins and passwords")
scrollToElementByText("Passwords")
}.openLoginsAndPasswordSubMenu {
verifyDefaultView()
verifyAutofillInFirefoxToggle(true)
@ -93,7 +80,7 @@ class LoginsTest {
}.openThreeDotMenu {
}.openSettings {
// Necessary to scroll a little bit for all screen sizes
scrollToElementByText("Logins and passwords")
scrollToElementByText("Passwords")
}.openLoginsAndPasswordSubMenu {
verifyDefaultView()
}.openSavedLogins {
@ -111,7 +98,7 @@ class LoginsTest {
}.openThreeDotMenu {
}.openSettings {
// Necessary to scroll a little bit for all screen sizes
scrollToElementByText("Logins and passwords")
scrollToElementByText("Passwords")
}.openLoginsAndPasswordSubMenu {
}.openSyncLogins {
verifyReadyToScanOption()
@ -145,7 +132,7 @@ class LoginsTest {
browserScreen {
}.openThreeDotMenu {
}.openSettings {
scrollToElementByText("Logins and passwords")
scrollToElementByText("Passwords")
}.openLoginsAndPasswordSubMenu {
verifyDefaultView()
}.openSavedLogins {
@ -235,7 +222,7 @@ class LoginsTest {
clickPageObject(itemWithText("Update"))
}.openThreeDotMenu {
}.openSettings {
scrollToElementByText("Logins and passwords")
scrollToElementByText("Passwords")
}.openLoginsAndPasswordSubMenu {
}.openSavedLogins {
verifySecurityPromptForLogins()

@ -5,17 +5,12 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import mozilla.components.concept.engine.utils.EngineReleaseChannel
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertNativeAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertYoutubeAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithCondition
@ -25,6 +20,10 @@ import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.nimbus.FxNimbus
import org.mozilla.fenix.nimbus.Translations
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickContextMenuItem
import org.mozilla.fenix.ui.robots.clickPageObject
@ -32,29 +31,29 @@ import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.longClickPageObject
import org.mozilla.fenix.ui.robots.navigationToolbar
class MainMenuTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class MainMenuTest : TestSetup() {
@get:Rule
val activityTestRule =
HomeActivityIntentTestRule.withDefaultSettingsOverrides(translationsEnabled = true)
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/233849
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
override fun setUp() {
super.setUp()
FxNimbus.features.translations.withInitializer { _, _ ->
// These are FML generated objects and enums
Translations(
mainFlowToolbarEnabled = true,
mainFlowBrowserMenuEnabled = true,
pageSettingsEnabled = true,
globalSettingsEnabled = true,
globalLangSettingsEnabled = true,
globalSiteSettingsEnabled = true,
downloadsEnabled = true,
)
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/233849
@Test
fun verifyTabMainMenuItemsTest() {
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)

@ -4,23 +4,17 @@
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.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -33,36 +27,14 @@ import org.mozilla.fenix.ui.robots.notificationShade
* - a media notification icon is displayed on the homescreen for the tab playing media content
* Note: this test only verifies media notifications, not media itself
*/
class MediaNotificationTest {
private lateinit var mockWebServer: MockWebServer
private lateinit var mDevice: UiDevice
class MediaNotificationTest : TestSetup() {
@get:Rule
val activityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides()
private lateinit var browserStore: BrowserStore
@Rule
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
// Initializing this as part of class construction, below the rule would throw a NPE
// So we are initializing this here instead of in all tests.
browserStore = activityTestRule.activity.components.core.store
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1347033
@SmokeTest
@Test

@ -5,19 +5,14 @@
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.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import java.util.Locale
@ -32,28 +27,10 @@ import java.util.Locale
* - Find in page
*/
class NavigationToolbarTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class NavigationToolbarTest : TestSetup() {
@get:Rule
val activityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides()
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
AppAndSystemHelper.resetSystemLocaleToEnUS()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/987326
// Swipes the nav bar left/right to switch between tabs
@SmokeTest

@ -5,28 +5,20 @@
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 mozilla.components.service.fxa.FirefoxAccount
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.helpers.TestSetup
class NimbusEventTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class NimbusEventTest : TestSetup() {
@get:Rule
val homeActivityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
.withIntent(
@ -39,20 +31,6 @@ class NimbusEventTest {
@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() {
Experimentation.withHelper {

@ -5,22 +5,18 @@
package org.mozilla.fenix.ui
import android.content.Intent
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import mozilla.components.service.nimbus.messaging.FxNimbusMessaging
import mozilla.components.service.nimbus.messaging.MessageData
import mozilla.components.service.nimbus.messaging.Messaging
import mozilla.components.service.nimbus.messaging.StyleData
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.experiments.nimbus.Res
import org.mozilla.fenix.FenixApplication
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.nimbus.FxNimbus
import org.mozilla.fenix.nimbus.HomeScreenSection
import org.mozilla.fenix.nimbus.Homescreen
@ -32,10 +28,7 @@ import org.mozilla.fenix.ui.robots.homeScreen
* Verifies a message can be displayed with all of the correct components
**/
class NimbusMessagingHomescreenTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class NimbusMessagingHomescreenTest : TestSetup() {
private var messageButtonLabel = "CLICK ME"
private var messageText = "Some Nimbus Messaging text"
private var messageTitle = "A Nimbus title"
@ -54,19 +47,20 @@ class NimbusMessagingHomescreenTest {
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
override fun setUp() {
super.setUp()
// Set up nimbus message
FxNimbusMessaging.features.messaging.withInitializer { _, _ ->
// FML generated objects.
Messaging(
messages = mapOf(
"test-message" to MessageData(
action = Res.string("TEST ACTION"),
action = "TEST ACTION",
style = "TEST STYLE",
buttonLabel = Res.string(messageButtonLabel),
text = Res.string(messageText),
title = Res.string(messageTitle),
trigger = listOf("ALWAYS"),
triggerIfAll = listOf("ALWAYS"),
),
),
styles = mapOf(
@ -95,22 +89,11 @@ class NimbusMessagingHomescreenTest {
),
)
}
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
// refresh message store
val application = (homeActivityTestRule.activity.application as FenixApplication)
application.restoreMessaging()
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
@Test
fun testNimbusMessageIsDisplayed() {
// Checks the home screen card message is displayed correctly

@ -5,8 +5,6 @@
package org.mozilla.fenix.ui
import android.content.Context
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import kotlinx.coroutines.test.runTest
import mozilla.components.service.nimbus.messaging.FxNimbusMessaging
import mozilla.components.service.nimbus.messaging.Messaging
@ -20,7 +18,7 @@ import org.junit.Test
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.messaging.CustomAttributeProvider
import org.mozilla.fenix.helpers.TestSetup
/**
* This test is to test the integrity of messages hardcoded in the FML.
@ -28,23 +26,21 @@ import org.mozilla.fenix.messaging.CustomAttributeProvider
* It tests if the trigger expressions are valid, all the fields are complete
* and a simple check if they are localized (don't contain `_`).
*/
class NimbusMessagingMessageTest {
class NimbusMessagingMessageTest : TestSetup() {
private lateinit var feature: Messaging
private lateinit var mDevice: UiDevice
private lateinit var context: Context
private val storage
get() = context.components.analytics.messagingStorage
private val messaging
get() = context.components.nimbus.messaging
@get:Rule
val activityTestRule =
HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@Before
fun setUp() {
override fun setUp() {
super.setUp()
context = TestHelper.appContext
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
feature = FxNimbusMessaging.features.messaging.value()
}
@ -55,7 +51,7 @@ class NimbusMessagingMessageTest {
*/
@Test
fun testAllMessageIntegrity() = runTest {
val messages = storage.getMessages()
val messages = messaging.getMessages()
val rawMessages = feature.messages
assertTrue(rawMessages.isNotEmpty())
@ -68,24 +64,6 @@ class NimbusMessagingMessageTest {
assertEquals(messages.size, rawMessages.size)
}
/**
* Check if the messages' triggers are well formed JEXL.
*/
@Test
fun testAllMessageTriggers() = runTest {
val nimbus = context.components.analytics.experiments
val helper = nimbus.createMessageHelper(
CustomAttributeProvider.getCustomAttributes(context),
)
val messages = storage.getMessages()
messages.forEach { message ->
storage.isMessageEligible(message, helper)
if (storage.malFormedMap.isNotEmpty()) {
fail("${message.id} has a problem with its JEXL trigger: ${storage.malFormedMap.keys}")
}
}
}
private fun checkIsLocalized(string: String) {
assertFalse(string.isBlank())
// The check will almost always succeed, since the generated code

@ -6,10 +6,8 @@ package org.mozilla.fenix.ui
import android.content.Context
import android.os.Build
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
import androidx.test.rule.GrantPermissionRule.grant
import androidx.test.uiautomator.UiDevice
import mozilla.components.service.nimbus.messaging.FxNimbusMessaging
import org.json.JSONObject
import org.junit.Before
@ -18,15 +16,15 @@ import org.junit.Test
import org.mozilla.experiments.nimbus.HardcodedNimbusFeatures
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.nimbus.FxNimbus
import org.mozilla.fenix.ui.robots.notificationShade
/**
* A UI test for testing the notification surface for Nimbus Messaging.
*/
class NimbusMessagingNotificationTest {
private lateinit var mDevice: UiDevice
class NimbusMessagingNotificationTest : TestSetup() {
private lateinit var context: Context
private lateinit var hardcodedNimbus: HardcodedNimbusFeatures
@ -43,9 +41,9 @@ class NimbusMessagingNotificationTest {
}
@Before
fun setUp() {
override fun setUp() {
super.setUp()
context = TestHelper.appContext
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
}
@Test

@ -4,8 +4,6 @@
package org.mozilla.fenix.ui
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import mozilla.components.service.nimbus.messaging.FxNimbusMessaging
import mozilla.components.service.nimbus.messaging.Messaging
import org.junit.Assert
@ -17,6 +15,7 @@ import org.mozilla.experiments.nimbus.internal.NimbusException
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.messaging.CustomAttributeProvider
/**
@ -26,9 +25,7 @@ import org.mozilla.fenix.messaging.CustomAttributeProvider
* - as much of the custom targeting and trigger attributes are recorded as possible.
* - we can run the Rust JEXL evaluator.
*/
class NimbusMessagingTriggerTest {
private lateinit var mDevice: UiDevice
class NimbusMessagingTriggerTest : TestSetup() {
private lateinit var feature: Messaging
private lateinit var nimbus: NimbusInterface
@ -36,9 +33,9 @@ class NimbusMessagingTriggerTest {
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
nimbus = TestHelper.appContext.components.analytics.experiments
override fun setUp() {
super.setUp()
nimbus = TestHelper.appContext.components.nimbus.sdk
feature = FxNimbusMessaging.features.messaging.value()
}

@ -5,7 +5,6 @@
package org.mozilla.fenix.ui
import androidx.core.net.toUri
import org.junit.After
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
@ -14,6 +13,7 @@ import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.verifyUrl
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -23,17 +23,11 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
*
*/
class NoNetworkAccessStartupTests {
class NoNetworkAccessStartupTests : TestSetup() {
@get:Rule
val activityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides(launchActivity = false)
@After
fun tearDown() {
// Restoring network connection
setNetworkEnabled(true)
}
// 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

@ -6,9 +6,10 @@ import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithLauncherIntent
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.homeScreen
class OnboardingTest {
class OnboardingTest : TestSetup() {
@get:Rule
val activityTestRule =
@ -32,7 +33,7 @@ class OnboardingTest {
fun verifyFirstOnboardingCardItemsFunctionalityTest() {
runWithLauncherIntent(activityTestRule) {
homeScreen {
clickNotNowOnboardingButton(activityTestRule)
clickDefaultCardNotNowOnboardingButton(activityTestRule)
verifySecondOnboardingCard(activityTestRule)
swipeSecondOnboardingCardToRight()
}.clickSetAsDefaultBrowserOnboardingButton(activityTestRule) {
@ -48,7 +49,7 @@ class OnboardingTest {
fun verifySecondOnboardingCardItemsTest() {
runWithLauncherIntent(activityTestRule) {
homeScreen {
clickNotNowOnboardingButton(activityTestRule)
clickDefaultCardNotNowOnboardingButton(activityTestRule)
verifySecondOnboardingCard(activityTestRule)
}
}
@ -57,11 +58,13 @@ class OnboardingTest {
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2122344
@SmokeTest
@Test
fun verifySecondOnboardingCardSignInFunctionalityTest() {
fun verifyThirdOnboardingCardSignInFunctionalityTest() {
runWithLauncherIntent(activityTestRule) {
homeScreen {
clickNotNowOnboardingButton(activityTestRule)
clickDefaultCardNotNowOnboardingButton(activityTestRule)
verifySecondOnboardingCard(activityTestRule)
clickAddSearchWidgetNotNowOnboardingButton(activityTestRule)
verifyThirdOnboardingCard(activityTestRule)
}.clickSignInOnboardingButton(activityTestRule) {
verifyTurnOnSyncMenu()
}

@ -5,30 +5,21 @@
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.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.clearDownloadsFolder
import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_DOCS
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.navigationToolbar
class PDFViewerTest {
private lateinit var mockWebServer: MockWebServer
class PDFViewerTest : TestSetup() {
private val downloadTestPage =
"https://storage.googleapis.com/mobile_test_assets/test_app/downloads.html"
private val pdfFileName = "washington.pdf"
@ -38,23 +29,6 @@ class PDFViewerTest {
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
// Check and clear the downloads folder
clearDownloadsFolder()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2048140
@SmokeTest
@Test
@ -70,20 +44,6 @@ class PDFViewerTest {
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2159718
@Test
fun verifyPDFViewerOpenInAppButtonTest() {
val genericURL = getGenericAsset(mockWebServer, 3)
navigationToolbar {
}.enterURLAndEnterToBrowser(genericURL.url) {
clickPageObject(itemWithText("PDF form file"))
verifyPDFReaderToolbarItems()
clickPageObject(itemWithResIdAndText("openInApp", "Open in app"))
assertExternalAppOpens(GOOGLE_DOCS)
}
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2145448
// Download PDF file using the download toolbar button
@Test

@ -1,22 +1,20 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.helpers.Constants
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.homeScreen
/**
* Tests for verifying the presence of the Pocket section and its elements
*/
class PocketTest {
private lateinit var mDevice: UiDevice
class PocketTest : TestSetup() {
private lateinit var firstPocketStoryPublisher: String
@get:Rule(order = 0)
@ -28,9 +26,8 @@ class PocketTest {
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
override fun setUp() {
super.setUp()
// Workaround to make sure the Pocket articles are populated before starting the tests.
homeScreen {
}.openThreeDotMenu {

@ -11,12 +11,13 @@ import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.customTabScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.pwaScreen
class PwaTest {
class PwaTest : TestSetup() {
/* Updated externalLinks.html to v2.0,
changed the hypertext reference to mozilla-mobile.github.io/testapp/downloads for "External link"
*/

@ -5,20 +5,16 @@
package org.mozilla.fenix.ui
import android.view.View
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.helpers.ViewVisibilityIdlingResource
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -32,9 +28,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
*
*/
class ReaderViewTest {
private lateinit var mockWebServer: MockWebServer
private lateinit var mDevice: UiDevice
class ReaderViewTest : TestSetup() {
private val estimatedReadingTime = "1 - 2 minutes"
@get:Rule
@ -44,20 +38,6 @@ class ReaderViewTest {
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
/**
* Verify that Reader View capable pages
*

@ -6,21 +6,17 @@ package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import androidx.test.espresso.intent.Intents
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -29,31 +25,14 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* Tests for verifying basic functionality of recently closed tabs history
*
*/
class RecentlyClosedTabsTest {
private lateinit var mockWebServer: MockWebServer
class RecentlyClosedTabsTest : TestSetup() {
@get:Rule
val activityTestRule = AndroidComposeTestRule(
HomeActivityTestRule.withDefaultSettingsOverrides(
HomeActivityIntentTestRule.withDefaultSettingsOverrides(
tabsTrayRewriteEnabled = true,
),
) { it.activity }
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
Intents.init()
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1065414
// Verifies that a recently closed item is properly opened
@SmokeTest

@ -21,7 +21,6 @@ import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AppAndSystemHelper
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertNativeAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.denyPermission
import org.mozilla.fenix.helpers.AppAndSystemHelper.grantSystemPermission
@ -45,6 +44,7 @@ import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.clickContextMenuItem
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -64,7 +64,7 @@ import java.util.Locale
*
*/
class SearchTest {
class SearchTest : TestSetup() {
private lateinit var searchMockServer: MockWebServer
private var queryString = "firefox"
private val generalEnginesList = listOf("DuckDuckGo", "Google", "Bing")
@ -84,7 +84,8 @@ class SearchTest {
) { it.activity }
@Before
fun setUp() {
override fun setUp() {
super.setUp()
searchMockServer = MockWebServer().apply {
dispatcher = SearchDispatcher()
start()
@ -92,9 +93,8 @@ class SearchTest {
}
@After
fun tearDown() {
override fun tearDown() {
searchMockServer.shutdown()
AppAndSystemHelper.resetSystemLocaleToEnUS()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2154189

@ -4,18 +4,13 @@
package org.mozilla.fenix.ui
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiSelector
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.RetryTestRule
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.clickRateButtonGooglePlay
import org.mozilla.fenix.ui.robots.homeScreen
@ -24,10 +19,7 @@ import org.mozilla.fenix.ui.robots.homeScreen
*
*/
class SettingsAboutTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class SettingsAboutTest : TestSetup() {
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule()
@ -35,20 +27,6 @@ class SettingsAboutTest {
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// Walks through the About settings menu to ensure all items are present
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2092700
@Test

@ -4,15 +4,11 @@
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.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
@ -20,6 +16,7 @@ import org.mozilla.fenix.helpers.TestAssetHelper.getEnhancedTrackingProtectionAs
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestHelper.waitUntilSnackbarGone
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.addonsMenu
import org.mozilla.fenix.ui.robots.homeScreen
@ -27,25 +24,10 @@ import org.mozilla.fenix.ui.robots.homeScreen
* Tests for verifying the functionality of installing or removing addons
*
*/
class SettingsAddonsTest {
private lateinit var mockWebServer: MockWebServer
class SettingsAddonsTest : TestSetup() {
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/875780
// Walks through settings add-ons menu to ensure all items are present
@Test

@ -5,16 +5,10 @@
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.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertYoutubeAppOpens
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
@ -22,6 +16,8 @@ import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
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.mDevice
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -31,31 +27,14 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
*
*/
class SettingsAdvancedTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class SettingsAdvancedTest : TestSetup() {
private val youTubeSchemaLink = itemContainingText("Youtube schema link")
private val youTubeFullLink = itemContainingText("Youtube full link")
private val playStoreLink = itemContainingText("Playstore link")
private val playStoreUrl = "play.google.com"
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2092699
// Walks through settings menu and sub-menus to ensure all items are present
@Test

@ -5,39 +5,21 @@
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.helpers.TestHelper.verifyDarkThemeApplied
import org.mozilla.fenix.helpers.TestHelper.verifyLightThemeApplied
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
class SettingsCustomizeTest {
private lateinit var mockWebServer: MockWebServer
class SettingsCustomizeTest : TestSetup() {
@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)

@ -8,15 +8,10 @@ import android.Manifest
import androidx.core.net.toUri
import androidx.test.espresso.Espresso.pressBack
import androidx.test.rule.GrantPermissionRule
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
@ -26,6 +21,7 @@ import org.mozilla.fenix.helpers.TestAssetHelper.getStorageTestAsset
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.downloadRobot
import org.mozilla.fenix.ui.robots.homeScreen
@ -36,9 +32,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* Delete Browsing Data on quit
*
*/
class SettingsDeleteBrowsingDataOnQuitTest {
private lateinit var mockWebServer: MockWebServer
class SettingsDeleteBrowsingDataOnQuitTest : TestSetup() {
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@ -48,22 +42,6 @@ class SettingsDeleteBrowsingDataOnQuitTest {
Manifest.permission.RECORD_AUDIO,
)
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
// Check and clear the downloads folder
AppAndSystemHelper.clearDownloadsFolder()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/416048
@Test
fun deleteBrowsingDataOnQuitSettingTest() {

@ -4,15 +4,11 @@
package org.mozilla.fenix.ui
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
@ -22,6 +18,7 @@ import org.mozilla.fenix.helpers.TestAssetHelper.getStorageTestAsset
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -33,25 +30,10 @@ import org.mozilla.fenix.ui.robots.settingsScreen
* Delete Browsing Data
*/
class SettingsDeleteBrowsingDataTest {
private lateinit var mockWebServer: MockWebServer
class SettingsDeleteBrowsingDataTest : TestSetup() {
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/937561
@Test
fun deleteBrowsingDataOptionStatesTest() {

@ -4,17 +4,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.FenixApplication
import org.mozilla.fenix.R
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
@ -23,6 +18,7 @@ import org.mozilla.fenix.helpers.RecyclerViewIdlingResource
import org.mozilla.fenix.helpers.TestAssetHelper.getLoremIpsumAsset
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeLong
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.checkTextSizeOnWebsite
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.util.FRENCH_LANGUAGE_HEADER
@ -35,26 +31,10 @@ import java.util.Locale
* Tests for verifying the General section of the Settings menu
*
*/
class SettingsGeneralTest {
private lateinit var mockWebServer: MockWebServer
class SettingsGeneralTest : TestSetup() {
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
AppAndSystemHelper.resetSystemLocaleToEnUS()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2092697
@Test
fun verifyGeneralSettingsItemsTest() {

@ -11,11 +11,12 @@ import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
class SettingsHTTPSOnlyModeTest {
class SettingsHTTPSOnlyModeTest : TestSetup() {
private val httpPageUrl = "http://example.com/"
private val httpsPageUrl = "https://example.com/"
private val insecureHttpPage = "http.badssl.com"

@ -4,14 +4,10 @@
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.AppAndSystemHelper.openAppFromExternalLink
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.RetryTestRule
@ -19,6 +15,7 @@ import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -27,9 +24,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* Tests for verifying the Homepage settings menu
*
*/
class SettingsHomepageTest {
private lateinit var mockWebServer: MockWebServer
class SettingsHomepageTest : TestSetup() {
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@ -37,19 +32,6 @@ class SettingsHomepageTest {
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1564843
@Test
fun verifyHomepageSettingsTest() {

@ -4,16 +4,12 @@
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.Rule
import org.junit.Test
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.TestSetup
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.notificationShade
@ -23,27 +19,10 @@ import org.mozilla.fenix.ui.robots.notificationShade
*
*/
class SettingsPrivacyTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class SettingsPrivacyTest : TestSetup() {
@get:Rule
val activityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2092698
@Test
fun settingsPrivacyItemsTest() {

@ -4,43 +4,26 @@
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.AppAndSystemHelper.openAppFromExternalLink
import org.mozilla.fenix.helpers.DataGenerationHelper.generateRandomString
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.addToHomeScreen
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
class SettingsPrivateBrowsingTest {
private lateinit var mockWebServer: MockWebServer
class SettingsPrivateBrowsingTest : TestSetup() {
private val pageShortcutName = generateRandomString(5)
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/555822
@Test
fun verifyPrivateBrowsingMenuItemsTest() {

@ -13,8 +13,6 @@ 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.AppAndSystemHelper.resetSystemLocaleToEnUS
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithSystemLocaleChanged
import org.mozilla.fenix.helpers.AppAndSystemHelper.setSystemLocale
import org.mozilla.fenix.helpers.DataGenerationHelper.setTextToClipBoard
@ -28,14 +26,14 @@ import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.EngineShortcut
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
import org.mozilla.fenix.ui.robots.searchScreen
import java.util.Locale
class SettingsSearchTest {
private lateinit var mockWebServer: MockWebServer
class SettingsSearchTest : TestSetup() {
private lateinit var searchMockServer: MockWebServer
private val defaultSearchEngineList =
listOf(
@ -50,12 +48,8 @@ class SettingsSearchTest {
) { it.activity }
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
override fun setUp() {
super.setUp()
searchMockServer = MockWebServer().apply {
dispatcher = SearchDispatcher()
start()
@ -63,9 +57,9 @@ class SettingsSearchTest {
}
@After
fun tearDown() {
mockWebServer.shutdown()
resetSystemLocaleToEnUS()
override fun tearDown() {
super.tearDown()
searchMockServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2203333

@ -7,17 +7,11 @@ package org.mozilla.fenix.ui
import androidx.core.net.toUri
import androidx.test.espresso.Espresso.pressBack
import androidx.test.filters.SdkSuppress
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.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.grantSystemPermission
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
@ -25,6 +19,7 @@ import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestAssetHelper.getMutedVideoPageAsset
import org.mozilla.fenix.helpers.TestAssetHelper.getVideoPageAsset
import org.mozilla.fenix.helpers.TestHelper.exitMenu
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -36,13 +31,11 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* - the settings effects on the app behavior
*
*/
class SettingsSitePermissionsTest {
class SettingsSitePermissionsTest : TestSetup() {
/* Test page created and handled by the Mozilla mobile test-eng team */
private val permissionsTestPage = "https://mozilla-mobile.github.io/testapp/v2.0/permissions"
private val permissionsTestPageHost = "https://mozilla-mobile.github.io"
private val testPageSubstring = "https://mozilla-mobile.github.io:443"
private lateinit var mockWebServer: MockWebServer
private lateinit var browserStore: BrowserStore
@get:Rule
val activityTestRule = HomeActivityTestRule(
@ -52,23 +45,6 @@ class SettingsSitePermissionsTest {
isDeleteSitePermissionsEnabled = true,
)
@Before
fun setUp() {
// Initializing this as part of class construction, below the rule would throw a NPE
// So we are initializing this here instead of in all tests.
browserStore = activityTestRule.activity.components.core.store
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/246974
@Test
fun sitePermissionsItemsTest() {

@ -11,14 +11,10 @@ import android.media.AudioManager
import android.os.Build
import androidx.core.net.toUri
import androidx.test.rule.GrantPermissionRule
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertExternalAppOpens
import org.mozilla.fenix.helpers.AppAndSystemHelper.grantSystemPermission
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
@ -27,6 +23,7 @@ import org.mozilla.fenix.helpers.MockLocationUpdatesRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -35,9 +32,8 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* Tests for verifying site permissions prompts & functionality
*
*/
class SitePermissionsTest {
class SitePermissionsTest : TestSetup() {
/* Test page created and handled by the Mozilla mobile test-eng team */
private lateinit var mockWebServer: MockWebServer
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
@ -64,19 +60,6 @@ class SitePermissionsTest {
@get: Rule
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2334295
@SmokeTest
@Test

@ -4,50 +4,27 @@
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.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.Constants.defaultTopSitesList
import org.mozilla.fenix.helpers.DataGenerationHelper.getSponsoredShortcutTitle
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestSetup
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"
class SponsoredShortcutsTest : TestSetup() {
private lateinit var sponsoredShortcutTitle: String
private lateinit var sponsoredShortcutTitle2: String
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1729331
// Expected for en-us defaults
@SmokeTest

@ -4,26 +4,20 @@
package org.mozilla.fenix.ui
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.google.android.material.bottomsheet.BottomSheetBehavior
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.mediasession.MediaSession
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.closeApp
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.homeScreen
@ -47,11 +41,7 @@ import org.mozilla.fenix.ui.robots.notificationShade
* - Shortcut context menu navigation
*/
class TabbedBrowsingTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
private lateinit var browserStore: BrowserStore
class TabbedBrowsingTest : TestSetup() {
@get:Rule
val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@ -59,24 +49,6 @@ class TabbedBrowsingTest {
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
// Initializing this as part of class construction, below the rule would throw a NPE
// So we are initializing this here instead of in all related tests.
browserStore = activityTestRule.activity.components.core.store
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903599
@Test
fun closeAllTabsTest() {

@ -4,20 +4,16 @@
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.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.clickContextMenuItem
import org.mozilla.fenix.ui.robots.clickPageObject
@ -28,10 +24,7 @@ import org.mozilla.fenix.ui.robots.openEditURLView
import org.mozilla.fenix.ui.robots.searchScreen
import org.mozilla.fenix.ui.robots.shareOverlay
class TextSelectionTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class TextSelectionTest : TestSetup() {
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides()
@ -39,20 +32,6 @@ class TextSelectionTest {
@JvmField
val retryTestRule = RetryTestRule(3)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326832
@SmokeTest
@Test

@ -4,24 +4,20 @@
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.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.Constants.defaultTopSitesList
import org.mozilla.fenix.helpers.DataGenerationHelper.generateRandomString
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
import org.mozilla.fenix.helpers.TestHelper.waitUntilSnackbarGone
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.browserScreen
import org.mozilla.fenix.ui.robots.homeScreen
import org.mozilla.fenix.ui.robots.navigationToolbar
@ -35,27 +31,10 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* - Verifies existence of default top sites available on the home-screen
*/
class TopSitesTest {
private lateinit var mDevice: UiDevice
private lateinit var mockWebServer: MockWebServer
class TopSitesTest : TestSetup() {
@get:Rule
val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true)
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/532598
@SmokeTest
@Test

@ -5,16 +5,15 @@
package org.mozilla.fenix.ui
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.components.toolbar.CFR_MINIMUM_NUMBER_OPENED_TABS
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.navigationToolbar
/**
@ -22,9 +21,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar
* Note: This involves setting the feature flags On for CFRs which are disabled elsewhere.
*
*/
class TotalCookieProtectionTest {
private lateinit var mockWebServer: MockWebServer
class TotalCookieProtectionTest : TestSetup() {
@get:Rule
val composeTestRule = AndroidComposeTestRule(
HomeActivityTestRule(
@ -33,17 +30,14 @@ class TotalCookieProtectionTest {
) { it.activity }
@Before
fun setUp() {
override fun setUp() {
super.setUp()
CFR_MINIMUM_NUMBER_OPENED_TABS = 0
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
override fun tearDown() {
super.tearDown()
CFR_MINIMUM_NUMBER_OPENED_TABS = 5
}

@ -10,6 +10,7 @@ import org.junit.Test
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.relaunchCleanApp
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.homeScreen
/**
@ -17,7 +18,7 @@ import org.mozilla.fenix.ui.robots.homeScreen
* Note: This involves setting the feature flag On for the onboarding cards
*
*/
class UpgradingUsersOnboardingTest {
class UpgradingUsersOnboardingTest : TestSetup() {
@get:Rule
val activityTestRule = AndroidComposeTestRule(

@ -4,12 +4,8 @@
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.AppAndSystemHelper.assertNativeAppOpens
import org.mozilla.fenix.helpers.Constants
import org.mozilla.fenix.helpers.HomeActivityTestRule
@ -19,6 +15,7 @@ import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText
import org.mozilla.fenix.helpers.TestAssetHelper
import org.mozilla.fenix.helpers.TestAssetHelper.getHTMLControlsFormAsset
import org.mozilla.fenix.helpers.TestSetup
import org.mozilla.fenix.ui.robots.clickPageObject
import org.mozilla.fenix.ui.robots.navigationToolbar
import java.time.LocalDate
@ -28,9 +25,7 @@ import java.time.LocalDate
*
*/
class WebControlsTest {
private lateinit var mockWebServer: MockWebServer
class WebControlsTest : TestSetup() {
private val hour = 10
private val minute = 10
private val colorHexValue = "#5b2067"
@ -43,19 +38,6 @@ class WebControlsTest {
isTCPCFREnabled = false,
)
@Before
fun setUp() {
mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher()
start()
}
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
// TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2316067
@Test
fun verifyCalendarFormInteractionsTest() {

@ -4,29 +4,66 @@
package org.mozilla.fenix.ui.robots
import android.util.Log
import androidx.test.espresso.Espresso
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.Visibility
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
import org.hamcrest.CoreMatchers
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.click
/**
* Implementation of Robot Pattern for the URL toolbar.
*/
class AccountSettingsRobot {
fun verifyBookmarksCheckbox() = assertBookmarksCheckbox()
fun verifyBookmarksCheckbox() {
Log.i(TAG, "verifyBookmarksCheckbox: Trying to verify that the bookmarks check box is visible")
bookmarksCheckbox().check(
matches(
withEffectiveVisibility(
Visibility.VISIBLE,
),
),
)
Log.i(TAG, "verifyBookmarksCheckbox: Verified that the bookmarks check box is visible")
}
fun verifyHistoryCheckbox() {
Log.i(TAG, "verifyHistoryCheckbox: Trying to verify that the history check box is visible")
historyCheckbox().check(
matches(
withEffectiveVisibility(
Visibility.VISIBLE,
),
),
)
Log.i(TAG, "verifyHistoryCheckbox: Verified that the history check box is visible")
}
fun verifyHistoryCheckbox() = assertHistoryCheckbox()
fun verifySignOutButton() {
Log.i(TAG, "verifySignOutButton: Trying to verify that the \"Sign out\" button is visible")
signOutButton().check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
Log.i(TAG, "verifySignOutButton: Verified that the \"Sign out\" button is visible")
}
fun verifySignOutButton() = assertSignOutButton()
fun verifyDeviceName() = assertDeviceName()
fun verifyDeviceName() {
Log.i(TAG, "verifyDeviceName: Trying to verify that the \"Device name\" option is visible")
deviceName().check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
Log.i(TAG, "verifyDeviceName: Verified that the \"Device name\" option is visible")
}
class Transition {
fun disconnectAccount(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition {
Log.i(TAG, "disconnectAccount: Trying to click the \"Sign out\" button")
signOutButton().click()
Log.i(TAG, "disconnectAccount: Clicked the \"Sign out\" button")
Log.i(TAG, "disconnectAccount: Trying to click the \"Disconnect\" button")
disconnectButton().click()
Log.i(TAG, "disconnectAccount: Clicked the \"Disconnect\" button")
SettingsRobot().interact()
return SettingsRobot.Transition()
@ -46,22 +83,3 @@ private fun signOutButton() = Espresso.onView(CoreMatchers.allOf(ViewMatchers.wi
private fun deviceName() = Espresso.onView(CoreMatchers.allOf(ViewMatchers.withText("Device name")))
private fun disconnectButton() = Espresso.onView(CoreMatchers.allOf(ViewMatchers.withId(R.id.signOutDisconnect)))
private fun assertBookmarksCheckbox() = bookmarksCheckbox().check(
ViewAssertions.matches(
ViewMatchers.withEffectiveVisibility(
ViewMatchers.Visibility.VISIBLE,
),
),
)
private fun assertHistoryCheckbox() = historyCheckbox().check(
ViewAssertions.matches(
ViewMatchers.withEffectiveVisibility(
ViewMatchers.Visibility.VISIBLE,
),
),
)
private fun assertSignOutButton() = signOutButton().check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
private fun assertDeviceName() = deviceName().check(ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))

@ -278,8 +278,8 @@ class BrowserRobot {
fun verifyPDFReaderToolbarItems() =
assertUIObjectExists(
itemWithResIdContainingText("download", "Download"),
itemWithResIdContainingText("openInApp", "Open in app"),
)
fun clickSubmitLoginButton() {
clickPageObject(itemWithResId("submit"))
assertUIObjectIsGone(itemWithResId("submit"))
@ -1408,7 +1408,7 @@ fun setPageObjectText(webPageItem: UiObject, text: String) {
it.clearTextField()
Log.i(TAG, "setPageObjectText: Cleared ${webPageItem.selector} text field")
Log.i(TAG, "setPageObjectText: Trying to set ${webPageItem.selector} text to $text")
it.text = text
it.setText(text)
Log.i(TAG, "setPageObjectText: ${webPageItem.selector} text was set to $text")
}

@ -58,7 +58,7 @@ class CollectionRobot {
// names a collection saved from tab drawer
fun typeCollectionNameAndSave(collectionName: String) {
Log.i(TAG, "typeCollectionNameAndSave: Trying to set collection name text field to: $collectionName")
collectionNameTextField().text = collectionName
collectionNameTextField().setText(collectionName)
Log.i(TAG, "typeCollectionNameAndSave: Collection name text field set to: $collectionName")
Log.i(TAG, "typeCollectionNameAndSave: Waiting for $waitingTime ms for add collection button panel to exist")
addCollectionButtonPanel().waitForExists(waitingTime)
@ -228,7 +228,7 @@ class CollectionRobot {
mainMenuEditCollectionNameField().waitForExists(waitingTime)
Log.i(TAG, "typeCollectionNameAndSave: Waited for $waitingTime ms for collection name text field to exist")
Log.i(TAG, "typeCollectionNameAndSave: Trying to set collection name text field to: $name")
mainMenuEditCollectionNameField().text = name
mainMenuEditCollectionNameField().setText(name)
Log.i(TAG, "typeCollectionNameAndSave: Collection name text field set to: $name")
Log.i(TAG, "typeCollectionNameAndSave: Trying to press done action button")
onView(withId(R.id.name_collection_edittext)).perform(pressImeActionButton())

@ -136,7 +136,9 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest
}
}
@OptIn(ExperimentalTestApi::class)
fun verifyNormalTabsList() {
composeTestRule.waitUntilDoesNotExist(hasTestTag("tabstray.tabList.normal.empty"), waitingTime)
Log.i(TAG, "verifyNormalTabsList: Trying to verify that the normal tabs list exists")
composeTestRule.normalTabsList().assertExists()
Log.i(TAG, "verifyNormalTabsList: Verified that the normal tabs list exists")

@ -150,7 +150,6 @@ class CustomTabRobot {
fun verifyPDFReaderToolbarItems() =
assertUIObjectExists(
itemWithResIdAndText("download", "Download"),
itemWithResIdAndText("openInApp", "Open in app"),
)
class Transition {

@ -223,7 +223,7 @@ fun historyMenu(interact: HistoryRobot.() -> Unit): HistoryRobot.Transition {
return HistoryRobot.Transition()
}
private fun testPageTitle() = onView(allOf(withId(R.id.title), withText("Test_Page_1")))
private fun testPageTitle() = onView(withId(R.id.title))
private fun pageUrl(url: String) = onView(allOf(withId(R.id.url), withText(url)))

@ -201,31 +201,72 @@ class HomeScreenRobot {
composeTestRule.also {
Log.i(TAG, "verifySecondOnboardingCard: Trying to verify that the second onboarding screen title exists")
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_sign_in_title_2),
getStringResource(R.string.juno_onboarding_add_search_widget_title),
).assertExists()
Log.i(TAG, "verifySecondOnboardingCard: Verified that the second onboarding screen title exists")
Log.i(TAG, "verifySecondOnboardingCard: Trying to verify that the second onboarding screen description exists")
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_sign_in_description_2),
getStringResource(R.string.juno_onboarding_add_search_widget_description),
).assertExists()
Log.i(TAG, "verifySecondOnboardingCard: Verified that the second onboarding screen description exists")
Log.i(TAG, "verifySecondOnboardingCard: Trying to verify that the first onboarding \"Sign in\" button exists")
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_sign_in_positive_button),
getStringResource(R.string.juno_onboarding_add_search_widget_positive_button),
).assertExists()
Log.i(TAG, "verifySecondOnboardingCard: Verified that the first onboarding \"Add Firefox widget\" button exists")
Log.i(TAG, "verifySecondOnboardingCard: Trying to verify that the second onboarding \"Not now\" button exists")
it.onNodeWithTag(
getStringResource(R.string.juno_onboarding_add_search_widget_title) + "onboarding_card.negative_button",
).assertExists()
Log.i(TAG, "verifySecondOnboardingCard: Verified that the second onboarding \"Not now\" button exists")
}
}
fun verifyThirdOnboardingCard(composeTestRule: ComposeTestRule) {
composeTestRule.also {
Log.i(TAG, "verifyThirdOnboardingCard: Trying to verify that the third onboarding screen title exists")
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_sign_in_title_2),
).assertExists()
Log.i(TAG, "verifyThirdOnboardingCard: Verified that the third onboarding screen title exists")
Log.i(TAG, "verifyThirdOnboardingCard: Trying to verify that the third onboarding screen description exists")
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_sign_in_description_2),
).assertExists()
Log.i(TAG, "verifySecondOnboardingCard: Verified that the first onboarding \"Sign in\" button exists")
Log.i(TAG, "verifySecondOnboardingCard: Trying to verify that the first onboarding \"Not now\" button exists")
Log.i(TAG, "verifyThirdOnboardingCard: Verified that the third onboarding screen description exists")
Log.i(TAG, "verifyThirdOnboardingCard: Trying to verify that the first onboarding \"Sign in\" button exists")
it.onNodeWithText(
getStringResource(R.string.juno_onboarding_sign_in_negative_button),
getStringResource(R.string.juno_onboarding_sign_in_positive_button),
).assertExists()
Log.i(TAG, "verifySecondOnboardingCard: Verified that the first onboarding \"Not now\" button exists")
Log.i(TAG, "verifyThirdOnboardingCard: Verified that the first onboarding \"Sign in\" button exists")
Log.i(TAG, "verifyThirdOnboardingCard: Trying to verify that the third onboarding \"Not now\" button exists")
it.onNodeWithTag(
getStringResource(R.string.juno_onboarding_sign_in_title_2) + "onboarding_card.negative_button",
).assertExists()
Log.i(TAG, "verifySecondOnboardingCard: Verified that the third onboarding \"Not now\" button exists")
}
}
fun clickNotNowOnboardingButton(composeTestRule: ComposeTestRule) {
fun clickDefaultCardNotNowOnboardingButton(composeTestRule: ComposeTestRule) {
Log.i(TAG, "clickNotNowOnboardingButton: Trying to click \"Not now\" onboarding button")
composeTestRule.onNodeWithTag(
getStringResource(R.string.juno_onboarding_default_browser_title_nimbus_2) + "onboarding_card.negative_button",
).performClick()
Log.i(TAG, "clickNotNowOnboardingButton: Clicked \"Not now\" onboarding button")
}
fun clickAddSearchWidgetNotNowOnboardingButton(composeTestRule: ComposeTestRule) {
Log.i(TAG, "clickNotNowOnboardingButton: Trying to click \"Not now\" onboarding button")
composeTestRule.onNodeWithTag(
getStringResource(R.string.juno_onboarding_add_search_widget_title) + "onboarding_card.negative_button",
).performClick()
Log.i(TAG, "clickNotNowOnboardingButton: Clicked \"Not now\" onboarding button")
}
fun clickSyncSignInWidgetNotNowOnboardingButton(composeTestRule: ComposeTestRule) {
Log.i(TAG, "clickNotNowOnboardingButton: Trying to click \"Not now\" onboarding button")
composeTestRule.onNodeWithText(
getStringResource(R.string.juno_onboarding_default_browser_negative_button),
composeTestRule.onNodeWithTag(
getStringResource(R.string.juno_onboarding_sign_in_title_2) + "onboarding_card.negative_button",
).performClick()
Log.i(TAG, "clickNotNowOnboardingButton: Clicked \"Not now\" onboarding button")
}

@ -19,6 +19,7 @@ class PwaRobot {
fun verifyCustomTabToolbarIsNotDisplayed() = assertUIObjectExists(itemWithResId("$packageName:id/toolbar"), exists = false)
fun verifyPwaActivityInCurrentTask() {
assertTrue("$TAG: The latest activity of the application is not used for custom tabs or PWAs", isExternalAppBrowserActivityInCurrentTask())
Log.i(TAG, "verifyPwaActivityInCurrentTask: Verified that the latest activity of the application is used for custom tabs or PWAs")
}
class Transition

@ -18,7 +18,6 @@ import androidx.compose.ui.test.onAllNodesWithTag
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performScrollToNode
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.closeSoftKeyboard
import androidx.test.espresso.assertion.PositionAssertions
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.intent.Intents
@ -28,16 +27,18 @@ import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiScrollable
import androidx.test.uiautomator.UiSelector
import org.hamcrest.CoreMatchers.allOf
import org.junit.Assert.assertTrue
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.AppAndSystemHelper.grantSystemPermission
import org.mozilla.fenix.helpers.AppAndSystemHelper.isPackageInstalled
import org.mozilla.fenix.helpers.Constants
import org.mozilla.fenix.helpers.Constants.LONG_CLICK_DURATION
import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_QUICK_SEARCH
import org.mozilla.fenix.helpers.Constants.RETRY_COUNT
import org.mozilla.fenix.helpers.Constants.SPEECH_RECOGNITION
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.MatcherHelper.assertItemTextContains
import org.mozilla.fenix.helpers.MatcherHelper.assertItemTextEquals
@ -67,18 +68,23 @@ class SearchRobot {
)
fun verifyScanButtonVisibility(visible: Boolean = true) =
assertUIObjectExists(scanButton, exists = visible)
assertUIObjectExists(scanButton(), exists = visible)
fun verifyVoiceSearchButtonVisibility(enabled: Boolean) =
assertUIObjectExists(voiceSearchButton, exists = enabled)
assertUIObjectExists(voiceSearchButton(), exists = enabled)
// Device or AVD requires a Google Services Android OS installation
fun startVoiceSearch() {
voiceSearchButton.click()
Log.i(TAG, "startVoiceSearch: Trying to click the voice search button button")
voiceSearchButton().click()
Log.i(TAG, "startVoiceSearch: Clicked the voice search button button")
grantSystemPermission()
if (isPackageInstalled(Constants.PackageName.GOOGLE_QUICK_SEARCH)) {
if (isPackageInstalled(GOOGLE_QUICK_SEARCH)) {
Log.i(TAG, "startVoiceSearch: $GOOGLE_QUICK_SEARCH is installed")
Log.i(TAG, "startVoiceSearch: Trying to verify the intent to: $GOOGLE_QUICK_SEARCH")
Intents.intended(IntentMatchers.hasAction(SPEECH_RECOGNITION))
Log.i(TAG, "startVoiceSearch: Verified the intent to: $GOOGLE_QUICK_SEARCH")
}
}
@ -91,15 +97,20 @@ class SearchRobot {
) {
rule.waitForIdle()
for (i in 1..RETRY_COUNT) {
Log.i(TAG, "verifySearchEngineSuggestionResults: Started try #$i")
try {
for (searchSuggestion in searchSuggestions) {
mDevice.waitForObjects(mDevice.findObject(UiSelector().textContains(searchSuggestion)))
rule.onNodeWithTag("mozac.awesomebar.suggestions")
.performScrollToNode(hasText(searchSuggestion))
.assertExists()
Log.i(TAG, "verifySearchEngineSuggestionResults: Trying to perform scroll action to $searchSuggestion search suggestion")
rule.onNodeWithTag("mozac.awesomebar.suggestions").performScrollToNode(hasText(searchSuggestion))
Log.i(TAG, "verifySearchEngineSuggestionResults: Performed scroll action to $searchSuggestion search suggestion")
Log.i(TAG, "verifySearchEngineSuggestionResults: Trying to verify that $searchSuggestion search suggestion exists")
rule.onNodeWithTag("mozac.awesomebar.suggestions").assertExists()
Log.i(TAG, "verifySearchEngineSuggestionResults: Verified that $searchSuggestion search suggestion exists")
}
break
} catch (e: AssertionError) {
Log.i(TAG, "verifySearchEngineSuggestionResults: AssertionError caught, executing fallback methods")
if (i == RETRY_COUNT) {
throw e
} else {
@ -117,29 +128,41 @@ class SearchRobot {
}
fun verifySuggestionsAreNotDisplayed(rule: ComposeTestRule, vararg searchSuggestions: String) {
Log.i(TAG, "verifySuggestionsAreNotDisplayed: Waiting for compose test rule to be idle")
rule.waitForIdle()
Log.i(TAG, "verifySuggestionsAreNotDisplayed: Waited for compose test rule to be idle")
for (searchSuggestion in searchSuggestions) {
Log.i(TAG, "verifySuggestionsAreNotDisplayed: Trying to verify that there are no $searchSuggestion related search suggestions")
rule.onAllNodesWithTag("mozac.awesomebar.suggestions")
.assertAny(
hasText(searchSuggestion)
.not(),
)
Log.i(TAG, "verifySuggestionsAreNotDisplayed: Verified that there are no $searchSuggestion related search suggestions")
}
}
@OptIn(ExperimentalTestApi::class)
fun verifySearchSuggestionsCount(rule: ComposeTestRule, numberOfSuggestions: Int, searchTerm: String) {
for (i in 1..RETRY_COUNT) {
Log.i(TAG, "verifySearchSuggestionsCount: Started try #$i")
try {
Log.i(TAG, "verifySearchSuggestionsCount: Compose test rule is waiting for $waitingTime ms until the note count equals to: $numberOfSuggestions")
rule.waitUntilNodeCount(hasTestTag("mozac.awesomebar.suggestion"), numberOfSuggestions, waitingTime)
Log.i(TAG, "verifySearchSuggestionsCount: Compose test rule waited for $waitingTime ms until the note count equals to: $numberOfSuggestions")
Log.i(TAG, "verifySearchSuggestionsCount: Trying to verify that the count of the search suggestions equals: $numberOfSuggestions")
rule.onAllNodesWithTag("mozac.awesomebar.suggestion").assertCountEquals(numberOfSuggestions)
Log.i(TAG, "verifySearchSuggestionsCount: Verified that the count of the search suggestions equals: $numberOfSuggestions")
break
} catch (e: ComposeTimeoutException) {
Log.i(TAG, "verifySearchSuggestionsCount: ComposeTimeoutException caught, executing fallback methods")
if (i == RETRY_COUNT) {
throw e
} else {
Log.i(TAG, "verifySearchSuggestionsCount: Trying to click device back button")
mDevice.pressBack()
Log.i(TAG, "verifySearchSuggestionsCount: Clicked device back button")
homeScreen {
}.openSearch {
typeSearch(searchTerm)
@ -159,28 +182,38 @@ class SearchRobot {
)
fun denySuggestionsInPrivateMode() {
Log.i(TAG, "denySuggestionsInPrivateMode: Trying to click the \"Dont allow\" button")
mDevice.findObject(
UiSelector().text(getStringResource(R.string.search_suggestions_onboarding_do_not_allow_button)),
).click()
Log.i(TAG, "denySuggestionsInPrivateMode: Clicked the \"Dont allow\" button")
}
fun allowSuggestionsInPrivateMode() {
Log.i(TAG, "allowSuggestionsInPrivateMode: Trying to click the \"Allow\" button")
mDevice.findObject(
UiSelector().text(getStringResource(R.string.search_suggestions_onboarding_allow_button)),
).click()
Log.i(TAG, "allowSuggestionsInPrivateMode: Clicked the \"Allow\" button")
}
fun verifySearchSelectorButton() = assertUIObjectExists(searchSelectorButton)
fun verifySearchSelectorButton() = assertUIObjectExists(searchSelectorButton())
fun clickSearchSelectorButton() {
searchSelectorButton.waitForExists(waitingTime)
searchSelectorButton.click()
Log.i(TAG, "clickSearchSelectorButton: Waiting for $waitingTime ms for search selector button to exist")
searchSelectorButton().waitForExists(waitingTime)
Log.i(TAG, "clickSearchSelectorButton: Waited for $waitingTime ms for search selector button to exist")
Log.i(TAG, "clickSearchSelectorButton: Trying to click the search selector button")
searchSelectorButton().click()
Log.i(TAG, "clickSearchSelectorButton: Clicked the search selector button")
}
fun verifySearchEngineIcon(name: String) = assertUIObjectExists(itemWithDescription(name))
fun verifySearchBarPlaceholder(text: String) {
Log.i(TAG, "verifySearchBarPlaceholder: Waiting for $waitingTime ms for the edit mode toolbar to exist")
browserToolbarEditView().waitForExists(waitingTime)
Log.i(TAG, "verifySearchBarPlaceholder: Waited for $waitingTime ms for the edit mode toolbar to exist")
assertItemTextEquals(browserToolbarEditView(), expectedText = text)
}
@ -188,105 +221,140 @@ class SearchRobot {
searchEngineName.forEach {
if (shouldExist) {
assertUIObjectExists(
searchShortcutList.getChild(UiSelector().text(it)),
searchShortcutList().getChild(UiSelector().text(it)),
)
} else {
assertUIObjectIsGone(searchShortcutList.getChild(UiSelector().text(it)))
assertUIObjectIsGone(searchShortcutList().getChild(UiSelector().text(it)))
}
}
}
// New unified search UI search selector.
fun selectTemporarySearchMethod(searchEngineName: String) {
searchShortcutList.getChild(UiSelector().text(searchEngineName)).click()
Log.i(TAG, "selectTemporarySearchMethod: Trying to click the $searchEngineName search shortcut")
searchShortcutList().getChild(UiSelector().text(searchEngineName)).click()
Log.i(TAG, "selectTemporarySearchMethod: Clicked the $searchEngineName search shortcut")
}
fun clickScanButton() =
scanButton.also {
scanButton().also {
Log.i(TAG, "clickScanButton: Waiting for $waitingTime ms for the scan button to exist")
it.waitForExists(waitingTime)
Log.i(TAG, "clickScanButton: Waited for $waitingTime ms for the scan button to exist")
Log.i(TAG, "clickScanButton: Trying to click the scan button")
it.click()
Log.i(TAG, "clickScanButton: Clicked the scan button")
}
fun clickDismissPermissionRequiredDialog() {
dismissPermissionButton.waitForExists(waitingTime)
dismissPermissionButton.click()
Log.i(TAG, "clickDismissPermissionRequiredDialog: Waiting for $waitingTime ms for the \"Dismiss\" permission button to exist")
dismissPermissionButton().waitForExists(waitingTime)
Log.i(TAG, "clickDismissPermissionRequiredDialog: Waited for $waitingTime ms for the \"Dismiss\" permission button to exist")
Log.i(TAG, "clickDismissPermissionRequiredDialog: Trying to click the \"Dismiss\" permission button")
dismissPermissionButton().click()
Log.i(TAG, "clickDismissPermissionRequiredDialog: Clicked the \"Dismiss\" permission button")
}
fun clickGoToPermissionsSettings() {
goToPermissionsSettingsButton.waitForExists(waitingTime)
goToPermissionsSettingsButton.click()
Log.i(TAG, "clickGoToPermissionsSettings: Waiting for $waitingTime ms for the \"Go To Settings\" permission button to exist")
goToPermissionsSettingsButton().waitForExists(waitingTime)
Log.i(TAG, "clickGoToPermissionsSettings: Waited for $waitingTime ms for the \"Go To Settings\" permission button to exist")
Log.i(TAG, "clickGoToPermissionsSettings: Trying to click the \"Go To Settings\" permission button")
goToPermissionsSettingsButton().click()
Log.i(TAG, "clickGoToPermissionsSettings: Clicked the \"Go To Settings\" permission button")
}
fun verifyScannerOpen() {
Log.i(TAG, "verifyScannerOpen: Trying to verify that the device camera is opened or that the camera app error message exist")
assertTrue(
"$TAG: Neither the device camera was opened nor the camera app error message was displayed",
mDevice.findObject(UiSelector().resourceId("$packageName:id/view_finder"))
.waitForExists(waitingTime) ||
// In case there is no camera available, an error will be shown.
mDevice.findObject(UiSelector().resourceId("$packageName:id/camera_error"))
.exists(),
)
Log.i(TAG, "verifyScannerOpen: Verified that the device camera is opened or that the camera app error message exist")
}
fun typeSearch(searchTerm: String) {
mDevice.findObject(
UiSelector().resourceId("$packageName:id/mozac_browser_toolbar_edit_url_view"),
).waitForExists(waitingTime)
Log.i(TAG, "typeSearch: Waiting for $waitingTime ms for the edit mode toolbar to exist")
browserToolbarEditView().waitForExists(waitingTime)
Log.i(TAG, "typeSearch: Waited for $waitingTime ms for the edit mode toolbar to exist")
Log.i(TAG, "typeSearch: Trying to set the edit mode toolbar text to $searchTerm")
browserToolbarEditView().setText(searchTerm)
Log.i(TAG, "typeSearch: Edit mode toolbar text was set to $searchTerm")
Log.i(TAG, "typeSearch: Waiting for device to be idle")
mDevice.waitForIdle()
Log.i(TAG, "typeSearch: Waited for device to be idle")
}
fun clickClearButton() {
Log.i(TAG, "clickClearButton: Trying to click the clear button")
clearButton().click()
Log.i(TAG, "clickClearButton: Clicked the clear button")
}
fun tapOutsideToDismissSearchBar() {
itemWithResId("$packageName:id/search_wrapper").click()
itemWithResId("$packageName:id/mozac_browser_toolbar_edit_url_view")
.waitUntilGone(waitingTime)
Log.i(TAG, "tapOutsideToDismissSearchBar: Trying to perform a backward scroll action")
// After updating UIAutomator to 2.3.0 the click action doesn't seem to dismiss anymore the awesome bar
// On the other hand, the scroll action seems to be working properly and dismisses the awesome bar
UiScrollable(UiSelector().resourceId("$packageName:id/search_wrapper")).scrollBackward()
Log.i(TAG, "tapOutsideToDismissSearchBar: Performed a backward scroll action")
Log.i(TAG, "tapOutsideToDismissSearchBar: Waiting for $waitingTime ms for the edit mode toolbar to be gone")
browserToolbarEditView().waitUntilGone(waitingTime)
Log.i(TAG, "tapOutsideToDismissSearchBar: Waited for $waitingTime ms for the edit mode toolbar to be gone")
}
fun longClickToolbar() {
Log.i(TAG, "longClickToolbar: Waiting for $waitingTime ms for $packageName window to be updated")
mDevice.waitForWindowUpdate(packageName, waitingTime)
Log.i(TAG, "longClickToolbar: Waited for $waitingTime ms for $packageName window to be updated")
Log.i(TAG, "longClickToolbar: Waiting for $waitingTime ms for the awesome bar to exist")
mDevice.findObject(UiSelector().resourceId("$packageName:id/awesomeBar"))
.waitForExists(waitingTime)
Log.i(TAG, "longClickToolbar: Waited for $waitingTime ms for the awesome bar to exist")
Log.i(TAG, "longClickToolbar: Waiting for $waitingTime ms for the toolbar to exist")
mDevice.findObject(UiSelector().resourceId("$packageName:id/toolbar"))
.waitForExists(waitingTime)
val toolbar = mDevice.findObject(By.res("$packageName:id/toolbar"))
toolbar.click(LONG_CLICK_DURATION)
Log.i(TAG, "longClickToolbar: Waited for $waitingTime ms for the toolbar to exist")
Log.i(TAG, "longClickToolbar: Trying to perform long click on the toolbar")
mDevice.findObject(By.res("$packageName:id/toolbar")).click(LONG_CLICK_DURATION)
Log.i(TAG, "longClickToolbar: Performed long click on the toolbar")
}
fun clickPasteText() {
Log.i(TAG, "clickPasteText: Waiting for $waitingTime ms for the \"Paste\" option to exist")
mDevice.findObject(UiSelector().textContains("Paste")).waitForExists(waitingTime)
val pasteText = mDevice.findObject(By.textContains("Paste"))
pasteText.click()
}
fun expandSearchSuggestionsList() {
onView(allOf(withId(R.id.search_wrapper))).perform(
closeSoftKeyboard(),
)
browserToolbarEditView().swipeUp(2)
Log.i(TAG, "clickPasteText: Waited for $waitingTime ms for the \"Paste\" option to exist")
Log.i(TAG, "clickPasteText: Trying to click the \"Paste\" button")
mDevice.findObject(By.textContains("Paste")).click()
Log.i(TAG, "clickPasteText: Clicked the \"Paste\" button")
}
fun verifyTranslatedFocusedNavigationToolbar(toolbarHintString: String) =
assertItemTextContains(browserToolbarEditView(), itemText = toolbarHintString)
fun verifyTypedToolbarText(expectedText: String) {
Log.i(TAG, "verifyTypedToolbarText: Waiting for $waitingTime ms for the toolbar to exist")
mDevice.findObject(UiSelector().resourceId("$packageName:id/toolbar"))
.waitForExists(waitingTime)
mDevice.findObject(UiSelector().resourceId("$packageName:id/mozac_browser_toolbar_url_view"))
.waitForExists(waitingTime)
Log.i(TAG, "verifyTypedToolbarText: Waited for $waitingTime ms for the toolbar to exist")
Log.i(TAG, "verifyTypedToolbarText: Waiting for $waitingTime ms for the edit mode toolbar to exist")
browserToolbarEditView().waitForExists(waitingTime)
Log.i(TAG, "verifyTypedToolbarText: Waited for $waitingTime ms for the edit mode toolbar to exist")
Log.i(TAG, "verifyTypedToolbarText: Trying to verify that $expectedText is visible in the toolbar")
onView(
allOf(
withText(expectedText),
withId(R.id.mozac_browser_toolbar_edit_url_view),
),
).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
Log.i(TAG, "verifyTypedToolbarText: Verified that $expectedText is visible in the toolbar")
}
fun verifySearchBarPosition(bottomPosition: Boolean) {
Log.i(TAG, "verifySearchBarPosition: Trying to verify that the search bar is set to bottom: $bottomPosition")
onView(withId(R.id.toolbar))
.check(
if (bottomPosition) {
@ -295,13 +363,17 @@ class SearchRobot {
PositionAssertions.isCompletelyAbove(withId(R.id.keyboard_divider))
},
)
Log.i(TAG, "verifySearchBarPosition: Verified that the search bar is set to bottom: $bottomPosition")
}
fun deleteSearchKeywordCharacters(numberOfDeletionSteps: Int) {
for (i in 1..numberOfDeletionSteps) {
Log.i(TAG, "deleteSearchKeywordCharacters: Trying to click keyboard delete button $i times")
mDevice.pressDelete()
Log.i(Constants.TAG, "deleteSearchKeywordCharacters: Pressed keyboard delete button $i times")
Log.i(TAG, "deleteSearchKeywordCharacters: Clicked keyboard delete button $i times")
Log.i(TAG, "deleteSearchKeywordCharacters: Waiting for $waitingTimeShort ms for $appName window to be updated")
mDevice.waitForWindowUpdate(appName, waitingTimeShort)
Log.i(TAG, "deleteSearchKeywordCharacters: Waited for $waitingTimeShort ms for $appName window to be updated")
}
}
@ -310,11 +382,18 @@ class SearchRobot {
fun dismissSearchBar(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
try {
Log.i(TAG, "dismissSearchBar: Waiting for $waitingTime ms for the search wrapper to exist")
searchWrapper().waitForExists(waitingTime)
Log.i(TAG, "dismissSearchBar: Waited for $waitingTime ms for the search wrapper to exist")
Log.i(TAG, "dismissSearchBar: Trying to click device back button")
mDevice.pressBack()
Log.i(TAG, "dismissSearchBar: Clicked device back button")
assertUIObjectIsGone(searchWrapper())
} catch (e: AssertionError) {
Log.i(TAG, "dismissSearchBar: AssertionError caught, executing fallback methods")
Log.i(TAG, "dismissSearchBar: Trying to click device back button")
mDevice.pressBack()
Log.i(TAG, "dismissSearchBar: Clicked device back button")
assertUIObjectIsGone(searchWrapper())
}
@ -323,9 +402,15 @@ class SearchRobot {
}
fun openBrowser(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
Log.i(TAG, "openBrowser: Waiting for device to be idle")
mDevice.waitForIdle()
Log.i(TAG, "openBrowser: Waited for device to be idle")
Log.i(TAG, "openBrowser: Trying to set the edit mode toolbar text to: mozilla")
browserToolbarEditView().setText("mozilla\n")
Log.i(TAG, "openBrowser: Edit mode toolbar text was set to: mozilla")
Log.i(TAG, "openBrowser: Trying to click device enter button")
mDevice.pressEnter()
Log.i(TAG, "openBrowser: Clicked device enter button")
BrowserRobot().interact()
return BrowserRobot.Transition()
@ -333,9 +418,15 @@ class SearchRobot {
fun submitQuery(query: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
sessionLoadedIdlingResource = SessionLoadedIdlingResource()
Log.i(TAG, "submitQuery: Waiting for $waitingTime ms for the search wrapper to exist")
searchWrapper().waitForExists(waitingTime)
Log.i(TAG, "submitQuery: Waited for $waitingTime ms for the search wrapper to exist")
Log.i(TAG, "submitQuery: Trying to set the edit mode toolbar text to: $query")
browserToolbarEditView().setText(query)
Log.i(TAG, "submitQuery: Edit mode toolbar text was set to: $query")
Log.i(TAG, "submitQuery: Trying to click device enter button")
mDevice.pressEnter()
Log.i(TAG, "submitQuery: Clicked device enter button")
runWithIdleRes(sessionLoadedIdlingResource) {
assertUIObjectExists(itemWithResId("$packageName:id/browserLayout"))
@ -346,7 +437,9 @@ class SearchRobot {
}
fun clickSearchEngineSettings(interact: SettingsSubMenuSearchRobot.() -> Unit): SettingsSubMenuSearchRobot.Transition {
searchShortcutList.getChild(UiSelector().text("Search settings")).click()
Log.i(TAG, "clickSearchEngineSettings: Trying to click the \"Search settings\" button")
searchShortcutList().getChild(UiSelector().text("Search settings")).click()
Log.i(TAG, "clickSearchEngineSettings: Clicked the \"Search settings\" button")
SettingsSubMenuSearchRobot().interact()
return SettingsSubMenuSearchRobot.Transition()
@ -354,8 +447,12 @@ class SearchRobot {
fun clickSearchSuggestion(searchSuggestion: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
mDevice.findObject(UiSelector().textContains(searchSuggestion)).also {
Log.i(TAG, "clickSearchSuggestion: Waiting for $waitingTime ms for search suggestion: $searchSuggestion to exist")
it.waitForExists(waitingTime)
Log.i(TAG, "clickSearchSuggestion: Waited for $waitingTime ms for search suggestion: $searchSuggestion to exist")
Log.i(TAG, "clickSearchSuggestion: Trying to click search suggestion: $searchSuggestion and wait for $waitingTimeShort ms for a new window")
it.clickAndWaitForNewWindow(waitingTimeShort)
Log.i(TAG, "clickSearchSuggestion: Clicked search suggestion: $searchSuggestion and waited for $waitingTimeShort ms for a new window")
}
BrowserRobot().interact()
@ -372,22 +469,22 @@ fun searchScreen(interact: SearchRobot.() -> Unit): SearchRobot.Transition {
private fun browserToolbarEditView() =
mDevice.findObject(UiSelector().resourceId("$packageName:id/mozac_browser_toolbar_edit_url_view"))
private val dismissPermissionButton =
private fun dismissPermissionButton() =
mDevice.findObject(UiSelector().text("DISMISS"))
private val goToPermissionsSettingsButton =
private fun goToPermissionsSettingsButton() =
mDevice.findObject(UiSelector().text("GO TO SETTINGS"))
private val scanButton = itemWithDescription("Scan")
private fun scanButton() = itemWithDescription("Scan")
private fun clearButton() =
mDevice.findObject(UiSelector().resourceId("$packageName:id/mozac_browser_toolbar_clear_view"))
private fun searchWrapper() = mDevice.findObject(UiSelector().resourceId("$packageName:id/search_wrapper"))
private val searchSelectorButton = itemWithResId("$packageName:id/search_selector")
private fun searchSelectorButton() = itemWithResId("$packageName:id/search_selector")
private val searchShortcutList =
private fun searchShortcutList() =
mDevice.findObject(UiSelector().resourceId("$packageName:id/mozac_browser_menu_recyclerView"))
private val voiceSearchButton = mDevice.findObject(UiSelector().description("Voice search"))
private fun voiceSearchButton() = mDevice.findObject(UiSelector().description("Voice search"))

@ -201,9 +201,9 @@ class SettingsRobot {
Log.i(TAG, "verifyEnhancedTrackingProtectionButton: Verified that the \"Enhanced Tracking Protection\" button is visible")
}
fun verifyLoginsAndPasswordsButton() {
scrollToElementByText("Logins and passwords")
scrollToElementByText("Passwords")
Log.i(TAG, "verifyLoginsAndPasswordsButton: Trying to verify that the \"Logins and passwords\" button is visible")
onView(withText(R.string.preferences_passwords_logins_and_passwords))
onView(withText(R.string.preferences_passwords_logins_and_passwords_2))
.check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
Log.i(TAG, "verifyLoginsAndPasswordsButton: Verified that the \"Logins and passwords\" button is visible")
}
@ -625,9 +625,9 @@ class SettingsRobot {
}
fun openLoginsAndPasswordSubMenu(interact: SettingsSubMenuLoginsAndPasswordRobot.() -> Unit): SettingsSubMenuLoginsAndPasswordRobot.Transition {
scrollToElementByText("Logins and passwords")
scrollToElementByText("Passwords")
Log.i(TAG, "openLoginsAndPasswordSubMenu: Trying to click the \"Logins and passwords\" button")
onView(withText("Logins and passwords")).click()
onView(withText("Passwords")).click()
Log.i(TAG, "openLoginsAndPasswordSubMenu: Clicked the \"Logins and passwords\" button")
SettingsSubMenuLoginsAndPasswordRobot().interact()
@ -784,7 +784,7 @@ private fun aboutFirefoxHeading(): UiObject {
}
}
}
return mDevice.findObject(UiSelector().text("About $appName"))
return itemContainingText("About $appName")
}
fun swipeToBottom() = onView(withId(R.id.recycler_view)).perform(ViewActions.swipeUp())

@ -7,6 +7,7 @@
package org.mozilla.fenix.ui.robots
import android.os.Build
import android.util.Log
import android.widget.TextView
import androidx.core.content.pm.PackageInfoCompat
import androidx.test.espresso.Espresso
@ -29,6 +30,7 @@ import org.hamcrest.CoreMatchers.containsString
import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.Constants.LISTS_MAXSWIPES
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
import org.mozilla.fenix.helpers.TestHelper
@ -47,175 +49,224 @@ import java.util.Date
*/
class SettingsSubMenuAboutRobot {
fun verifyAboutFirefoxPreviewInfo() {
assertVersionNumber()
assertProductCompany()
assertCurrentTimestamp()
verifyVersionNumber()
verifyProductCompany()
verifyCurrentTimestamp()
verifyTheLinksList()
}
class Transition {
fun goBack(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition {
goBackButton().perform(click())
fun verifyVersionNumber() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val packageInfo = context.packageManager.getPackageInfoCompat(context.packageName, 0)
val versionCode = PackageInfoCompat.getLongVersionCode(packageInfo).toString()
val buildNVersion = "${packageInfo.versionName} (Build #$versionCode)\n"
val geckoVersion =
org.mozilla.geckoview.BuildConfig.MOZ_APP_VERSION + "-" + org.mozilla.geckoview.BuildConfig.MOZ_APP_BUILDID
val asVersion = mozilla.components.Build.applicationServicesVersion
Log.i(TAG, "verifyVersionNumber: Trying to verify that the about section contains build version: $buildNVersion")
onView(withId(R.id.about_text)).check(matches(withText(containsString(buildNVersion))))
Log.i(TAG, "verifyVersionNumber: Verified that the about section contains build version: $buildNVersion")
Log.i(TAG, "verifyVersionNumber: Trying to verify that the about section contains gecko version: $geckoVersion")
onView(withId(R.id.about_text)).check(matches(withText(containsString(geckoVersion))))
Log.i(TAG, "verifyVersionNumber: Verified that the about section contains gecko version: $geckoVersion")
Log.i(TAG, "verifyVersionNumber: Trying to verify that the about section contains android services version: $asVersion")
onView(withId(R.id.about_text)).check(matches(withText(containsString(asVersion))))
Log.i(TAG, "verifyVersionNumber: Verified that the about section contains android services version: $asVersion")
}
SettingsRobot().interact()
return SettingsRobot.Transition()
}
fun verifyProductCompany() {
Log.i(TAG, "verifyProductCompany: Trying to verify that the about section contains the company that produced the app info: ${"$appName is produced by Mozilla."}")
onView(withId(R.id.about_content))
.check(matches(withText(containsString("$appName is produced by Mozilla."))))
Log.i(TAG, "verifyProductCompany: Verified that the about section contains the company that produced the app info: \"$appName is produced by Mozilla.\"")
}
}
private fun navigateBackToAboutPage(itemToInteract: () -> Unit) {
navigationToolbar {
}.openThreeDotMenu {
}.openSettings {
}.openAboutFirefoxPreview {
itemToInteract()
fun verifyCurrentTimestamp() {
Log.i(TAG, "verifyCurrentTimestamp: Trying to verify that the about section contains \"debug build\"")
onView(withId(R.id.build_date))
// Currently UI tests run against debug builds, which display a hard-coded string 'debug build'
// instead of the date. See https://github.com/mozilla-mobile/fenix/pull/10812#issuecomment-633746833
.check(matches(withText(containsString("debug build"))))
// This assertion should be valid for non-debug build types.
// .check(BuildDateAssertion.isDisplayedDateAccurate())
Log.i(TAG, "verifyCurrentTimestamp: Verified that the about section contains \"debug build\"")
}
}
private fun verifyTheLinksList() {
assertAboutToolbar()
assertWhatIsNewInFirefoxPreview()
navigateBackToAboutPage(::assertSupport)
assertCrashes()
navigateBackToAboutPage(::assertPrivacyNotice)
navigateBackToAboutPage(::assertKnowYourRights)
navigateBackToAboutPage(::assertLicensingInformation)
navigateBackToAboutPage(::assertLibrariesUsed)
}
fun verifyAboutToolbar() {
Log.i(TAG, "verifyAboutToolbar: Trying to verify that the \"About $appName\" toolbar title is visible")
onView(
allOf(
withId(R.id.navigationToolbar),
hasDescendant(withText("About $appName")),
),
).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
Log.i(TAG, "verifyAboutToolbar: Verified that the \"About $appName\" toolbar title is visible")
}
private fun assertAboutToolbar() =
onView(
allOf(
withId(R.id.navigationToolbar),
hasDescendant(withText("About $appName")),
),
).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
private fun assertVersionNumber() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val packageInfo = context.packageManager.getPackageInfoCompat(context.packageName, 0)
val versionCode = PackageInfoCompat.getLongVersionCode(packageInfo).toString()
val buildNVersion = "${packageInfo.versionName} (Build #$versionCode)\n"
val geckoVersion =
org.mozilla.geckoview.BuildConfig.MOZ_APP_VERSION + "-" + org.mozilla.geckoview.BuildConfig.MOZ_APP_BUILDID
val asVersion = mozilla.components.Build.applicationServicesVersion
onView(withId(R.id.about_text))
.check(matches(withText(containsString(buildNVersion))))
.check(matches(withText(containsString(geckoVersion))))
.check(matches(withText(containsString(asVersion))))
}
fun verifyWhatIsNewInFirefoxLink() {
Log.i(TAG, "verifyWhatIsNewInFirefoxLink: Trying to perform ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
Log.i(TAG, "verifyWhatIsNewInFirefoxLink: Performed ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
val firefox = TestHelper.appContext.getString(R.string.firefox)
Log.i(TAG, "verifyWhatIsNewInFirefoxLink: Trying to verify that the \"Whats new in $firefox\" link is visible")
onView(withText("Whats new in $firefox")).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
Log.i(TAG, "verifyWhatIsNewInFirefoxLink: Verified that the \"Whats new in $firefox\" link is visible")
Log.i(TAG, "verifyWhatIsNewInFirefoxLink: Trying to click the \"Whats new in $firefox\" link")
onView(withText("Whats new in $firefox")).perform(click())
Log.i(TAG, "verifyWhatIsNewInFirefoxLink: Clicked the \"Whats new in $firefox\" link")
}
fun verifySupport() {
Log.i(TAG, "verifySupport: Trying to perform ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
Log.i(TAG, "verifySupport: Performed ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
Log.i(TAG, "verifySupport: Trying to verify that the \"Support\" link is visible")
onView(withText("Support")).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
Log.i(TAG, "verifySupport: Verified that the \"Support\" link is visible")
Log.i(TAG, "verifySupport: Trying to click the \"Support\" link")
onView(withText("Support")).perform(click())
Log.i(TAG, "verifySupport: Clicked the \"Support\" link")
TestHelper.verifyUrl(
"support.mozilla.org",
"org.mozilla.fenix.debug:id/mozac_browser_toolbar_url_view",
R.id.mozac_browser_toolbar_url_view,
)
}
private fun assertProductCompany() {
onView(withId(R.id.about_content))
.check(matches(withText(containsString("$appName is produced by Mozilla."))))
}
fun verifyCrashesLink() {
navigationToolbar {
}.openThreeDotMenu {
}.openSettings {
}.openAboutFirefoxPreview {}
Log.i(TAG, "verifyCrashesLink: Trying to perform ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
Log.i(TAG, "verifyCrashesLink: Performed ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
Log.i(TAG, "verifyCrashesLink: Trying to verify that the \"Crashes\" link is visible")
onView(withText("Crashes")).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
Log.i(TAG, "verifyCrashesLink: Verified that the \"Crashes\" link is visible")
Log.i(TAG, "verifyCrashesLink: Trying to click the \"Crashes\" link")
onView(withText("Crashes")).perform(click())
Log.i(TAG, "verifyCrashesLink: Clicked the \"Crashes\" link")
assertUIObjectExists(itemContainingText("No crash reports have been submitted."))
for (i in 1..3) {
Log.i(TAG, "verifyCrashesLink: Trying to perform press back action")
Espresso.pressBack()
Log.i(TAG, "verifyCrashesLink: Performed press back action")
}
}
private fun assertCurrentTimestamp() {
onView(withId(R.id.build_date))
// Currently UI tests run against debug builds, which display a hard-coded string 'debug build'
// instead of the date. See https://github.com/mozilla-mobile/fenix/pull/10812#issuecomment-633746833
.check(matches(withText(containsString("debug build"))))
// This assertion should be valid for non-debug build types.
// .check(BuildDateAssertion.isDisplayedDateAccurate())
}
fun verifyPrivacyNoticeLink() {
Log.i(TAG, "verifyPrivacyNoticeLink: Trying to perform ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
Log.i(TAG, "verifyPrivacyNoticeLink: Performed ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
Log.i(TAG, "verifyPrivacyNoticeLink: Trying to verify that the \"Privacy notice\" link is visible")
onView(withText("Privacy notice")).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
Log.i(TAG, "verifyPrivacyNoticeLink: Verified that the \"Privacy notice\" link is visible")
Log.i(TAG, "verifyPrivacyNoticeLink: Trying to click the \"Privacy notice\" link")
onView(withText("Privacy notice")).perform(click())
Log.i(TAG, "verifyPrivacyNoticeLink: Clicked the \"Privacy notice\" link")
TestHelper.verifyUrl(
"/privacy/firefox",
"org.mozilla.fenix.debug:id/mozac_browser_toolbar_url_view",
R.id.mozac_browser_toolbar_url_view,
)
}
private fun assertWhatIsNewInFirefoxPreview() {
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
fun verifyKnowYourRightsLink() {
Log.i(TAG, "verifyKnowYourRightsLink: Trying to perform ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
Log.i(TAG, "verifyKnowYourRightsLink: Performed ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
Log.i(TAG, "verifyKnowYourRightsLink: Trying to verify that the \"Know your rights\" link is visible")
onView(withText("Know your rights")).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
Log.i(TAG, "verifyKnowYourRightsLink: Verified that the \"Know your rights\" link is visible")
Log.i(TAG, "verifyKnowYourRightsLink: Trying to click the \"Know your rights\" link")
onView(withText("Know your rights")).perform(click())
Log.i(TAG, "verifyKnowYourRightsLink: Clicked the \"Know your rights\" link")
TestHelper.verifyUrl(
SupportUtils.SumoTopic.YOUR_RIGHTS.topicStr,
"org.mozilla.fenix.debug:id/mozac_browser_toolbar_url_view",
R.id.mozac_browser_toolbar_url_view,
)
}
val firefox = TestHelper.appContext.getString(R.string.firefox)
onView(withText("Whats new in $firefox"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
.perform(click())
}
fun verifyLicensingInformationLink() {
Log.i(TAG, "verifyLicensingInformationLink: Trying to perform ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
Log.i(TAG, "verifyLicensingInformationLink: Performed ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
Log.i(TAG, "verifyLicensingInformationLink: Trying to verify that the \"Licensing information\" link is visible")
onView(withText("Licensing information")).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
Log.i(TAG, "verifyLicensingInformationLink: Verified that the \"Licensing information\" link is visible")
Log.i(TAG, "verifyLicensingInformationLink: Trying to click the \"Licensing information\" link")
onView(withText("Licensing information")).perform(click())
Log.i(TAG, "verifyLicensingInformationLink: Clicked the \"Licensing information\" link")
TestHelper.verifyUrl(
"about:license",
"org.mozilla.fenix.debug:id/mozac_browser_toolbar_url_view",
R.id.mozac_browser_toolbar_url_view,
)
}
private fun assertSupport() {
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
fun verifyLibrariesUsedLink() {
Log.i(TAG, "verifyLibrariesUsedLink: Trying to perform ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
Log.i(TAG, "verifyLibrariesUsedLink: Performed ${LISTS_MAXSWIPES}x a scroll action to the end of the about list")
Log.i(TAG, "verifyLibrariesUsedLink: Trying to verify that the \"Libraries that we use\" link is visible")
onView(withText("Libraries that we use")).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
Log.i(TAG, "verifyLibrariesUsedLink: Verified that the \"Libraries that we use\" link is visible")
Log.i(TAG, "verifyLibrariesUsedLink: Trying to click the \"Libraries that we use\" link")
onView(withText("Libraries that we use")).perform(click())
Log.i(TAG, "verifyLibrariesUsedLink: Clicked the \"Libraries that we use\" link")
Log.i(TAG, "verifyLibrariesUsedLink: Trying to verify that the toolbar has title: \"$appName | OSS Libraries\"")
onView(withId(R.id.navigationToolbar)).check(matches(hasDescendant(withText(containsString("$appName | OSS Libraries")))))
Log.i(TAG, "verifyLibrariesUsedLink: Verified that the toolbar has title: \"$appName | OSS Libraries\"")
Log.i(TAG, "verifyLibrariesUsedLink: Trying to perform press back action")
Espresso.pressBack()
Log.i(TAG, "verifyLibrariesUsedLink: Performed press back action")
}
onView(withText("Support"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
.perform(click())
fun verifyTheLinksList() {
verifyAboutToolbar()
verifyWhatIsNewInFirefoxLink()
navigateBackToAboutPage()
verifySupport()
verifyCrashesLink()
navigateBackToAboutPage()
verifyPrivacyNoticeLink()
navigateBackToAboutPage()
verifyKnowYourRightsLink()
navigateBackToAboutPage()
verifyLicensingInformationLink()
navigateBackToAboutPage()
verifyLibrariesUsedLink()
}
TestHelper.verifyUrl(
"support.mozilla.org",
"org.mozilla.fenix.debug:id/mozac_browser_toolbar_url_view",
R.id.mozac_browser_toolbar_url_view,
)
class Transition {
fun goBack(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition {
Log.i(TAG, "goBack: Trying to click the navigate up button")
goBackButton().perform(click())
Log.i(TAG, "goBack: Clicked the navigate up button")
SettingsRobot().interact()
return SettingsRobot.Transition()
}
}
}
private fun assertCrashes() {
private fun navigateBackToAboutPage() {
navigationToolbar {
}.openThreeDotMenu {
}.openSettings {
}.openAboutFirefoxPreview {}
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
onView(withText("Crashes"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
.perform(click())
assertUIObjectExists(itemContainingText("No crash reports have been submitted."))
for (i in 1..3) {
Espresso.pressBack()
}.openAboutFirefoxPreview {
}
}
private fun assertPrivacyNotice() {
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
onView(withText("Privacy notice"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
.perform(click())
TestHelper.verifyUrl(
"/privacy/firefox",
"org.mozilla.fenix.debug:id/mozac_browser_toolbar_url_view",
R.id.mozac_browser_toolbar_url_view,
)
}
private fun assertKnowYourRights() {
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
onView(withText("Know your rights"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
.perform(click())
TestHelper.verifyUrl(
SupportUtils.SumoTopic.YOUR_RIGHTS.topicStr,
"org.mozilla.fenix.debug:id/mozac_browser_toolbar_url_view",
R.id.mozac_browser_toolbar_url_view,
)
}
private fun assertLicensingInformation() {
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
onView(withText("Licensing information"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
.perform(click())
TestHelper.verifyUrl(
"about:license",
"org.mozilla.fenix.debug:id/mozac_browser_toolbar_url_view",
R.id.mozac_browser_toolbar_url_view,
)
}
private fun assertLibrariesUsed() {
aboutMenuList.scrollToEnd(LISTS_MAXSWIPES)
onView(withText("Libraries that we use"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
.perform(click())
onView(withId(R.id.navigationToolbar)).check(matches(hasDescendant(withText(containsString("$appName | OSS Libraries")))))
Espresso.pressBack()
}
private val aboutMenuList = UiScrollable(UiSelector().resourceId("$packageName:id/about_layout"))
private fun goBackButton() =

@ -36,6 +36,7 @@ import org.mozilla.fenix.helpers.Constants.RETRY_COUNT
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText
import org.mozilla.fenix.helpers.MatcherHelper.itemWithText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeLong
@ -43,7 +44,6 @@ import org.mozilla.fenix.helpers.TestHelper.appName
import org.mozilla.fenix.helpers.TestHelper.mDevice
import org.mozilla.fenix.helpers.TestHelper.packageName
import org.mozilla.fenix.helpers.TestHelper.restartApp
import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText
import org.mozilla.fenix.helpers.click
import org.mozilla.fenix.helpers.ext.waitNotNull
@ -90,15 +90,6 @@ class SettingsSubMenuAddonsManagerRobot {
),
)
Log.i(TAG, "clickInstallAddon: Scrolled into view the install $addonName button")
Log.i(TAG, "clickInstallAddon: Trying to ensure the full visibility of the the install $addonName button")
addonsList().ensureFullyVisible(
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/details_container")
.childSelector(UiSelector().text(addonName)),
),
)
Log.i(TAG, "clickInstallAddon: Ensured the full visibility of the the install $addonName button")
Log.i(TAG, "clickInstallAddon: Trying to click the install $addonName button")
installButtonForAddon(addonName).click()
Log.i(TAG, "clickInstallAddon: Clicked the install $addonName button")
@ -120,7 +111,7 @@ class SettingsSubMenuAddonsManagerRobot {
homeScreen {
}.openThreeDotMenu {
}.openAddonsManagerMenu {
scrollToElementByText(addonName)
scrollToAddon(addonName)
clickInstallAddon(addonName)
verifyAddonPermissionPrompt(addonName)
acceptPermissionToInstallAddon()
@ -152,7 +143,7 @@ class SettingsSubMenuAddonsManagerRobot {
}
fun verifyAddonIsInstalled(addonName: String) {
scrollToElementByText(addonName)
scrollToAddon(addonName)
Log.i(TAG, "verifyAddonIsInstalled: Trying to verify that the $addonName add-on was installed")
onView(
allOf(
@ -199,7 +190,7 @@ class SettingsSubMenuAddonsManagerRobot {
Log.i(TAG, "verifyAddonsItems: Verified that all uBlock Origin items are completely displayed")
}
fun verifyAddonCanBeInstalled(addonName: String) {
scrollToElementByText(addonName)
scrollToAddon(addonName)
mDevice.waitNotNull(Until.findObject(By.text(addonName)), waitingTime)
Log.i(TAG, "verifyAddonCanBeInstalled: Trying to verify that the install $addonName button is visible")
onView(
@ -250,7 +241,7 @@ class SettingsSubMenuAddonsManagerRobot {
addonName: String,
interact: SettingsSubMenuAddonsManagerAddonDetailedMenuRobot.() -> Unit,
): SettingsSubMenuAddonsManagerAddonDetailedMenuRobot.Transition {
scrollToElementByText(addonName)
scrollToAddon(addonName)
Log.i(TAG, "openDetailedMenuForAddon: Trying to verify that the $addonName add-on is visible")
addonItem(addonName).check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
Log.i(TAG, "openDetailedMenuForAddon: Verified that the $addonName add-on is visible")
@ -297,6 +288,17 @@ fun addonsMenu(interact: SettingsSubMenuAddonsManagerRobot.() -> Unit): Settings
return SettingsSubMenuAddonsManagerRobot.Transition()
}
private fun scrollToAddon(addonName: String) {
Log.i(TAG, "scrollToAddon: Trying to scroll into view add-on: $addonName")
addonsList().scrollIntoView(
itemWithResIdContainingText(
resourceId = "$packageName:id/add_on_name",
text = addonName,
),
)
Log.i(TAG, "scrollToAddon: Scrolled into view add-on: $addonName")
}
private fun addonItem(addonName: String) =
onView(
allOf(

@ -5,6 +5,7 @@
package org.mozilla.fenix.ui.robots
import android.util.Log
import androidx.test.espresso.Espresso.closeSoftKeyboard
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.RootMatchers
@ -36,11 +37,10 @@ import org.mozilla.fenix.helpers.click
class SettingsSubMenuAutofillRobot {
fun verifyAutofillToolbarTitle() {
assertUIObjectExists(autofillToolbarTitle)
Log.i(TAG, "verifyAutofillToolbarTitle: Verified \"Autofill\" toolbar title exists")
assertUIObjectExists(autofillToolbarTitle())
}
fun verifyManageAddressesToolbarTitle() {
Log.i(TAG, "verifyManageAddressesToolbarTitle: Trying to verify the \"Manage addresses\" toolbar title is displayed")
Log.i(TAG, "verifyManageAddressesToolbarTitle: Trying to verify that the \"Manage addresses\" toolbar title is displayed")
onView(
allOf(
withId(R.id.navigationToolbar),
@ -49,21 +49,21 @@ class SettingsSubMenuAutofillRobot {
),
),
).check(matches(isDisplayed()))
Log.i(TAG, "verifyManageAddressesToolbarTitle: Verified the \"Manage addresses\" toolbar title is displayed")
Log.i(TAG, "verifyManageAddressesToolbarTitle: Verified that the \"Manage addresses\" toolbar title is displayed")
}
fun verifyAddressAutofillSection(isAddressAutofillEnabled: Boolean, userHasSavedAddress: Boolean) {
assertUIObjectExists(
autofillToolbarTitle,
addressesSectionTitle,
saveAndAutofillAddressesOption,
saveAndAutofillAddressesSummary,
autofillToolbarTitle(),
addressesSectionTitle(),
saveAndAutofillAddressesOption(),
saveAndAutofillAddressesSummary(),
)
if (userHasSavedAddress) {
assertUIObjectExists(manageAddressesButton)
assertUIObjectExists(manageAddressesButton())
} else {
assertUIObjectExists(addAddressButton)
assertUIObjectExists(addAddressButton())
}
verifyAddressesAutofillToggle(isAddressAutofillEnabled)
@ -71,18 +71,18 @@ class SettingsSubMenuAutofillRobot {
fun verifyCreditCardsAutofillSection(isAddressAutofillEnabled: Boolean, userHasSavedCreditCard: Boolean) {
assertUIObjectExists(
autofillToolbarTitle,
creditCardsSectionTitle,
saveAndAutofillCreditCardsOption,
saveAndAutofillCreditCardsSummary,
syncCreditCardsAcrossDevicesButton,
autofillToolbarTitle(),
creditCardsSectionTitle(),
saveAndAutofillCreditCardsOption(),
saveAndAutofillCreditCardsSummary(),
syncCreditCardsAcrossDevicesButton(),
)
if (userHasSavedCreditCard) {
assertUIObjectExists(manageSavedCreditCardsButton)
assertUIObjectExists(manageSavedCreditCardsButton())
} else {
assertUIObjectExists(addCreditCardButton)
assertUIObjectExists(addCreditCardButton())
}
verifySaveAndAutofillCreditCardsToggle(isAddressAutofillEnabled)
@ -90,28 +90,28 @@ class SettingsSubMenuAutofillRobot {
fun verifyManageAddressesSection(vararg savedAddressDetails: String) {
assertUIObjectExists(
navigateBackButton,
manageAddressesToolbarTitle,
addAddressButton,
navigateBackButton(),
manageAddressesToolbarTitle(),
addAddressButton(),
)
for (savedAddressDetail in savedAddressDetails) {
assertUIObjectExists(itemContainingText(savedAddressDetail))
Log.i(TAG, "verifyManageAddressesSection: Verified saved address detail: $savedAddressDetail exists")
}
}
fun verifySavedCreditCardsSection(creditCardLastDigits: String, creditCardExpiryDate: String) {
assertUIObjectExists(
navigateBackButton,
savedCreditCardsToolbarTitle,
addCreditCardButton,
navigateBackButton(),
savedCreditCardsToolbarTitle(),
addCreditCardButton(),
itemContainingText(creditCardLastDigits),
itemContainingText(creditCardExpiryDate),
)
}
fun verifyAddressesAutofillToggle(enabled: Boolean) {
onView(withText(R.string.preferences_addresses_save_and_autofill_addresses))
Log.i(TAG, "verifyAddressesAutofillToggle: Trying to verify that the \"Save and autofill addresses\" toggle is checked: $enabled")
onView(withText(R.string.preferences_addresses_save_and_autofill_addresses_2))
.check(
matches(
hasCousin(
@ -126,11 +126,12 @@ class SettingsSubMenuAutofillRobot {
),
),
)
Log.i(TAG, "verifyAddressesAutofillToggle: Verified if address autofill toggle is enabled: $enabled")
Log.i(TAG, "verifyAddressesAutofillToggle: Verified that the \"Save and autofill addresses\" toggle is checked: $enabled")
}
fun verifySaveAndAutofillCreditCardsToggle(enabled: Boolean) =
onView(withText(R.string.preferences_credit_cards_save_and_autofill_cards))
fun verifySaveAndAutofillCreditCardsToggle(enabled: Boolean) {
Log.i(TAG, "verifySaveAndAutofillCreditCardsToggle: Trying to verify that the \"Save and autofill cards\" toggle is checked: $enabled")
onView(withText(R.string.preferences_credit_cards_save_and_autofill_cards_2))
.check(
matches(
hasCousin(
@ -145,46 +146,41 @@ class SettingsSubMenuAutofillRobot {
),
),
)
Log.i(TAG, "verifySaveAndAutofillCreditCardsToggle: Verified that the \"Save and autofill cards\" toggle is checked: $enabled")
}
fun verifyAddAddressView() {
Log.i(TAG, "verifyAddAddressView: Trying to perform \"Close soft keyboard\" action")
// Closing the keyboard to ensure full visibility of the "Add address" view
closeSoftKeyboard()
Log.i(TAG, "verifyAddAddressView: Performed \"Close soft keyboard\" action")
assertUIObjectExists(
addAddressToolbarTitle,
navigateBackButton,
toolbarCheckmarkButton,
firstNameTextInput,
middleNameTextInput,
)
scrollToElementByText(getStringResource(R.string.addresses_street_address))
Log.i(TAG, "verifyAddAddressView: Scrolled to \"Street Address\" text input")
assertUIObjectExists(
lastNameTextInput,
streetAddressTextInput,
addAddressToolbarTitle(),
navigateBackButton(),
toolbarCheckmarkButton(),
nameTextInput(),
streetAddressTextInput(),
cityTextInput(),
subRegionDropDown(),
)
scrollToElementByText(getStringResource(R.string.addresses_country))
Log.i(TAG, "verifyAddAddressView: Scrolled to \"Country or region\" dropdown")
assertUIObjectExists(
cityTextInput,
subRegionDropDown,
zipCodeTextInput,
zipCodeTextInput(),
countryDropDown(),
phoneTextInput(),
emailTextInput(),
)
scrollToElementByText(getStringResource(R.string.addresses_save_button))
Log.i(TAG, "verifyAddAddressView: Scrolled to \"Save\" button")
assertUIObjectExists(
countryDropDown,
phoneTextInput,
emailTextInput,
)
assertUIObjectExists(
saveButton,
cancelButton,
saveButton(),
cancelButton(),
)
}
fun verifyCountryOption(country: String) {
scrollToElementByText(getStringResource(R.string.addresses_country))
Log.i(TAG, "verifyCountryOption: Scrolled to \"Country or region\" dropdown")
mDevice.pressBack()
Log.i(TAG, "fillAndSaveAddress: Dismissed \"Country or region\" dropdown using device back button")
Log.i(TAG, "verifyCountryOption: Trying to perform \"Close soft keyboard\" action")
// Closing the keyboard to ensure full visibility of the "Add address" view
closeSoftKeyboard()
Log.i(TAG, "verifyCountryOption: Performed \"Close soft keyboard\" action")
assertUIObjectExists(itemContainingText(country))
}
@ -193,116 +189,115 @@ class SettingsSubMenuAutofillRobot {
}
fun verifyCountryOptions(vararg countries: String) {
countryDropDown.click()
Log.i(TAG, "verifyCountryOptions: Clicked \"Country or region\" dropdown")
Log.i(TAG, "verifyCountryOptions: Trying to click the \"Country or region\" dropdown")
countryDropDown().click()
Log.i(TAG, "verifyCountryOptions: Clicked the \"Country or region\" dropdown")
for (country in countries) {
assertUIObjectExists(itemContainingText(country))
}
}
fun selectCountry(country: String) {
countryDropDown.click()
Log.i(TAG, "selectCountry: Clicked \"Country or region\" dropdown")
Log.i(TAG, "selectCountry: Trying to click the \"Country or region\" dropdown")
countryDropDown().click()
Log.i(TAG, "selectCountry: Clicked the \"Country or region\" dropdown")
Log.i(TAG, "selectCountry: Trying to select $country dropdown option")
countryOption(country).click()
Log.i(TAG, "selectCountry: Selected $country dropdown option")
}
fun verifyEditAddressView() {
assertUIObjectExists(
editAddressToolbarTitle,
navigateBackButton,
toolbarDeleteAddressButton,
toolbarCheckmarkButton,
firstNameTextInput,
middleNameTextInput,
)
scrollToElementByText(getStringResource(R.string.addresses_street_address))
Log.i(TAG, "verifyEditAddressView: Scrolled to \"Street Address\" text input")
assertUIObjectExists(
lastNameTextInput,
streetAddressTextInput,
editAddressToolbarTitle(),
navigateBackButton(),
toolbarDeleteAddressButton(),
toolbarCheckmarkButton(),
nameTextInput(),
streetAddressTextInput(),
cityTextInput(),
subRegionDropDown(),
)
scrollToElementByText(getStringResource(R.string.addresses_country))
Log.i(TAG, "verifyEditAddressView: Scrolled to \"Country or region\" dropdown")
assertUIObjectExists(
cityTextInput,
subRegionDropDown,
zipCodeTextInput,
zipCodeTextInput(),
countryDropDown(),
phoneTextInput(),
emailTextInput(),
)
scrollToElementByText(getStringResource(R.string.addresses_save_button))
Log.i(TAG, "verifyEditAddressView: Scrolled to \"Save\" button")
assertUIObjectExists(
countryDropDown,
phoneTextInput,
emailTextInput,
saveButton(),
cancelButton(),
)
assertUIObjectExists(
saveButton,
cancelButton,
)
assertUIObjectExists(deleteAddressButton)
assertUIObjectExists(deleteAddressButton())
}
fun clickSaveAndAutofillAddressesOption() {
saveAndAutofillAddressesOption.click()
Log.i(TAG, "clickSaveAndAutofillAddressesOption: Clicked \"Save and autofill addresses\" button")
Log.i(TAG, "clickSaveAndAutofillAddressesOption: Trying to click the \"Save and fill addresses\" button")
saveAndAutofillAddressesOption().click()
Log.i(TAG, "clickSaveAndAutofillAddressesOption: Clicked the \"Save and fill addresses\" button")
}
fun clickAddAddressButton() {
addAddressButton.click()
Log.i(TAG, "clickAddAddressButton: Clicked \"Add address\" button")
Log.i(TAG, "clickAddAddressButton: Trying to click the \"Add address\" button")
addAddressButton().click()
Log.i(TAG, "clickAddAddressButton: Clicked the \"Add address\" button")
}
fun clickManageAddressesButton() {
manageAddressesButton.click()
Log.i(TAG, "clickManageAddressesButton: Clicked \"Manage addresses\" button")
Log.i(TAG, "clickManageAddressesButton: Trying to click the \"Manage addresses\" button")
manageAddressesButton().click()
Log.i(TAG, "clickManageAddressesButton: Clicked the \"Manage addresses\" button")
}
fun clickSavedAddress(firstName: String) {
savedAddress(firstName).clickAndWaitForNewWindow(waitingTime)
Log.i(TAG, "clickSavedAddress: Clicked $firstName saved address and waiting for a new window for $waitingTime")
fun clickSavedAddress(name: String) {
Log.i(TAG, "clickSavedAddress: Trying to click the $name saved address and and wait for $waitingTime ms for a new window")
savedAddress(name).clickAndWaitForNewWindow(waitingTime)
Log.i(TAG, "clickSavedAddress: Clicked the $name saved address and and waited for $waitingTime ms for a new window")
}
fun clickDeleteAddressButton() {
Log.i(TAG, "clickDeleteAddressButton: Looking for delete address toolbar button")
toolbarDeleteAddressButton.waitForExists(waitingTime)
toolbarDeleteAddressButton.click()
Log.i(TAG, "clickDeleteAddressButton: Clicked delete address toolbar button")
Log.i(TAG, "clickDeleteAddressButton: Waiting for $waitingTime ms for the delete address toolbar button to exist")
toolbarDeleteAddressButton().waitForExists(waitingTime)
Log.i(TAG, "clickDeleteAddressButton: Waited for $waitingTime ms for the delete address toolbar button to exist")
Log.i(TAG, "clickDeleteAddressButton: Trying to click the delete address toolbar button")
toolbarDeleteAddressButton().click()
Log.i(TAG, "clickDeleteAddressButton: Clicked the delete address toolbar button")
}
fun clickCancelDeleteAddressButton() {
cancelDeleteAddressButton.click()
Log.i(TAG, "clickCancelDeleteAddressButton: Clicked \"CANCEL\" button from delete address dialog")
Log.i(TAG, "clickCancelDeleteAddressButton: Trying to click the \"CANCEL\" button from the delete address dialog")
cancelDeleteAddressButton().click()
Log.i(TAG, "clickCancelDeleteAddressButton: Clicked the \"CANCEL\" button from the delete address dialog")
}
fun clickConfirmDeleteAddressButton() {
confirmDeleteAddressButton.click()
Log.i(TAG, "clickConfirmDeleteAddressButton: Clicked \"DELETE\" button from delete address dialog")
Log.i(TAG, "clickConfirmDeleteAddressButton: Trying to click the \"DELETE\" button from the delete address dialog")
confirmDeleteAddressButton().click()
Log.i(TAG, "clickConfirmDeleteAddressButton: Clicked \"DELETE\" button from the delete address dialog")
}
fun clickSubRegionOption(subRegion: String) {
scrollToElementByText(subRegion)
Log.i(TAG, "clickSubRegionOption: Scrolled to \"State\" drop down")
subRegionOption(subRegion).also {
Log.i(TAG, "clickSubRegionOption: Looking for \"State\" $subRegion dropdown option")
Log.i(TAG, "clickSubRegionOption: Waiting for $waitingTime ms for the \"State\" $subRegion dropdown option to exist")
it.waitForExists(waitingTime)
Log.i(TAG, "clickSubRegionOption: Waited for $waitingTime ms for the \"State\" $subRegion dropdown option to exist")
Log.i(TAG, "clickSubRegionOption: Trying to click the \"State\" $subRegion dropdown option")
it.click()
Log.i(TAG, "clickSubRegionOption: Clicked \"State\" $subRegion dropdown option")
Log.i(TAG, "clickSubRegionOption: Clicked the \"State\" $subRegion dropdown option")
}
}
fun clickCountryOption(country: String) {
Log.i(TAG, "clickCountryOption: Looking for \"Country or region\" $country dropdown option")
Log.i(TAG, "clickCountryOption: Waiting for $waitingTime ms for the \"Country or region\" $country dropdown option to exist")
countryOption(country).waitForExists(waitingTime)
Log.i(TAG, "clickCountryOption: Waited for $waitingTime ms for the \"Country or region\" $country dropdown option to exist")
Log.i(TAG, "clickCountryOption: Trying to click \"Country or region\" $country dropdown option")
countryOption(country).click()
Log.i(TAG, "clickCountryOption: Clicked \"Country or region\" $country dropdown option")
}
fun verifyAddAddressButton() {
assertUIObjectExists(addAddressButton)
Log.i(TAG, "verifyAddAddressButton: Verified \"Add address\" button exists")
}
fun verifyAddAddressButton() = assertUIObjectExists(addAddressButton())
fun fillAndSaveAddress(
navigateToAutofillSettings: Boolean,
isAddressAutofillEnabled: Boolean = true,
userHasSavedAddress: Boolean = false,
firstName: String,
middleName: String,
lastName: String,
name: String,
streetAddress: String,
city: String,
state: String,
@ -320,98 +315,180 @@ class SettingsSubMenuAutofillRobot {
clickAddAddressButton()
}
}
Log.i(TAG, "fillAndSaveAddress: Looking for \"First Name\" text input")
firstNameTextInput.waitForExists(waitingTime)
Log.i(TAG, "fillAndSaveAddress: Waiting for $waitingTime ms for \"Name\" text field to exist")
nameTextInput().waitForExists(waitingTime)
Log.i(TAG, "fillAndSaveAddress: Waited for $waitingTime ms for \"Name\" text field to exist")
Log.i(TAG, "fillAndSaveAddress: Trying to click device back button to dismiss keyboard using device back button")
mDevice.pressBack()
Log.i(TAG, "fillAndSaveAddress: Dismissed keyboard using device back button")
firstNameTextInput.setText(firstName)
Log.i(TAG, "fillAndSaveAddress: \"First Name\" set to $firstName")
middleNameTextInput.setText(middleName)
Log.i(TAG, "fillAndSaveAddress: \"Middle Name\" set to $middleName")
lastNameTextInput.setText(lastName)
Log.i(TAG, "fillAndSaveAddress: \"Last Name\" set to $lastName")
streetAddressTextInput.setText(streetAddress)
Log.i(TAG, "fillAndSaveAddress: \"Street Address\" set to $streetAddress")
cityTextInput.setText(city)
Log.i(TAG, "fillAndSaveAddress: \"City\" set to $city")
subRegionDropDown.click()
Log.i(TAG, "fillAndSaveAddress: Clicked device back button to dismiss keyboard using device back button")
Log.i(TAG, "fillAndSaveAddress: Trying to set \"Name\" to $name")
nameTextInput().setText(name)
Log.i(TAG, "fillAndSaveAddress: \"Name\" was set to $name")
Log.i(TAG, "fillAndSaveAddress: Trying to set \"Street Address\" to $streetAddress")
streetAddressTextInput().setText(streetAddress)
Log.i(TAG, "fillAndSaveAddress: \"Street Address\" was set to $streetAddress")
Log.i(TAG, "fillAndSaveAddress: Trying to set \"City\" to $city")
cityTextInput().setText(city)
Log.i(TAG, "fillAndSaveAddress: \"City\" was set to $city")
Log.i(TAG, "fillAndSaveAddress: Trying to click \"State\" dropdown button")
subRegionDropDown().click()
Log.i(TAG, "fillAndSaveAddress: Clicked \"State\" dropdown button")
Log.i(TAG, "fillAndSaveAddress: Trying to click the $state dropdown option")
clickSubRegionOption(state)
Log.i(TAG, "fillAndSaveAddress: Selected $state as \"State\"")
zipCodeTextInput.setText(zipCode)
Log.i(TAG, "fillAndSaveAddress: \"Zip\" set to $zipCode")
countryDropDown.click()
Log.i(TAG, "fillAndSaveAddress: Clicked $state dropdown option")
Log.i(TAG, "fillAndSaveAddress: Trying to set \"Zip\" to $zipCode")
zipCodeTextInput().setText(zipCode)
Log.i(TAG, "fillAndSaveAddress: \"Zip\" was set to $zipCode")
Log.i(TAG, "fillAndSaveAddress: Trying to click \"Country or region\" dropdown button")
countryDropDown().click()
Log.i(TAG, "fillAndSaveAddress: Clicked \"Country or region\" dropdown button")
Log.i(TAG, "fillAndSaveAddress: Trying to click $country dropdown option")
clickCountryOption(country)
Log.i(TAG, "fillAndSaveAddress: Selected $country as \"Country or region\"")
Log.i(TAG, "fillAndSaveAddress: Clicked $country dropdown option")
scrollToElementByText(getStringResource(R.string.addresses_save_button))
Log.i(TAG, "fillAndSaveAddress: Scrolled to \"Save\" button")
phoneTextInput.setText(phoneNumber)
Log.i(TAG, "fillAndSaveAddress: \"Phone\" set to $phoneNumber")
emailTextInput.setText(emailAddress)
Log.i(TAG, "fillAndSaveAddress: \"Email\" set to $emailAddress")
saveButton.click()
Log.i(TAG, "fillAndSaveAddress: Clicked \"Save\" button")
Log.i(TAG, "fillAndSaveAddress: Looking for \"Manage addressese\" button")
manageAddressesButton.waitForExists(waitingTime)
}
fun clickAddCreditCardButton() = addCreditCardButton.click()
fun clickManageSavedCreditCardsButton() = manageSavedCreditCardsButton.click()
fun clickSecuredCreditCardsLaterButton() = securedCreditCardsLaterButton.click()
fun clickSavedCreditCard() = savedCreditCardNumber.clickAndWaitForNewWindow(waitingTime)
Log.i(TAG, "fillAndSaveAddress: Trying to set \"Phone\" to $phoneNumber")
phoneTextInput().setText(phoneNumber)
Log.i(TAG, "fillAndSaveAddress: \"Phone\" was set to $phoneNumber")
Log.i(TAG, "fillAndSaveAddress: Trying to set \"Email\" to $emailAddress")
emailTextInput().setText(emailAddress)
Log.i(TAG, "fillAndSaveAddress: \"Email\" was set to $emailAddress")
Log.i(TAG, "fillAndSaveAddress: Trying to click the \"Save\" button")
saveButton().click()
Log.i(TAG, "fillAndSaveAddress: Clicked the \"Save\" button")
Log.i(TAG, "fillAndSaveAddress: Waiting for $waitingTime ms for for \"Manage addresses\" button to exist")
manageAddressesButton().waitForExists(waitingTime)
Log.i(TAG, "fillAndSaveAddress: Waited for $waitingTime ms for for \"Manage addresses\" button to exist")
}
fun clickAddCreditCardButton() {
Log.i(TAG, "clickAddCreditCardButton: Trying to click the \"Add credit card\" button")
addCreditCardButton().click()
Log.i(TAG, "clickAddCreditCardButton: Clicked the \"Add credit card\" button")
}
fun clickManageSavedCreditCardsButton() {
Log.i(TAG, "clickManageSavedCreditCardsButton: Trying to click the \"Manage saved cards\" button")
manageSavedCreditCardsButton().click()
Log.i(TAG, "clickManageSavedCreditCardsButton: Clicked the \"Manage saved cards\" button")
}
fun clickSecuredCreditCardsLaterButton() {
Log.i(TAG, "clickSecuredCreditCardsLaterButton: Trying to click the \"Later\" button")
securedCreditCardsLaterButton().click()
Log.i(TAG, "clickSecuredCreditCardsLaterButton: Clicked the \"Later\" button")
}
fun clickSavedCreditCard() {
Log.i(TAG, "clickSavedCreditCard: Trying to click the saved credit card and and wait for $waitingTime ms for a new window")
savedCreditCardNumber().clickAndWaitForNewWindow(waitingTime)
Log.i(TAG, "clickSavedCreditCard: Clicked the saved credit card and and waited for $waitingTime ms for a new window")
}
fun clickDeleteCreditCardToolbarButton() {
deleteCreditCardToolbarButton.waitForExists(waitingTime)
deleteCreditCardToolbarButton.click()
Log.i(TAG, "clickDeleteCreditCardToolbarButton: Waiting for $waitingTime ms for the delete credit card toolbar button to exist")
deleteCreditCardToolbarButton().waitForExists(waitingTime)
Log.i(TAG, "clickDeleteCreditCardToolbarButton: Waited for $waitingTime ms for the delete credit card toolbar button to exist")
Log.i(TAG, "clickDeleteCreditCardToolbarButton: Trying to click the delete credit card toolbar button")
deleteCreditCardToolbarButton().click()
Log.i(TAG, "clickDeleteCreditCardToolbarButton: Clicked the delete credit card toolbar button")
}
fun clickDeleteCreditCardMenuButton() {
deleteCreditCardMenuButton.waitForExists(waitingTime)
deleteCreditCardMenuButton.click()
Log.i(TAG, "clickDeleteCreditCardMenuButton: Waiting for $waitingTime ms for the delete credit card menu button to exist")
deleteCreditCardMenuButton().waitForExists(waitingTime)
Log.i(TAG, "clickDeleteCreditCardMenuButton: Waited for $waitingTime ms for the delete credit card menu button to exist")
Log.i(TAG, "clickDeleteCreditCardMenuButton: Trying to click the delete credit card menu button")
deleteCreditCardMenuButton().click()
Log.i(TAG, "clickDeleteCreditCardMenuButton: Clicked the delete credit card menu button")
}
fun clickSaveAndAutofillCreditCardsOption() {
Log.i(TAG, "clickSaveAndAutofillCreditCardsOption: Trying to click the \"Save and autofill cards\" option")
saveAndAutofillCreditCardsOption().click()
Log.i(TAG, "clickSaveAndAutofillCreditCardsOption: Clicked the \"Save and autofill cards\" option")
}
fun clickSaveAndAutofillCreditCardsOption() = saveAndAutofillCreditCardsOption.click()
fun clickConfirmDeleteCreditCardButton() = confirmDeleteCreditCardButton.click()
fun clickConfirmDeleteCreditCardButton() {
Log.i(TAG, "clickConfirmDeleteCreditCardButton: Trying to click the \"Delete\" credit card dialog button")
confirmDeleteCreditCardButton().click()
Log.i(TAG, "clickConfirmDeleteCreditCardButton: Clicked the \"Delete\" credit card dialog button")
}
fun clickCancelDeleteCreditCardButton() = cancelDeleteCreditCardButton.click()
fun clickCancelDeleteCreditCardButton() {
Log.i(TAG, "clickCancelDeleteCreditCardButton: Trying to click the \"Cancel\" credit card dialog button")
cancelDeleteCreditCardButton().click()
Log.i(TAG, "clickCancelDeleteCreditCardButton: Clicked the \"Cancel\" credit card dialog button")
}
fun clickExpiryMonthOption(expiryMonth: String) {
Log.i(TAG, "clickExpiryMonthOption: Waiting for $waitingTime ms for the $expiryMonth expiry month option to exist")
expiryMonthOption(expiryMonth).waitForExists(waitingTime)
Log.i(TAG, "clickExpiryMonthOption: Waited for $waitingTime ms for the $expiryMonth expiry month option to exist")
Log.i(TAG, "clickExpiryMonthOption: Trying to click $expiryMonth expiry month option")
expiryMonthOption(expiryMonth).click()
Log.i(TAG, "clickExpiryMonthOption: Clicked $expiryMonth expiry month option")
}
fun clickExpiryYearOption(expiryYear: String) {
Log.i(TAG, "clickExpiryYearOption: Waiting for $waitingTime ms for the $expiryYear expiry year option to exist")
expiryYearOption(expiryYear).waitForExists(waitingTime)
Log.i(TAG, "clickExpiryYearOption: Waited for $waitingTime ms for the $expiryYear expiry year option to exist")
Log.i(TAG, "clickExpiryYearOption: Trying to click $expiryYear expiry year option")
expiryYearOption(expiryYear).click()
Log.i(TAG, "clickExpiryYearOption: Clicked $expiryYear expiry year option")
}
fun verifyAddCreditCardsButton() = assertUIObjectExists(addCreditCardButton)
fun verifyAddCreditCardsButton() = assertUIObjectExists(addCreditCardButton())
fun fillAndSaveCreditCard(cardNumber: String, cardName: String, expiryMonth: String, expiryYear: String) {
creditCardNumberTextInput.waitForExists(waitingTime)
creditCardNumberTextInput.setText(cardNumber)
nameOnCreditCardTextInput.setText(cardName)
expiryMonthDropDown.click()
Log.i(TAG, "fillAndSaveCreditCard: Waiting for $waitingTime ms for the credit card number text field to exist")
creditCardNumberTextInput().waitForExists(waitingTime)
Log.i(TAG, "fillAndSaveCreditCard: Waited for $waitingTime ms for the credit card number text field to exist")
Log.i(TAG, "fillAndSaveCreditCard: Trying to set the credit card number to: $cardNumber")
creditCardNumberTextInput().setText(cardNumber)
Log.i(TAG, "fillAndSaveCreditCard: The credit card number was set to: $cardNumber")
Log.i(TAG, "fillAndSaveCreditCard: Trying to set the name on card to: $cardName")
nameOnCreditCardTextInput().setText(cardName)
Log.i(TAG, "fillAndSaveCreditCard: The credit card name was set to: $cardName")
Log.i(TAG, "fillAndSaveCreditCard: Trying to click the expiry month dropdown")
expiryMonthDropDown().click()
Log.i(TAG, "fillAndSaveCreditCard: Clicked the expiry month dropdown")
Log.i(TAG, "fillAndSaveCreditCard: Trying to click $expiryMonth expiry month option")
clickExpiryMonthOption(expiryMonth)
expiryYearDropDown.click()
Log.i(TAG, "fillAndSaveCreditCard: Clicked $expiryMonth expiry month option")
Log.i(TAG, "fillAndSaveCreditCard: Trying to click the expiry year dropdown")
expiryYearDropDown().click()
Log.i(TAG, "fillAndSaveCreditCard: Clicked the expiry year dropdown")
Log.i(TAG, "fillAndSaveCreditCard: Trying to click $expiryYear expiry year option")
clickExpiryYearOption(expiryYear)
saveButton.click()
manageSavedCreditCardsButton.waitForExists(waitingTime)
Log.i(TAG, "fillAndSaveCreditCard: Clicked $expiryYear expiry year option")
Log.i(TAG, "fillAndSaveCreditCard: Trying to click the \"Save\" button")
saveButton().click()
Log.i(TAG, "fillAndSaveCreditCard: Clicked the \"Save\" button")
Log.i(TAG, "fillAndSaveCreditCard: Waiting for $waitingTime ms for the \"Manage saved cards\" button to exist")
manageSavedCreditCardsButton().waitForExists(waitingTime)
Log.i(TAG, "fillAndSaveCreditCard: Waited for $waitingTime ms for the \"Manage saved cards\" button to exist")
}
fun clearCreditCardNumber() =
creditCardNumberTextInput.also {
creditCardNumberTextInput().also {
Log.i(TAG, "clearCreditCardNumber: Waiting for $waitingTime ms for the credit card number text field to exist")
it.waitForExists(waitingTime)
Log.i(TAG, "clearCreditCardNumber: Waited for $waitingTime ms for the credit card number text field to exist")
Log.i(TAG, "clearCreditCardNumber: Trying to clear the credit card number text field")
it.clearTextField()
Log.i(TAG, "clearCreditCardNumber: Cleared the credit card number text field")
}
fun clearNameOnCreditCard() =
nameOnCreditCardTextInput.also {
nameOnCreditCardTextInput().also {
Log.i(TAG, "clearNameOnCreditCard: Waiting for $waitingTime ms for name on card text field to exist")
it.waitForExists(waitingTime)
Log.i(TAG, "clearNameOnCreditCard: Waited for $waitingTime ms for name on card text field to exist")
Log.i(TAG, "clearNameOnCreditCard: Trying to clear the name on card text field")
it.clearTextField()
Log.i(TAG, "clearNameOnCreditCard: Cleared the name on card text field")
}
fun clickSaveCreditCardToolbarButton() = saveCreditCardToolbarButton.click()
fun clickSaveCreditCardToolbarButton() {
Log.i(TAG, "clickSaveCreditCardToolbarButton: Trying to click the save credit card toolbar button")
saveCreditCardToolbarButton().click()
Log.i(TAG, "clickSaveCreditCardToolbarButton: Clicked the save credit card toolbar button")
}
fun verifyEditCreditCardView(
cardNumber: String,
@ -420,19 +497,22 @@ class SettingsSubMenuAutofillRobot {
expiryYear: String,
) {
assertUIObjectExists(
editCreditCardToolbarTitle,
navigateBackButton,
deleteCreditCardToolbarButton,
saveCreditCardToolbarButton,
editCreditCardToolbarTitle(),
navigateBackButton(),
deleteCreditCardToolbarButton(),
saveCreditCardToolbarButton(),
)
assertEquals(cardNumber, creditCardNumberTextInput.text)
assertEquals(cardName, nameOnCreditCardTextInput.text)
Log.i(TAG, "verifyEditCreditCardView: Trying to verify that the card number text field is set to: $cardNumber")
assertEquals(cardNumber, creditCardNumberTextInput().text)
Log.i(TAG, "verifyEditCreditCardView: Verified that the card number text field was set to: $cardNumber")
Log.i(TAG, "verifyEditCreditCardView: Trying to verify that the card name text field is set to: $cardName")
assertEquals(cardName, nameOnCreditCardTextInput().text)
Log.i(TAG, "verifyEditCreditCardView: Verified that the card card name text field was set to: $cardName")
// Can't get the text from the drop-down items, need to verify them individually
assertUIObjectExists(
expiryYearDropDown,
expiryMonthDropDown,
expiryYearDropDown(),
expiryMonthDropDown(),
)
assertUIObjectExists(
@ -441,47 +521,53 @@ class SettingsSubMenuAutofillRobot {
)
assertUIObjectExists(
saveButton,
cancelButton,
saveButton(),
cancelButton(),
)
assertUIObjectExists(deleteCreditCardMenuButton)
assertUIObjectExists(deleteCreditCardMenuButton())
}
fun verifyEditCreditCardToolbarTitle() = assertUIObjectExists(editCreditCardToolbarTitle)
fun verifyEditCreditCardToolbarTitle() = assertUIObjectExists(editCreditCardToolbarTitle())
fun verifyCreditCardNumberErrorMessage() =
assertUIObjectExists(itemContainingText(getStringResource(R.string.credit_cards_number_validation_error_message)))
assertUIObjectExists(itemContainingText(getStringResource(R.string.credit_cards_number_validation_error_message_2)))
fun verifyNameOnCreditCardErrorMessage() =
assertUIObjectExists(itemContainingText(getStringResource(R.string.credit_cards_name_on_card_validation_error_message)))
assertUIObjectExists(itemContainingText(getStringResource(R.string.credit_cards_name_on_card_validation_error_message_2)))
class Transition {
fun goBack(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition {
Log.i(TAG, "goBack: Trying to click the device back button")
mDevice.pressBack()
Log.i(TAG, "goBack: Clicked the device back button")
SettingsRobot().interact()
return SettingsRobot.Transition()
}
fun goBackToAutofillSettings(interact: SettingsSubMenuAutofillRobot.() -> Unit): SettingsSubMenuAutofillRobot.Transition {
navigateBackButton.click()
Log.i(TAG, "goBackToAutofillSettings: Clicked \"Navigate back\" toolbar button")
Log.i(TAG, "goBackToAutofillSettings: Trying to click the navigate up toolbar button")
navigateBackButton().click()
Log.i(TAG, "goBackToAutofillSettings: Clicked the navigate up toolbar button")
SettingsSubMenuAutofillRobot().interact()
return SettingsSubMenuAutofillRobot.Transition()
}
fun goBackToSavedCreditCards(interact: SettingsSubMenuAutofillRobot.() -> Unit): SettingsSubMenuAutofillRobot.Transition {
navigateBackButton.click()
Log.i(TAG, "goBackToSavedCreditCards: Trying to click the navigate up toolbar button")
navigateBackButton().click()
Log.i(TAG, "goBackToSavedCreditCards: Clicked the navigate up toolbar button")
SettingsSubMenuAutofillRobot().interact()
return SettingsSubMenuAutofillRobot.Transition()
}
fun goBackToBrowser(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
Log.i(TAG, "goBackToBrowser: Trying to click the device back button")
mDevice.pressBack()
Log.i(TAG, "goBackToBrowser: Go back to browser view using device back button")
Log.i(TAG, "goBackToBrowser: Clicked the device back button")
BrowserRobot().interact()
return BrowserRobot.Transition()
@ -494,66 +580,65 @@ fun autofillScreen(interact: SettingsSubMenuAutofillRobot.() -> Unit): SettingsS
return SettingsSubMenuAutofillRobot.Transition()
}
private val autofillToolbarTitle = itemContainingText(getStringResource(R.string.preferences_autofill))
private val addressesSectionTitle = itemContainingText(getStringResource(R.string.preferences_addresses))
private val manageAddressesToolbarTitle =
private fun autofillToolbarTitle() = itemContainingText(getStringResource(R.string.preferences_autofill))
private fun addressesSectionTitle() = itemContainingText(getStringResource(R.string.preferences_addresses))
private fun manageAddressesToolbarTitle() =
mDevice.findObject(
UiSelector()
.resourceId("$packageName:id/navigationToolbar")
.childSelector(UiSelector().text(getStringResource(R.string.addresses_manage_addresses))),
)
private val saveAndAutofillAddressesOption = itemContainingText(getStringResource(R.string.preferences_addresses_save_and_autofill_addresses))
private val saveAndAutofillAddressesSummary = itemContainingText(getStringResource(R.string.preferences_addresses_save_and_autofill_addresses_summary))
private val addAddressButton = itemContainingText(getStringResource(R.string.preferences_addresses_add_address))
private val manageAddressesButton =
private fun saveAndAutofillAddressesOption() = itemContainingText(getStringResource(R.string.preferences_addresses_save_and_autofill_addresses_2))
private fun saveAndAutofillAddressesSummary() = itemContainingText(getStringResource(R.string.preferences_addresses_save_and_autofill_addresses_summary_2))
private fun addAddressButton() = itemContainingText(getStringResource(R.string.preferences_addresses_add_address))
private fun manageAddressesButton() =
mDevice.findObject(
UiSelector()
.resourceId("android:id/title")
.text(getStringResource(R.string.preferences_addresses_manage_addresses)),
)
private val addAddressToolbarTitle = itemContainingText(getStringResource(R.string.addresses_add_address))
private val editAddressToolbarTitle = itemContainingText(getStringResource(R.string.addresses_edit_address))
private val toolbarCheckmarkButton = itemWithResId("$packageName:id/save_address_button")
private val navigateBackButton = itemWithDescription(getStringResource(R.string.action_bar_up_description))
private val firstNameTextInput = itemWithResId("$packageName:id/first_name_input")
private val middleNameTextInput = itemWithResId("$packageName:id/middle_name_input")
private val lastNameTextInput = itemWithResId("$packageName:id/last_name_input")
private val streetAddressTextInput = itemWithResId("$packageName:id/street_address_input")
private val cityTextInput = itemWithResId("$packageName:id/city_input")
private val subRegionDropDown = itemWithResId("$packageName:id/subregion_drop_down")
private val zipCodeTextInput = itemWithResId("$packageName:id/zip_input")
private val countryDropDown = itemWithResId("$packageName:id/country_drop_down")
private val phoneTextInput = itemWithResId("$packageName:id/phone_input")
private val emailTextInput = itemWithResId("$packageName:id/email_input")
private val saveButton = itemWithResId("$packageName:id/save_button")
private val cancelButton = itemWithResId("$packageName:id/cancel_button")
private val deleteAddressButton = itemContainingText(getStringResource(R.string.addressess_delete_address_button))
private val toolbarDeleteAddressButton = itemWithResId("$packageName:id/delete_address_button")
private val cancelDeleteAddressButton = onView(withId(android.R.id.button2)).inRoot(RootMatchers.isDialog())
private val confirmDeleteAddressButton = onView(withId(android.R.id.button1)).inRoot(RootMatchers.isDialog())
private val creditCardsSectionTitle = itemContainingText(getStringResource(R.string.preferences_credit_cards))
private val saveAndAutofillCreditCardsOption = itemContainingText(getStringResource(R.string.preferences_credit_cards_save_and_autofill_cards))
private val saveAndAutofillCreditCardsSummary = itemContainingText(getStringResource(R.string.preferences_credit_cards_save_and_autofill_cards_summary))
private val syncCreditCardsAcrossDevicesButton = itemContainingText(getStringResource(R.string.preferences_credit_cards_sync_cards_across_devices))
private val addCreditCardButton = mDevice.findObject(UiSelector().textContains(getStringResource(R.string.preferences_credit_cards_add_credit_card)))
private val savedCreditCardsToolbarTitle = itemContainingText(getStringResource(R.string.credit_cards_saved_cards))
private val editCreditCardToolbarTitle = itemContainingText(getStringResource(R.string.credit_cards_edit_card))
private val manageSavedCreditCardsButton = mDevice.findObject(UiSelector().textContains(getStringResource(R.string.preferences_credit_cards_manage_saved_cards)))
private val creditCardNumberTextInput = mDevice.findObject(UiSelector().resourceId("$packageName:id/card_number_input"))
private val nameOnCreditCardTextInput = mDevice.findObject(UiSelector().resourceId("$packageName:id/name_on_card_input"))
private val expiryMonthDropDown = mDevice.findObject(UiSelector().resourceId("$packageName:id/expiry_month_drop_down"))
private val expiryYearDropDown = mDevice.findObject(UiSelector().resourceId("$packageName:id/expiry_year_drop_down"))
private val savedCreditCardNumber = mDevice.findObject(UiSelector().resourceId("$packageName:id/credit_card_logo"))
private val deleteCreditCardToolbarButton = mDevice.findObject(UiSelector().resourceId("$packageName:id/delete_credit_card_button"))
private val saveCreditCardToolbarButton = itemWithResId("$packageName:id/save_credit_card_button")
private val deleteCreditCardMenuButton = itemContainingText(getStringResource(R.string.credit_cards_delete_card_button))
private val confirmDeleteCreditCardButton = onView(withId(android.R.id.button1)).inRoot(RootMatchers.isDialog())
private val cancelDeleteCreditCardButton = onView(withId(android.R.id.button2)).inRoot(RootMatchers.isDialog())
private val securedCreditCardsLaterButton = onView(withId(android.R.id.button2)).inRoot(RootMatchers.isDialog())
private fun savedAddress(firstName: String) = mDevice.findObject(UiSelector().textContains(firstName))
private fun addAddressToolbarTitle() = itemContainingText(getStringResource(R.string.addresses_add_address))
private fun editAddressToolbarTitle() = itemContainingText(getStringResource(R.string.addresses_edit_address))
private fun toolbarCheckmarkButton() = itemWithResId("$packageName:id/save_address_button")
private fun navigateBackButton() = itemWithDescription(getStringResource(R.string.action_bar_up_description))
private fun nameTextInput() = itemWithResId("$packageName:id/name_input")
private fun streetAddressTextInput() = itemWithResId("$packageName:id/street_address_input")
private fun cityTextInput() = itemWithResId("$packageName:id/city_input")
private fun subRegionDropDown() = itemWithResId("$packageName:id/subregion_drop_down")
private fun zipCodeTextInput() = itemWithResId("$packageName:id/zip_input")
private fun countryDropDown() = itemWithResId("$packageName:id/country_drop_down")
private fun phoneTextInput() = itemWithResId("$packageName:id/phone_input")
private fun emailTextInput() = itemWithResId("$packageName:id/email_input")
private fun saveButton() = itemWithResId("$packageName:id/save_button")
private fun cancelButton() = itemWithResId("$packageName:id/cancel_button")
private fun deleteAddressButton() = itemContainingText(getStringResource(R.string.addressess_delete_address_button))
private fun toolbarDeleteAddressButton() = itemWithResId("$packageName:id/delete_address_button")
private fun cancelDeleteAddressButton() = onView(withId(android.R.id.button2)).inRoot(RootMatchers.isDialog())
private fun confirmDeleteAddressButton() = onView(withId(android.R.id.button1)).inRoot(RootMatchers.isDialog())
private fun creditCardsSectionTitle() = itemContainingText(getStringResource(R.string.preferences_credit_cards_2))
private fun saveAndAutofillCreditCardsOption() = itemContainingText(getStringResource(R.string.preferences_credit_cards_save_and_autofill_cards_2))
private fun saveAndAutofillCreditCardsSummary() = itemContainingText(getStringResource(R.string.preferences_credit_cards_save_and_autofill_cards_summary_2))
private fun syncCreditCardsAcrossDevicesButton() = itemContainingText(getStringResource(R.string.preferences_credit_cards_sync_cards_across_devices))
private fun addCreditCardButton() = mDevice.findObject(UiSelector().textContains(getStringResource(R.string.preferences_credit_cards_add_credit_card_2)))
private fun savedCreditCardsToolbarTitle() = itemContainingText(getStringResource(R.string.credit_cards_saved_cards))
private fun editCreditCardToolbarTitle() = itemContainingText(getStringResource(R.string.credit_cards_edit_card))
private fun manageSavedCreditCardsButton() = mDevice.findObject(UiSelector().textContains(getStringResource(R.string.preferences_credit_cards_manage_saved_cards_2)))
private fun creditCardNumberTextInput() = mDevice.findObject(UiSelector().resourceId("$packageName:id/card_number_input"))
private fun nameOnCreditCardTextInput() = mDevice.findObject(UiSelector().resourceId("$packageName:id/name_on_card_input"))
private fun expiryMonthDropDown() = mDevice.findObject(UiSelector().resourceId("$packageName:id/expiry_month_drop_down"))
private fun expiryYearDropDown() = mDevice.findObject(UiSelector().resourceId("$packageName:id/expiry_year_drop_down"))
private fun savedCreditCardNumber() = mDevice.findObject(UiSelector().resourceId("$packageName:id/credit_card_logo"))
private fun deleteCreditCardToolbarButton() = mDevice.findObject(UiSelector().resourceId("$packageName:id/delete_credit_card_button"))
private fun saveCreditCardToolbarButton() = itemWithResId("$packageName:id/save_credit_card_button")
private fun deleteCreditCardMenuButton() = itemContainingText(getStringResource(R.string.credit_cards_delete_card_button))
private fun confirmDeleteCreditCardButton() = onView(withId(android.R.id.button1)).inRoot(RootMatchers.isDialog())
private fun cancelDeleteCreditCardButton() = onView(withId(android.R.id.button2)).inRoot(RootMatchers.isDialog())
private fun securedCreditCardsLaterButton() = onView(withId(android.R.id.button2)).inRoot(RootMatchers.isDialog())
private fun savedAddress(name: String) = mDevice.findObject(UiSelector().textContains(name))
private fun subRegionOption(subRegion: String) = mDevice.findObject(UiSelector().textContains(subRegion))
private fun countryOption(country: String) = mDevice.findObject(UiSelector().textContains(country))

@ -7,9 +7,10 @@
package org.mozilla.fenix.ui.robots
import android.os.Build
import android.util.Log
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.ViewInteraction
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.hasSibling
@ -21,6 +22,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withText
import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.Matchers.endsWith
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
import org.mozilla.fenix.helpers.TestHelper.hasCousin
import org.mozilla.fenix.helpers.TestHelper.mDevice
@ -31,27 +33,67 @@ import org.mozilla.fenix.helpers.click
*/
class SettingsSubMenuCustomizeRobot {
fun verifyThemes() = assertThemes()
fun verifyThemes() {
Log.i(TAG, "verifyThemes: Trying to verify that the \"Light\" mode option is visible")
lightModeToggle()
.check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
Log.i(TAG, "verifyThemes: Verified that the \"Light\" mode option is visible")
Log.i(TAG, "verifyThemes: Trying to verify that the \"Dark\" mode option is visible")
darkModeToggle()
.check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
Log.i(TAG, "verifyThemes: Verified that the \"Dark\" mode option is visible")
Log.i(TAG, "verifyThemes: Trying to verify that the \"Follow device theme\" option is visible")
deviceModeToggle()
.check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
Log.i(TAG, "verifyThemes: Verified that the \"Follow device theme\" option is visible")
}
fun selectDarkMode() = darkModeToggle().click()
fun selectDarkMode() {
Log.i(TAG, "selectDarkMode: Trying to click the \"Dark\" mode option")
darkModeToggle().click()
Log.i(TAG, "selectDarkMode: Clicked the \"Dark\" mode option")
}
fun selectLightMode() = lightModeToggle().click()
fun selectLightMode() {
Log.i(TAG, "selectLightMode: Trying to click the \"Light\" mode option")
lightModeToggle().click()
Log.i(TAG, "selectLightMode: Clicked the \"Light\" mode option")
}
fun clickTopToolbarToggle() = topToolbarToggle().click()
fun clickTopToolbarToggle() {
Log.i(TAG, "clickTopToolbarToggle: Trying to click the \"Top\" toolbar option")
topToolbarToggle().click()
Log.i(TAG, "clickTopToolbarToggle: Clicked the \"Top\" toolbar option")
}
fun clickBottomToolbarToggle() = bottomToolbarToggle().click()
fun clickBottomToolbarToggle() {
Log.i(TAG, "clickBottomToolbarToggle: Trying to click the \"Bottom\" toolbar option")
bottomToolbarToggle().click()
Log.i(TAG, "clickBottomToolbarToggle: Clicked the \"Bottom\" toolbar option")
}
fun verifyToolbarPositionPreference(selectedPosition: String) {
Log.i(TAG, "verifyToolbarPositionPreference: Trying to verify that the $selectedPosition toolbar option is checked")
onView(withText(selectedPosition))
.check(matches(hasSibling(allOf(withId(R.id.radio_button), isChecked()))))
Log.i(TAG, "verifyToolbarPositionPreference: Verified that the $selectedPosition toolbar option is checked")
}
fun clickSwipeToolbarToSwitchTabToggle() = swipeToolbarToggle.click()
fun clickSwipeToolbarToSwitchTabToggle() {
Log.i(TAG, "clickSwipeToolbarToSwitchTabToggle: Trying to click the \"Swipe toolbar sideways to switch tabs\" toggle")
swipeToolbarToggle().click()
Log.i(TAG, "clickSwipeToolbarToSwitchTabToggle: Clicked the \"Swipe toolbar sideways to switch tabs\" toggle")
}
fun clickPullToRefreshToggle() = pullToRefreshToggle.click()
fun clickPullToRefreshToggle() {
Log.i(TAG, "clickPullToRefreshToggle: Trying to click the \"Pull to refresh\" toggle")
pullToRefreshToggle().click()
Log.i(TAG, "clickPullToRefreshToggle: Clicked the \"Pull to refresh\" toggle")
}
fun verifySwipeToolbarGesturePrefState(isEnabled: Boolean) {
swipeToolbarToggle
Log.i(TAG, "verifySwipeToolbarGesturePrefState: Trying to verify that the \"Swipe toolbar sideways to switch tabs\" toggle is checked: $isEnabled")
swipeToolbarToggle()
.check(
matches(
hasCousin(
@ -66,10 +108,12 @@ class SettingsSubMenuCustomizeRobot {
),
),
)
Log.i(TAG, "verifySwipeToolbarGesturePrefState: Verified that the \"Swipe toolbar sideways to switch tabs\" toggle is checked: $isEnabled")
}
fun verifyPullToRefreshGesturePrefState(isEnabled: Boolean) {
pullToRefreshToggle
Log.i(TAG, "verifyPullToRefreshGesturePrefState: Trying to verify that the \"Pull to refresh\" toggle is checked: $isEnabled")
pullToRefreshToggle()
.check(
matches(
hasCousin(
@ -84,12 +128,17 @@ class SettingsSubMenuCustomizeRobot {
),
),
)
Log.i(TAG, "verifyPullToRefreshGesturePrefState: Verified that the \"Pull to refresh\" toggle is checked: $isEnabled")
}
class Transition {
fun goBack(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition {
Log.i(TAG, "goBack: Waiting for device to be idle")
mDevice.waitForIdle()
goBackButton().perform(ViewActions.click())
Log.i(TAG, "goBack: Waited for device to be idle")
Log.i(TAG, "goBack: Trying to click the navigate up toolbar button")
goBackButton().perform(click())
Log.i(TAG, "goBack: Clicked the navigate up toolbar button")
SettingsRobot().interact()
return SettingsRobot.Transition()
@ -97,15 +146,6 @@ class SettingsSubMenuCustomizeRobot {
}
}
private fun assertThemes() {
lightModeToggle()
.check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
darkModeToggle()
.check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
deviceModeToggle()
.check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
}
private fun darkModeToggle() = onView(withText("Dark"))
private fun lightModeToggle() = onView(withText("Light"))
@ -120,10 +160,10 @@ private fun deviceModeToggle(): ViewInteraction {
return onView(withText(followDeviceThemeText))
}
private val swipeToolbarToggle =
private fun swipeToolbarToggle() =
onView(withText(getStringResource(R.string.preference_gestures_swipe_toolbar_switch_tabs)))
private val pullToRefreshToggle =
private fun pullToRefreshToggle() =
onView(withText(getStringResource(R.string.preference_gestures_website_pull_to_refresh)))
private fun goBackButton() =

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

Loading…
Cancel
Save