commit b573255586efdfe56eb2d92ac20c107f34620a29 parent 6553440ace3ab9b90455eda769b4df80d8188855 Author: agoloman <agoloman@mozilla.com> Date: Tue, 9 Dec 2025 19:48:13 +0200 Revert "Bug 2004910 - Enable composable logins in UI tests r=avirvara,aaronmt" for failing legacy-arm in Fenix login tests. This reverts commit e85f232074024db458759d51f8357a74fc9cfe33. Diffstat:
9 files changed, 313 insertions(+), 400 deletions(-)
diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/FeatureSettingsHelper.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/FeatureSettingsHelper.kt @@ -117,6 +117,11 @@ interface FeatureSettingsHelper { var isTermsOfServiceAccepted: Boolean /** + * Enable or disable the composable logins. + */ + var isComposeLoginsEnabled: Boolean + + /** * The Open links in External apps settings, between the following options: * - Ask before opening * - Never diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/FeatureSettingsHelperDelegate.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/FeatureSettingsHelperDelegate.kt @@ -48,6 +48,7 @@ class FeatureSettingsHelperDelegate : FeatureSettingsHelper { isUseNewCrashReporterDialog = settings.useNewCrashReporterDialog, isTabSwipeCFREnabled = settings.hasShownTabSwipeCFR, isTermsOfServiceAccepted = settings.hasAcceptedTermsOfService, + isComposeLoginsEnabled = settings.enableComposeLogins, openLinksInApp = getOpenLinksInApp(settings), tabManagerOpeningAnimationEnabled = settings.tabManagerOpeningAnimationEnabled, hasSeenBrowserToolbarCFR = settings.hasSeenBrowserToolbarCFR, @@ -77,6 +78,7 @@ class FeatureSettingsHelperDelegate : FeatureSettingsHelper { override var isUseNewCrashReporterDialog: Boolean by updatedFeatureFlags::isUseNewCrashReporterDialog override var isTabSwipeCFREnabled: Boolean by updatedFeatureFlags::isTabSwipeCFREnabled override var isTermsOfServiceAccepted: Boolean by updatedFeatureFlags::isTermsOfServiceAccepted + override var isComposeLoginsEnabled: Boolean by updatedFeatureFlags::isComposeLoginsEnabled override var openLinksInExternalApp: OpenLinksInApp by updatedFeatureFlags::openLinksInApp override var tabManagerOpeningAnimationEnabled: Boolean by updatedFeatureFlags::tabManagerOpeningAnimationEnabled override var hasSeenBrowserToolbarCFR: Boolean by updatedFeatureFlags::hasSeenBrowserToolbarCFR @@ -116,6 +118,7 @@ class FeatureSettingsHelperDelegate : FeatureSettingsHelper { settings.useNewCrashReporterDialog = featureFlags.isUseNewCrashReporterDialog settings.hasShownTabSwipeCFR = !featureFlags.isTabSwipeCFREnabled settings.hasAcceptedTermsOfService = featureFlags.isTermsOfServiceAccepted + settings.enableComposeLogins = featureFlags.isComposeLoginsEnabled setOpenLinksInApp(featureFlags.openLinksInApp) settings.tabManagerOpeningAnimationEnabled = featureFlags.tabManagerOpeningAnimationEnabled settings.hasSeenBrowserToolbarCFR = featureFlags.hasSeenBrowserToolbarCFR @@ -143,6 +146,7 @@ private data class FeatureFlags( var isUseNewCrashReporterDialog: Boolean, var isTabSwipeCFREnabled: Boolean, var isTermsOfServiceAccepted: Boolean, + var isComposeLoginsEnabled: Boolean, var openLinksInApp: OpenLinksInApp, var tabManagerOpeningAnimationEnabled: Boolean, var hasSeenBrowserToolbarCFR: Boolean, diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt @@ -71,6 +71,7 @@ class HomeActivityTestRule( isUseNewCrashReporterDialog: Boolean = false, isTabSwipeCFREnabled: Boolean = false, isTermsOfServiceAccepted: Boolean = true, + isComposeLoginsEnabled: Boolean = false, openLinksInExternalApp: OpenLinksInApp = getOpenLinksInApp(settings), hasSeenBrowserToolbarCFR: Boolean = true, ) : this(initialTouchMode, launchActivity, skipOnboarding) { @@ -94,6 +95,7 @@ class HomeActivityTestRule( this.isUseNewCrashReporterDialog = isUseNewCrashReporterDialog this.isTabSwipeCFREnabled = isTabSwipeCFREnabled this.isTermsOfServiceAccepted = isTermsOfServiceAccepted + this.isComposeLoginsEnabled = isComposeLoginsEnabled this.openLinksInExternalApp = openLinksInExternalApp this.hasSeenBrowserToolbarCFR = hasSeenBrowserToolbarCFR } @@ -160,6 +162,7 @@ class HomeActivityTestRule( isUseNewCrashReporterDialog = useNewCrashReporterDialog, isTabSwipeCFREnabled = true, isTermsOfServiceAccepted = true, + isComposeLoginsEnabled = false, ) } } @@ -205,6 +208,7 @@ class HomeActivityIntentTestRule internal constructor( onboardingFeatureEnabled: Boolean = true, isTabSwipeCFREnabled: Boolean = false, isTermsOfServiceAccepted: Boolean = true, + isComposeLoginsEnabled: Boolean = false, openLinksInExternalApp: OpenLinksInApp = getOpenLinksInApp(settings), tabManagerOpeningAnimationEnabled: Boolean = false, hasSeenBrowserToolbarCFR: Boolean = true, @@ -229,6 +233,7 @@ class HomeActivityIntentTestRule internal constructor( this.onboardingFeatureEnabled = onboardingFeatureEnabled this.isTabSwipeCFREnabled = isTabSwipeCFREnabled this.isTermsOfServiceAccepted = isTermsOfServiceAccepted + this.isComposeLoginsEnabled = isComposeLoginsEnabled this.openLinksInExternalApp = openLinksInExternalApp this.tabManagerOpeningAnimationEnabled = tabManagerOpeningAnimationEnabled this.hasSeenBrowserToolbarCFR = hasSeenBrowserToolbarCFR @@ -305,6 +310,7 @@ class HomeActivityIntentTestRule internal constructor( shouldUseBottomToolbar = settings.shouldUseBottomToolbar isTabSwipeCFREnabled = !settings.hasShownTabSwipeCFR isTermsOfServiceAccepted = settings.hasAcceptedTermsOfService + isComposeLoginsEnabled = settings.enableComposeLogins openLinksInExternalApp = getOpenLinksInApp(settings) tabManagerOpeningAnimationEnabled = settings.tabManagerOpeningAnimationEnabled hasSeenBrowserToolbarCFR = settings.hasSeenBrowserToolbarCFR @@ -338,6 +344,7 @@ class HomeActivityIntentTestRule internal constructor( isPageLoadTranslationsPromptEnabled = false, isTabSwipeCFREnabled = true, isTermsOfServiceAccepted = true, + isComposeLoginsEnabled = false, tabManagerOpeningAnimationEnabled = false, ) } diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/syncintegration/SyncIntegrationTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/syncintegration/SyncIntegrationTest.kt @@ -132,7 +132,7 @@ class SyncIntegrationTest { tapSetupLater() // Check the logins synced verifySavedLoginsAfterSync() - }.goBack(activityTestRule) { + }.goBack { // After checking the synced logins // on Logins and Passwords menu the Sync passwords option is set to On verifyDefaultViewAfterSync() diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/LoginsTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/LoginsTest.kt @@ -43,7 +43,7 @@ import org.mozilla.fenix.ui.robots.setPageObjectText */ class LoginsTest : TestSetup() { @get:Rule - val composeTestRule = + val activityTestRule = AndroidComposeTestRule( HomeActivityIntentTestRule.withDefaultSettingsOverrides(), ) { it.activity } @@ -93,7 +93,7 @@ class LoginsTest : TestSetup() { verifySecurityPromptForLogins() tapSetupLater() // Verify that logins list is empty - verifyEmptySavedLoginsListView(composeTestRule) + verifyEmptySavedLoginsListView() } } @@ -172,8 +172,8 @@ class LoginsTest : TestSetup() { }.openSavedLogins { verifySecurityPromptForLogins() tapSetupLater() - viewSavedLoginDetails(composeTestRule, userName) - }.goToSavedWebsite(composeTestRule) { + viewSavedLoginDetails(userName) + }.goToSavedWebsite { verifyUrl(originWebsite) } } @@ -197,9 +197,9 @@ class LoginsTest : TestSetup() { verifySecurityPromptForLogins() tapSetupLater() // Verify that the login list is empty - verifyEmptySavedLoginsListView(composeTestRule) - verifyNotSavedLoginFromPrompt(composeTestRule) - }.goBack(composeTestRule) { + verifyEmptySavedLoginsListView() + verifyNotSavedLoginFromPrompt() + }.goBack { }.openLoginExceptions { // Verify localhost was added to exceptions list verifyLocalhostExceptionAdded() @@ -236,9 +236,9 @@ class LoginsTest : TestSetup() { tapSetupLater() // Verify that the login appears correctly verifySavedLoginsSectionUsername("test@example.com") - viewSavedLoginDetails(composeTestRule, "test@example.com") - revealPassword(composeTestRule) - verifyPasswordSaved(composeTestRule, "test") + viewSavedLoginDetails("test@example.com") + revealPassword() + verifyPasswordSaved("test") // failing here locally } } @@ -274,11 +274,11 @@ class LoginsTest : TestSetup() { }.enterURLAndEnterToBrowser(loginPage.toUri()) { clickPageObject(itemWithResId("username")) clickSuggestedLoginsButton() - verifySuggestedUserName(composeTestRule, firstUser) - verifySuggestedUserName(composeTestRule, secondUser) - clickSuggestedLogin(composeTestRule, firstUser) + verifySuggestedUserName(activityTestRule, firstUser) + verifySuggestedUserName(activityTestRule, secondUser) + clickSuggestedLogin(activityTestRule, firstUser) clickPageObject(itemWithResId("togglePassword")) - verifyPrefilledLoginCredentials(composeTestRule, firstUser, firstPass, true) + verifyPrefilledLoginCredentials(activityTestRule, firstUser, firstPass, true) } } @@ -287,7 +287,7 @@ class LoginsTest : TestSetup() { @SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1935209"]) fun verifyEditLoginsViewTest() { val loginPage = "https://mozilla-mobile.github.io/testapp/loginForm" - val originWebsite = "https://mozilla-mobile.github.io" + val originWebsite = "mozilla-mobile.github.io" navigationToolbar { }.enterURLAndEnterToBrowser(loginPage.toUri()) { @@ -304,14 +304,13 @@ class LoginsTest : TestSetup() { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { tapSetupLater() - viewSavedLoginDetails(composeTestRule, originWebsite) - clickThreeDotButton(composeTestRule) - clickEditLoginButton(composeTestRule) - setNewPasswordWhileEditingALogin(composeTestRule, "fenix") - saveEditedLogin(composeTestRule) - clickThreeDotButton(composeTestRule) - clickEditLoginButton(composeTestRule) - verifyPasswordWhileEditingALogin(composeTestRule, "fenix") + viewSavedLoginDetails(originWebsite) + clickThreeDotButton(activityTestRule.activityRule) + clickEditLoginButton() + setNewPassword("fenix") + saveEditedLogin() + revealPassword() + verifyPasswordSaved("fenix") } } @@ -319,7 +318,7 @@ class LoginsTest : TestSetup() { @Test fun verifyEditedLoginsAreSavedTest() { val loginPage = "https://mozilla-mobile.github.io/testapp/v2.0/loginForm.html" - val originWebsite = "https://mozilla-mobile.github.io" + val originWebsite = "mozilla-mobile.github.io" navigationToolbar { }.enterURLAndEnterToBrowser(loginPage.toUri()) { @@ -337,14 +336,12 @@ class LoginsTest : TestSetup() { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { tapSetupLater() - viewSavedLoginDetails(composeTestRule, originWebsite) - clickThreeDotButton(composeTestRule) - clickEditLoginButton(composeTestRule) - setNewUserNameWhileEditingALogin(composeTestRule, "android") - setNewPasswordWhileEditingALogin(composeTestRule, "fenix") - saveEditedLogin(composeTestRule) - clickGoBackButton(composeTestRule) - }.goBack(composeTestRule) { + viewSavedLoginDetails(originWebsite) + clickThreeDotButton(activityTestRule.activityRule) + clickEditLoginButton() + setNewUserName("android") + setNewPassword("fenix") + saveEditedLogin() } exitMenu() @@ -354,7 +351,7 @@ class LoginsTest : TestSetup() { }.refreshPage { waitForPageToLoad(pageLoadWaitingTime = waitingTimeLong) clickPageObject(itemWithResId("togglePassword")) - verifyPrefilledLoginCredentials(composeTestRule, "android", "fenix", true) + verifyPrefilledLoginCredentials(activityTestRule, "android", "fenix", true) } } @@ -363,7 +360,7 @@ class LoginsTest : TestSetup() { @SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1935209"]) fun verifyLoginWithNoUserNameCanNotBeSavedTest() { val loginPage = "https://mozilla-mobile.github.io/testapp/loginForm" - val originWebsite = "https://mozilla-mobile.github.io" + val originWebsite = "mozilla-mobile.github.io" navigationToolbar { }.enterURLAndEnterToBrowser(loginPage.toUri()) { @@ -380,14 +377,14 @@ class LoginsTest : TestSetup() { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { tapSetupLater() - viewSavedLoginDetails(composeTestRule, originWebsite) - clickThreeDotButton(composeTestRule) - clickEditLoginButton(composeTestRule) - clickClearUserNameButton(composeTestRule) - verifyUserNameRequiredErrorMessage(composeTestRule) - verifySaveLoginButtonIsEnabled(composeTestRule, false) - clickGoBackButton(composeTestRule) - verifyLoginItemUsername(composeTestRule, "mozilla") + viewSavedLoginDetails(originWebsite) + clickThreeDotButton(activityTestRule.activityRule) + clickEditLoginButton() + clickClearUserNameButton() + verifyUserNameRequiredErrorMessage() + verifySaveLoginButtonIsEnabled(false) + clickGoBackButton() + verifyLoginItemUsername("mozilla") } } @@ -396,7 +393,7 @@ class LoginsTest : TestSetup() { @SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1935209"]) fun verifyLoginWithoutPasswordCanNotBeSavedTest() { val loginPage = "https://mozilla-mobile.github.io/testapp/loginForm" - val originWebsite = "https://mozilla-mobile.github.io" + val originWebsite = "mozilla-mobile.github.io" navigationToolbar { }.enterURLAndEnterToBrowser(loginPage.toUri()) { @@ -413,15 +410,15 @@ class LoginsTest : TestSetup() { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { tapSetupLater() - viewSavedLoginDetails(composeTestRule, originWebsite) - clickThreeDotButton(composeTestRule) - clickEditLoginButton(composeTestRule) - clickClearPasswordButton(composeTestRule) - verifyPasswordRequiredErrorMessage(composeTestRule) - verifySaveLoginButtonIsEnabled(composeTestRule, false) - clickGoBackButton(composeTestRule) - revealPassword(composeTestRule) - verifyPasswordSaved(composeTestRule, "firefox") + viewSavedLoginDetails(originWebsite) + clickThreeDotButton(activityTestRule.activityRule) + clickEditLoginButton() + clickClearPasswordButton() + verifyPasswordRequiredErrorMessage() + verifySaveLoginButtonIsEnabled(false) + clickGoBackButton() + revealPassword() + verifyPasswordSaved("firefox") } } @@ -430,7 +427,7 @@ class LoginsTest : TestSetup() { @SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1935209"]) fun verifyEditModeDismissalDoesNotSaveLoginCredentialsTest() { val loginPage = "https://mozilla-mobile.github.io/testapp/loginForm" - val originWebsite = "https://mozilla-mobile.github.io" + val originWebsite = "mozilla-mobile.github.io" navigationToolbar { }.enterURLAndEnterToBrowser(loginPage.toUri()) { @@ -447,15 +444,15 @@ class LoginsTest : TestSetup() { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { tapSetupLater() - viewSavedLoginDetails(composeTestRule, originWebsite) - clickThreeDotButton(composeTestRule) - clickEditLoginButton(composeTestRule) - setNewUserNameWhileEditingALogin(composeTestRule, "android") - setNewPasswordWhileEditingALogin(composeTestRule, "fenix") - clickGoBackButton(composeTestRule) - verifyLoginItemUsername(composeTestRule, "mozilla") - revealPassword(composeTestRule) - verifyPasswordSaved(composeTestRule, "firefox") + viewSavedLoginDetails(originWebsite) + clickThreeDotButton(activityTestRule.activityRule) + clickEditLoginButton() + setNewUserName("android") + setNewPassword("fenix") + clickGoBackButton() + verifyLoginItemUsername("mozilla") + revealPassword() + verifyPasswordSaved("firefox") } } @@ -474,17 +471,17 @@ class LoginsTest : TestSetup() { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { tapSetupLater() - viewSavedLoginDetails(composeTestRule, "test@example.com") - clickThreeDotButton(composeTestRule) - clickDeleteLoginButton(composeTestRule) - verifyLoginDeletionPrompt(composeTestRule) - clickCancelDeleteLogin(composeTestRule) - verifyLoginItemUsername(composeTestRule, "test@example.com") - viewSavedLoginDetails(composeTestRule, "test@example.com") - clickThreeDotButton(composeTestRule) - clickDeleteLoginButton(composeTestRule) - verifyLoginDeletionPrompt(composeTestRule) - clickConfirmDeleteLogin(composeTestRule) + viewSavedLoginDetails("test@example.com") + clickThreeDotButton(activityTestRule.activityRule) + clickDeleteLoginButton() + verifyLoginDeletionPrompt() + clickCancelDeleteLogin() + verifyLoginItemUsername("test@example.com") + viewSavedLoginDetails("test@example.com") + clickThreeDotButton(activityTestRule.activityRule) + clickDeleteLoginButton() + verifyLoginDeletionPrompt() + clickConfirmDeleteLogin() // The account remains displayed, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1812431 // verifyNotSavedLoginFromPrompt() } @@ -532,7 +529,7 @@ class LoginsTest : TestSetup() { waitForPageToLoad(pageLoadWaitingTime = waitingTimeLong) verifySaveLoginPromptIsDisplayed() clickPageObject(itemWithText("Save")) - }.openTabDrawer(composeTestRule) { + }.openTabDrawer(activityTestRule) { closeTab() } @@ -540,8 +537,8 @@ class LoginsTest : TestSetup() { }.enterURLAndEnterToBrowser(loginPage.toUri()) { waitForPageToLoad(pageLoadWaitingTime = waitingTimeLong) clickPageObject(itemWithResId("togglePassword")) - verifyPrefilledLoginCredentials(composeTestRule, "mozilla", "firefox", true) - }.openTabDrawer(composeTestRule) { + verifyPrefilledLoginCredentials(activityTestRule, "mozilla", "firefox", true) + }.openTabDrawer(activityTestRule) { closeTab() } @@ -559,7 +556,7 @@ class LoginsTest : TestSetup() { navigationToolbar { }.enterURLAndEnterToBrowser(loginPage.toUri()) { - verifyPrefilledLoginCredentials(composeTestRule, "mozilla", "firefox", false) + verifyPrefilledLoginCredentials(activityTestRule, "mozilla", "firefox", false) } } @@ -568,7 +565,7 @@ class LoginsTest : TestSetup() { @SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1935209"]) fun doNotSaveOptionWillNotUpdateALoginTest() { val loginPage = "https://mozilla-mobile.github.io/testapp/v2.0/loginForm.html" - val originWebsite = "https://mozilla-mobile.github.io" + val originWebsite = "mozilla-mobile.github.io" navigationToolbar { }.enterURLAndEnterToBrowser(loginPage.toUri()) { @@ -593,9 +590,9 @@ class LoginsTest : TestSetup() { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { tapSetupLater() - viewSavedLoginDetails(composeTestRule, originWebsite) - revealPassword(composeTestRule) - verifyPasswordSaved(composeTestRule, "firefox") + viewSavedLoginDetails(originWebsite) + revealPassword() + verifyPasswordSaved("firefox") } } @@ -605,7 +602,7 @@ class LoginsTest : TestSetup() { fun searchLoginsByUsernameTest() { val firstLoginPage = mockWebServer.saveLoginAsset val secondLoginPage = "https://mozilla-mobile.github.io/testapp/v2.0/loginForm.html" - val originWebsite = "https://mozilla-mobile.github.io" + val originWebsite = "mozilla-mobile.github.io" navigationToolbar { }.enterURLAndEnterToBrowser(firstLoginPage.url) { @@ -624,26 +621,24 @@ class LoginsTest : TestSetup() { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { tapSetupLater() - clickSearchLoginButton(composeTestRule) - searchLogin(composeTestRule, "ANDROID") - viewSavedLoginDetails(composeTestRule, originWebsite) - verifyLoginItemUsername(composeTestRule, "android") - revealPassword(composeTestRule) - verifyPasswordSaved(composeTestRule, "firefox") - clickGoBackButton(composeTestRule) - clickSearchLoginButton(composeTestRule) - searchLogin(composeTestRule, "android") - viewSavedLoginDetails(composeTestRule, originWebsite) - verifyLoginItemUsername(composeTestRule, "android") - revealPassword(composeTestRule) - verifyPasswordSaved(composeTestRule, "firefox") - clickGoBackButton(composeTestRule) - clickSearchLoginButton(composeTestRule) - searchLogin(composeTestRule, "AnDrOiD") - viewSavedLoginDetails(composeTestRule, originWebsite) - verifyLoginItemUsername(composeTestRule, "android") - revealPassword(composeTestRule) - verifyPasswordSaved(composeTestRule, "firefox") + clickSearchLoginButton() + searchLogin("ANDROID") + viewSavedLoginDetails(originWebsite) + verifyLoginItemUsername("android") + revealPassword() + verifyPasswordSaved("firefox") + }.goBackToSavedLogins { + searchLogin("android") + viewSavedLoginDetails(originWebsite) + verifyLoginItemUsername("android") + revealPassword() + verifyPasswordSaved("firefox") + }.goBackToSavedLogins { + searchLogin("AnDrOiD") + viewSavedLoginDetails(originWebsite) + verifyLoginItemUsername("android") + revealPassword() + verifyPasswordSaved("firefox") } } @@ -653,7 +648,7 @@ class LoginsTest : TestSetup() { fun searchLoginsByUrlTest() { val firstLoginPage = mockWebServer.saveLoginAsset val secondLoginPage = "https://mozilla-mobile.github.io/testapp/v2.0/loginForm.html" - val originWebsite = "https://mozilla-mobile.github.io" + val originWebsite = "mozilla-mobile.github.io" navigationToolbar { }.enterURLAndEnterToBrowser(firstLoginPage.url) { @@ -672,26 +667,24 @@ class LoginsTest : TestSetup() { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { tapSetupLater() - clickSearchLoginButton(composeTestRule) - searchLogin(composeTestRule, "MOZILLA") - viewSavedLoginDetails(composeTestRule, originWebsite) - verifyLoginItemUsername(composeTestRule, "android") - revealPassword(composeTestRule) - verifyPasswordSaved(composeTestRule, "firefox") - clickGoBackButton(composeTestRule) - clickSearchLoginButton(composeTestRule) - searchLogin(composeTestRule, "mozilla") - viewSavedLoginDetails(composeTestRule, originWebsite) - verifyLoginItemUsername(composeTestRule, "android") - revealPassword(composeTestRule) - verifyPasswordSaved(composeTestRule, "firefox") - clickGoBackButton(composeTestRule) - clickSearchLoginButton(composeTestRule) - searchLogin(composeTestRule, "MoZiLlA") - viewSavedLoginDetails(composeTestRule, originWebsite) - verifyLoginItemUsername(composeTestRule, "android") - revealPassword(composeTestRule) - verifyPasswordSaved(composeTestRule, "firefox") + clickSearchLoginButton() + searchLogin("MOZILLA") + viewSavedLoginDetails(originWebsite) + verifyLoginItemUsername("android") + revealPassword() + verifyPasswordSaved("firefox") + }.goBackToSavedLogins { + searchLogin("mozilla") + viewSavedLoginDetails(originWebsite) + verifyLoginItemUsername("android") + revealPassword() + verifyPasswordSaved("firefox") + }.goBackToSavedLogins { + searchLogin("MoZiLlA") + viewSavedLoginDetails(originWebsite) + verifyLoginItemUsername("android") + revealPassword() + verifyPasswordSaved("firefox") } } @@ -700,6 +693,7 @@ class LoginsTest : TestSetup() { fun verifyLastUsedLoginSortingOptionTest() { val firstLoginPage = mockWebServer.saveLoginAsset val secondLoginPage = "https://mozilla-mobile.github.io/testapp/v2.0/loginForm.html" + val originWebsite = "mozilla-mobile.github.io" navigationToolbar { }.enterURLAndEnterToBrowser(firstLoginPage.url) { @@ -718,26 +712,26 @@ class LoginsTest : TestSetup() { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { tapSetupLater() - clickSortPasswordsButton(composeTestRule) - verifyLoginsSortingOptions(composeTestRule) - clickLastUsedSortingOption(composeTestRule) - verifySortedLogin(1, "https://mozilla-mobile.github.io") - verifySortedLogin(2, "${firstLoginPage.url.scheme}://${firstLoginPage.url.authority}") - }.goBack(composeTestRule) { + clickSavedLoginsChevronIcon() + verifyLoginsSortingOptions() + clickLastUsedSortingOption() + verifySortedLogin(0, originWebsite) + verifySortedLogin(1, firstLoginPage.url.authority.toString()) + }.goBack { }.openSavedLogins { - verifySortedLogin(1, "https://mozilla-mobile.github.io") - verifySortedLogin(2, "${firstLoginPage.url.scheme}://${firstLoginPage.url.authority}") + verifySortedLogin(0, originWebsite) + verifySortedLogin(1, firstLoginPage.url.authority.toString()) } - restartApp(composeTestRule.activityRule) + restartApp(activityTestRule.activityRule) browserScreen { }.openThreeDotMenu { }.openSettings { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { - verifySortedLogin(1, "https://mozilla-mobile.github.io") - verifySortedLogin(2, "${firstLoginPage.url.scheme}://${firstLoginPage.url.authority}") + verifySortedLogin(0, originWebsite) + verifySortedLogin(1, firstLoginPage.url.authority.toString()) } } @@ -746,6 +740,7 @@ class LoginsTest : TestSetup() { fun verifyAlphabeticalLoginSortingOptionTest() { val firstLoginPage = mockWebServer.saveLoginAsset val secondLoginPage = "https://mozilla-mobile.github.io/testapp/v2.0/loginForm.html" + val originWebsite = "mozilla-mobile.github.io" navigationToolbar { }.enterURLAndEnterToBrowser(firstLoginPage.url) { @@ -765,23 +760,23 @@ class LoginsTest : TestSetup() { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { tapSetupLater() - verifySortedLogin(1, "${firstLoginPage.url.scheme}://${firstLoginPage.url.authority}") - verifySortedLogin(2, "https://mozilla-mobile.github.io") - }.goBack(composeTestRule) { + verifySortedLogin(0, firstLoginPage.url.authority.toString()) + verifySortedLogin(1, originWebsite) + }.goBack { }.openSavedLogins { - verifySortedLogin(1, "${firstLoginPage.url.scheme}://${firstLoginPage.url.authority}") - verifySortedLogin(2, "https://mozilla-mobile.github.io") + verifySortedLogin(0, firstLoginPage.url.authority.toString()) + verifySortedLogin(1, originWebsite) } - restartApp(composeTestRule.activityRule) + restartApp(activityTestRule.activityRule) browserScreen { }.openThreeDotMenu { }.openSettings { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { - verifySortedLogin(1, "${firstLoginPage.url.scheme}://${firstLoginPage.url.authority}") - verifySortedLogin(2, "https://mozilla-mobile.github.io") + verifySortedLogin(0, firstLoginPage.url.authority.toString()) + verifySortedLogin(1, originWebsite) } } @@ -797,20 +792,18 @@ class LoginsTest : TestSetup() { }.openSavedLogins { tapSetupLater() clickAddLoginButton() - verifyAddNewLoginView(composeTestRule) - enterSiteCredentialWhileAddingALogin(composeTestRule, "mozilla") - verifyHostnameErrorMessage(composeTestRule) - enterSiteCredentialWhileAddingALogin(composeTestRule, loginPage) - verifyHostnameClearButton(composeTestRule) - setUserNameWhileAddingANewLogin(composeTestRule, "mozilla") - setNewPasswordWhileAddingANewLogin(composeTestRule, "firefox") - clickClearPasswordButton(composeTestRule) - verifyPasswordErrorMessage(composeTestRule) - setNewPasswordWhileAddingANewLogin(composeTestRule, "firefox") - verifyPasswordClearButton(composeTestRule) - saveNewLogin(composeTestRule) - clickGoBackButton(composeTestRule) - }.goBack(composeTestRule) { + verifyAddNewLoginView() + enterSiteCredential("mozilla") + verifyHostnameErrorMessage() + enterSiteCredential(loginPage) + verifyHostnameClearButtonEnabled() + setNewUserName("mozilla") + setNewPassword("firefox") + clickClearPasswordButton() + verifyPasswordErrorMessage() + setNewPassword("firefox") + verifyPasswordClearButtonEnabled() + saveEditedLogin() } exitMenu() @@ -819,10 +812,10 @@ class LoginsTest : TestSetup() { }.enterURLAndEnterToBrowser(loginPage.toUri()) { clickPageObject(itemWithResId("username")) clickSuggestedLoginsButton() - verifySuggestedUserName(composeTestRule, "mozilla") - clickSuggestedLogin(composeTestRule, "mozilla") + verifySuggestedUserName(activityTestRule, "mozilla") + clickSuggestedLogin(activityTestRule, "mozilla") clickPageObject(itemWithResId("togglePassword")) - verifyPrefilledLoginCredentials(composeTestRule, "mozilla", "firefox", true) + verifyPrefilledLoginCredentials(activityTestRule, "mozilla", "firefox", true) } } @@ -843,7 +836,7 @@ class LoginsTest : TestSetup() { }.openLoginsAndPasswordSubMenu { }.openSavedLogins { tapSetupLater() - viewSavedLoginDetails(composeTestRule, "test@example.com") + viewSavedLoginDetails("test@example.com") clickCopyUserNameButton() verifySnackBarText("Username copied to clipboard") clickCopyPasswordButton() diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/MainMenuTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/MainMenuTest.kt @@ -87,13 +87,8 @@ class MainMenuTest : TestSetup() { }.openPasswords { verifySecurityPromptForLogins() tapSetupLater() - verifyEmptySavedLoginsListView(composeTestRule) - }.goBack(composeTestRule) { - } - - exitMenu() - - homeScreen { + verifyEmptySavedLoginsListView() + }.goBackToHomeScreen { }.openThreeDotMenu { }.openAddonsManagerMenu { verifyAddonsListIsDisplayed(true) diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/MainMenuTestCompose.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/MainMenuTestCompose.kt @@ -190,11 +190,9 @@ class MainMenuTestCompose : TestSetup() { }.openPasswords { verifySecurityPromptForLogins() tapSetupLater() - verifyEmptySavedLoginsListView(composeTestRule) - }.goBack(composeTestRule) { + verifyEmptySavedLoginsListView() + exitMenu() } - - exitMenu() browserScreen { verifyPageContent(testPage.content) } @@ -1090,13 +1088,8 @@ class MainMenuTestCompose : TestSetup() { }.openPasswords { verifySecurityPromptForLogins() tapSetupLater() - verifyEmptySavedLoginsListView(composeTestRule) - }.goBack(composeTestRule) { - } - - exitMenu() - - homeScreen { + verifyEmptySavedLoginsListView() + }.goBackToHomeScreen { verifyHomeComponent(composeTestRule) } } diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot.kt @@ -5,50 +5,38 @@ package org.mozilla.fenix.ui.robots import android.util.Log -import androidx.compose.ui.test.assert -import androidx.compose.ui.test.assertIsDisplayed -import androidx.compose.ui.test.assertIsEnabled -import androidx.compose.ui.test.assertIsNotDisplayed -import androidx.compose.ui.test.assertIsNotEnabled -import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.ComposeTestRule -import androidx.compose.ui.test.onNodeWithContentDescription -import androidx.compose.ui.test.onNodeWithTag -import androidx.compose.ui.test.onNodeWithText -import androidx.compose.ui.test.performClick import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.assertion.ViewAssertions import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.RootMatchers import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility +import androidx.test.espresso.matcher.ViewMatchers.withHint +import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.uiautomator.By +import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until import org.hamcrest.CoreMatchers import org.hamcrest.CoreMatchers.containsString import org.mozilla.fenix.R import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource -import org.mozilla.fenix.helpers.HomeActivityComposeTestRule +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.helpers.MatcherHelper.assertItemIsEnabledAndVisible import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists +import org.mozilla.fenix.helpers.MatcherHelper.checkedItemWithResId import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText +import org.mozilla.fenix.helpers.MatcherHelper.itemWithClassNameAndIndex import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId -import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndIndex import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime import org.mozilla.fenix.helpers.TestHelper.mDevice import org.mozilla.fenix.helpers.TestHelper.packageName -import org.mozilla.fenix.helpers.TestHelper.waitForAppWindowToBeUpdated -import org.mozilla.fenix.helpers.ext.clearAndSetText +import org.mozilla.fenix.helpers.click import org.mozilla.fenix.helpers.ext.waitNotNull -import org.mozilla.fenix.settings.logins.ui.LoginsTestingTags.ADD_LOGIN_HOST_NAME_TEXT_FIELD -import org.mozilla.fenix.settings.logins.ui.LoginsTestingTags.ADD_LOGIN_PASSWORD_TEXT_FIELD -import org.mozilla.fenix.settings.logins.ui.LoginsTestingTags.ADD_LOGIN_USER_NAME_TEXT_FIELD -import org.mozilla.fenix.settings.logins.ui.LoginsTestingTags.EDIT_LOGIN_PASSWORD_TEXT_FIELD -import org.mozilla.fenix.settings.logins.ui.LoginsTestingTags.EDIT_LOGIN_USERNAME_TEXT_FIELD -import org.mozilla.fenix.settings.logins.ui.LoginsTestingTags.LOGIN_DETAILS_PASSWORD_TEXT_FIELD -import org.mozilla.fenix.settings.logins.ui.LoginsTestingTags.SAVED_LOGINS_PASSWORD_SEARCH_FIELD /** * Implementation of Robot Pattern for the Privacy Settings > saved logins sub menu @@ -67,16 +55,18 @@ class SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot { Log.i(TAG, "verifySecurityPromptForLogins: Verified that the \"Secure your saved passwords\" dialog is visible") } - fun verifyEmptySavedLoginsListView(composeTestRule: HomeActivityComposeTestRule) { + fun verifyEmptySavedLoginsListView() { Log.i(TAG, "verifyEmptySavedLoginsListView: Trying to verify that the saved logins section description is displayed") - composeTestRule.onNodeWithText(getStringResource(R.string.preferences_passwords_saved_logins_description_empty_text_2)).assertIsDisplayed() + onView(withText(getStringResource(R.string.preferences_passwords_saved_logins_description_empty_text_2))) + .check(matches(isDisplayed())) Log.i(TAG, "verifyEmptySavedLoginsListView: Verified that the saved logins section description is displayed") Log.i(TAG, "verifyEmptySavedLoginsListView: Trying to verify that the \"Learn more about Sync\" link is displayed") - composeTestRule.onNodeWithContentDescription("Learn more about sync Links available", useUnmergedTree = true).assertIsDisplayed() - Log.i(TAG, "verifyEmptySavedLoginsListView: Verified that the \"Learn more about Sync\" link is displayed") + onView(withText(R.string.preferences_passwords_saved_logins_description_empty_learn_more_link_2)) + .check(matches(isDisplayed())) Log.i(TAG, "verifyEmptySavedLoginsListView: Verified that the \"Learn more about Sync\" link is displayed") Log.i(TAG, "verifyEmptySavedLoginsListView: Trying to verify that the \"Add login\" button is displayed") - composeTestRule.onNodeWithText(getStringResource(R.string.preferences_logins_add_login_2)).assertIsDisplayed() + onView(withText(R.string.preferences_logins_add_login_2)) + .check(matches(isDisplayed())) Log.i(TAG, "verifyEmptySavedLoginsListView: Verified that the \"Add login\" button is displayed") } @@ -102,107 +92,87 @@ class SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot { Log.i(TAG, "clickAddLoginButton: Clicked the \"Add login\" button") } - fun verifyAddNewLoginView(composeTestRule: ComposeTestRule) { - Log.i(TAG, "verifyAddNewLoginView: Trying to verify the \"Add login\" view items") - composeTestRule.onNodeWithText(getStringResource(R.string.preferences_passwords_saved_logins_site), useUnmergedTree = true).assertIsDisplayed() - composeTestRule.onNodeWithTag(ADD_LOGIN_HOST_NAME_TEXT_FIELD).assertIsDisplayed() - composeTestRule.onNodeWithText(getStringResource(R.string.add_login_hostname_invalid_text_3), useUnmergedTree = true).assertIsDisplayed() - composeTestRule.onNodeWithText(getStringResource(R.string.preferences_passwords_saved_logins_username), useUnmergedTree = true).assertIsDisplayed() - composeTestRule.onNodeWithTag(ADD_LOGIN_USER_NAME_TEXT_FIELD).assertIsDisplayed() - composeTestRule.onNodeWithText(getStringResource(R.string.preferences_passwords_saved_logins_password), useUnmergedTree = true).assertIsDisplayed() - composeTestRule.onNodeWithTag(ADD_LOGIN_PASSWORD_TEXT_FIELD, useUnmergedTree = true).assertIsDisplayed() - Log.i(TAG, "verifyAddNewLoginView: Verified the \"Add login\" view items") + fun verifyAddNewLoginView() { + assertUIObjectExists( + siteHeader(), + siteTextInput(), + usernameHeader(), + usernameTextInput(), + passwordHeader(), + passwordTextInput(), + siteDescription(), + ) + Log.i(TAG, "verifyAddNewLoginView: Trying to verify the \"https://www.example.com\" site text box hint") + siteTextInputHint().check(matches(withHint(R.string.add_login_hostname_hint_text))) + Log.i(TAG, "verifyAddNewLoginView: Verified the \"https://www.example.com\" site text box hint") } - fun enterSiteCredentialWhileAddingALogin(composeTestRule: ComposeTestRule, website: String) { - Log.i(TAG, "enterSiteCredentialWhileAddingALogin: Trying to set the \"Site\" text box text to: $website") - composeTestRule.onNodeWithTag(ADD_LOGIN_HOST_NAME_TEXT_FIELD).performClick() - composeTestRule.onNodeWithTag(ADD_LOGIN_HOST_NAME_TEXT_FIELD).clearAndSetText(website) - Log.i(TAG, "enterSiteCredentialWhileAddingALogin: The \"Site\" text box text was set to: $website") + fun enterSiteCredential(website: String) { + Log.i(TAG, "enterSiteCredential: Trying to set the \"Site\" text box text to: $website") + siteTextInput().setText(website) + Log.i(TAG, "enterSiteCredential: The \"Site\" text box text was set to: $website") } - fun verifyHostnameErrorMessage(composeTestRule: ComposeTestRule) { - Log.i(TAG, "verifyHostnameErrorMessage: Trying to verify that the host name error message is displayed") - composeTestRule.onNodeWithText(getStringResource(R.string.add_login_hostname_invalid_text_2), useUnmergedTree = true).assertIsDisplayed() - Log.i(TAG, "verifyHostnameErrorMessage: Verified that the host name error message is displayed") - } + fun verifyHostnameErrorMessage() = + assertUIObjectExists(itemContainingText(getStringResource(R.string.add_login_hostname_invalid_text_2))) - fun verifyPasswordErrorMessage(composeTestRule: ComposeTestRule) { - Log.i(TAG, "verifyPasswordErrorMessage: Trying to verify that the password error message is displayed") - composeTestRule.onNodeWithText(getStringResource(R.string.saved_login_password_required_2), useUnmergedTree = true).assertIsDisplayed() - Log.i(TAG, "verifyPasswordErrorMessage: Verified that the password error message is displayed") - } + fun verifyPasswordErrorMessage() = + assertUIObjectExists(itemContainingText(getStringResource(R.string.saved_login_password_required_2))) - fun verifyPasswordClearButton(composeTestRule: ComposeTestRule) { - Log.i(TAG, "verifyPasswordClearButton: Trying to verify that the clear password button is displayed") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.saved_logins_clear_password)).assertIsDisplayed() - Log.i(TAG, "verifyPasswordClearButton: Verified that the clear password button is displayed") - } + fun verifyPasswordClearButtonEnabled() = + assertItemIsEnabledAndVisible(itemWithResId("$packageName:id/clearPasswordTextButton")) - fun verifyHostnameClearButton(composeTestRule: ComposeTestRule) { - Log.i(TAG, "verifyHostnameClearButton: Trying to verify the clear host name button is displayed") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.saved_login_clear_hostname), useUnmergedTree = true) - .assertIsDisplayed() - Log.i(TAG, "verifyHostnameClearButton: Verified that the clear host name button is displayed") - } + fun verifyHostnameClearButtonEnabled() = + assertItemIsEnabledAndVisible(itemWithResId("$packageName:id/clearHostnameTextButton")) - fun clickSearchLoginButton(composeTestRule: ComposeTestRule) { + fun clickSearchLoginButton() { Log.i(TAG, "clickSearchLoginButton: Trying to click the search logins button") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.preferences_passwords_saved_logins_search_2)).performClick() + itemWithResId("$packageName:id/search").click() Log.i(TAG, "clickSearchLoginButton: Clicked the search logins button") } - fun clickSortPasswordsButton(composeTestRule: ComposeTestRule) { - Log.i(TAG, "clickSortPasswordsButton: Trying to click the \"Saved logins\" sort button") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.saved_logins_menu_dropdown_chevron_icon_content_description_2)).performClick() - Log.i(TAG, "clickSortPasswordsButton: Clicked the \"Saved logins\" sort button") + fun clickSavedLoginsChevronIcon() { + Log.i(TAG, "clickSavedLoginsChevronIcon: Trying to click the \"Saved logins\" chevron button") + itemWithResId("$packageName:id/toolbar_chevron_icon").click() + Log.i(TAG, "clickSavedLoginsChevronIcon: Clicked the \"Saved logins\" chevron button") } - fun verifyLoginsSortingOptions(composeTestRule: ComposeTestRule) { - Log.i(TAG, "clickSortPasswordsButton: Trying to verify that the logins sorting options are displayed") - composeTestRule.onNodeWithText(getStringResource(R.string.saved_logins_sort_strategy_alphabetically)).assertIsDisplayed() - composeTestRule.onNodeWithText(getStringResource(R.string.saved_logins_sort_strategy_last_used)).assertIsDisplayed() - Log.i(TAG, "clickSortPasswordsButton: Verified that the logins sorting options are displayed") + fun verifyLoginsSortingOptions() { + assertUIObjectExists(itemContainingText(getStringResource(R.string.saved_logins_sort_strategy_alphabetically))) + assertUIObjectExists(itemContainingText(getStringResource(R.string.saved_logins_sort_strategy_last_used))) } - fun clickLastUsedSortingOption(composeTestRule: ComposeTestRule) { + fun clickLastUsedSortingOption() { Log.i(TAG, "clickLastUsedSortingOption: Trying to click the \"Last used\" sorting option") - composeTestRule.onNodeWithText(getStringResource(R.string.saved_logins_sort_strategy_last_used)).performClick() + itemContainingText(getStringResource(R.string.saved_logins_sort_strategy_last_used)).click() Log.i(TAG, "clickLastUsedSortingOption: Clicked the \"Last used\" sorting option") - Log.i(TAG, "clickLastUsedSortingOption: Waiting for compose rule to be idle") - composeTestRule.waitForIdle() - Log.i(TAG, "clickLastUsedSortingOption: Waited for compose rule to be idle") } - fun verifySortedLogin(position: Int, loginItemUrl: String) { - waitForAppWindowToBeUpdated() + fun verifySortedLogin(position: Int, loginTitle: String) = assertUIObjectExists( - itemWithResIdAndIndex( - "saved.logins.list.item.$loginItemUrl", - index = position - 1, - ), + itemWithClassNameAndIndex(className = "android.view.ViewGroup", index = position) + .getChild( + UiSelector() + .resourceId("$packageName:id/webAddressView") + .textContains(loginTitle), + ), ) - } - fun searchLogin(composeTestRule: ComposeTestRule, searchTerm: String) { + fun searchLogin(searchTerm: String) { Log.i(TAG, "searchLogin: Trying to set the search bar text to: $searchTerm") - composeTestRule.onNodeWithTag(SAVED_LOGINS_PASSWORD_SEARCH_FIELD).performClick() - composeTestRule.onNodeWithTag(SAVED_LOGINS_PASSWORD_SEARCH_FIELD).clearAndSetText(searchTerm) + itemWithResId("$packageName:id/search").setText(searchTerm) Log.i(TAG, "searchLogin: Search bar text was set to: $searchTerm") } fun verifySavedLoginsSectionUsername(username: String) = mDevice.waitNotNull(Until.findObjects(By.text(username))) - fun verifyLoginItemUsername(composeTestRule: ComposeTestRule, loginUserName: String) = { - Log.i(TAG, "verifyLoginItemUsername: Trying to verify that the login item with user name: $loginUserName is displayed") - composeTestRule.onNodeWithText(loginUserName, useUnmergedTree = true).assertIsDisplayed() - Log.i(TAG, "verifyLoginItemUsername: Verified that the login item with user name: $loginUserName is displayed") - } + fun verifyLoginItemUsername(username: String) = assertUIObjectExists(itemContainingText(username)) - fun verifyNotSavedLoginFromPrompt(composeTestRule: ComposeTestRule) { + fun verifyNotSavedLoginFromPrompt() { Log.i(TAG, "verifyNotSavedLoginFromPrompt: Trying to verify that \"test@example.com\" does not exist in the saved logins list") - composeTestRule.onNodeWithText("test@example.com", useUnmergedTree = true).assertIsNotDisplayed() + onView(withText("test@example.com")) + .check(ViewAssertions.doesNotExist()) Log.i(TAG, "verifyNotSavedLoginFromPrompt: Verified that \"test@example.com\" does not exist in the saved logins list") } @@ -213,172 +183,100 @@ class SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot { Log.i(TAG, "verifyLocalhostExceptionAdded: Verified that \"localhost\" is visible in the exceptions list") } - fun viewSavedLoginDetails(composeTestRule: ComposeTestRule, loginDetail: String) { - waitForAppWindowToBeUpdated() - Log.i(TAG, "viewSavedLoginDetails: Trying to click $loginDetail saved login") - composeTestRule.onNodeWithText(loginDetail, useUnmergedTree = true).performClick() - Log.i(TAG, "viewSavedLoginDetails: Clicked $loginDetail saved login") + fun viewSavedLoginDetails(loginUserName: String) { + Log.i(TAG, "viewSavedLoginDetails: Trying to click $loginUserName saved login") + onView(withText(loginUserName)).click() + Log.i(TAG, "viewSavedLoginDetails: Clicked $loginUserName saved login") } - fun clickThreeDotButton(composeTestRule: ComposeTestRule) { + fun clickThreeDotButton(activityTestRule: HomeActivityIntentTestRule) { Log.i(TAG, "clickThreeDotButton: Trying to click the three dot button") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.login_detail_menu_button_content_description)) - .performClick() + openActionBarOverflowOrOptionsMenu(activityTestRule.activity) Log.i(TAG, "clickThreeDotButton: Clicked the three dot button") } - fun clickEditLoginButton(composeTestRule: ComposeTestRule) { + fun clickEditLoginButton() { Log.i(TAG, "clickEditLoginButton: Trying to click the \"Edit\" button") - composeTestRule.onNodeWithText( - getStringResource(R.string.login_detail_menu_edit_button), - useUnmergedTree = true, - ).performClick() + itemContainingText("Edit").click() Log.i(TAG, "clickEditLoginButton: Clicked the \"Edit\" button") } - fun clickDeleteLoginButton(composeTestRule: ComposeTestRule) { + fun clickDeleteLoginButton() { Log.i(TAG, "clickDeleteLoginButton: Trying to click the \"Delete\" button") - composeTestRule.onNodeWithText( - getStringResource(R.string.login_detail_menu_delete_button), - useUnmergedTree = true, - ).performClick() + itemContainingText("Delete").click() Log.i(TAG, "clickDeleteLoginButton: Clicked the \"Delete\" button") } - fun verifyLoginDeletionPrompt(composeTestRule: ComposeTestRule) { - Log.i(TAG, "clickDeleteLoginButton: Trying to verify that the login deletion prompt is displayed") - composeTestRule.onNodeWithText( - getStringResource(R.string.login_deletion_confirmation_2), - useUnmergedTree = true, - ).assertIsDisplayed() - Log.i(TAG, "clickDeleteLoginButton: Verified that the login deletion prompt is displayed") - } + fun verifyLoginDeletionPrompt() = + assertUIObjectExists(itemContainingText(getStringResource(R.string.login_deletion_confirmation_2))) - fun clickConfirmDeleteLogin(composeTestRule: ComposeTestRule) { + fun clickConfirmDeleteLogin() { Log.i(TAG, "clickConfirmDeleteLogin: Trying to click the \"Delete\" dialog button") - composeTestRule.onNodeWithText(getStringResource(R.string.dialog_delete_positive)) - .performClick() + onView(withId(android.R.id.button1)).inRoot(RootMatchers.isDialog()).click() Log.i(TAG, "clickConfirmDeleteLogin: Clicked the \"Delete\" dialog button") } - fun clickCancelDeleteLogin(composeTestRule: ComposeTestRule) { + fun clickCancelDeleteLogin() { Log.i(TAG, "clickCancelDeleteLogin: Trying to click the \"Cancel\" dialog button") - composeTestRule.onNodeWithText(getStringResource(R.string.dialog_delete_negative)) - .performClick() + onView(withId(android.R.id.button2)).inRoot(RootMatchers.isDialog()).click() Log.i(TAG, "clickCancelDeleteLogin: Clicked the \"Cancel\" dialog button") } - fun setNewUserNameWhileEditingALogin(composeTestRule: ComposeTestRule, userName: String) { - Log.i(TAG, "setNewUserNameWhileEditingALogin: Trying to set \"Username\" text box to: $userName") - composeTestRule.onNodeWithTag(EDIT_LOGIN_USERNAME_TEXT_FIELD).performClick() - composeTestRule.onNodeWithTag(EDIT_LOGIN_USERNAME_TEXT_FIELD).clearAndSetText(userName) - Log.i(TAG, "setNewUserNameWhileEditingALogin: \"Username\" text box was set to: $userName") - } - - fun setUserNameWhileAddingANewLogin(composeTestRule: ComposeTestRule, userName: String) { - Log.i(TAG, "setUserNameWhileAddingANewLogin: Trying to set \"Username\" text box to: $userName") - composeTestRule.onNodeWithTag(ADD_LOGIN_USER_NAME_TEXT_FIELD).performClick() - composeTestRule.onNodeWithTag(ADD_LOGIN_USER_NAME_TEXT_FIELD).clearAndSetText(userName) - Log.i(TAG, "setUserNameWhileAddingANewLogin: \"Username\" text box was set to: $userName") + fun setNewUserName(userName: String) { + Log.i(TAG, "setNewUserName: Trying to set \"Username\" text box to: $userName") + usernameTextInput().setText(userName) + Log.i(TAG, "setNewUserName: \"Username\" text box was set to: $userName") } - fun clickClearUserNameButton(composeTestRule: ComposeTestRule) { + fun clickClearUserNameButton() { Log.i(TAG, "clickClearUserNameButton: Trying to click the clear username button") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.saved_login_clear_username)) - .performClick() + itemWithResId("$packageName:id/clearUsernameTextButton").click() Log.i(TAG, "clickClearUserNameButton: Clicked the clear username button") } - fun setNewPasswordWhileEditingALogin(composeTestRule: ComposeTestRule, password: String) { - Log.i(TAG, "setNewPasswordWhileEditingALogin: Trying to set \"Password\" text box to: $password") - composeTestRule.onNodeWithTag(EDIT_LOGIN_PASSWORD_TEXT_FIELD).performClick() - composeTestRule.onNodeWithTag(EDIT_LOGIN_PASSWORD_TEXT_FIELD).clearAndSetText(password) - Log.i(TAG, "setNewPasswordWhileEditingALogin: \"Password\" text box was set to: $password") - } - - fun setNewPasswordWhileAddingANewLogin(composeTestRule: ComposeTestRule, password: String) { - Log.i(TAG, "setNewPasswordWhileAddingANewLogin: Trying to set \"Password\" text box to: $password") - composeTestRule.onNodeWithTag(ADD_LOGIN_PASSWORD_TEXT_FIELD).performClick() - composeTestRule.onNodeWithTag(ADD_LOGIN_PASSWORD_TEXT_FIELD).clearAndSetText(password) - Log.i(TAG, "setNewPasswordWhileAddingANewLogin: \"Password\" text box was set to: $password") + fun setNewPassword(password: String) { + Log.i(TAG, "setNewPassword: Trying to set \"Password\" text box to: $password") + passwordTextInput().setText(password) + Log.i(TAG, "setNewPassword: \"Password\" text box was set to: $password") } - fun clickClearPasswordButton(composeTestRule: ComposeTestRule) { + fun clickClearPasswordButton() { Log.i(TAG, "clickClearPasswordButton: Trying to click the clear password button") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.saved_logins_clear_password)) - .performClick() + itemWithResId("$packageName:id/clearPasswordTextButton").click() Log.i(TAG, "clickClearPasswordButton: Clicked the clear password button") } - fun saveEditedLogin(composeTestRule: ComposeTestRule) { + fun saveEditedLogin() { Log.i(TAG, "saveEditedLogin: Trying to click the toolbar save button") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.edit_login_button_content_description)).performClick() + itemWithResId("$packageName:id/save_login_button").click() Log.i(TAG, "saveEditedLogin: Clicked the toolbar save button") - waitForAppWindowToBeUpdated() - } - - fun saveNewLogin(composeTestRule: ComposeTestRule) { - Log.i(TAG, "saveNewLogin: Trying to click the toolbar save button") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.add_login_save_new_login_button_content_description)) - .performClick() - Log.i(TAG, "saveNewLogin: Clicked the toolbar save button") - waitForAppWindowToBeUpdated() } - fun verifySaveLoginButtonIsEnabled(composeTestRule: ComposeTestRule, isEnabled: Boolean) { - if (isEnabled) { - Log.i(TAG, "verifySaveLoginButtonIsEnabled: Trying to verify that the save login button is enabled") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.edit_login_button_content_description)) - .assertIsEnabled() - Log.i(TAG, "verifySaveLoginButtonIsEnabled: Verified that the save login button is enabled") - } else { - Log.i(TAG, "verifySaveLoginButtonIsEnabled: Trying to verify that the save login button is not enabled") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.edit_login_button_content_description)) - .assertIsNotEnabled() - Log.i(TAG, "verifySaveLoginButtonIsEnabled: Verified that the save login button is not enabled") - } - } + fun verifySaveLoginButtonIsEnabled(isEnabled: Boolean) = + assertUIObjectExists( + checkedItemWithResId("$packageName:id/save_login_button", isChecked = true), + exists = isEnabled, + ) - fun revealPassword(composeTestRule: ComposeTestRule) { + fun revealPassword() { Log.i(TAG, "revealPassword: Trying to click the reveal password button") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.saved_login_reveal_password), useUnmergedTree = true) - .performClick() + onView(withId(R.id.revealPasswordButton)).click() Log.i(TAG, "revealPassword: Clicked the reveal password button") } - fun verifyPasswordSaved(composeTestRule: ComposeTestRule, password: String) { - Log.i(TAG, "verifyPasswordSaved: Trying to verify that the saved login password is set to: $password") - composeTestRule.onNodeWithTag(LOGIN_DETAILS_PASSWORD_TEXT_FIELD).assert(hasText(password)) - Log.i(TAG, "verifyPasswordSaved: Verified that the saved login password is set to: $password") + fun verifyPasswordSaved(password: String) { + Log.i(TAG, "verifyPasswordSaved: Trying to verify that the \"Password\" text box is set to $password") + onView(withId(R.id.passwordText)).check(matches(withText(password))) + Log.i(TAG, "verifyPasswordSaved: Verified that the \"Password\" text box is set to $password") } - fun verifyPasswordWhileEditingALogin(composeTestRule: ComposeTestRule, password: String) { - Log.i(TAG, "verifyPasswordWhileEditingALogin: Trying to verify that the saved login password while editing a login is set to: $password") - composeTestRule.onNodeWithTag(EDIT_LOGIN_PASSWORD_TEXT_FIELD).assert(hasText(password)) - Log.i(TAG, "verifyPasswordWhileEditingALogin: Verified that the saved login password while editing a login is set to: $password") - } + fun verifyUserNameRequiredErrorMessage() = + assertUIObjectExists(itemContainingText(getStringResource(R.string.saved_login_username_required_2))) - fun verifyUserNameRequiredErrorMessage(composeTestRule: ComposeTestRule) { - Log.i(TAG, "verifyUserNameRequiredErrorMessage: Trying to verify the user name required error message is displayed") - composeTestRule.onNodeWithText(getStringResource(R.string.saved_login_username_required_2)) - .assertIsDisplayed() - Log.i(TAG, "verifyUserNameRequiredErrorMessage: Verified the user name required error message is displayed") - } + fun verifyPasswordRequiredErrorMessage() = + assertUIObjectExists(itemContainingText(getStringResource(R.string.saved_login_password_required_2))) - fun verifyPasswordRequiredErrorMessage(composeTestRule: ComposeTestRule) { - Log.i(TAG, "verifyUserNameRequiredErrorMessage: Trying to verify the password required error message is displayed") - composeTestRule.onNodeWithText(getStringResource(R.string.saved_login_password_required_2)) - .assertIsDisplayed() - Log.i(TAG, "verifyUserNameRequiredErrorMessage: Verified the password required error message is displayed") - } - - fun clickGoBackButton(composeTestRule: ComposeTestRule) { - Log.i(TAG, "clickGoBackButton: Trying to click the go back button") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.edit_login_navigate_back_button_content_description)) - .performClick() - Log.i(TAG, "clickGoBackButton: Clicked the go back button") - waitForAppWindowToBeUpdated() - } + fun clickGoBackButton() = goBackButton().click() fun clickCopyUserNameButton() = itemWithResId("$packageName:id/copyUsername").also { @@ -401,10 +299,9 @@ class SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot { } class Transition { - fun goBack(composeTestRule: ComposeTestRule, interact: SettingsSubMenuLoginsAndPasswordRobot.() -> Unit): SettingsSubMenuLoginsAndPasswordRobot.Transition { + fun goBack(interact: SettingsSubMenuLoginsAndPasswordRobot.() -> Unit): SettingsSubMenuLoginsAndPasswordRobot.Transition { Log.i(TAG, "goBack: Trying to click the navigate up button") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.logins_navigate_back_button_content_description)) - .performClick() + goBackButton().perform(ViewActions.click()) Log.i(TAG, "goBack: Clicked the navigate up button") SettingsSubMenuLoginsAndPasswordRobot().interact() @@ -420,10 +317,18 @@ class SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot { return HomeScreenRobot.Transition() } - fun goToSavedWebsite(composeTestRule: ComposeTestRule, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + fun goBackToSavedLogins(interact: SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot.() -> Unit): SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot.Transition { + Log.i(TAG, "goBackToSavedLogins: Trying to click the navigate up button") + goBackButton().perform(ViewActions.click()) + Log.i(TAG, "goBackToSavedLogins: Clicked the navigate up button") + + SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot().interact() + return SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot.Transition() + } + + fun goToSavedWebsite(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { Log.i(TAG, "goToSavedWebsite: Trying to click the open web site button") - composeTestRule.onNodeWithContentDescription(getStringResource(R.string.saved_login_open_site)) - .performClick() + openWebsiteButton().click() Log.i(TAG, "goToSavedWebsite: Clicked the open web site button") BrowserRobot().interact() @@ -434,3 +339,14 @@ class SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot { private fun goBackButton() = onView(CoreMatchers.allOf(ViewMatchers.withContentDescription("Navigate up"))) + +private fun openWebsiteButton() = onView(withId(R.id.openWebAddress)) + +private fun siteHeader() = itemWithResId("$packageName:id/hostnameHeaderText") +private fun siteTextInput() = itemWithResId("$packageName:id/hostnameText") +private fun siteDescription() = itemContainingText(getStringResource(R.string.add_login_hostname_invalid_text_3)) +private fun siteTextInputHint() = onView(withId(R.id.hostnameText)) +private fun usernameHeader() = itemWithResId("$packageName:id/usernameHeader") +private fun usernameTextInput() = itemWithResId("$packageName:id/usernameText") +private fun passwordHeader() = itemWithResId("$packageName:id/passwordHeader") +private fun passwordTextInput() = itemWithResId("$packageName:id/passwordText") diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/logins/ui/AddLoginScreen.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/logins/ui/AddLoginScreen.kt @@ -235,7 +235,7 @@ private fun AddLoginPassword(store: LoginsStore) { .semantics { testTag = LoginsTestingTags.ADD_LOGIN_PASSWORD_TEXT_FIELD }, - label = stringResource(R.string.preferences_passwords_saved_logins_password), + label = stringResource(R.string.saved_logins_clear_password), trailingIcon = { if (isFocused && state?.password?.isNotEmpty() == true) { CrossTextFieldButton(contentDescription = Text.Resource(R.string.saved_logins_clear_password)) {