From 0fce3e60f521909af84527e9b9ae2ab81a9b815d Mon Sep 17 00:00:00 2001 From: Churikova Tetiana Date: Thu, 8 Jul 2021 10:32:08 +0200 Subject: [PATCH] e2e: communities Signed-off-by: Churikova Tetiana --- .../tests/atomic/chats/test_communities.py | 72 +++++++++++ .../tests/atomic/chats/test_group_chat.py | 1 - test/appium/views/chat_view.py | 122 ++++++++++++++++++ test/appium/views/home_view.py | 44 ++++++- test/appium/views/profile_view.py | 20 +-- 5 files changed, 243 insertions(+), 16 deletions(-) create mode 100644 test/appium/tests/atomic/chats/test_communities.py diff --git a/test/appium/tests/atomic/chats/test_communities.py b/test/appium/tests/atomic/chats/test_communities.py new file mode 100644 index 0000000000..a935b8e1df --- /dev/null +++ b/test/appium/tests/atomic/chats/test_communities.py @@ -0,0 +1,72 @@ +from tests import marks +from tests.base_test_case import MultipleDeviceTestCase +from views.sign_in_view import SignInView +from views.chat_view import CommunityView + +class TestCommunitiesMultipleDevices(MultipleDeviceTestCase): + + @marks.testrail_id(695842) + @marks.medium + def test_creating_community_accept_membership(self): + self.create_drivers(2) + home_1, home_2 = SignInView(self.drivers[0]).create_user(), SignInView(self.drivers[1]).create_user() + community_name, pub_chat_name, channel_name = "some name", home_1.get_random_chat_name(), "first_channel" + community_description, community_pic = "something in community", 'sauce_logo.png' + message, message_member = "message", "from member" + userkey_2, username_2 = home_2.get_public_key_and_username(return_username=True) + home_2.home_button.click() + community_1 = home_1.create_community(community_name, community_description, set_image=True, file_name=community_pic) + channel_1 = community_1.add_channel(channel_name) + channel_1.send_message(message) + home_1.home_button.double_click() + + home_1.just_fyi("Sending community link to public chat") + community_1 = home_1.get_chat(community_name, community=True).click() + community_link_text = community_1.copy_community_link() + pub_1 = home_1.join_public_chat(pub_chat_name) + pub_1.chat_message_input.paste_text_from_clipboard() + pub_1.send_message_button.click() + pub_1.get_back_to_home_view() + + home_2.just_fyi("Tapping on community link and request membership") + pub_2 = home_2.join_public_chat(pub_chat_name) + # TODO: due to #12271 + pub_2.element_by_text(community_name).wait_for_element(180) + community_message_2 = pub_2.get_community_link_preview_by_text(community_link_text) + if community_message_2.community_description != community_description: + self.errors.append("Community description '%s' does not match expected" % community_message_2.community_description) + if community_message_2.community_members_amount != 1: + self.errors.append("Members amount in resolved message '%s' does not match expected" % str(community_message_2.community_members_amount)) + community_message_2.view() + community_2 = CommunityView(self.drivers[1]) + community_2.request_access_button.click() + if not community_2.membership_request_pending_text.is_element_displayed(): + self.errors.append("Membership request is not pending") + + home_1.just_fyi("Checking pending membership") + community_1 = home_1.get_chat(community_name, community=True).click() + community_1.community_options_button.click() + community_1.community_info_button.click() + if community_1.community_membership_request_value.text != '1': + self.drivers[0].fail("Membership request value '%s' is not equal expected" % community_1.community_membership_request_value) + + home_1.just_fyi("Approve membership") + community_1.handle_membership_request(username_2, approve=True) + if not community_1.element_by_text(username_2).is_element_displayed(): + self.errors.append("New member %s is not shown as added to community on info page!" % username_2) + if not community_2.community_info_picture.is_element_image_similar_to_template(community_pic): + self.errors.append("Community image is different!") + channel_2 = community_2.get_chat(channel_name).click() + # TODO: due to 12281 + # if not channel_2.chat_element_by_text(message).is_element_displayed(): + # self.errors.append("Message was not received in community channel!") + channel_2.send_message(message_member) + community_1.home_button.double_click() + home_1.get_chat(community_name, community=True).click() + chat_element_1 = community_1.get_chat(channel_name) + if not chat_element_1.new_messages_public_chat.is_element_displayed(): + self.errors.append("Unread messages counter is not shown for community channel!") + if not community_1.element_by_text(message_member).is_element_displayed(): + self.errors.append("Message from member is not shown for community channel!") + + self.errors.verify_no_errors() diff --git a/test/appium/tests/atomic/chats/test_group_chat.py b/test/appium/tests/atomic/chats/test_group_chat.py index 1b33b9c5a3..3a95a418fe 100644 --- a/test/appium/tests/atomic/chats/test_group_chat.py +++ b/test/appium/tests/atomic/chats/test_group_chat.py @@ -2,7 +2,6 @@ from tests import marks from tests.base_test_case import MultipleDeviceTestCase, SingleDeviceTestCase from tests.users import transaction_senders, ens_user from views.sign_in_view import SignInView -from time import sleep import random, emoji diff --git a/test/appium/views/chat_view.py b/test/appium/views/chat_view.py index 1df3f94399..807f26a2b2 100644 --- a/test/appium/views/chat_view.py +++ b/test/appium/views/chat_view.py @@ -1,6 +1,7 @@ from datetime import datetime, timedelta import dateutil.parser import time +import re from selenium.common.exceptions import NoSuchElementException @@ -9,6 +10,7 @@ from time import sleep from views.base_element import Button, EditBox, Text, BaseElement, SilentButton from views.base_view import BaseView from views.profile_view import ProfilePictureElement +from views.home_view import HomeView class CommandsButton(Button): @@ -270,6 +272,67 @@ class GroupChatInfoView(BaseView): return user +class CommunityView(HomeView): + def __init__(self, driver): + super().__init__(driver) + + # Main community page (list with channels) + self.add_channel_button = HomeView(self.driver).plus_button + self.community_create_a_channel_button = Button(self.driver, accessibility_id="community-create-channel") + self.channel_name_edit_box = EditBox(self.driver, translation_id="name-your-channel-placeholder") + self.channel_descripton = ChatView(self.driver).community_description_edit_box + self.community_options_button = Button(self.driver, accessibility_id="community-menu-button") + self.community_info_button = Button(self.driver, translation_id="community-info") + + # Community info page + self.community_membership_request_value = Text(self.driver, translation_id="members-label", + suffix='/following-sibling::android.view.ViewGroup/android.widget.TextView') + self.members_button = Button(self.driver, translation_id="members-label") + self.community_info_picture = Button(self.driver, accessibility_id="chat-icon") + + # Members + self.invite_people_button = Button(self.driver, accessibility_id="community-invite-people") + self.membership_requests_button = Button(self.driver, translation_id="membership-requests") + + # Requesting access to commmunity + self.request_access_button = Button(self.driver, translation_id="request-access") + self.membership_request_pending_text = Text(self.driver, translation_id="membership-request-pending") + + + def add_channel(self, name: str, description="Some new channel"): + self.driver.info("**Adding channel**") + self.plus_button.click() + self.community_create_a_channel_button.wait_and_click() + self.channel_name_edit_box.set_value(name) + self.channel_descripton.set_value(description) + chat_view = ChatView(self.driver) + chat_view.confirm_create_in_community_button.click() + self.get_chat(name).click() + return chat_view + + def copy_community_link(self): + self.driver.info("**Copy community link**") + self.community_options_button.click() + self.community_info_button.click() + self.element_starts_with_text('join.status.im/c/').click() + community_link_text = self.element_starts_with_text('join.status.im/c/').text + self.home_button.double_click() + return 'https://%s'% community_link_text + + def handle_membership_request(self, username: str, approve=True): + self.driver.info("**Handling membership request of user %s, approve=%s**" %(username, str(approve))) + self.members_button.click() + self.membership_requests_button.click() + approve_suffix, decline_suffix = '/following-sibling::android.view.ViewGroup[1]', '/following-sibling::android.view.ViewGroup[2]' + if approve: + Button(self.driver, xpath="//*[starts-with(@text,'%s')]%s" % (username, approve_suffix)).click() + else: + Button(self.driver, xpath="//*[starts-with(@text,'%s')]%s" % (username, decline_suffix)).click() + self.close_button.click() + + + + class PreviewMessage(ChatElementByText): def __init__(self, driver, text:str): super().__init__(driver, text=text) @@ -304,6 +367,46 @@ class PreviewMessage(ChatElementByText): return PreviewMessage.return_element_or_empty(PreviewSubTitle(self.driver, self.locator)) +class CommunityLinkPreviewMessage(ChatElementByText): + def __init__(self, driver, text:str): + super().__init__(driver, text=text) + self.locator+="//*[@text='%s']" % self.get_translation_by_key('community') + + @property + def community_name(self) -> str: + class CommunityName(SilentButton): + def __init__(self, driver, parent_locator: str): + super().__init__(driver, prefix=parent_locator, xpath="/following-sibling::android.widget.TextView[1]") + + return CommunityName(self.driver, self.locator).text + + @property + def community_description(self) -> str: + class CommunityDescription(SilentButton): + def __init__(self, driver, parent_locator: str): + super().__init__(driver, prefix=parent_locator, xpath="/following-sibling::android.widget.TextView[2]") + + return CommunityDescription(self.driver, self.locator).text + + @property + def community_members_amount(self) -> int: + class CommunityMembers(SilentButton): + def __init__(self, driver, parent_locator: str): + super().__init__(driver, prefix=parent_locator, xpath="/following-sibling::android.widget.TextView[3]") + members_string = CommunityMembers(self.driver, self.locator).text + + return int(re.search(r'\d+', members_string).group()) + + def view(self) -> object: + class CommunityViewButton(SilentButton): + def __init__(self, driver, parent_locator: str): + super().__init__(driver, prefix=parent_locator, xpath="/..//*[@text='%s']" % self.get_translation_by_key("view")) + CommunityViewButton(self.driver, self.locator).click() + CommunityView(self.driver).request_access_button.wait_for_element(20) + return CommunityView(self.driver) + + + class TransactionMessage(ChatElementByText): def __init__(self, driver, text:str, transaction_value): super().__init__(driver, text=text) @@ -496,6 +599,16 @@ class ChatView(BaseView): self.timeline_send_my_status_button = Button(self.driver, accessibility_id="send-my-status-button") self.timeline_own_account_photo = Button(self.driver, accessibility_id="own-account-photo") + # Communities + self.create_community_button = Button(self.driver, translation_id="create-community") + self.community_name_edit_box = EditBox(self.driver, translation_id="name-your-community-placeholder") + self.community_description_edit_box = EditBox(self.driver, xpath='//android.widget.EditText[@text="%s"]' % + self.get_translation_by_key("give-a-short-description-community")) + 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") + + + def get_outgoing_transaction(self, account=None, transaction_value=None) -> object: if account is None: @@ -511,6 +624,9 @@ class ChatView(BaseView): self.driver.info('**Getting preview message for link:%s**' % text) return PreviewMessage(self.driver, text) + def get_community_link_preview_by_text(self, text=None) -> object: + self.driver.info('**Getting community preview message for link:%s**' % text) + return CommunityLinkPreviewMessage(self.driver, text) def delete_chat(self): self.driver.info("**Delete chat via options**") @@ -741,6 +857,12 @@ class ChatView(BaseView): transaction_message = self.get_outgoing_transaction(account=None, transaction_value=transaction_value) 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.click() + return CommunityView(self.driver) + + @staticmethod def get_resolved_chat_key(username, chat_key): return '%s • %s…%s' % (username, chat_key[:6], chat_key[-4:]) diff --git a/test/appium/views/home_view.py b/test/appium/views/home_view.py index a781245f2d..958c749fdd 100644 --- a/test/appium/views/home_view.py +++ b/test/appium/views/home_view.py @@ -14,18 +14,28 @@ class ChatButton(Button): class ChatElement(SilentButton): - def __init__(self, driver, username_part): + def __init__(self, driver, username_part, community): self.username = username_part + self.community = community super().__init__(driver, xpath="//*[@content-desc='chat-name-text'][starts-with(@text,'%s')]/.." % username_part) def navigate(self): - from views.chat_view import ChatView - return ChatView(self.driver) + if self.community: + from views.chat_view import CommunityView + return CommunityView(self.driver) + else: + from views.chat_view import ChatView + return ChatView(self.driver) def click(self): - from views.chat_view import ChatView - desired_element = ChatView(self.driver).chat_message_input + if self.community: + from views.chat_view import CommunityView + desired_element = CommunityView(self.driver).community_options_button + else: + from views.chat_view import ChatView + desired_element = ChatView(self.driver).chat_message_input self.click_until_presence_of_element(desired_element=desired_element) + return self.navigate() def find_element(self): @@ -90,6 +100,7 @@ class HomeView(BaseView): self.invite_friends_button = Button(self.driver, accessibility_id="invite-friends-button") self.stop_status_service_button = Button(self.driver, accessibility_id="STOP") self.my_profile_on_start_new_chat_button = Button(self.driver, xpath="//*[@content-desc='current-account-photo']") + self.communities_button = ChatButton(self.driver, accessibility_id="communities-button") # Notification centre self.notifications_button = Button(self.driver, accessibility_id="notifications-button") @@ -135,9 +146,9 @@ class HomeView(BaseView): except TimeoutException: break - def get_chat(self, username): + def get_chat(self, username, community=False): self.driver.info("**Looking for chat '%s'**" % username) - chat_element = ChatElement(self.driver, username[:25]) + chat_element = ChatElement(self.driver, username[:25], community=community) if not chat_element.is_element_displayed(): self.notifications_unread_badge.wait_and_click(30) chat_in_ac = ChatElementInAC(self.driver, username[:25]) @@ -190,6 +201,25 @@ class HomeView(BaseView): self.driver.info("**Group chat %s is created successfully!**" % group_chat_name) return chat_view + def create_community(self, name: str, description="some_description", users_to_add=[], + set_image=False, file_name='sauce_logo.png'): + self.plus_button.click() + chat_view = self.communities_button.click() + chat_view.create_community_button.click() + chat_view.community_name_edit_box.set_value(name) + chat_view.community_description_edit_box.set_value(description) + if set_image: + from views.profile_view import ProfileView + set_picture_view = ProfileView(self.driver) + set_picture_view.element_by_translation_id("community-thumbnail-upload").click() + set_picture_view.element_by_translation_id("community-image-pick").click() + set_picture_view.select_photo_from_gallery(file_name) + set_picture_view.crop_photo_button.click() + + chat_view.confirm_create_in_community_button.click() + return chat_view.get_community_by_name(name) + + def join_public_chat(self, chat_name: str): self.driver.info("**Creating public chat %s**" % chat_name) self.plus_button.click_until_presence_of_element(self.join_public_chat_button, attempts=5) diff --git a/test/appium/views/profile_view.py b/test/appium/views/profile_view.py index 3155e225e1..a52b7b2a41 100644 --- a/test/appium/views/profile_view.py +++ b/test/appium/views/profile_view.py @@ -358,14 +358,7 @@ class ProfileView(BaseView): self.profile_picture.template = file_name if update_by == "Gallery": self.select_from_gallery_button.click() - if self.allow_button.is_element_displayed(sec=5): - self.allow_button.click() - image_full_content = self.get_image_in_storage_by_name(file_name) - if not image_full_content.is_element_displayed(2): - self.show_roots_button.click() - for element_text in 'Images', 'DCIM': - self.element_by_text(element_text).click() - image_full_content.click() + self.select_photo_from_gallery(file_name) else: ## take by Photo self.take_photo() @@ -386,6 +379,17 @@ class ProfileView(BaseView): self.element_by_text("NEXT").click() self.shutter_button.click() + def select_photo_from_gallery(self, file_name: str): + if self.allow_button.is_element_displayed(sec=5): + self.allow_button.click() + image_full_content = self.get_image_in_storage_by_name(file_name) + if not image_full_content.is_element_displayed(2): + self.show_roots_button.click() + for element_text in 'Images', 'DCIM': + self.element_by_text(element_text).click() + image_full_content.click() + + def logout(self): self.driver.info("**Logging out**") self.logout_button.click()