diff --git a/test/appium/tests/atomic/account_management/test_profile.py b/test/appium/tests/atomic/account_management/test_profile.py index a1e2ca0dad..7955f0751f 100644 --- a/test/appium/tests/atomic/account_management/test_profile.py +++ b/test/appium/tests/atomic/account_management/test_profile.py @@ -327,6 +327,32 @@ class TestProfileSingleDevice(SingleDeviceTestCase): self.verify_no_errors() + @marks.testrail_id(5738) + @marks.medium + def test_dapps_permissions(self): + sign_in_view = SignInView(self.driver) + home_view = sign_in_view.create_user() + home_view.open_status_test_dapp() + home_view.back_button.click() + profile_view = home_view.profile_button.click() + profile_view.dapp_permissions_button.click() + profile_view.element_by_text('status-im.github.io').click() + if not profile_view.element_by_text('Wallet').is_element_displayed(): + self.errors.append('Wallet permission was not granted') + if not profile_view.element_by_text('Contact code').is_element_displayed(): + self.errors.append('Contact code permission was not granted') + profile_view.revoke_access_button.click() + profile_view.back_button.click() + dapp_view = profile_view.dapp_tab_button.click() + dapp_view.open_url('status-im.github.io/dapp') + if not dapp_view.element_by_text_part('connect to your wallet').is_element_displayed(): + self.errors.append('Wallet permission is not asked') + if dapp_view.allow_button.is_element_displayed(): + dapp_view.allow_button.click(times_to_click=1) + if not dapp_view.element_by_text_part('to your profile').is_element_displayed(): + self.errors.append('Profile permission is not asked') + self.verify_no_errors() + @marks.all @marks.account @@ -409,6 +435,7 @@ class TestProfileMultipleDevice(MultipleDeviceTestCase): chat_2.send_message_button.click() chat_1.chat_element_by_text(message_1).wait_for_visibility_of_element() + @marks.all @marks.account class TestProfileMultipleDevice(MultipleDeviceTestCase): @@ -462,7 +489,9 @@ class TestProfileMultipleDevice(MultipleDeviceTestCase): # device 2: check that messages appeared in 1-1 chat and new contacts are synced if not device_2_profile.element_by_text(transaction_senders['A']['username']): - self.errors.append('"%s" is not found in Contacts after adding when devices are paired' % transaction_senders['A']['username']) + self.errors.append( + '"%s" is not found in Contacts after adding when devices are paired' % transaction_senders['A'][ + 'username']) device_2_profile.get_back_to_home_view() chat = device_2_home.get_chat_with_user(basic_user['username']).click() if chat.chat_element_by_text(message_before_sync).is_element_displayed(): @@ -522,7 +551,7 @@ class TestProfileMultipleDevice(MultipleDeviceTestCase): # device 2: check that public chat and profile details are updated device_2_home = device_2_profile.get_back_to_home_view() if not device_2_home.element_by_text('#%s' % public_chat_before_sync_name).is_element_displayed(): - pytest.fail('Public chat "%s" doesn\'t appear after initial sync'% public_chat_before_sync_name) + pytest.fail('Public chat "%s" doesn\'t appear after initial sync' % public_chat_before_sync_name) device_2_home.profile_button.click() device_2_profile.contacts_button.scroll_to_element(9, 'up') # if not device_2_profile.element_by_text(username_before_sync).is_element_displayed(): @@ -553,7 +582,8 @@ class TestProfileMultipleDevice(MultipleDeviceTestCase): device_2_profile.get_back_to_home_view() if not device_2_home.element_by_text('#%s' % public_chat_after_sync_name).is_element_displayed(): - pytest.fail('Public chat "%s" doesn\'t appear on other device when devices are paired'% public_chat_before_sync_name) + pytest.fail( + 'Public chat "%s" doesn\'t appear on other device when devices are paired' % public_chat_before_sync_name) device_2_home.element_by_text(group_chat_name).click() device_2_group_chat = device_2_home.get_chat_view() diff --git a/test/appium/tests/atomic/account_management/test_wallet_management.py b/test/appium/tests/atomic/account_management/test_wallet_management.py index 77f70edc5b..1702195d7b 100644 --- a/test/appium/tests/atomic/account_management/test_wallet_management.py +++ b/test/appium/tests/atomic/account_management/test_wallet_management.py @@ -222,3 +222,37 @@ class TestWalletManagement(SingleDeviceTestCase): self.driver.fail('User collectibles token name in not shown') if not wallet_view.element_by_text('1').is_element_displayed(): self.driver.fail('User collectibles amount does not match') + + @marks.testrail_id(6208) + @marks.high + def test_add_custom_token(self): + contract_address = '0x25B1bD06fBfC2CbDbFc174e10f1B78b1c91cc77B' + name = 'SNTMiniMeToken' + symbol = 'SNT' + decimals = '18' + sign_in_view = SignInView(self.driver) + sign_in_view.create_user() + wallet_view = sign_in_view.wallet_button.click() + wallet_view.set_up_wallet() + wallet_view.multiaccount_more_options.click() + wallet_view.manage_assets_button.click() + token_view = wallet_view.add_custom_token_button.click() + token_view.contract_address_input.send_keys(contract_address) + token_view.progress_bar.wait_for_invisibility_of_element(30) + if token_view.name_input.text != name: + self.errors.append('Name for custom token was not set') + if token_view.symbol_input.text != symbol: + self.errors.append('Symbol for custom token was not set') + if token_view.decimals_input.text != decimals: + self.errors.append('Decimals for custom token was not set') + token_view.add_button.click() + token_view.back_button.click() + if not wallet_view.asset_by_name(symbol).is_element_displayed(): + self.errors.append('Custom token is not shown on Wallet view') + wallet_view.accounts_status_account.click() + send_transaction = wallet_view.send_transaction_button.click() + token_element = send_transaction.asset_by_name(symbol) + send_transaction.select_asset_button.click_until_presence_of_element(token_element) + if not token_element.is_element_displayed(): + self.errors.append('Custom token is not shown on Send Transaction view') + self.verify_no_errors() diff --git a/test/appium/tests/atomic/chats/test_public.py b/test/appium/tests/atomic/chats/test_public.py index 968f7a8014..e7b7552bf6 100644 --- a/test/appium/tests/atomic/chats/test_public.py +++ b/test/appium/tests/atomic/chats/test_public.py @@ -1,4 +1,7 @@ import time + +import emoji +import random from selenium.common.exceptions import TimeoutException from support.utilities import generate_timestamp from tests import marks @@ -110,6 +113,41 @@ class TestPublicChatMultipleDevice(MultipleDeviceTestCase): self.errors.append('New messages counter is shown on chat element for already seen message') self.verify_no_errors() + @marks.testrail_id(6202) + @marks.low + def test_emoji_messages_long_press(self): + self.create_drivers(2) + device_1, device_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1]) + home_1, home_2 = device_1.create_user(), device_2.create_user() + + chat_name = home_1.get_public_chat_name() + chat_1, chat_2 = home_1.join_public_chat(chat_name), home_2.join_public_chat(chat_name) + emoji_name = random.choice(list(emoji.EMOJI_UNICODE)) + emoji_unicode = emoji.EMOJI_UNICODE[emoji_name] + chat_1.chat_message_input.send_keys(emoji.emojize(emoji_name)) + chat_1.send_message_button.click() + + chat_1.chat_element_by_text(emoji_unicode).long_press_element() + chat_1.element_by_text('Copy').click() + chat_1.chat_message_input.paste_text_from_clipboard() + if chat_1.chat_message_input.text != emoji_unicode: + self.errors.append('Emoji message was not copied') + + chat_element_2 = chat_2.chat_element_by_text(emoji_unicode) + if not chat_element_2.is_element_displayed(sec=10): + self.errors.append('Message with emoji was not received in public chat by the recipient') + + chat_element_2.long_press_element() + chat_2.element_by_text('Reply').click() + message_text = 'test message' + chat_2.chat_message_input.send_keys(message_text) + chat_2.send_message_button.click() + + chat_element_1 = chat_1.chat_element_by_text(message_text) + if not chat_element_1.is_element_displayed(sec=10) or chat_element_1.replied_message_text != emoji_unicode: + self.errors.append('Reply message was not received by the sender') + self.verify_no_errors() + @marks.chat class TestPublicChatSingleDevice(SingleDeviceTestCase): @@ -198,4 +236,4 @@ class TestPublicChatSingleDevice(SingleDeviceTestCase): for message in (before_yesterday, quiet_time_before_yesterday): if not chat.element_by_text_part(message).is_element_displayed(): self.driver.fail('"%s" is not shown' % message) - self.verify_no_errors() \ No newline at end of file + self.verify_no_errors() diff --git a/test/appium/views/add_custom_token_view.py b/test/appium/views/add_custom_token_view.py new file mode 100644 index 0000000000..2fb0266c70 --- /dev/null +++ b/test/appium/views/add_custom_token_view.py @@ -0,0 +1,39 @@ +from views.base_element import BaseEditBox +from views.base_view import BaseView + + +class ContractAddressInput(BaseEditBox): + def __init__(self, driver): + super(ContractAddressInput, self).__init__(driver) + self.locator = self.Locator.xpath_selector( + "//*[@text='Contract address']/following-sibling::*[2]/android.widget.EditText") + + +class NameInput(BaseEditBox): + def __init__(self, driver): + super(NameInput, self).__init__(driver) + self.locator = self.Locator.xpath_selector("//*[@text='Name']/following-sibling::*[1]/android.widget.EditText") + + +class SymbolInput(BaseEditBox): + def __init__(self, driver): + super(SymbolInput, self).__init__(driver) + self.locator = self.Locator.xpath_selector( + "//*[@text='Symbol']/following-sibling::*[2]/android.widget.EditText") + + +class DecimalsInput(BaseEditBox): + def __init__(self, driver): + super(DecimalsInput, self).__init__(driver) + self.locator = self.Locator.xpath_selector( + "//*[@text='Decimals']/following-sibling::*[2]/android.widget.EditText") + + +class AddCustomTokenView(BaseView): + def __init__(self, driver): + super(AddCustomTokenView, self).__init__(driver) + self.driver = driver + self.contract_address_input = ContractAddressInput(self.driver) + self.name_input = NameInput(self.driver) + self.symbol_input = SymbolInput(self.driver) + self.decimals_input = DecimalsInput(self.driver) diff --git a/test/appium/views/base_view.py b/test/appium/views/base_view.py index b1cefb4f23..b3895e3526 100644 --- a/test/appium/views/base_view.py +++ b/test/appium/views/base_view.py @@ -35,9 +35,9 @@ class AllowButton(BaseButton): super(AllowButton, self).__init__(driver) self.locator = self.Locator.xpath_selector("//*[@text='Allow' or @text='ALLOW']") - def click(self): + def click(self, times_to_click=3): try: - for _ in range(3): + for _ in range(times_to_click): self.find_element().click() self.driver.info('Tap on %s' % self.name) except NoSuchElementException: @@ -334,6 +334,7 @@ class BaseView(object): self.show_roots_button = ShowRoots(self.driver) self.get_started_button = GetStartedButton(self.driver) self.ok_got_it_button = OkGotItButton(self.driver) + self.progress_bar = ProgressBar(self.driver) # external browser self.open_in_status_button = OpenInStatusButton(self.driver) diff --git a/test/appium/views/chat_view.py b/test/appium/views/chat_view.py index 3bce78f167..596b50fb56 100644 --- a/test/appium/views/chat_view.py +++ b/test/appium/views/chat_view.py @@ -252,8 +252,9 @@ class ChatElementByText(BaseText): def __init__(self, driver, text): super(ChatElementByText, self).__init__(driver) self.message_text = text + self.message_locator = "//*[starts-with(@text,'%s')]" % text self.locator = self.Locator.xpath_selector( - "//*[starts-with(@text,'%s')]/ancestor::android.view.ViewGroup[@content-desc='chat-item']" % text) + self.message_locator + "/ancestor::android.view.ViewGroup[@content-desc='chat-item']") def find_element(self): self.driver.info("Looking for message with text '%s'" % self.message_text) @@ -311,6 +312,19 @@ class ChatElementByText(BaseText): self.locator.value + "//android.view.ViewGroup//android.widget.TextView[contains(@text,'%s')]" % text) return element.is_element_displayed(wait_time) + @property + def replied_message_text(self): + class RepliedMessageText(BaseButton): + def __init__(self, driver, parent_locator): + super(RepliedMessageText, self).__init__(driver) + self.locator = self.Locator.xpath_selector( + parent_locator + "/preceding-sibling::*[1]/android.widget.TextView[2]") + + try: + return RepliedMessageText(self.driver, self.message_locator).text + except NoSuchElementException: + return '' + class EmptyPublicChatMessage(BaseText): def __init__(self, driver): diff --git a/test/appium/views/profile_view.py b/test/appium/views/profile_view.py index 4577c10d6d..35ca536739 100644 --- a/test/appium/views/profile_view.py +++ b/test/appium/views/profile_view.py @@ -412,48 +412,73 @@ class RemovePictureButton(BaseButton): super().__init__(driver) self.locator = self.Locator.text_selector('Remove current photo') + class DevicesButton(BaseButton): def __init__(self, driver): super().__init__(driver) self.locator = self.Locator.accessibility_id('pairing-settings-button') + class DeviceNameInput(BaseEditBox): def __init__(self, driver): super().__init__(driver) self.locator = self.Locator.accessibility_id('device-name') + class ContinueButton(BaseButton): def __init__(self, driver): super(ContinueButton, self).__init__(driver) self.locator = self.Locator.text_selector('Continue') + class GoToPairingSettingsButton(BaseButton): def __init__(self, driver): super(GoToPairingSettingsButton, self).__init__(driver) self.locator = self.Locator.text_selector('GO TO PAIRING SETTINGS') + class AdvertiseDeviceButton(BaseButton): def __init__(self, driver): super(AdvertiseDeviceButton, self).__init__(driver) self.locator = self.Locator.accessibility_id('advertise-device') + class SyncedDeviceToggle(BaseButton): def __init__(self, driver, device_name): super(SyncedDeviceToggle, self).__init__(driver) self.device_name = device_name - self.locator = self.Locator.xpath_selector('//android.widget.TextView[@text="%s"]/../android.widget.Switch' % device_name) + self.locator = self.Locator.xpath_selector( + '//android.widget.TextView[@text="%s"]/../android.widget.Switch' % device_name) + class SyncAllButton(BaseButton): def __init__(self, driver): super(SyncAllButton, self).__init__(driver) self.locator = self.Locator.text_selector('Sync all devices') + class ContactsButton(BaseButton): def __init__(self, driver): super(ContactsButton, self).__init__(driver) self.locator = self.Locator.text_selector('Contacts') +class DappPermissionsButton(BaseButton): + def __init__(self, driver): + super(DappPermissionsButton, self).__init__(driver) + self.locator = self.Locator.accessibility_id('dapps-permissions-button') + + def click(self): + self.scroll_to_element().click() + self.driver.info('Tap on %s' % self.name) + + +class RevokeAccessButton(BaseButton): + def __init__(self, driver): + super(RevokeAccessButton, self).__init__(driver) + self.locator = self.Locator.text_selector('Revoke access') + + class ProfileView(BaseView): def __init__(self, driver): @@ -494,6 +519,8 @@ class ProfileView(BaseView): self.advanced_button = AdvancedButton(self.driver) self.debug_mode_toggle = DebugModeToggle(self.driver) self.contacts_button = ContactsButton(self.driver) + self.dapp_permissions_button = DappPermissionsButton(self.driver) + self.revoke_access_button = RevokeAccessButton(self.driver) # Backup recovery phrase self.backup_recovery_phrase_button = BackupRecoveryPhraseButton(self.driver) @@ -529,7 +556,6 @@ class ProfileView(BaseView): self.advertise_device_button = AdvertiseDeviceButton(self.driver) self.sync_all_button = SyncAllButton(self.driver) - def switch_network(self, network): self.advanced_button.click() self.debug_mode_toggle.click() @@ -620,7 +646,6 @@ class ProfileView(BaseView): self.logout_button.click() return self.logout_dialog.logout_button.click() - def mail_server_by_name(self, server_name): return MailServerElement(self.driver, server_name) @@ -636,7 +661,6 @@ class ProfileView(BaseView): self.continue_button.click_until_presence_of_element(self.advertise_device_button, 2) self.advertise_device_button.click() - @property def current_active_network(self): self.advanced_button.click() diff --git a/test/appium/views/send_transaction_view.py b/test/appium/views/send_transaction_view.py index 071997a31d..1ced192b02 100644 --- a/test/appium/views/send_transaction_view.py +++ b/test/appium/views/send_transaction_view.py @@ -1,7 +1,7 @@ from tests import common_password from views.base_element import BaseText, BaseElement from views.base_element import BaseButton, BaseEditBox -from views.base_view import BaseView, OkButton, ProgressBar +from views.base_view import BaseView, OkButton class FirstRecipient(BaseButton): @@ -219,7 +219,6 @@ class SendTransactionView(BaseView): self.error_dialog = ErrorDialog(self.driver) self.share_button = ShareButton(self.driver) - self.progress_bar = ProgressBar(self.driver) self.onboarding_message = OnboardingMessage(self.driver) self.validation_warnings = ValidationWarnings(self.driver) diff --git a/test/appium/views/wallet_view.py b/test/appium/views/wallet_view.py index cc53695b25..b28df47ae3 100644 --- a/test/appium/views/wallet_view.py +++ b/test/appium/views/wallet_view.py @@ -187,13 +187,13 @@ class BackupRecoveryPhraseWarningText(BaseButton): class MultiaccountMoreOptions(BaseButton): - def __init__(self,driver): + def __init__(self, driver): super(MultiaccountMoreOptions, self).__init__(driver) self.locator = self.Locator.accessibility_id('accounts-more-options') class AccountsStatusAccount(BaseButton): - def __init__(self,driver): + def __init__(self, driver): super(AccountsStatusAccount, self).__init__(driver) self.locator = self.Locator.xpath_selector("//android.widget.HorizontalScrollView//*[@text='Status account']") @@ -220,6 +220,16 @@ class ReceiveTransactionButton(BaseButton): return SendTransactionView(self.driver) +class AddCustomTokenButton(BaseButton): + def __init__(self, driver): + super(AddCustomTokenButton, self).__init__(driver) + self.locator = self.Locator.xpath_selector("//*[@text='Add custom token']") + + def navigate(self): + from views.add_custom_token_view import AddCustomTokenView + return AddCustomTokenView(self.driver) + + class WalletView(BaseView): def __init__(self, driver): super(WalletView, self).__init__(driver) @@ -251,6 +261,8 @@ class WalletView(BaseView): self.backup_recovery_phrase = BackupRecoveryPhrase(self.driver) self.backup_recovery_phrase_warning_text = BackupRecoveryPhraseWarningText(self.driver) + self.add_custom_token_button = AddCustomTokenButton(self.driver) + # elements for multiaccount self.multiaccount_more_options = MultiaccountMoreOptions(self.driver) self.accounts_status_account = AccountsStatusAccount(self.driver)