diff --git a/test/appium/Jenkinsfile b/test/appium/Jenkinsfile index 02b8775482..c76551aa0e 100644 --- a/test/appium/Jenkinsfile +++ b/test/appium/Jenkinsfile @@ -1,6 +1,6 @@ node {sauce('b9aded57-5cc1-4f6b-b5ea-42d989987852') { checkout([$class: 'GitSCM', branches: [[name: '*/develop']], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'CleanBeforeCheckout']], submoduleCfg: [], userRemoteConfigs: [[url: 'https://github.com/status-im/status-react.git']]]) - try {sh 'cd test/appium/tests && /usr/local/bin/python3 -m pytest -m sanity --build ${JOB_NAME}__${BUILD_NUMBER} -v --dist=loadscope -n3' + try {sh 'cd test/appium/tests && /usr/local/bin/python3 -m pytest -m all --build ${JOB_NAME}__${BUILD_NUMBER} -v --dist=loadscope -n3' } finally { saucePublisher() diff --git a/test/appium/tests/basetestcase.py b/test/appium/tests/basetestcase.py index ad91b4060e..8d72347fa7 100644 --- a/test/appium/tests/basetestcase.py +++ b/test/appium/tests/basetestcase.py @@ -77,8 +77,7 @@ class AbstractTestCase: desired_caps['platformName'] = 'Android' desired_caps['appiumVersion'] = '1.7.1' desired_caps['platformVersion'] = '6.0' - desired_caps['commandTimeout'] = 600 - desired_caps['idleTimeout'] = 1000 + desired_caps['newCommandTimeout'] = 600 return desired_caps @abstractmethod diff --git a/test/appium/tests/conftest.py b/test/appium/tests/conftest.py index b9e01fe46d..ea52a318dc 100644 --- a/test/appium/tests/conftest.py +++ b/test/appium/tests/conftest.py @@ -55,7 +55,7 @@ def is_uploaded(): def pytest_configure(config): import logging logging.basicConfig(level=logging.INFO) - if is_master(config): + if is_master(config) and config.getoption('env') == 'sauce': if not is_uploaded(): response = requests.get(storage + latest_apk, stream=True) response.raise_for_status() diff --git a/test/appium/tests/test_chats.py b/test/appium/tests/test_chats.py index f47b54f29e..11980b8e1c 100644 --- a/test/appium/tests/test_chats.py +++ b/test/appium/tests/test_chats.py @@ -4,7 +4,7 @@ from tests.preconditions import set_password_as_new_user from views.home import HomeView -@pytest.mark.sanity +@pytest.mark.all class TestChats(MultiplyDeviceTestCase): def test_one_to_one_chat(self): diff --git a/test/appium/tests/test_group_chats.py b/test/appium/tests/test_group_chats.py index 8ffc992cbb..447cebd1de 100644 --- a/test/appium/tests/test_group_chats.py +++ b/test/appium/tests/test_group_chats.py @@ -4,9 +4,10 @@ from tests.preconditions import set_password_as_new_user from views.home import HomeView -@pytest.mark.sanity +@pytest.mark.all class TestGroupChats(MultiplyDeviceTestCase): + @pytest.mark.chat def test_group_chat_send_receive_messages_and_remove_user(self): device_1, device_2 = HomeView(self.driver_1), \ diff --git a/test/appium/tests/test_networks.py b/test/appium/tests/test_networks.py new file mode 100644 index 0000000000..2705310ca8 --- /dev/null +++ b/test/appium/tests/test_networks.py @@ -0,0 +1,100 @@ +import pytest +from tests.basetestcase import MultiplyDeviceTestCase, SingleDeviceTestCase +from tests.preconditions import set_password_as_new_user +from views.home import HomeView +from selenium.common.exceptions import TimeoutException + + +class TestNetwork(SingleDeviceTestCase): + + @pytest.mark.network + @pytest.mark.parametrize("network", ['Ropsten', 'Rinkeby', 'Rinkeby with upstream RPC', + 'Mainnet', 'Mainnet with upstream RPC']) + def test_network_switch(self, network): + + home = HomeView(self.driver) + set_password_as_new_user(home) + home.back_button.click() + chats = home.get_chats() + chats.profile_button.click() + profile = chats.profile_icon.click() + login = profile.switch_network(network) + login.first_account_button.click() + login.password_input.send_keys('qwerty1234') + login.sign_in_button.click() + login.find_full_text('Chats', 20) + + +class TestNetworkChats(MultiplyDeviceTestCase): + + networks = [['Ropsten', 'Ropsten with upstream RPC'], ['Ropsten', 'Rinkeby'], + ['Ropsten', 'Rinkeby with upstream RPC'], ['Ropsten', 'Mainnet'], + ['Ropsten', 'Mainnet with upstream RPC'], ['Ropsten', 'Ropsten'], + ['Ropsten with upstream RPC', 'Ropsten with upstream RPC'], ['Ropsten with upstream RPC', 'Rinkeby'], + ['Ropsten with upstream RPC', 'Rinkeby with upstream RPC'], ['Ropsten with upstream RPC', 'Mainnet'], + ['Ropsten with upstream RPC', 'Mainnet with upstream RPC'], ['Rinkeby', 'Rinkeby'], + ['Rinkeby', 'Rinkeby with upstream RPC'], ['Rinkeby', 'Mainnet'], + ['Rinkeby', 'Mainnet with upstream RPC'], ['Rinkeby with upstream RPC', 'Rinkeby with upstream RPC'], + ['Rinkeby with upstream RPC', 'Mainnet'], ['Rinkeby with upstream RPC', 'Mainnet with upstream RPC'], + ['Mainnet', 'Mainnet'], ['Mainnet', 'Mainnet with upstream RPC'], + ['Mainnet with upstream RPC', 'Mainnet with upstream RPC']] + + @pytest.mark.network_chat + @pytest.mark.parametrize("network", networks, + ids=[i[0] + ' & ' + i[1] for i in networks]) + def test_one_to_one_chat_between(self, network): + device_1, device_2 = HomeView(self.driver_1), HomeView(self.driver_2) + set_password_as_new_user(device_1, device_2) + device_1.back_button.click() + chats_d1 = device_1.get_chats() + chats_d1.profile_button.click() + profile_d1 = chats_d1.profile_icon.click() + key = profile_d1.public_key_text.text + if network[0] != 'Ropsten with upstream RPC': + login_d1 = profile_d1.switch_network(network[0]) + login_d1.first_account_button.click() + login_d1.password_input.send_keys('qwerty1234') + login_d1.sign_in_button.click() + login_d1.find_full_text('Chats', 60) + else: + profile_d1.back_button.click() + device_2.back_button.click() + chats_d2 = device_2.get_chats() + if network[1] != 'Ropsten with upstream RPC': + chats_d2.profile_button.click() + profile_d2 = chats_d2.profile_icon.click() + login_d2 = profile_d2.switch_network(network[1]) + login_d2.first_account_button.click() + login_d2.password_input.send_keys('qwerty1234') + login_d2.sign_in_button.click() + login_d2.find_full_text('Chats', 60) + chats_d2.plus_button.click() + chats_d2.add_new_contact.click() + chats_d2.public_key_edit_box.send_keys(key) + chats_d2.confirm() + chats_d2.confirm_public_key_button.click() + message_1 = network[0] + message_2 = network[1] + user_d1_name = chats_d2.user_name_text.text + chats_d2.chat_message_input.send_keys(message_2) + chats_d2.send_message_button.click() + errors = list() + try: + chats_d1.find_full_text(message_2) + except TimeoutException: + errors.append("Message '%s' wasn't received by Device #1") + one_to_one_chat_d1 = chats_d1.element_by_text(message_2, 'button') + one_to_one_chat_d1.click() + one_to_one_chat_d2 = chats_d2.element_by_text(user_d1_name, 'button') + one_to_one_chat_d2.click() + chats_d1.chat_message_input.send_keys(message_1) + chats_d1.send_message_button.click() + try: + chats_d2.find_full_text(message_1) + except TimeoutException: + errors.append("Message '%s' wasn't received by Device #2") + if errors: + msg = '' + for error in errors: + msg += (error + '\n') + pytest.fail(msg, pytrace=False) diff --git a/test/appium/tests/test_sanity.py b/test/appium/tests/test_sanity.py index ecc492b517..56fc4e1275 100644 --- a/test/appium/tests/test_sanity.py +++ b/test/appium/tests/test_sanity.py @@ -6,7 +6,7 @@ from tests.preconditions import set_password_as_new_user, recover_access from tests import basic_user, transaction_users -@pytest.mark.sanity +@pytest.mark.all class TestAccess(SingleDeviceTestCase): def test_recover_access(self): @@ -63,9 +63,10 @@ class TestAccess(SingleDeviceTestCase): home.confirm() home.find_full_text(verifications[verification]["outcome"]) - @pytest.mark.parametrize("test, recipient, sender", [('wrong_password', 'A_USER', 'B_USER'), - ('group_chat', 'A_USER', 'B_USER'), - ('one_to_one_chat', 'B_USER', 'A_USER')], + @pytest.mark.transaction + @pytest.mark.parametrize("test, recipient, sender", [('group_chat', 'A_USER', 'B_USER'), + ('one_to_one_chat', 'B_USER', 'A_USER'), + ('wrong_password', 'A_USER', 'B_USER')], ids=['group_chat', 'one_to_one_chat', 'wrong_password']) def test_send_transaction(self, test, recipient, sender): home = HomeView(self.driver) @@ -123,6 +124,7 @@ class TestAccess(SingleDeviceTestCase): chats.find_full_text('to ' + transaction_users[recipient]['username'], 60) chats.verify_balance_is_updated(initial_balance_recipient, recipient_address) + @pytest.mark.transaction def test_send_transaction_from_daap(self): home = HomeView(self.driver) set_password_as_new_user(home) diff --git a/test/appium/views/base_element.py b/test/appium/views/base_element.py index e4bd40e49e..dc38f9ac9e 100644 --- a/test/appium/views/base_element.py +++ b/test/appium/views/base_element.py @@ -52,8 +52,7 @@ class BaseElement(object): action = TouchAction(self.driver) for _ in range(5): try: - self.find_element() - break + return self.find_element() except NoSuchElementException: logging.info('Scrolling to %s' % self.name) action.press(x=0, y=1000).move_to(x=200, y=-1000).release().perform() diff --git a/test/appium/views/profile.py b/test/appium/views/profile.py index 1268d48026..902b351b17 100644 --- a/test/appium/views/profile.py +++ b/test/appium/views/profile.py @@ -8,6 +8,12 @@ class PublicKeyText(BaseText): super(PublicKeyText, self).__init__(driver) self.locator = self.Locator.accessibility_id('profile-public-key') + @property + def text(self): + text = self.scroll_to_element().text + logging.info('%s is %s' % (self.name, text)) + return text + class ProfileAddressText(BaseText): @@ -16,6 +22,56 @@ class ProfileAddressText(BaseText): self.locator = self.Locator.accessibility_id('profile-address') +class NetworkSettingsButton(BaseButton): + + def __init__(self, driver): + super(NetworkSettingsButton, self).__init__(driver) + self.locator = self.Locator.xpath_selector('//*[@text="Network settings"]') + + class Ropsten(BaseButton): + + def __init__(self, driver): + super(NetworkSettingsButton.Ropsten, self).__init__(driver) + self.locator = self.Locator.xpath_selector('//*[@text="Ropsten"]') + + class RopstenWithUpstreamRPC(BaseButton): + + def __init__(self, driver): + super(NetworkSettingsButton.RopstenWithUpstreamRPC, self).__init__(driver) + self.locator = self.Locator.xpath_selector('//*[@text="Ropsten with upstream RPC"]') + + class Rinkeby(BaseButton): + + def __init__(self, driver): + super(NetworkSettingsButton.Rinkeby, self).__init__(driver) + self.locator = self.Locator.xpath_selector('//*[@text="Rinkeby"]') + + class RinkebyWithUpstreamRPC(BaseButton): + + def __init__(self, driver): + super(NetworkSettingsButton.RinkebyWithUpstreamRPC, self).__init__(driver) + self.locator = self.Locator.xpath_selector('//*[@text="Rinkeby with upstream RPC"]') + + class Mainnet(BaseButton): + + def __init__(self, driver): + super(NetworkSettingsButton.Mainnet, self).__init__(driver) + self.locator = self.Locator.xpath_selector('//*[@text="Mainnet"]') + + class MainnetWithUpstreamRPC(BaseButton): + + def __init__(self, driver): + super(NetworkSettingsButton.MainnetWithUpstreamRPC, self).__init__(driver) + self.locator = self.Locator.xpath_selector('//*[@text="Mainnet with upstream RPC"]') + + class ConnectButton(BaseButton): + + def __init__(self, driver): + super(NetworkSettingsButton.ConnectButton, self).__init__(driver) + self.locator = self.Locator.xpath_selector('//*[@text="CONNECT"]') + + + class ProfileViewObject(BaseViewObject): def __init__(self, driver): @@ -24,3 +80,27 @@ class ProfileViewObject(BaseViewObject): self.public_key_text = PublicKeyText(self.driver) self.profile_address_text = ProfileAddressText(self.driver) + + self.network_settings_button = NetworkSettingsButton(self.driver) + + self.ropsten = NetworkSettingsButton.Ropsten(self.driver) + self.ropsten_upstream_rpc = NetworkSettingsButton.RopstenWithUpstreamRPC(self.driver) + self.rinkeby = NetworkSettingsButton.Rinkeby(self.driver) + self.rinkeby_upstream_rpc_ = NetworkSettingsButton.RinkebyWithUpstreamRPC(self.driver) + self.mainnet = NetworkSettingsButton.Mainnet(self.driver) + self.mainnet_upstream_rpc = NetworkSettingsButton.MainnetWithUpstreamRPC(self.driver) + self.connect_button = NetworkSettingsButton.ConnectButton(self.driver) + + def switch_network(self, network): + self.network_settings_button.scroll_to_element() + self.network_settings_button.click() + networks = {'Ropsten': self.ropsten, + 'Ropsten with upstream RPC': self.ropsten_upstream_rpc, + 'Rinkeby': self.rinkeby, + 'Rinkeby with upstream RPC': self.ropsten_upstream_rpc, + 'Mainnet': self.mainnet, + 'Mainnet with upstream RPC': self.mainnet_upstream_rpc} + networks[network].click() + self.connect_button.click() + from views.login import LoginView + return LoginView(self.driver)