From 6f4d09ae9e46fbdedc8434bf9fd6ab05ea7bc468 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Fri, 12 Jul 2024 12:53:00 +0545 Subject: [PATCH 1/3] test: add multiple accounts --- .../scripts/helpers/SetupClientHelper.py | 139 ++++++++++-------- .../scripts/pageObjects/EnterPassword.py | 108 +++++++++----- test/gui/shared/steps/account_context.py | 67 ++++++--- test/gui/shared/steps/spaces_context.py | 6 +- .../tst_removeAccountConnection/test.feature | 8 +- 5 files changed, 202 insertions(+), 126 deletions(-) diff --git a/test/gui/shared/scripts/helpers/SetupClientHelper.py b/test/gui/shared/scripts/helpers/SetupClientHelper.py index cec39052449..b26d91141b1 100644 --- a/test/gui/shared/scripts/helpers/SetupClientHelper.py +++ b/test/gui/shared/scripts/helpers/SetupClientHelper.py @@ -1,5 +1,6 @@ import squish, test import psutil +import uuid from urllib.parse import urlparse from os import makedirs from os.path import exists, join @@ -7,6 +8,7 @@ from helpers.ConfigHelper import get_config, set_config, isWindows from helpers.SyncHelper import listenSyncStatusForItem from helpers.api.utils import url_join +from helpers.UserHelper import getDisplaynameForUser def substituteInLineCodes(value): @@ -100,71 +102,86 @@ def startClient(): def getPollingInterval(): - pollingInterval = '''[ownCloud] - remotePollInterval={pollingInterval} - ''' + pollingInterval = ''' +[ownCloud] +remotePollInterval={pollingInterval} +''' args = {'pollingInterval': 5000} pollingInterval = pollingInterval.format(**args) return pollingInterval -def setUpClient(username, displayName, space="Personal"): - userSetting = ''' - [Accounts] - 0/Folders/1/davUrl={url} - 0/Folders/1/ignoreHiddenFiles=true - 0/Folders/1/localPath={client_sync_path} - 0/Folders/1/displayString={displayString} - 0/Folders/1/paused=false - 0/Folders/1/targetPath=/ - 0/Folders/1/version=2 - 0/Folders/1/virtualFilesMode={vfs} - 0/dav_user={davUserName} - 0/display-name={displayUserName} - 0/http_CredentialVersion=1 - 0/http_oauth={oauth} - 0/http_user={davUserName} - 0/url={local_server} - 0/user={displayUserFirstName} - 0/version=1 - 0/supportsSpaces={supportsSpaces} - version=2 - ''' - - userSetting = userSetting + getPollingInterval() - - syncPath = createUserSyncPath(username) - dav_endpoint = url_join("remote.php/dav/files", username) - - server_url = get_config('localBackendUrl') - is_ocis = get_config('ocis') - if is_ocis: - set_config('syncConnectionName', space) - syncPath = createSpacePath(space) - if space == "Personal": - space = displayName - dav_endpoint = url_join("dav/spaces", get_space_id(space, username)) - - args = { - 'url': url_join(server_url, dav_endpoint, ''), - 'displayString': get_config('syncConnectionName'), - 'displayUserName': displayName, - 'davUserName': username if is_ocis else username.lower(), - 'displayUserFirstName': displayName.split()[0], - 'client_sync_path': syncPath, - 'local_server': server_url, - 'oauth': 'true' if is_ocis else 'false', - 'vfs': 'wincfapi' if isWindows() else 'off', - 'supportsSpaces': 'true' if is_ocis else 'false', - } - userSetting = userSetting.format(**args) - - configFile = open(get_config('clientConfigFile'), "w") - configFile.write(userSetting) - configFile.close() - +def generate_account_config(users, space="Personal"): + sync_paths = [] + user_setting = '' + for idx, username in enumerate(users): + user_setting += ''' +{user_index}/Folders/{uuid_v4}/davUrl={url} +{user_index}/Folders/{uuid_v4}/ignoreHiddenFiles=true +{user_index}/Folders/{uuid_v4}/localPath={client_sync_path} +{user_index}/Folders/{uuid_v4}/displayString={displayString} +{user_index}/Folders/{uuid_v4}/paused=false +{user_index}/Folders/{uuid_v4}/targetPath=/ +{user_index}/Folders/{uuid_v4}/version=13 +{user_index}/Folders/{uuid_v4}/virtualFilesMode=off +{user_index}/dav_user={davUserName} +{user_index}/display-name={displayUserName} +{user_index}/http_CredentialVersion=1 +{user_index}/http_oauth={oauth} +{user_index}/http_user={davUserName} +{user_index}/url={local_server} +{user_index}/user={displayUserFirstName} +{user_index}/supportsSpaces={supportsSpaces} +{user_index}/version=13 +''' + if not idx: + user_setting = "[Accounts]" + user_setting + + sync_path = createUserSyncPath(username) + dav_endpoint = url_join("remote.php/dav/files", username) + + server_url = get_config('localBackendUrl') + is_ocis = get_config('ocis') + if is_ocis: + set_config('syncConnectionName', space) + sync_path = createSpacePath(space) + space_name = space + if space == "Personal": + space_name = getDisplaynameForUser(username) + dav_endpoint = url_join("dav/spaces", get_space_id(space_name, username)) + + args = { + 'url': url_join(server_url, dav_endpoint, ''), + 'displayString': get_config('syncConnectionName'), + 'displayUserName': getDisplaynameForUser(username), + 'davUserName': username if is_ocis else username.lower(), + 'displayUserFirstName': getDisplaynameForUser(username).split()[0], + 'client_sync_path': sync_path, + 'local_server': server_url, + 'oauth': 'true' if is_ocis else 'false', + 'vfs': 'wincfapi' if isWindows() else 'off', + 'supportsSpaces': 'true' if is_ocis else 'false', + 'user_index': idx, + 'uuid_v4': generate_UUIDV4(), + } + user_setting = user_setting.format(**args) + sync_paths.append(sync_path) + # append extra configs + user_setting += "version=13" + user_setting = user_setting + getPollingInterval() + + config_file = open(get_config('clientConfigFile'), "a+", encoding="utf-8") + config_file.write(user_setting) + config_file.close() + + return sync_paths + + +def setUpClient(username, space="Personal"): + sync_paths = generate_account_config([username], space) startClient() - listenSyncStatusForItem(syncPath) + for sync_path in sync_paths: + listenSyncStatusForItem(sync_path) def is_app_killed(pid): @@ -185,3 +202,7 @@ def wait_until_app_killed(pid=0): test.log( "Application was not terminated within {} milliseconds".format(timeout) ) + + +def generate_UUIDV4(): + return str(uuid.uuid4()) diff --git a/test/gui/shared/scripts/pageObjects/EnterPassword.py b/test/gui/shared/scripts/pageObjects/EnterPassword.py index 98c7bdd3802..01752cd3704 100644 --- a/test/gui/shared/scripts/pageObjects/EnterPassword.py +++ b/test/gui/shared/scripts/pageObjects/EnterPassword.py @@ -1,79 +1,115 @@ -import names import squish from helpers.WebUIHelper import authorize_via_webui from helpers.ConfigHelper import get_config -from pageObjects.AccountConnectionWizard import AccountConnectionWizard +from helpers.UserHelper import getPasswordForUser class EnterPassword: + LOGIN_DIALOG = { + "name": "LoginRequiredDialog", + "type": "OCC::LoginRequiredDialog", + "visible": 1, + } + LOGIN_USER_LABEL = { + "name": "topLabel", + "type": "QLabel", + "visible": 1, + "window": LOGIN_DIALOG, + } + USERNAME_BOX = { + "name": "usernameLineEdit", + "type": "QLineEdit", + "visible": 1, + "window": LOGIN_DIALOG, + } PASSWORD_BOX = { - "container": names.loginRequiredDialog_contentWidget_QStackedWidget, "name": "passwordLineEdit", "type": "QLineEdit", "visible": 1, + "window": LOGIN_DIALOG, } LOGIN_BUTTON = { "text": "Log in", "type": "QPushButton", "visible": 1, - "window": names.stack_stackedWidget_QStackedWidget, + "window": LOGIN_DIALOG, } LOGOUT_BUTTON = { "text": "Log out", "type": "QPushButton", "visible": 1, - "window": names.stack_stackedWidget_QStackedWidget, + "window": LOGIN_DIALOG, } COPY_URL_TO_CLIPBOARD_BUTTON = { - "container": names.loginRequiredDialog_contentWidget_QStackedWidget, "name": "copyUrlToClipboardButton", "type": "QPushButton", "visible": 1, + "window": LOGIN_DIALOG, + } + TLS_CERT_WINDOW = { + "name": "OCC__TlsErrorDialog", + "type": "OCC::TlsErrorDialog", + "visible": 1, + } + ACCEPT_CERTIFICATE_YES = { + "text": "Yes", + "type": "QPushButton", + "visible": 1, + "window": TLS_CERT_WINDOW, } - @staticmethod - def enterPassword(password): - squish.waitForObject( - EnterPassword.PASSWORD_BOX, get_config('maxSyncTimeout') * 1000 - ) - squish.type(squish.waitForObject(EnterPassword.PASSWORD_BOX), password) - squish.clickButton(squish.waitForObject(EnterPassword.LOGIN_BUTTON)) + def __init__(self, occurrence=1): + if occurrence > 1 and not get_config('ocis'): + self.LOGIN_DIALOG.update({"occurrence": occurrence}) + elif occurrence > 1 and get_config('ocis'): + self.TLS_CERT_WINDOW.update({"occurrence": occurrence}) - @staticmethod - def oidcReLogin(username, password): + def get_username(self): + # Parse username from following label: + # Please enter your password to log in to the account Alice Hansen@localhost. + # The account Alice Hansen@localhost:9200 is currently logged out. + label = str(squish.waitForObjectExists(self.LOGIN_USER_LABEL).text) + label = label.split("@", maxsplit=1)[0].split(" ") + label.reverse() + return label[1].capitalize() + + def enterPassword(self, password): + squish.waitForObject(self.PASSWORD_BOX, get_config('maxSyncTimeout') * 1000) + squish.type(squish.waitForObject(self.PASSWORD_BOX), password) + squish.clickButton(squish.waitForObject(self.LOGIN_BUTTON)) + + def oidcReLogin(self, username, password): # wait 500ms for copy button to fully load squish.snooze(1 / 2) - squish.clickButton( - squish.waitForObject(EnterPassword.COPY_URL_TO_CLIPBOARD_BUTTON) - ) + squish.clickButton(squish.waitForObject(self.COPY_URL_TO_CLIPBOARD_BUTTON)) authorize_via_webui(username, password) - @staticmethod - def oauthReLogin(username, password): + def oauthReLogin(self, username, password): # wait 500ms for copy button to fully load squish.snooze(1 / 2) - squish.clickButton( - squish.waitForObject(EnterPassword.COPY_URL_TO_CLIPBOARD_BUTTON) - ) + squish.clickButton(squish.waitForObject(self.COPY_URL_TO_CLIPBOARD_BUTTON)) authorize_via_webui(username, password, "oauth") - @staticmethod - def reLogin(username, password, oauth=False): + def reLogin(self, username, password, oauth=False): if get_config('ocis'): - EnterPassword.oidcReLogin(username, password) + self.oidcReLogin(username, password) elif oauth: - EnterPassword.oauthReLogin(username, password) + self.oauthReLogin(username, password) else: - EnterPassword.enterPassword(password) + self.enterPassword(password) + + def loginAfterSetup(self, username=None, password=None): + if not username: + username = self.get_username() + password = getPasswordForUser(username) - @staticmethod - def loginAfterSetup(username, password): if get_config('ocis'): - AccountConnectionWizard.acceptCertificate() - EnterPassword.oidcReLogin(username, password) + self.oidcReLogin(username, password) else: - EnterPassword.enterPassword(password) + self.enterPassword(password) + + def logout(self): + squish.clickButton(squish.waitForObject(self.LOGOUT_BUTTON)) - @staticmethod - def logout(): - squish.clickButton(squish.waitForObject(EnterPassword.LOGOUT_BUTTON)) + def accept_certificate(self): + squish.clickButton(squish.waitForObject(self.ACCEPT_CERTIFICATE_YES)) diff --git a/test/gui/shared/steps/account_context.py b/test/gui/shared/steps/account_context.py index 709514a8e38..9be55dc56f6 100644 --- a/test/gui/shared/steps/account_context.py +++ b/test/gui/shared/steps/account_context.py @@ -4,27 +4,19 @@ from pageObjects.Toolbar import Toolbar from pageObjects.AccountSetting import AccountSetting -from helpers.SetupClientHelper import substituteInLineCodes, getClientDetails +from helpers.SetupClientHelper import ( + setUpClient, + startClient, + substituteInLineCodes, + getClientDetails, + generate_account_config, + getResourcePath, +) from helpers.UserHelper import getDisplaynameForUser, getPasswordForUser -from helpers.SetupClientHelper import setUpClient, startClient -from helpers.SyncHelper import waitForInitialSyncToComplete -from helpers.SetupClientHelper import getResourcePath +from helpers.SyncHelper import waitForInitialSyncToComplete, listenSyncStatusForItem from helpers.ConfigHelper import get_config, isWindows, isLinux -@Given(r'the user has added (the first|another) account with', regexp=True) -def step(context, accountType): - if accountType == 'another': - Toolbar.openNewAccountSetup() - account_details = getClientDetails(context) - AccountConnectionWizard.addAccount(account_details) - space = "" - if get_config("ocis"): - space = "Personal" - # wait for files to sync - waitForInitialSyncToComplete(getResourcePath('/', account_details["user"], space)) - - @When('the user adds the following wrong user credentials:') def step(context): account_details = getClientDetails(context) @@ -61,14 +53,40 @@ def step(context, displayname, host): @Given('user "|any|" has set up a client with default settings') def step(context, username): password = getPasswordForUser(username) - displayName = getDisplaynameForUser(username) - setUpClient(username, displayName) - EnterPassword.loginAfterSetup(username, password) + setUpClient(username) + enter_password = EnterPassword() + if get_config('ocis'): + enter_password.accept_certificate() + + enter_password.loginAfterSetup(username, password) # wait for files to sync waitForInitialSyncToComplete(getResourcePath('/', username)) +@Given('the user has set up the following accounts with default settings:') +def step(context): + users = [] + for row in context.table: + users.append(row[0]) + sync_paths = generate_account_config(users) + startClient() + if get_config('ocis'): + # accept certificate for each user + for idx, _ in enumerate(users): + enter_password = EnterPassword(len(users) - idx) + enter_password.accept_certificate() + + for idx, sync_path in enumerate(sync_paths): + listenSyncStatusForItem(sync_path) + # login from last dialog + account_idx = len(sync_paths) - idx + enter_password = EnterPassword(account_idx) + enter_password.loginAfterSetup() + # wait for files to sync + waitForInitialSyncToComplete(sync_path) + + @Given('the user has started the client') def step(context): startClient() @@ -127,7 +145,8 @@ def step(context, username): def step(context, username): AccountSetting.login() password = getPasswordForUser(username) - EnterPassword.reLogin(username, password) + enter_password = EnterPassword() + enter_password.reLogin(username, password) # wait for files to sync waitForInitialSyncToComplete(getResourcePath('/', username)) @@ -150,7 +169,8 @@ def step(context, username): @When('user "|any|" enters the password "|any|"') def step(context, username, password): - EnterPassword.reLogin(username, password) + enter_password = EnterPassword() + enter_password.reLogin(username, password) @Then('user "|any|" should be connect to the client-UI') @@ -279,7 +299,8 @@ def step(context): @When('user "|any|" logs out from the login required dialog') def step(context, username): - EnterPassword.logout() + enter_password = EnterPassword() + enter_password.logout() @When("the user quits the client") diff --git a/test/gui/shared/steps/spaces_context.py b/test/gui/shared/steps/spaces_context.py index fd73fcfa915..5dd20c36bc2 100644 --- a/test/gui/shared/steps/spaces_context.py +++ b/test/gui/shared/steps/spaces_context.py @@ -38,9 +38,9 @@ def step(context, user, space_name, role): @Given('user "|any|" has set up a client with space "|any|"') def step(context, user, space_name): password = getPasswordForUser(user) - displayName = getDisplaynameForUser(user) - setUpClient(user, displayName, space_name) - EnterPassword.loginAfterSetup(user, password) + setUpClient(user, space_name) + enter_password = EnterPassword() + enter_password.loginAfterSetup(user, password) # wait for files to sync waitForInitialSyncToComplete(getResourcePath('/', user, space_name)) diff --git a/test/gui/tst_removeAccountConnection/test.feature b/test/gui/tst_removeAccountConnection/test.feature index 4ff3da9181d..d1503f0224d 100644 --- a/test/gui/tst_removeAccountConnection/test.feature +++ b/test/gui/tst_removeAccountConnection/test.feature @@ -8,11 +8,9 @@ Feature: remove account connection Scenario: remove an account connection Given user "Alice" has been created on the server with default attributes and without skeleton files And user "Brian" has been created on the server with default attributes and without skeleton files - And user "Alice" has set up a client with default settings - And the user has added another account with - | server | %local_server% | - | user | Brian | - | password | AaBb2Cc3Dd4 | + And the user has set up the following accounts with default settings: + | Alice | + | Brian | When the user removes the connection for user "Brian" and host %local_server_hostname% Then the account with displayname "Brian Murphy" and host "%local_server_hostname%" should not be displayed But the account with displayname "Alice Hansen" and host "%local_server_hostname%" should be displayed From 4a501a77fdb603aa45dbbdb824d770c7809b8633 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Fri, 12 Jul 2024 14:38:15 +0545 Subject: [PATCH 2/3] test: fix tests --- .../gui/shared/scripts/helpers/SpaceHelper.py | 2 +- .../scripts/pageObjects/EnterPassword.py | 19 +++++++++---------- test/gui/shared/steps/spaces_context.py | 2 ++ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/test/gui/shared/scripts/helpers/SpaceHelper.py b/test/gui/shared/scripts/helpers/SpaceHelper.py index e8e56b1c1f2..4026c423821 100644 --- a/test/gui/shared/scripts/helpers/SpaceHelper.py +++ b/test/gui/shared/scripts/helpers/SpaceHelper.py @@ -27,7 +27,7 @@ def get_share_endpint(): def create_space(space_name): - body = json.dumps({"Name": space_name}) + body = json.dumps({"name": space_name}) response = request.post(get_space_endpint(), body) if response.status_code != 201: raise Exception( diff --git a/test/gui/shared/scripts/pageObjects/EnterPassword.py b/test/gui/shared/scripts/pageObjects/EnterPassword.py index 01752cd3704..33bdec07895 100644 --- a/test/gui/shared/scripts/pageObjects/EnterPassword.py +++ b/test/gui/shared/scripts/pageObjects/EnterPassword.py @@ -1,3 +1,4 @@ +import names import squish from helpers.WebUIHelper import authorize_via_webui from helpers.ConfigHelper import get_config @@ -5,7 +6,7 @@ class EnterPassword: - LOGIN_DIALOG = { + LOGIN_CONTAINER = { "name": "LoginRequiredDialog", "type": "OCC::LoginRequiredDialog", "visible": 1, @@ -14,37 +15,37 @@ class EnterPassword: "name": "topLabel", "type": "QLabel", "visible": 1, - "window": LOGIN_DIALOG, + "window": LOGIN_CONTAINER, } USERNAME_BOX = { "name": "usernameLineEdit", "type": "QLineEdit", "visible": 1, - "window": LOGIN_DIALOG, + "window": LOGIN_CONTAINER, } PASSWORD_BOX = { "name": "passwordLineEdit", "type": "QLineEdit", "visible": 1, - "window": LOGIN_DIALOG, + "window": LOGIN_CONTAINER, } LOGIN_BUTTON = { "text": "Log in", "type": "QPushButton", "visible": 1, - "window": LOGIN_DIALOG, + "window": names.stack_stackedWidget_QStackedWidget, } LOGOUT_BUTTON = { "text": "Log out", "type": "QPushButton", "visible": 1, - "window": LOGIN_DIALOG, + "window": names.stack_stackedWidget_QStackedWidget, } COPY_URL_TO_CLIPBOARD_BUTTON = { "name": "copyUrlToClipboardButton", "type": "QPushButton", "visible": 1, - "window": LOGIN_DIALOG, + "window": LOGIN_CONTAINER, } TLS_CERT_WINDOW = { "name": "OCC__TlsErrorDialog", @@ -59,9 +60,7 @@ class EnterPassword: } def __init__(self, occurrence=1): - if occurrence > 1 and not get_config('ocis'): - self.LOGIN_DIALOG.update({"occurrence": occurrence}) - elif occurrence > 1 and get_config('ocis'): + if occurrence > 1 and get_config('ocis'): self.TLS_CERT_WINDOW.update({"occurrence": occurrence}) def get_username(self): diff --git a/test/gui/shared/steps/spaces_context.py b/test/gui/shared/steps/spaces_context.py index 5dd20c36bc2..096e593a400 100644 --- a/test/gui/shared/steps/spaces_context.py +++ b/test/gui/shared/steps/spaces_context.py @@ -40,6 +40,8 @@ def step(context, user, space_name): password = getPasswordForUser(user) setUpClient(user, space_name) enter_password = EnterPassword() + if get_config('ocis'): + enter_password.accept_certificate() enter_password.loginAfterSetup(user, password) # wait for files to sync waitForInitialSyncToComplete(getResourcePath('/', user, space_name)) From 3dc4c465749147bf180f65a4af9ce994b84565a7 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Mon, 15 Jul 2024 15:59:09 +0545 Subject: [PATCH 3/3] test: fix sync path per user --- .../gui/shared/scripts/helpers/SetupClientHelper.py | 6 +++--- .../gui/shared/scripts/pageObjects/EnterPassword.py | 6 +----- test/gui/shared/steps/account_context.py | 13 ++++++++----- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/test/gui/shared/scripts/helpers/SetupClientHelper.py b/test/gui/shared/scripts/helpers/SetupClientHelper.py index b26d91141b1..dbafd93105e 100644 --- a/test/gui/shared/scripts/helpers/SetupClientHelper.py +++ b/test/gui/shared/scripts/helpers/SetupClientHelper.py @@ -112,7 +112,7 @@ def getPollingInterval(): def generate_account_config(users, space="Personal"): - sync_paths = [] + sync_paths = {} user_setting = '' for idx, username in enumerate(users): user_setting += ''' @@ -165,7 +165,7 @@ def generate_account_config(users, space="Personal"): 'uuid_v4': generate_UUIDV4(), } user_setting = user_setting.format(**args) - sync_paths.append(sync_path) + sync_paths.update({username: sync_path}) # append extra configs user_setting += "version=13" user_setting = user_setting + getPollingInterval() @@ -180,7 +180,7 @@ def generate_account_config(users, space="Personal"): def setUpClient(username, space="Personal"): sync_paths = generate_account_config([username], space) startClient() - for sync_path in sync_paths: + for _, sync_path in sync_paths.items(): listenSyncStatusForItem(sync_path) diff --git a/test/gui/shared/scripts/pageObjects/EnterPassword.py b/test/gui/shared/scripts/pageObjects/EnterPassword.py index 33bdec07895..10ae9531831 100644 --- a/test/gui/shared/scripts/pageObjects/EnterPassword.py +++ b/test/gui/shared/scripts/pageObjects/EnterPassword.py @@ -97,11 +97,7 @@ def reLogin(self, username, password, oauth=False): else: self.enterPassword(password) - def loginAfterSetup(self, username=None, password=None): - if not username: - username = self.get_username() - password = getPasswordForUser(username) - + def loginAfterSetup(self, username, password): if get_config('ocis'): self.oidcReLogin(username, password) else: diff --git a/test/gui/shared/steps/account_context.py b/test/gui/shared/steps/account_context.py index 9be55dc56f6..8ad6ff6fe7c 100644 --- a/test/gui/shared/steps/account_context.py +++ b/test/gui/shared/steps/account_context.py @@ -77,14 +77,16 @@ def step(context): enter_password = EnterPassword(len(users) - idx) enter_password.accept_certificate() - for idx, sync_path in enumerate(sync_paths): - listenSyncStatusForItem(sync_path) + for idx, sync_path in enumerate(sync_paths.values()): # login from last dialog account_idx = len(sync_paths) - idx enter_password = EnterPassword(account_idx) - enter_password.loginAfterSetup() + username = enter_password.get_username() + password = getPasswordForUser(username) + listenSyncStatusForItem(sync_paths[username]) + enter_password.loginAfterSetup(username, password) # wait for files to sync - waitForInitialSyncToComplete(sync_path) + waitForInitialSyncToComplete(sync_paths[username]) @Given('the user has started the client') @@ -156,7 +158,8 @@ def step(context, username): def step(context, username): AccountSetting.login() password = getPasswordForUser(username) - EnterPassword.reLogin(username, password, True) + enter_password = EnterPassword() + enter_password.reLogin(username, password, True) # wait for files to sync waitForInitialSyncToComplete(getResourcePath('/', username))