import time import typing import allure from allure_commons._allure import step import configs import driver from constants import UserChannel, ColorCodes from driver.objects_access import walk_children from gui.components.community.community_category_popup import NewCategoryPopup, EditCategoryPopup, CategoryPopup from gui.components.community.community_channel_popups import EditChannelPopup, NewChannelPopup from gui.components.community.invite_contacts import InviteContactsPopup from gui.components.community.welcome_community import WelcomeCommunityPopup from gui.components.context_menu import ContextMenu from gui.components.delete_popup import DeletePopup, DeleteCategoryPopup from gui.components.profile_popup import ProfilePopupFromMembers from gui.elements.button import Button from gui.elements.list import List from gui.elements.object import QObject from gui.elements.text_label import TextLabel from gui.objects_map import names, communities_names, messaging_names from gui.screens.community_settings import CommunitySettingsScreen from scripts.tools.image import Image class CommunityScreen(QObject): def __init__(self): super().__init__(communities_names.mainWindow_communityLoader_Loader) self.left_panel = LeftPanel() self.tool_bar = ToolBar() self.chat = Chat() self.right_panel = Members() @allure.step('Wait until appears {0}') def wait_until_appears(self, timeout_msec: int = configs.timeouts.UI_LOAD_TIMEOUT_MSEC): self.left_panel.wait_until_appears(timeout_msec) return self @allure.step('Create channel') def create_channel(self, name: str, description: str, emoji: str = None): self.left_panel.open_create_channel_popup().create(name, description, emoji).save() @allure.step('Edit channel') def edit_channel(self, channel, name: str, description: str, emoji: str = None): self.left_panel.select_channel(channel) self.tool_bar.open_edit_channel_popup().edit(name, description, emoji) @allure.step('Delete channel') def delete_channel(self, name: str): self.left_panel.select_channel(name) self.tool_bar.open_delete_channel_popup().delete() @allure.step('Verify channel') def verify_channel( self, name: str, description: str, emoji): with step('Channel is correct in channels list'): channel = self.left_panel.get_channel_parameters(name) assert channel.name == name with step('Channel is correct in community toolbar'): assert self.tool_bar.channel_name == name assert self.tool_bar.channel_description == description if emoji is not None: assert self.tool_bar.channel_emoji == emoji with step('Verify channel in chat'): assert self.chat.channel_name == name if emoji is not None: assert self.chat.channel_emoji == emoji @allure.step('Create category') def create_category(self, name: str, general_checkbox: bool): self.left_panel.open_create_category_popup().create(name, general_checkbox) @allure.step('Delete category from the list') def delete_category(self): self.left_panel.open_more_options() self.left_panel.open_delete_category_popup().delete() @allure.step('Edit category') def edit_category(self): self.left_panel.open_more_options() self.left_panel.open_edit_category_popup() return EditCategoryPopup() @allure.step('Verify category in the list') def verify_category(self, category_name: str): category = self.left_panel.find_category_in_list(category_name) assert category.category_name == category_name class ToolBar(QObject): def __init__(self): super().__init__(communities_names.mainWindow_statusToolBar_StatusToolBar) self._more_options_button = Button(communities_names.statusToolBar_chatToolbarMoreOptionsButton) self._options_list = List(names.o_StatusListView) self._edit_channel_context_item = QObject(communities_names.edit_Channel_StatusMenuItem) self._channel_icon = QObject(communities_names.statusToolBar_statusSmartIdenticonLetter_StatusLetterIdenticon) self._channel_name = TextLabel( communities_names.statusToolBar_statusChatInfoButtonNameText_TruncatedTextWithTooltip) self._channel_description = TextLabel(communities_names.statusToolBar_TruncatedTextWithTooltip) self._delete_channel_context_item = QObject(communities_names.delete_Channel_StatusMenuItem) self._channel_header = QObject(communities_names.statusToolBar_chatInfoBtnInHeader_StatusChatInfoButton) @property @allure.step('Get channel emoji') def channel_emoji(self): return self._channel_header.object.asset.emoji @property @allure.step('Get channel color') def channel_color(self) -> str: return str(self._channel_header.object.asset.color.name).lower() @property @allure.step('Get channel name') def channel_name(self) -> str: return self._channel_name.text @property @allure.step('Get channel description') def channel_description(self) -> str: return self._channel_description.text @allure.step('Open edit channel popup') def open_edit_channel_popup(self): self.open_more_options_dropdown() self._edit_channel_context_item.click() return EditChannelPopup().wait_until_appears() @allure.step('Open delete channel popup') def open_delete_channel_popup(self): self.open_more_options_dropdown() self._delete_channel_context_item.click() return DeletePopup().wait_until_appears() @allure.step('Open more options dropdown') def open_more_options_dropdown(self): self._more_options_button.click() return ContextMenu() @allure.step('Get visibility state of edit item') def is_edit_item_visible(self) -> bool: return self._edit_channel_context_item.exists @allure.step('Get visibility state of delete item') def is_delete_item_visible(self) -> bool: return self._delete_channel_context_item.exists class CategoryItem: def __init__(self, obj): self.object = obj self.category_name: typing.Optional[Image] = None self._add_category_button: typing.Optional[Button] = None self._more_button: typing.Optional[Button] = None self._arrow_button: typing.Optional[Button] = None self._arrow_icon: typing.Optional[QObject] = None self.init_ui() def __repr__(self): return self.category_name def init_ui(self): for child in walk_children(self.object): if str(getattr(child, 'id', '')) == 'statusChatListCategoryItem': self.category_name = str(child.text) elif str(getattr(child, 'id', '')) == 'addButton': self._add_channel_button = Button(real_name=driver.objectMap.realName(child)) elif str(getattr(child, 'id', '')) == 'menuButton': self._more_button = Button(real_name=driver.objectMap.realName(child)) elif str(getattr(child, 'id', '')) == 'toggleButton': self._arrow_button = Button(real_name=driver.objectMap.realName(child)) elif str(getattr(child, 'objectName', '')) == 'chevron-down-icon': self._arrow_icon = QObject(real_name=driver.objectMap.realName(child)) @allure.step('Click arrow button') def click_arrow_button(self): self._arrow_button.click() @allure.step('Get arrow button rotation value') def get_arrow_icon_rotation_value(self) -> int: return self._arrow_icon.object.rotation class LeftPanel(QObject): def __init__(self): super().__init__(communities_names.mainWindow_communityColumnView_CommunityColumnView) self._community_info_button = Button(communities_names.mainWindow_communityHeaderButton_StatusChatInfoButton) self._community_logo = QObject(communities_names.mainWindow_identicon_StatusSmartIdenticon) self._name_text_label = TextLabel( communities_names.mainWindow_statusChatInfoButtonNameText_TruncatedTextWithTooltip) self._members_text_label = TextLabel(communities_names.mainWindow_Members_TruncatedTextWithTooltip) self._general_channel_item = QObject(communities_names.scrollView_general_StatusChatListItem) self._add_channels_button = Button(communities_names.add_channels_StatusButton) self._channel_list_item = QObject(communities_names.channel_listItem) self._channel_icon_template = QObject(communities_names.channel_identicon_StatusSmartIdenticon) self._channel_or_category_button = Button( communities_names.mainWindow_createChannelOrCategoryBtn_StatusBaseText) self._create_channel_menu_item = Button(communities_names.create_channel_StatusMenuItem) self._create_category_menu_item = Button(communities_names.create_category_StatusMenuItem) self._join_community_button = Button(communities_names.mainWindow_Join_Community_StatusButton) self._categories_items_list = List(communities_names.scrollView_chatListItems_StatusListView) self._category_list_item = QObject(communities_names.categoryItem_StatusChatListCategoryItem) self._create_category_button = Button(communities_names.add_categories_StatusFlatButton) self._delete_category_item = QObject(communities_names.delete_Category_StatusMenuItem) self._edit_category_item = QObject(communities_names.edit_Category_StatusMenuItem) self._add_channel_inside_category_item = QObject( communities_names.scrollView_addButton_StatusChatListCategoryItemButton) self._more_button = Button(communities_names.scrollView_menuButton_StatusChatListCategoryItemButton) self._arrow_button = Button(communities_names.scrollView_toggleButton_StatusChatListCategoryItemButton) self._add_members_button = Button(names.scrollView_Add_members_StatusButton) @property @allure.step('Get community logo') def logo(self) -> Image: return self._community_logo.image @property @allure.step('Get community name') def name(self) -> str: return self._name_text_label.text @property @allure.step('Get community members label') def members(self) -> str: return self._members_text_label.text @property @allure.step('Get Join button visible attribute') def is_join_community_visible(self) -> bool: return self._join_community_button.exists @property @allure.step('Get channels') def channels(self) -> typing.List[UserChannel]: time.sleep(0.5) channels_list = [] for obj in driver.findAllObjects(self._channel_list_item.real_name): container = driver.objectMap.realName(obj) self._channel_icon_template.real_name['container'] = container channels_list.append(UserChannel( str(obj.objectName), obj.item.selected, obj.item.visible )) return channels_list @property @allure.step('Get categories') def categories_items(self) -> typing.List[CategoryItem]: return [CategoryItem(item) for item in self._categories_items_list.items] @allure.step('Get arrow button rotation value') def get_arrow_icon_rotation_value(self, category_name) -> int: category = self.find_category_in_list(category_name) return int(category.get_arrow_icon_rotation_value()) @allure.step('Get channel params') def get_channel_parameters(self, name) -> UserChannel: for channel in self.channels: if channel.name == name: return channel raise LookupError(f'Channel not found in {self.channels}') @allure.step('Open community settings') def open_community_settings(self): self._community_info_button.click() return CommunitySettingsScreen().wait_until_appears() @allure.step('Open create channel popup') def open_create_channel_popup(self) -> NewChannelPopup: self._channel_or_category_button.click() self._create_channel_menu_item.click() return NewChannelPopup() @allure.step('Get presence state of create channel or category button') def does_create_channel_or_category_button_exist(self) -> bool: return self._channel_or_category_button.exists @allure.step('Get visibility state of add channels button') def is_add_channels_button_visible(self) -> bool: return self._add_channels_button.is_visible @allure.step('Get visibility state of add category button') def is_add_category_button_visible(self) -> bool: return self._create_category_button.is_visible @allure.step('Select channel') def select_channel(self, name: str): for obj in driver.findAllObjects(self._channel_list_item.real_name): if str(obj.objectName) == name: driver.mouseClick(obj) return obj raise LookupError('Channel not found') @allure.step('Open general channel context menu') def open_general_channel_context_menu(self): self._general_channel_item.right_click() return ContextMenu() @allure.step('Open category context menu') def open_category_context_menu(self): self._category_list_item.right_click() @allure.step('Open create category popup') def open_create_category_popup(self, attempts: int = 2) -> NewCategoryPopup: self._channel_or_category_button.click() try: self._create_category_menu_item.click() return NewCategoryPopup() except Exception as ex: if attempts: self.open_create_category_popup(attempts - 1) else: raise ex @allure.step('Open join community popup') def open_welcome_community_popup(self): self._join_community_button.wait_until_appears(configs.timeouts.UI_LOAD_TIMEOUT_MSEC) self._join_community_button.click() return WelcomeCommunityPopup().wait_until_appears() @allure.step('Find category') def find_category_in_list( self, category_name: str, timeout_sec: int = configs.timeouts.MESSAGING_TIMEOUT_SEC): started_at = time.monotonic() category = None while category is None: categories = self.categories_items for _category in categories: if _category.category_name == category_name: category = _category assert time.monotonic() - started_at < timeout_sec, f'Category: {category_name} not found in {categories}' return category def click_category(self, category_name: str): driver.mouseClick(self.find_category_in_list(category_name).object) @allure.step('Open more options') def open_more_options(self, attempts: int = 2): self._arrow_button.click() try: self._more_button.click() except LookupError as err: if attempts: return self._more_button.click(attempts - 1) else: raise err return self @allure.step('Get visibility state of delete item') def is_delete_item_visible(self) -> bool: return self._delete_category_item.is_visible @allure.step('Get visibility state of edit item') def is_edit_item_visible(self) -> bool: return self._edit_category_item.is_visible @allure.step('Open delete category popup') def open_delete_category_popup(self) -> DeleteCategoryPopup: self._delete_category_item.click() return DeleteCategoryPopup().wait_until_appears() @allure.step('Open edit category popup') def open_edit_category_popup(self) -> EditCategoryPopup: self._edit_category_item.click() return CategoryPopup().wait_until_appears() @allure.step('Open new channel popup inside category') def open_new_channel_popup_in_category(self) -> NewChannelPopup: self._arrow_button.click() self._add_channel_inside_category_item.click() return NewChannelPopup().wait_until_appears() @allure.step('Get channel or category index in the list') def get_channel_or_category_index(self, name: str) -> int: for child in walk_children(self._categories_items_list.object): if child.objectName == name: return child.visualIndex @allure.step('Right click on left panel') def right_click_on_panel(self): super(LeftPanel, self).right_click() @allure.step('Invite people to community') def invite_people_to_community(self, contacts: typing.List[str], message: str, attempts: int = 2): self._add_members_button.click() try: InviteContactsPopup().wait_until_appears().invite(contacts, message) except AssertionError as err: if attempts: self.invite_people_to_community(contacts, message, attempts - 1) else: raise err class Chat(QObject): def __init__(self): super().__init__(communities_names.mainWindow_ChatColumnView) self._channel_icon = QObject( communities_names.chatMessageViewDelegate_channelIdentifierSmartIdenticon_StatusSmartIdenticon) self._channel_name_label = TextLabel( communities_names.chatMessageViewDelegate_channelIdentifierNameText_StyledText) self._channel_welcome_label = TextLabel(communities_names.chatMessageViewDelegate_Welcome) self._channel_identifier_view = QObject(messaging_names.chatMessageViewDelegate_ChannelIdentifierView) @property @allure.step('Get channel emoji') def channel_emoji(self): return self._channel_identifier_view.object.chatEmoji @property @allure.step('Get channel color') def channel_color(self) -> str: return str(self._channel_identifier_view.object.chatColor).lower() @property @allure.step('Get channel name') def channel_name(self) -> str: return self._channel_name_label.text @property @allure.step('Get channel welcome note') def channel_welcome_note(self) -> str: return self._channel_welcome_label.text class Members(QObject): def __init__(self): super().__init__(communities_names.mainWindow_userListPanel_StatusListView) self._member_item = QObject(communities_names.userListPanel_StatusMemberListItem) self._user_badge_color = QObject(communities_names.statusBadge_StatusBadge) @property @allure.step('Get all members') def members(self) -> typing.List[str]: return [str(member.statusListItemTitle.text) for member in driver.findAllObjects(self._member_item.real_name)] @allure.step('Click member by name') def click_member(self, member_name: str): for member in driver.findAllObjects(self._member_item.real_name): if getattr(member, 'title', '') == member_name: driver.mouseClick(member) break return ProfilePopupFromMembers().wait_until_appears() @allure.step('Verify member is offline by index') def member_state(self, member_name: str) -> bool: for member in driver.findAllObjects(self._member_item.real_name): if getattr(member, 'title', '') == member_name: for child in walk_children(member): if getattr(child, 'id', '') == 'statusBadge': return child.color.name