284 lines
11 KiB
Python
284 lines
11 KiB
Python
from types import SimpleNamespace
|
|
from appium.webdriver.common.appiumby import AppiumBy as By
|
|
from selenium.webdriver.common.keys import Keys
|
|
|
|
from helpers.SetupClientHelper import get_current_user_sync_path
|
|
from helpers.AppHelper import app
|
|
|
|
|
|
class SyncConnectionWizard:
|
|
CHOOSE_LOCAL_SYNC_FOLDER = SimpleNamespace(
|
|
by=By.ACCESSIBILITY_ID, selector="localFolderLineEdit"
|
|
)
|
|
BACK_BUTTON = SimpleNamespace(by=By.NAME, selector="< Back")
|
|
NEXT_BUTTON = SimpleNamespace(by=By.NAME, selector="Next >")
|
|
SELECTIVE_SYNC_ROOT_FOLDER = SimpleNamespace(by=None, selector=None)
|
|
ADD_SYNC_CONNECTION_BUTTON = SimpleNamespace(
|
|
by=By.XPATH, selector="//dialog[@name='Add Space']//*[@name='Add Space']"
|
|
)
|
|
REMOTE_FOLDER_TREE = SimpleNamespace(by=None, selector=None)
|
|
SELECTIVE_SYNC_TREE_HEADER = SimpleNamespace(by=None, selector=None)
|
|
CANCEL_FOLDER_SYNC_CONNECTION_WIZARD = SimpleNamespace(
|
|
by=By.NAME, selector="Cancel"
|
|
)
|
|
SPACES_LIST = SimpleNamespace(by=By.NAME, selector="Spaces list")
|
|
SPACE_NAME_SELECTOR = SimpleNamespace(by=By.NAME, selector="{space_name},")
|
|
CREATE_REMOTE_FOLDER_BUTTON = SimpleNamespace(by=None, selector=None)
|
|
CREATE_REMOTE_FOLDER_INPUT = SimpleNamespace(by=None, selector=None)
|
|
CREATE_REMOTE_FOLDER_CONFIRM_BUTTON = SimpleNamespace(by=None, selector=None)
|
|
REFRESH_BUTTON = SimpleNamespace(by=None, selector=None)
|
|
REMOTE_FOLDER_SELECTION_INPUT = SimpleNamespace(by=None, selector=None)
|
|
ADD_FOLDER_SYNC_BUTTON = SimpleNamespace(by=None, selector=None)
|
|
WARN_LABEL = SimpleNamespace(by=None, selector=None)
|
|
CHOOSE_WHAT_TO_SYNC_FOLDER_TREE = SimpleNamespace(by=None, selector=None)
|
|
|
|
@staticmethod
|
|
def set_sync_path_oc(sync_path):
|
|
if not sync_path:
|
|
sync_path = get_current_user_sync_path()
|
|
sync_path_input = app().find_element(
|
|
SyncConnectionWizard.CHOOSE_LOCAL_SYNC_FOLDER.by,
|
|
SyncConnectionWizard.CHOOSE_LOCAL_SYNC_FOLDER.selector,
|
|
)
|
|
sync_path_input.clear()
|
|
sync_path_input.send_keys(sync_path)
|
|
SyncConnectionWizard.next_step()
|
|
|
|
@staticmethod
|
|
def set_sync_path(sync_path=""):
|
|
SyncConnectionWizard.set_sync_path_oc(sync_path)
|
|
|
|
@staticmethod
|
|
def next_step():
|
|
next_button = app().find_element(
|
|
SyncConnectionWizard.NEXT_BUTTON.by,
|
|
SyncConnectionWizard.NEXT_BUTTON.selector,
|
|
)
|
|
if not next_button.is_enabled():
|
|
raise AssertionError("Next button is not enabled")
|
|
next_button.click()
|
|
|
|
@staticmethod
|
|
def back():
|
|
squish.clickButton(squish.waitForObject(SyncConnectionWizard.BACK_BUTTON))
|
|
|
|
@staticmethod
|
|
def select_remote_destination_folder(folder):
|
|
squish.mouseClick(
|
|
squish.waitForObjectItem(SyncConnectionWizard.REMOTE_FOLDER_TREE, folder)
|
|
)
|
|
SyncConnectionWizard.next_step()
|
|
|
|
@staticmethod
|
|
def deselect_all_remote_folders():
|
|
element = app().find_element(
|
|
SyncConnectionWizard.ADD_SYNC_CONNECTION_BUTTON.by,
|
|
SyncConnectionWizard.ADD_SYNC_CONNECTION_BUTTON.selector,
|
|
)
|
|
element.send_keys(Keys.ARROW_DOWN)
|
|
element.native_send_keys(Keys.SPACE) # uncheck the root folder
|
|
|
|
@staticmethod
|
|
def sort_by(header_text):
|
|
squish.mouseClick(
|
|
squish.waitForObject(
|
|
{
|
|
"container": SyncConnectionWizard.SELECTIVE_SYNC_TREE_HEADER,
|
|
"text": header_text,
|
|
"type": "HeaderViewItem",
|
|
"visible": True,
|
|
}
|
|
)
|
|
)
|
|
|
|
@staticmethod
|
|
def add_sync_connection():
|
|
app().find_element(
|
|
SyncConnectionWizard.ADD_SYNC_CONNECTION_BUTTON.by,
|
|
SyncConnectionWizard.ADD_SYNC_CONNECTION_BUTTON.selector,
|
|
).click()
|
|
|
|
@staticmethod
|
|
def get_item_name_from_row(row_index):
|
|
folder_row = {
|
|
"row": row_index,
|
|
"container": SyncConnectionWizard.SELECTIVE_SYNC_ROOT_FOLDER,
|
|
"type": "QModelIndex",
|
|
}
|
|
return str(squish.waitForObjectExists(folder_row).displayText)
|
|
|
|
@staticmethod
|
|
def is_root_folder_checked():
|
|
state = squish.waitForObject(SyncConnectionWizard.SELECTIVE_SYNC_ROOT_FOLDER)[
|
|
"checkState"
|
|
]
|
|
return state == "checked"
|
|
|
|
@staticmethod
|
|
def cancel_folder_sync_connection_wizard():
|
|
app().find_element(
|
|
SyncConnectionWizard.CANCEL_FOLDER_SYNC_CONNECTION_WIZARD.by,
|
|
SyncConnectionWizard.CANCEL_FOLDER_SYNC_CONNECTION_WIZARD.selector,
|
|
).click()
|
|
|
|
@staticmethod
|
|
def select_space(space_name):
|
|
spaces_list = app().find_element(
|
|
SyncConnectionWizard.SPACES_LIST.by,
|
|
SyncConnectionWizard.SPACES_LIST.selector,
|
|
)
|
|
space_item = spaces_list.find_element(
|
|
SyncConnectionWizard.SPACE_NAME_SELECTOR.by,
|
|
SyncConnectionWizard.SPACE_NAME_SELECTOR.selector.format(
|
|
space_name=space_name
|
|
),
|
|
)
|
|
# ISSUE: https://github.com/opencloud-eu/desktop/pull/879
|
|
# Cannot select space by click event
|
|
# Select space using keyboard events as a workaround
|
|
# TODO: Remove 'send_keys' and uncomment 'click' action
|
|
space_item.send_keys(Keys.ARROW_DOWN)
|
|
# space_item.click()
|
|
if space_item.get_attribute("selected") != "true":
|
|
raise AssertionError("Failed to select the space: " + space_name)
|
|
|
|
@staticmethod
|
|
def sync_space(space_name):
|
|
SyncConnectionWizard.set_sync_path(get_current_user_sync_path())
|
|
SyncConnectionWizard.select_space(space_name)
|
|
SyncConnectionWizard.next_step()
|
|
SyncConnectionWizard.add_sync_connection()
|
|
|
|
@staticmethod
|
|
def create_folder_in_remote_destination(folder_name):
|
|
squish.clickButton(
|
|
squish.waitForObject(SyncConnectionWizard.CREATE_REMOTE_FOLDER_BUTTON)
|
|
)
|
|
squish.type(
|
|
squish.waitForObject(SyncConnectionWizard.CREATE_REMOTE_FOLDER_INPUT),
|
|
folder_name,
|
|
)
|
|
squish.clickButton(
|
|
squish.waitForObject(
|
|
SyncConnectionWizard.CREATE_REMOTE_FOLDER_CONFIRM_BUTTON
|
|
)
|
|
)
|
|
|
|
@staticmethod
|
|
def refresh_remote():
|
|
squish.clickButton(squish.waitForObject(SyncConnectionWizard.REFRESH_BUTTON))
|
|
|
|
@staticmethod
|
|
def is_remote_folder_selected(folder_selector):
|
|
return squish.waitForObjectExists(folder_selector).selected
|
|
|
|
@staticmethod
|
|
def open_sync_connection_wizard():
|
|
squish.mouseClick(
|
|
squish.waitForObject(SyncConnectionWizard.ADD_FOLDER_SYNC_BUTTON)
|
|
)
|
|
|
|
@staticmethod
|
|
def get_local_sync_path():
|
|
return str(
|
|
squish.waitForObjectExists(
|
|
SyncConnectionWizard.CHOOSE_LOCAL_SYNC_FOLDER
|
|
).displayText
|
|
)
|
|
|
|
@staticmethod
|
|
def get_warn_label():
|
|
return str(squish.waitForObjectExists(SyncConnectionWizard.WARN_LABEL).text)
|
|
|
|
@staticmethod
|
|
def is_add_sync_folder_button_enabled():
|
|
return squish.waitForObjectExists(
|
|
SyncConnectionWizard.ADD_FOLDER_SYNC_BUTTON
|
|
).enabled
|
|
|
|
@staticmethod
|
|
def select_or_unselect_folders_to_sync(folders, select=True):
|
|
expected_state = "true" if select else "false"
|
|
|
|
if select:
|
|
SyncConnectionWizard.deselect_all_remote_folders()
|
|
|
|
for folder_path in folders:
|
|
parents = folder_path.strip("/").split("/")
|
|
target_folder = parents.pop()
|
|
|
|
parent_element = None
|
|
parent_position = 0
|
|
for parent in parents:
|
|
p_elements = app().find_elements(By.NAME, parent)
|
|
# select nested folders based on the position of the parent folder
|
|
for p_element in p_elements:
|
|
if (
|
|
p_element.get_attribute("checked") == 'true'
|
|
and p_element.rect["x"] > parent_position
|
|
):
|
|
parent_element = p_element
|
|
parent_position = p_element.rect["x"]
|
|
break
|
|
parent_element.native_double_click() # expand the folder
|
|
# retry once if the folder is not expanded
|
|
if parent_element.is_selected():
|
|
print('[WARN] Folder was not expanded, retrying with space key')
|
|
# expand using space key
|
|
parent_element.native_click()
|
|
parent_element.native_send_keys(Keys.SPACE)
|
|
if parent_element.is_selected():
|
|
raise AssertionError(f'Failed to expand folder: {parent}')
|
|
|
|
folder_element = None
|
|
target_folders = app().find_elements(By.NAME, target_folder)
|
|
# select the folder that is inside the current parent position
|
|
for folder in target_folders:
|
|
if folder.rect["x"] > parent_position:
|
|
folder_element = folder
|
|
break
|
|
is_checked = folder_element.get_attribute("checked")
|
|
# return early if the folder is already in the expected state.
|
|
if is_checked == expected_state:
|
|
return
|
|
|
|
folder_element.native_click()
|
|
if not folder_element.is_selected():
|
|
raise AssertionError(f"Failed to focus folder: {target_folder}")
|
|
folder_element.native_send_keys(Keys.SPACE) # toggle the folder selection
|
|
|
|
is_checked = folder_element.get_attribute("checked")
|
|
if is_checked != expected_state:
|
|
raise AssertionError(
|
|
f"Failed to {'select' if select else 'unselect'} folder: {folder_path}"
|
|
)
|
|
|
|
@staticmethod
|
|
def confirm_choose_what_to_sync_selection():
|
|
app().find_element(By.NAME, "OK").click()
|
|
|
|
@staticmethod
|
|
def __handle_folder_selection(folders, should_select, new_sync_connection_wizard):
|
|
SyncConnectionWizard.select_or_unselect_folders_to_sync(folders, should_select)
|
|
|
|
if new_sync_connection_wizard:
|
|
SyncConnectionWizard.add_sync_connection()
|
|
else:
|
|
SyncConnectionWizard.confirm_choose_what_to_sync_selection()
|
|
|
|
@staticmethod
|
|
def unselect_folders_to_sync(folders, new_sync_connection_wizard=False):
|
|
SyncConnectionWizard.__handle_folder_selection(
|
|
folders,
|
|
should_select=False,
|
|
new_sync_connection_wizard=new_sync_connection_wizard,
|
|
)
|
|
|
|
@staticmethod
|
|
def select_folders_to_sync(folders, new_sync_connection_wizard=False):
|
|
SyncConnectionWizard.__handle_folder_selection(
|
|
folders,
|
|
should_select=True,
|
|
new_sync_connection_wizard=new_sync_connection_wizard,
|
|
)
|