diff --git a/test/appium/support/testrail_report.py b/test/appium/support/testrail_report.py index 7a424e64d1..f10a38d690 100644 --- a/test/appium/support/testrail_report.py +++ b/test/appium/support/testrail_report.py @@ -210,6 +210,7 @@ class TestrailReport(BaseTestReport): 'status_id': self.outcomes['undefined_fail'] if last_testrun.error else self.outcomes['passed'], 'comment': comment}) + print("RESULTS:\n%s" % "\n".join(str(i) for i in data)) results = self.post('add_results_for_cases/%s' % self.run_id, data={"results": data}) try: results[0] diff --git a/test/appium/tests/base_test_case.py b/test/appium/tests/base_test_case.py index 1cfe75f93d..ff14de93b4 100644 --- a/test/appium/tests/base_test_case.py +++ b/test/appium/tests/base_test_case.py @@ -312,6 +312,7 @@ def create_shared_drivers(quantity): return drivers, loop except MaxRetryError as e: test_suite_data.current_test.testruns[-1].error = e.reason + raise e class LocalSharedMultipleDeviceTestCase(AbstractTestCase): @@ -371,11 +372,14 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase): '%s_geth%s.log' % (test_suite_data.current_test.name, str(self.drivers[driver].number))) geth_contents.append(self.pull_geth(self.drivers[driver])) - except (WebDriverException, AttributeError): + except (WebDriverException, AttributeError, RemoteDisconnected): pass finally: - geth = {geth_names[i]: geth_contents[i] for i in range(len(geth_names))} - test_suite_data.current_test.geth_paths = self.github_report.save_geth(geth) + try: + geth = {geth_names[i]: geth_contents[i] for i in range(len(geth_names))} + test_suite_data.current_test.geth_paths = self.github_report.save_geth(geth) + except IndexError: + pass @pytest.fixture(scope='class', autouse=True) def prepare(self, request): @@ -390,28 +394,30 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase): from tests.conftest import sauce requests_session = requests.Session() requests_session.auth = (sauce_username, sauce_access_key) - for _, driver in cls.drivers.items(): - session_id = driver.session_id - try: - sauce.jobs.update_job(username=sauce_username, job_id=session_id, name=cls.__name__) - except (RemoteDisconnected, SauceException): - pass - try: - driver.quit() - except WebDriverException: - pass - url = 'https://api.%s/rest/v1/%s/jobs/%s/assets/%s' % (apibase, sauce_username, session_id, "log.json") - WebDriverWait(driver, 60, 2).until(lambda _: requests_session.get(url).status_code == 200) - commands = requests_session.get(url).json() - for command in commands: + if cls.drivers: + for _, driver in cls.drivers.items(): + session_id = driver.session_id try: - if command['message'].startswith("Started "): - for test in test_suite_data.tests: - if command['message'] == "Started %s" % test.name: - test.testruns[-1].first_commands[session_id] = commands.index(command) + 1 - except KeyError: - continue - cls.loop.close() + sauce.jobs.update_job(username=sauce_username, job_id=session_id, name=cls.__name__) + except (RemoteDisconnected, SauceException): + pass + try: + driver.quit() + except WebDriverException: + pass + url = 'https://api.%s/rest/v1/%s/jobs/%s/assets/%s' % (apibase, sauce_username, session_id, "log.json") + WebDriverWait(driver, 60, 2).until(lambda _: requests_session.get(url).status_code == 200) + commands = requests_session.get(url).json() + for command in commands: + try: + if command['message'].startswith("Started "): + for test in test_suite_data.tests: + if command['message'] == "Started %s" % test.name: + test.testruns[-1].first_commands[session_id] = commands.index(command) + 1 + except KeyError: + continue + if cls.loop: + cls.loop.close() for test in test_suite_data.tests: cls.github_report.save_test(test) diff --git a/test/appium/tests/critical/chats/test_1_1_public_chats.py b/test/appium/tests/critical/chats/test_1_1_public_chats.py index 2815e3b0a0..d394606dbe 100644 --- a/test/appium/tests/critical/chats/test_1_1_public_chats.py +++ b/test/appium/tests/critical/chats/test_1_1_public_chats.py @@ -3,7 +3,7 @@ import time import emoji import pytest -from selenium.common.exceptions import TimeoutException +from selenium.common.exceptions import TimeoutException, NoSuchElementException from tests import marks, common_password, run_in_parallel from tests.base_test_case import MultipleSharedDeviceTestCase, create_shared_drivers @@ -453,7 +453,6 @@ class TestContactBlockMigrateKeycardMultipleSharedDevices(MultipleSharedDeviceTe self.errors.append('Contact is shown in Profile after removing user from contacts') self.errors.verify_no_errors() - @marks.testrail_id(702188) @marks.xfail( reason="flaky; issue when sometimes history is not fetched from offline for public chat, needs investigation") @@ -840,7 +839,7 @@ class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase): 'username': self.username_2})))) self.home_1, self.home_2 = self.device_1.get_home_view(), self.device_2.get_home_view() self.homes = (self.home_1, self.home_2) - self.profile_1, self.profile_2 = (home.get_profile_view() for home in self.homes) + self.profile_1, self.profile_2 = (home.get_profile_view() for home in self.homes) self.public_key_2 = self.home_2.get_public_key() self.profile_1.just_fyi("Sending contact request via Profile > Contacts") @@ -927,6 +926,7 @@ class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase): self.home_2.just_fyi("Check 'Open in Status' option") url_message = 'http://status.im' self.chat_1.send_message(url_message) + self.chat_2.element_starts_with_text(url_message, 'button').wait_for_visibility_of_element(120) self.chat_2.element_starts_with_text(url_message, 'button').click_inside_element_by_coordinate(0.2, 0.5) web_view = self.chat_2.open_in_status_button.click() if not web_view.element_by_text('Private, Secure Communication').is_element_displayed(60): @@ -934,6 +934,7 @@ class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase): self.errors.verify_no_errors() + @marks.xfail(reason="Pin feature is in development", run=False) @marks.testrail_id(702731) def test_1_1_chat_pin_messages(self): self.home_1.just_fyi("Check that Device1 can pin own message in 1-1 chat") @@ -1034,19 +1035,23 @@ class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase): self.chat_2.just_fyi("Send messages with non-latin symbols") self.home_1.jump_to_card_by_text(self.username_2) + self.chat_1.send_message("just a text") # Sending a message here so the next ones will be in a separate line messages = ['hello', '¿Cómo estás tu año?', 'ё, доброго вечерочка', '® æ ç ♥'] [self.chat_2.send_message(message) for message in messages] for message in messages: if not self.chat_1.chat_element_by_text(message).is_element_displayed(): - self.errors.append("Message with test '%s' was not received" % message) + self.errors.append("Message with text '%s' was not received" % message) self.chat_2.just_fyi("Checking updated member photo, timestamp and username on message") self.chat_2.hide_keyboard_if_shown() - timestamp = self.chat_2.chat_element_by_text(messages[0]).timestamp - sent_time_variants = self.chat_2.convert_device_time_to_chat_timestamp() - if timestamp not in sent_time_variants: - self.errors.append( - 'Timestamp on message %s does not correspond expected [%s]' % (timestamp, *sent_time_variants)) + try: + timestamp = self.chat_2.chat_element_by_text(messages[0]).timestamp + sent_time_variants = self.chat_2.convert_device_time_to_chat_timestamp() + if timestamp not in sent_time_variants: + self.errors.append( + 'Timestamp on message %s does not correspond expected [%s]' % (timestamp, *sent_time_variants)) + except NoSuchElementException: + self.errors.append("No timestamp on message %s" % messages[0]) for message in [messages[1], messages[2]]: if self.chat_2.chat_element_by_text(message).member_photo.is_element_displayed(): self.errors.append('%s is not stack to 1st(they are sent in less than 5 minutes)!' % message) @@ -1187,6 +1192,7 @@ class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase): [device.click_system_back_button_until_element_is_shown() for device in (self.device_1, self.device_2)] self.errors.verify_no_errors() + @marks.xfail(reason="Issue with messages not being sent for a long time") @marks.testrail_id(702783) def test_1_1_chat_is_shown_message_sent_delivered_from_offline(self): self.chat_2.jump_to_card_by_text(self.username_1) diff --git a/test/appium/tests/critical/chats/test_group_chat.py b/test/appium/tests/critical/chats/test_group_chat.py index 2241e66826..b4c7654503 100644 --- a/test/appium/tests/critical/chats/test_group_chat.py +++ b/test/appium/tests/critical/chats/test_group_chat.py @@ -257,6 +257,7 @@ class TestGroupChatMultipleDeviceMergedNewUI(MultipleSharedDeviceTestCase): self.errors.append('%s if not shown for device %s' % (message, str(i))) self.errors.verify_no_errors() + @marks.xfail(reason="Pin feature is in development", run=False) @marks.testrail_id(702732) def test_group_chat_pin_messages(self): [self.homes[i].click_system_back_button_until_element_is_shown() for i in range(3)] diff --git a/test/appium/tests/critical/test_public_chat_browsing.py b/test/appium/tests/critical/test_public_chat_browsing.py index 83ca395a3e..0fc53076bd 100644 --- a/test/appium/tests/critical/test_public_chat_browsing.py +++ b/test/appium/tests/critical/test_public_chat_browsing.py @@ -4,13 +4,13 @@ from datetime import timedelta import emoji import pytest from dateutil import parser -from selenium.common.exceptions import NoSuchElementException +from selenium.common.exceptions import NoSuchElementException, TimeoutException -from tests import marks, test_dapp_name, test_dapp_url, run_in_parallel, common_password +from tests import marks, test_dapp_name, test_dapp_url, run_in_parallel from tests.base_test_case import create_shared_drivers, MultipleSharedDeviceTestCase from views.chat_view import CommunityView -from views.sign_in_view import SignInView from views.dbs.waku_backup import user as waku_user +from views.sign_in_view import SignInView @pytest.mark.xdist_group(name="three_1") @@ -342,7 +342,8 @@ class TestCommunityOneDeviceMerged(MultipleSharedDeviceTestCase): self.channel.copy_message_text(message) actual_copied_text = self.channel.driver.get_clipboard_text() if actual_copied_text != message: - self.errors.append('Message %s text was not copied in community channel, text in clipboard %s' % actual_copied_text) + self.errors.append( + 'Message %s text was not copied in community channel, text in clipboard %s' % actual_copied_text) self.errors.verify_no_errors() @@ -443,7 +444,6 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase): self.channel_2 = self.community_2.get_channel(self.channel_name).click() @marks.testrail_id(702838) - @marks.xfail(reason="blocked by 14797") def test_community_message_send_check_timestamps_sender_username(self): message = self.text_message sent_time_variants = self.channel_1.convert_device_time_to_chat_timestamp() @@ -499,13 +499,12 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase): self.home_1.just_fyi('Send image in 1-1 chat from Gallery') image_description = 'description' self.channel_1.send_images_with_description(image_description) - # TODO: possible after adding proper accessibility-id to 1 image in chat - # self.channel_1.chat_message_input.click() - # self.channel_1.chat_element_by_text(image_description).image_in_message.click() - # self.channel_1.click_system_back_button() + self.channel_1.chat_message_input.click() + self.channel_1.chat_element_by_text(image_description).image_in_message.click() + self.channel_1.click_system_back_button() # TODO: options for image are still WIP; add case with edit description of image and after 15901 fix - # self.home_2.just_fyi('check image, description and options for receiver') + self.home_2.just_fyi('check image, description and options for receiver') # self.channel_2.chat_element_by_text(image_description).image_in_message.click() # self.home_1.just_fyi('save image') # self.chat_1.save_image_button.click_until_presence_of_element(self.chat_1.show_images_button) @@ -531,6 +530,10 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase): # # self.channel_2.chat_element_by_text(image_description).image_in_message.save_new_screenshot_of_element('images_test.png') + if not self.channel_2.chat_element_by_text( + image_description).image_in_message.is_element_image_similar_to_template('image_sent_in_community.png'): + self.errors.append("Not expected image is shown to the receiver") + self.channel_2.just_fyi("Can reply to images") self.channel_2.quote_message(image_description) message_text = 'reply to image' @@ -551,7 +554,8 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase): self.channel_2.just_fyi("Check gallery on second device") self.channel_2.jump_to_communities_home() self.home_2.get_to_community_channel_from_home(self.community_name) - if self.channel_2.chat_element_by_text(image_description).image_container_in_message.is_element_differs_from_template(file_name, 5): + if self.channel_2.chat_element_by_text( + image_description).image_container_in_message.is_element_differs_from_template(file_name, 5): self.errors.append("Gallery message do not match the template!") self.channel_2.just_fyi("Can reply to gallery") @@ -593,67 +597,66 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase): @marks.testrail_id(702844) def test_community_links_with_previews_github_youtube_twitter_gif_send_enable(self): preview_urls = { - # TODO: disabled because of the bug in 15891 - # 'giphy':{'url': 'https://giphy.com/gifs/this-is-fine-QMHoU66sBXqqLqYvGO', - # 'title': 'This Is Fine GIF - Find & Share on GIPHY', - # 'description': 'Discover & share this Meme GIF with everyone you know. GIPHY is how you search, share, discover, and create GIFs.', - # 'link': 'giphy.com'}, - 'github_pr': {'url': 'https://github.com/status-im/status-mobile/pull/11707', - 'title': 'Update translations by jinhojang6 · Pull Request #11707 · status-im/status-mobile', - 'description': 'Update translation json files of 19 languages.', - 'link': 'github.com'}, - 'yotube_short': { - 'url': 'https://youtu.be/Je7yErjEVt4', - 'title': 'Status, your gateway to Ethereum', - 'description': 'Learn more at https://status.im. This video aims to provide an explanation ' - 'and brief preview of the utility that will be supported by the Status App - provid...', - 'link': 'youtu.be'}, - 'yotube_full': { - 'url': 'https://www.youtube.com/watch?v=XN-SVmuJH2g&list=PLbrz7IuP1hrgNtYe9g6YHwHO6F3OqNMao', - 'title': 'Status & Keycard – Hardware-Enforced Security', - 'description': 'With Status and Keycard, you can enable hardware enforced authorizations to ' - 'your Status account and transactions. Two-factor authentication to access your ac...', - 'link': 'www.youtube.com'}, - 'yotube_mobile': { - 'url': 'https://m.youtube.com/watch?v=Je7yErjEVt4', - 'title': 'Status, your gateway to Ethereum', - 'description': 'Learn more at https://status.im. This video aims to provide an explanation ' - 'and brief preview of the utility that will be supported by the Status App - provid...', - 'link': 'm.youtube.com', - }, + # TODO: disabled because of the bug in 15891 + # 'giphy':{'url': 'https://giphy.com/gifs/this-is-fine-QMHoU66sBXqqLqYvGO', + # 'title': 'This Is Fine GIF - Find & Share on GIPHY', + # 'description': 'Discover & share this Meme GIF with everyone you know. GIPHY is how you search, share, discover, and create GIFs.', + # 'link': 'giphy.com'}, + 'github_pr': {'url': 'https://github.com/status-im/status-mobile/pull/11707', + 'title': 'Update translations by jinhojang6 · Pull Request #11707 · status-im/status-mobile', + 'description': 'Update translation json files of 19 languages.', + 'link': 'github.com'}, + 'yotube_short': { + 'url': 'https://youtu.be/Je7yErjEVt4', + 'title': 'Status, your gateway to Ethereum', + 'description': 'Learn more at https://status.im. This video aims to provide an explanation ' + 'and brief preview of the utility that will be supported by the Status App - provid...', + 'link': 'youtu.be'}, + 'yotube_full': { + 'url': 'https://www.youtube.com/watch?v=XN-SVmuJH2g&list=PLbrz7IuP1hrgNtYe9g6YHwHO6F3OqNMao', + 'title': 'Status & Keycard – Hardware-Enforced Security', + 'description': 'With Status and Keycard, you can enable hardware enforced authorizations to ' + 'your Status account and transactions. Two-factor authentication to access your ac...', + 'link': 'www.youtube.com'}, + 'yotube_mobile': { + 'url': 'https://m.youtube.com/watch?v=Je7yErjEVt4', + 'title': 'Status, your gateway to Ethereum', + 'description': 'Learn more at https://status.im. This video aims to provide an explanation ' + 'and brief preview of the utility that will be supported by the Status App - provid...', + 'link': 'm.youtube.com', + }, - # twitter link is temporary removed from check as current xpath locator in message.preview_title is not applicable for this type of links - # 'twitter': { - # 'url': 'https://twitter.com/ethdotorg/status/1445161651771162627?s=20', - # 'txt': "We've rethought how we translate content, allowing us to translate", - # 'subtitle': 'Twitter' - # } - } + # twitter link is temporary removed from check as current xpath locator in message.preview_title is not applicable for this type of links + # 'twitter': { + # 'url': 'https://twitter.com/ethdotorg/status/1445161651771162627?s=20', + # 'txt': "We've rethought how we translate content, allowing us to translate", + # 'subtitle': 'Twitter' + # } + } - - for key in preview_urls: + for key, data in preview_urls.items(): self.home_2.just_fyi("Checking %s preview case" % key) - data = preview_urls[key] url = data['url'] self.channel_2.chat_message_input.set_value(url) self.channel_2.url_preview_composer.wait_for_element(20) - if self.channel_2.url_preview_composer_text.text != data['title']: - self.errors.append( - "Preview text is not expected, it is '%s'" % self.channel_2.url_preview_composer_text.text) + shown_title = self.channel_2.url_preview_composer_text.text + if shown_title != data['title']: + self.errors.append("Preview text is not expected, it is '%s'" % shown_title) self.channel_2.send_message_button.click() self.channel_1.get_preview_message_by_text(url).wait_for_element(60) message = self.channel_1.get_preview_message_by_text(url) # if not message.preview_image: # self.errors.append("No preview is shown for %s" % link_data['url']) - if message.preview_title.text != data['title']: - self.errors.append("Title is not equal expected for '%s', actual is '%s'" % (url, message.preview_title.text)) - - if message.preview_subtitle.text != data['description']: + shown_title = message.preview_title.text + if shown_title != data['title']: + self.errors.append("Title is not equal expected for '%s', actual is '%s'" % (url, shown_title)) + shown_description = message.preview_subtitle.text + if shown_description != data['description']: self.errors.append( - "Description is not equal expected for '%s', actual is '%s'" % (url, message.preview_subtitle.text)) - - if message.preview_link.text != data['link']: - self.errors.append("Link is not equal expected for '%s', actual is '%s'" % (url, message.preview_link.text)) + "Description is not equal expected for '%s', actual is '%s'" % (url, shown_description)) + shown_link = message.preview_link.text + if shown_link != data['link']: + self.errors.append("Link is not equal expected for '%s', actual is '%s'" % (url, shown_link)) self.errors.verify_no_errors() @@ -743,8 +746,14 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase): self.home_2.just_fyi("Check message in 1-1 chat after unblock") self.home_2.get_chat(self.username_1).click() self.chat_2.send_message(message_unblocked) - if not self.chat_1.chat_element_by_text(message_unblocked).is_element_displayed(30): - self.errors.append("Message was not received in 1-1 chat after user unblock!") + try: + self.chat_2.chat_element_by_text(message_unblocked).wait_for_status_to_be(expected_status='Delivered', + timeout=120) + if not self.chat_1.chat_element_by_text(message_unblocked).is_element_displayed(30): + self.errors.append("Message was not received in 1-1 chat after user unblock!") + except TimeoutException: + self.errors.append('Message was not delivered after back up online.') + self.errors.verify_no_errors() @marks.testrail_id(703086) @@ -759,13 +768,14 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase): community_1_element.long_press_until_element_is_shown(mark_as_read_button) mark_as_read_button.click() if community_1_element.new_messages_public_chat.is_element_displayed(): - self.errors.append('Unread messages badge is shown in community channel while there are no unread messages') - # TODO: there should be one more check for community channel, which is still not ready + self.errors.append( + 'Unread messages badge is shown in community channel while there are no unread messages') + # TODO: there should be one more check for community channel, which is still not ready - # self.community_1.click_system_back_button_until_element_is_shown() - # community_1_element = self.home_1.get_chat(self.community_name, community=True) - # if community_1_element.new_messages_community.is_element_displayed(): - # self.errors.append('New messages community badge is shown on community after marking messages as read') + # self.community_1.click_system_back_button_until_element_is_shown() + # community_1_element = self.home_1.get_chat(self.community_name, community=True) + # if community_1_element.new_messages_community.is_element_displayed(): + # self.errors.append('New messages community badge is shown on community after marking messages as read') self.errors.verify_no_errors() @marks.testrail_id(702786) @@ -790,7 +800,8 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase): if self.channel_1.chat_message_input.is_element_displayed(): self.errors.append("Message with the mention is not shown in the chat for the admin") else: - self.errors.append("Channel did not open by clicking on a notification with the mention for admin") + self.errors.append( + "Channel did not open by clicking on a notification with the mention for admin") else: self.errors.append("Push notification with the mention was not received by admin") diff --git a/test/appium/views/chat_view.py b/test/appium/views/chat_view.py index 528d8a9d5c..95e0316bcf 100644 --- a/test/appium/views/chat_view.py +++ b/test/appium/views/chat_view.py @@ -278,7 +278,7 @@ class ChatElementByText(Text): try: self.driver.info("Trying to access image inside message with text '%s'" % self.message_text) ChatElementByText(self.driver, self.message_text).wait_for_sent_state(60) - return Button(self.driver, xpath='%s//android.view.ViewGroup/android.widget.ImageView' % self.locator) + return Button(self.driver, xpath="%s//*[@content-desc='image-message']" % self.locator) except NoSuchElementException: self.driver.fail("No image is found in message!") @@ -996,10 +996,9 @@ class ChatView(BaseView): def set_reaction(self, message: str, emoji: str = 'thumbs-up', emoji_message=False): self.driver.info("Setting '%s' reaction" % emoji) - key = emojis[emoji] # Audio message is obvious should be tapped not on audio-scroll-line # so we tap on its below element as exception here (not the case for link/tag message!) - element = Button(self.driver, accessibility_id='emoji-picker-%s' % key) + element = Button(self.driver, accessibility_id='reaction-%s' % emoji) if message == 'audio': self.audio_message_in_chat_timer.long_press_element() else: diff --git a/test/appium/views/elements_templates/image_sent_in_community.png b/test/appium/views/elements_templates/image_sent_in_community.png new file mode 100644 index 0000000000..1146f987dc Binary files /dev/null and b/test/appium/views/elements_templates/image_sent_in_community.png differ