diff --git a/configs/__init__.py b/configs/__init__.py index df885a5..8f4c3bc 100644 --- a/configs/__init__.py +++ b/configs/__init__.py @@ -1,7 +1,7 @@ import logging from scripts.utils.system_path import SystemPath -from . import testpath, timeouts, testrail, system +from . import testpath, timeouts, testrail, squish, system _logger = logging.getLogger(__name__) diff --git a/configs/squish.py b/configs/squish.py new file mode 100644 index 0000000..13a84b0 --- /dev/null +++ b/configs/squish.py @@ -0,0 +1 @@ +AUT_PORT = 61500 \ No newline at end of file diff --git a/constants/user.py b/constants/user.py index b130c60..c2e0452 100644 --- a/constants/user.py +++ b/constants/user.py @@ -1,5 +1,7 @@ from collections import namedtuple +import configs + UserAccount = namedtuple('User', ['name', 'password', 'seed_phrase']) user_account_default = UserAccount('squisher', '*P@ssw0rd*', [ 'rail', 'witness', 'era', 'asthma', 'empty', 'cheap', 'shed', 'pond', 'skate', 'amount', 'invite', 'year' @@ -8,5 +10,14 @@ user_account_one = UserAccount('tester123', 'TesTEr16843/!@00', []) user_account_two = UserAccount('Athletic', 'TesTEr16843/!@00', []) user_account_three = UserAccount('Nervous', 'TesTEr16843/!@00', []) +default_community_params = { + 'name': 'Name', + 'description': 'Description', + 'logo': {'fp': configs.testpath.TEST_FILES / 'tv_signal.png', 'zoom': None, 'shift': None}, + 'banner': {'fp': configs.testpath.TEST_FILES / 'banner.png', 'zoom': None, 'shift': None}, + 'intro': 'Intro', + 'outro': 'Outro' +} -UserCommunity = namedtuple('Community', ['name', 'description', 'members', 'image']) +UserCommunityInfo = namedtuple('CommunityInfo', ['name', 'description', 'members', 'image']) +UserChannel = namedtuple('Channel', ['name', 'image', 'selected']) diff --git a/driver/atomacos.py b/driver/atomacos.py index 92c5820..c80657e 100644 --- a/driver/atomacos.py +++ b/driver/atomacos.py @@ -2,6 +2,7 @@ import time from copy import deepcopy import configs.timeouts +from scripts.utils import local_system if configs.system.IS_MAC: from atomacos._a11y import _running_apps_with_bundle_id @@ -26,7 +27,11 @@ def attach_atomac(timeout_sec: int = configs.timeouts.UI_LOAD_TIMEOUT_SEC): ) return atomacos.NativeUIElement.from_pid(apps[-1].processIdentifier()) - atomator = from_bundle_id(BUNDLE_ID) + if configs.DEV_BUILD: + pid = local_system.find_process_by_port(configs.squish.AUT_PORT) + atomator = atomacos.getAppRefByPid(pid) + else: + atomator = from_bundle_id(BUNDLE_ID) started_at = time.monotonic() while not hasattr(atomator, 'AXMainWindow'): time.sleep(1) diff --git a/driver/aut.py b/driver/aut.py index 1967c53..a7f65e1 100644 --- a/driver/aut.py +++ b/driver/aut.py @@ -14,7 +14,7 @@ class AUT: self, app_path: system_path.SystemPath = configs.APP_DIR, host: str = '127.0.0.1', - port: int = 61500 + port: int = configs.squish.AUT_PORT ): super(AUT, self).__init__() self.path = app_path diff --git a/ext/vp/test_communities/test_create_community_channel/channel_icon_in_chat.png b/ext/vp/test_communities/test_create_community_channel/channel_icon_in_chat.png new file mode 100644 index 0000000..3ea7809 Binary files /dev/null and b/ext/vp/test_communities/test_create_community_channel/channel_icon_in_chat.png differ diff --git a/ext/vp/test_communities/test_create_community_channel/channel_icon_in_list.png b/ext/vp/test_communities/test_create_community_channel/channel_icon_in_list.png new file mode 100644 index 0000000..040e41d Binary files /dev/null and b/ext/vp/test_communities/test_create_community_channel/channel_icon_in_list.png differ diff --git a/ext/vp/test_communities/test_create_community_channel/channel_icon_in_toolbar.png b/ext/vp/test_communities/test_create_community_channel/channel_icon_in_toolbar.png new file mode 100644 index 0000000..6d82723 Binary files /dev/null and b/ext/vp/test_communities/test_create_community_channel/channel_icon_in_toolbar.png differ diff --git a/ext/vp/test_communities/test_edit_community_channel/channel_icon_in_chat.png b/ext/vp/test_communities/test_edit_community_channel/channel_icon_in_chat.png new file mode 100644 index 0000000..3ea7809 Binary files /dev/null and b/ext/vp/test_communities/test_edit_community_channel/channel_icon_in_chat.png differ diff --git a/ext/vp/test_communities/test_edit_community_channel/channel_icon_in_list.png b/ext/vp/test_communities/test_edit_community_channel/channel_icon_in_list.png new file mode 100644 index 0000000..040e41d Binary files /dev/null and b/ext/vp/test_communities/test_edit_community_channel/channel_icon_in_list.png differ diff --git a/ext/vp/test_communities/test_edit_community_channel/channel_icon_in_toolbar.png b/ext/vp/test_communities/test_edit_community_channel/channel_icon_in_toolbar.png new file mode 100644 index 0000000..6d82723 Binary files /dev/null and b/ext/vp/test_communities/test_edit_community_channel/channel_icon_in_toolbar.png differ diff --git a/ext/vp/test_communities/test_edit_community_channel/general_channel_icon_in_chat.png b/ext/vp/test_communities/test_edit_community_channel/general_channel_icon_in_chat.png new file mode 100644 index 0000000..97aecf8 Binary files /dev/null and b/ext/vp/test_communities/test_edit_community_channel/general_channel_icon_in_chat.png differ diff --git a/ext/vp/test_communities/test_edit_community_channel/general_channel_icon_in_list.png b/ext/vp/test_communities/test_edit_community_channel/general_channel_icon_in_list.png new file mode 100644 index 0000000..07bc287 Binary files /dev/null and b/ext/vp/test_communities/test_edit_community_channel/general_channel_icon_in_list.png differ diff --git a/ext/vp/test_communities/test_edit_community_channel/general_channel_icon_in_toolbar.png b/ext/vp/test_communities/test_edit_community_channel/general_channel_icon_in_toolbar.png new file mode 100644 index 0000000..5994cfe Binary files /dev/null and b/ext/vp/test_communities/test_edit_community_channel/general_channel_icon_in_toolbar.png differ diff --git a/gui/components/community/community_channel_popups.py b/gui/components/community/community_channel_popups.py new file mode 100644 index 0000000..729dff5 --- /dev/null +++ b/gui/components/community/community_channel_popups.py @@ -0,0 +1,44 @@ +import configs +from gui.components.base_popup import BasePopup +from gui.components.emoji_popup import EmojiPopup +from gui.elements.qt.button import Button +from gui.elements.qt.text_edit import TextEdit + + +class ChannelPopup(BasePopup): + + def __init__(self): + super(ChannelPopup, self).__init__() + self._name_text_edit = TextEdit('createOrEditCommunityChannelNameInput_TextEdit') + self._description_text_edit = TextEdit('createOrEditCommunityChannelDescriptionInput_TextEdit') + self._save_create_button = Button('createOrEditCommunityChannelBtn_StatusButton') + self._emoji_button = Button('createOrEditCommunityChannel_EmojiButton') + + def wait_until_appears(self, timeout_msec: int = configs.timeouts.UI_LOAD_TIMEOUT_MSEC): + self._name_text_edit.wait_until_appears(timeout_msec) + return self + + +class NewChannelPopup(ChannelPopup): + + def create(self, name: str, description: str, emoji: str = None): + self._name_text_edit.text = name + self._description_text_edit.text = description + if emoji is not None: + self._emoji_button.click() + EmojiPopup().wait_until_appears().select(emoji) + self._save_create_button.click() + self.wait_until_hidden() + + +class EditChannelPopup(ChannelPopup): + + def edit(self, name: str, description: str = None, emoji: str = None): + self._name_text_edit.text = name + if description is not None: + self._description_text_edit.text = description + if emoji is not None: + self._emoji_button.click() + EmojiPopup().wait_until_appears().select(emoji) + self._save_create_button.click() + self.wait_until_hidden() diff --git a/gui/components/delete_popup.py b/gui/components/delete_popup.py new file mode 100644 index 0000000..cb7040e --- /dev/null +++ b/gui/components/delete_popup.py @@ -0,0 +1,16 @@ +import allure + +from gui.components.base_popup import BasePopup +from gui.elements.qt.button import Button + + +class DeletePopup(BasePopup): + + def __init__(self): + super().__init__() + self._delete_button = Button('delete_StatusButton') + + @allure.step("Delete entity") + def delete(self): + self._delete_button.click() + self.wait_until_hidden() diff --git a/gui/components/emoji_popup.py b/gui/components/emoji_popup.py new file mode 100644 index 0000000..f34462d --- /dev/null +++ b/gui/components/emoji_popup.py @@ -0,0 +1,25 @@ +import allure + +import configs +from .base_popup import BasePopup +from ..elements.qt.object import QObject +from ..elements.qt.text_edit import TextEdit + + +class EmojiPopup(BasePopup): + def __init__(self): + super(EmojiPopup, self).__init__() + self._search_text_edit = TextEdit('mainWallet_AddEditAccountPopup_AccountEmojiSearchBox') + self._emoji_item = QObject('mainWallet_AddEditAccountPopup_AccountEmoji') + + @allure.step('Wait until appears {0}') + def wait_until_appears(self, timeout_msec: int = configs.timeouts.UI_LOAD_TIMEOUT_MSEC): + self._search_text_edit.wait_until_appears(timeout_msec) + return self + + @allure.step('Select emoji') + def select(self, name: str): + self._search_text_edit.text = name + self._emoji_item.real_name['objectName'] = 'statusEmoji_' + name + self._emoji_item.click() + self._search_text_edit.wait_until_hidden() diff --git a/gui/objects_map/community_names.py b/gui/objects_map/community_names.py index 533dce1..2a99259 100644 --- a/gui/objects_map/community_names.py +++ b/gui/objects_map/community_names.py @@ -16,11 +16,27 @@ mainWindow_startChatButton_StatusIconTabButton = {"checkable": True, "container" mainWindow_createChatOrCommunity_Loader = {"container": mainWindow_communityColumnView_CommunityColumnView, "id": "createChatOrCommunity", "type": "Loader", "unnamed": 1, "visible": True} mainWindow_scrollView_StatusScrollView = {"container": mainWindow_communityColumnView_CommunityColumnView, "id": "scrollView", "type": "StatusScrollView", "unnamed": 1, "visible": True} scrollView_Flickable = {"container": mainWindow_scrollView_StatusScrollView, "type": "Flickable", "unnamed": 1, "visible": True} +scrollView_chatListItems_StatusListView = {"container": scrollView_Flickable, "objectName": "chatListItems", "type": "StatusListView", "visible": True} +channel_listItem = {"container": scrollView_chatListItems_StatusListView, "id": "chatListDelegate", "type": "DropArea", "isCategory": False, "visible": True} +channel_identicon_StatusSmartIdenticon = {"container": None, "id": "identicon", "type": "StatusSmartIdenticon", "unnamed": 1, "visible": True} +channel_name_StatusBaseText = {"container": None, "type": "StatusBaseText", "unnamed": 1, "visible": True} +mainWindow_createChannelOrCategoryBtn_StatusBaseText = {"container": mainWindow_communityColumnView_CommunityColumnView, "objectName": "createChannelOrCategoryBtn", "type": "StatusBaseText", "visible": True} +create_channel_StatusMenuItem = {"container": statusDesktop_mainWindow_overlay, "enabled": True, "objectName": "createCommunityChannelBtn", "type": "StatusMenuItem", "visible": True} + # Tool Bar mainWindow_statusToolBar_StatusToolBar = {"container": mainWindow_communityLoader_Loader, "objectName": "statusToolBar", "type": "StatusToolBar", "visible": True} statusToolBar_chatToolbarMoreOptionsButton = {"container": mainWindow_statusToolBar_StatusToolBar, "objectName": "chatToolbarMoreOptionsButton", "type": "StatusFlatRoundButton", "visible": True} delete_Channel_StatusMenuItem = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "enabled": True, "objectName": "deleteOrLeaveMenuItem", "type": "StatusMenuItem", "visible": True} +edit_Channel_StatusMenuItem = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "enabled": True, "objectName": "editChannelMenuItem", "type": "StatusMenuItem", "visible": True} +statusToolBar_statusSmartIdenticonLetter_StatusLetterIdenticon = {"container": mainWindow_statusToolBar_StatusToolBar, "objectName": "statusSmartIdenticonLetter", "type": "StatusLetterIdenticon", "visible": True} +statusToolBar_statusChatInfoButtonNameText_TruncatedTextWithTooltip = {"container": mainWindow_statusToolBar_StatusToolBar, "objectName": "statusChatInfoButtonNameText", "type": "TruncatedTextWithTooltip", "visible": True} +statusToolBar_TruncatedTextWithTooltip = {"container": mainWindow_statusToolBar_StatusToolBar, "type": "TruncatedTextWithTooltip", "unnamed": 1, "visible": True} +# Chat +mainWindow_ChatColumnView = {"container": mainWindow_communityLoader_Loader, "type": "ChatColumnView", "unnamed": 1, "visible": True} +chatMessageViewDelegate_channelIdentifierNameText_StyledText = {"container": mainWindow_ChatColumnView, "objectName": "channelIdentifierNameText", "type": "StyledText", "visible": True} +chatMessageViewDelegate_Welcome = {"container": mainWindow_ChatColumnView, "type": "StatusBaseText", "unnamed": 1, "visible": True} +chatMessageViewDelegate_channelIdentifierSmartIdenticon_StatusSmartIdenticon = {"container": mainWindow_ChatColumnView, "objectName": "channelIdentifierSmartIdenticon", "type": "StatusSmartIdenticon", "visible": True} # Community Settings mainWindow_communitySettingsBackToCommunityButton_StatusBaseText = {"container": mainWindow_communityLoader_Loader, "objectName": "communitySettingsBackToCommunityButton", "type": "StatusBaseText", "visible": True} diff --git a/gui/objects_map/component_names.py b/gui/objects_map/component_names.py index f1e4d58..8684ab4 100644 --- a/gui/objects_map/component_names.py +++ b/gui/objects_map/component_names.py @@ -1,15 +1,15 @@ from objectmaphelper import * -from . main_names import statusDesktop_mainWindow_overlay -from . main_names import statusDesktop_mainWindow +from .main_names import statusDesktop_mainWindow_overlay # Scroll o_Flickable = {"container": statusDesktop_mainWindow_overlay, "type": "Flickable", "unnamed": 1, "visible": True} # Context Menu -o_StatusListView = {"container": statusDesktop_mainWindow_overlay, "type": "StatusListView", "unnamed": 1, - "visible": True} +o_StatusListView = {"container": statusDesktop_mainWindow_overlay, "type": "StatusListView", "unnamed": 1, "visible": True} + +""" Onboarding """ # Before you get started Popup acknowledge_checkbox = {"checkable": True, "container": statusDesktop_mainWindow_overlay, "objectName": "acknowledgeCheckBox", "type": "StatusCheckBox", "visible": True} termsOfUseCheckBox_StatusCheckBox = {"checkable": True, "container": statusDesktop_mainWindow_overlay, "objectName":"termsOfUseCheckBox", "type": "StatusCheckBox", "visible": True} @@ -65,11 +65,8 @@ agreeToUse_StatusCheckBox = {"checkable": True, "container": statusDesktop_mainW readyToUse_StatusCheckBox = {"checkable": True, "container": statusDesktop_mainWindow_overlay, "id": "readyToUse", "type": "StatusCheckBox", "unnamed": 1, "visible": True} i_m_ready_to_use_Status_Desktop_Beta_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "type": "StatusButton", "unnamed": 1, "visible": True} -# Picture Edit Popup -o_StatusSlider = {"container": statusDesktop_mainWindow_overlay, "type": "StatusSlider", "unnamed": 1, "visible": True} -cropSpaceItem_Item = {"container": statusDesktop_mainWindow_overlay, "id": "cropSpaceItem", "type": "Item", "unnamed": 1, "visible": True} -make_picture_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "objectName": "imageCropperAcceptButton", "type": "StatusButton", "visible": True} -o_DropShadow = {"container": statusDesktop_mainWindow_overlay, "type": "DropShadow", "unnamed": 1, "visible": True} + +""" Communities """ # Create Community Banner create_new_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "objectName": "communityBannerButton", "type": "StatusButton", "visible": True} @@ -93,6 +90,14 @@ createCommunityIntroMessageInput_TextEdit = {"container": statusDesktop_mainWind createCommunityOutroMessageInput_TextEdit = {"container": statusDesktop_mainWindow_overlay, "objectName": "createCommunityOutroMessageInput", "type": "TextEdit", "visible": True} createCommunityFinalBtn_StatusButton = {"container": statusDesktop_mainWindow_overlay, "objectName": "createCommunityFinalBtn", "type": "StatusButton", "visible": True} +# Community channel popup: +createOrEditCommunityChannelNameInput_TextEdit = {"container": statusDesktop_mainWindow_overlay, "objectName": "createOrEditCommunityChannelNameInput", "type": "TextEdit", "visible": True} +createOrEditCommunityChannelDescriptionInput_TextEdit = {"container": statusDesktop_mainWindow_overlay, "objectName": "createOrEditCommunityChannelDescriptionInput", "type": "TextEdit", "visible": True} +createOrEditCommunityChannelBtn_StatusButton = {"container": statusDesktop_mainWindow_overlay, "objectName": "createOrEditCommunityChannelBtn", "type": "StatusButton", "visible": True} +createOrEditCommunityChannel_EmojiButton = {"container": statusDesktop_mainWindow_overlay, "objectName": "StatusChannelPopup_emojiButton", "type": "StatusRoundButton", "visible": True} + +""" Common """ + # Select Color Popup communitySettings_ColorPanel_HexColor_Input = {"container": statusDesktop_mainWindow_overlay, "objectName": "communityColorPanelHexInput", "type": "TextEdit", "visible": True} communitySettings_SaveColor_Button = {"container": statusDesktop_mainWindow_overlay, "objectName": "communityColorPanelSelectColorButton", "type": "StatusButton", "visible": True} @@ -126,3 +131,16 @@ contextMenuItem = {"container": statusDesktop_mainWindow_overlay, "type": "Statu # Confirmation Popup confirmButton = {"container": statusDesktop_mainWindow_overlay, "objectName": RegularExpression("confirm*"), "type": "StatusButton"} +# Picture Edit Popup +o_StatusSlider = {"container": statusDesktop_mainWindow_overlay, "type": "StatusSlider", "unnamed": 1, "visible": True} +cropSpaceItem_Item = {"container": statusDesktop_mainWindow_overlay, "id": "cropSpaceItem", "type": "Item", "unnamed": 1, "visible": True} +make_picture_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "objectName": "imageCropperAcceptButton", "type": "StatusButton", "visible": True} +o_DropShadow = {"container": statusDesktop_mainWindow_overlay, "type": "DropShadow", "unnamed": 1, "visible": True} + +# Emoji Popup +mainWallet_AddEditAccountPopup_AccountEmojiSearchBox = {"container": statusDesktop_mainWindow, "objectName": "StatusEmojiPopup_searchBox", "type": "TextEdit", "visible": True} +mainWallet_AddEditAccountPopup_AccountEmoji = {"container": statusDesktop_mainWindow, "type": "StatusEmoji", "visible": True} + +# Delete Popup +o_StatusDialogBackground = {"container": statusDesktop_mainWindow_overlay, "type": "StatusDialogBackground", "unnamed": 1, "visible": True} +delete_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "objectName": "deleteChatConfirmationDialogDeleteButton", "type": "StatusButton", "visible": True} \ No newline at end of file diff --git a/gui/screens/community.py b/gui/screens/community.py index 40add82..9ec2042 100644 --- a/gui/screens/community.py +++ b/gui/screens/community.py @@ -1,10 +1,18 @@ -import allure +import typing +import allure +from allure_commons._allure import step + +import driver +from constants import UserChannel +from gui.components.community.community_channel_popups import EditChannelPopup, NewChannelPopup +from gui.components.delete_popup import DeletePopup from gui.elements.qt.button import Button from gui.elements.qt.list import List from gui.elements.qt.object import QObject from gui.elements.qt.text_label import TextLabel from gui.screens.community_settings import CommunitySettingsScreen +from scripts.tools import image from scripts.tools.image import Image @@ -13,7 +21,40 @@ class CommunityScreen(QObject): def __init__(self): super().__init__('mainWindow_communityLoader_Loader') self.left_panel = LeftPanel() - self._tool_bar = ToolBar() + self.tool_bar = ToolBar() + self.chat = Chat() + + @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) + + @allure.step('Create 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, icon_in_list: str, icon_in_toolbar: str, icon_in_chat: str): + with step('Channel is correct in channels list'): + channel = self.left_panel.get_channel_parameters(name) + image.compare(channel.image, icon_in_list, timout_sec=5) + assert channel.name == name + assert channel.selected + + with step('Channel is correct in community toolbar'): + assert self.tool_bar.channel_name == name + assert self.tool_bar.channel_description == description + image.compare(self.tool_bar.channel_icon, icon_in_toolbar, timout_sec=5) + + with step('Verify channel in chat'): + assert self.chat.channel_name == name + image.compare(self.chat.channel_icon, icon_in_chat, timout_sec=5) class ToolBar(QObject): @@ -22,11 +63,38 @@ class ToolBar(QObject): super().__init__('mainWindow_statusToolBar_StatusToolBar') self._more_options_button = Button('statusToolBar_chatToolbarMoreOptionsButton') self._options_list = List('o_StatusListView') + self._edit_channel_context_item = QObject('edit_Channel_StatusMenuItem') + self._channel_icon = QObject('statusToolBar_statusSmartIdenticonLetter_StatusLetterIdenticon') + self._channel_name = TextLabel('statusToolBar_statusChatInfoButtonNameText_TruncatedTextWithTooltip') + self._channel_description = TextLabel('statusToolBar_TruncatedTextWithTooltip') + self._delete_channel_context_item = QObject('delete_Channel_StatusMenuItem') - @allure.step('Open edit community popup') - def open_edit_community_popup(self): + @property + @allure.step('Get channel icon') + def channel_icon(self) -> Image: + return self._channel_icon.image + + @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._more_options_button.click() - self._options_list.select() + self._edit_channel_context_item.click() + return EditChannelPopup().wait_until_appears() + + @allure.step('Open delete channel popup') + def open_delete_channel_popup(self): + self._more_options_button.click() + self._delete_channel_context_item.click() + return DeletePopup().wait_until_appears() class LeftPanel(QObject): @@ -37,6 +105,10 @@ class LeftPanel(QObject): self._community_logo = QObject('mainWindow_identicon_StatusSmartIdenticon') self._name_text_label = TextLabel('mainWindow_statusChatInfoButtonNameText_TruncatedTextWithTooltip') self._members_text_label = TextLabel('mainWindow_Members_TruncatedTextWithTooltip') + self._channel_list_item = QObject('channel_listItem') + self._channel_icon_template = QObject('channel_identicon_StatusSmartIdenticon') + self._channel_or_category_button = Button('mainWindow_createChannelOrCategoryBtn_StatusBaseText') + self._create_channel_menu_item = Button('create_channel_StatusMenuItem') @property @allure.step('Get community logo') @@ -53,7 +125,66 @@ class LeftPanel(QObject): def members(self) -> str: return self._members_text_label.text + @property + @allure.step('Get channels') + def channels(self) -> typing.List[UserChannel]: + 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), + self._channel_icon_template.image, + obj.item.selected + )) + return channels_list + + @allure.step('Get channel params') + def get_channel_parameters(self, name) -> UserChannel: + for channal in self.channels: + if channal.name == name: + return channal + 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().wait_until_appears() + + @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 + raise LookupError('Channel not found') + + +class Chat(QObject): + + def __init__(self): + super().__init__('mainWindow_ChatColumnView') + self._channel_icon = QObject('chatMessageViewDelegate_channelIdentifierSmartIdenticon_StatusSmartIdenticon') + self._channel_name_label = TextLabel('chatMessageViewDelegate_channelIdentifierNameText_StyledText') + self._channel_welcome_label = TextLabel('chatMessageViewDelegate_Welcome') + + @property + @allure.step('Get channel icon') + def channel_icon(self) -> Image: + return self._channel_icon.image + + @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 diff --git a/gui/screens/settings.py b/gui/screens/settings.py index 74b2b75..dccc789 100644 --- a/gui/screens/settings.py +++ b/gui/screens/settings.py @@ -3,7 +3,7 @@ import typing import allure import driver -from constants import UserCommunity +from constants import UserCommunityInfo from driver import objects_access from gui.elements.qt.button import Button from gui.elements.qt.object import QObject @@ -40,7 +40,7 @@ class CommunitiesSettingsView(QObject): @property @allure.step('Get communities') - def communities(self) -> typing.List[UserCommunity]: + def communities(self) -> typing.List[UserCommunityInfo]: _communities = [] for obj in driver.findAllObjects(self._community_item.real_name): container = driver.objectMap.realName(obj) @@ -49,7 +49,7 @@ class CommunitiesSettingsView(QObject): self._community_template_description.real_name['container'] = container self._community_template_members.real_name['container'] = container - _communities.append(UserCommunity( + _communities.append(UserCommunityInfo( self._community_template_name.text, self._community_template_description.text, self._community_template_members.text, @@ -65,7 +65,7 @@ class CommunitiesSettingsView(QObject): raise LookupError(f'Community item: {name} not found') @allure.step('Open community info') - def get_community_info(self, name: str) -> UserCommunity: + def get_community_info(self, name: str) -> UserCommunityInfo: for community in self.communities: if community.name == name: return community diff --git a/scripts/utils/local_system.py b/scripts/utils/local_system.py index a066235..cb9bd69 100644 --- a/scripts/utils/local_system.py +++ b/scripts/utils/local_system.py @@ -5,6 +5,7 @@ import subprocess import time import allure +import psutil import configs from configs.system import IS_WIN @@ -12,6 +13,16 @@ from configs.system import IS_WIN _logger = logging.getLogger(__name__) +def find_process_by_port(port: int) -> int: + for proc in psutil.process_iter(): + try: + for conns in proc.connections(kind='inet'): + if conns.laddr.port == port: + return proc.pid + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): + pass + + @allure.step('Kill process') def kill_process(pid): os.kill(pid, signal.SIGILL if IS_WIN else signal.SIGKILL) diff --git a/tests/fixtures/aut.py b/tests/fixtures/aut.py index 4531166..4413dcb 100644 --- a/tests/fixtures/aut.py +++ b/tests/fixtures/aut.py @@ -54,3 +54,12 @@ def main_screen(user_account: UserAccount, main_window: MainWindow) -> MainWindo yield main_window.log_in(user_account) else: yield main_window.sign_up(user_account) + + +@pytest.fixture +def community(main_screen, request) -> dict: + community_params = request.param + communities_portal = main_screen.left_panel.open_communities_portal() + create_community_form = communities_portal.open_create_community_popup() + create_community_form.create(community_params) + return community_params diff --git a/tests/test_communities.py b/tests/test_communities.py index fe73d20..836a3cf 100644 --- a/tests/test_communities.py +++ b/tests/test_communities.py @@ -5,7 +5,9 @@ import pytest from allure_commons._allure import step import configs.testpath +import constants.user from gui.main_window import MainWindow +from gui.screens.community import CommunityScreen from scripts.tools import image pytestmark = allure.suite("Communities") @@ -13,30 +15,19 @@ pytestmark = allure.suite("Communities") @allure.testcase('https://ethstatus.testrail.net/index.php?/cases/view/703084', 'Create community') @pytest.mark.case(703084) -@pytest.mark.parametrize('community_params', [ - { - 'name': f'Name', - 'description': f'Description', - 'logo': {'fp': configs.testpath.TEST_FILES / 'tv_signal.png', 'zoom': None, 'shift': None}, - 'banner': {'fp': configs.testpath.TEST_FILES / 'banner.png', 'zoom': None, 'shift': None}, - 'color': '#ff7d46', - 'tags': ['Culture', 'Sports'], - 'intro': 'Intro', - 'outro': 'Outro' - } -]) -def test_create_community(user_account, main_screen: MainWindow, community_params): +@pytest.mark.parametrize('params', [constants.user.default_community_params]) +def test_create_community(user_account, main_screen: MainWindow, params): with step('Create community'): communities_portal = main_screen.left_panel.open_communities_portal() create_community_form = communities_portal.open_create_community_popup() - community_screen = create_community_form.create(community_params) + community_screen = create_community_form.create(params) with step('Verify community parameters in community overview'): with step('Icon is correct'): - community_icon = main_screen.left_panel.get_community_logo(community_params['name']) + community_icon = main_screen.left_panel.get_community_logo(params['name']) image.compare(community_icon, 'button_logo.png', timout_sec=5) with step('Name is correct'): - assert community_screen.left_panel.name == community_params['name'] + assert community_screen.left_panel.name == params['name'] with step('Members count is correct'): assert '1' in community_screen.left_panel.members with step('Logo is correct'): @@ -46,9 +37,9 @@ def test_create_community(user_account, main_screen: MainWindow, community_param community_setting = community_screen.left_panel.open_community_settings() overview_setting = community_setting.left_panel.open_overview() with step('Name is correct'): - assert overview_setting.name == community_params['name'] + assert overview_setting.name == params['name'] with step('Description is correct'): - assert overview_setting.description == community_params['description'] + assert overview_setting.description == params['description'] with step('Members count is correct'): members_settings = community_setting.left_panel.open_members() assert user_account.name in members_settings.members @@ -56,116 +47,152 @@ def test_create_community(user_account, main_screen: MainWindow, community_param with step('Verify community parameters in community settings screen'): settings_screen = main_screen.left_panel.open_settings() community_settings = settings_screen.open_communities_settings() - community = community_settings.get_community_info(community_params['name']) - assert community.name == community_params['name'] - assert community.description == community_params['description'] + community = community_settings.get_community_info(params['name']) + assert community.name == params['name'] + assert community.description == params['description'] assert '1' in community.members image.compare(community.image, 'logo_in_settings.png') @allure.testcase('https://ethstatus.testrail.net/index.php?/cases/view/703056', 'Edit community separately') @pytest.mark.case(703056) -@pytest.mark.parametrize('default_params, update_params', [( - { - 'name': 'Name', - 'description': 'Description', - 'logo': {'fp': configs.testpath.TEST_FILES / 'tv_signal.png', 'zoom': None, 'shift': None}, - 'banner': {'fp': configs.testpath.TEST_FILES / 'banner.png', 'zoom': None, 'shift': None}, - 'intro': 'Intro', - 'outro': 'Outro' - }, +@pytest.mark.parametrize('community', [constants.user.default_community_params], indirect=True) +@pytest.mark.parametrize('community_params', [ { 'name': f'Name_{datetime.now():%H%M%S}', 'description': f'Description_{datetime.now():%H%M%S}', 'color': '#ff7d46', }, -)]) -def test_edit_community_separately(main_screen: MainWindow, default_params, update_params): - with step('Create community'): - communities_portal = main_screen.left_panel.open_communities_portal() - create_community_form = communities_portal.open_create_community_popup() - community_screen = create_community_form.create(default_params) +]) +def test_edit_community_separately(main_screen, community: dict, community_params): with step('Edit community name'): + community_screen = main_screen.left_panel.select_community(community['name']) community_setting = community_screen.left_panel.open_community_settings() edit_community_form = community_setting.left_panel.open_overview().open_edit_community_view() - edit_community_form.edit({'name': update_params['name']}) + edit_community_form.edit({'name': community_params['name']}) with step('Name is correct'): overview_setting = community_setting.left_panel.open_overview() - assert overview_setting.name == update_params['name'] + assert overview_setting.name == community_params['name'] with step('Description is correct'): - assert overview_setting.description == default_params['description'] + assert overview_setting.description == constants.default_community_params['description'] with step('Edit community name'): edit_community_form = overview_setting.open_edit_community_view() - edit_community_form.edit({'description': update_params['description']}) + edit_community_form.edit({'description': community_params['description']}) with step('Name is correct'): overview_setting = community_setting.left_panel.open_overview() - assert overview_setting.name == update_params['name'] + assert overview_setting.name == community_params['name'] with step('Description is correct'): - assert overview_setting.description == update_params['description'] + assert overview_setting.description == community_params['description'] @allure.testcase('https://ethstatus.testrail.net/index.php?/cases/view/703057', 'Edit community') @pytest.mark.case(703057) -@pytest.mark.parametrize('default_params, community_params', [( - { - 'name': f'Name_{datetime.now():%H%M%S}', - 'description': f'Description_{datetime.now():%H%M%S}', - 'logo': {'fp': configs.testpath.TEST_FILES / 'tv_signal.png', 'zoom': None, 'shift': None}, - 'banner': {'fp': configs.testpath.TEST_FILES / 'banner.png', 'zoom': None, 'shift': None}, - 'color': '#ff7d46', - 'tags': ['Culture', 'Sports'], - 'intro': 'Intro', - 'outro': 'Outro' - }, +@pytest.mark.parametrize('community', [constants.user.default_community_params], indirect=True) +@pytest.mark.parametrize('params', [ { 'name': 'Updated Name', 'description': 'Updated Description', 'logo': {'fp': configs.testpath.TEST_FILES / 'banner.png', 'zoom': None, 'shift': None}, 'banner': {'fp': configs.testpath.TEST_FILES / 'tv_signal.png', 'zoom': None, 'shift': None}, - 'color': '#7140fd', + 'color': '#ff7d46', 'tags': ['Ethereum'], 'intro': 'Updated Intro', 'outro': 'Updated Outro' } -)]) -def test_edit_community(main_screen: MainWindow, default_params, community_params): - with step('Create community'): - communities_portal = main_screen.left_panel.open_communities_portal() - create_community_form = communities_portal.open_create_community_popup() - community_screen = create_community_form.create(default_params) +]) +def test_edit_community(main_screen: MainWindow, community: dict, params): with step('Edit community'): + community_screen = main_screen.left_panel.select_community(community['name']) community_setting = community_screen.left_panel.open_community_settings() edit_community_form = community_setting.left_panel.open_overview().open_edit_community_view() - edit_community_form.edit(community_params) + edit_community_form.edit(params) with step('Verify community parameters on settings overview'): overview_setting = community_setting.left_panel.open_overview() with step('Name is correct'): - assert overview_setting.name == community_params['name'] + assert overview_setting.name == params['name'] with step('Description is correct'): - assert overview_setting.description == community_params['description'] + assert overview_setting.description == params['description'] with step('Verify community parameters in community screen'): community_setting.left_panel.back_to_community() with step('Icon is correct'): - community_icon = main_screen.left_panel.get_community_logo(community_params['name']) + community_icon = main_screen.left_panel.get_community_logo(params['name']) image.compare(community_icon, 'button_updated_logo.png') with step('Name is correct'): - assert community_screen.left_panel.name == community_params['name'] + assert community_screen.left_panel.name == params['name'] with step('Logo is correct'): image.compare(community_screen.left_panel.logo, 'updated_logo.png') with step('Verify community parameters in community settings screen'): settings_screen = main_screen.left_panel.open_settings() community_settings = settings_screen.open_communities_settings() - community = community_settings.communities[0] - assert community.name == community_params['name'] - assert community.description == community_params['description'] - assert '1' in community.members - image.compare(community.image, 'logo_in_settings_updated.png') + community_info = community_settings.communities[0] + assert community_info.name == params['name'] + assert community_info.description == params['description'] + assert '1' in community_info.members + image.compare(community_info.image, 'logo_in_settings_updated.png') + + +@allure.testcase('https://ethstatus.testrail.net/index.php?/cases/view/703049', 'Create community channel') +@pytest.mark.case(703049) +@pytest.mark.parametrize('community', [constants.user.default_community_params], indirect=True) +@pytest.mark.parametrize('channel_name, channel_description, channel_emoji', [('Channel', 'Description', 'sunglasses')]) +def test_create_community_channel(main_screen: MainWindow, community: dict, channel_name, channel_description, + channel_emoji): + community_screen = main_screen.left_panel.select_community(community['name']) + community_screen.create_channel(channel_name, channel_description, channel_emoji) + + with step('Verify channel'): + community_screen.verify_channel( + channel_name, + channel_description, + 'channel_icon_in_list.png', + 'channel_icon_in_toolbar.png', + 'channel_icon_in_chat.png' + ) + + +@allure.testcase('https://ethstatus.testrail.net/index.php?/cases/view/703050', 'Edit community channel') +@pytest.mark.case(703050) +@pytest.mark.parametrize('community', [constants.user.default_community_params], indirect=True) +@pytest.mark.parametrize('channel_name, channel_description, channel_emoji', [('Channel', 'Description', 'sunglasses')]) +def test_edit_community_channel(community: dict, channel_name, channel_description, channel_emoji): + community_screen = CommunityScreen() + + with step('Verify General channel'): + community_screen.verify_channel( + 'general', + 'General channel for the community', + 'general_channel_icon_in_list.png', + 'general_channel_icon_in_toolbar.png', + 'general_channel_icon_in_chat.png' + ) + + community_screen.edit_channel('general', channel_name, channel_description, channel_emoji) + + with step('Verify General channel'): + community_screen.verify_channel( + channel_name, + channel_description, + 'channel_icon_in_list.png', + 'channel_icon_in_toolbar.png', + 'channel_icon_in_chat.png' + ) + + +@allure.testcase('https://ethstatus.testrail.net/index.php?/cases/view/703051', 'Delete community channel') +@pytest.mark.case(703051) +@pytest.mark.parametrize('community', [constants.user.default_community_params], indirect=True) +def test_delete_community_channel(community: dict): + with step('Delete channel'): + CommunityScreen().delete_channel('general') + + with step('Verify channel is not exists'): + assert not CommunityScreen().left_panel.channels