diff --git a/test/appium/requirements.txt b/test/appium/requirements.txt index 5d093f5210..2a55405bb5 100644 --- a/test/appium/requirements.txt +++ b/test/appium/requirements.txt @@ -1,56 +1,56 @@ +Appium-Python-Client==2.11.1 +Pillow==8.1.0 +PyGithub==1.55 +PyYAML==5.4 aiohttp==3.8.1 allpairspy==2.5.0 apipkg==1.5 -Appium-Python-Client==1.3.0 -PyGithub==1.55 async-timeout==4.0.1 -certifi==2020.11.8 +certifi==2023.7.22 chardet==3.0.4 cycler==0.10.0 cytoolz==0.12.0 +docker==4.4.0 emoji==0.5.0 +eth-account==0.7.0 eth-hash==0.3.2 eth-keys execnet==1.7.1 -future==0.18.2 flaky==3.7.0 +future==0.18.2 +hexbytes==0.2.2 idna==2.10 +imagehash +influxdb==5.3.1 kiwisolver==1.3.1 +lru-dict==1.1.7 lxml==4.6.5 matplotlib==3.3.3 multidict==5.0.2 namedlist==1.8 numpy==1.23.0 pbkdf2==1.3 -Pillow==8.1.0 -py==1.10.0 py-ecc==6.0.0 +py==1.10.0 pycryptodome==3.9.9 pyethash==0.1.27 pyparsing==2.4.7 pysha3==1.0.2 -pytest==7.2.1 pytest-forked==1.3.0 pytest-xdist==3.2.0 +pytest==7.2.1 python-dateutil==2.8.1 pytz==2020.4 -PyYAML==5.4 repoze.lru==0.7 -requests==2.25.1 +requests==2.31.0 rlp==3.0.0 sauceclient==1.0.0 +saucelab-api-client==0.6.2 scrypt==0.8.17 -selenium==3.14.1 +selenium==4.11.2 six==1.16.0 urllib3==1.26.12 -yarl==1.6.3 -docker==4.4.0 -influxdb==5.3.1 web3==6.0.0b5 -imagehash -hexbytes==0.2.2 -eth-account==0.7.0 -lru-dict==1.1.7 -websockets==10.3 websocket-client==1.3.2 -saucelab-api-client==0.6.2 \ No newline at end of file +websockets==10.3 +yarl==1.6.3 \ No newline at end of file diff --git a/test/appium/tests/base_test_case.py b/test/appium/tests/base_test_case.py index e7d2f652ed..36a068a37d 100644 --- a/test/appium/tests/base_test_case.py +++ b/test/appium/tests/base_test_case.py @@ -60,25 +60,35 @@ def add_local_devices_to_capabilities(): def get_capabilities_sauce_lab(): - desired_caps = dict() - desired_caps['app'] = 'sauce-storage:' + test_suite_data.apk_name + caps = dict() + caps['platformName'] = 'Android' + caps['idleTimeout'] = 1000 + caps['appium:app'] = 'sauce-storage:' + test_suite_data.apk_name + caps['appium:deviceName'] = 'Android GoogleAPI Emulator' + caps['appium:deviceOrientation'] = 'portrait' + caps['appium:platformVersion'] = '10.0' + caps['appium:automationName'] = 'UiAutomator2' + caps['appium:newCommandTimeout'] = 600 + caps['appium:idleTimeout'] = 1000 + caps['appium:unicodeKeyboard'] = True + caps['appium:automationName'] = 'UiAutomator2' + caps['appium:setWebContentDebuggingEnabled'] = True + caps['appium:ignoreUnimportantViews'] = False + caps['ignoreUnimportantViews'] = False + caps['appium:enableNotificationListener'] = True + caps['enableNotificationListener'] = True + caps['appium:enforceXPath1'] = True + caps['enforceXPath1'] = True + caps['sauce:options'] = dict() + caps['sauce:options']['appiumVersion'] = '2.0.0' + caps['sauce:options']['username'] = sauce_username + caps['sauce:options']['accessKey'] = sauce_access_key + caps['sauce:options']['build'] = pytest_config_global['build'] + caps['sauce:options']['name'] = test_suite_data.current_test.name + caps['sauce:options']['maxDuration'] = 3600 + caps['sauce:options']['idleTimeout'] = 1000 - desired_caps['build'] = pytest_config_global['build'] - desired_caps['name'] = test_suite_data.current_test.name - desired_caps['platformName'] = 'Android' - desired_caps['appiumVersion'] = '1.18.1' - desired_caps['platformVersion'] = '10.0' - desired_caps['deviceName'] = 'Android GoogleAPI Emulator' - desired_caps['deviceOrientation'] = "portrait" - desired_caps['commandTimeout'] = 600 - desired_caps['idleTimeout'] = 1000 - desired_caps['unicodeKeyboard'] = True - desired_caps['automationName'] = 'UiAutomator2' - desired_caps['setWebContentDebuggingEnabled'] = True - desired_caps['ignoreUnimportantViews'] = False - desired_caps['enableNotificationListener'] = True - desired_caps['maxDuration'] = 3600 - return desired_caps + return caps def update_capabilities_sauce_lab(new_capabilities: dict): diff --git a/test/appium/tests/medium/test_activity_center.py b/test/appium/tests/medium/test_activity_center.py index b68e9457f4..f52ac070c2 100644 --- a/test/appium/tests/medium/test_activity_center.py +++ b/test/appium/tests/medium/test_activity_center.py @@ -226,6 +226,8 @@ class TestActivityMultipleDevicePR(MultipleSharedDeviceTestCase): if not reply_element.unread_indicator.is_element_displayed(): self.errors.append("No unread dot is shown on activity center element!") + self.home_2.chats_tab.is_element_displayed() # just saving device 2 session from expiration + self.home_1.just_fyi("Swiping to 'Replies' on activity center and check unread there") self.home_1.mention_activity_tab_button.click() if reply_element.is_element_displayed(2): @@ -236,6 +238,8 @@ class TestActivityMultipleDevicePR(MultipleSharedDeviceTestCase): if not reply_element.is_element_displayed(): self.errors.append("Filter on replies tab is not working in Activity centre!") + self.home_2.chats_tab.is_element_displayed() # just saving device 2 session from expiration + self.home_1.just_fyi("Mark it as read and check filter") reply_element.swipe_right_on_element() self.home_1.activity_notification_swipe_button.click() @@ -245,6 +249,8 @@ class TestActivityMultipleDevicePR(MultipleSharedDeviceTestCase): if not reply_element.is_element_displayed(2): self.errors.append("Read filter is not displayed read message!") + self.home_2.chats_tab.is_element_displayed() # just saving device 2 session from expiration + self.home_1.just_fyi("Mark it as unread and check filter via right swipe") reply_element.swipe_right_on_element() self.home_1.activity_notification_swipe_button.click() @@ -260,6 +266,8 @@ class TestActivityMultipleDevicePR(MultipleSharedDeviceTestCase): if self.home_1.notifications_unread_badge.is_element_displayed(): self.errors.append("Notification was not marked as read after opening it in community channel!") + self.home_2.chats_tab.is_element_displayed() # just saving device 2 session from expiration + self.home_1.just_fyi("Delete it from unread via left swipe") self.home_1.open_activity_center_button.click() reply_element.swipe_left_on_element() @@ -323,6 +331,7 @@ class TestActivityMultipleDevicePR(MultipleSharedDeviceTestCase): self.home_2.clear_chat_long_press(self.username_1) [home.navigate_back_to_home_view() for home in (self.home_1, self.home_2)] + self.home_1.just_fyi("Open community to message") self.home_1.communities_tab.click() community_name = 'closed community' diff --git a/test/appium/views/base_element.py b/test/appium/views/base_element.py index 930ee709e5..6cf6e0fb06 100644 --- a/test/appium/views/base_element.py +++ b/test/appium/views/base_element.py @@ -9,8 +9,7 @@ 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.common.exceptions import NoSuchElementException, StaleElementReferenceException, TimeoutException from selenium.webdriver.support import expected_conditions from selenium.webdriver.support.wait import WebDriverWait @@ -81,8 +80,8 @@ class BaseElement(object): "Device %s: %s by %s: `%s` is not found on the screen" % ( self.driver.number, self.name, self.by, self.locator)) from None except Exception as exception: - if 'Internal Server Error' in str(exception): - continue + # if 'Internal Server Error' in str(exception): + raise exception def find_elements(self): return self.driver.find_elements(self.by, self.locator) @@ -150,22 +149,45 @@ class BaseElement(object): "Device %s: %s by %s: `%s` is still visible on the screen after %s seconds after wait_for_invisibility_of_element" % ( self.driver.number, self.name, self.by, self.locator, seconds)) from None + def wait_for_staleness_of_element(self, seconds=10): + try: + return WebDriverWait(self.driver, seconds).until(expected_conditions.staleness_of(self.find_element())) + except TimeoutException: + raise TimeoutException( + "Device %s: %s by %s: `%s` is not stale after %s seconds" % ( + self.driver.number, self.name, self.by, self.locator, seconds)) from None + + def wait_for_rendering_ended_and_click(self, attempts=3): + for i in range(attempts): + try: + self.click() + self.driver.info("Attempt %s is successful clicking %s" % (i, self.locator)) + return + except StaleElementReferenceException: + time.sleep(1) + raise StaleElementReferenceException( + msg="Device %s: continuous rendering, can't click an element by %s: %s" % ( + self.driver.number, self.by, self.locator)) + def wait_for_element_text(self, text, wait_time=30, message=None): - counter = 0 + if not isinstance(text, str): + text = str(text) self.driver.info("Wait for text element `%s` to be equal to `%s`" % (self.name, text)) - while True: - text_element = self.find_element().text - if isinstance(text, int): - text_element = int(text_element.strip()) - if counter >= wait_time: - self.driver.fail(message if message else "`%s` is not equal to expected `%s` in %s sec" % ( - text_element, text, wait_time)) - elif text_element != text: - counter += 10 - time.sleep(10) - else: + element_text = str() + counter = 0 + while counter < wait_time: + try: + element_text = self.find_element().text.strip() + except StaleElementReferenceException: + time.sleep(1) + element_text = self.find_element().text.strip() + if element_text == text: self.driver.info('Element %s text is equal to %s' % (self.name, text)) return + counter += 10 + time.sleep(10) + self.driver.fail(message if message else "`%s` is not equal to expected `%s` in %s sec" % ( + element_text, text, wait_time)) def scroll_to_element(self, depth: int = 9, direction='down'): self.driver.info('Scrolling %s to %s' % (direction, self.name)) diff --git a/test/appium/views/home_view.py b/test/appium/views/home_view.py index 759b16325a..dbf992d97e 100644 --- a/test/appium/views/home_view.py +++ b/test/appium/views/home_view.py @@ -149,13 +149,10 @@ class ActivityCenterElement(SilentButton): return Button(self.driver, xpath=self.locator + '//*[@content-desc="activity-message-body"]') def handle_cr(self, element_accessibility: str): - try: - accept_element = Button(self.driver, - xpath=self.locator + '/*[@content-desc="%s"]' % element_accessibility).find_element() - except NoSuchElementException: - return '' - if accept_element: - accept_element.click() + Button( + self.driver, + xpath=self.locator + '/*[@content-desc="%s"]' % element_accessibility + ).wait_for_rendering_ended_and_click() def accept_contact_request(self): self.handle_cr("accept-contact-request") @@ -383,7 +380,7 @@ class HomeView(BaseView): chat_element.cancel_contact_request() else: self.driver.fail("Illegal option for CR!") - self.close_activity_centre.click() + self.close_activity_centre.wait_for_rendering_ended_and_click() self.chats_tab.wait_for_visibility_of_element() def get_username_below_start_new_chat_button(self, username_part):