blob: 58bf8fbf8c417bd1fb28f5d3f2cb54fc639dd126 [file] [log] [blame]
# 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)