Support sunset sync promo for RemoveAllAccounts & RemoveAccounts action

Bug:40283739,40255960

This changes the fix supports

1. Support new sunset sync promos and label changes
2. Supports new flow to remove signed in accounts

No-Try:true
No-Presubmit: true
Change-Id: I6998b71cc0d207dd5c9cb304f9f129ddfeb987eb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/tools/franky/+/6218102
Commit-Queue: Himabindu Vedantam <himabinduv@chromium.org>
Reviewed-by: Lindsay Pasricha <lindsayw@chromium.org>
Reviewed-by: Yue She <yueshe@google.com>
diff --git a/franky/actions/settings.py b/franky/actions/settings.py
index 428afb0..58bf8fb 100644
--- a/franky/actions/settings.py
+++ b/franky/actions/settings.py
@@ -49,14 +49,15 @@
 _ACCOUNT_SIGNOUT_CELL_PATH = 'kSettingsAccountsTableViewId'
 _ACCOUNT_CELL_PATH = 'kSettingsAccountCellId'
 _SIGNIN_CELL_PATH = 'kSettingsSignInCellId'
-_SIGNIN_CELL_PROMO_PATH = 'kSigninPromoViewId'
+_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 = 'Remove'
+_REMOVE_BUTTON_PATH = 'RemoveAlertAction'
 _SETTINGS_CELL_PATH = 'Settings'
 _USERNAME_PATH = 'Email or phone'
 
@@ -64,8 +65,8 @@
     '//XCUIElementTypeTable["kSettingsTableViewId"]/'
     'XCUIElementTypeCell[1]')
 _IOS_GOT_IT_BUTTON_PATH = 'Ok, Got it'
-_IOS_YES_IMIN_BUTTTON_PATH = "kConfirmationAccessibilityIdentifier"
-_IOS_CONTINUE_BUTTON_PATH = 'Continue'
+_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"]//'
@@ -166,175 +167,42 @@
         tap.IOSTap().TapOnElementByID(driver_provider, _IOS_CONTINUE_BUTTON_PATH)
 
   def RemoveAllAccounts(self, driver_provider, unused_step):
-    loop_count = 0
-    while loop_count < 20:
-      loop_count += 1
-      time.sleep(1)
-      pagesource = driver_provider.driver.page_source
-      tree = ET.fromstring(pagesource.encode('utf-8'))
-      #Check if screen contains SignInPromo:
-      xpath = './/XCUIElementTypeOther[@name="'+ _SIGNIN_CELL_PROMO_PATH +'"]'
-      ele =  tree.findall(xpath)
-      #Check if the element is present in the XMLTree.
-      #On IPads SignIn Promo is always Present but not Visible if the screen
-      # is in background.
-      if ele and ele[0].attrib['visible'] == 'true':
-          promo_cell_element = element.IOSElement().GetElementsByID(
-              driver_provider, _SIGNIN_CELL_PROMO_PATH)[0]
-          x = promo_cell_element.size.get('width') * 0.5
-          y = promo_cell_element.size.get('height') * 0.8
-          tap.IOSTap().TapWithOptions(driver_provider,
-                                      promo_cell_element, x, y)
-          continue
-      #Check If Unified Consent Screen is present
-      xpath = './/*[@name="kUnifiedConsentScrollViewIdentifier"]'
-      ele = tree.findall(xpath)
+      # Check if screen contains SignInPromo:
+      ele = element.IOSElement().IsElementBySeleniumLocatorPresent(
+          driver_provider, 'id', _SIGNIN_CELL_PATH, timeout_util.WAIT_FOR_PRESENCE_TIMEOUT)
       if ele:
