diff --git a/test/e2e/gui/components/community/community_channel_popups.py b/test/e2e/gui/components/community/community_channel_popups.py index 60cf8060fe..66e292c22b 100644 --- a/test/e2e/gui/components/community/community_channel_popups.py +++ b/test/e2e/gui/components/community/community_channel_popups.py @@ -1,7 +1,9 @@ import configs from gui.components.base_popup import BasePopup +from gui.components.community.new_permission_popup import NewPermissionPopup from gui.components.emoji_popup import EmojiPopup from gui.elements.button import Button +from gui.elements.check_box import CheckBox from gui.elements.text_edit import TextEdit from gui.objects_map import names @@ -14,6 +16,8 @@ class ChannelPopup(BasePopup): self._description_text_edit = TextEdit(names.createOrEditCommunityChannelDescriptionInput_TextEdit) self._save_create_button = Button(names.createOrEditCommunityChannelBtn_StatusButton) self._emoji_button = Button(names.createOrEditCommunityChannel_EmojiButton) + self._add_permission_button = Button(names.add_permission_StatusButton) + self._hide_channel_checkbox = CheckBox(names.hide_channel_checkbox) def wait_until_appears(self, timeout_msec: int = configs.timeouts.UI_LOAD_TIMEOUT_MSEC): self._name_text_edit.wait_until_appears(timeout_msec) @@ -28,6 +32,22 @@ class NewChannelPopup(ChannelPopup): if emoji is not None: self._emoji_button.click() EmojiPopup().wait_until_appears().select(emoji) + return self + + def add_permission(self): + self._add_permission_button.click() + return NewPermissionPopup().wait_until_appears() + + def hide_permission(self, value: bool, attempt: int = 2): + try: + return self._hide_channel_checkbox.set(value) + except AssertionError as err: + if attempt: + self.hide_permission(True, attempt - 1) + else: + raise err + + def save(self): self._save_create_button.click() diff --git a/test/e2e/gui/components/community/new_permission_popup.py b/test/e2e/gui/components/community/new_permission_popup.py new file mode 100644 index 0000000000..1d6937baf6 --- /dev/null +++ b/test/e2e/gui/components/community/new_permission_popup.py @@ -0,0 +1,113 @@ +import allure + +import configs +import driver +from driver.objects_access import walk_children +from gui.elements.button import Button +from gui.elements.check_box import CheckBox +from gui.elements.object import QObject +from gui.elements.text_edit import TextEdit +from gui.objects_map import communities_names + + +class NewPermissionPopup(QObject): + def __init__(self): + super(NewPermissionPopup, self).__init__() + self._who_holds_checkbox = CheckBox(communities_names.whoHoldsSwitch_StatusSwitch) + self._who_holds_asset_field = TextEdit(communities_names.edit_TextEdit) + self._who_holds_amount_field = TextEdit(communities_names.inputValue_StyledTextField) + self._asset_item = QObject(communities_names.o_TokenItem) + self._is_allowed_to_option_button = Button(communities_names.customPermissionListItem) + self._hide_permission_checkbox = CheckBox(communities_names.switchItem_StatusSwitch) + self._create_permission_button = Button(communities_names.create_permission_StatusButton) + self._add_button_who_holds = Button(communities_names.add_update_statusButton) + self._add_button_is_allowed_to = Button(communities_names.add_StatusButton) + self._who_holds_list_item = QObject(communities_names.who_holds_StatusItemSelector) + self._is_allowed_to_list_item = QObject(communities_names.is_allowed_to_StatusFlowSelector) + + @allure.step('Wait until appears {0}') + def wait_until_appears(self, timeout_msec: int = configs.timeouts.UI_LOAD_TIMEOUT_MSEC): + driver.waitForObjectExists(self._create_permission_button.real_name, timeout_msec) + return self + + @allure.step('Set state of who holds checkbox') + def set_who_holds_checkbox_state(self, state): + if state is False: + self._who_holds_checkbox.set(state) + + @allure.step('Open Who holds context menu') + def open_who_holds_context_menu(self, attempt: int = 2): + try: + for child in walk_children(self._who_holds_list_item.object): + if getattr(child, 'objectName', '') == 'addItemButton': + driver.mouseClick(child) + return self._who_holds_asset_field.wait_until_appears() + except AssertionError: + if attempt: + return self.open_who_holds_context_menu(attempt - 1) + else: + raise LookupError('Add button for who holds not found') + + @allure.step('Open Is allowed to context menu') + def open_is_allowed_to_context_menu(self, attempt: int = 2): + try: + for child in walk_children(self._is_allowed_to_list_item.object): + if getattr(child, 'objectName', '') == 'addItemButton': + driver.mouseClick(child) + return + except LookupError: + if attempt: + return self.open_is_allowed_to_context_menu(attempt - 1) + else: + raise LookupError('Add button for allowed to not found') + + @allure.step('Set asset and amount') + def set_who_holds_asset_and_amount(self, asset: str, amount: str): + if asset is not False: + self.open_who_holds_context_menu() + self._who_holds_asset_field.clear().text = asset + self._asset_item.click() + self._who_holds_asset_field.wait_until_hidden() + self._who_holds_amount_field.text = amount + self.click_add_button_who_holds() + return self + + @allure.step('Choose option from Is allowed to context menu') + def set_is_allowed_to(self, name): + self.open_is_allowed_to_context_menu() + self._is_allowed_to_option_button.real_name['objectName'] = name + self._is_allowed_to_option_button.wait_until_appears().click() + self.click_add_button_is_allowed() + return self + + @allure.step('Click add button for who holds') + def click_add_button_who_holds(self, attempt: int = 2): + self._add_button_who_holds.click() + try: + self._add_button_who_holds.wait_until_hidden() + except AssertionError as err: + if attempt: + self.click_add_button_who_holds(attempt - 1) + else: + raise err + + @allure.step('Click add button is allowed') + def click_add_button_is_allowed(self, attempt: int = 2): + self._add_button_is_allowed_to.click() + try: + self._add_button_is_allowed_to.wait_until_hidden() + except AssertionError as err: + if attempt: + self.click_add_button_is_allowed(attempt - 1) + else: + raise err + + @allure.step('Click create permission') + def create_permission(self): + self._create_permission_button.click() + self._create_permission_button.wait_until_hidden() + + @allure.step('Switch hide permission checkbox') + def switch_hide_permission_checkbox(self, state): + self._hide_permission_checkbox.set(state) + return self diff --git a/test/e2e/gui/objects_map/communities_names.py b/test/e2e/gui/objects_map/communities_names.py index 7d2b8409e4..da241c2f5c 100644 --- a/test/e2e/gui/objects_map/communities_names.py +++ b/test/e2e/gui/objects_map/communities_names.py @@ -161,18 +161,20 @@ add_new_permission_button = {"container": statusDesktop_mainWindow, "objectName" # Permissions Settings View mainWindow_editPermissionView_EditPermissionView = {"container": statusDesktop_mainWindow, "id": "editPermissionView", "type": "EditPermissionView", "unnamed": 1, "visible": True} -editPermissionView_Who_holds_StatusItemSelector = {"container": mainWindow_editPermissionView_EditPermissionView, "id": "tokensSelector", "type": "StatusItemSelector", "unnamed": 1, "visible": True} -editPermissionView_Is_allowed_to_StatusFlowSelector = {"container": mainWindow_editPermissionView_EditPermissionView, "id": "permissionsSelector", "type": "StatusFlowSelector", "unnamed": 1, "visible": True} +editPermissionView_Who_holds_StatusItemSelector = {"container": mainWindow_editPermissionView_EditPermissionView, "objectName": "tokensSelector", "type": "StatusItemSelector", "visible": True} +editPermissionView_Is_allowed_to_StatusFlowSelector = {"container": mainWindow_editPermissionView_EditPermissionView, "objectName": "permissionsSelector", "type": "StatusFlowSelector", "visible": True} editPermissionView_In_StatusItemSelector = {"container": mainWindow_editPermissionView_EditPermissionView, "id": "inSelector", "type": "StatusItemSelector", "unnamed": 1, "visible": True} editPermissionView_whoHoldsSwitch_StatusSwitch = {"checkable": True, "container": mainWindow_editPermissionView_EditPermissionView, "id": "whoHoldsSwitch", "type": "StatusSwitch", "unnamed": 1, "visible": True} edit_TextEdit = {"container": statusDesktop_mainWindow_overlay, "type": "TextEdit", "unnamed": 1, "visible": True} inputValue_StyledTextField = {"container": statusDesktop_mainWindow_overlay, "id": "inputValue", "type": "StyledTextField", "unnamed": 1, "visible": True} o_TokenItem = {"container": statusDesktop_mainWindow_overlay, "index": 0, "type": "TokenItem", "unnamed": 1, "visible": True} -add_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "type": "StatusButton", "unnamed": 1, "visible": True} +add_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "objectName": "addButton", "type": "StatusButton", "visible": True} +add_update_statusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "id": "addOrUpdateButton", "type": "StatusButton", "unnamed": 1, "visible": True} +add_StatusButton_in = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "type": "StatusButton", "unnamed": 1, "visible": True} customPermissionListItem = {"container": statusDesktop_mainWindow_overlay, "objectName": "becomeAdmin", "type": "CustomPermissionListItem", "visible": True} checkBox_StatusCheckBox = {"checkable": True, "container": statusDesktop_mainWindow_overlay, "id": "checkBox", "type": "StatusCheckBox", "unnamed": 1, "visible": True} editPermissionView_switchItem_StatusSwitch = {"checkable": True, "container": mainWindow_editPermissionView_EditPermissionView, "objectName": "switchItem", "type": "StatusSwitch", "visible": True} -editPermissionView_Create_permission_StatusButton = {"checkable": False, "container": mainWindow_editPermissionView_EditPermissionView, "text": "Create permission", "type": "StatusButton", "unnamed": 1, "visible": True} +editPermissionView_Create_permission_StatusButton = {"checkable": False, "container": mainWindow_editPermissionView_EditPermissionView, "objectName": "createPermissionButton", "type": "StatusButton", "visible": True} mainWindow_PermissionsView = {"container": statusDesktop_mainWindow, "type": "PermissionsView", "unnamed": 1, "visible": True} o_StatusListItemTag = {"container": mainWindow_PermissionsView, "type": "StatusListItemTag", "visible": True} o_IntroPanel = {"container": mainWindow_PermissionsView, "type": "IntroPanel", "unnamed": 1, "visible": True} @@ -188,6 +190,11 @@ editPermissionView_settingsDirtyToastMessage_SettingsDirtyToastMessage = {"conta update_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "type": "StatusButton", "unnamed": 1, "visible": True} isAllowedToEditPermissionView_StatusListItemTag = {"container": mainWindow_editPermissionView_EditPermissionView, "type": "StatusListItemTag", "unnamed": 1, "visible": True} editPermissionView_duplicationPanel_WarningPanel = {"container": mainWindow_editPermissionView_EditPermissionView, "objectName": "duplicationPanel", "type": "WarningPanel", "visible": True} +create_permission_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "objectName": "createChannelNextBtn", "type": "StatusButton", "visible": True} +who_holds_StatusItemSelector = {"container": statusDesktop_mainWindow_overlay, "objectName": "tokensSelector", "type": "StatusItemSelector", "visible": True} +is_allowed_to_StatusFlowSelector = {"container": statusDesktop_mainWindow_overlay, "objectName": "permissionsSelector", "type": "StatusFlowSelector", "visible": True} +switchItem_StatusSwitch = {"checkable": True, "container": statusDesktop_mainWindow_overlay, "objectName": "switchItem", "occurrence": 2, "type": "StatusSwitch", "visible": True} +whoHoldsSwitch_StatusSwitch = {"checkable": True, "container": statusDesktop_mainWindow_overlay, "id": "whoHoldsSwitch", "type": "StatusSwitch", "unnamed": 1, "visible": True} # Edit Community mainWindow_communityEditPanelScrollView_EditSettingsPanel = {"container": statusDesktop_mainWindow, "objectName": "communityEditPanelScrollView", "type": "EditSettingsPanel", "visible": True} diff --git a/test/e2e/gui/objects_map/names.py b/test/e2e/gui/objects_map/names.py index 86adeea99f..c8698722f5 100644 --- a/test/e2e/gui/objects_map/names.py +++ b/test/e2e/gui/objects_map/names.py @@ -149,6 +149,8 @@ createOrEditCommunityChannelNameInput_TextEdit = {"container": statusDesktop_mai 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} +add_permission_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "objectName": "addPermissionButton", "type": "StatusButton", "visible": True} +hide_channel_checkbox = {"checkable": True, "container": statusDesktop_mainWindow_overlay, "objectName": "hideChannelCheckbox", "type": "StatusCheckBox", "visible": True} # Community Category Popup createOrEditCommunityCategoryNameInput_TextEdit = {"container": statusDesktop_mainWindow_overlay, "objectName": "createOrEditCommunityCategoryNameInput", "type": "TextEdit", "visible": True} diff --git a/test/e2e/gui/screens/community.py b/test/e2e/gui/screens/community.py index 6159aec6a2..59cf24f02c 100644 --- a/test/e2e/gui/screens/community.py +++ b/test/e2e/gui/screens/community.py @@ -40,7 +40,7 @@ class CommunityScreen(QObject): @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) + 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): diff --git a/test/e2e/gui/screens/community_settings.py b/test/e2e/gui/screens/community_settings.py index b0f70abc64..72679e5d74 100644 --- a/test/e2e/gui/screens/community_settings.py +++ b/test/e2e/gui/screens/community_settings.py @@ -438,6 +438,8 @@ class PermissionsSettingsView(QObject): self._hide_permission_checkbox = CheckBox(communities_names.editPermissionView_switchItem_StatusSwitch) self._create_permission_button = Button(communities_names.editPermissionView_Create_permission_StatusButton) self._add_button = Button(communities_names.add_StatusButton) + self._add_button_who_holds = Button(communities_names.add_update_statusButton) + self._add_button_in = Button(communities_names.add_StatusButton_in) self._who_holds_list_item = QObject(communities_names.editPermissionView_Who_holds_StatusItemSelector) self._is_allowed_to_list_item = QObject(communities_names.editPermissionView_Is_allowed_to_StatusFlowSelector) self._in_list_item = QObject(communities_names.editPermissionView_In_StatusItemSelector) @@ -505,30 +507,52 @@ class PermissionsSettingsView(QObject): self._asset_item.click() self._who_holds_asset_field.wait_until_hidden() self._who_holds_amount_field.text = amount - self.click_add_button() + self.click_add_button_who_holds() @allure.step('Choose option from Is allowed to context menu') def set_is_allowed_to(self, name): self.open_is_allowed_to_context_menu() self._is_allowed_to_option_button.real_name['objectName'] = name self._is_allowed_to_option_button.wait_until_appears().click() - self.click_add_button() + self.click_add_button_allowed_to() @allure.step('Choose channel from In context menu') def set_in(self, in_general): if in_general == '#general': self.open_in_context_menu() self._in_general_checkbox.wait_until_appears().click() - self.click_add_button() + self.click_add_button_in() - @allure.step('Click add button') - def click_add_button(self, attempt: int = 2): + @allure.step('Click add button for allowed to') + def click_add_button_allowed_to(self, attempt: int = 2): self._add_button.click() try: self._add_button.wait_until_hidden() except AssertionError as err: if attempt: - self.click_add_button(attempt - 1) + self.click_add_button_allowed_to(attempt - 1) + else: + raise err + + @allure.step('Click add button for who holds') + def click_add_button_who_holds(self, attempt: int = 2): + self._add_button_who_holds.click() + try: + self._add_button.wait_until_hidden() + except AssertionError as err: + if attempt: + self.click_add_button_who_holds(attempt - 1) + else: + raise err + + @allure.step('Click add button for in') + def click_add_button_in(self, attempt: int = 2): + self._add_button_in.click() + try: + self._add_button.wait_until_hidden() + except AssertionError as err: + if attempt: + self.click_add_button_in(attempt - 1) else: raise err @@ -585,4 +609,4 @@ class PermissionsSettingsView(QObject): self._is_allowed_to_edit_tag.click() self._is_allowed_to_option_button.real_name['objectName'] = name self._is_allowed_to_option_button.wait_until_appears().click() - self.click_add_button() + self.click_add_button_allowed_to() diff --git a/test/e2e/tests/communities/test_communities_categories.py b/test/e2e/tests/communities/test_communities_categories.py index 5cadc15376..714bea47d4 100644 --- a/test/e2e/tests/communities/test_communities_categories.py +++ b/test/e2e/tests/communities/test_communities_categories.py @@ -43,7 +43,7 @@ def test_create_edit_remove_community_category(main_screen: MainWindow, category with step('Create community channel inside category'): community_screen.left_panel.open_new_channel_popup_in_category().create(channel_name, channel_description, - channel_emoji) + channel_emoji).save() with step('Create community channel outside of category'): community_screen.create_channel(second_channel_name, second_channel_description, second_channel_emoji) diff --git a/test/e2e/tests/communities/test_communities_channels.py b/test/e2e/tests/communities/test_communities_channels.py index 70ecf90a5a..9670f2c688 100644 --- a/test/e2e/tests/communities/test_communities_channels.py +++ b/test/e2e/tests/communities/test_communities_channels.py @@ -1,3 +1,6 @@ +import random +import string + import allure import pytest from allure_commons._allure import step @@ -5,8 +8,10 @@ from allure_commons._allure import step import configs import constants import driver +from constants import UserAccount from gui.components.context_menu import ContextMenu from gui.main_window import MainWindow +from gui.screens.messages import MessagesScreen from . import marks pytestmark = marks @@ -20,7 +25,7 @@ pytestmark = marks 'channel_name, channel_description, channel_emoji, channel_emoji_image, channel_color, new_channel_name, ' 'new_channel_description, new_channel_emoji', [('Channel', 'Description', 'sunglasses', None, '#4360df', 'New-channel', 'New channel description', 'thumbsup')]) -# @pytest.mark.critical TODO: https://github.com/status-im/desktop-qa-automation/issues/658 + # @pytest.mark.critical TODO: https://github.com/status-im/desktop-qa-automation/issues/658 def test_create_edit_remove_community_channel(main_screen, channel_name, channel_description, channel_emoji, channel_emoji_image, channel_color, new_channel_name, new_channel_description, @@ -114,3 +119,51 @@ def test_member_role_cannot_add_edit_and_delete_channels(main_screen: MainWindow with step('Verify that delete item is not present in context menu'): assert more_options.is_delete_channel_option_present() is False, \ f'Delete channel option is present when it should not' + + +@allure.testcase('https://ethstatus.testrail.net/index.php?/cases/edit/737079', + 'Member not holding permission cannot see channel (view-only permission)') +@pytest.mark.case(737079) +@pytest.mark.parametrize('user_data_one, user_data_two, asset, amount, channel_description', [ + (configs.testpath.TEST_USER_DATA / 'squisher', configs.testpath.TEST_USER_DATA / 'athletic', 'ETH', '10', + 'description') +]) +def test_member_cannot_see_hidden_channel(multiple_instances, user_data_one, user_data_two, asset, amount, + channel_description): + user_one: UserAccount = constants.user_account_one + user_two: UserAccount = constants.user_account_two + channel_name = ''.join(random.choices(string.ascii_letters + string.digits, k=8)) + main_screen = MainWindow() + + with (multiple_instances(user_data=user_data_one) as aut_one, multiple_instances( + user_data=user_data_two) as aut_two): + with step(f'Launch multiple instances with authorized users {user_one.name} and {user_two.name}'): + for aut, account in zip([aut_one, aut_two], [user_one, user_two]): + aut.attach() + main_screen.wait_until_appears(configs.timeouts.APP_LOAD_TIMEOUT_MSEC).prepare() + main_screen.authorize_user(account) + main_screen.hide() + + with step(f'User {user_two.name}, select non-restricted channel and can send message'): + aut_two.attach() + main_screen.prepare() + community_screen = main_screen.left_panel.select_community('Community with 2 users') + + with step(f'User {user_two.name}, create hidden channel, verify that it is in the list'): + permission_popup = community_screen.left_panel.open_create_channel_popup().create(channel_name, + channel_description, + emoji=None) + permission_popup.add_permission().set_who_holds_asset_and_amount(asset, amount).set_is_allowed_to( + 'viewOnly').switch_hide_permission_checkbox(True).create_permission() + permission_popup.hide_permission(True) + permission_popup.save() + channel = community_screen.left_panel.get_channel_parameters(channel_name) + assert driver.waitFor(lambda: channel in community_screen.left_panel.channels, + configs.timeouts.UI_LOAD_TIMEOUT_MSEC) + main_screen.hide() + + with step(f'User {user_one.name}, cannot see hidden channel in the list'): + aut_one.attach() + main_screen.prepare() + assert driver.waitFor(lambda: channel not in community_screen.left_panel.channels, + configs.timeouts.UI_LOAD_TIMEOUT_MSEC) diff --git a/ui/app/AppLayouts/Communities/popups/CreateChannelPopup.qml b/ui/app/AppLayouts/Communities/popups/CreateChannelPopup.qml index bff0d6d623..1afae5ac60 100644 --- a/ui/app/AppLayouts/Communities/popups/CreateChannelPopup.qml +++ b/ui/app/AppLayouts/Communities/popups/CreateChannelPopup.qml @@ -783,6 +783,7 @@ StatusStackModal { visible: viewOnlyCanAddReactionCheckbox.visible } StatusCheckBox { + objectName: "hideChannelCheckbox" id: viewOnlyCanAddReactionCheckbox Layout.fillWidth: true Layout.preferredHeight: 48 @@ -808,6 +809,7 @@ StatusStackModal { } Item { Layout.fillWidth: true } StatusButton { + objectName: "addPermissionButton" text: qsTr("Add permission") enabled: !!nameInput.text property ListModel channelToAddPermission: ListModel { } diff --git a/ui/app/AppLayouts/Communities/popups/PermissionsDropdown.qml b/ui/app/AppLayouts/Communities/popups/PermissionsDropdown.qml index c621fb73d9..2c75e5a2de 100644 --- a/ui/app/AppLayouts/Communities/popups/PermissionsDropdown.qml +++ b/ui/app/AppLayouts/Communities/popups/PermissionsDropdown.qml @@ -166,6 +166,7 @@ StatusDropdown { StatusButton { Layout.fillWidth: true Layout.topMargin: d.buttonTopMargin + objectName: "addButton" text: root.mode === PermissionsDropdown.Mode.Add ? qsTr("Add") : qsTr("Update") enabled: !!group.checkedButton diff --git a/ui/app/AppLayouts/Communities/views/EditPermissionView.qml b/ui/app/AppLayouts/Communities/views/EditPermissionView.qml index 88de35933c..290d83f78b 100644 --- a/ui/app/AppLayouts/Communities/views/EditPermissionView.qml +++ b/ui/app/AppLayouts/Communities/views/EditPermissionView.qml @@ -186,6 +186,7 @@ StatusScrollView { StatusItemSelector { id: tokensSelector + objectName: "tokensSelector" property int editedIndex: -1 @@ -380,6 +381,7 @@ StatusScrollView { StatusFlowSelector { id: permissionsSelector + objectName: "permissionsSelector" Layout.fillWidth: true @@ -627,6 +629,7 @@ StatusScrollView { Layout.topMargin: Style.current.bigPadding visible: !root.isEditState && root.showChannelSelector + objectName: "createPermissionButton" text: qsTr("Create permission") enabled: root.saveEnabled