Initial QSfera import

This commit is contained in:
Курнат Андрей
2026-06-07 10:20:04 +03:00
commit 2315f25754
16485 changed files with 4826827 additions and 0 deletions
+292
View File
@@ -0,0 +1,292 @@
import shutil
import os
from behave import given as Given, when as When, then as Then
from sure import expect, ensure
from pageObjects.AccountConnectionWizard import AccountConnectionWizard
from pageObjects.SyncConnectionWizard import SyncConnectionWizard
from pageObjects.AccountSetting import AccountSetting
from pageObjects.Toolbar import Toolbar
from pageObjects.EnterPassword import EnterPassword
from helpers.SetupClientHelper import (
start_client,
setup_client,
substitute_inline_codes,
get_client_details,
generate_account_config,
get_resource_path,
)
from helpers.SyncHelper import (
wait_for_initial_sync_to_complete,
listen_sync_status_for_item,
)
from helpers.UserHelper import get_displayname_for_user, get_password_for_user
from helpers.ConfigHelper import get_config
from helpers.TableParser import table_rows_hash
from helpers.AppHelper import close_and_kill_app
@Given('the user has started the client')
def step(context):
start_client()
@When('the user adds the following user credentials:')
def step(context):
account_details = get_client_details(context)
set_config('syncConnectionName', get_displayname_for_user(account_details['user']))
AccountConnectionWizard.add_user_credentials(
account_details['user'], account_details['password']
)
@Then('"{username}" account should be added')
def step(context, username):
username = substitute_inline_codes(username)
expect(Toolbar.account_exists(username)).to.be.true
@Then('"{username}" account should not be displayed')
def step(context, username):
username = substitute_inline_codes(username)
expect(Toolbar.account_exists(username)).to.be.false
@Given('user "{username}" has set up a client with default settings')
def step(context, username):
password = get_password_for_user(username)
setup_client(username)
enter_password = EnterPassword()
enter_password.accept_certificate()
enter_password.login_after_setup(username, password)
# wait for files to sync
wait_for_initial_sync_to_complete(get_resource_path('/', username))
Toolbar.wait_toolbar_enabled()
@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)
start_client()
# accept certificate for each user
for idx, _ in enumerate(users):
enter_password = EnterPassword()
enter_password.accept_certificate()
for idx, _ in enumerate(sync_paths.values()):
# login from last dialog
enter_password = EnterPassword()
username = enter_password.get_username()
password = get_password_for_user(username)
listen_sync_status_for_item(sync_paths[username])
enter_password.login_after_setup(username, password)
# wait for files to sync
wait_for_initial_sync_to_complete(sync_paths[username])
Toolbar.wait_toolbar_enabled()
@When('the user starts the client')
def step(context):
start_client()
@When('the user opens the add-account dialog')
def step(context):
Toolbar.open_new_account_setup()
@When('the user adds the following account:')
def step(context):
data = table_rows_hash(context.table)
account_details = get_client_details(data)
AccountConnectionWizard.add_account(account_details)
# # wait for files to sync
wait_for_initial_sync_to_complete(get_resource_path('/', account_details['user']))
Toolbar.wait_toolbar_enabled()
@Given('the user has entered the following account information:')
def step(context):
data = table_rows_hash(context.table)
account_details = get_client_details(data)
AccountConnectionWizard.add_account_information(account_details)
@When('the user "{username}" logs out using the client-UI')
def step(context, username):
AccountSetting.logout()
@Then('user "{username}" should be signed out')
def step(context, username):
user_signed_out = AccountSetting.is_user_signed_out()
with ensure('User "{0}" should be signed out, but is still signed in', username):
user_signed_out.should.be.true
@Given('user "{username}" has logged out from the client-UI')
def step(context, username):
AccountSetting.logout()
if not AccountSetting.is_user_signed_out():
raise LookupError(f'Failed to logout user {username}')
@When('user "{username}" logs in using the client-UI')
def step(context, username):
AccountSetting.login()
password = get_password_for_user(username)
enter_password = EnterPassword()
enter_password.relogin(username, password)
# wait for files to sync
wait_for_initial_sync_to_complete(get_resource_path('/', username))
Toolbar.wait_toolbar_enabled()
@When('user "|any|" opens login dialog')
def step(context, _):
AccountSetting.login()
@Then('user "{username}" should be connected to the server')
def step(context, username):
AccountSetting.wait_until_account_is_connected()
@When('the user removes the connection for user "{username}"')
def step(context, username):
username = substitute_inline_codes(username)
AccountSetting.remove_connection_for_user(username)
@Then('connection wizard should be visible')
def step(context):
test.compare(
AccountConnectionWizard.is_new_connection_window_visible(),
True,
'Connection window is visible',
)
@When('the user accepts the certificate')
def step(context):
AccountConnectionWizard.accept_certificate()
@When('the user adds the server "|any|"')
def step(context, server):
server_url = substitute_inline_codes(server)
AccountConnectionWizard.add_server(server_url)
@When('the user selects manual sync folder option in advanced section')
def step(context):
AccountConnectionWizard.select_manual_sync_folder_option()
AccountConnectionWizard.next_step()
@Then('credentials wizard should be visible')
def step(context):
test.compare(
AccountConnectionWizard.is_credential_window_visible(),
True,
'Credentials wizard is visible',
)
@When('the user selects download everything option in advanced section')
def step(context):
AccountConnectionWizard.select_download_everything_option()
AccountConnectionWizard.next_step()
@When('the user opens the advanced configuration')
def step(context):
AccountConnectionWizard.select_advanced_config()
@Then('the user should be able to choose the local download directory')
def step(context):
test.compare(True, AccountConnectionWizard.can_change_local_sync_dir())
@Then('the download everything option should be selected by default for Linux')
def step(context):
if is_linux():
test.compare(
True,
AccountConnectionWizard.is_sync_everything_option_checked(),
'Sync everything option is checked',
)
@When(r'^the user presses the "([^"]*)" key(?:s)?', regexp=True)
def step(context, key):
AccountSetting.press_key(key)
@Then('the log dialog should be opened')
def step(context):
test.compare(True, AccountSetting.is_log_dialog_visible(), 'Log dialog is opened')
@When('the user cancels the sync connection wizard')
def step(context):
SyncConnectionWizard.cancel_folder_sync_connection_wizard()
@When('the user quits the client')
def step(context):
Toolbar.quit_qsfera()
close_and_kill_app()
@Then('"{username}" account should be opened')
def step(context, username):
username = substitute_inline_codes(username)
expect(Toolbar.account_has_focus(username)).to.be.true
@Then(
r'the default local sync path should contain "([^"]*)" in the (configuration|sync connection) wizard',
regexp=True,
)
def step(context, sync_path, wizard):
sync_path = substitute_inline_codes(sync_path)
actual_sync_path = ''
if wizard == 'configuration':
actual_sync_path = AccountConnectionWizard.get_local_sync_path()
else:
actual_sync_path = SyncConnectionWizard.get_local_sync_path()
test.compare(
actual_sync_path,
convert_path_separators_for_os(sync_path),
'Compare sync path contains the expected path',
)
@Then('the warning "|any|" should appear in the sync connection wizard')
def step(context, warn_message):
actual_message = SyncConnectionWizard.get_warn_label()
test.compare(
True,
warn_message in actual_message,
'Contains warning message',
)
@Given('the user has removed the connection for user "{username}"')
def step(context, username):
username = substitute_inline_codes(username)
AccountSetting.remove_connection_for_user(username)
AccountSetting.wait_until_account_is_removed(username)
shutil.rmtree(os.path.join(get_config("clientRootSyncPath"), username))
+458
View File
@@ -0,0 +1,458 @@
import os
import re
import builtins
import shutil
import zipfile
from os.path import isfile, join, isdir, exists
from behave import when as When, then as Then
from sure import ensure
from helpers.SetupClientHelper import get_resource_path, get_temp_resource_path
from helpers.SyncHelper import (
wait_for_client_to_be_ready,
listen_sync_status_for_item,
wait_for,
)
from helpers.ConfigHelper import get_config, is_windows
from helpers.FilesHelper import (
build_conflicted_regex,
sanitize_path,
can_read,
can_write,
read_file_content,
get_size_in_bytes,
prefix_path_namespace,
remember_path,
convert_path_separators_for_os,
get_file_for_upload,
)
def folder_exists(folder_path, timeout=1000):
return wait_for(
lambda: isdir(sanitize_path(folder_path)),
timeout,
)
def file_exists(file_path, timeout=1000):
return wait_for(
lambda: isfile(sanitize_path(file_path)),
timeout,
)
# To create folders in a temporary directory, we set is_temp_folder True
# And if is_temp_folder is True, the create_folder function create folders in tempFolderPath
def create_folder(foldername, username=None, is_temp_folder=False):
if is_temp_folder:
folder_path = join(get_config('tempFolderPath'), foldername)
else:
folder_path = get_resource_path(foldername, username)
os.makedirs(prefix_path_namespace(convert_path_separators_for_os(folder_path)))
def rename_file_folder(source, destination):
source = get_resource_path(source)
destination = get_resource_path(destination)
os.rename(source, destination)
def create_file_with_size(filename, filesize, is_temp_folder=False):
if is_temp_folder:
file = join(get_config('tempFolderPath'), filename)
else:
file = get_resource_path(filename)
with open(prefix_path_namespace(file), 'wb') as f:
f.seek(get_size_in_bytes(filesize) - 1)
f.write(b'\0')
def write_file(resource, content):
with open(prefix_path_namespace(resource), 'w', encoding='utf-8') as f:
f.write(content)
def wait_and_write_file(path, content):
wait_for_client_to_be_ready()
listen_sync_status_for_item(get_resource_path(path), 'FILE')
write_file(path, content)
def wait_and_try_to_write_file(resource, content):
wait_for_client_to_be_ready()
listen_sync_status_for_item(get_resource_path(resource), 'FILE')
try:
write_file(resource, content)
except:
pass
def create_zip(resources, zip_file_name, cwd=''):
os.chdir(cwd)
with zipfile.ZipFile(zip_file_name, 'w') as zipped_file:
for resource in resources:
zipped_file.write(resource)
def extract_zip(zip_file_path, destination_dir):
with zipfile.ZipFile(zip_file_path, 'r') as zip_file:
zip_file.extractall(destination_dir)
def add_copy_suffix(resource_path, resource_type):
suffix = ' (Copy)'
if resource_type == 'file':
source_dir = resource_path.rsplit('.', 1)
return source_dir[0] + suffix + '.' + source_dir[-1]
return resource_path + suffix
def copy_resource(resource_type, source, destination, from_files_for_upload=False):
if from_files_for_upload:
source = get_file_for_upload(source)
else:
source = get_resource_path(source)
destination = get_resource_path(destination)
if source == destination and destination != '/':
destination = add_copy_suffix(source, resource_type)
wait_for_client_to_be_ready()
listen_sync_status_for_item(destination, resource_type)
if resource_type == 'folder':
return shutil.copytree(source, destination)
return shutil.copy2(source, destination)
def move_resource(username, resource_type, source, destination, is_temp_folder=False):
if not is_temp_folder:
source = get_resource_path(source, username)
if destination == '/':
destination = ''
destination = get_resource_path(destination, username)
wait_for_client_to_be_ready()
listen_sync_status_for_item(destination, resource_type)
shutil.move(source, destination)
def deleteResource(resource, resource_type):
wait_for_client_to_be_ready()
listen_sync_status_for_item(resource, resource_type)
resource_path = sanitize_path(get_resource_path(resource))
if resource_type == 'file':
os.remove(resource_path)
else:
shutil.rmtree(resource_path)
@When(
'user "{username}" creates a file "{filename}" with the following content inside the sync folder'
)
def step(context, username, filename):
file = get_resource_path(filename, username)
wait_and_write_file(convert_path_separators_for_os(file), context.text)
@When('user "{username}" creates a folder "{foldername}" inside the sync folder')
def step(context, username, foldername):
wait_for_client_to_be_ready()
create_folder(foldername, username)
@Given('user "{username}" has created a folder "{foldername}" inside the sync folder')
def step(context, username, foldername):
create_folder(foldername, username)
@When(
'user "{user}" creates a file "{filename}" with size "{filesize}" inside the sync folder'
)
def step(context, user, filename, filesize):
create_file_with_size(filename, filesize)
@When(r'the user copies (file|folder) "([^"]*)" into folder "([^"]*)"', regexp=True)
def step(context, resource_type, resource_name, destination_dir):
copy_resource(resource_type, resource_name, destination_dir, False)
@When(
'the user copies {resource_type:ResourceType} "{resource_name}" into the same directory'
)
def step(context, resource_type, resource_name):
copy_resource(resource_type, resource_name, resource_name, False)
@When('the user renames a file "{source}" to "{destination}"')
@When('the user renames a folder "{source}" to "{destination}"')
def step(context, source, destination):
wait_for_client_to_be_ready()
rename_file_folder(source, destination)
@Then(
'the file "{file_path}" should exist on the file system with the following content'
)
def step(context, file_path):
expected = context.text
file_path = get_resource_path(file_path)
with open(file_path, 'r', encoding='utf-8') as f:
contents = f.read()
with ensure(
'{0} expected to exist with content "{1}" but has content "{2}"',
file_path,
expected,
contents,
):
contents.should.equal(expected)
@Then('the {resource_type:ResourceType} "{resource}" should exist on the file system')
def step(context, resource_type, resource):
resource_path = get_resource_path(resource)
resource_exists = False
timeout = get_config('maxSyncTimeout') * 1000
if resource_type == 'file':
resource_exists = file_exists(resource_path, timeout)
else:
resource_exists = folder_exists(resource_path, timeout)
with ensure(
'{0} "{1}" should exist, but it does not',
resource_type.capitalize(),
resource,
):
resource_exists.should.be.true
@Then(
'the {resource_type:ResourceType} "{resource}" should not exist on the file system'
)
def step(context, resource_type, resource):
resource_path = get_resource_path(resource)
with ensure(
'{0} "{1}" should not exist, but it does',
resource_type.capitalize(),
resource,
):
exists(resource_path).should.be.false
@Given('the user has changed the content of local file "|any|" to:')
def step(context, filename):
file_content = '\n'.join(context.multiLineText)
wait_and_write_file(get_resource_path(filename), file_content)
@Then(
'a conflict file for "|any|" should exist on the file system with the following content'
)
def step(context, filename):
expected = '\n'.join(context.multiLineText)
onlyfiles = [
f for f in os.listdir(get_resource_path()) if isfile(get_resource_path(f))
]
found = False
pattern = re.compile(build_conflicted_regex(filename))
for file in onlyfiles:
if pattern.match(file):
with open(get_resource_path(file), 'r', encoding='utf-8') as f:
if f.read() == expected:
found = True
break
if not found:
raise AssertionError('Conflict file not found with given name')
@When('the user overwrites the file "{resource}" with content "{content}"')
def step(context, resource, content):
resource = get_resource_path(resource)
wait_and_write_file(resource, content)
@When('the user tries to overwrite the file "|any|" with content "|any|"')
def step(context, resource, content):
resource = get_resource_path(resource)
wait_and_try_to_write_file(resource, content)
@When('user "|any|" tries to overwrite the file "|any|" with content "|any|"')
def step(context, user, resource, content):
resource = get_resource_path(resource, user)
wait_and_try_to_write_file(resource, content)
@When('the user deletes the {resource_type:ResourceType} "{resource_name}"')
def step(context, resource_type, resource_name):
deleteResource(resource_name, resource_type)
@When('user "|any|" creates the following files inside the sync folder:')
def step(context, username):
for row in context.table[1:]:
file = get_resource_path(row[0], username)
wait_and_write_file(file, '')
@Given('the user has created a folder "|any|" in temp folder')
def step(context, folder_name):
create_folder(folder_name, is_temp_folder=True)
@Given(
'the user has created "|any|" files each of size "|any|" bytes inside folder "|any|" in temp folder'
)
def step(context, file_number, file_size, folder_name):
current_sync_path = get_temp_resource_path(folder_name)
if folder_exists(current_sync_path):
file_size = builtins.int(file_size)
for i in range(0, builtins.int(file_number)):
file_name = f'file{i}.txt'
create_file_with_size(join(current_sync_path, file_name), file_size, True)
else:
raise FileNotFoundError(
f"Folder '{folder_name}' does not exist in the temp folder"
)
@When(
r'user "([^"]*)" reads the content of file "([^"]*)"',
regexp=True,
)
def step(context, username, file):
file_path = get_resource_path(file, username)
with open(file_path, 'r') as f:
f.read()
@When(
r'user "([^"]*)" moves (folder|file) "([^"]*)" from the temp folder into the sync folder',
regexp=True,
)
def step(context, username, resource_type, resource_name):
source_dir = join(get_config('tempFolderPath'), resource_name)
move_resource(username, resource_type, source_dir, '/', True)
@When(
r'user "([^"]*)" moves (folder|file) "([^"]*)" to the temp folder',
regexp=True,
)
def step(context, username, resource_type, resource_name):
destination = join(get_config('tempFolderPath'), resource_name)
move_resource(username, resource_type, resource_name, destination)
@When(
'user "{username}" moves {resource_type:ResourceType} "{source}" to "{destination}" in the sync folder'
)
def step(context, username, resource_type, source, destination):
move_resource(username, resource_type, source, destination)
@Then('user "{user}" should be able to open the file "{file_name}" on the file system')
def step(context, user, file_name):
file_path = get_resource_path(file_name, user)
with ensure(
'File should be readable but user "{0}" cannot read file "{1}"',
user,
file_name,
):
can_read(file_path).should.be.true
@Then(
'as "{user}" the file "{file_name}" should have content "{content}" on the file system'
)
def step(context, user, file_name, content):
file_path = get_resource_path(file_name, user)
file_content = read_file_content(file_path)
with ensure(
'File "{0}" should have content "{1}" but got "{2}"',
file_name,
content,
file_content,
):
content.should.equal(file_content)
@Then('user "|any|" should not be able to edit the file "|any|" on the file system')
def step(context, user, file_name):
file_path = get_resource_path(file_name, user)
test.compare(not can_write(file_path), True, 'File should not be writable')
@Given(
'the user has created a zip file "|any|" with the following resources in the temp folder'
)
def step(context, zip_file_name):
resource_list = []
for row in context.table[1:]:
resource_list.append(row[0])
resource = join(get_config('tempFolderPath'), row[0])
if row[1] == 'folder':
os.makedirs(resource)
elif row[1] == 'file':
content = ''
if len(row) > 2 and row[2]:
content = row[2]
write_file(resource, content)
create_zip(resource_list, zip_file_name, get_config('tempFolderPath'))
@When('user "|any|" unzips the zip file "|any|" inside the sync root')
def step(context, username, zip_file_name):
destination_dir = get_resource_path('/', username)
zip_file_path = join(destination_dir, zip_file_name)
extract_zip(zip_file_path, destination_dir)
@When('user "|any|" copies file "|any|" to temp folder')
def step(context, username, source):
wait_for_client_to_be_ready()
source_dir = get_resource_path(source, username)
destination_dir = get_temp_resource_path(source)
shutil.copy2(source_dir, destination_dir)
@Given('the user has created folder "|any|" in the default home path')
def step(context, folder_name):
folder_path = join(get_config('home_dir'), folder_name)
os.makedirs(prefix_path_namespace(folder_path))
remember_path(folder_path)
# when account is added, folder with suffix will be created
remember_path(f'{folder_path} (2)')
@Given(
r'the user has copied file "([^"]*)" from outside the sync folder to "([^"]*)" in the sync folder',
regexp=True,
)
def step(context, resource_name, destination):
copy_resource('file', resource_name, destination, True)
@When(
r'the user copies file "([^"]*)" from outside the sync folder to "([^"]*)" in the sync folder',
regexp=True,
)
def step(context, resource_name, destination):
copy_resource('file', resource_name, destination, True)
@When('the user deletes the following files')
def step(context):
wait_for_client_to_be_ready()
for row in context.table[1:]:
filename = row[0]
deleteResource(filename, 'file')
@Given('user "|any|" has created a file "|any|" with size "|any|" in the sync folder')
def step(context, _, filename, filesize):
create_file_with_size(filename, filesize)
+148
View File
@@ -0,0 +1,148 @@
from behave import given as Given, then as Then
from sure import ensure
from helpers.api import provisioning, webdav_helper as webdav
from helpers.TableParser import table_rows_hash
@Given('user "{user}" has been created in the server with default attributes')
def step(context, user):
provisioning.create_user(user)
@Then(
'as "{user_name}" {resource_type:ResourceType} "{resource_name}" should not exist in the server'
)
def step(context, user_name, resource_type, resource_name):
resource_exists = webdav.resource_exists(user_name, resource_name)
with ensure(
'{0} "{1}" should not exist, but it does',
resource_type.capitalize(),
resource_name,
):
resource_exists.should.be.false
@Then(
'as "{user_name}" {resource_type:ResourceType} "{resource_name}" should exist in the server'
)
def step(context, user_name, resource_type, resource_name):
resource_exists = webdav.resource_exists(user_name, resource_name)
with ensure(
'{0} "{1}" should exist, but it does not',
resource_type.capitalize(),
resource_name,
):
resource_exists.should.be.true
@Then(
'as "{user_name}" the file "{file_name}" should have the content "{content}" in the server'
)
def step(context, user_name, file_name, content):
text_content = webdav.get_file_content(user_name, file_name)
with ensure(
'{0} should have content "{1}" but found "{2}"',
file_name,
content,
text_content,
):
text_content.should.equal(content)
@Then(
r'as user "([^"].*)" folder "([^"].*)" should contain "([^"].*)" items in the server',
regexp=True,
)
def step(context, user_name, folder_name, items_number):
total_items = webdav.get_folder_items_count(user_name, folder_name)
test.compare(
total_items, items_number, f'Folder should contain {items_number} items'
)
@Given('user "{user}" has created folder "{folder_name}" in the server')
def step(context, user, folder_name):
webdav.create_folder(user, folder_name)
@Given(
'user "{user}" has uploaded file with content "{file_content}" to "{file_name}" in the server'
)
def step(context, user, file_content, file_name):
webdav.create_file(user, file_name, file_content)
@When('the user clicks on the settings tab')
def step(context):
Toolbar.open_settings_tab()
@When('user "{user}" uploads file with content "{file_content}" to "{file_name}" in the server')
def step(context, user, file_content, file_name):
webdav.create_file(user, file_name, file_content)
@When('user "{user}" deletes the folder "{folder_name}" in the server')
def step(context, user, folder_name):
webdav.delete_resource(user, folder_name)
@Given('user "{user}" has uploaded file "{file_name}" to "{destination}" in the server')
def step(context, user, file_name, destination):
webdav.upload_file(user, file_name, destination)
@Then(
'as "|any|" the content of file "|any|" in the server should match the content of local file "|any|"'
)
def step(context, user_name, server_file_name, local_file_name):
raw_server_content = webdav.get_file_content(user_name, server_file_name)
with tempfile.NamedTemporaryFile(suffix=Path(server_file_name).suffix) as tmp_file:
if isinstance(raw_server_content, str):
tmp_file.write(raw_server_content.encode('utf-8'))
else:
tmp_file.write(raw_server_content)
server_content = get_document_content(tmp_file.name)
local_content = get_document_content(get_file_for_upload(local_file_name))
test.compare(
server_content,
local_content,
f"Server file '{server_file_name}' differs from local file '{local_file_name}'",
)
@Then(
r'as "([^"].*)" following files should not exist in the server',
regexp=True,
)
def step(context, user_name):
for row in context.table[1:]:
resource_name = row[0]
test.compare(
webdav.resource_exists(user_name, resource_name),
False,
f"Resource '{resource_name}' should not exist, but does",
)
@Given('user "|any|" has uploaded the following files to the server')
def step(context, user):
for row in context.table[1:]:
file_name = row[0]
file_content = row[1]
webdav.create_file(user, file_name, file_content)
@Given('user "{user}" has sent the following resource share invitation:')
def step(context, user):
resource_details = table_rows_hash(context.table)
webdav.send_resource_share_invitation(
user,
resource_details['resource'],
resource_details['sharee'],
resource_details['permissionsRole'],
)
+80
View File
@@ -0,0 +1,80 @@
from sure import ensure
from pageObjects.EnterPassword import EnterPassword
from pageObjects.Toolbar import Toolbar
from helpers.UserHelper import get_password_for_user
from helpers.SetupClientHelper import setup_client, get_resource_path
from helpers.SyncHelper import wait_for_initial_sync_to_complete
from helpers.SpaceHelper import (
create_space,
create_space_folder,
create_space_file,
add_user_to_space,
get_file_content,
resource_exists,
)
from helpers.ConfigHelper import get_config, set_config
@Given('the administrator has created a space "{space_name}"')
def step(context, space_name):
create_space(space_name)
@Given('the administrator has created a folder "{folder_name}" in space "{space_name}"')
def step(context, folder_name, space_name):
create_space_folder(space_name, folder_name)
@Given(
'the administrator has uploaded a file "{file_name}" with content "{content}" inside space "{space_name}"'
)
def step(context, file_name, content, space_name):
create_space_file(space_name, file_name, content)
@Given(
'the administrator has added user "{user}" to space "{space_name}" with role "{role}"'
)
def step(context, user, space_name, role):
add_user_to_space(user, space_name, role)
@Given('user "{user}" has set up a client with space "{space_name}"')
def step(context, user, space_name):
set_config('syncConnectionName', space_name)
password = get_password_for_user(user)
setup_client(user, space_name)
enter_password = EnterPassword()
enter_password.accept_certificate()
enter_password.login_after_setup(user, password)
# wait for files to sync
wait_for_initial_sync_to_complete(get_resource_path('/', user, space_name))
Toolbar.wait_toolbar_enabled()
@Then(
'as "{user}" the file "{file_name}" in the space "{space_name}" should have content "{content}" in the server'
)
def step(context, user, file_name, space_name, content):
downloaded_content = get_file_content(space_name, file_name, user)
with ensure(
'File "{0}" in space "{1}" should have content "{2}" but got "{3}"',
file_name,
space_name,
content,
downloaded_content,
):
content.should.equal(downloaded_content)
@Then(
'as "{user}" the space "{space_name}" should have file "{resource_name}" in the server'
)
@Then(
'as "{user}" the space "{space_name}" should have folder "{resource_name}" in the server'
)
def step(context, user, space_name, resource_name):
exists = resource_exists(space_name, resource_name, user)
with ensure('Resource "{0}" should exist but it does not', resource_name):
exists.should.be.true
+377
View File
@@ -0,0 +1,377 @@
from behave import when as When, then as Then
from sure import ensure
from pageObjects.SyncConnectionWizard import SyncConnectionWizard
from pageObjects.Toolbar import Toolbar
from pageObjects.Activity import Activity
from pageObjects.SyncConnection import SyncConnection
from pageObjects.Settings import Settings
from helpers.ConfigHelper import set_config
from helpers.SyncHelper import (
wait_for_resource_to_sync,
wait_for_resource_to_have_sync_error,
)
from helpers.SetupClientHelper import (
get_temp_resource_path,
set_current_user_sync_path,
substitute_inline_codes,
get_resource_path,
)
from helpers.FilesHelper import convert_path_separators_for_os
from helpers.TableParser import table_hashes, table_raw
@Given('the user has paused the file sync')
def step(context):
SyncConnection.pause_sync()
@When('the user resumes the file sync on the client')
def step(context):
SyncConnection.resume_sync()
@When('the user force syncs the files')
def step(context):
SyncConnection.force_sync()
@When('the user waits for the files to sync')
def step(context):
wait_for_resource_to_sync(get_resource_path('/'), force_sync=True)
@When('the user waits for {resource_type:ResourceType} "{resource}" to be synced')
def step(context, resource_type, resource):
resource = get_resource_path(resource)
wait_for_resource_to_sync(convert_path_separators_for_os(resource), resource_type)
Toolbar.wait_toolbar_enabled()
@When(r'the user waits for (file|folder) "([^"]*)" to have sync error', regexp=True)
def step(context, resource_type, resource):
resource = get_resource_path(resource)
wait_for_resource_to_have_sync_error(resource, resource_type)
@When(
r'user "([^"]*)" waits for (file|folder) "([^"]*)" to have sync error', regexp=True
)
def step(context, username, resource_type, resource):
resource = get_resource_path(resource, username)
wait_for_resource_to_have_sync_error(resource, resource_type)
@Then('the "|any|" button should be available')
def step(context, item):
SyncConnection.open_menu()
SyncConnection.has_menu_item(item)
@Then('the "|any|" button should not be available')
def step(context, item):
SyncConnection.open_menu()
test.compare(
SyncConnection.menu_item_exists(item),
False,
f'Menu item "{item}" does not exist.',
)
@When('the user opens the activity tab')
def step(context):
Toolbar.open_activity()
@When('the user opens the settings tab')
def step(context):
Toolbar.open_settings_tab()
@Then('the table of conflict warnings should include file "|any|"')
def step(context, filename):
Activity.check_file_exist(filename)
@Then('the file "|any|" should be blacklisted')
def step(context, filename):
test.compare(
True, Activity.is_resource_blacklisted(filename), 'File is Blacklisted'
)
@Then('the file "|any|" should be ignored')
def step(context, filename):
test.compare(True, Activity.is_resource_ignored(filename), 'File is Ignored')
@Then('the file "|any|" should be excluded')
def step(context, filename):
test.compare(True, Activity.is_resource_excluded(filename), 'File is Excluded')
@When('the user selects "{tab_name}" tab in the activity')
def step(context, tab_name):
Activity.click_tab(tab_name)
@Then('the toolbar should have the following tabs:')
def step(context):
tabs = table_raw(context.table)
for tab_name in tabs:
tab_name = tab_name[0]
with ensure('Tab not found: {0}', tab_name):
Toolbar.has_tab(tab_name).should.be.true
@When('the user selects the following folders to sync:')
def step(context):
folders = []
for row in context.table:
folders.append(row[0])
SyncConnectionWizard.select_folders_to_sync(
folders, new_sync_connection_wizard=True
)
@When('the user sorts the folder list by "|any|"')
def step(context, header_text):
if (header_text := header_text.capitalize()) in ['Size', 'Name']:
SyncConnectionWizard.sort_by(header_text)
else:
raise ValueError("Sorting by '" + header_text + "' is not supported.")
@Then('the sync all checkbox should be checked')
def step(context):
test.compare(
SyncConnectionWizard.is_root_folder_checked(),
True,
'Sync all checkbox is checked',
)
@Then('the folders should be in the following order:')
def step(context):
row_index = 0
for row in context.table[1:]:
expected_folder = row[0]
actual_folder = SyncConnectionWizard.get_item_name_from_row(row_index)
test.compare(actual_folder, expected_folder)
row_index += 1
@When('the user selects "{space_name}" space in sync connection wizard')
def step(context, space_name):
SyncConnectionWizard.select_space(space_name)
SyncConnectionWizard.next_step()
set_config('syncConnectionName', space_name)
@When('the user sets the sync path in sync connection wizard')
def step(context):
SyncConnectionWizard.set_sync_path()
@When(
'the user sets the temp folder "|any|" as local sync path in sync connection wizard'
)
def step(context, folder_name):
sync_path = get_temp_resource_path(folder_name)
SyncConnectionWizard.set_sync_path(sync_path)
set_current_user_sync_path(sync_path)
@When('the user syncs the "{space_name}" space')
def step(context, space_name):
SyncConnectionWizard.sync_space(space_name)
@Then('the settings tab should have the following options in the general section:')
def step(context):
settings = table_raw(context.table)
for setting in settings:
setting = setting[0]
with ensure('General setting not found: {0}', setting):
Settings.has_general_setting(setting).should.be.true
@Then('the settings tab should have the following options in the advanced section:')
def step(context):
settings = table_raw(context.table)
for setting in settings:
setting = setting[0]
with ensure('Advanced setting not found: {0}', setting):
Settings.has_advanced_setting(setting).should.be.true
@Then('the settings tab should have the following options in the network section:')
def step(context):
settings = table_raw(context.table)
for setting in settings:
setting = setting[0]
with ensure('Network setting not found: {0}', setting):
Settings.has_network_setting(setting).should.be.true
@When('the user opens the about dialog')
def step(context):
Settings.open_about_dialog()
@Then('the about dialog should be opened')
def step(context):
with ensure('About dialog is not opened.'):
Settings.has_about_dialog().should.be.true
@When('the user closes the about dialog')
def step(context):
Settings.close_about_dialog()
@When('the user adds the folder sync connection')
def step(context):
SyncConnectionWizard.add_sync_connection()
@When('user unselects all the remote folders')
def step(context):
SyncConnectionWizard.deselect_all_remote_folders()
@Then('for user "{user}" sync folder "{sync_folder}" should not be displayed')
def step(context, user, sync_folder):
Toolbar.open_account(user)
has_sync_connection = SyncConnection.has_sync_connection(sync_folder)
with ensure(
'There should not be "{0}" folder sync connection, but found.', sync_folder
):
has_sync_connection.should.be.false
@When('the user navigates back in the sync connection wizard')
def step(context):
SyncConnectionWizard.back()
@When('the user removes the folder sync connection')
def step(context):
SyncConnection.remove_folder_sync_connection()
SyncConnection.confirm_folder_sync_connection_removal()
@Then('the file "{file_name}" should have status "{status}" in the activity tab')
def step(context, file_name, status):
Activity.has_sync_status(file_name, status)
@When('the user opens the sync connection wizard')
def step(context):
SyncConnectionWizard.open_sync_connection_wizard()
@Then('the button to open sync connection wizard should be disabled')
def step(context):
test.compare(
False,
SyncConnectionWizard.is_add_sync_folder_button_enabled(),
'Button to open sync connection wizard should be disabled',
)
@When('the user checks the activities of account "{account}"')
def step(context, account):
account = substitute_inline_codes(account)
Activity.select_synced_filter(account)
@Then('the following activities should be displayed in synced table')
def step(context):
activities = table_hashes(context.table)
for activity in activities:
activity["account"] = substitute_inline_codes(activity["account"])
has_activity = Activity.has_activity(
activity["resource"], activity["action"], activity["account"]
)
with ensure(
'Activity should exist: {0} | {1} | {2}',
activity["resource"],
activity["action"],
activity["account"],
):
has_activity.should.be.true
@Then('the following activities should not be displayed in synced table')
def step(context):
activities = table_hashes(context.table)
for activity in activities:
activity["account"] = substitute_inline_codes(activity["account"])
has_activity = Activity.has_activity(
activity["resource"], activity["action"], activity["account"]
)
with ensure(
'Activity should not exist: {0} | {1} | {2}',
activity["resource"],
activity["action"],
activity["account"],
):
has_activity.should.be.false
@Then(
r'the following activities (should|should not) be displayed in not synced table',
regexp=True,
)
def step(context, should_or_should_not):
expected = should_or_should_not == "should"
for row in context.table[1:]:
resource = row[0]
status = row[1]
account = substitute_inline_codes(row[2])
test.compare(
Activity.check_not_synced_table(resource, status, account),
expected,
'Resource should be displayed in the not synced table',
)
@When('the user unchecks the "|any|" filter')
def step(context, filter_option):
Activity.select_not_synced_filter(filter_option)
@Then('the following error message should appear in the client')
def step(context):
expected_error_message = '\n'.join(context.multiLineText)
actual_error_message = SyncConnection.get_permission_error_message()
# wait for error message to disappear
SyncConnection.wait_for_error_label(False)
test.compare(
actual_error_message,
expected_error_message,
f'Expected error message: "{expected_error_message}" but got: "{actual_error_message}"',
)
@Given('the user has waited for "|any|" seconds')
def step(context, wait_for):
squish.snooze(float(wait_for))
@When(
'the user unselects the following folders to sync in "Choose what to sync" window:'
)
def step(context):
SyncConnection.choose_what_to_sync()
folders = []
for row in context.table:
folders.append(row[0])
SyncConnectionWizard.unselect_folders_to_sync(
folders, new_sync_connection_wizard=False
)
+21
View File
@@ -0,0 +1,21 @@
from helpers.SetupClientHelper import get_resource_path
from helpers.SyncHelper import perform_file_explorer_vfs_action
from helpers.VFSFileHelper import is_placeholder_resource, is_file_downloaded
@Then('the placeholder file "|any|" should exist on the file system')
def step(context, file_name):
resource_path = get_resource_path(file_name)
test.compare(is_placeholder_resource(resource_path), True, f"File is a placeholder")
@Then('the file "|any|" should be downloaded')
def step(context, file_name):
resource_path = get_resource_path(file_name)
test.compare(is_file_downloaded(resource_path), True, f"File is downloaded")
@When(r'user "([^"]*)" marks (?:file|folder) "([^"]*)" as "(Free up space|Always keep on this device)" from the file explorer', regexp=True)
def step(context, user, resource, action):
resource_path = get_resource_path(resource, user)
perform_file_explorer_vfs_action(resource_path, action)