diff --git a/test/desktop.sikuli/pytest.ini b/test/desktop.sikuli/pytest.ini new file mode 100644 index 0000000000..140a62df5b --- /dev/null +++ b/test/desktop.sikuli/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = -s -v --junitxml=result.xml --tb=line diff --git a/test/desktop.sikuli/requirements.txt b/test/desktop.sikuli/requirements.txt new file mode 100644 index 0000000000..beeef104fa --- /dev/null +++ b/test/desktop.sikuli/requirements.txt @@ -0,0 +1,16 @@ +atomicwrites==1.2.1 +attrs==18.2.0 +certifi==2018.8.24 +chardet==3.0.4 +funcsigs==1.0.2 +idna==2.7 +jip==0.9.13 +more-itertools==4.3.0 +pathlib2==2.3.2 +pluggy==0.7.1 +py==1.6.0 +pytest==2.7.2 +requests==2.19.1 +scandir==1.9.0 +six==1.11.0 +urllib3==1.23 \ No newline at end of file diff --git a/test/desktop.sikuli/tests/__init__.py b/test/desktop.sikuli/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/desktop.sikuli/tests/base_test_case.py b/test/desktop.sikuli/tests/base_test_case.py new file mode 100644 index 0000000000..4958fd7a98 --- /dev/null +++ b/test/desktop.sikuli/tests/base_test_case.py @@ -0,0 +1,52 @@ +import org.sikuli.script.SikulixForJython +import pytest +from sikuli import * +from subprocess import check_output + + +def mac_os_setup(): + check_output(['hdiutil', 'attach', 'nightly.dmg']) + check_output(['cp', '-rf', '/Volumes/Status/Status.app', '/Applications/']) + check_output(['hdiutil', 'detach', '/Volumes/Status/']) + import time + time.sleep(10) + openApp('Status.app') + + +def mac_os_teardown(): + closeApp('Status.app') + for dir in '/Applications/Status.app', '/Library/Application\ Support/StatusIm', \ + '/Users/yberdnyk/Library/Caches/StatusIm': + check_output(['rm', '-rf', dir]) + + +def linux_setup(): + check_output(['chmod', '+x', './nightly.AppImage']) + check_output(['./nightly.AppImage', '--appimage-extract']) + check_output(['chmod', '+x', '/src/squashfs-root/AppRun']) + openApp('/src/squashfs-root/AppRun') + + +def linux_teardown(): + pass + # check_output(['killall', 'ubuntu-server']) + # check_output(['rm', '-rf', '~/.local/share/StatusIm/']) + # check_output(['rm', '-rf', '~/.cache/StatusIm/']) + + +class BaseTestCase: + Settings.ActionLogs = 0 + Settings.OcrTextSearch = True + Settings.OcrTextRead = True + + def setup_method(self, method): + if pytest.config.getoption('os') == 'linux': + linux_setup() + else: + mac_os_setup() + + def teardown_method(self, method): + if pytest.config.getoption('os') == 'linux': + linux_teardown() + else: + mac_os_teardown() diff --git a/test/desktop.sikuli/tests/conftest.py b/test/desktop.sikuli/tests/conftest.py new file mode 100644 index 0000000000..622a9f3891 --- /dev/null +++ b/test/desktop.sikuli/tests/conftest.py @@ -0,0 +1,56 @@ +import org.sikuli.script.SikulixForJython +from sikuli import * +import pytest +import requests +import re +from urllib import urlretrieve +from subprocess import check_output + +from tests.report import save_test_result, TEST_REPORT_DIR + + +def pytest_addoption(parser): + parser.addoption('--os', + action='store', + default='linux') + parser.addoption("--nightly", + action="store", + default=True) + parser.addoption('--dmg', + action='store', + default=None, + help='Url or local path to dmg') + + +def pytest_configure(config): + if config.getoption('nightly'): + raw_data = requests.request('GET', 'https://status-im.github.io/nightly/').text + if config.getoption('os') == 'linux': + app_url = re.findall('href="(.*AppImage)', raw_data)[0] + urlretrieve(app_url, 'nightly.AppImage') + else: + dmg_url = re.findall('href="(.*dmg)', raw_data)[0] + urlretrieve(dmg_url, 'nightly.dmg') + + +@pytest.mark.hookwrapper +def pytest_runtest_makereport(item, call): + import logging + # logging.basicConfig(filename='%s/%s.log' % (TEST_REPORT_DIR, item.name), filemode='w', level=logging.INFO) + outcome = yield + report = outcome.get_result() + if report.when == 'call': + pass + # save_test_result(item, report) + + +def after_all(): + if pytest.config.getoption('os') == 'linux': + check_output(['rm', '-rf', 'nightly.AppImage']) + else: + check_output(['rm', '-rf', 'nightly.dmg']) + + +@pytest.fixture(scope="session", autouse=True) +def before_all(request): + request.addfinalizer(finalizer=after_all) diff --git a/test/desktop.sikuli/tests/report.py b/test/desktop.sikuli/tests/report.py new file mode 100644 index 0000000000..6415601e2e --- /dev/null +++ b/test/desktop.sikuli/tests/report.py @@ -0,0 +1,33 @@ +import json +import os +from subprocess import check_output + +TEST_REPORT_DIR = "%s/../report" % os.path.dirname(os.path.abspath(__file__)) + + +def get_test_report_file_path(test_name): + file_name = "%s.json" % test_name + if not os.path.exists(TEST_REPORT_DIR): + os.makedirs(TEST_REPORT_DIR) + return os.path.join(TEST_REPORT_DIR, file_name) + + +def get_testrail_case_id(obj): + if 'testrail_id' in obj.keywords._markers: + return obj.keywords._markers['testrail_id'].args[0] + + +def save_test_result(test, report): + test_name = test.name + file_path = get_test_report_file_path(test_name) + if report.failed: + check_output(['screencapture', '%s/%s.png' % (TEST_REPORT_DIR, test_name)]) + with open('%s/%s.log' % (TEST_REPORT_DIR, test_name), 'r') as log: + steps = [i for i in log] + test_dict = { + 'testrail_case_id': get_testrail_case_id(test), + 'name': test_name, + 'steps': steps, + 'error': str(report.longrepr.reprcrash.message), + 'screenshot': test_name + '.png'} + json.dump(test_dict, open(file_path, 'w')) diff --git a/test/desktop.sikuli/tests/test_create_account.py b/test/desktop.sikuli/tests/test_create_account.py new file mode 100644 index 0000000000..ad2defb5a8 --- /dev/null +++ b/test/desktop.sikuli/tests/test_create_account.py @@ -0,0 +1,16 @@ +from tests.base_test_case import BaseTestCase +from views.sign_in_view import SignInView + + +class TestCreateAccount(BaseTestCase): + + def test_create_account(self): + sign_in = SignInView() + sign_in.create_account_button.click() + sign_in.password_input.input_value('123456') + sign_in.next_button.click() + sign_in.confirm_password_input.input_value('123456') + sign_in.next_button.click() + sign_in.username_input.input_value('test') + sign_in.next_button.click() + sign_in.home_button.find_element() diff --git a/test/desktop.sikuli/views/__init__.py b/test/desktop.sikuli/views/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/desktop.sikuli/views/base_element.py b/test/desktop.sikuli/views/base_element.py new file mode 100644 index 0000000000..e1218f07d2 --- /dev/null +++ b/test/desktop.sikuli/views/base_element.py @@ -0,0 +1,27 @@ +import logging +import org.sikuli.script.SikulixForJython +import pytest +from sikuli import * + + +class BaseElement(object): + def __init__(self, screenshot): + self.screenshot = screenshot + + def find_element(self): + try: + wait(self.screenshot, 10) + except FindFailed: + pytest.fail('%s was not found' % self.__class__.__name__) + + def click(self): + logging.info('Click %s' % self.__class__.__name__) + self.find_element() + click(self.screenshot) + + +class InputField(BaseElement): + + def input_value(self, value): + self.click() + type(value) diff --git a/test/desktop.sikuli/views/base_view.py b/test/desktop.sikuli/views/base_view.py new file mode 100644 index 0000000000..423474ab3c --- /dev/null +++ b/test/desktop.sikuli/views/base_view.py @@ -0,0 +1,17 @@ +import os + +from views.base_element import BaseElement + +IMAGES_PATH = os.path.join(os.path.dirname(__file__), 'images/base_view') + + +class HomeButton(BaseElement): + def __init__(self): + super(HomeButton, self).__init__(IMAGES_PATH + '/home_button.png') + + +class BaseView(object): + + def __init__(self): + super(BaseView, self).__init__() + self.home_button = HomeButton() diff --git a/test/desktop.sikuli/views/images/base_view/home_button.png b/test/desktop.sikuli/views/images/base_view/home_button.png new file mode 100644 index 0000000000..ee58a86b93 Binary files /dev/null and b/test/desktop.sikuli/views/images/base_view/home_button.png differ diff --git a/test/desktop.sikuli/views/images/sign_in_view/confirm_password_input.png b/test/desktop.sikuli/views/images/sign_in_view/confirm_password_input.png new file mode 100644 index 0000000000..cfc731b181 Binary files /dev/null and b/test/desktop.sikuli/views/images/sign_in_view/confirm_password_input.png differ diff --git a/test/desktop.sikuli/views/images/sign_in_view/create_account.png b/test/desktop.sikuli/views/images/sign_in_view/create_account.png new file mode 100644 index 0000000000..a40c9333c5 Binary files /dev/null and b/test/desktop.sikuli/views/images/sign_in_view/create_account.png differ diff --git a/test/desktop.sikuli/views/images/sign_in_view/next_button.png b/test/desktop.sikuli/views/images/sign_in_view/next_button.png new file mode 100644 index 0000000000..c177085bbb Binary files /dev/null and b/test/desktop.sikuli/views/images/sign_in_view/next_button.png differ diff --git a/test/desktop.sikuli/views/images/sign_in_view/password_input.png b/test/desktop.sikuli/views/images/sign_in_view/password_input.png new file mode 100644 index 0000000000..8590c420ca Binary files /dev/null and b/test/desktop.sikuli/views/images/sign_in_view/password_input.png differ diff --git a/test/desktop.sikuli/views/images/sign_in_view/username_input.png b/test/desktop.sikuli/views/images/sign_in_view/username_input.png new file mode 100644 index 0000000000..5ec46c0b1f Binary files /dev/null and b/test/desktop.sikuli/views/images/sign_in_view/username_input.png differ diff --git a/test/desktop.sikuli/views/sign_in_view.py b/test/desktop.sikuli/views/sign_in_view.py new file mode 100644 index 0000000000..27987c88d0 --- /dev/null +++ b/test/desktop.sikuli/views/sign_in_view.py @@ -0,0 +1,41 @@ +import os + +from views.base_element import BaseElement, InputField +from views.base_view import BaseView + +IMAGES_PATH = os.path.join(os.path.dirname(__file__), 'images/sign_in_view') + + +class CreateAccountButton(BaseElement): + def __init__(self): + super(CreateAccountButton, self).__init__(IMAGES_PATH + '/create_account.png') + + +class PasswordInput(InputField): + def __init__(self): + super(PasswordInput, self).__init__(IMAGES_PATH + '/password_input.png') + + +class ConfirmPasswordInput(InputField): + def __init__(self): + super(ConfirmPasswordInput, self).__init__(IMAGES_PATH + '/confirm_password_input.png') + + +class UserNameInput(InputField): + def __init__(self): + super(UserNameInput, self).__init__(IMAGES_PATH + '/username_input.png') + + +class NextButton(InputField): + def __init__(self): + super(NextButton, self).__init__(IMAGES_PATH + '/next_button.png') + + +class SignInView(BaseView): + def __init__(self): + super(SignInView, self).__init__() + self.create_account_button = CreateAccountButton() + self.password_input = PasswordInput() + self.confirm_password_input = ConfirmPasswordInput() + self.username_input = UserNameInput() + self.next_button = NextButton()