WIP, report automated test results to GitHub as comment under appropriate PR
Signed-off-by: Eric Dvorsak <eric@dvorsak.fr>
This commit is contained in:
parent
8582be2e69
commit
f3a1248b13
|
@ -91,6 +91,16 @@ node ('macos1') {
|
|||
'\niOS: ' + ipaUrl
|
||||
}
|
||||
|
||||
stage('Run e2e tests') {
|
||||
if (env.CHANGE_ID != null){
|
||||
withCredentials([string(credentialsId: 'SAUCE_ACCESS_KEY', variable: 'key'), string(credentialsId: 'SAUCE_USERNAME', variable: 'username')]){
|
||||
def apk_name = env.CHANGE_ID + '.apk'
|
||||
sh('curl -u ' + username+ ':' + key + ' -X POST -H "Content-Type: application/octet-stream" https://saucelabs.com/rest/v1/storage/' + username + '/' + apk_name + '?overwrite=true --data-binary @android/app/build/outputs/apk/release/app-release.apk')
|
||||
build job: 'end-to-end-tests/status-app-end-to-end-tests', parameters: [string(name: 'apk', value: '--apk=' + apk_name), string(name: 'pr_id', value: env.CHANGE_ID)], wait: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
slackSend color: 'bad', message: BRANCH_NAME + ' failed to build. ' + env.BUILD_URL
|
||||
throw e
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[pytest]
|
||||
norecursedirs = .git views
|
||||
addopts = -s --junitxml=result.xml --tb=short
|
||||
addopts = -s -v --junitxml=result.xml --tb=line
|
||||
|
|
|
@ -21,3 +21,5 @@ selenium==3.8.1
|
|||
six==1.10.0
|
||||
urllib3==1.22
|
||||
yarl==0.12.0
|
||||
zbarlight=1.2
|
||||
eth-keys==0.1.0b4
|
|
@ -1,16 +1,26 @@
|
|||
import asyncio
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def start_threads(amount, func, *args):
|
||||
features = dict()
|
||||
def start_threads(quantity: int, func: type, returns: dict, *args):
|
||||
loop = asyncio.get_event_loop()
|
||||
for i in range(amount):
|
||||
features['feature_' + str(i)] = loop.run_in_executor(None, func, *args)
|
||||
for k in features:
|
||||
features[k] = yield from features[k]
|
||||
return (features[k] for k in features)
|
||||
for i in range(quantity):
|
||||
returns[i] = loop.run_in_executor(None, func, *args)
|
||||
for k in returns:
|
||||
returns[k] = yield from returns[k]
|
||||
return returns
|
||||
|
||||
|
||||
def get_current_time():
|
||||
return datetime.now().strftime('%-m%-d%-H%-M%-S')
|
||||
|
||||
|
||||
def info(text: str):
|
||||
if "Base" not in text:
|
||||
logging.info(text)
|
||||
test_data.test_info[test_data.test_name]['steps'] += text + '\n'
|
||||
|
||||
|
||||
class TestData(object):
|
||||
|
@ -18,37 +28,40 @@ class TestData(object):
|
|||
def __init__(self):
|
||||
self.test_name = None
|
||||
self.apk_name = None
|
||||
self.test_info = dict()
|
||||
|
||||
|
||||
test_data = TestData()
|
||||
|
||||
|
||||
basic_user = {'password': "newuniquepassword12",
|
||||
'passphrase': "tree weekend ceiling awkward universe pyramid glimpse raven pair lounge grant grief",
|
||||
'username': "Splendid Useless Racerunner"}
|
||||
basic_user = dict()
|
||||
basic_user['password'] = "newuniquepassword12"
|
||||
basic_user['passphrase'] = "tree weekend ceiling awkward universe pyramid glimpse raven pair lounge grant grief"
|
||||
basic_user['username'] = "Splendid Useless Racerunner"
|
||||
basic_user['public_key'] = "0x0448243ea6adfd2f825f083a02a1fea11e323a3ba32c9dc9992d3d465e932964" \
|
||||
"38792f11380e14c6700f598e89bafaddd2579823f4273358f9f66828fcac7dd465"
|
||||
|
||||
transaction_users = {
|
||||
'A_USER': {'password': "qwerty",
|
||||
'passphrase': "pet letter very ozone shop humor "
|
||||
"shuffle bounce convince soda hint brave",
|
||||
'public_key': '0x040e016b940e067997be8d91298d893ff2bc3580504b4ccb155ea03d183b85f1'
|
||||
'8e771a763d99f60fec70edf637eb6bad9f96d3e8a544168d3ad144f83b4cf7625c',
|
||||
'address': '67a50ef1d26de6d65dbfbb88172ac1e7017e766d',
|
||||
'username': 'Evergreen Handsome Cottontail'},
|
||||
transaction_users = dict()
|
||||
transaction_users['A_USER'] = dict()
|
||||
transaction_users['A_USER']['password'] = "qwerty"
|
||||
transaction_users['A_USER']['passphrase'] = "pet letter very ozone shop humor " \
|
||||
"shuffle bounce convince soda hint brave"
|
||||
|
||||
'B_USER': {'password': "qwerty",
|
||||
'passphrase': "resemble soap taxi meat reason "
|
||||
"inflict dilemma calm warrior key gloom again",
|
||||
'public_key': '0x0406b17e5cdfadb2a05e84508b1a2916def6395e6295f57e92b85f915d40bca3'
|
||||
'f4a7e4c6d6b25afa840dd042fac83d3f856181d553f34f1c2b12878e774adde099',
|
||||
'address': '3d672407a7e1250bbff85b7cfdb456f5015164db',
|
||||
'username': 'Brief Organic Xenops'
|
||||
},
|
||||
}
|
||||
transaction_users['A_USER']['username'] = "Evergreen Handsome Cottontail"
|
||||
transaction_users['A_USER']['address'] = "67a50ef1d26de6d65dbfbb88172ac1e7017e766d"
|
||||
transaction_users['A_USER']['public_key'] = "0x040e016b940e067997be8d91298d893ff2bc3580504b4ccb155ea03d183b85f1" \
|
||||
"8e771a763d99f60fec70edf637eb6bad9f96d3e8a544168d3ad144f83b4cf7625c"
|
||||
transaction_users['B_USER'] = dict()
|
||||
transaction_users['B_USER']['password'] = "qwerty"
|
||||
transaction_users['B_USER']['passphrase'] = "resemble soap taxi meat reason " \
|
||||
"inflict dilemma calm warrior key gloom again"
|
||||
|
||||
transaction_users['B_USER']['username'] = "Brief Organic Xenops"
|
||||
transaction_users['B_USER']['address'] = "3d672407a7e1250bbff85b7cfdb456f5015164db"
|
||||
transaction_users['B_USER']['public_key'] = "0x0406b17e5cdfadb2a05e84508b1a2916def6395e6295f57e92b85f915d40bca3" \
|
||||
"f4a7e4c6d6b25afa840dd042fac83d3f856181d553f34f1c2b12878e774adde099"
|
||||
|
||||
transaction_users_wallet = dict()
|
||||
|
||||
transaction_users_wallet['A_USER'] = dict()
|
||||
transaction_users_wallet['A_USER']['password'] = "new_unique_password"
|
||||
transaction_users_wallet['A_USER']['passphrase'] = "kiss catch paper awesome ecology surface " \
|
||||
|
@ -67,6 +80,3 @@ transaction_users_wallet['B_USER']['address'] = "5261ceba31e3a7204b498b2dd20220a
|
|||
transaction_users_wallet['B_USER']['public_key'] = "0x04cd70746f3df6cae7b45c32c211bd7e9e95ed5a1ec470db8f3b1f244eed182" \
|
||||
"1d4a2053d7671802c5f7ce5b81f5fc2016a8109e1bc83f151ceff21f08c0cdcc6e4"
|
||||
|
||||
|
||||
def get_current_time():
|
||||
return datetime.now().strftime('%-m%-d%-H%-M%-S')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
import pytest
|
||||
import requests
|
||||
import time
|
||||
from tests import info
|
||||
|
||||
|
||||
def get_transactions(address: str) -> dict:
|
||||
|
@ -27,7 +27,7 @@ def find_transaction_on_ropsten(address: str, transaction_hash: str):
|
|||
transactions = get_transactions(address=address)
|
||||
for transaction in transactions:
|
||||
if transaction['hash'] == transaction_hash:
|
||||
logging.info('Transaction is found in Ropsten network')
|
||||
info('Transaction is found in Ropsten network')
|
||||
return
|
||||
pytest.fail('Transaction is not found in Ropsten network')
|
||||
|
||||
|
@ -40,9 +40,9 @@ def verify_balance_is_updated(initial_balance, recipient_address, wait_time=240)
|
|||
elif initial_balance == get_balance(recipient_address):
|
||||
counter += 10
|
||||
time.sleep(10)
|
||||
logging.info('Waiting %s seconds for funds' % counter)
|
||||
info('Waiting %s seconds for funds' % counter)
|
||||
else:
|
||||
logging.info('Transaction is received')
|
||||
info('Transaction is received')
|
||||
return
|
||||
|
||||
|
||||
|
@ -57,9 +57,9 @@ def get_donate(address, wait_time=300):
|
|||
elif get_balance(address) == initial_balance:
|
||||
counter += 10
|
||||
time.sleep(10)
|
||||
logging.info('Waiting %s seconds for donation' % counter)
|
||||
info('Waiting %s seconds for donation' % counter)
|
||||
else:
|
||||
logging.info('Got %s for %s' % (response["amount_eth"], address))
|
||||
info('Got %s for %s' % (response["amount_eth"], address))
|
||||
return
|
||||
|
||||
|
||||
|
|
|
@ -1,29 +1,27 @@
|
|||
import pytest
|
||||
import sys
|
||||
from tests import *
|
||||
from os import environ
|
||||
from appium import webdriver
|
||||
from abc import ABCMeta, \
|
||||
abstractmethod
|
||||
import hmac
|
||||
import re
|
||||
import subprocess
|
||||
from hashlib import md5
|
||||
import asyncio
|
||||
from selenium.common.exceptions import WebDriverException
|
||||
from tests import test_data, start_threads
|
||||
from os import environ
|
||||
from appium import webdriver
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
|
||||
class AbstractTestCase:
|
||||
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
@property
|
||||
def sauce_access_key(self):
|
||||
return environ.get('SAUCE_ACCESS_KEY')
|
||||
|
||||
@property
|
||||
def sauce_username(self):
|
||||
return environ.get('SAUCE_USERNAME')
|
||||
|
||||
@property
|
||||
def sauce_access_key(self):
|
||||
return environ.get('SAUCE_ACCESS_KEY')
|
||||
|
||||
@property
|
||||
def executor_sauce_lab(self):
|
||||
return 'http://%s:%s@ondemand.saucelabs.com:80/wd/hub' % (self.sauce_username, self.sauce_access_key)
|
||||
|
@ -32,16 +30,10 @@ class AbstractTestCase:
|
|||
def executor_local(self):
|
||||
return 'http://localhost:4723/wd/hub'
|
||||
|
||||
def get_public_url(self, driver):
|
||||
token = hmac.new(bytes(self.sauce_username + ":" + self.sauce_access_key, 'latin-1'),
|
||||
bytes(driver.session_id, 'latin-1'), md5).hexdigest()
|
||||
return "https://saucelabs.com/jobs/%s?auth=%s" % (driver.session_id, token)
|
||||
|
||||
def print_sauce_lab_info(self, driver):
|
||||
sys.stdout = sys.stderr
|
||||
print("SauceOnDemandSessionID=%s job-name=%s" % (driver.session_id,
|
||||
pytest.config.getoption('build')))
|
||||
print(self.get_public_url(driver))
|
||||
|
||||
def add_local_devices_to_capabilities(self):
|
||||
updated_capabilities = list()
|
||||
|
@ -79,7 +71,7 @@ class AbstractTestCase:
|
|||
desired_caps['appiumVersion'] = '1.7.1'
|
||||
desired_caps['platformVersion'] = '6.0'
|
||||
desired_caps['newCommandTimeout'] = 600
|
||||
desired_caps['fullReset'] = True
|
||||
desired_caps['fullReset'] = False
|
||||
return desired_caps
|
||||
|
||||
@abstractmethod
|
||||
|
@ -98,20 +90,51 @@ class AbstractTestCase:
|
|||
def implicitly_wait(self):
|
||||
return 10
|
||||
|
||||
def update_test_info_dict(self):
|
||||
test_data.test_info[test_data.test_name] = dict()
|
||||
test_data.test_info[test_data.test_name]['jobs'] = list()
|
||||
test_data.test_info[test_data.test_name]['steps'] = str()
|
||||
|
||||
|
||||
class SingleDeviceTestCase(AbstractTestCase):
|
||||
|
||||
def setup_method(self, method):
|
||||
self.update_test_info_dict()
|
||||
|
||||
capabilities = {'local': {'executor': self.executor_local,
|
||||
'capabilities': self.capabilities_local},
|
||||
'sauce': {'executor': self.executor_sauce_lab,
|
||||
'capabilities': self.capabilities_sauce_lab}}
|
||||
|
||||
self.driver = webdriver.Remote(capabilities[self.environment]['executor'],
|
||||
capabilities[self.environment]['capabilities'])
|
||||
self.driver.implicitly_wait(self.implicitly_wait)
|
||||
test_data.test_info[test_data.test_name]['jobs'].append(self.driver.session_id)
|
||||
|
||||
def teardown_method(self, method):
|
||||
if self.environment == 'sauce':
|
||||
self.print_sauce_lab_info(self.driver)
|
||||
try:
|
||||
self.driver.quit()
|
||||
except WebDriverException:
|
||||
pass
|
||||
|
||||
|
||||
class LocalMultipleDeviceTestCase(AbstractTestCase):
|
||||
|
||||
def setup_method(self, method):
|
||||
self.drivers = dict()
|
||||
|
||||
def create_drivers(self, quantity):
|
||||
capabilities = self.add_local_devices_to_capabilities()
|
||||
self.driver_1 = webdriver.Remote(self.executor_local, capabilities[0])
|
||||
self.driver_2 = webdriver.Remote(self.executor_local, capabilities[1])
|
||||
for driver in self.driver_1, self.driver_2:
|
||||
driver.implicitly_wait(self.implicitly_wait)
|
||||
for driver in range(quantity):
|
||||
self.drivers[driver] = webdriver.Remote(self.executor_local, capabilities[driver])
|
||||
self.drivers[driver].implicitly_wait(self.implicitly_wait)
|
||||
|
||||
def teardown_method(self, method):
|
||||
for driver in self.driver_1, self.driver_2:
|
||||
for driver in self.drivers:
|
||||
try:
|
||||
driver.quit()
|
||||
self.drivers[driver].quit()
|
||||
except WebDriverException:
|
||||
pass
|
||||
|
||||
|
@ -123,19 +146,23 @@ class SauceMultipleDeviceTestCase(AbstractTestCase):
|
|||
cls.loop = asyncio.get_event_loop()
|
||||
|
||||
def setup_method(self, method):
|
||||
self.driver_1, \
|
||||
self.driver_2 = self.loop.run_until_complete(start_threads(2,
|
||||
webdriver.Remote,
|
||||
self.executor_sauce_lab,
|
||||
self.capabilities_sauce_lab))
|
||||
for driver in self.driver_1, self.driver_2:
|
||||
driver.implicitly_wait(self.implicitly_wait)
|
||||
self.update_test_info_dict()
|
||||
self.drivers = dict()
|
||||
|
||||
def create_drivers(self, quantity=2):
|
||||
self.drivers = self.loop.run_until_complete(start_threads(quantity, webdriver.Remote,
|
||||
self.drivers,
|
||||
self.executor_sauce_lab,
|
||||
self.capabilities_sauce_lab))
|
||||
for driver in range(quantity):
|
||||
self.drivers[driver].implicitly_wait(self.implicitly_wait)
|
||||
test_data.test_info[test_data.test_name]['jobs'].append(self.drivers[driver].session_id)
|
||||
|
||||
def teardown_method(self, method):
|
||||
for driver in self.driver_1, self.driver_2:
|
||||
self.print_sauce_lab_info(driver)
|
||||
for driver in self.drivers:
|
||||
self.print_sauce_lab_info(self.drivers[driver])
|
||||
try:
|
||||
driver.quit()
|
||||
self.drivers[driver].quit()
|
||||
except WebDriverException:
|
||||
pass
|
||||
|
||||
|
@ -144,28 +171,6 @@ class SauceMultipleDeviceTestCase(AbstractTestCase):
|
|||
cls.loop.close()
|
||||
|
||||
|
||||
class SingleDeviceTestCase(AbstractTestCase):
|
||||
|
||||
def setup_method(self, method):
|
||||
|
||||
capabilities = {'local': {'executor': self.executor_local,
|
||||
'capabilities': self.capabilities_local},
|
||||
'sauce': {'executor': self.executor_sauce_lab,
|
||||
'capabilities': self.capabilities_sauce_lab}}
|
||||
|
||||
self.driver = webdriver.Remote(capabilities[self.environment]['executor'],
|
||||
capabilities[self.environment]['capabilities'])
|
||||
self.driver.implicitly_wait(self.implicitly_wait)
|
||||
|
||||
def teardown_method(self, method):
|
||||
if self.environment == 'sauce':
|
||||
self.print_sauce_lab_info(self.driver)
|
||||
try:
|
||||
self.driver.quit()
|
||||
except WebDriverException:
|
||||
pass
|
||||
|
||||
|
||||
environments = {'local': LocalMultipleDeviceTestCase,
|
||||
'sauce': SauceMultipleDeviceTestCase}
|
||||
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
from tests import test_data
|
||||
import requests
|
||||
import re
|
||||
import pytest
|
||||
from datetime import datetime
|
||||
from os import environ
|
||||
from io import BytesIO
|
||||
from sauceclient import SauceClient
|
||||
from hashlib import md5
|
||||
import hmac
|
||||
|
||||
storage = 'http://artifacts.status.im:8081/artifactory/nightlies-local/'
|
||||
|
||||
sauce_username = environ.get('SAUCE_USERNAME')
|
||||
sauce_access_key = environ.get('SAUCE_ACCESS_KEY')
|
||||
github_token = environ.get('GIT_HUB_TOKEN')
|
||||
|
||||
sauce = SauceClient(sauce_username, sauce_access_key)
|
||||
|
||||
|
||||
def get_latest_apk():
|
||||
|
@ -41,6 +47,10 @@ def pytest_addoption(parser):
|
|||
action='store',
|
||||
default=False,
|
||||
help='Display each test step in terminal as plain text: True/False')
|
||||
parser.addoption('--pr_number',
|
||||
action='store',
|
||||
default=None,
|
||||
help='Pull Request number')
|
||||
|
||||
|
||||
def is_master(config):
|
||||
|
@ -48,33 +58,82 @@ def is_master(config):
|
|||
|
||||
|
||||
def is_uploaded():
|
||||
stored_files = SauceClient(sauce_username, sauce_access_key).storage.get_stored_files()
|
||||
stored_files = sauce.storage.get_stored_files()
|
||||
for i in range(len(stored_files['files'])):
|
||||
if stored_files['files'][i]['name'] == test_data.apk_name:
|
||||
return True
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
|
||||
if config.getoption('log'):
|
||||
import logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
test_data.apk_name = ([i for i in [i for i in config.getoption('apk').split('/')
|
||||
if '.apk' in i]])[0]
|
||||
|
||||
if is_master(config) and config.getoption('env') == 'sauce':
|
||||
if config.getoption('pr_number'):
|
||||
with open('github_comment.txt', 'w') as _:
|
||||
pass
|
||||
if not is_uploaded():
|
||||
response = requests.get(config.getoption('apk'), stream=True)
|
||||
response.raise_for_status()
|
||||
file = BytesIO(response.content)
|
||||
del response
|
||||
requests.post('http://saucelabs.com/rest/v1/storage/'
|
||||
+ sauce_username + '/' + test_data.apk_name + '?overwrite=true',
|
||||
auth=(sauce_username, sauce_access_key),
|
||||
data=file,
|
||||
headers={'Content-Type': 'application/octet-stream'})
|
||||
if 'http' in config.getoption('apk'):
|
||||
response = requests.get(config.getoption('apk'), stream=True)
|
||||
response.raise_for_status()
|
||||
file = BytesIO(response.content)
|
||||
del response
|
||||
requests.post('http://saucelabs.com/rest/v1/storage/'
|
||||
+ sauce_username + '/' + test_data.apk_name + '?overwrite=true',
|
||||
auth=(sauce_username, sauce_access_key),
|
||||
data=file,
|
||||
headers={'Content-Type': 'application/octet-stream'})
|
||||
else:
|
||||
sauce.storage.upload_file(config.getoption('apk'))
|
||||
|
||||
|
||||
def pytest_unconfigure(config):
|
||||
if is_master(config) and config.getoption('pr_number'):
|
||||
from github import Github
|
||||
repo = Github(github_token).get_user('status-im').get_repo('status-react')
|
||||
pull = repo.get_pull(int(config.getoption('pr_number')))
|
||||
with open('github_comment.txt', 'r') as comment:
|
||||
pull.create_issue_comment('# Automated test results: \n' + comment.read())
|
||||
|
||||
|
||||
def get_public_url(job_id):
|
||||
token = hmac.new(bytes(sauce_username + ":" + sauce_access_key, 'latin-1'),
|
||||
bytes(job_id, 'latin-1'), md5).hexdigest()
|
||||
return "https://saucelabs.com/jobs/%s?auth=%s" % (job_id, token)
|
||||
|
||||
|
||||
def make_github_report(error=None):
|
||||
if pytest.config.getoption('pr_number'):
|
||||
title = '### %s' % test_data.test_name
|
||||
outcome = '%s' % ':x:' if error else ':white_check_mark:' + ':\n'
|
||||
title += outcome
|
||||
steps = '\n\n <details>\n<summary>Test Steps & Error message:</summary>\n\n ```%s ```%s\n\n</details>\n' % \
|
||||
(test_data.test_info[test_data.test_name]['steps'], '\n```' + error + '```' if error else '')
|
||||
sessions = str()
|
||||
|
||||
for job_id in test_data.test_info[test_data.test_name]['jobs']:
|
||||
sessions += ' - [Android Device Session](%s) \n' % get_public_url(job_id)
|
||||
with open('github_comment.txt', 'a') as comment:
|
||||
comment.write(title + '\n' + steps + '\n' + sessions + '---\n')
|
||||
|
||||
|
||||
@pytest.mark.hookwrapper
|
||||
def pytest_runtest_makereport(item, call):
|
||||
outcome = yield
|
||||
report = outcome.get_result()
|
||||
if pytest.config.getoption('env') == 'sauce':
|
||||
if report.when == 'call':
|
||||
if report.passed:
|
||||
for job_id in test_data.test_info[test_data.test_name]['jobs']:
|
||||
sauce.jobs.update_job(job_id, name=test_data.test_name, passed=True)
|
||||
make_github_report()
|
||||
if report.failed:
|
||||
for job_id in test_data.test_info[test_data.test_name]['jobs']:
|
||||
sauce.jobs.update_job(job_id, name=test_data.test_name, passed=False)
|
||||
make_github_report(error=report.longreprtext)
|
||||
|
||||
|
||||
def pytest_runtest_setup(item):
|
||||
test_data.test_name = item.name + '_' + test_data.apk_name
|
||||
test_data.test_name = item.name
|
||||
|
|
|
@ -2,63 +2,28 @@ import pytest
|
|||
from selenium.common.exceptions import NoSuchElementException, TimeoutException
|
||||
from tests import api_requests
|
||||
from tests.base_test_case import MultipleDeviceTestCase
|
||||
from tests import user_flow, transaction_users, get_current_time
|
||||
from tests import transaction_users, get_current_time
|
||||
from views.console_view import ConsoleView
|
||||
|
||||
|
||||
@pytest.mark.all
|
||||
class TestMultipleDevices(MultipleDeviceTestCase):
|
||||
|
||||
@pytest.mark.skip('Discover functionality is not available')
|
||||
@pytest.mark.discover
|
||||
def test_new_profile_name_and_status_on_discover(self):
|
||||
device_1, device_2 = ConsoleView(self.driver_1), ConsoleView(self.driver_2)
|
||||
for profile in device_1, device_2:
|
||||
user_flow.create_user(profile)
|
||||
profile.back_button.click()
|
||||
device_1_home, device_2_home = device_1.get_home_view(), device_2.get_home_view()
|
||||
|
||||
device_2_public_key = user_flow.get_public_key(device_2_home)
|
||||
user_flow.add_contact(device_1_home, device_2_public_key)
|
||||
device_1_chat = device_1_home.get_chat_view()
|
||||
device_1_chat.chat_message_input.send_keys('test123')
|
||||
device_1_chat.send_message_button.click()
|
||||
device_1_chat.back_button.click()
|
||||
|
||||
device_2_home.element_by_text('test123', 'button').click()
|
||||
device_2_chat = device_2_home.get_chat_view()
|
||||
device_2_chat.add_to_contacts.click()
|
||||
device_2_chat.back_button.click()
|
||||
|
||||
device_1_profile, device_2_profile = device_1_chat.profile_button.click(), device_2_chat.profile_button.click()
|
||||
|
||||
for profile in device_1_profile, device_2_profile:
|
||||
user_details = user_flow.get_new_username_and_status(profile)
|
||||
profile.back_button.click()
|
||||
discover = profile.discover_button.click()
|
||||
discover.all_popular.click()
|
||||
discover.find_full_text(user_details['name'])
|
||||
discover.find_full_text(' %s' % user_details['status'])
|
||||
discover.back_button.click()
|
||||
discover.all_recent.click()
|
||||
discover.find_full_text(user_details['name'])
|
||||
discover.find_full_text('%s ' % user_details['status'])
|
||||
|
||||
@pytest.mark.chat
|
||||
def test_one_to_one_chat(self):
|
||||
device_1, device_2 = ConsoleView(self.driver_1), ConsoleView(self.driver_2)
|
||||
for device in device_1, device_2:
|
||||
user_flow.create_user(device)
|
||||
device.back_button.click()
|
||||
self.create_drivers(2)
|
||||
device_1, device_2 = \
|
||||
ConsoleView(self.drivers[0]), ConsoleView(self.drivers[1])
|
||||
for console in device_1, device_2:
|
||||
console.create_user()
|
||||
console.back_button.click()
|
||||
device_1_home, device_2_home = device_1.get_home_view(), device_2.get_home_view()
|
||||
|
||||
device_1_public_key = user_flow.get_public_key(device_1_home)
|
||||
user_flow.add_contact(device_2_home, device_1_public_key)
|
||||
device_1_public_key = device_1_home.get_public_key()
|
||||
device_2_home.add_contact(device_1_public_key)
|
||||
device_2_chat = device_2_home.get_chat_view()
|
||||
message_1 = 'SOMETHING'
|
||||
device_2_chat.chat_message_input.send_keys(message_1)
|
||||
device_2_chat.send_message_button.click()
|
||||
|
||||
message_2 = 'another SOMETHING'
|
||||
device_1_home.home_button.click()
|
||||
device_1_home.find_full_text(message_1)
|
||||
|
@ -70,15 +35,16 @@ class TestMultipleDevices(MultipleDeviceTestCase):
|
|||
|
||||
@pytest.mark.chat
|
||||
def test_group_chat_send_receive_messages_and_remove_user(self):
|
||||
device_1, device_2 = ConsoleView(self.driver_1), \
|
||||
ConsoleView(self.driver_2)
|
||||
for device in device_1, device_2:
|
||||
user_flow.create_user(device)
|
||||
device.back_button.click()
|
||||
self.create_drivers(2)
|
||||
device_1, device_2 = \
|
||||
ConsoleView(self.drivers[0]), ConsoleView(self.drivers[1])
|
||||
for console in device_1, device_2:
|
||||
console.create_user()
|
||||
console.back_button.click()
|
||||
device_1_home = device_1.get_home_view()
|
||||
device_2_home = device_2.get_home_view()
|
||||
device_1_public_key = user_flow.get_public_key(device_1_home)
|
||||
user_flow.add_contact(device_2_home, device_1_public_key)
|
||||
device_1_public_key = device_1_home.get_public_key()
|
||||
device_2_home.add_contact(device_1_public_key)
|
||||
device_2_chat = device_2_home.get_chat_view()
|
||||
device_1_user_name = device_2_chat.user_name_text.text
|
||||
device_2_home.back_button.click(times_to_click=3)
|
||||
|
@ -86,7 +52,7 @@ class TestMultipleDevices(MultipleDeviceTestCase):
|
|||
message_1 = 'first SOMETHING'
|
||||
message_2 = 'second SOMETHING'
|
||||
message_3 = 'third SOMETHING'
|
||||
user_flow.create_group_chat(device_2_home, device_1_user_name, chat_name)
|
||||
device_2_home.create_group_chat([device_1_user_name], chat_name)
|
||||
|
||||
# send_and_receive_messages
|
||||
device_2_chat.chat_message_input.send_keys(message_1)
|
||||
|
@ -100,7 +66,7 @@ class TestMultipleDevices(MultipleDeviceTestCase):
|
|||
device_2_chat.find_full_text(message_2)
|
||||
|
||||
# remove user
|
||||
device_2_chat.group_chat_options.click()
|
||||
device_2_chat.chat_options.click()
|
||||
device_2_chat.chat_settings.click()
|
||||
for _ in range(2):
|
||||
try:
|
||||
|
@ -126,22 +92,22 @@ class TestMultipleDevices(MultipleDeviceTestCase):
|
|||
],
|
||||
ids=['group_chat', 'one_to_one_chat'])
|
||||
def test_send_funds_via_request(self, test, recipient, sender):
|
||||
device_1, device_2 = ConsoleView(self.driver_1), ConsoleView(self.driver_2)
|
||||
user_flow.recover_access(device_1,
|
||||
passphrase=recipient['passphrase'],
|
||||
password=recipient['password'],
|
||||
username=recipient['username'])
|
||||
user_flow.recover_access(device_2,
|
||||
passphrase=sender['passphrase'],
|
||||
password=sender['password'],
|
||||
username=sender['username'])
|
||||
self.create_drivers(2)
|
||||
device_1, device_2 = \
|
||||
ConsoleView(self.drivers[0]), ConsoleView(self.drivers[1])
|
||||
device_1.recover_access(passphrase=recipient['passphrase'],
|
||||
password=recipient['password'],
|
||||
username=recipient['username'])
|
||||
device_2.recover_access(passphrase=sender['passphrase'],
|
||||
password=sender['password'],
|
||||
username=sender['username'])
|
||||
device_2_home = device_2.get_home_view()
|
||||
device_1_home = device_1.get_home_view()
|
||||
user_flow.add_contact(device_1_home, sender['public_key'])
|
||||
device_1_home.add_contact(sender['public_key'])
|
||||
device_1_home.back_button.click(times_to_click=3)
|
||||
if test == 'group_chat':
|
||||
group_chat_name = 'gtr_%s' % get_current_time()
|
||||
user_flow.create_group_chat(device_1_home, sender['username'], group_chat_name)
|
||||
device_1_home.create_group_chat([sender['username']], group_chat_name)
|
||||
device_2_home.element_by_text(group_chat_name, 'button').click()
|
||||
else:
|
||||
one_to_one_chat_device_1 = device_1_home.element_by_text_part(sender['username'][:25], 'button')
|
||||
|
@ -166,7 +132,7 @@ class TestMultipleDevices(MultipleDeviceTestCase):
|
|||
device_2_chat.element_by_text_part('Requesting %s ETH' % amount, 'button').click()
|
||||
device_2_chat.send_message_button.click()
|
||||
device_2_send_transaction = device_2_chat.get_send_transaction_view()
|
||||
device_2_send_transaction.sign_transaction_button.click()
|
||||
device_2_send_transaction.try_to_sing_transaction()
|
||||
device_2_send_transaction.enter_password_input.send_keys(sender['password'])
|
||||
device_2_send_transaction.sign_transaction_button.click()
|
||||
device_2_send_transaction.got_it_button.click()
|
||||
|
@ -177,5 +143,3 @@ class TestMultipleDevices(MultipleDeviceTestCase):
|
|||
transaction_element = transactions_view.transactions_table.find_transaction(amount=amount)
|
||||
transaction_details_view = transaction_element.click()
|
||||
transaction_hash = transaction_details_view.get_transaction_hash()
|
||||
api_requests.find_transaction_on_ropsten(address=sender['address'],
|
||||
transaction_hash=transaction_hash)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import pytest
|
||||
from itertools import combinations_with_replacement
|
||||
from tests.base_test_case import MultipleDeviceTestCase, SingleDeviceTestCase
|
||||
from tests import user_flow
|
||||
from views.console_view import ConsoleView
|
||||
from selenium.common.exceptions import TimeoutException
|
||||
|
||||
|
@ -13,7 +12,7 @@ class TestNetwork(SingleDeviceTestCase):
|
|||
'Mainnet', 'Mainnet with upstream RPC'])
|
||||
def test_network_switch(self, network):
|
||||
console = ConsoleView(self.driver)
|
||||
user_flow.create_user(console)
|
||||
console.create_user()
|
||||
console.back_button.click()
|
||||
profile_view = console.profile_button.click()
|
||||
sign_in_view = profile_view.switch_network(network)
|
||||
|
@ -32,9 +31,10 @@ class TestNetworkChats(MultipleDeviceTestCase):
|
|||
@pytest.mark.parametrize("network", network_combinations,
|
||||
ids=[i[0] + ' & ' + i[1] for i in network_combinations])
|
||||
def test_one_to_one_chat_between(self, network):
|
||||
device_1, device_2 = ConsoleView(self.driver_1), ConsoleView(self.driver_2)
|
||||
for device in device_1, device_2:
|
||||
user_flow.create_user(device)
|
||||
self.create_drivers(2)
|
||||
device_1, device_2 = ConsoleView(self.drivers[0]), ConsoleView(self.drivers[1])
|
||||
for console in device_1, device_2:
|
||||
console.create_user()
|
||||
device_1.back_button.click()
|
||||
device_1_profile_view = device_1.profile_button.click()
|
||||
device_1_public_key = device_1_profile_view.public_key_text.text
|
||||
|
@ -46,7 +46,6 @@ class TestNetworkChats(MultipleDeviceTestCase):
|
|||
login_d1.find_full_text('Wallet', 60)
|
||||
else:
|
||||
device_1_profile_view.back_button.click()
|
||||
|
||||
device_2.back_button.click()
|
||||
device_2_home_view = device_2.get_home_view()
|
||||
if network[1] != 'Ropsten with upstream RPC':
|
||||
|
@ -56,7 +55,7 @@ class TestNetworkChats(MultipleDeviceTestCase):
|
|||
device_2_sign_in.password_input.send_keys('qwerty1234')
|
||||
device_2_home_view = device_2_sign_in.sign_in_button.click()
|
||||
device_2_home_view.find_full_text('Wallet', 60)
|
||||
user_flow.add_contact(device_2_home_view, device_1_public_key)
|
||||
device_2_home_view.add_contact(device_1_public_key)
|
||||
device_2_chat = device_2.get_chat_view()
|
||||
message_1 = network[0]
|
||||
message_2 = network[1]
|
||||
|
|
|
@ -1,13 +1,106 @@
|
|||
import pytest
|
||||
from tests import transaction_users, transaction_users_wallet
|
||||
from tests.base_test_case import SingleDeviceTestCase
|
||||
from views.console_view import ConsoleView
|
||||
from tests import user_flow
|
||||
from tests import basic_user
|
||||
|
||||
|
||||
@pytest.mark.all
|
||||
class TestSanity(SingleDeviceTestCase):
|
||||
|
||||
@pytest.mark.profile
|
||||
def test_change_user_name(self):
|
||||
console_view = ConsoleView(self.driver)
|
||||
console_view.create_user()
|
||||
console_view.back_button.click()
|
||||
profile_view = console_view.profile_button.click()
|
||||
profile_view.edit_button.click()
|
||||
profile_view.username_input.clear()
|
||||
new_username = 'NewUserName!'
|
||||
profile_view.username_input.send_keys(new_username)
|
||||
profile_view.confirm_button.click()
|
||||
sign_in_view = profile_view.logout_button.click()
|
||||
sign_in_view.first_account_button.click()
|
||||
sign_in_view.password_input.send_keys('qwerty1234')
|
||||
home_view = sign_in_view.sign_in_button.click()
|
||||
home_view.find_full_text('Wallet', 60)
|
||||
home_view.profile_button.click()
|
||||
profile_view.edit_button.click()
|
||||
profile_view.find_full_text(new_username, 5)
|
||||
|
||||
@pytest.mark.recover
|
||||
def test_recover_access(self):
|
||||
console_view = ConsoleView(self.driver)
|
||||
console_view.create_user()
|
||||
console_view.back_button.click()
|
||||
profile_view = console_view.profile_button.click()
|
||||
sign_in_view = profile_view.logout_button.click()
|
||||
recover_access_view = sign_in_view.recover_access_button.click()
|
||||
recover_access_view.passphrase_input.send_keys(basic_user['passphrase'])
|
||||
recover_access_view.password_input.send_keys(basic_user['password'])
|
||||
recover_access_view.confirm_recover_access.click()
|
||||
recovered_user = sign_in_view.element_by_text(basic_user['username'], 'button')
|
||||
recovered_user.click()
|
||||
sign_in_view.password_input.send_keys(basic_user['password'])
|
||||
sign_in_view.sign_in_button.click()
|
||||
console_view.find_full_text('Wallet', 60)
|
||||
if basic_user['password'] in str(console_view.logcat):
|
||||
pytest.fail('Password in logcat!!!', pytrace=False)
|
||||
|
||||
@pytest.mark.gorup_chat
|
||||
def test_group_chat_members(self):
|
||||
console_view = ConsoleView(self.driver)
|
||||
console_view.create_user()
|
||||
console_view.back_button.click()
|
||||
home_view = console_view.get_home_view()
|
||||
|
||||
users = [transaction_users_wallet['A_USER'], transaction_users_wallet['B_USER'],
|
||||
transaction_users['A_USER'], transaction_users['B_USER'], basic_user]
|
||||
user_names = sorted([user['username'] for user in users])
|
||||
|
||||
for user in users:
|
||||
home_view.add_contact(user['public_key'])
|
||||
console_view.back_button.click(3)
|
||||
home_view.create_group_chat(sorted([user['username'] for user in users]))
|
||||
group_chat = home_view.get_chat_view()
|
||||
group_chat.chat_options.click()
|
||||
group_chat.chat_settings.click()
|
||||
group_chat.confirm()
|
||||
group_chat.more_users_button.click()
|
||||
for username in user_names:
|
||||
group_chat.find_full_text(username, 10)
|
||||
|
||||
def test_commands_on_second_app_run(self):
|
||||
console_view = ConsoleView(self.driver)
|
||||
console_view.create_user()
|
||||
console_view.back_button.click()
|
||||
home_view = console_view.get_home_view()
|
||||
home_view.plus_button.click()
|
||||
contact_jarrad = home_view.element_by_text('Jarrad', 'button')
|
||||
contact_jarrad.scroll_to_element()
|
||||
contact_jarrad.click()
|
||||
chat_view = home_view.get_chat_view()
|
||||
|
||||
commands = '/request', '/send'
|
||||
|
||||
for command in commands:
|
||||
chat_view.find_full_text(command, 2)
|
||||
self.driver.close_app()
|
||||
console_view.apps_button.click()
|
||||
console_view.status_app_icon.scroll_to_element()
|
||||
console_view.status_app_icon.click()
|
||||
console_view.ok_button_apk.click()
|
||||
sign_in_view = console_view.get_sign_in_view()
|
||||
sign_in_view.first_account_button.click()
|
||||
sign_in_view.password_input.send_keys('qwerty1234')
|
||||
sign_in_view.sign_in_button.click()
|
||||
contact_jarrad.wait_for_element(30)
|
||||
contact_jarrad.click()
|
||||
for command in commands:
|
||||
chat_view.find_full_text(command, 2)
|
||||
chat_view.back_button.click()
|
||||
home_view.create_group_chat(['Jarrad'])
|
||||
|
||||
@pytest.mark.sign_in
|
||||
@pytest.mark.parametrize("verification", ["invalid", "valid"])
|
||||
def test_sign_in(self, verification):
|
||||
|
@ -18,7 +111,7 @@ class TestSanity(SingleDeviceTestCase):
|
|||
{"input": "12345ewq",
|
||||
"outcome": "Wrong password"}}
|
||||
console_view = ConsoleView(self.driver)
|
||||
user_flow.create_user(console_view)
|
||||
console_view.create_user()
|
||||
console_view.back_button.click()
|
||||
profile_view = console_view.profile_button.click()
|
||||
profile_view.logout_button.scroll_to_element()
|
||||
|
@ -54,46 +147,3 @@ class TestSanity(SingleDeviceTestCase):
|
|||
console.find_full_text(verifications[verification]["outcome"])
|
||||
if verifications[verification]["input"] in str(console.logcat):
|
||||
pytest.fail('Password in logcat!!!', pytrace=False)
|
||||
|
||||
@pytest.mark.profile
|
||||
def test_change_profile_name_and_status(self):
|
||||
new_status = '#newstatus'
|
||||
new_username = 'NewUserName!'
|
||||
console_view = ConsoleView(self.driver)
|
||||
user_flow.create_user(console_view)
|
||||
console_view.back_button.click()
|
||||
profile_view = console_view.profile_button.click()
|
||||
profile_view.user_status_box.click()
|
||||
profile_view.user_status_input.clear()
|
||||
profile_view.user_status_input.send_keys(new_status)
|
||||
profile_view.username_input.click()
|
||||
profile_view.username_input.clear()
|
||||
profile_view.username_input.send_keys(new_username)
|
||||
profile_view.save_button.click()
|
||||
sign_in_view = profile_view.logout_button.click()
|
||||
sign_in_view.first_account_button.click()
|
||||
sign_in_view.password_input.send_keys('qwerty1234')
|
||||
home_view = sign_in_view.sign_in_button.click()
|
||||
home_view.find_full_text('Wallet', 60)
|
||||
home_view.profile_button.click()
|
||||
for text in new_status + ' ', new_username:
|
||||
home_view.find_full_text(text, 5)
|
||||
|
||||
@pytest.mark.recover
|
||||
def test_recover_access(self):
|
||||
console_view = ConsoleView(self.driver)
|
||||
user_flow.create_user(console_view)
|
||||
console_view.back_button.click()
|
||||
profile_view = console_view.profile_button.click()
|
||||
sign_in_view = profile_view.logout_button.click()
|
||||
recover_access_view = sign_in_view.recover_access_button.click()
|
||||
recover_access_view.passphrase_input.send_keys(basic_user['passphrase'])
|
||||
recover_access_view.password_input.send_keys(basic_user['password'])
|
||||
recover_access_view.confirm_recover_access.click()
|
||||
recovered_user = sign_in_view.element_by_text(basic_user['username'], 'button')
|
||||
recovered_user.click()
|
||||
sign_in_view.password_input.send_keys(basic_user['password'])
|
||||
sign_in_view.sign_in_button.click()
|
||||
console_view.find_full_text('Wallet', 60)
|
||||
if basic_user['password'] in str(console_view.logcat):
|
||||
pytest.fail('Password in logcat!!!', pytrace=False)
|
||||
|
|
|
@ -2,7 +2,7 @@ import pytest
|
|||
import time
|
||||
from views.console_view import ConsoleView
|
||||
from tests.base_test_case import SingleDeviceTestCase
|
||||
from tests import user_flow, transaction_users, api_requests, get_current_time
|
||||
from tests import transaction_users, api_requests, get_current_time
|
||||
from selenium.common.exceptions import TimeoutException
|
||||
|
||||
|
||||
|
@ -18,21 +18,22 @@ class TestTransactions(SingleDeviceTestCase):
|
|||
'wrong_password'])
|
||||
def test_transaction_send_command(self, test, recipient):
|
||||
console_view = ConsoleView(self.driver)
|
||||
user_flow.create_user(console_view)
|
||||
console_view.create_user()
|
||||
console_view.back_button.click()
|
||||
home_view = console_view.get_home_view()
|
||||
recipient_address = transaction_users[recipient]['address']
|
||||
recipient_key = transaction_users[recipient]['public_key']
|
||||
transaction_amount = '0.001'
|
||||
sender_address = user_flow.get_address(home_view)
|
||||
sender_public_key = home_view.get_public_key()
|
||||
sender_address = home_view.public_key_to_address(sender_public_key)
|
||||
home_view.home_button.click()
|
||||
api_requests.get_donate(sender_address)
|
||||
initial_balance_recipient = api_requests.get_balance(recipient_address)
|
||||
|
||||
user_flow.add_contact(home_view, recipient_key)
|
||||
home_view.add_contact(recipient_key)
|
||||
if test == 'group_chat':
|
||||
home_view.back_button.click(times_to_click=3)
|
||||
user_flow.create_group_chat(home_view, transaction_users[recipient]['username'],
|
||||
home_view.create_group_chat([transaction_users[recipient]['username']],
|
||||
'trg_%s' % get_current_time())
|
||||
chat_view = home_view.get_chat_view()
|
||||
else:
|
||||
|
@ -67,10 +68,9 @@ class TestTransactions(SingleDeviceTestCase):
|
|||
@pytest.mark.transaction
|
||||
def test_send_transaction_from_daap(self):
|
||||
console = ConsoleView(self.driver)
|
||||
user_flow.recover_access(console,
|
||||
transaction_users['B_USER']['passphrase'],
|
||||
transaction_users['B_USER']['password'],
|
||||
transaction_users['B_USER']['username'])
|
||||
console.recover_access(transaction_users['B_USER']['passphrase'],
|
||||
transaction_users['B_USER']['password'],
|
||||
transaction_users['B_USER']['username'])
|
||||
home_view = console.get_home_view()
|
||||
address = transaction_users['B_USER']['address']
|
||||
initial_balance = api_requests.get_balance(address)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import pytest
|
||||
from tests import api_requests, user_flow, transaction_users_wallet
|
||||
from tests import api_requests, transaction_users_wallet
|
||||
from tests.base_test_case import SingleDeviceTestCase
|
||||
from views.console_view import ConsoleView
|
||||
|
||||
|
@ -10,7 +10,7 @@ class TestWallet(SingleDeviceTestCase):
|
|||
@pytest.mark.wallet
|
||||
def test_wallet_error_messages(self):
|
||||
console = ConsoleView(self.driver)
|
||||
user_flow.create_user(console)
|
||||
console.create_user()
|
||||
console.back_button.click()
|
||||
wallet_view = console.wallet_button.click()
|
||||
send_transaction = wallet_view.send_button.click()
|
||||
|
@ -22,13 +22,12 @@ class TestWallet(SingleDeviceTestCase):
|
|||
@pytest.mark.wallet
|
||||
def test_request_transaction_from_wallet(self):
|
||||
console_view = ConsoleView(self.driver)
|
||||
user_flow.recover_access(console_view,
|
||||
transaction_users_wallet['A_USER']['passphrase'],
|
||||
transaction_users_wallet['A_USER']['password'],
|
||||
transaction_users_wallet['A_USER']['username'])
|
||||
console_view.recover_access(transaction_users_wallet['A_USER']['passphrase'],
|
||||
transaction_users_wallet['A_USER']['password'],
|
||||
transaction_users_wallet['A_USER']['username'])
|
||||
home_view = console_view.get_home_view()
|
||||
recipient_key = transaction_users_wallet['B_USER']['public_key']
|
||||
user_flow.add_contact(home_view, recipient_key)
|
||||
home_view.add_contact(recipient_key)
|
||||
home_view.back_button.click(times_to_click=3)
|
||||
wallet_view = home_view.wallet_button.click()
|
||||
send_transaction_view = wallet_view.request_button.click()
|
||||
|
@ -43,15 +42,14 @@ class TestWallet(SingleDeviceTestCase):
|
|||
ids=['sign_now','sign_later'])
|
||||
def test_send_transaction_from_wallet(self, test, recipient, sender):
|
||||
console_view = ConsoleView(self.driver)
|
||||
user_flow.recover_access(console_view,
|
||||
transaction_users_wallet[sender]['passphrase'],
|
||||
transaction_users_wallet[sender]['password'],
|
||||
transaction_users_wallet[sender]['username'])
|
||||
console_view.recover_access(transaction_users_wallet[sender]['passphrase'],
|
||||
transaction_users_wallet[sender]['password'],
|
||||
transaction_users_wallet[sender]['username'])
|
||||
home_view = console_view.get_home_view()
|
||||
recipient_key = transaction_users_wallet[recipient]['public_key']
|
||||
recipient_address = transaction_users_wallet[recipient]['address']
|
||||
initial_balance_recipient = api_requests.get_balance(recipient_address)
|
||||
user_flow.add_contact(home_view, recipient_key)
|
||||
home_view.add_contact(recipient_key)
|
||||
home_view.back_button.click(times_to_click=3)
|
||||
wallet_view = home_view.wallet_button.click()
|
||||
send_transaction = wallet_view.send_button.click()
|
||||
|
@ -83,18 +81,15 @@ class TestWallet(SingleDeviceTestCase):
|
|||
transactions_view = wallet_view.transactions_button.click()
|
||||
transaction = transactions_view.transactions_table.find_transaction(amount=amount)
|
||||
details_view = transaction.click()
|
||||
transaction_hash = details_view.get_transaction_hash()
|
||||
api_requests.find_transaction_on_ropsten(address=transaction_users_wallet[sender]['address'],
|
||||
transaction_hash=transaction_hash)
|
||||
details_view.get_transaction_hash()
|
||||
|
||||
@pytest.mark.wallet
|
||||
def test_eth_and_currency_balance(self):
|
||||
errors = list()
|
||||
console = ConsoleView(self.driver)
|
||||
user_flow.recover_access(console,
|
||||
passphrase=transaction_users_wallet['A_USER']['passphrase'],
|
||||
password=transaction_users_wallet['A_USER']['password'],
|
||||
username=transaction_users_wallet['A_USER']['username'])
|
||||
console.recover_access(passphrase=transaction_users_wallet['A_USER']['passphrase'],
|
||||
password=transaction_users_wallet['A_USER']['password'],
|
||||
username=transaction_users_wallet['A_USER']['username'])
|
||||
home_view = console.get_home_view()
|
||||
wallet = home_view.wallet_button.click()
|
||||
address = transaction_users_wallet['A_USER']['address']
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
from tests import get_current_time
|
||||
|
||||
|
||||
def create_user(console):
|
||||
console.request_password_icon.click()
|
||||
console.chat_request_input.send_keys("qwerty1234")
|
||||
console.confirm()
|
||||
console.chat_request_input.send_keys("qwerty1234")
|
||||
console.confirm()
|
||||
console.find_full_text(
|
||||
"Here is your signing phrase. You will use it to verify your transactions. Write it down and keep it safe!")
|
||||
|
||||
|
||||
def recover_access(console, passphrase, password, username):
|
||||
recover_access_view = console.recover_button.click()
|
||||
recover_access_view.passphrase_input.send_keys(passphrase)
|
||||
recover_access_view.password_input.send_keys(password)
|
||||
recover_access_view.confirm_recover_access.click()
|
||||
recovered_user = recover_access_view.element_by_text(username, 'button')
|
||||
recover_access_view.confirm()
|
||||
recovered_user.click()
|
||||
recover_access_view.password_input.send_keys(password)
|
||||
recover_access_view.sign_in_button.click()
|
||||
recover_access_view.find_full_text('Wallet', 60)
|
||||
|
||||
|
||||
def get_public_key(home):
|
||||
profile_view = home.profile_button.click()
|
||||
return profile_view.public_key_text.text
|
||||
|
||||
|
||||
def get_address(home):
|
||||
profile_view = home.profile_button.click()
|
||||
return profile_view.profile_address_text.text
|
||||
|
||||
|
||||
def add_contact(home, public_key):
|
||||
start_new_chat = home.plus_button.click()
|
||||
start_new_chat.add_new_contact.click()
|
||||
start_new_chat.public_key_edit_box.send_keys(public_key)
|
||||
start_new_chat.confirm()
|
||||
start_new_chat.confirm_public_key_button.click()
|
||||
|
||||
|
||||
def create_group_chat(home, username_to_add, group_chat_name='new_group_chat'):
|
||||
start_new_chat = home.plus_button.click()
|
||||
start_new_chat.new_group_chat_button.click()
|
||||
user_contact = start_new_chat.element_by_text(username_to_add, 'button')
|
||||
user_contact.scroll_to_element()
|
||||
user_contact.click()
|
||||
start_new_chat.next_button.click()
|
||||
start_new_chat.name_edit_box.send_keys(group_chat_name)
|
||||
start_new_chat.save_button.click()
|
||||
|
||||
|
||||
def get_new_username_and_status(profile):
|
||||
users_details = dict()
|
||||
current_time = get_current_time()
|
||||
new_status = '#newstatus_%s' % current_time
|
||||
new_username = 'New_User_Name_%s' % current_time
|
||||
|
||||
profile.user_status_box.click()
|
||||
profile.user_status_input.clear()
|
||||
profile.user_status_input.send_keys(new_status)
|
||||
profile.username_input.clear()
|
||||
profile.username_input.send_keys(new_username)
|
||||
profile.save_button.click()
|
||||
users_details['status'] = new_status
|
||||
users_details['name'] = new_username
|
||||
return users_details
|
|
@ -1,9 +1,9 @@
|
|||
from appium.webdriver.common.mobileby import MobileBy
|
||||
from selenium.common.exceptions import NoSuchElementException, TimeoutException
|
||||
from selenium.common.exceptions import NoSuchElementException
|
||||
from selenium.common.exceptions import TimeoutException
|
||||
from selenium.webdriver.support.wait import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions
|
||||
from appium.webdriver.common.touch_action import TouchAction
|
||||
import logging
|
||||
from tests import info
|
||||
|
||||
|
||||
class BaseElement(object):
|
||||
|
@ -37,25 +37,33 @@ class BaseElement(object):
|
|||
return None
|
||||
|
||||
def find_element(self):
|
||||
self.info('Looking for %s' % self.name)
|
||||
return self.driver.find_element(self.locator.by, self.locator.value)
|
||||
info('Looking for %s' % self.name)
|
||||
try:
|
||||
return self.driver.find_element(self.locator.by, self.locator.value)
|
||||
except NoSuchElementException as exception:
|
||||
exception.msg = "'%s' is not found on screen, using: '%s'" % (self.name, self.locator)
|
||||
raise exception
|
||||
|
||||
def find_elements(self):
|
||||
self.info('Looking for %s' % self.name)
|
||||
info('Looking for %s' % self.name)
|
||||
return self.driver.find_elements(self.locator.by, self.locator.value)
|
||||
|
||||
def wait_for_element(self, seconds=10):
|
||||
return WebDriverWait(self.driver, seconds)\
|
||||
.until(expected_conditions.presence_of_element_located((self.locator.by, self.locator.value)))
|
||||
try:
|
||||
return WebDriverWait(self.driver, seconds)\
|
||||
.until(expected_conditions.presence_of_element_located((self.locator.by, self.locator.value)))
|
||||
except TimeoutException as exception:
|
||||
exception.msg = "'%s' is not found on screen, using: '%s', during '%s' seconds" % (self.name, self.locator,
|
||||
seconds)
|
||||
raise exception
|
||||
|
||||
def scroll_to_element(self):
|
||||
action = TouchAction(self.driver)
|
||||
for _ in range(5):
|
||||
for _ in range(9):
|
||||
try:
|
||||
return self.find_element()
|
||||
except NoSuchElementException:
|
||||
self.info('Scrolling to %s' % self.name)
|
||||
action.press(x=0, y=1000).move_to(x=200, y=-1000).release().perform()
|
||||
info('Scrolling down to %s' % self.name)
|
||||
self.driver.swipe(500, 1000, 500, 500)
|
||||
|
||||
def is_element_present(self, sec=5):
|
||||
try:
|
||||
|
@ -68,10 +76,6 @@ class BaseElement(object):
|
|||
def text(self):
|
||||
return self.find_element().text
|
||||
|
||||
def info(self, text):
|
||||
if not "Base" in text:
|
||||
logging.info(text)
|
||||
|
||||
|
||||
class BaseEditBox(BaseElement):
|
||||
|
||||
|
@ -80,19 +84,19 @@ class BaseEditBox(BaseElement):
|
|||
|
||||
def send_keys(self, value):
|
||||
self.find_element().send_keys(value)
|
||||
self.info("Type '%s' to %s" % (value, self.name))
|
||||
info("Type '%s' to %s" % (value, self.name))
|
||||
|
||||
def set_value(self, value):
|
||||
self.find_element().set_value(value)
|
||||
self.info("Type '%s' to %s" % (value, self.name))
|
||||
info("Type '%s' to %s" % (value, self.name))
|
||||
|
||||
def clear(self):
|
||||
self.find_element().clear()
|
||||
self.info('Clear text in %s' % self.name)
|
||||
info('Clear text in %s' % self.name)
|
||||
|
||||
def click(self):
|
||||
self.find_element().click()
|
||||
self.info('Tap on %s' % self.name)
|
||||
info('Tap on %s' % self.name)
|
||||
|
||||
|
||||
class BaseText(BaseElement):
|
||||
|
@ -103,7 +107,7 @@ class BaseText(BaseElement):
|
|||
@property
|
||||
def text(self):
|
||||
text = self.find_element().text
|
||||
self.info('%s is %s' % (self.name, text))
|
||||
info('%s is %s' % (self.name, text))
|
||||
return text
|
||||
|
||||
|
||||
|
@ -114,5 +118,5 @@ class BaseButton(BaseElement):
|
|||
|
||||
def click(self):
|
||||
self.find_element().click()
|
||||
self.info('Tap on %s' % self.name)
|
||||
info('Tap on %s' % self.name)
|
||||
return self.navigate()
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import logging
|
||||
import time
|
||||
import base64
|
||||
import zbarlight
|
||||
from tests import info
|
||||
from eth_keys import datatypes
|
||||
from selenium.common.exceptions import NoSuchElementException, TimeoutException
|
||||
|
||||
from PIL import Image
|
||||
from datetime import datetime
|
||||
|
||||
from io import BytesIO
|
||||
from views.base_element import BaseButton, BaseElement, BaseEditBox, BaseText
|
||||
|
||||
|
||||
|
@ -16,9 +19,9 @@ class BackButton(BaseButton):
|
|||
for _ in range(times_to_click):
|
||||
try:
|
||||
self.find_element().click()
|
||||
info('Tap on %s' % self.name)
|
||||
except (NoSuchElementException, TimeoutException):
|
||||
pass
|
||||
logging.info('Tap on %s' % self.name)
|
||||
return self.navigate()
|
||||
|
||||
|
||||
|
@ -31,9 +34,9 @@ class AllowButton(BaseButton):
|
|||
try:
|
||||
for _ in range(3):
|
||||
self.find_element().click()
|
||||
info('Tap on %s' % self.name)
|
||||
except NoSuchElementException:
|
||||
pass
|
||||
logging.info('Tap on %s' % self.name)
|
||||
|
||||
|
||||
class DenyButton(BaseButton):
|
||||
|
@ -110,6 +113,13 @@ class NextButton(BaseButton):
|
|||
"//android.widget.TextView[@text='NEXT']")
|
||||
|
||||
|
||||
class DoneButton(BaseButton):
|
||||
def __init__(self, driver):
|
||||
super(DoneButton, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector(
|
||||
"//android.widget.TextView[@text='Done']")
|
||||
|
||||
|
||||
class AppsButton(BaseButton):
|
||||
def __init__(self, driver):
|
||||
super(AppsButton, self).__init__(driver)
|
||||
|
@ -141,6 +151,7 @@ class BaseView(object):
|
|||
self.ok_button_apk = OkButton(self.driver)
|
||||
self.next_button = NextButton(self.driver)
|
||||
self.save_button = SaveButton(self.driver)
|
||||
self.done_button = DoneButton(self.driver)
|
||||
|
||||
self.apps_button = AppsButton(self.driver)
|
||||
self.status_app_icon = StatusAppIcon(self.driver)
|
||||
|
@ -157,7 +168,7 @@ class BaseView(object):
|
|||
return self.driver.get_log("logcat")
|
||||
|
||||
def confirm(self):
|
||||
logging.info("Tap 'Confirm' on native keyboard")
|
||||
info("Tap 'Confirm' on native keyboard")
|
||||
self.driver.keyevent(66)
|
||||
|
||||
def send_as_keyevent(self, string):
|
||||
|
@ -170,30 +181,30 @@ class BaseView(object):
|
|||
'k': 39, 'l': 40, 'm': 41, 'n': 42, 'o': 43, 'p': 44, 'q': 45, 'r': 46, 's': 47, 't': 48,
|
||||
'u': 49, 'v': 50, 'w': 51, 'x': 52, 'y': 53, 'z': 54}
|
||||
for i in string:
|
||||
logging.info("Tap '%s' on native keyboard" % i)
|
||||
info("Tap '%s' on native keyboard" % i)
|
||||
time.sleep(1)
|
||||
self.driver.keyevent(keys[i])
|
||||
|
||||
def find_full_text(self, text, wait_time=60):
|
||||
logging.info("Looking for full text: '%s'" % text)
|
||||
info("Looking for full text: '%s'" % text)
|
||||
element = BaseElement(self.driver)
|
||||
element.locator = element.Locator.xpath_selector('//*[@text="' + text + '"]')
|
||||
return element.wait_for_element(wait_time)
|
||||
|
||||
def find_text_part(self, text, wait_time=60):
|
||||
logging.info("Looking for a text part: '%s'" % text)
|
||||
info("Looking for a text part: '%s'" % text)
|
||||
element = BaseElement(self.driver)
|
||||
element.locator = element.Locator.xpath_selector('//*[contains(@text, "' + text + '")]')
|
||||
return element.wait_for_element(wait_time)
|
||||
|
||||
def element_by_text(self, text, element_type='base'):
|
||||
logging.info("Looking for an element by text: '%s'" % text)
|
||||
info("Looking for an element by text: '%s'" % text)
|
||||
element = self.element_types[element_type](self.driver)
|
||||
element.locator = element.Locator.xpath_selector('//*[@text="' + text + '"]')
|
||||
return element
|
||||
|
||||
def element_by_text_part(self, text, element_type='base'):
|
||||
logging.info("Looking for an element by text part: '%s'" % text)
|
||||
info("Looking for an element by text part: '%s'" % text)
|
||||
element = self.element_types[element_type](self.driver)
|
||||
element.locator = element.Locator.xpath_selector('//*[contains(@text, "' + text + '")]')
|
||||
return element
|
||||
|
@ -216,3 +227,15 @@ class BaseView(object):
|
|||
|
||||
def get_unique_amount(self):
|
||||
return '0.0%s' % datetime.now().strftime('%-m%-d%-H%-M%-S').strip('0')
|
||||
|
||||
def get_text_from_qr(self):
|
||||
image = Image.open(BytesIO(base64.b64decode(self.driver.get_screenshot_as_base64())))
|
||||
image.load()
|
||||
try:
|
||||
return str(zbarlight.scan_codes('qrcode', image)[0])[2:][:132]
|
||||
except IndexError:
|
||||
raise BaseException('No data in QR code')
|
||||
|
||||
def public_key_to_address(self, public_key):
|
||||
raw_public_key = bytearray.fromhex(public_key.replace('0x04', ''))
|
||||
return datatypes.PublicKey(raw_public_key).to_address()[2:]
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import logging
|
||||
|
||||
from selenium.common.exceptions import TimeoutException
|
||||
|
||||
from tests import info
|
||||
from views.base_element import BaseButton, BaseEditBox, BaseText
|
||||
from views.base_view import BaseView
|
||||
|
||||
|
@ -19,7 +17,7 @@ class SendMessageButton(BaseButton):
|
|||
|
||||
def click(self):
|
||||
self.find_element().click()
|
||||
logging.info('Tap on %s' % self.name)
|
||||
info('Tap on %s' % self.name)
|
||||
|
||||
|
||||
class AddToContacts(BaseButton):
|
||||
|
@ -48,11 +46,17 @@ class RequestCommand(BaseButton):
|
|||
self.locator = self.Locator.xpath_selector("//*[@text='/request']")
|
||||
|
||||
|
||||
class GroupChatOptions(BaseButton):
|
||||
class ChatOptions(BaseButton):
|
||||
def __init__(self, driver):
|
||||
super(GroupChatOptions, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector(
|
||||
"//android.view.ViewGroup[2]//android.widget.TextView[@text='n']")
|
||||
super(ChatOptions, self).__init__(driver)
|
||||
self.locator = self.Locator.accessibility_id('chat-menu')
|
||||
|
||||
|
||||
class MembersButton(BaseButton):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(MembersButton, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector('(//android.view.ViewGroup[@content-desc="action"])[1]')
|
||||
|
||||
|
||||
class ChatSettings(BaseButton):
|
||||
|
@ -81,6 +85,19 @@ class FirstRecipient(BaseButton):
|
|||
"//android.widget.ImageView[@content-desc='chat-icon']")
|
||||
|
||||
|
||||
class MessageByUsername(BaseText):
|
||||
def __init__(self, driver, username):
|
||||
super(MessageByUsername, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector('//*[@text="' + username + '"]'
|
||||
'/following-sibling::android.widget.TextView')
|
||||
|
||||
|
||||
class MoreUsersButton(BaseButton):
|
||||
def __init__(self, driver):
|
||||
super(MoreUsersButton, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector("//android.widget.TextView[contains(@text, 'MORE')]")
|
||||
|
||||
|
||||
class ChatView(BaseView):
|
||||
def __init__(self, driver):
|
||||
super(ChatView, self).__init__(driver)
|
||||
|
@ -93,18 +110,24 @@ class ChatView(BaseView):
|
|||
self.send_command = SendCommand(self.driver)
|
||||
self.request_command = RequestCommand(self.driver)
|
||||
|
||||
self.group_chat_options = GroupChatOptions(self.driver)
|
||||
self.chat_options = ChatOptions(self.driver)
|
||||
self.members_button = MembersButton(self.driver)
|
||||
|
||||
self.chat_settings = ChatSettings(self.driver)
|
||||
self.more_users_button = MoreUsersButton(self.driver)
|
||||
self.user_options = UserOptions(self.driver)
|
||||
self.remove_button = RemoveButton(self.driver)
|
||||
|
||||
self.first_recipient_button = FirstRecipient(self.driver)
|
||||
|
||||
def wait_for_syncing_complete(self):
|
||||
logging.info('Waiting for syncing complete:')
|
||||
info('Waiting for syncing complete:')
|
||||
while True:
|
||||
try:
|
||||
sync = self.find_text_part('Syncing', 10)
|
||||
logging.info(sync.text)
|
||||
info(sync.text)
|
||||
except TimeoutException:
|
||||
break
|
||||
|
||||
def get_messages_sent_by_user(self, username):
|
||||
return MessageByUsername(self.driver, username).find_elements()
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import logging
|
||||
|
||||
from tests import info
|
||||
from selenium.common.exceptions import NoSuchElementException, TimeoutException
|
||||
|
||||
from views.base_element import BaseButton, BaseEditBox
|
||||
from views.base_view import BaseView
|
||||
|
||||
|
@ -10,12 +8,12 @@ class RequestPasswordIcon(BaseButton):
|
|||
|
||||
def __init__(self, driver):
|
||||
super(RequestPasswordIcon, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector("//*[@content-desc='request-password']")
|
||||
self.locator = self.Locator.accessibility_id('request-password')
|
||||
|
||||
def click(self):
|
||||
self.wait_for_element(10)
|
||||
self.find_element().click()
|
||||
logging.info('Tap on %s' % self.name)
|
||||
info('Tap on %s' % self.name)
|
||||
return self.navigate()
|
||||
|
||||
|
||||
|
@ -55,3 +53,24 @@ class ConsoleView(BaseView):
|
|||
i.click()
|
||||
except (NoSuchElementException, TimeoutException):
|
||||
pass
|
||||
|
||||
def create_user(self):
|
||||
self.request_password_icon.click()
|
||||
self.chat_request_input.send_keys("qwerty1234")
|
||||
self.confirm()
|
||||
self.chat_request_input.send_keys("qwerty1234")
|
||||
self.confirm()
|
||||
self.find_full_text(
|
||||
"Here is your signing phrase. You will use it to verify your transactions. Write it down and keep it safe!")
|
||||
|
||||
def recover_access(self, passphrase, password, username):
|
||||
recover_access_view = self.recover_button.click()
|
||||
recover_access_view.passphrase_input.send_keys(passphrase)
|
||||
recover_access_view.password_input.send_keys(password)
|
||||
recover_access_view.confirm_recover_access.click()
|
||||
recovered_user = recover_access_view.element_by_text(username, 'button')
|
||||
recover_access_view.confirm()
|
||||
recovered_user.click()
|
||||
recover_access_view.password_input.send_keys(password)
|
||||
recover_access_view.sign_in_button.click()
|
||||
recover_access_view.find_full_text('Wallet', 30)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import logging
|
||||
|
||||
from tests import info
|
||||
import time
|
||||
from selenium.common.exceptions import TimeoutException
|
||||
|
||||
from views.base_element import BaseButton
|
||||
from views.base_view import BaseView
|
||||
|
||||
|
@ -42,13 +41,39 @@ class HomeView(BaseView):
|
|||
self.console_button = ConsoleButton(self.driver)
|
||||
|
||||
def wait_for_syncing_complete(self):
|
||||
logging.info('Waiting for syncing complete:')
|
||||
info('Waiting for syncing complete:')
|
||||
while True:
|
||||
try:
|
||||
sync = self.find_text_part('Syncing', 10)
|
||||
logging.info(sync.text)
|
||||
info(sync.text)
|
||||
except TimeoutException:
|
||||
break
|
||||
|
||||
def get_chat_with_user(self, username):
|
||||
return ChatElement(self.driver, username)
|
||||
|
||||
def add_contact(self, public_key):
|
||||
start_new_chat = self.plus_button.click()
|
||||
start_new_chat.add_new_contact.click()
|
||||
start_new_chat.public_key_edit_box.send_keys(public_key)
|
||||
start_new_chat.confirm()
|
||||
start_new_chat.confirm_public_key_button.click()
|
||||
|
||||
def create_group_chat(self, user_names_to_add: list, group_chat_name: str = 'new_group_chat'):
|
||||
start_new_chat = self.plus_button.click()
|
||||
start_new_chat.new_group_chat_button.click()
|
||||
for user_name in user_names_to_add:
|
||||
user_contact = start_new_chat.element_by_text(user_name, 'button')
|
||||
user_contact.scroll_to_element()
|
||||
user_contact.click()
|
||||
start_new_chat.next_button.click()
|
||||
start_new_chat.name_edit_box.send_keys(group_chat_name)
|
||||
start_new_chat.save_button.click()
|
||||
|
||||
def get_public_key(self):
|
||||
profile_view = self.profile_button.click()
|
||||
profile_view.share_my_contact_key_button.click()
|
||||
time.sleep(4)
|
||||
public_key = profile_view.get_text_from_qr()
|
||||
profile_view.cross_icon.click()
|
||||
return public_key
|
||||
|
|
|
@ -19,7 +19,7 @@ class SwitchUsersButton(BaseButton):
|
|||
|
||||
def click(self):
|
||||
self.find_element().click()
|
||||
logging.info('Tap on %s' % self.name)
|
||||
info('Tap on %s' % self.name)
|
||||
return self.navigate()
|
||||
|
||||
def navigate(self):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import logging
|
||||
|
||||
import time
|
||||
from tests import info
|
||||
from views.base_element import BaseText, BaseButton, BaseEditBox
|
||||
from views.base_view import BaseView
|
||||
|
||||
|
@ -13,7 +13,7 @@ class PublicKeyText(BaseText):
|
|||
@property
|
||||
def text(self):
|
||||
text = self.scroll_to_element().text
|
||||
logging.info('%s is %s' % (self.name, text))
|
||||
info('%s is %s' % (self.name, text))
|
||||
return text
|
||||
|
||||
|
||||
|
@ -35,20 +35,19 @@ class OptionsButton(BaseButton):
|
|||
|
||||
def __init__(self, driver):
|
||||
super(OptionsButton.UserStatusBox, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector(
|
||||
'//android.widget.ImageView[@content-desc="chat-icon"]/..//android.widget.ScrollView')
|
||||
self.locator = self.Locator.xpath_selector('(//android.widget.ScrollView)[2]//android.widget.TextView')
|
||||
|
||||
class UsernameInput(BaseEditBox):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(OptionsButton.UsernameInput, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector('//*[@text="Name"]/..//android.widget.EditText')
|
||||
self.locator = self.Locator.xpath_selector('//android.widget.EditText')
|
||||
|
||||
class UserStatusInput(BaseEditBox):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(OptionsButton.UserStatusInput, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector('//android.view.ViewGroup[count(*)=1]/android.widget.EditText')
|
||||
self.locator = self.Locator.xpath_selector('(//android.widget.EditText)[2]')
|
||||
|
||||
|
||||
class NetworkSettingsButton(BaseButton):
|
||||
|
@ -73,22 +72,54 @@ class LogoutButton(BaseButton):
|
|||
|
||||
def __init__(self, driver):
|
||||
super(LogoutButton, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector('//*[@text="Logout"]')
|
||||
self.locator = self.Locator.xpath_selector('//*[@text="Log out"]')
|
||||
|
||||
def click(self):
|
||||
self.scroll_to_element()
|
||||
self.find_element().click()
|
||||
self.info('Tap on %s' % self.name)
|
||||
for _ in range(2):
|
||||
self.find_element().click()
|
||||
time.sleep(2)
|
||||
info('Tap on %s' % self.name)
|
||||
from views.sign_in_view import SignInView
|
||||
return SignInView(self.driver)
|
||||
|
||||
|
||||
class ShareMyContactKeyButton(BaseButton):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(ShareMyContactKeyButton, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector('//*[@text="SHARE MY CONTACT CODE"]')
|
||||
|
||||
|
||||
class EditButton(BaseButton):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(EditButton, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector('//*[@text="EDIT"]')
|
||||
|
||||
|
||||
class ConfirmButton(BaseButton):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(ConfirmButton, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector('(//android.view.ViewGroup[@content-desc="icon"])[1]')
|
||||
|
||||
|
||||
class CrossIcon(BaseButton):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(CrossIcon, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector(
|
||||
'(// android.view.ViewGroup[@ content-desc="icon"])[1]/android.view.View')
|
||||
|
||||
|
||||
class ProfileView(BaseView):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(ProfileView, self).__init__(driver)
|
||||
self.driver = driver
|
||||
|
||||
# old design
|
||||
self.options_button = OptionsButton(self.driver)
|
||||
self.username_input = OptionsButton.UsernameInput(self.driver)
|
||||
self.user_status_box = OptionsButton.UserStatusBox(self.driver)
|
||||
|
@ -100,6 +131,13 @@ class ProfileView(BaseView):
|
|||
self.connect_button = NetworkSettingsButton.ConnectButton(self.driver)
|
||||
self.logout_button = LogoutButton(self.driver)
|
||||
|
||||
# new design
|
||||
|
||||
self.share_my_contact_key_button = ShareMyContactKeyButton(self.driver)
|
||||
self.edit_button = EditButton(self.driver)
|
||||
self.confirm_button = ConfirmButton(self.driver)
|
||||
self.cross_icon = CrossIcon(self.driver)
|
||||
|
||||
def switch_network(self, network):
|
||||
self.network_settings_button.scroll_to_element()
|
||||
self.network_settings_button.click()
|
||||
|
@ -108,3 +146,7 @@ class ProfileView(BaseView):
|
|||
self.connect_button.click()
|
||||
from views.sign_in_view import SignInView
|
||||
return SignInView(self.driver)
|
||||
|
||||
def get_address(self):
|
||||
profile_view = self.profile_button.click()
|
||||
return profile_view.profile_address_text.text
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from views.base_element import BaseButton, BaseEditBox
|
||||
from views.base_view import BaseView
|
||||
from selenium.common.exceptions import NoSuchElementException, TimeoutException
|
||||
|
||||
|
||||
class FirstRecipient(BaseButton):
|
||||
|
@ -80,3 +81,11 @@ class SendTransactionView(BaseView):
|
|||
self.password_input = PasswordInput(self.driver)
|
||||
self.enter_password_input = EnterPasswordInput(self.driver)
|
||||
self.got_it_button = GotItButton(self.driver)
|
||||
|
||||
def try_to_sing_transaction(self):
|
||||
for _ in range(4):
|
||||
try:
|
||||
self.sign_transaction_button.click()
|
||||
self.password_input.wait_for_element(5)
|
||||
except (NoSuchElementException, TimeoutException):
|
||||
pass
|
||||
|
|
|
@ -42,13 +42,13 @@ class TransactionTable(BaseElement):
|
|||
return self.TransactionElement(self.driver, amount=amount)
|
||||
|
||||
def find_transaction(self, amount: str) -> TransactionElement:
|
||||
for i in range(18):
|
||||
for i in range(9):
|
||||
try:
|
||||
element = self.get_transaction_element(amount=amount.replace(',', '.'))
|
||||
element.find_element()
|
||||
return element
|
||||
except NoSuchElementException:
|
||||
time.sleep(10)
|
||||
time.sleep(5)
|
||||
self.driver.swipe(500, 500, 500, 1000)
|
||||
pytest.fail('Transaction was not found on Wallet/Transaction screen')
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import logging
|
||||
|
||||
from tests import info
|
||||
from views.base_view import BaseView
|
||||
from views.base_element import BaseButton, BaseText
|
||||
|
||||
|
@ -96,4 +95,4 @@ class WalletView(BaseView):
|
|||
if percentage_diff > 2:
|
||||
errors.append('Difference between current (%s) and expected (%s) USD balance > 2%%!!' % (usd, expected_usd))
|
||||
else:
|
||||
logging.info('Current USD balance %s is ok' % usd)
|
||||
info('Current USD balance %s is ok' % usd)
|
||||
|
|
Loading…
Reference in New Issue