Bug 1881733 - Add logs to SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot
[gecko.git] / mobile / android / fenix / app / src / androidTest / java / org / mozilla / fenix / ui / robots / SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot.kt
blob86e985524acdbba108378953572ab16a483557c3
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 package org.mozilla.fenix.ui.robots
7 import android.util.Log
8 import androidx.test.espresso.Espresso.onView
9 import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
10 import androidx.test.espresso.action.ViewActions
11 import androidx.test.espresso.assertion.ViewAssertions
12 import androidx.test.espresso.assertion.ViewAssertions.matches
13 import androidx.test.espresso.matcher.RootMatchers
14 import androidx.test.espresso.matcher.ViewMatchers
15 import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
16 import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
17 import androidx.test.espresso.matcher.ViewMatchers.withHint
18 import androidx.test.espresso.matcher.ViewMatchers.withId
19 import androidx.test.espresso.matcher.ViewMatchers.withText
20 import androidx.test.uiautomator.By
21 import androidx.test.uiautomator.UiSelector
22 import androidx.test.uiautomator.Until
23 import org.hamcrest.CoreMatchers
24 import org.hamcrest.CoreMatchers.containsString
25 import org.mozilla.fenix.R
26 import org.mozilla.fenix.helpers.Constants.TAG
27 import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
28 import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
29 import org.mozilla.fenix.helpers.MatcherHelper.assertItemIsEnabledAndVisible
30 import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists
31 import org.mozilla.fenix.helpers.MatcherHelper.checkedItemWithResId
32 import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText
33 import org.mozilla.fenix.helpers.MatcherHelper.itemWithClassNameAndIndex
34 import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId
35 import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
36 import org.mozilla.fenix.helpers.TestHelper.mDevice
37 import org.mozilla.fenix.helpers.TestHelper.packageName
38 import org.mozilla.fenix.helpers.click
39 import org.mozilla.fenix.helpers.ext.waitNotNull
41 /**
42  * Implementation of Robot Pattern for the Privacy Settings > saved logins sub menu
43  */
45 class SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot {
46     fun verifySecurityPromptForLogins() {
47         Log.i(TAG, "verifySecurityPromptForLogins: Trying to verify that the \"Secure your logins and passwords\" dialog is visible")
48         onView(withText("Secure your logins and passwords")).check(
49             matches(
50                 withEffectiveVisibility(
51                     ViewMatchers.Visibility.VISIBLE,
52                 ),
53             ),
54         )
55         Log.i(TAG, "verifySecurityPromptForLogins: Verified that the \"Secure your logins and passwords\" dialog is visible")
56     }
58     fun verifyEmptySavedLoginsListView() {
59         Log.i(TAG, "verifyEmptySavedLoginsListView: Trying to verify that the saved logins section description is displayed")
60         onView(withText(getStringResource(R.string.preferences_passwords_saved_logins_description_empty_text)))
61             .check(matches(isDisplayed()))
62         Log.i(TAG, "verifyEmptySavedLoginsListView: Verified that the saved logins section description is displayed")
63         Log.i(TAG, "verifyEmptySavedLoginsListView: Trying to verify that the \"Learn more about Sync\" link is displayed")
64         onView(withText(R.string.preferences_passwords_saved_logins_description_empty_learn_more_link))
65             .check(matches(isDisplayed()))
66         Log.i(TAG, "verifyEmptySavedLoginsListView: Verified that the \"Learn more about Sync\" link is displayed")
67         Log.i(TAG, "verifyEmptySavedLoginsListView: Trying to verify that the \"Add login\" button is displayed")
68         onView(withText(R.string.preferences_logins_add_login))
69             .check(matches(isDisplayed()))
70         Log.i(TAG, "verifyEmptySavedLoginsListView: Verified that the \"Add login\" button is displayed")
71     }
73     fun verifySavedLoginsAfterSync() {
74         mDevice.waitNotNull(
75             Until.findObjects(By.text("https://accounts.google.com")),
76             waitingTime,
77         )
78         Log.i(TAG, "verifySavedLoginsAfterSync: Trying to verify that the \"https://accounts.google.comn\" login is displayed")
79         onView(withText("https://accounts.google.com")).check(matches(isDisplayed()))
80         Log.i(TAG, "verifySavedLoginsAfterSync: Verified that the \"https://accounts.google.comn\" login is displayed")
81     }
83     fun tapSetupLater() {
84         Log.i(TAG, "tapSetupLater: Trying to click the \"Later\" dialog button")
85         onView(withText("Later")).perform(ViewActions.click())
86         Log.i(TAG, "tapSetupLater: Clicked the \"Later\" dialog button")
87     }
89     fun clickAddLoginButton() {
90         Log.i(TAG, "clickAddLoginButton: Trying to click the \"Add login\" button")
91         itemContainingText(getStringResource(R.string.preferences_logins_add_login)).click()
92         Log.i(TAG, "clickAddLoginButton: Clicked the \"Add login\" button")
93     }
95     fun verifyAddNewLoginView() {
96         assertUIObjectExists(
97             siteHeader(),
98             siteTextInput(),
99             usernameHeader(),
100             usernameTextInput(),
101             passwordHeader(),
102             passwordTextInput(),
103             siteDescription(),
104         )
105         Log.i(TAG, "verifyAddNewLoginView: Trying to verify the \"https://www.example.com\" site text box hint")
106         siteTextInputHint().check(matches(withHint(R.string.add_login_hostname_hint_text)))
107         Log.i(TAG, "verifyAddNewLoginView: Verified the \"https://www.example.com\" site text box hint")
108     }
110     fun enterSiteCredential(website: String) {
111         Log.i(TAG, "enterSiteCredential: Trying to set the \"Site\" text box text to: $website")
112         siteTextInput().setText(website)
113         Log.i(TAG, "enterSiteCredential: The \"Site\" text box text was set to: $website")
114     }
116     fun verifyHostnameErrorMessage() =
117         assertUIObjectExists(itemContainingText(getStringResource(R.string.add_login_hostname_invalid_text_2)))
119     fun verifyPasswordErrorMessage() =
120         assertUIObjectExists(itemContainingText(getStringResource(R.string.saved_login_password_required)))
122     fun verifyPasswordClearButtonEnabled() =
123         assertItemIsEnabledAndVisible(itemWithResId("$packageName:id/clearPasswordTextButton"))
125     fun verifyHostnameClearButtonEnabled() =
126         assertItemIsEnabledAndVisible(itemWithResId("$packageName:id/clearHostnameTextButton"))
128     fun clickSearchLoginButton() {
129         Log.i(TAG, "clickSearchLoginButton: Trying to click the search logins button")
130         itemWithResId("$packageName:id/search").click()
131         Log.i(TAG, "clickSearchLoginButton: Clicked the search logins button")
132     }
134     fun clickSavedLoginsChevronIcon() {
135         Log.i(TAG, "clickSavedLoginsChevronIcon: Trying to click the \"Saved logins\" chevron button")
136         itemWithResId("$packageName:id/toolbar_chevron_icon").click()
137         Log.i(TAG, "clickSavedLoginsChevronIcon: Clicked the \"Saved logins\" chevron button")
138     }
140     fun verifyLoginsSortingOptions() {
141         assertUIObjectExists(itemContainingText(getStringResource(R.string.saved_logins_sort_strategy_alphabetically)))
142         assertUIObjectExists(itemContainingText(getStringResource(R.string.saved_logins_sort_strategy_last_used)))
143     }
145     fun clickLastUsedSortingOption() {
146         Log.i(TAG, "clickLastUsedSortingOption: Trying to click the \"Last used\" sorting option")
147         itemContainingText(getStringResource(R.string.saved_logins_sort_strategy_last_used)).click()
148         Log.i(TAG, "clickLastUsedSortingOption: Clicked the \"Last used\" sorting option")
149     }
151     fun verifySortedLogin(position: Int, loginTitle: String) =
152         assertUIObjectExists(
153             itemWithClassNameAndIndex(className = "android.view.ViewGroup", index = position)
154                 .getChild(
155                     UiSelector()
156                         .resourceId("$packageName:id/webAddressView")
157                         .textContains(loginTitle),
158                 ),
159         )
161     fun searchLogin(searchTerm: String) {
162         Log.i(TAG, "searchLogin: Trying to set the search bar text to: $searchTerm")
163         itemWithResId("$packageName:id/search").setText(searchTerm)
164         Log.i(TAG, "searchLogin: Search bar text was set to: $searchTerm")
165     }
167     fun verifySavedLoginsSectionUsername(username: String) =
168         mDevice.waitNotNull(Until.findObjects(By.text(username)))
170     fun verifyLoginItemUsername(username: String) = assertUIObjectExists(itemContainingText(username))
172     fun verifyNotSavedLoginFromPrompt() {
173         Log.i(TAG, "verifyNotSavedLoginFromPrompt: Trying to verify that \"test@example.com\" does not exist in the saved logins list")
174         onView(withText("test@example.com"))
175             .check(ViewAssertions.doesNotExist())
176         Log.i(TAG, "verifyNotSavedLoginFromPrompt: Verified that \"test@example.com\" does not exist in the saved logins list")
177     }
179     fun verifyLocalhostExceptionAdded() {
180         Log.i(TAG, "verifyLocalhostExceptionAdded: Trying to verify that \"localhost\" is visible in the exceptions list")
181         onView(withText(containsString("localhost")))
182             .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
183         Log.i(TAG, "verifyLocalhostExceptionAdded: Verified that \"localhost\" is visible in the exceptions list")
184     }
186     fun viewSavedLoginDetails(loginUserName: String) {
187         Log.i(TAG, "viewSavedLoginDetails: Trying to click $loginUserName saved login")
188         onView(withText(loginUserName)).click()
189         Log.i(TAG, "viewSavedLoginDetails: Clicked $loginUserName saved login")
190     }
192     fun clickThreeDotButton(activityTestRule: HomeActivityIntentTestRule) {
193         Log.i(TAG, "clickThreeDotButton: Trying to click the three dot button")
194         openActionBarOverflowOrOptionsMenu(activityTestRule.activity)
195         Log.i(TAG, "clickThreeDotButton: Clicked the three dot button")
196     }
198     fun clickEditLoginButton() {
199         Log.i(TAG, "clickEditLoginButton: Trying to click the \"Edit\" button")
200         itemContainingText("Edit").click()
201         Log.i(TAG, "clickEditLoginButton: Clicked the \"Edit\" button")
202     }
204     fun clickDeleteLoginButton() {
205         Log.i(TAG, "clickDeleteLoginButton: Trying to click the \"Delete\" button")
206         itemContainingText("Delete").click()
207         Log.i(TAG, "clickDeleteLoginButton: Clicked the \"Delete\" button")
208     }
210     fun verifyLoginDeletionPrompt() =
211         assertUIObjectExists(itemContainingText(getStringResource(R.string.login_deletion_confirmation)))
213     fun clickConfirmDeleteLogin() {
214         Log.i(TAG, "clickConfirmDeleteLogin: Trying to click the \"Delete\" dialog button")
215         onView(withId(android.R.id.button1)).inRoot(RootMatchers.isDialog()).click()
216         Log.i(TAG, "clickConfirmDeleteLogin: Clicked the \"Delete\" dialog button")
217     }
219     fun clickCancelDeleteLogin() {
220         Log.i(TAG, "clickCancelDeleteLogin: Trying to click the \"Cancel\" dialog button")
221         onView(withId(android.R.id.button2)).inRoot(RootMatchers.isDialog()).click()
222         Log.i(TAG, "clickCancelDeleteLogin: Clicked the \"Cancel\" dialog button")
223     }
225     fun setNewUserName(userName: String) {
226         Log.i(TAG, "setNewUserName: Trying to set \"Username\" text box to: $userName")
227         usernameTextInput().setText(userName)
228         Log.i(TAG, "setNewUserName: \"Username\" text box was set to: $userName")
229     }
231     fun clickClearUserNameButton() {
232         Log.i(TAG, "clickClearUserNameButton: Trying to click the clear username button")
233         itemWithResId("$packageName:id/clearUsernameTextButton").click()
234         Log.i(TAG, "clickClearUserNameButton: Clicked the clear username button")
235     }
237     fun setNewPassword(password: String) {
238         Log.i(TAG, "setNewPassword: Trying to set \"Password\" text box to: $password")
239         passwordTextInput().setText(password)
240         Log.i(TAG, "setNewPassword: \"Password\" text box was set to: $password")
241     }
243     fun clickClearPasswordButton() {
244         Log.i(TAG, "clickClearPasswordButton: Trying to click the clear password button")
245         itemWithResId("$packageName:id/clearPasswordTextButton").click()
246         Log.i(TAG, "clickClearPasswordButton: Clicked the clear password button")
247     }
249     fun saveEditedLogin() {
250         Log.i(TAG, "saveEditedLogin: Trying to click the toolbar save button")
251         itemWithResId("$packageName:id/save_login_button").click()
252         Log.i(TAG, "saveEditedLogin: Clicked the toolbar save button")
253     }
255     fun verifySaveLoginButtonIsEnabled(isEnabled: Boolean) =
256         assertUIObjectExists(
257             checkedItemWithResId("$packageName:id/save_login_button", isChecked = true),
258             exists = isEnabled,
259         )
261     fun revealPassword() {
262         Log.i(TAG, "revealPassword: Trying to click the reveal password button")
263         onView(withId(R.id.revealPasswordButton)).click()
264         Log.i(TAG, "revealPassword: Clicked the reveal password button")
265     }
267     fun verifyPasswordSaved(password: String) {
268         Log.i(TAG, "verifyPasswordSaved: Trying to verify that the \"Password\" text box is set to $password")
269         onView(withId(R.id.passwordText)).check(matches(withText(password)))
270         Log.i(TAG, "verifyPasswordSaved: Verified that the \"Password\" text box is set to $password")
271     }
273     fun verifyUserNameRequiredErrorMessage() =
274         assertUIObjectExists(itemContainingText(getStringResource(R.string.saved_login_username_required)))
276     fun verifyPasswordRequiredErrorMessage() =
277         assertUIObjectExists(itemContainingText(getStringResource(R.string.saved_login_password_required)))
279     fun clickGoBackButton() = goBackButton().click()
281     fun clickCopyUserNameButton() =
282         itemWithResId("$packageName:id/copyUsername").also {
283             Log.i(TAG, "clickCopyUserNameButton: Waiting for $waitingTime ms for the copy username button to exist")
284             it.waitForExists(waitingTime)
285             Log.i(TAG, "clickCopyUserNameButton: Waited for $waitingTime ms for the copy username button to exist")
286             Log.i(TAG, "clickCopyUserNameButton:Trying to click the copy username button")
287             it.click()
288             Log.i(TAG, "clickCopyUserNameButton:Clicked the copy username button")
289         }
291     fun clickCopyPasswordButton() =
292         itemWithResId("$packageName:id/copyPassword").also {
293             Log.i(TAG, "clickCopyPasswordButton: Waiting for $waitingTime ms for the copy password button to exist")
294             it.waitForExists(waitingTime)
295             Log.i(TAG, "clickCopyPasswordButton: Waited for $waitingTime ms for the copy password button to exist")
296             Log.i(TAG, "clickCopyPasswordButton:Trying to click the copy password button")
297             it.click()
298             Log.i(TAG, "clickCopyPasswordButton:Clicked the copy password button")
299         }
301     class Transition {
302         fun goBack(interact: SettingsSubMenuLoginsAndPasswordRobot.() -> Unit): SettingsSubMenuLoginsAndPasswordRobot.Transition {
303             Log.i(TAG, "goBack: Trying to click the navigate up button")
304             goBackButton().perform(ViewActions.click())
305             Log.i(TAG, "goBack: Clicked the navigate up button")
307             SettingsSubMenuLoginsAndPasswordRobot().interact()
308             return SettingsSubMenuLoginsAndPasswordRobot.Transition()
309         }
311         fun goBackToSavedLogins(interact: SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot.() -> Unit): SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot.Transition {
312             Log.i(TAG, "goBackToSavedLogins: Trying to click the navigate up button")
313             goBackButton().perform(ViewActions.click())
314             Log.i(TAG, "goBackToSavedLogins: Clicked the navigate up button")
316             SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot().interact()
317             return SettingsSubMenuLoginsAndPasswordsSavedLoginsRobot.Transition()
318         }
320         fun goToSavedWebsite(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition {
321             Log.i(TAG, "goToSavedWebsite: Trying to click the open web site button")
322             openWebsiteButton().click()
323             Log.i(TAG, "goToSavedWebsite: Clicked the open web site button")
325             BrowserRobot().interact()
326             return BrowserRobot.Transition()
327         }
328     }
331 private fun goBackButton() =
332     onView(CoreMatchers.allOf(ViewMatchers.withContentDescription("Navigate up")))
334 private fun openWebsiteButton() = onView(withId(R.id.openWebAddress))
336 private fun siteHeader() = itemWithResId("$packageName:id/hostnameHeaderText")
337 private fun siteTextInput() = itemWithResId("$packageName:id/hostnameText")
338 private fun siteDescription() = itemContainingText(getStringResource(R.string.add_login_hostname_invalid_text_3))
339 private fun siteTextInputHint() = onView(withId(R.id.hostnameText))
340 private fun usernameHeader() = itemWithResId("$packageName:id/usernameHeader")
341 private fun usernameTextInput() = itemWithResId("$packageName:id/usernameText")
342 private fun passwordHeader() = itemWithResId("$packageName:id/passwordHeader")
343 private fun passwordTextInput() = itemWithResId("$packageName:id/passwordText")