-          # If "ADD ACCOUNT button is present that means there are no accounts
-          # present on the device.
-          # Tap Cancel to Dismiss the screen and exit while loop.
-          add_account_xpath = './/*[@name="kAddAccountAccessibilityIdentifier"]'
-          add_account_element = tree.findall(add_account_xpath)
-          if add_account_element:
-              tap.IOSTap().TapOnElementByID(driver_provider, 'kSkipSigninAccessibilityIdentifier')
-              return
-      #If accounts are present on the device, the Choose an account UI
-      # is displayed.
-      choose_account_xpath = './/*[@name="Choose an Account"]'
-      choose_account_element = tree.findall(choose_account_xpath)
-      if choose_account_element:
-          tap.IOSTap().TapOnElementByXPATH(driver_provider, '//XCUIElementTypeCell[1]')
-          tap.IOSTap().TapOnElementByID(driver_provider, "kConfirmationAccessibilityIdentifier")
-          continue
-      #If the user is already singed in.
-      xpath = './/*[@name="' + _ACCOUNT_CELL_PATH + '"]'
-      ele = tree.findall(xpath)
-      if ele and ele[0].attrib['visible'] == 'true':
-          tap.IOSTap().TapOnElementByID(driver_provider, _ACCOUNT_CELL_PATH)
-          continue
-      # Tap on Sign into Chrome cell if the user is not signed in.
-      # Handles a case with New Sign In Promo is not displayed.
-      xpath = './/*[@name="' +_SIGNIN_CELL_PATH +'"]'
-      ele = tree.findall(xpath)
-      if ele and ele[0].attrib['visible'] == 'true':
-         tap.IOSTap().TapOnElementByID(driver_provider, _SIGNIN_CELL_PATH)
-         continue
-
-      # All accounts are removed if Chrome Sign in screen is found.
-      # This is old flow (Without Unified Consent)
-      xpath = './/*[@name="' +_USERNAME_PATH +'"]'
-      ele = tree.findall(xpath)
-      if ele and ele[0].attrib['visible'] == 'true':
-          tap.IOSTap().TapOnElementByIDAtIndex(driver_provider,
-                                               _CLOSE_BUTTON_PATH, index=-1)
-          return
-      # User could be redirected to Chrome account info screen after taping
-      # on first cell on Settings screen if user was previously signed into
-      # Chrome.
-      xpath = './/*[@name="' + _ACCOUNT_SIGNOUT_CELL_PATH + '"]'
-      ele = tree.findall(xpath)
-      if ele and ele[0].attrib['visible'] == 'true':
-          self._RemoveFirstAccount(driver_provider)
-          continue
-
-      # Tap Continue button if displayed. OLD UI Case:
-      xpath = './/*[@name="'+_IOS_CONTINUE_BUTTON_PATH+'"]'
-      ele = tree.findall(xpath)
-      if ele:
-          tap.IOSTap().TapOnElementByID(driver_provider,
-                                        _IOS_CONTINUE_BUTTON_PATH)
-          continue
-
-      # Tap OK, Got It if displayed. OLD UI Case:
-      xpath = './/*[@name="'+_IOS_GOT_IT_BUTTON_PATH+'"]'
-      ele = tree.findall(xpath)
-      if ele:
-          tap.IOSTap().TapOnElementByID(driver_provider,
-                                        _IOS_GOT_IT_BUTTON_PATH)
-          tap.IOSTap().TapOnElementByXPATH(driver_provider,
-                                           _FIRST_COLLECTION_CELL_PATH)
-          self._RemoveFirstAccount(driver_provider)
-          continue
-
-      # Handle import data flow.
-      xpath = './/*[@name="' + _IMPORT_DATA_CELL_PATH + '"]'
-      ele = tree.findall(xpath)
-      if ele and ele[0].attrib['visible'] == 'true':
-          tap.IOSTap().TapOnElementByID(driver_provider,
-                                        _IMPORT_DATA_CELL_PATH)
-          tap.IOSTap().TapOnElementByID(driver_provider,
-                                        _IOS_CONTINUE_BUTTON_PATH)
-          #http://crbug/958823 Unified Consent with screen doesn't
-          # disable background elements. So wait few seconds before continue.
-          time.sleep(3)
-          continue
-
-    raise action_error.TooManyElementsFoundError(
-        'Exceeded loop count when trying to remove all accounts.')
-
-  # TODO(crbug/959903): Remove this method later.
-  def RemoveAllAccounts_OLD(self, driver_provider, unused_step):
-    """See description in base class.
-
-    Args:
-      driver_provider: An instance of DriverProvider class.
-      unused_step: A Step tuple.
-
-    Raises:
-      TooManyElementsFoundError: Excessive looping trying to remove accounts.
-    """
-    # Remove accounts from Chrome one by one until all are gone.
-    loop_count = 0
-    while loop_count < 25:
-      loop_count += 1
-      if element.IOSElement().IsElementBySeleniumLocatorPresent(
-          driver_provider, step_module.ID, _COLLECTIONVIEW_PATH, _TIMEOUT):
-        # Tap on the account cell if the user is signed in.
-        if element.IOSElement().IsElementBySeleniumLocatorPresent(
-            driver_provider, step_module.ID, _ACCOUNT_CELL_PATH, _TIMEOUT):
-          tap.IOSTap().TapOnElementByID(driver_provider, _ACCOUNT_CELL_PATH)
-        # If the new sign in Promo is displayed.
-        elif element.IOSElement().IsElementBySeleniumLocatorPresent(
-            driver_provider, step_module.ID, _SIGNIN_CELL_PROMO_PATH, _TIMEOUT):
-          promo_cell_element = element.IOSElement().GetElementsByID(
-              driver_provider, _SIGNIN_CELL_PROMO_PATH)[0]
-          x = promo_cell_element.size.get('width') * 0.5
-          y = promo_cell_element.size.get('height') * 0.8
-          tap.IOSTap().TapWithOptions(driver_provider, promo_cell_element, x, y)
-        # Tap on Sign in to Chrome cell if the user is not signed in.
-        else:
           tap.IOSTap().TapOnElementByID(driver_provider, _SIGNIN_CELL_PATH)
