mirror of
https://github.com/status-im/status-desktop.git
synced 2025-01-21 20:09:37 +00:00
parent
fc15f82e1b
commit
4da388b5bc
0
test/ui-test/__init__.py
Normal file
0
test/ui-test/__init__.py
Normal file
@ -1,23 +1,29 @@
|
||||
|
||||
import configs
|
||||
import drivers.SquishDriver as driver
|
||||
import drivers.SquishDriverVerification as verification
|
||||
import drivers.SDKeyboardCommands as keyCommands
|
||||
|
||||
def start_application(app_name: str):
|
||||
driver.start_application(app_name)
|
||||
|
||||
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):
|
||||
driver.click_obj_by_name(objName)
|
||||
|
||||
|
||||
def input_text(text: str, objName: str):
|
||||
driver.type_text(objName, text)
|
||||
|
||||
|
||||
def object_not_enabled(objName: str):
|
||||
verification.verify_object_enabled(objName, 500, False)
|
||||
|
||||
|
||||
def str_to_bool(string: str):
|
||||
return string.lower() in ["yes", "true", "1", "y", "enabled"]
|
||||
|
||||
|
||||
def clear_input_text(objName: str):
|
||||
keyCommands.press_select_all(objName)
|
||||
keyCommands.press_backspace(objName)
|
||||
|
@ -1 +1,2 @@
|
||||
from . import squish
|
||||
from . import path
|
||||
from . import squish
|
10
test/ui-test/src/configs/path.py
Normal file
10
test/ui-test/src/configs/path.py
Normal file
@ -0,0 +1,10 @@
|
||||
import os
|
||||
|
||||
from utils.system_path import SystemPath
|
||||
|
||||
ROOT: SystemPath = SystemPath(__file__).resolve().parent.parent.parent
|
||||
TMP: SystemPath = ROOT / 'tmp'
|
||||
|
||||
AUT: SystemPath = SystemPath(os.getenv('AUT_PATH', ROOT.parent.parent / 'bin' / 'nim_status_client'))
|
||||
STATUS_APP_DATA = TMP / 'Status'
|
||||
STATUS_USER_DATA: SystemPath = STATUS_APP_DATA / 'data'
|
@ -1,3 +1,3 @@
|
||||
|
||||
UI_LOAD_TIMEOUT_MSEC = 5000
|
||||
APP_LOAD_TIMEOUT_MSEC = 60000
|
||||
PROCESS_LOAD_TIMEOUT_MSEC = 10000
|
||||
|
@ -10,18 +10,20 @@
|
||||
import copy
|
||||
import sys
|
||||
import test
|
||||
import time
|
||||
|
||||
import configs
|
||||
import names
|
||||
import object
|
||||
import objectMap
|
||||
import toplevelwindow
|
||||
import utils.FileManager as filesMngr
|
||||
# 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
|
||||
import squish
|
||||
import toplevelwindow
|
||||
from objectmaphelper import Wildcard
|
||||
from utils.system_path import SystemPath
|
||||
|
||||
from .aut import * # noqa
|
||||
from .context import * # noqa
|
||||
from .elements import * # noqa
|
||||
|
||||
# The default maximum timeout to find ui object
|
||||
@ -36,18 +38,16 @@ _MAX_WAIT_APP_TIMEOUT = 15000
|
||||
_SEARCH_IMAGES_PATH = "../shared/searchImages/"
|
||||
|
||||
|
||||
def start_application(app_name: str, attempt=2):
|
||||
try:
|
||||
ctx = squish.startApplication(app_name)
|
||||
assert squish.waitFor(lambda: ctx.isRunning, _MAX_WAIT_APP_TIMEOUT), 'Start application error'
|
||||
toplevelwindow.ToplevelWindow(squish.waitForObject(names.statusDesktop_mainWindow)).maximize()
|
||||
except (AssertionError, RuntimeError):
|
||||
if attempt:
|
||||
[ctx.detach() for ctx in squish.applicationContextList()]
|
||||
time.sleep(1)
|
||||
start_application(app_name, attempt - 1)
|
||||
else:
|
||||
raise
|
||||
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.
|
||||
|
@ -17,14 +17,17 @@ _MAX_WAIT_CLOSE_APP_TIMEOUT = 20
|
||||
import traceback
|
||||
|
||||
def verify_screen(objName: str, timeout: int=1000):
|
||||
from drivers.SquishDriver import is_loaded_visible_and_enabled
|
||||
result = is_loaded_visible_and_enabled(objName, timeout)
|
||||
test.verify(result, f'Verifying screen for real-name {objName}')
|
||||
|
||||
def verify_object_enabled(objName: str, timeout: int=_MIN_WAIT_OBJ_TIMEOUT, condition: bool=True):
|
||||
from drivers.SquishDriver import is_loaded_visible_and_enabled
|
||||
result = is_loaded_visible_and_enabled(objName, timeout)
|
||||
test.verify(result[0] == condition, "Checking if object enabled")
|
||||
|
||||
def verify_text_matching(objName: str, text: str):
|
||||
from drivers.SquishDriver import is_text_matching
|
||||
test.verify(is_text_matching(objName, text), "Checking if text matches")
|
||||
|
||||
def verify_text_matching_insensitive(obj, text: str):
|
||||
|
28
test/ui-test/src/drivers/aut.py
Normal file
28
test/ui-test/src/drivers/aut.py
Normal file
@ -0,0 +1,28 @@
|
||||
import configs
|
||||
from utils.system_path import SystemPath
|
||||
|
||||
import squish
|
||||
from . import context
|
||||
|
||||
|
||||
class ExecutableAut:
|
||||
|
||||
def __init__(self, fp: SystemPath):
|
||||
self.fp = fp
|
||||
self.ctx = None
|
||||
|
||||
def start(self, *args, attempt: int = 2):
|
||||
args = ' '.join([self.fp.name] + [str(arg) for arg in args])
|
||||
try:
|
||||
self.ctx = squish.startApplication(args)
|
||||
assert squish.waitFor(lambda: self.ctx.isRunning, configs.squish.APP_LOAD_TIMEOUT_MSEC)
|
||||
except (AssertionError, RuntimeError):
|
||||
if attempt:
|
||||
self.detach()
|
||||
self.start(*args, attempt - 1)
|
||||
else:
|
||||
raise
|
||||
|
||||
@staticmethod
|
||||
def detach():
|
||||
context.detach()
|
12
test/ui-test/src/drivers/context.py
Normal file
12
test/ui-test/src/drivers/context.py
Normal file
@ -0,0 +1,12 @@
|
||||
import configs
|
||||
import squish
|
||||
import time
|
||||
|
||||
|
||||
def detach():
|
||||
for ctx in squish.applicationContextList():
|
||||
ctx.detach()
|
||||
assert squish.waitFor(
|
||||
lambda: not ctx.isRunning, configs.squish.PROCESS_LOAD_TIMEOUT_MSEC), 'Detach application failed'
|
||||
# TODO: close by ctx.pid and then detach
|
||||
time.sleep(5)
|
24
test/ui-test/src/utils/system_path.py
Normal file
24
test/ui-test/src/utils/system_path.py
Normal file
@ -0,0 +1,24 @@
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
|
||||
class SystemPath(pathlib.Path):
|
||||
_accessor = pathlib._normal_accessor # noqa
|
||||
_flavour = pathlib._windows_flavour if os.name == 'nt' else pathlib._posix_flavour # noqa
|
||||
|
||||
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:
|
||||
self.rmdir()
|
||||
except OSError:
|
||||
if not ignore_errors:
|
||||
raise
|
@ -4,20 +4,21 @@
|
||||
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 drivers.SquishDriver as driver
|
||||
from steps.commonInitSteps import context_init
|
||||
|
||||
|
||||
|
||||
@OnScenarioStart
|
||||
def hook(context):
|
||||
context_init(context, testSettings)
|
||||
context.userData["scenario_name"] = context._data["title"]
|
||||
|
||||
|
||||
@OnScenarioEnd
|
||||
def hook(context):
|
||||
ctx = currentApplicationContext()
|
||||
ctx.detach()
|
||||
assert waitFor(lambda: not ctx.isRunning, _app_closure_timeout), 'Detach application failed'
|
||||
driver.detach()
|
||||
|
||||
|
||||
@OnStepEnd
|
||||
def hook(context):
|
||||
context.userData["step_name"] = context._data["text"]
|
||||
context.userData["step_name"] = context._data["text"]
|
||||
|
@ -4,6 +4,7 @@ import os
|
||||
|
||||
import utils.FileManager as filesMngr
|
||||
import common.Common as common
|
||||
import configs
|
||||
|
||||
from screens.StatusWelcomeScreen import StatusWelcomeScreen
|
||||
from screens.StatusMainScreen import StatusMainScreen
|
||||
@ -58,13 +59,12 @@ def context_init(context, testSettings, screenshot_on_fail = True):
|
||||
context.userData[_fixtures_root] = os.path.join(joined_path, "fixtures/")
|
||||
|
||||
def a_first_time_user_lands_on(context):
|
||||
filesMngr.erase_directory(context.userData[_status_data_folder])
|
||||
common.start_application(context.userData[_aut_name])
|
||||
common.start_application()
|
||||
|
||||
def a_user_starts_the_application_with_a_specific_data_folder(context, data_folder_path):
|
||||
filesMngr.clear_directory(context.userData["status_data_folder_path"])
|
||||
filesMngr.copy_directory(data_folder_path, context.userData["status_data_folder_path"])
|
||||
common.start_application(context.userData[_aut_name])
|
||||
filesMngr.clear_directory(configs.path.STATUS_USER_DATA)
|
||||
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):
|
||||
a_first_time_user_lands_on(context)
|
||||
@ -76,8 +76,7 @@ def a_user_lands_on_and_generates_new_key(context):
|
||||
welcome_screen.generate_new_key()
|
||||
|
||||
def a_first_time_user_lands_on_and_navigates_to_import_seed_phrase(context):
|
||||
filesMngr.erase_directory(context.userData[_status_data_folder])
|
||||
filesMngr.start_application(context.userData[_aut_name])
|
||||
common.start_application()
|
||||
welcome_screen = StatusWelcomeScreen()
|
||||
welcome_screen.agree_terms_conditions_and_navigate_to_import_seed_phrase()
|
||||
|
||||
|
@ -17,13 +17,14 @@ import time
|
||||
# *****************************************************************************
|
||||
import common.Common as common
|
||||
import steps.commonInitSteps as init_steps
|
||||
from drivers.SquishDriver import start_application
|
||||
import drivers.SquishDriver as driver
|
||||
from screens.StatusChatScreen import StatusChatScreen
|
||||
from screens.StatusMainScreen import StatusMainScreen
|
||||
|
||||
_statusMain = StatusMainScreen()
|
||||
_statusChat = StatusChatScreen()
|
||||
|
||||
|
||||
#########################
|
||||
### PRECONDITIONS region:
|
||||
#########################
|
||||
@ -32,30 +33,37 @@ _statusChat = StatusChatScreen()
|
||||
def step(context, data_folder_path):
|
||||
init_steps.a_user_starts_the_application_with_a_specific_data_folder(context, data_folder_path)
|
||||
|
||||
|
||||
@Given("the user restarts the app")
|
||||
def step(context):
|
||||
the_user_restarts_the_app(context)
|
||||
|
||||
|
||||
|
||||
@Given("the user joins chat room \"|any|\"")
|
||||
def step(context, room):
|
||||
the_user_joins_chat_room(room)
|
||||
|
||||
|
||||
@Given("the user clicks on escape key")
|
||||
def step(context):
|
||||
_statusMain.click_escape()
|
||||
|
||||
_statusMain.click_escape()
|
||||
|
||||
|
||||
@Given("the user clears input \"|any|\"")
|
||||
def step(context, input_component):
|
||||
common.clear_input_text(input_component)
|
||||
|
||||
common.clear_input_text(input_component)
|
||||
|
||||
|
||||
@Given("the user inputs the following \"|any|\" with ui-component \"|any|\"")
|
||||
def step(context, text, obj):
|
||||
the_user_inputs_the_following_text_with_uicomponent(text, obj)
|
||||
|
||||
the_user_inputs_the_following_text_with_uicomponent(text, obj)
|
||||
|
||||
|
||||
@Given("the user clicks on the following ui-component \"|any|\"")
|
||||
def step(context: any, obj: str):
|
||||
the_user_clicks_on_the_following_ui_component(obj)
|
||||
|
||||
|
||||
#########################
|
||||
### ACTIONS region:
|
||||
#########################
|
||||
@ -63,24 +71,29 @@ def step(context: any, obj: str):
|
||||
@When("the user restarts the app")
|
||||
def step(context):
|
||||
the_user_restarts_the_app(context)
|
||||
|
||||
|
||||
|
||||
@When("the user inputs the following \"|any|\" with ui-component \"|any|\"")
|
||||
def step(context, text, obj):
|
||||
the_user_inputs_the_following_text_with_uicomponent(text, obj)
|
||||
|
||||
|
||||
@When("the user clicks on the following ui-component \"|any|\"")
|
||||
def step(context: any, obj: str):
|
||||
init_steps.the_user_clicks_on_the_following_ui_component(obj)
|
||||
|
||||
|
||||
@When("the user joins chat room \"|any|\"")
|
||||
def step(context, room):
|
||||
the_user_joins_chat_room(room)
|
||||
|
||||
|
||||
# TODO remove when we have a reliable local mailserver
|
||||
@When("the user waits |any| seconds")
|
||||
def step(context, amount):
|
||||
time.sleep(2)
|
||||
|
||||
|
||||
#########################
|
||||
### VERIFICATIONS region:
|
||||
#########################
|
||||
@ -88,21 +101,24 @@ def step(context, amount):
|
||||
@Then("the following ui-component \"|any|\" is not enabled")
|
||||
def step(context, obj):
|
||||
common.object_not_enabled(obj)
|
||||
|
||||
|
||||
|
||||
###########################################################################
|
||||
### COMMON methods used in different steps given/when/then region:
|
||||
###########################################################################
|
||||
|
||||
def the_user_restarts_the_app(context: any):
|
||||
[ctx.detach() for ctx in squish.applicationContextList()]
|
||||
start_application(context.userData["aut_name"])
|
||||
|
||||
driver.detach()
|
||||
driver.start_application(clear_user_data=False)
|
||||
|
||||
|
||||
def the_user_joins_chat_room(room: str):
|
||||
init_steps.the_user_joins_chat_room(room)
|
||||
|
||||
|
||||
|
||||
def the_user_inputs_the_following_text_with_uicomponent(text: str, obj):
|
||||
common.input_text(text, obj)
|
||||
|
||||
|
||||
def the_user_clicks_on_the_following_ui_component(obj):
|
||||
init_steps.the_user_clicks_on_the_following_ui_component(obj)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user