| # Copyright 2017 Google Inc. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| """Provides all settings related actions. |
| |
| """ |
| |
| from __future__ import absolute_import |
| import abc |
| import time |
| |
| import action_error |
| from appium_util import path_constants |
| from appium_util import timeout_util |
| import element |
| import input as input_module |
| import scroll |
| import step as step_module |
| import tap |
| import xml.etree.ElementTree as ET |
| import six |
| |
| # Settings paths. |
| _ANDROID_CLEAR_BUTTON_PATH = 'clear_button' |
| _ANDROID_CLEAR_BROWSING_DATA_PATH = 'clear_browsing_data_button' |
| _ANDROID_FIRST_ACCOUNT_XPATH = ( |
| '//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/' |
| 'android.view.View[1]/android.widget.FrameLayout[2]/' |
| 'android.widget.LinearLayout[1]/android.widget.ListView[1]/' |
| 'android.widget.LinearLayout[1]') |
| _ANDROID_MORE_BUTTON_PATH = 'more_button' |
| _ANDROID_POSITIVE_BUTTON_PATH = 'positive_button' |
| _ANDROID_SIGN_IN_ICON_PATH = 'icon' |
| |
| _IOS_CLEAR_BROWSING_DATA_PATH = 'Clear Browsing Data' |
| _IOS_CLEAR_BROWSING_DATA_BUTTON_ID = 'kClearBrowsingDataButtonIdentifier' |
| _IOS_DELETE_BROWSING_DATA_PATH = 'Delete browsing data' |
| |
| _ACCOUNT_SIGNOUT_CELL_PATH = 'kSettingsAccountsTableViewId' |
| _ACCOUNT_CELL_PATH = 'kSettingsAccountCellId' |
| _SIGNIN_CELL_PATH = 'kSettingsSignInCellId' |
| _IOS_CONTINUE_AS_BUTTON_PATH= 'WebSigninPrimaryButtonAccessibilityIdentifier' |
| _SIGNIN_CELL_PROMO_PATH = '//XCUIElementTypeTable[@name="kSettingsTableViewId"]/XCUIElementTypeCell[1]' |
| _CLOSE_BUTTON_PATH = 'ic_close' |
| _COLLECTIONVIEW_PATH = 'kSettingsTableViewId' |
| _HISTORY_PATH = 'History' |
| _IMPORT_DATA_CELL_PATH = 'kImportDataKeepSeparateCellId' |
| _PASSWORD_PATH = 'Enter your password' |
| _PRIVACY_CELL_PATH = 'kSettingsPrivacyCellId' |
| _REMOVE_BUTTON_PATH = 'RemoveAlertAction' |
| _SETTINGS_CELL_PATH = 'Settings' |
| _USERNAME_PATH = 'Email or phone' |
| |
| _FIRST_COLLECTION_CELL_PATH = ( |
| '//XCUIElementTypeTable["kSettingsTableViewId"]/' |
| 'XCUIElementTypeCell[1]') |
| _IOS_GOT_IT_BUTTON_PATH = 'Ok, Got it' |
| _IOS_YES_IMIN_BUTTTON_PATH= "PromoStylePrimaryActionAccessibilityIdentifier" |
| _IOS_CONTINUE_BUTTON_PATH = 'kImportDataContinueButtonId' |
| _IOS_NEXT_BUTTON_PATH = '(//XCUIElementTypeButton[@name="Next"])[1]' |
| _IOS_FIRST_SETTINGS_ACCOUNT_CELL_PATH = ( |
| '//XCUIElementTypeTable["kSettingsAccountsTableViewId"]//' |
| 'XCUIElementTypeCell[contains(@name, "@")]') |
| |
| _TEXT_XPATH = path_constants.CONTAINS_TEXT_XPATH_PATTERN |
| |
| # Maximum time in seconds to wait for an element that is expected to be absent. |
| _TIMEOUT = timeout_util.WAIT_FOR_ABSENCE_TIMEOUT |
| |
| |
| class Settings(six.with_metaclass(abc.ABCMeta, object)): |
| """Abstract base class for settings related actions. |
| |
| """ |
| |
| @abc.abstractmethod |
| def AddAccount(self, driver_provider, step): |
| """Adds an account from Chrome Add Account screen. |
| |
| Should be called from Chrome Sign in screen. |
| |
| Args: |
| driver_provider: An instance of DriverProvider class. |
| step: A Step tuple. |
| """ |
| pass |
| |
| @abc.abstractmethod |
| def RemoveAllAccounts(self, driver_provider, unused_step): |
| """Remove all accounts from the app. |
| |
| Should be called from the Settings screen, giving more flexibility to remove |
| all accounts regardless of the current state of the app. |
| |
| Args: |
| driver_provider: An instance of DriverProvider class. |
| unused_step: A Step tuple. |
| """ |
| pass |
| |
| @abc.abstractmethod |
| def TapOnFirstAccountInSettingsAccounts(self, driver_provider, unused_step): |
| """Taps on the first account in the settings accounts view. |
| |
| Args: |
| driver_provider: An instance of DriverProvider class. |
| unused_step: A Step tuple. |
| """ |
| pass |
| |
| @abc.abstractmethod |
| def ClearBrowsingData(self, driver_provider, unused_step): |
| """Clears all browsing data. |
| |
| Should be called from the Settings screen, giving more flexibility to clear |
| all browsing data regardless of the current state of the app. |
| |
| Args: |
| driver_provider: An instance of DriverProvider class. |
| unused_step: A Step tuple. |
| """ |
| pass |
| |
| |
| class IOSSettings(Settings): |
| """Provides iOS implementation for settings related actions. |
| |
| """ |
| |
| def AddAccount(self, driver_provider, step): |
| """See description in base class. |
| |
| Args: |
| driver_provider: An instance of DriverProvider class. |
| step: A Step tuple. |
| """ |
| # Enter Username. |
| username, password = step.value.split(',') |
| input_module.IOSInput().TypeUsingLocator( |
| driver_provider, step_module.ID, _USERNAME_PATH, username, |
| timeout_util.WAIT_FOR_PRESENCE_TIMEOUT) |
| # Tap on Next button. |
| tap.IOSTap().TapOnElementByXPATH(driver_provider, _IOS_NEXT_BUTTON_PATH) |
| time.sleep(1) |
| # Enter Password. |
| input_module.IOSInput().TypeUsingLocator(driver_provider, step_module.ID, |
| _PASSWORD_PATH, password, _TIMEOUT) |
| # Tap on Next button. |
| tap.IOSTap().TapOnElementByXPATH(driver_provider, _IOS_NEXT_BUTTON_PATH) |
| tap.IOSTap().TapOnElementByID(driver_provider, _IOS_YES_IMIN_BUTTTON_PATH, |
| timeout_util.WAIT_FOR_PRESENCE_TIMEOUT) |
| # Handle when import data flow UI is presented. |
| if element.IOSElement().IsElementBySeleniumLocatorPresent( |
| driver_provider, step_module.ID, _IMPORT_DATA_CELL_PATH, |
| timeout_util.WAIT_FOR_PRESENCE_TIMEOUT): |
| tap.IOSTap().TapOnElementByID(driver_provider, _IMPORT_DATA_CELL_PATH) |
| tap.IOSTap().TapOnElementByID(driver_provider, _IOS_CONTINUE_BUTTON_PATH) |
| |
| def RemoveAllAccounts(self, driver_provider, unused_step): |
| # Check if screen contains SignInPromo: |
| ele = element.IOSElement().IsElementBySeleniumLocatorPresent( |
| driver_provider, 'id', _SIGNIN_CELL_PATH, timeout_util.WAIT_FOR_PRESENCE_TIMEOUT) |
| if ele: |
| tap.IOSTap().TapOnElementByID(driver_provider, _SIGNIN_CELL_PATH) |
| # If accounts are present on the device, then sign in to chrome prompt |
| # is displayed. |
| continue_as = element.IOSElement().IsElementBySeleniumLocatorPresent( |
| driver_provider, 'id', _IOS_CONTINUE_AS_BUTTON_PATH, timeout_util.WAIT_FOR_PRESENCE_TIMEOUT) |
| if continue_as: |
| tap.IOSTap().TapOnElementByID(driver_provider, _IOS_CONTINUE_AS_BUTTON_PATH) |
| tap.IOSTap().TapOnElementByID(driver_provider, _IOS_YES_IMIN_BUTTTON_PATH) |
| time.sleep(2) |
| # if user already signed in |
| ele = element.IOSElement().IsElementBySeleniumLocatorPresent( |
| driver_provider, 'id', _ACCOUNT_CELL_PATH, timeout_util.WAIT_FOR_PRESENCE_TIMEOUT) |
| if ele: |
| tap.IOSTap().TapOnElementByXPATH(driver_provider, _SIGNIN_CELL_PROMO_PATH) |
| screen_element = element.IOSElement().GetElementBySeleniumLocator(driver_provider, 'id', |
| 'ManageSyncTableViewAccessibilityIdentifier', |
| timeout=None) |
| scroll.IOSScroll().DragInsideWithOptions(driver_provider, |
| screen_element, step_module.Point(0.5, 0.9), |
| step_module.Point(0.5, 0.1), 2000) |
| time.sleep(1) |
| tap.IOSTap().TapOnElementByXPATH(driver_provider, |
| '//XCUIElementTypeCell[@name="Manage accounts on this deviceā¦"]') |
| self._RemoveAccounts(driver_provider) |
| time.sleep(1) |
| return |
| # If no accounts are available in device |
| if element.IOSElement().IsElementBySeleniumLocatorPresent(driver_provider, 'id', 'Create account', |
| timeout_util.WAIT_FOR_PRESENCE_TIMEOUT): |
| tap.IOSTap().TapOnElementByID(driver_provider, 'close') |
| return |
| raise action_error.TooManyElementsFoundError('Failed to remove all accounts') |
| |
| def TapOnFirstAccountInSettingsAccounts(self, driver_provider, unused_step): |
| """See description in base class. |
| |
| Args: |
| driver_provider: An instance of DriverProvider class. |
| unused_step: A Step tuple. |
| """ |
| tap.IOSTap().TapOnElementByXPATH(driver_provider, |
| _IOS_FIRST_SETTINGS_ACCOUNT_CELL_PATH, |
| timeout_util.WAIT_FOR_PRESENCE_TIMEOUT) |
| |
| def ClearBrowsingData(self, driver_provider, unused_step): |
| """See description in base class. |
| |
| Args: |
| driver_provider: An instance of DriverProvider class. |
| unused_step: A Step tuple. |
| """ |
| tap.IOSTap().TapOnElementByID( |
| driver_provider, _PRIVACY_CELL_PATH) |
| tap.IOSTap().TapOnElementByID(driver_provider, |
| _IOS_DELETE_BROWSING_DATA_PATH) |
| time.sleep(1) |
| tap.IOSTap().TapOnElementByID(driver_provider, |
| _IOS_CLEAR_BROWSING_DATA_BUTTON_ID) |
| tap.IOSTap().TapOnElementByID(driver_provider, 'Delete browsing dataAlertAction') |
| time.sleep(3) |
| |
| def _RemoveAccounts(self, driver_provider): |
| """Removes all accounts from Chrome account info screen. |
| |
| Args: |
| driver_provider: An instance of DriverProvider class. |
| """ |
| time.sleep(1) |
| accounts = element.IOSElement().GetElementsByID( |
| driver_provider, 'chevron') |
| allaccounts = len(accounts) |
| for account in accounts: |
| tap.IOSTap().TapOnElementByXPATH(driver_provider, |
| '(//XCUIElementTypeTable["SettingsAccountsTableViewId"]/XCUIElementTypeCell[' + |
| str(allaccounts) + '])[2]', timeout_util.WAIT_FOR_PRESENCE_TIMEOUT) |
| tap.IOSTap().TapOnElementByID(driver_provider, 'Remove from this deviceAlertAction') |
| tap.IOSTap().TapOnElementByID(driver_provider, _REMOVE_BUTTON_PATH) |
| time.sleep(1) |
| allaccounts = allaccounts - 1 |
| |
| |
| class AndroidSettings(Settings): |
| """Provides Android implementation for settings related actions. |
| |
| """ |
| |
| def AddAccount(self, driver_provider, step): |
| """See description in base class. |
| |
| Args: |
| driver_provider: An instance of DriverProvider class. |
| step: A Step tuple. |
| """ |
| # TODO(crbug.com/651234): Enter method implementation here. |
| return |
| |
| def RemoveAllAccounts(self, driver_provider, unused_step): |
| """See description in base class. |
| |
| Args: |
| driver_provider: An instance of DriverProvider class. |
| unused_step: A Step tuple. |
| """ |
| # TODO(crbug.com/651234): Enter method implementation here. |
| return |
| |
| def SignInWithAccountAlreadyOnDevice(self, driver_provider, step): |
| """Signs into Chrome when an Account is already on the device. |
| |
| Should be called from the Settings Screen. |
| |
| Args: |
| driver_provider: An instance of DriverProvider class. |
| step: A Step tuple. |
| """ |
| timeout = timeout_util.WAIT_FOR_PRESENCE_TIMEOUT |
| tap.AndroidTap().TapOnElementByID(driver_provider, |
| _ANDROID_SIGN_IN_ICON_PATH) |
| # Choose the desired account if one is provided. |
| if step.value: |
| tap.AndroidTap().TapOnElementByXPATH(driver_provider, |
| _TEXT_XPATH % step.value) |
| |
| tap.AndroidTap().TapOnElementByID(driver_provider, |
| _ANDROID_POSITIVE_BUTTON_PATH) |
| # This may or may not appear depending on screen size. |
| if element.AndroidElement().IsElementBySeleniumLocatorPresent( |
| driver_provider, step_module.ID, _ANDROID_MORE_BUTTON_PATH, timeout): |
| tap.AndroidTap().TapOnElementByID(driver_provider, |
| _ANDROID_MORE_BUTTON_PATH) |
| |
| tap.AndroidTap().TapOnElementByID(driver_provider, |
| _ANDROID_POSITIVE_BUTTON_PATH, timeout) |
| |
| def TapOnFirstAccountInSettingsAccounts(self, driver_provider, unused_step): |
| """See description in base class. |
| |
| Args: |
| driver_provider: An instance of DriverProvider class. |
| unused_step: A Step tuple. |
| """ |
| tap.AndroidTap().TapOnElementByXPATH(driver_provider, |
| _ANDROID_FIRST_ACCOUNT_XPATH, |
| timeout_util.WAIT_FOR_PRESENCE_TIMEOUT) |
| |
| def ClearBrowsingData(self, driver_provider, unused_step): |
| """See description in base class. |
| |
| Args: |
| driver_provider: An instance of DriverProvider class. |
| unused_step: A Step tuple. |
| """ |
| tap.AndroidTap().TapOnElementByXPATH(driver_provider, |
| _TEXT_XPATH % _HISTORY_PATH) |
| tap.AndroidTap().TapOnElementByID(driver_provider, |
| _ANDROID_CLEAR_BROWSING_DATA_PATH) |
| tap.AndroidTap().TapOnElementByID(driver_provider, |
| _ANDROID_CLEAR_BUTTON_PATH) |