-      # All accounts are removed if Chrome Sign in screen is found.
-      if element.IOSElement().IsElementBySeleniumLocatorPresent(
-          driver_provider, step_module.ID, _USERNAME_PATH,
-          timeout_util.WAIT_FOR_PRESENCE_TIMEOUT):
-        tap.IOSTap().TapOnElementByIDAtIndex(
-            driver_provider, _CLOSE_BUTTON_PATH, index=-1)
-        return
-      # User could be redirected to Chrome account info screen after taping on
-      # first cell on Settings screen if user was previously signed into Chrome.
-      if element.IOSElement().IsElementBySeleniumLocatorPresent(
-          driver_provider, step_module.ID, _ACCOUNT_SIGNOUT_CELL_PATH,
-          _TIMEOUT):
-        self._RemoveFirstAccount(driver_provider)
-      # User could be redirected to Sign in screen after taping on the first
-      # cell on Settings screen if user was previously signed out of Chrome.
-      else:
-        tap.IOSTap().TapOnElementByID(driver_provider,
-                                      _IOS_CONTINUE_BUTTON_PATH)
-        # Handle import data flow.
-        if element.IOSElement().IsElementBySeleniumLocatorPresent(
-            driver_provider, step_module.ID, _IMPORT_DATA_CELL_PATH, _TIMEOUT):
-          tap.IOSTap().TapOnElementByID(driver_provider, _IMPORT_DATA_CELL_PATH)
-          tap.IOSTap().TapOnElementByID(driver_provider,
-                                        _IOS_CONTINUE_BUTTON_PATH)
-        # Carry on with Sign in flow.
-        tap.IOSTap().TapOnElementByID(driver_provider, _IOS_GOT_IT_BUTTON_PATH)
-        tap.IOSTap().TapOnElementByXPATH(driver_provider,
-                                         _FIRST_COLLECTION_CELL_PATH)
-        self._RemoveFirstAccount(driver_provider)
-    raise action_error.TooManyElementsFoundError(
-        'Exceeded loop count when trying to remove all accounts.')
+      # 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.
@@ -364,17 +232,24 @@
     tap.IOSTap().TapOnElementByID(driver_provider, 'Delete browsing dataAlertAction')
     time.sleep(3)
 
-  def _RemoveFirstAccount(self, driver_provider):
-    """Removes the first account from Chrome account info screen.
+  def _RemoveAccounts(self, driver_provider):
+    """Removes all accounts from Chrome account info screen.
 
     Args:
       driver_provider: An instance of DriverProvider class.
     """
-    self.TapOnFirstAccountInSettingsAccounts(driver_provider, unused_step=None)
     time.sleep(1)
-    tap.IOSTap().TapOnElementByID(driver_provider, 'Remove Account from this Device')
-    tap.IOSTap().TapOnElementByID(driver_provider, _REMOVE_BUTTON_PATH)
-    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):