diff --git a/test/appium/tests/base_test_case.py b/test/appium/tests/base_test_case.py index d98ff057c8..1cfe75f93d 100644 --- a/test/appium/tests/base_test_case.py +++ b/test/appium/tests/base_test_case.py @@ -1,11 +1,11 @@ import asyncio import base64 import logging +import re import subprocess import sys from abc import ABCMeta, abstractmethod from http.client import RemoteDisconnected -import re import pytest import requests @@ -15,12 +15,13 @@ from sauceclient import SauceException from selenium.common.exceptions import NoSuchElementException from selenium.common.exceptions import WebDriverException from selenium.webdriver.support.wait import WebDriverWait +from urllib3.exceptions import MaxRetryError -from tests.conftest import option, sauce_username, sauce_access_key, apibase from support.api.network_api import NetworkApi from support.github_report import GithubHtmlReport from tests import test_suite_data, start_threads, appium_container, pytest_config_global from tests import transl +from tests.conftest import sauce_username, sauce_access_key, apibase executor_sauce_lab = 'https://%s:%s@ondemand.%s:443/wd/hub' % (sauce_username, sauce_access_key, apibase) @@ -293,20 +294,24 @@ def create_shared_drivers(quantity): driver.implicitly_wait(implicit_wait) drivers[i] = driver loop = None + return drivers, loop else: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) capabilities = {'maxDuration': 3600} print('SC Executor: %s' % executor_sauce_lab) - drivers = loop.run_until_complete(start_threads(quantity, + try: + drivers = loop.run_until_complete(start_threads(quantity, Driver, drivers, executor_sauce_lab, update_capabilities_sauce_lab(capabilities))) - for i in range(quantity): - test_suite_data.current_test.testruns[-1].jobs[drivers[i].session_id] = i + 1 - drivers[i].implicitly_wait(implicit_wait) - return drivers, loop + for i in range(quantity): + test_suite_data.current_test.testruns[-1].jobs[drivers[i].session_id] = i + 1 + drivers[i].implicitly_wait(implicit_wait) + return drivers, loop + except MaxRetryError as e: + test_suite_data.current_test.testruns[-1].error = e.reason class LocalSharedMultipleDeviceTestCase(AbstractTestCase): @@ -345,6 +350,8 @@ class LocalSharedMultipleDeviceTestCase(AbstractTestCase): class SauceSharedMultipleDeviceTestCase(AbstractTestCase): def setup_method(self, method): + if not self.drivers: + pytest.fail(test_suite_data.current_test.testruns[-1].error) for _, driver in self.drivers.items(): driver.execute_script("sauce:context=Started %s" % method.__name__) jobs = test_suite_data.current_test.testruns[-1].jobs diff --git a/test/appium/tests/critical/test_public_chat_browsing.py b/test/appium/tests/critical/test_public_chat_browsing.py index b05021d03d..46b3fad012 100644 --- a/test/appium/tests/critical/test_public_chat_browsing.py +++ b/test/appium/tests/critical/test_public_chat_browsing.py @@ -361,6 +361,7 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase): self.public_key_1, self.default_username_1 = self.home_1.get_public_key_and_username(return_username=True) self.public_key_2, self.default_username_2 = self.home_2.get_public_key_and_username(return_username=True) self.profile_1 = self.home_1.get_profile_view() + self.profile_1.switch_push_notifications() [home.click_system_back_button_until_element_is_shown() for home in (self.home_1, self.home_2)] [home.chats_tab.click() for home in (self.home_1, self.home_2)] self.home_1.add_contact(self.public_key_2) @@ -639,6 +640,73 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase): # 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) + def test_community_mentions_push_notification(self): + self.home_1.click_system_back_button_until_element_is_shown() + if not self.channel_2.chat_message_input.is_element_displayed(): + self.channel_2.click_system_back_button_until_element_is_shown() + self.home_2.communities_tab.click() + self.home_2.get_chat(self.community_name, community=True).click() + self.community_2.get_channel(self.channel_name).click() + + self.device_2.just_fyi("Invited member sends a message with a mention") + self.channel_2.send_message("hi") + self.channel_2.mention_user(self.default_username_1) + self.channel_2.send_message_button.click() + + self.device_1.just_fyi("Admin gets push notification with the mention and tap it") + self.device_1.open_notification_bar() + if self.home_1.get_pn(self.default_username_1): + self.device_1.click_upon_push_notification_by_text(self.default_username_1) + if not self.channel_1.chat_element_by_text(self.default_username_1).is_element_displayed(): + 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") + else: + self.errors.append("Push notification with the mention was not received by admin") + + # ToDo: this part is skipped because of an issue - sent messages stuck without any status for a long time + # and can not be edited during that time + # self.device_2.just_fyi("Sender edits the message with a mention") + # self.channel_2.chat_element_by_text(self.default_username_1).long_press_element_by_coordinate(rel_y=0) + # try: + # self.channel_2.element_by_translation_id("edit-message").click() + # for i in range(29, 32): + # self.channel_2.driver.press_keycode(i) + # self.channel_2.send_message_button.click() + # edited_message = self.default_username_1 + " abc" + # if not self.channel_2.chat_element_by_text(edited_message).is_element_displayed(): + # self.errors.append("Edited message is not shown correctly for the sender") + # if not self.channel_1.chat_element_by_text(edited_message).is_element_displayed(): + # self.errors.append("Edited message is not shown correctly for the (receiver) admin") + # except NoSuchElementException: + # self.errors.append("Can not edit a message with a mention") + + # ToDo: enable when https://github.com/status-im/status-mobile/issues/14956 is fixed + # self.home_2.click_system_back_button_until_element_is_shown() + # if not self.channel_1.chat_message_input.is_element_displayed(): + # self.channel_1.click_system_back_button_until_element_is_shown() + # self.home_1.communities_tab.click() + # self.home_1.get_chat(self.community_name, community=True).click() + # self.community_1.get_channel(self.channel_name).click() + # + # self.device_1.just_fyi("Admin sends a message with a mention") + # self.channel_1.mention_user(self.default_username_2) + # self.channel_1.send_message_button.click() + # self.device_2.just_fyi("Invited member gets push notification with the mention and tap it") + # self.device_2.open_notification_bar() + # if not self.home_2.get_pn(self.default_username_2): + # self.device_2.driver.fail("Push notification with the mention was not received by the invited member") + # self.device_2.click_upon_push_notification_by_text(self.default_username_2) + # if not self.channel_2.chat_element_by_text(self.default_username_2).is_element_displayed(): + # if self.channel_2.chat_message_input.is_element_displayed(): + # self.device_2.driver.fail("Message with the mention is not shown in the chat for the invited member") + # else: + # self.device_2.driver.fail( + # "Channel did not open by clicking on a notification with the mention for the invited member") + self.errors.verify_no_errors() + @marks.testrail_id(702845) def test_community_leave(self): self.home_2.jump_to_communities_home() diff --git a/test/appium/views/base_element.py b/test/appium/views/base_element.py index 3ea04ff018..b966afbb6d 100644 --- a/test/appium/views/base_element.py +++ b/test/appium/views/base_element.py @@ -1,18 +1,19 @@ import base64 -from io import BytesIO import os import time -import emoji +from io import BytesIO from timeit import timeit +import emoji +import imagehash from PIL import Image, ImageChops, ImageStat from appium.webdriver.common.mobileby import MobileBy from appium.webdriver.common.touch_action import TouchAction from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException from selenium.common.exceptions import TimeoutException -from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions -import imagehash +from selenium.webdriver.support.wait import WebDriverWait + from tests import transl @@ -289,6 +290,15 @@ class BaseElement(object): if expected_element.is_element_displayed(): return + def long_press_element_by_coordinate(self, rel_x=0.8, rel_y=0.8): + element = self.find_element() + location = element.location + size = element.size + x = int(location['x'] + size['width'] * rel_x) + y = int(location['y'] + size['height'] * rel_y) + action = TouchAction(self.driver) + action.long_press(x=x, y=y).release().perform() + def measure_time_before_element_appears(self, max_wait_time=30): def wrapper(): return self.wait_for_visibility_of_element(max_wait_time) diff --git a/test/appium/views/chat_view.py b/test/appium/views/chat_view.py index e2f198b02c..f8f4e327f9 100644 --- a/test/appium/views/chat_view.py +++ b/test/appium/views/chat_view.py @@ -4,6 +4,7 @@ from datetime import datetime, timedelta from time import sleep import dateutil.parser +from appium.webdriver.common.mobileby import MobileBy from appium.webdriver.common.touch_action import TouchAction from selenium.common.exceptions import NoSuchElementException, TimeoutException @@ -404,13 +405,15 @@ class CommunityView(HomeView): self.close_button.click() def send_invite_to_community(self, user_names_to_invite): + if isinstance(user_names_to_invite, str): + user_names_to_invite = [user_names_to_invite] self.driver.info("Send %s invite to community" % ', '.join(map(str, user_names_to_invite))) self.community_options_button.click() self.community_info_button.click() self.invite_button.click() - user_contact = self.element_by_text_part(user_names_to_invite) - user_contact.scroll_to_element() - user_contact.click() + for user_name in user_names_to_invite: + user_contact = self.element_by_text_part(user_name) + user_contact.scroll_and_click() self.share_invite_button.click_until_presence_of_element(self.invite_button) self.back_button.click_until_presence_of_element(self.plus_button) @@ -640,6 +643,12 @@ class ChatMessageInput(EditBox): action.long_press(x=x + 250, y=y).release().perform() # long press action.tap(x=x + 50, y=y - 50).release().perform() # tap Paste + def click_inside(self): + action = TouchAction(self.driver) + location = self.find_element().location + x, y = location['x'], location['y'] + action.tap(x=x + 250, y=y).release().perform() + class ChatView(BaseView): def __init__(self, driver): @@ -778,6 +787,7 @@ class ChatView(BaseView): self.set_community_image_button = Button(self.driver, translation_id='community-thumbnail-image', suffix='/following-sibling::android.view.ViewGroup') self.confirm_create_in_community_button = Button(self.driver, translation_id="create") + self.mentions_list = BaseElement(self.driver, accessibility_id="mentions-list") # New UI self.pinned_messages_count = Button(self.driver, @@ -1091,11 +1101,25 @@ class ChatView(BaseView): return transaction_message def get_community_by_name(self, community_name: str): - community_button = Button(self.driver, - xpath="//*[@content-desc='community-name-text'][starts-with(@text,'%s')]/.." % community_name) + community_button = Button( + self.driver, + xpath="//*[@content-desc='community-name-text'][starts-with(@text,'%s')]/.." % community_name + ) community_button.click() return CommunityView(self.driver) + def mention_user(self, user_name: str): + self.driver.info("Mention user %s in the chat" % user_name) + gboard = self.driver.available_ime_engines[0] + self.driver.activate_ime_engine(gboard) # workaround to get mentions list expanded + self.chat_message_input.click_inside() + self.chat_message_input.send_keys("@") + try: + mentions_list = self.mentions_list.wait_for_element() + mentions_list.find_element(MobileBy.XPATH, "//*[@text='%s']" % user_name).click() + except TimeoutException: + self.driver.fail("Mentions list is not shown") + @staticmethod def get_resolved_chat_key(username, chat_key): return '%s • %s…%s' % (username, chat_key[:6], chat_key[-4:])