diff --git a/src/status_im/ui/screens/chat/views.cljs b/src/status_im/ui/screens/chat/views.cljs index 73e73d8af8..cdd531a4b3 100644 --- a/src/status_im/ui/screens/chat/views.cljs +++ b/src/status_im/ui/screens/chat/views.cljs @@ -87,7 +87,8 @@ color loading-messages? no-messages?]}] - [react/view (style/intro-header-container loading-messages? no-messages?) + [react/view {:style (style/intro-header-container loading-messages? no-messages?) + :accessibility-label :history-chat} ;; Icon section [react/view {:style {:margin-top 42 :margin-bottom 24}} @@ -117,7 +118,7 @@ (defn chat-intro-one-to-one [{:keys [chat-id] :as opts}] (let [contact-names @(re-frame/subscribe [:contacts/contact-two-names-by-identity chat-id])] - (chat-intro (assoc opts :contact-name (first contact-names))))) + [chat-intro (assoc opts :contact-name (first contact-names))])) (defn chat-intro-header-container [{:keys [group-chat invitation-admin @@ -126,8 +127,8 @@ public?]} no-messages] [react/touchable-without-feedback - {:style {:flex 1 - :align-items :flex-start} + {:style {:flex 1 + :align-items :flex-start} :on-press (fn [_] (react/dismiss-keyboard!))} (let [opts diff --git a/test/appium/tests/__init__.py b/test/appium/tests/__init__.py index 1166919162..f837a81431 100644 --- a/test/appium/tests/__init__.py +++ b/test/appium/tests/__init__.py @@ -24,6 +24,8 @@ def get_current_time(): def debug(text: str): logging.debug(text) +appium_root_project_path = os.path.join(os.sep.join(__file__.split(os.sep)[:-1]), '../') + pytest_config_global = dict() test_suite_data = TestSuiteData() appium_container = AppiumContainer() @@ -43,7 +45,8 @@ staging_fleet = 'eth.staging' prod_fleet = 'eth.prod' # This fleet is used in the tests used_fleet = staging_fleet -geth_log_emulator_path = '/storage/emulated/0/Android/data/im.status.ethereum/files/Download/geth.log' +app_path = '/storage/emulated/0/Android/data/im.status.ethereum/files/Download/' +geth_log_emulator_path = app_path + 'geth.log' mailserver_ams = 'mail-01.do-ams3' mailserver_hk = 'mail-01.ac-cn-hongkong-c' diff --git a/test/appium/tests/atomic/chats/test_public.py b/test/appium/tests/atomic/chats/test_public.py index b74abda7f6..b330dc602a 100644 --- a/test/appium/tests/atomic/chats/test_public.py +++ b/test/appium/tests/atomic/chats/test_public.py @@ -78,7 +78,7 @@ class TestPublicChatMultipleDevice(MultipleDeviceTestCase): if home_1.home_button.public_unread_messages.is_element_displayed(): self.errors.append('New messages public chat badge is shown on Home button') if chat_element.new_messages_public_chat.is_element_displayed(): - self.errors.append('Unread messages badge is shown in public chat while while there are no unread messages') + self.errors.append('Unread messages badge is shown in public chat while there are no unread messages') [home.get_chat('#' + chat_name).click() for home in (home_1,home_2)] chat_1.send_message(message_2) chat_2.chat_element_by_text(message_2).wait_for_element(20) diff --git a/test/appium/tests/atomic/dapps_and_browsing/test_browsing.py b/test/appium/tests/atomic/dapps_and_browsing/test_browsing.py index 01424ff117..85af3dc681 100644 --- a/test/appium/tests/atomic/dapps_and_browsing/test_browsing.py +++ b/test/appium/tests/atomic/dapps_and_browsing/test_browsing.py @@ -296,7 +296,6 @@ class TestBrowsing(SingleDeviceTestCase): dapp_view.enter_url_editbox.click() dapp_view.paste_text() dapp_view.confirm() - dapp_view.progress_bar.wait_for_invisibility_of_element(20) if not dapp_view.web_page.is_element_image_equals_template(urls[url]): self.errors.append('Web page does not match expected template %s' % urls[url]) dapp_view.cross_icon.click() diff --git a/test/appium/tests/atomic/test_upgrade.py b/test/appium/tests/atomic/test_upgrade.py index 6c69657b8a..4d9a96485e 100644 --- a/test/appium/tests/atomic/test_upgrade.py +++ b/test/appium/tests/atomic/test_upgrade.py @@ -1,25 +1,122 @@ from tests import marks from tests.base_test_case import SingleDeviceTestCase +from tests.users import upgrade_users from views.sign_in_view import SignInView +import views.upgrade_dbs.chats.data as chat_data - -@marks.skip +@marks.upgrade class TestUpgradeApplication(SingleDeviceTestCase): @marks.testrail_id(6284) - def test_apk_upgrade(self): + def test_unread_previews_public_chat_upgrade(self): sign_in = SignInView(self.driver) - home = sign_in.create_user() + unread_one_to_one_name, unread_public_name = 'All Whopping Dassierat', '#before-upgrade' + chats = chat_data.chats + home = sign_in.import_db(user=upgrade_users['chats'], import_db_folder_name='chats') + home.just_fyi("Grab profile version") + profile = home.profile_button.click() profile.about_button.click() old_version = profile.app_version_text.text + profile.upgrade_app() self.app = sign_in.driver.launch_app() home = sign_in.sign_in() - profile = home.profile_button.click() + home.profile_button.click() profile.about_button.click() new_version = profile.app_version_text.text - print('Upgraded app version is %s vs base version is %s ' % (new_version, old_version)) - assert new_version != old_version + # Commented for releases only + # if new_version == old_version: + # self.errors.append('Upgraded app version is %s vs base version is %s ' % (new_version, old_version)) + home.home_button.click() + + home.just_fyi("Check chat previews") + for chat in chats.keys(): + actual_chat_preview = home.get_chat(chat).chat_preview + expected_chat_preview = chats[chat]['preview'] + if actual_chat_preview != expected_chat_preview: + self.errors.append('Expected preview for %s is "%s", in fact "%s"' % (chat, expected_chat_preview, actual_chat_preview)) + + home.just_fyi("Check unread indicator") + if home.home_button.counter.text != '1': + self.errors.append('New messages counter is not shown on Home button') + unread_one_to_one, unread_public = home.get_chat(unread_one_to_one_name), home.get_chat(unread_public_name) + if unread_one_to_one.new_messages_counter.text != chats[unread_one_to_one_name]['unread']: + self.errors.append('New messages counter is not shown on chat element') + if not unread_public.new_messages_public_chat.is_element_displayed(): + self.errors.append('Unread messages badge is not shown in public chat') + + home.just_fyi("Check images / add to contacts") + not_contact = unread_one_to_one_name + not_contact_chat = home.get_chat(not_contact).click() + if not not_contact_chat.add_to_contacts.is_element_displayed(): + self.errors.append('Add to contacts is not shown in 1-1 chat') + images = not_contact_chat.image_chat_item.find_elements() + if len(images) != 2: + self.errors.append('%s images are shown instead of 2' % str(len(images))) + for message in chats[not_contact]['messages']: + if not not_contact_chat.chat_element_by_text(message).is_element_displayed(): + self.errors.append('"%s" is not shown after upgrade' % message) + home.home_button.double_click() + if unread_one_to_one.new_messages_counter.text == '1': + self.errors.append('New messages counter is shown on chat element after opening chat') + + home.just_fyi("**Check public chat**") + pub_chat_data = chats[unread_public_name] + public_chat = home.get_chat(unread_public_name).click() + public_chat.scroll_to_start_of_history() + for key in pub_chat_data['preview_messages']: + home.just_fyi("Checking %s preview case in public chat" % key) + data = pub_chat_data['preview_messages'][key] + if not public_chat.element_by_text_part(data['txt']).is_element_displayed(): + public_chat.element_by_text_part(data['txt']).scroll_to_element() + message = public_chat.get_preview_message_by_text(data['txt']) + if not message.preview_image: + self.errors.append('Preview message is not shown for %s' % key) + if 'title' in data: + if message.preview_title.text != data['title']: + self.errors.append("Title '%s' does not match expected" % message.preview_title.text) + if message.preview_subtitle.text != data['subtitle']: + self.errors.append("Subtitle '%s' does not match expected" % message.preview_subtitle.text) + home.home_button.click() + + home.just_fyi("Checking markdown messages in public chat") + home.get_chat(unread_public_name).click() + messages = list(pub_chat_data['quoted_text_messages']) + public_chat.element_by_text(messages[0]).scroll_to_element(10, 'up') + for i in range(len(messages)): + if not public_chat.element_by_text(messages[i]).is_element_displayed(): + self.errors.append("Markdown message '%s' does not match expected" % messages[i]) + + home.just_fyi("Checking that have uncollapse on long message") + messages = pub_chat_data['messages'] + public_chat.element_starts_with_text(messages['long']).scroll_to_element() + public_chat.element_by_text_part(messages['tag']).scroll_to_element() + if not public_chat.chat_element_by_text(messages['long']).uncollapse: + self.errors.append("No uncollapse icon on long message is shown!") + + home.just_fyi("Checking reaction, tag message and sticker") + tag_message = public_chat.chat_element_by_text(messages['tag']) + if tag_message.emojis_below_message(emoji='love', own=True) !=1: + self.errors.append("Emojis are not displayed below tag message!") + if not public_chat.sticker_message.is_element_displayed(): + self.errors.append("Sticker is not displayed!") + public_chat.element_starts_with_text(messages['tag']).click() + public_chat.history_start_icon.wait_for_visibility_of_element(20) + if not public_chat.user_name_text.text == messages['tag']: + self.errors.append('Could not redirect a user to a public chat tapping the tag message after upgrade') + home.home_button.click() + + home.just_fyi("Checking reply and mention message") + public_chat = home.get_chat(unread_public_name).click() + public_replied_message = public_chat.chat_element_by_text(messages['reply']) + if messages['long'] not in public_replied_message.replied_message_text: + self.errors.append("Reply is not present in message received in public chat after upgrade") + if not public_chat.chat_element_by_text(messages['mention']).is_element_displayed(): + self.errors.append("Mention is not present in public chat after upgrade") + + self.errors.verify_no_errors() + + diff --git a/test/appium/tests/atomic/transactions/test_wallet.py b/test/appium/tests/atomic/transactions/test_wallet.py index 1a547b4a6f..49d311cad9 100644 --- a/test/appium/tests/atomic/transactions/test_wallet.py +++ b/test/appium/tests/atomic/transactions/test_wallet.py @@ -457,7 +457,6 @@ class TestTransactionWalletSingleDevice(SingleDeviceTestCase): 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: diff --git a/test/appium/tests/marks.py b/test/appium/tests/marks.py index 01ffa3a8a1..53547673e7 100644 --- a/test/appium/tests/marks.py +++ b/test/appium/tests/marks.py @@ -9,4 +9,5 @@ low = pytest.mark.low flaky = pytest.mark.flaky transaction = pytest.mark.transaction +upgrade = pytest.mark.upgrade skip = pytest.mark.skip \ No newline at end of file diff --git a/test/appium/tests/users.py b/test/appium/tests/users.py index af0fcf0bab..88948b7a3b 100644 --- a/test/appium/tests/users.py +++ b/test/appium/tests/users.py @@ -37,6 +37,10 @@ dummy_user['public_key'] = "0x04596348471aa19d31c8503fa00f95abd0fc3ca90866881728 "a2748453accf9d358b8d7a1448597201c664dc280e37" dummy_user['address'] = "0xdF6Bc71206d7ea89ec905a7f5ce8Ff34C85eB04e" +upgrade_users = dict() + +upgrade_users['chats'] = dict() +upgrade_users['chats']['passphrase'] = 'identify level pink lift choose winner hour onion style festival rather salmon' wallet_users = dict() diff --git a/test/appium/views/base_view.py b/test/appium/views/base_view.py index 2c5979d26f..0d81738352 100644 --- a/test/appium/views/base_view.py +++ b/test/appium/views/base_view.py @@ -145,11 +145,6 @@ class SendMessageButton(Button): super().__init__(driver, accessibility_id="send-message-button") -class ProgressBar(BaseElement): - def __init__(self, driver, parent_locator: str = ''): - super().__init__(driver, xpath="%s//android.widget.ProgressBar" % parent_locator) - - class AssetButton(Button): def __init__(self, driver, asset_name): super().__init__(driver, xpath="(//*[@content-desc=':%s-asset-value'])[1]" % asset_name) @@ -233,7 +228,6 @@ class BaseView(object): self.show_roots_button = Button(self.driver, accessibility_id="Show roots") self.get_started_button = Button(self.driver, translation_id="get-started") self.ok_got_it_button = Button(self.driver, translation_id="ok-got-it") - self.progress_bar = ProgressBar(self.driver) self.cross_icon_inside_welcome_screen_button = Button(self.driver, accessibility_id='hide-home-button') self.status_in_background_button = Button(self.driver, xpath="//*[contains(@content-desc,'Status')]") self.cancel_button = Button(self.driver, translation_id="cancel", uppercase=True) diff --git a/test/appium/views/chat_view.py b/test/appium/views/chat_view.py index ec69e95f8a..a7bad2b53c 100644 --- a/test/appium/views/chat_view.py +++ b/test/appium/views/chat_view.py @@ -7,7 +7,7 @@ from selenium.common.exceptions import NoSuchElementException from tests import emojis from time import sleep from views.base_element import Button, EditBox, Text, BaseElement, SilentButton -from views.base_view import BaseView, ProgressBar +from views.base_view import BaseView from views.profile_view import ProfilePictureElement @@ -144,9 +144,6 @@ class ChatElementByText(Text): return TimeStampText(self.driver, self.locator) - @property - def progress_bar(self): - return ProgressBar(self.driver, self.locator) @property def member_photo(self): @@ -169,6 +166,14 @@ class ChatElementByText(Text): xpath="//android.view.ViewGroup//android.widget.TextView[contains(@text,'%s')]" % text) return element.is_element_displayed(wait_time) + @property + def uncollapse(self) -> bool: + class Collapse(Button): + def __init__(self, driver, parent_locator: str): + super().__init__(driver, prefix=parent_locator, xpath="/../../..//android.widget.ImageView[@content-desc='icon']") + + return Collapse(self.driver, self.locator).is_element_displayed() + @property def status(self) -> str: sent = Text(self.driver, prefix=self.locator, xpath="//*[@content-desc='sent']") @@ -264,12 +269,12 @@ class GroupChatInfoView(BaseView): class PreviewMessage(ChatElementByText): def __init__(self, driver, text:str): super().__init__(driver, text=text) - self.locator+="/android.view.ViewGroup/android.view.ViewGroup/" + self.locator+="/android.view.ViewGroup/android.view.ViewGroup" @staticmethod def return_element_or_empty(obj): try: - return obj.find_element() + return obj.scroll_to_element() except NoSuchElementException: return '' @@ -277,21 +282,21 @@ class PreviewMessage(ChatElementByText): def preview_image(self): class PreviewImage(SilentButton): def __init__(self, driver, parent_locator: str): - super().__init__(driver, prefix=parent_locator, xpath="android.widget.ImageView") + super().__init__(driver, prefix=parent_locator, xpath="/android.widget.ImageView") return PreviewMessage.return_element_or_empty(PreviewImage(self.driver, self.locator)) @property def preview_title(self): class PreviewTitle(SilentButton): def __init__(self, driver, parent_locator: str): - super().__init__(driver, prefix=parent_locator, xpath="android.widget.TextView[1]") + super().__init__(driver, prefix=parent_locator, xpath="/android.widget.TextView[1]") return PreviewMessage.return_element_or_empty(PreviewTitle(self.driver, self.locator)) @property def preview_subtitle(self): class PreviewSubTitle(SilentButton): def __init__(self, driver, parent_locator: str): - super().__init__(driver, prefix=parent_locator, xpath="android.widget.TextView[2]") + super().__init__(driver, prefix=parent_locator, xpath="/android.widget.TextView[2]") return PreviewMessage.return_element_or_empty(PreviewSubTitle(self.driver, self.locator)) @@ -406,6 +411,9 @@ class ChatView(BaseView): self.send_command = SendCommand(self.driver) self.request_command = RequestCommand(self.driver) + # General chat view + self.history_start_icon = Button(self.driver, accessibility_id="history-chat") + #Stickers self.show_stickers_button = Button(self.driver, accessibility_id="show-stickers-icon") self.get_stickers = Button(self.driver, translation_id="get-stickers") @@ -641,6 +649,17 @@ class ChatView(BaseView): element.click() element.wait_for_invisibility_of_element() + def scroll_to_start_of_history(self, depth=20): + self.driver.info('*Scrolling *') + for _ in range(depth): + try: + return self.history_start_icon.find_element() + except NoSuchElementException: + size = self.driver.get_window_size() + self.driver.swipe(500, size["height"] * 0.1, 500, size["height"] * 0.8) + else: + raise Exception('Start of chat history is not reached!') + def user_profile_image_in_mentions_list(self, username): return Button(self.driver, xpath="//*[@content-desc='suggestions-list']//*[@text='%s']/" "..//*[@content-desc='member-photo']" % username) diff --git a/test/appium/views/home_view.py b/test/appium/views/home_view.py index c89fa5a954..1cbe019607 100644 --- a/test/appium/views/home_view.py +++ b/test/appium/views/home_view.py @@ -47,6 +47,14 @@ class ChatElement(SilentButton): return UnreadMessagesCountText(self.driver, self.locator) + @property + def chat_preview(self): + class PreveiewMessageText(Text): + def __init__(self, driver, parent_locator: str): + super().__init__(driver, xpath="%s//*[@content-desc='chat-message-text']" % parent_locator) + + return PreveiewMessageText(self.driver, self.locator).text + @property def new_messages_public_chat(self): class UnreadMessagesPublicChat(BaseElement): diff --git a/test/appium/views/sign_in_view.py b/test/appium/views/sign_in_view.py index 73d9f29184..506e6b164a 100644 --- a/test/appium/views/sign_in_view.py +++ b/test/appium/views/sign_in_view.py @@ -1,7 +1,7 @@ from appium.webdriver.common.touch_action import TouchAction from selenium.common.exceptions import NoSuchElementException - -from tests import common_password +import os +from tests import common_password, appium_root_project_path, app_path from views.base_element import Button, EditBox, Text from views.base_view import BaseView @@ -234,3 +234,23 @@ class SignInView(BaseView): self.driver.info("**Open weblink %s**" % url_weblink) self.open_universal_web_link(url_weblink) self.sign_in() + + def import_db(self, user, import_db_folder_name): + self.just_fyi('**Importing database**') + import_file_name = 'export.db' + home = self.recover_access(user['passphrase']) + profile = home.profile_button.click() + full_path_to_file = os.path.join(appium_root_project_path, 'views/upgrade_dbs/%s/%s' % + (import_db_folder_name, import_file_name)) + profile.logout() + self.multi_account_on_login_button.wait_for_visibility_of_element(30) + self.get_multiaccount_by_position(1).click() + self.password_input.set_value(common_password) + self.driver.push_file(source_path=full_path_to_file, destination_path=app_path + import_file_name) + self.options_button.click() + self.element_by_text('Import unencrypted').click() + self.element_by_text('Import unencrypted').wait_for_invisibility_of_element(40) + self.sign_in_button.click() + self.home_button.wait_for_element(40) + self.just_fyi('**Importing database is finished!**') + return self.get_home_view() diff --git a/test/appium/views/upgrade_dbs/chats/data.py b/test/appium/views/upgrade_dbs/chats/data.py new file mode 100644 index 0000000000..96d1436268 --- /dev/null +++ b/test/appium/views/upgrade_dbs/chats/data.py @@ -0,0 +1,51 @@ +chats = { + 'All Whopping Dassierat': { + 'preview': 'unread 1-1', + 'unread' : '1', + 'messages': { + 'pic with descr', + 'unread 1-1' + } + }, + '#before-upgrade':{ + 'preview': 'one more new', + 'preview_messages':{ + 'status_im': {'txt':'1) https://our.status.im/tag/news-and-announcements/', + 'title': 'News & Announcements - Our Status', + 'subtitle':'Our Status'}, + 'youtu.be': {'txt':'short youtu.be https://youtu.be/LesnixX76YY', + 'title':'Short URLs or Branded Links?', + 'subtitle': 'YouTube'}, + 'youtube': {'txt': '2. YOTUBE full https://www.youtube.com/watch?v=5sd7gJTnFRM', + 'title': 'Animal ДжаZ — Чувства', + 'subtitle': 'YouTube'}, + 'gph.is': {'txt':'4. short vertical gif https://gph.is/2jG1Xjj'}, + 'giphy.com': {'txt':'5. long landscape gif https://giphy.com/gifs/thegoodplace-season-1-episode-11-3oxHQoD2rep6XGbDDa'}, + 'media.giphy': {'txt':'6. media gif https://media.giphy.com/media/iFxXouCf76ZencqIRP/giphy.gif'}, + 'github': {'txt': '7. github. com https://github.com/status-im/status-react/ ', + 'title': 'status-im/status-react', + 'subtitle': 'GitHub'} + }, + 'quoted_text_messages': { + 'MARKDOWN\ninline code\nbold text in asterics\nbold text in underscores\nitalic text in asteric\nitalic text in underscore', + 'code blocks\n8\n9\n0', + 'quoted 1\n2\n3\n4' + }, + 'messages':{'long': 'Папирус (др.-греч. πάπῡρος, лат. papyrus), или би́блиос (др.-греч. βιβλίος), также ха́рта', + 'tag': '#what-is-going-on', + 'reply': 'reply', + 'mention': 'All Whopping Dassierat be my friend'}, + 'first_timastamp': 'Mar 25, 2021' + }, + 'Thoughtful Stupendous Graywolf': { + 'preview':'hey Thoughtful Stupendous Graywolf !', + 'messages':{ + + }, + + + }, + 'Royal Defensive Solenodon': { + 'preview':'Request address for transaction accepted', + } +} \ No newline at end of file diff --git a/test/appium/views/upgrade_dbs/chats/export.db b/test/appium/views/upgrade_dbs/chats/export.db new file mode 100644 index 0000000000..2a0615dd24 Binary files /dev/null and b/test/appium/views/upgrade_dbs/chats/export.db differ