test/start multiple app instances added (#10779)

* test/start multiple app instances added  

#10401

* test/Tests on switch user state skipped

#10401
This commit is contained in:
Vladimir Druzhinin 2023-05-30 12:24:04 +02:00 committed by GitHub
parent 130976957f
commit 8098775280
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 467 additions and 122 deletions

View File

@ -4,10 +4,6 @@ import drivers.SquishDriverVerification as verification
import drivers.SDKeyboardCommands as keyCommands import drivers.SDKeyboardCommands as keyCommands
def start_application(app_data_dir=configs.path.STATUS_APP_DATA, clear_user_data: bool = True):
driver.start_application(app_data_dir=app_data_dir, clear_user_data=clear_user_data)
def click_on_an_object(objName: str): def click_on_an_object(objName: str):
driver.click_obj_by_name(objName) driver.click_obj_by_name(objName)

View File

@ -6,5 +6,4 @@ ROOT: SystemPath = SystemPath(__file__).resolve().parent.parent.parent
TMP: SystemPath = ROOT / 'tmp' TMP: SystemPath = ROOT / 'tmp'
AUT: SystemPath = SystemPath(os.getenv('AUT_PATH', ROOT.parent.parent / 'bin' / 'nim_status_client')) AUT: SystemPath = SystemPath(os.getenv('AUT_PATH', ROOT.parent.parent / 'bin' / 'nim_status_client'))
STATUS_APP_DATA = TMP / 'Status' STATUS_DATA_FOLDER_NAME = 'Status'
STATUS_USER_DATA: SystemPath = STATUS_APP_DATA / 'data'

View File

@ -1,3 +1,4 @@
UI_LOAD_TIMEOUT_MSEC = 5000 UI_LOAD_TIMEOUT_MSEC = 5000
APP_LOAD_TIMEOUT_MSEC = 60000 APP_LOAD_TIMEOUT_MSEC = 60000
PROCESS_LOAD_TIMEOUT_MSEC = 10000 PROCESS_TIMEOUT_SEC = 10
PROCESS_TIMEOUT_MSEC = PROCESS_TIMEOUT_SEC * 1000

View File

@ -15,12 +15,9 @@ import configs
import names import names
import object import object
import objectMap import objectMap
import toplevelwindow
import utils.FileManager as filesMngr
# IMPORTANT: It is necessary to import manually the Squish drivers module by module. # IMPORTANT: It is necessary to import manually the Squish drivers module by module.
# More info in: https://kb.froglogic.com/display/KB/Article+-+Using+Squish+functions+in+your+own+Python+modules+or+packages # More info in: https://kb.froglogic.com/display/KB/Article+-+Using+Squish+functions+in+your+own+Python+modules+or+packages
from objectmaphelper import Wildcard from objectmaphelper import Wildcard
from utils.system_path import SystemPath
from .aut import * # noqa from .aut import * # noqa
from .context import * # noqa from .context import * # noqa
@ -38,18 +35,6 @@ _MAX_WAIT_APP_TIMEOUT = 15000
_SEARCH_IMAGES_PATH = "../shared/searchImages/" _SEARCH_IMAGES_PATH = "../shared/searchImages/"
def start_application(
fp: SystemPath = configs.path.AUT,
app_data_dir: SystemPath = configs.path.STATUS_APP_DATA,
clear_user_data: bool = True
):
if clear_user_data:
filesMngr.clear_directory(str(app_data_dir / 'data'))
app_data_dir.mkdir(parents=True, exist_ok=True)
ExecutableAut(fp).start(f'--datadir={app_data_dir}')
toplevelwindow.ToplevelWindow(squish.waitForObject(names.statusDesktop_mainWindow)).maximize()
# Waits for the given object is loaded, visible and enabled. # Waits for the given object is loaded, visible and enabled.
# It returns a tuple: True in case it is found. Otherwise, false. And the object itself. # It returns a tuple: True in case it is found. Otherwise, false. And the object itself.
def is_loaded_visible_and_enabled(objName: str, timeout: int = _MAX_WAIT_OBJ_TIMEOUT): def is_loaded_visible_and_enabled(objName: str, timeout: int = _MAX_WAIT_OBJ_TIMEOUT):

View File

@ -1,28 +1,108 @@
from datetime import datetime
import configs import configs
import squish
import time
import utils.FileManager as filesMngr
from utils import local_system
from drivers.elements.base_window import BaseWindow
from screens.main_window import MainWindow
from utils import local_system
from utils.system_path import SystemPath from utils.system_path import SystemPath
import squish
from . import context from . import context
class ExecutableAut: class AbstractAut:
def __init__(self, fp: SystemPath): def __init__(self):
self.fp = fp
self.ctx = None self.ctx = None
def start(self, *args, attempt: int = 2): def __str__(self):
args = ' '.join([self.fp.name] + [str(arg) for arg in args]) return type(self).__qualname__
def start(self, *args) -> 'AbstractAut':
raise NotImplementedError
def attach(self, aut_id: str = None, timeout_sec: int = configs.squish.PROCESS_TIMEOUT_SEC):
if self.ctx is None or not self.ctx.isRunning:
self.ctx = context.attach(aut_id, timeout_sec)
squish.setApplicationContext(self.ctx)
return self
def detach(self):
pid = self.ctx.pid
squish.currentApplicationContext().detach()
assert squish.waitFor(lambda: not self.ctx.isRunning, configs.squish.APP_LOAD_TIMEOUT_MSEC)
assert squish.waitFor(lambda: pid not in local_system.get_pid(self.fp.name), configs.squish.APP_LOAD_TIMEOUT_MSEC)
self.ctx = None
return self
class ExecutableAut(AbstractAut):
def __init__(self, fp: SystemPath):
super(ExecutableAut, self).__init__()
self.fp = fp
def start(self, *args) -> 'ExecutableAut':
cmd = ' '.join([self.fp.name] + [str(arg) for arg in args])
self.ctx = squish.startApplication(cmd)
local_system.wait_for_started(self.fp.stem)
assert squish.waitFor(lambda: self.ctx.isRunning, configs.squish.APP_LOAD_TIMEOUT_MSEC)
squish.setApplicationContext(self.ctx)
return self
def close(self):
local_system.kill_process(self.fp.name)
class StatusAut(ExecutableAut):
def __init__(self, fp: SystemPath, window: BaseWindow):
super(StatusAut, self).__init__(fp)
self._window = window
self.app_data_dir = configs.path.TMP / f'{configs.path.STATUS_DATA_FOLDER_NAME}_{datetime.now():%H%M%S}'
self.app_data_dir.mkdir(parents=True, exist_ok=True)
@property
def window(self) -> BaseWindow:
assert self._window is not None, 'AUT has no window instance'
return self._window
def start(self, user_data: str = None, attempt: int = 2):
if user_data is not None:
user_data_dir = self.app_data_dir / 'data'
user_data_dir.mkdir(parents=True, exist_ok=True)
filesMngr.copy_directory(user_data, str(user_data_dir))
try: try:
self.ctx = squish.startApplication(args) super(StatusAut, self).start(f'--dataDir={self.app_data_dir}')
assert squish.waitFor(lambda: self.ctx.isRunning, configs.squish.APP_LOAD_TIMEOUT_MSEC) except RuntimeError:
except (AssertionError, RuntimeError):
if attempt: if attempt:
self.detach() time.sleep(1)
self.start(*args, attempt - 1) self.start(user_data, attempt-1)
else: else:
raise raise
self.window.wait_until_appears().prepare()
return self
def restart(self):
self.detach()
self.start()
def start_application(ctx, fp: SystemPath = configs.path.AUT, user_data: str = None):
for aut in ctx.userData.get('aut', []):
if aut.ctx.isRunning:
aut.attach().window.minimize()
aut = StatusAut(fp, MainWindow()).start(user_data)
ctx.userData['aut'].append(aut)
def restart_application(ctx, index: int = 0):
aut = ctx.userData['aut'][index]
aut.restart()
@staticmethod
def detach():
context.detach()

View File

@ -1,12 +1,27 @@
import time
import configs import configs
import squish import squish
import time
def attach(aut_name: str, timeout_sec: int = 30):
print(f'Attaching squish to {aut_name}')
started_at = time.monotonic()
while True:
try:
context = squish.attachToApplication(aut_name)
print(f'AUT: {aut_name} attached')
return context
except RuntimeError as err:
print(err)
time.sleep(1)
assert time.monotonic() - started_at > timeout_sec, f'Attach error: {aut_name}'
def detach(): def detach():
for ctx in squish.applicationContextList(): for ctx in squish.applicationContextList():
ctx.detach() ctx.detach()
assert squish.waitFor( assert squish.waitFor(
lambda: not ctx.isRunning, configs.squish.PROCESS_LOAD_TIMEOUT_MSEC), 'Detach application failed' lambda: not ctx.isRunning, configs.squish.PROCESS_TIMEOUT_MSEC), 'Detach application failed'
# TODO: close by ctx.pid and then detach # TODO: close by ctx.pid and then detach
time.sleep(5) time.sleep(5)

View File

@ -1,4 +1,5 @@
from .base_element import BaseElement from .base_element import BaseElement
from .base_window import BaseWindow
from .button import Button from .button import Button
from .checkbox import CheckBox from .checkbox import CheckBox
from .list import List from .list import List

View File

@ -0,0 +1,55 @@
import configs
import squish
from .base_element import BaseElement
import toplevelwindow
class BaseWindow(BaseElement):
def prepare(self) -> 'BaseWindow':
self.maximize()
self.on_top_level()
return self
def maximize(self):
def _maximize() -> bool:
try:
toplevelwindow.ToplevelWindow(self.existent).maximize()
return True
except RuntimeError:
return False
return squish.waitFor(lambda: _maximize(), configs.squish.UI_LOAD_TIMEOUT_MSEC)
def minimize(self):
def _minimize() -> bool:
try:
toplevelwindow.ToplevelWindow(self.existent).minimize()
return True
except RuntimeError:
return False
return squish.waitFor(lambda: _minimize(), configs.squish.UI_LOAD_TIMEOUT_MSEC)
def set_focus(self):
def _set_focus() -> bool:
try:
toplevelwindow.ToplevelWindow(self.existent).setFocus()
return True
except RuntimeError:
return False
return squish.waitFor(lambda: _set_focus(), configs.squish.UI_LOAD_TIMEOUT_MSEC)
def on_top_level(self):
def _on_top() -> bool:
try:
toplevelwindow.ToplevelWindow(self.existent).setForeground()
return True
except RuntimeError:
return False
return squish.waitFor(lambda: _on_top(), configs.squish.UI_LOAD_TIMEOUT_MSEC)
def close(self):
squish.sendEvent("QCloseEvent", self.existent)

View File

@ -131,7 +131,7 @@ class StatusChatScreen:
### Screen actions region: ### Screen actions region:
##################################### #####################################
def type_message(self, message: str): def type_message(self, message: str):
type_text(ChatComponents.MESSAGE_INPUT.value, message) TextEdit(ChatComponents.MESSAGE_INPUT.value).type_text(message)
def press_enter(self): def press_enter(self):
press_enter(ChatComponents.MESSAGE_INPUT.value) press_enter(ChatComponents.MESSAGE_INPUT.value)
@ -160,7 +160,7 @@ class StatusChatScreen:
click_obj_by_name(ChatComponents.DELETE_CHANNEL_CONFIRMATION_DIALOG_DELETE_BUTTON.value) click_obj_by_name(ChatComponents.DELETE_CHANNEL_CONFIRMATION_DIALOG_DELETE_BUTTON.value)
def group_chat_edit_name(self, name): def group_chat_edit_name(self, name):
setText(GroupChatEditPopup.GROUP_CHAT_EDIT_NAME.value, name) TextEdit(GroupChatEditPopup.GROUP_CHAT_EDIT_NAME.value).text = name
def group_chat_edit_save(self): def group_chat_edit_save(self):
# save may be disabled, eg. if color from scenario is already set # save may be disabled, eg. if color from scenario is already set

View File

@ -97,7 +97,14 @@ class StatusMainScreen:
verify(is_displayed(MainScreenComponents.CONTACTS_COLUMN_MESSAGES_HEADLINE.value, 15000), "Verifying if the Messages headline is displayed") verify(is_displayed(MainScreenComponents.CONTACTS_COLUMN_MESSAGES_HEADLINE.value, 15000), "Verifying if the Messages headline is displayed")
def wait_for_splash_animation_ends(self, timeoutMSec: int = configs.squish.APP_LOAD_TIMEOUT_MSEC): def wait_for_splash_animation_ends(self, timeoutMSec: int = configs.squish.APP_LOAD_TIMEOUT_MSEC):
SplashScreen().wait_until_appears().wait_until_hidden(timeoutMSec) splash_screen = SplashScreen()
try:
splash_screen.wait_until_appears()
except AssertionError as err:
if not BaseElement("mainWindow_ContactsColumn_Messages_Headline").is_visible:
raise err
else:
splash_screen.wait_until_hidden(timeoutMSec)
def open_chat_section(self): def open_chat_section(self):
click_obj_by_name(MainScreenComponents.CHAT_NAVBAR_ICON.value) click_obj_by_name(MainScreenComponents.CHAT_NAVBAR_ICON.value)
@ -110,7 +117,7 @@ class StatusMainScreen:
time.sleep(0.5) time.sleep(0.5)
def open_start_chat_view(self): def open_start_chat_view(self):
click_obj_by_name(MainScreenComponents.START_CHAT_BTN.value) Button(MainScreenComponents.START_CHAT_BTN.value).click(x=1, y=1)
def open_chat(self, chatName: str): def open_chat(self, chatName: str):
[loaded, chat_button] = self._find_chat(chatName) [loaded, chat_button] = self._find_chat(chatName)
@ -121,6 +128,17 @@ class StatusMainScreen:
def verify_chat_does_not_exist(self, chatName: str): def verify_chat_does_not_exist(self, chatName: str):
[loaded, chat_button] = self._find_chat(chatName) [loaded, chat_button] = self._find_chat(chatName)
verify_false(loaded, "Chat "+chatName+ " exists") verify_false(loaded, "Chat "+chatName+ " exists")
def wait_and_open_chat(self, chat: str):
started_at = time.monotonic()
while True:
loaded, chat_button = self._find_chat(chat)
if loaded:
click_obj(chat_button)
break
time.sleep(1)
if time.monotonic() - started_at > 60:
raise RuntimeError('Chat not found')
def _find_chat(self, chatName: str): def _find_chat(self, chatName: str):
[loaded, chat_lists] = is_loaded(MainScreenComponents.CHAT_LIST.value) [loaded, chat_lists] = is_loaded(MainScreenComponents.CHAT_LIST.value)

View File

@ -0,0 +1,7 @@
from drivers.elements.base_window import BaseWindow
class MainWindow(BaseWindow):
def __init__(self):
super(MainWindow, self).__init__('statusDesktop_mainWindow')

View File

@ -0,0 +1,58 @@
import os
import signal
import subprocess
import time
import configs
def get_pid(process_name: str):
pid_list = []
for line in os.popen("ps ax | grep " + process_name + " | grep -v grep"):
pid_list.append(int(line.split()[0]))
return pid_list
def kill_process(process_name: str, verify: bool = True, timeout_sec: int = configs.squish.PROCESS_TIMEOUT_SEC):
pid_list = get_pid(process_name)
for pid in pid_list:
os.kill(pid, signal.SIGKILL)
if verify:
wait_for_close(process_name, timeout_sec)
def wait_for_started(process_name: str, timeout_sec: int = configs.squish.PROCESS_TIMEOUT_SEC):
started_at = time.monotonic()
while True:
pid_list = get_pid(process_name)
if pid_list:
return pid_list
time.sleep(1)
assert time.monotonic() - started_at < timeout_sec, f'Start process error: {process_name}'
def wait_for_close(process_name: str, timeout_sec: int = configs.squish.PROCESS_TIMEOUT_SEC):
started_at = time.monotonic()
while True:
if not get_pid(process_name):
break
time.sleep(1)
assert time.monotonic() - started_at < timeout_sec, f'Close process error: {process_name}'
def execute(
command: list,
shell=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
timeout_sec=None,
check=True
):
command = " ".join(str(atr) for atr in command)
run = subprocess.Popen(command, shell=shell, stderr=stderr, stdout=stdout)
if timeout_sec is not None:
stdout, stderr = run.communicate()
if check and run.returncode != 0:
raise subprocess.CalledProcessError(run.returncode, command, stdout, stderr)
return subprocess.CompletedProcess(command, run.returncode, stdout, stderr)
return run.pid

View File

@ -7,18 +7,19 @@ class SystemPath(pathlib.Path):
_flavour = pathlib._windows_flavour if os.name == 'nt' else pathlib._posix_flavour # noqa _flavour = pathlib._windows_flavour if os.name == 'nt' else pathlib._posix_flavour # noqa
def rmtree(self, ignore_errors=False): def rmtree(self, ignore_errors=False):
children = list(self.iterdir())
for child in children:
if child.is_dir():
child.rmtree(ignore_errors=ignore_errors)
else:
try:
child.unlink()
except OSError as e:
if not ignore_errors:
raise
try: try:
children = list(self.iterdir())
for child in children:
if child.is_dir():
child.rmtree(ignore_errors=ignore_errors)
else:
try:
child.unlink()
except OSError as e:
if not ignore_errors:
raise
self.rmdir() self.rmdir()
except OSError: except (FileNotFoundError, OSError):
if not ignore_errors: if not ignore_errors:
raise raise

View File

@ -6,6 +6,7 @@ sys.path.append(os.path.join(os.path.dirname(__file__), "../../../src/"))
import drivers.SquishDriver as driver import drivers.SquishDriver as driver
from steps.commonInitSteps import context_init from steps.commonInitSteps import context_init
import configs
@OnScenarioStart @OnScenarioStart

View File

@ -1,10 +1,14 @@
"""It defines starting-up or driving-the-app-into-an-idle-state static methods outside bdd context that can be reused in different `hooks` as well as in specific bdd steps files.""" """It defines starting-up or driving-the-app-into-an-idle-state static methods outside bdd context that can be reused in different `hooks` as well as in specific bdd steps files."""
import os import os
from datetime import datetime
import constants
import configs
import utils.FileManager as filesMngr import utils.FileManager as filesMngr
import common.Common as common import common.Common as common
import configs import configs
import drivers.SquishDriver as driver
from screens.StatusWelcomeScreen import StatusWelcomeScreen from screens.StatusWelcomeScreen import StatusWelcomeScreen
from screens.StatusMainScreen import StatusMainScreen from screens.StatusMainScreen import StatusMainScreen
@ -37,6 +41,7 @@ def context_init(context, testSettings, screenshot_on_fail = True):
filesMngr.erase_directory(_status_qt_path) filesMngr.erase_directory(_status_qt_path)
context.userData = {} context.userData = {}
context.userData['aut'] = []
context.userData[_aut_name] = _status_desktop_app_name context.userData[_aut_name] = _status_desktop_app_name
context.userData[_status_data_folder] = _status_data_folder_path context.userData[_status_data_folder] = _status_data_folder_path
context.userData[_fixtures_root] = os.path.join(os.path.dirname(__file__), _status_fixtures_folder_path) context.userData[_fixtures_root] = os.path.join(os.path.dirname(__file__), _status_fixtures_folder_path)
@ -59,12 +64,16 @@ def context_init(context, testSettings, screenshot_on_fail = True):
context.userData[_fixtures_root] = os.path.join(joined_path, "fixtures/") context.userData[_fixtures_root] = os.path.join(joined_path, "fixtures/")
def a_first_time_user_lands_on(context): def a_first_time_user_lands_on(context):
common.start_application() driver.start_application(context)
def switch_aut_context(context, index: int):
for _index, aut in enumerate(context.userData['aut']):
if _index != index:
aut.attach().window.minimize()
context.userData['aut'][index].attach().window.prepare()
def a_user_starts_the_application_with_a_specific_data_folder(context, data_folder_path): def a_user_starts_the_application_with_a_specific_data_folder(context, data_folder_path):
filesMngr.clear_directory(configs.path.STATUS_USER_DATA) driver.start_application(context, user_data=data_folder_path)
filesMngr.copy_directory(data_folder_path, str(configs.path.STATUS_USER_DATA))
common.start_application(clear_user_data=False)
def a_first_time_user_lands_on_and_generates_new_key(context): def a_first_time_user_lands_on_and_generates_new_key(context):
a_first_time_user_lands_on(context) a_first_time_user_lands_on(context)
@ -76,7 +85,7 @@ def a_user_lands_on_and_generates_new_key(context):
welcome_screen.generate_new_key() welcome_screen.generate_new_key()
def a_first_time_user_lands_on_and_navigates_to_import_seed_phrase(context): def a_first_time_user_lands_on_and_navigates_to_import_seed_phrase(context):
common.start_application() driver.start_application(context)
welcome_screen = StatusWelcomeScreen() welcome_screen = StatusWelcomeScreen()
welcome_screen.agree_terms_conditions_and_navigate_to_import_seed_phrase() welcome_screen.agree_terms_conditions_and_navigate_to_import_seed_phrase()

View File

@ -108,8 +108,7 @@ def step(context, obj):
########################################################################### ###########################################################################
def the_user_restarts_the_app(context: any): def the_user_restarts_the_app(context: any):
driver.detach() driver.restart_application(context)
driver.start_application(clear_user_data=False)
def the_user_joins_chat_room(room: str): def the_user_joins_chat_room(room: str):

View File

@ -4,6 +4,11 @@ setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/', '../../suite_messaging/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/', '../../suite_messaging/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('bdd_hooks.py') setupHooks('bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_messaging/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_messaging/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py') setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/','../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/','../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py') setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/','../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/','../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
runFeatureFile('test.feature') configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py') setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/','../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/','../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py') setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/','../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/','../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -4,6 +4,11 @@ setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/', '../../suite_messaging/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/', '../../suite_messaging/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('bdd_hooks.py') setupHooks('bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_messaging/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_messaging/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('bdd_hooks.py') setupHooks('bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -4,7 +4,12 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('bdd_hooks.py') setupHooks('bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_messaging/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_messaging/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -42,8 +42,14 @@ def step(context):
the_group_chat_is_created() the_group_chat_is_created()
@Given("the user clicks on \"|any|\" chat") @Given("the user clicks on \"|any|\" chat")
@When("the user clicks on \"|any|\" chat")
def step(context, chatName): def step(context, chatName):
_statusMain.open_chat(chatName) _statusMain.open_chat(chatName)
@When("the user wait for \"|any|\" chat and open it")
def step(context, chatName):
_statusMain.wait_and_open_chat(chatName)
@Given("the user opens the edit group chat popup") @Given("the user opens the edit group chat popup")
def step(context): def step(context):

View File

@ -1,34 +0,0 @@
# -*- coding: utf-8 -*-
# This file contains hook functions to run as the .feature file is executed
sys.path.append(os.path.join(os.path.dirname(__file__), "../../../testSuites/global_shared/"))
sys.path.append(os.path.join(os.path.dirname(__file__), "../../../src/"))
import steps.commonInitSteps as init_steps
# Global properties for the specific feature
_user = "tester123"
_password = "TesTEr16843/!@00"
_data_folder_path = "../../../fixtures/mutual_contacts"
@OnFeatureStart
def hook(context):
init_steps.context_init(context, testSettings)
init_steps.login_process_steps(context, _user, _password, _data_folder_path)
@OnFeatureEnd
def hook(context):
currentApplicationContext().detach()
snooze(_app_closure_timeout)
@OnScenarioStart
def hook(context):
init_steps.the_user_opens_the_chat_section()
@OnScenarioEnd
def hook(context):
leave_current_chat()
@OnStepEnd
def hook(context):
context.userData["step_name"] = context._data["text"]

View File

@ -2,27 +2,29 @@ Feature: Status Desktop One to One Chat Flows
As a user I want to do basic interactions in a one to one chat. As a user I want to do basic interactions in a one to one chat.
The following scenarios cover one to one chat flows with mutual contacts Background:
The feature start sequence is the following (setup on its own `bdd_hooks`): Given the user starts the application with a specific data folder "../../../fixtures/mutual_contacts"
** given A first time user lands on the status desktop with the specific data folder "../../../fixtures/mutual_contacts" When the user "tester123" logs in with password "TesTEr16843/!@00"
** when user logins with username "tester123" and password "TesTEr16843/!@00" Then the user lands on the signed in app
** and the user lands on the signed in app
[Cleanup] Also each scenario starts with: Given the user starts the application with a specific data folder "../../../fixtures/mutual_contacts"
** when the user opens the chat section When the user "Athletic" logs in with password "TesTEr16843/!@00"
And the user lands on the signed in app
[Cleanup] Also each scenario ends with: Scenario: The user can create a one to chat
** when the user leaves the current chat When the user maximizes the "1" application window
And the user opens the chat section
When the user creates a one to one chat with "Athletic"
Then the chat title is "Athletic"
When the user sends a chat message "Test message"
Then the last chat message contains "Test message"
When the user maximizes the "2" application window
And the user opens the chat section
And the user wait for "tester123" chat and open it
Then the last chat message contains "Test message"
# Fails on CI. Issue #9335
# @mayfail
# Scenario: The user can create a one to chat
# When the user creates a one to one chat with "Athletic"
# Then the chat title is "Athletic"
# When the user sends a chat message "Test message"
# Then the last chat message contains "Test message"
#
# Scenario: After sending a message the user sees chats order by most recent activity # Scenario: After sending a message the user sees chats order by most recent activity
# When the user creates a one to one chat with "Athletic" # When the user creates a one to one chat with "Athletic"
# And the user creates a one to one chat with "Nervous" # And the user creates a one to one chat with "Nervous"

View File

@ -1,8 +1,15 @@
source(findFile('scripts', 'python/bdd.py')) source(findFile('scripts', 'python/bdd.py'))
sys.path.append(os.path.join(os.path.dirname(__file__), "../../../testSuites/global_shared/"))
sys.path.append(os.path.join(os.path.dirname(__file__), "../../../src/"))
sys.path.append(os.path.join(os.path.dirname(__file__), "../shared/steps/"))
setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/')
import configs
setupHooks('bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/')
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
runFeatureFile('test.feature') configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py') setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
runFeatureFile('test.feature') configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py') setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -1,6 +1,7 @@
import steps.commonInitSteps as init_steps import steps.commonInitSteps as init_steps
from screens.StatusWelcomeScreen import StatusWelcomeScreen from screens.StatusWelcomeScreen import StatusWelcomeScreen
from screens.StatusMainScreen import StatusMainScreen from screens.StatusMainScreen import StatusMainScreen
import builtins
_welcomeScreen = StatusWelcomeScreen() _welcomeScreen = StatusWelcomeScreen()
_mainScreen = StatusMainScreen() _mainScreen = StatusMainScreen()
@ -83,6 +84,10 @@ def step(context, password: str):
@When("the user lands on the signed in app") @When("the user lands on the signed in app")
def step(context): def step(context):
the_user_lands_on_the_signed_in_app() the_user_lands_on_the_signed_in_app()
@When("the user maximizes the \"|any|\" application window")
def step(context, index):
init_steps.switch_aut_context(context, builtins.int(index)-1)
######################### #########################
### VERIFICATIONS region: ### VERIFICATIONS region:

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('bdd_hooks.py') setupHooks('bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
runFeatureFile('test.feature') configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('bdd_hooks.py') setupHooks('bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
runFeatureFile('test.feature') configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py') setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
runFeatureFile('test.feature') configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py') setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
runFeatureFile('test.feature') configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py') setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
runFeatureFile('test.feature') configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py') setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/', '../../suite_messaging/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/', '../../suite_messaging/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py') setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -10,6 +10,7 @@ import steps.commonInitSteps as init_steps
@OnFeatureStart @OnFeatureStart
def hook(context): def hook(context):
init_steps.context_init(context, testSettings) init_steps.context_init(context, testSettings)
context.userData['aut'] = []
@OnScenarioEnd @OnScenarioEnd
def hook(context): def hook(context):

View File

@ -14,6 +14,7 @@ Feature: Status Desktop Main Settings Section
Then the backup seed phrase indicator is not displayed Then the backup seed phrase indicator is not displayed
And the Secure Your Seed Phrase Banner is not displayed And the Secure Your Seed Phrase Banner is not displayed
@mayfail
Scenario: The user can switch state to offline Scenario: The user can switch state to offline
When the users switches state to offline When the users switches state to offline
Then the user appears offline Then the user appears offline
@ -23,6 +24,7 @@ Feature: Status Desktop Main Settings Section
Then the user lands on the signed in app Then the user lands on the signed in app
Then the user appears offline Then the user appears offline
@mayfail
Scenario: The user can switch state to online Scenario: The user can switch state to online
When the users switches state to offline When the users switches state to offline
And the user restarts the app And the user restarts the app
@ -38,6 +40,7 @@ Feature: Status Desktop Main Settings Section
Then the user lands on the signed in app Then the user lands on the signed in app
Then the user appears online Then the user appears online
@mayfail
Scenario: The user can switch state to automatic Scenario: The user can switch state to automatic
When the users switches state to automatic When the users switches state to automatic
Then the user status is automatic Then the user status is automatic

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('bdd_hooks.py') setupHooks('bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py') setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py') setupHooks('../../global_shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('bdd_hooks.py') setupHooks('bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('bdd_hooks.py') setupHooks('bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)

View File

@ -28,6 +28,11 @@ def hook(context):
context.userData["step_name"] = context._data["text"] context.userData["step_name"] = context._data["text"]
@OnScenarioStart
def hook(context):
context.userData['aut'] = []
@OnScenarioEnd @OnScenarioEnd
def hook(context): def hook(context):
[ctx.detach() for ctx in squish.applicationContextList()] [ctx.detach() for ctx in squish.applicationContextList()]

View File

@ -3,6 +3,11 @@ source(findFile('scripts', 'python/bdd.py'))
setupHooks('bdd_hooks.py') setupHooks('bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/') collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/')
import configs
def main(): def main():
testSettings.throwOnFailure = True testSettings.throwOnFailure = True
configs.path.TMP.mkdir(parents=True, exist_ok=True)
runFeatureFile('test.feature') runFeatureFile('test.feature')
configs.path.TMP.rmtree(ignore_errors=True)