test(chore/suite_messaging): Added specific `bdd_hooks` for `suite_messaging/tst_ChatFlow`

- Reviewed `suite_messaging/tst_ChatFlow` feature: Cleanup of duplicated steps and separation of action / validation applied.

- Reviewed `suite_messaging/tst_groupChat` feature.

- Added new tag to `Jenkins` file: `relyon-mailserver`.

- Added new `StartupSteps` class to manage init / startup static methods outside bdd steps. It can be used as a util in `hooks` and `steps`.

Closes #7931
This commit is contained in:
Noelia 2022-10-13 18:03:10 +02:00 committed by Noelia
parent 7706a6caea
commit 728aa00c3c
15 changed files with 826 additions and 615 deletions

View File

@ -115,6 +115,9 @@ pipeline {
--tags
~merge
--tags
~relyon-mailserver
--config
addAUT
nim_status_client

View File

@ -1,19 +1,18 @@
from drivers.SquishDriver import *
from drivers.SquishDriverVerification import *
import drivers.SquishDriver as driver
import drivers.SquishDriverVerification as verification
def start_application(app_name: str):
driver.start_application(app_name)
def click_on_an_object(objName: str):
click_obj_by_name(objName)
driver.click_obj_by_name(objName)
def input_text(text: str, objName: str):
type(objName, text)
driver.type(objName, text)
def object_not_enabled(objName: str):
verify_object_enabled(objName, 500, False)
verification.verify_object_enabled(objName, 500, False)
def str_to_bool(string: str):
return string.lower() in ["yes", "true", "1", "y", "enabled"]

View File

@ -30,6 +30,9 @@ _MIN_WAIT_OBJ_TIMEOUT = 500
_SEARCH_IMAGES_PATH = "../shared/searchImages/"
def start_application(app_name: str):
squish.startApplication(app_name)
# Waits for the given object is loaded, visible and enabled.
# It returns a tuple: True in case it is found. Otherwise, false. And the object itself.
def is_loaded_visible_and_enabled(objName: str, timeout: int=_MAX_WAIT_OBJ_TIMEOUT):

View File

@ -106,6 +106,9 @@ class StatusChatScreen:
verify_screen(ChatComponents.MESSAGE_INPUT.value)
verify_screen(ChatComponents.TOOLBAR_INFO_BUTTON.value)
#####################################
### Screen get states:
#####################################
def chat_loaded(self):
verify(is_displayed(ChatComponents.LAST_MESSAGE.value), "Checking chat is loaded by looking if last message is displayed.")
@ -113,16 +116,18 @@ class StatusChatScreen:
obj = wait_and_get_obj(ChatComponents.CHAT_LOG.value).itemAtIndex(int(index))
return obj
# Screen actions region:
def type_message_in_chat_input(self, message: str):
#####################################
### Screen actions region:
#####################################
def type_message(self, message: str):
type(ChatComponents.MESSAGE_INPUT.value, message)
def press_enter_in_chat_input(self):
def press_enter(self):
press_enter(ChatComponents.MESSAGE_INPUT.value)
def send_message(self, message: str):
self.type_message_in_chat_input(message)
self.press_enter_in_chat_input()
self.type_message(message)
self.press_enter()
def clear_history(self):
click_obj_by_name(ChatComponents.MORE_OPTIONS_BUTTON.value)
@ -167,11 +172,6 @@ class StatusChatScreen:
workflow.cropImage(groupChatUrl)
click_obj_by_name(GroupChatEditPopup.GROUP_CHAT_CROPPER_ACCEPT_BUTTON.value)
# Verifications region:
def verify_last_message_is_not_loaded(self):
[loaded, _] = is_loaded_visible_and_enabled(ChatComponents.LAST_MESSAGE_TEXT.value)
verify_false(loaded, "Success: No message was found")
def send_gif(self):
click_obj_by_name(ChatComponents.GIF_POPUP_BUTTON.value)
click_obj_by_name(ChatComponents.ENABLE_GIF_BUTTON.value)
@ -181,7 +181,139 @@ class StatusChatScreen:
def select_the_emoji_in_suggestion_list(self):
click_obj_by_name(Emoji.EMOJI_SUGGESTIONS_FIRST_ELEMENT.value)
# Verifications region:
def reply_to_message_at_index(self, index: int, message: str):
message_object_to_reply_to = self.get_message_at_index(index)
verify(not is_null(message_object_to_reply_to), "Message to reply to is loaded")
move_mouse_over_object(message_object_to_reply_to)
click_obj_by_name(ChatComponents.REPLY_TO_MESSAGE_BUTTON.value)
self.send_message(message)
def edit_message_at_index(self, index: int, message: str):
message_object_to_edit = get_obj(ChatComponents.CHAT_LOG.value).itemAtIndex(int(index))
hover_obj(message_object_to_edit)
click_obj_by_name(ChatComponents.EDIT_MESSAGE_BUTTON.value)
wait_for_object_and_type(ChatComponents.EDIT_MESSAGE_TEXTAREA.value, "<Ctrl+a>")
type(ChatComponents.EDIT_MESSAGE_TEXTAREA.value, message)
press_enter(ChatComponents.EDIT_MESSAGE_TEXTAREA.value)
def switch_to_chat(self, chatName: str):
chat_lists = get_obj(ChatComponents.CHAT_LIST.value)
verify(chat_lists.count > 0, "At least one chat exists")
for i in range(chat_lists.count):
chat = chat_lists.itemAt(i)
chat_list_items = getChildrenWithObjectName(chat, "chatItem")
verify(len(chat_list_items) > 0, "StatusChatListItem exists")
if str(chat_list_items[0].name) == chatName:
click_obj(chat)
return
verify(False, "Chat switched")
# TODO: Find ADMIN
def find_member_in_panel(self, member: str):
found = False
[is_loaded, membersList] = is_loaded_visible_and_enabled(ChatComponents.MEMBERS_LISTVIEW.value)
if is_loaded:
for index in range(membersList.count):
user = membersList.itemAtIndex(index)
if(user.userName == member):
found = True
break
return found
def delete_message_at_index(self, index: int):
message_object_to_delete = self.get_message_at_index(index)
move_mouse_over_object(message_object_to_delete)
click_obj_by_name(ChatComponents.DELETE_MESSAGE_BUTTON.value)
click_obj_by_name(ChatComponents.CONFIRM_DELETE_MESSAGE_BUTTON.value)
def cannot_delete_last_message(self):
[loaded, last_message_obj] = is_loaded_visible_and_enabled(ChatComponents.LAST_MESSAGE.value)
if not loaded:
verify_failure("No message found")
return
hover_obj(last_message_obj)
object_not_enabled(ChatComponents.DELETE_MESSAGE_BUTTON.value)
def send_message_with_mention(self, displayName: str, message: str):
self.do_mention(displayName)
self.send_message(message)
def cannot_do_mention(self, displayName: str):
self.type_message(_MENTION_SYMBOL + displayName)
displayed = is_displayed(ChatComponents.SUGGESTIONS_BOX.value)
self.press_enter()
verify(displayed == False , "Checking suggestion box is not displayed when trying to mention a non existing user.")
def do_mention(self, displayName: str):
self.type_message(_MENTION_SYMBOL + displayName)
displayed = is_displayed(ChatComponents.SUGGESTIONS_BOX.value)
verify(displayed, "Checking suggestion box displayed when trying to do a mention")
[loaded, suggestions_list] = is_loaded_visible_and_enabled(ChatComponents.SUGGESTIONS_LIST.value)
verify(suggestions_list.count > 0, "Checking if suggestion list is greater than 0")
found = False
if loaded:
for index in range(suggestions_list.count):
user_mention = suggestions_list.itemAtIndex(index)
if user_mention.objectName == displayName:
found = True
click_obj(user_mention)
break
verify(found, "Checking if the following display name is in the mention's list: " + displayName)
def install_sticker_pack(self, pack_index: str):
click_obj_by_name(ChatComponents.CHAT_INPUT_STICKER_BUTTON.value)
click_obj_by_name(ChatStickerPopup.STICKERS_POPUP_GET_STICKERS_BUTTON.value)
# Wait for grid view to be loaded
loaded, grid_view = is_loaded_visible_and_enabled(ChatStickerPopup.STICKERS_POPUP_MARKET_GRID_VIEW.value)
if (not loaded):
verify_failure("Sticker market grid view is not loaded")
# Wait for the items in the GridView to be loaded
verify(is_displayed(ChatStickerPopup.STICKERS_POPUP_MARKET_GRID_VIEW_DELEGATE_ITEM_1.value), "Sticker item 0 is not displayed")
scroll_list_view_at_index(grid_view, int(pack_index))
sticker_pack = grid_view.itemAtIndex(int(pack_index))
click_obj(sticker_pack)
# Install and close
click_obj_by_name(ChatStickerPopup.STICKERS_POPUP_MARKET_INSTALL_BUTTON.value)
click_obj_by_name(ChatStickerPopup.MODAL_CLOSE_BUTTON.value)
verify(sticker_pack.installed == True, "The sticker pack at position " + str(pack_index) + " was not installed")
#Close sticker popup
click_obj_by_name(ChatComponents.CHAT_INPUT_STICKER_BUTTON.value)
def send_sticker(self, sticker_index: int):
click_obj_by_name(ChatComponents.CHAT_INPUT_STICKER_BUTTON.value)
loaded, sticker_list_grid = is_loaded_visible_and_enabled(ChatStickerPopup.STICKER_LIST_GRID.value)
if (not loaded):
verify_failure("Sticker list grid view is not loaded")
sticker = sticker_list_grid.itemAtIndex(int(sticker_index))
click_obj(sticker)
def send_emoji(self, emoji_short_name: str, message: str):
if (message != ""):
self.type_message(message)
click_obj_by_name(ChatComponents.CHAT_INPUT_EMOJI_BUTTON.value)
emojiAttr = copy.deepcopy(getattr(names, ChatComponents.EMOJI_POPUP_EMOJI_PLACEHOLDER.value))
emojiAttr["objectName"] = emojiAttr["objectName"].replace("%NAME%", emoji_short_name)
click_obj_by_attr(emojiAttr)
self.press_enter()
#####################################
### Verifications region:
#####################################
def verify_last_message_is_not_loaded(self):
[loaded, _] = is_loaded_visible_and_enabled(ChatComponents.LAST_MESSAGE_TEXT.value)
verify_false(loaded, "Success: No message was found")
def verify_last_message_sent(self, message: str):
# Get the message text
# We don't search for StatusTextMessage_chatText directly, because there're 2 instances of it in a reply message
@ -266,127 +398,10 @@ class StatusChatScreen:
chat_createChat_text_obj = self.get_message_at_index(ChatMessagesHistory.CHAT_CREATED_TEXT.value)
verify_text_contains(str(chat_createChat_text_obj.messageText), createdTxt)
def reply_to_message_at_index(self, index: int, message: str):
message_object_to_reply_to = self.get_message_at_index(index)
verify(not is_null(message_object_to_reply_to), "Message to reply to is loaded")
move_mouse_over_object(message_object_to_reply_to)
click_obj_by_name(ChatComponents.REPLY_TO_MESSAGE_BUTTON.value)
self.send_message(message)
def edit_message_at_index(self, index: int, message: str):
message_object_to_edit = get_obj(ChatComponents.CHAT_LOG.value).itemAtIndex(int(index))
hover_obj(message_object_to_edit)
click_obj_by_name(ChatComponents.EDIT_MESSAGE_BUTTON.value)
wait_for_object_and_type(ChatComponents.EDIT_MESSAGE_TEXTAREA.value, "<Ctrl+a>")
type(ChatComponents.EDIT_MESSAGE_TEXTAREA.value, message)
press_enter(ChatComponents.EDIT_MESSAGE_TEXTAREA.value)
# TODO: Find ADMIN
def find_member_in_panel(self, member: str):
found = False
[is_loaded, membersList] = is_loaded_visible_and_enabled(ChatComponents.MEMBERS_LISTVIEW.value)
if is_loaded:
for index in range(membersList.count):
user = membersList.itemAtIndex(index)
if(user.userName == member):
found = True
break
return found
def delete_message_at_index(self, index: int):
message_object_to_delete = self.get_message_at_index(index)
move_mouse_over_object(message_object_to_delete)
click_obj_by_name(ChatComponents.DELETE_MESSAGE_BUTTON.value)
click_obj_by_name(ChatComponents.CONFIRM_DELETE_MESSAGE_BUTTON.value)
def cannot_delete_last_message(self):
[loaded, last_message_obj] = is_loaded_visible_and_enabled(ChatComponents.LAST_MESSAGE.value)
if not loaded:
verify_failure("No message found")
return
hover_obj(last_message_obj)
object_not_enabled(ChatComponents.DELETE_MESSAGE_BUTTON.value)
def send_message_with_mention(self, displayName: str, message: str):
self.do_mention(displayName)
self.send_message(message)
def cannot_do_mention(self, displayName: str):
self.chat_loaded()
self.type_message_in_chat_input(_MENTION_SYMBOL + displayName)
displayed = is_displayed(ChatComponents.SUGGESTIONS_BOX.value)
verify(displayed == False , "Checking suggestion box is not displayed when trying to mention a non existing user.")
def do_mention(self, displayName: str):
self.chat_loaded()
self.type_message_in_chat_input(_MENTION_SYMBOL + displayName)
displayed = is_displayed(ChatComponents.SUGGESTIONS_BOX.value)
verify(displayed, "Checking suggestion box displayed when trying to do a mention")
[loaded, suggestions_list] = is_loaded_visible_and_enabled(ChatComponents.SUGGESTIONS_LIST.value)
verify(suggestions_list.count > 0, "Checking if suggestion list is greater than 0")
found = False
if loaded:
for index in range(suggestions_list.count):
user_mention = suggestions_list.itemAtIndex(index)
if user_mention.objectName == displayName:
found = True
click_obj(user_mention)
break
verify(found, "Checking if the following display name is in the mention's list: " + displayName)
def install_sticker_pack(self, pack_index: str):
click_obj_by_name(ChatComponents.CHAT_INPUT_STICKER_BUTTON.value)
click_obj_by_name(ChatStickerPopup.STICKERS_POPUP_GET_STICKERS_BUTTON.value)
# Wait for grid view to be loaded
loaded, grid_view = is_loaded_visible_and_enabled(ChatStickerPopup.STICKERS_POPUP_MARKET_GRID_VIEW.value)
if (not loaded):
verify_failure("Sticker market grid view is not loaded")
# Wait for the items in the GridView to be loaded
verify(is_displayed(ChatStickerPopup.STICKERS_POPUP_MARKET_GRID_VIEW_DELEGATE_ITEM_1.value), "Sticker item 0 is not displayed")
scroll_list_view_at_index(grid_view, int(pack_index))
sticker_pack = grid_view.itemAtIndex(int(pack_index))
click_obj(sticker_pack)
# Install and close
click_obj_by_name(ChatStickerPopup.STICKERS_POPUP_MARKET_INSTALL_BUTTON.value)
click_obj_by_name(ChatStickerPopup.MODAL_CLOSE_BUTTON.value)
verify(sticker_pack.installed == True, "The sticker pack at position " + str(pack_index) + " was not installed")
#Close sticker popup
click_obj_by_name(ChatComponents.CHAT_INPUT_STICKER_BUTTON.value)
def send_sticker(self, sticker_index: int):
click_obj_by_name(ChatComponents.CHAT_INPUT_STICKER_BUTTON.value)
loaded, sticker_list_grid = is_loaded_visible_and_enabled(ChatStickerPopup.STICKER_LIST_GRID.value)
if (not loaded):
verify_failure("Sticker list grid view is not loaded")
sticker = sticker_list_grid.itemAtIndex(int(sticker_index))
click_obj(sticker)
def verify_last_message_is_sticker(self):
last_message_obj = get_obj(ChatComponents.CHAT_LOG.value).itemAtIndex(0)
verify_values_equal(str(last_message_obj.messageContentType), str(MessageContentType.STICKER.value), "The last message is not a sticker")
def send_emoji(self, emoji_short_name: str, message: str):
if (message != ""):
self.type_message_in_chat_input(message)
click_obj_by_name(ChatComponents.CHAT_INPUT_EMOJI_BUTTON.value)
emojiAttr = copy.deepcopy(getattr(names, ChatComponents.EMOJI_POPUP_EMOJI_PLACEHOLDER.value))
emojiAttr["objectName"] = emojiAttr["objectName"].replace("%NAME%", emoji_short_name)
click_obj_by_attr(emojiAttr)
self.press_enter_in_chat_input()
def verify_chat_order(self, index: int, chatName: str):
chat_lists = get_obj(ChatComponents.CHAT_LIST.value)
chat = chat_lists.itemAt(index)
@ -395,18 +410,6 @@ class StatusChatScreen:
verify(len(chat_list_items) > 0, "StatusChatListItem exists")
verify(str(chat_list_items[0].name) == chatName, "Chat in order")
def switch_to_chat(self, chatName: str):
chat_lists = get_obj(ChatComponents.CHAT_LIST.value)
verify(chat_lists.count > 0, "At least one chat exists")
for i in range(chat_lists.count):
chat = chat_lists.itemAt(i)
chat_list_items = getChildrenWithObjectName(chat, "chatItem")
verify(len(chat_list_items) > 0, "StatusChatListItem exists")
if str(chat_list_items[0].name) == chatName:
click_obj(chat)
return
verify(False, "Chat switched")
def _verify_image_unfurled_status_for_component(self, objectName: str, image_link: str, unfurled: bool):
if not unfurled:
verify_false(is_loaded_visible_and_enabled(objectName, 10)[0], "Image link preview component is not loaded")
@ -420,6 +423,3 @@ class StatusChatScreen:
def verify_link_image_unfurled_status(self, image_link: str, unfurled: bool):
self._verify_image_unfurled_status_for_component(ChatComponents.LINK_PREVIEW_UNFURLED_LINK_IMAGE.value, image_link, unfurled)
def open_settings_from_message(self):
click_obj_by_name(ChatComponents.LINK_PREVIEW_OPEN_SETTINGS.value)

View File

@ -4,44 +4,17 @@
sys.path.append(os.path.join(os.path.dirname(__file__), "../../../testSuites/global_shared/"))
sys.path.append(os.path.join(os.path.dirname(__file__), "../../../src/"))
from utils.FileManager import *
_status_desktop_app_name = "nim_status_client"
_status_data_folder_path = "../../../../../Status/data"
_status_qt_path = "../../../../../Status/qt"
_app_closure_timeout = 2 #[seconds]
from steps.startupSteps import *
@OnScenarioStart
def hook(context):
erase_directory(_status_qt_path)
context.userData = {}
context.userData["aut_name"] = _status_desktop_app_name
context.userData["status_data_folder_path"] = _status_data_folder_path
context.userData["fixtures_root"] = os.path.join(os.path.dirname(__file__), "../../../fixtures/")
context.userData["search_images"] = os.path.join(os.path.dirname(__file__), "../shared/searchImages/")
context.userData["scenario_name"] = context._data["title"]
base_path = os.path.join(os.path.dirname(__file__))
split_path = base_path.split("/")
# Remove the last three parts of the path to go back to the fixtures
del split_path[len(split_path) - 1]
del split_path[len(split_path) - 1]
del split_path[len(split_path) - 1]
joined_path = ""
for path_part in split_path:
joined_path += path_part + "/"
context.userData["fixtures_root"] = os.path.join(joined_path, "fixtures/")
context_init(context)
@OnScenarioEnd
def hook(context):
currentApplicationContext().detach()
snooze(_app_closure_timeout)
@OnStepEnd
def hook(context):
context.userData["step_name"] = context._data["text"]

View File

@ -7,10 +7,29 @@ _statusMain = StatusMainScreen()
_settingsScreen = SettingsScreen()
_languageScreen = StatusLanguageScreen()
#########################
### PRECONDITIONS region:
#########################
@Given("the user opens app settings screen")
def step(context: any):
the_user_opens_app_settings_screen()
@Given("the user opens the messaging settings")
def step(context: any):
the_user_opens_the_messaging_settings()
@Given("tenor GIFs preview is enabled")
def step(context: any):
_settingsScreen.check_tenor_gif_preview_is_enabled()
#########################
### ACTIONS region:
#########################
@When("the user opens app settings screen")
def step(context: any):
_statusMain.open_settings()
the_user_opens_app_settings_screen()
@When("the user opens the wallet settings")
def step(context: any):
@ -18,7 +37,7 @@ def step(context: any):
@When("the user opens the messaging settings")
def step(context: any):
_settingsScreen.open_messaging_settings()
the_user_opens_the_messaging_settings()
@When("the user activates link preview")
def step(context: any):
@ -28,10 +47,6 @@ def step(context: any):
def step(context: any):
_settingsScreen.activate_image_unfurling()
@Then("tenor GIFs preview is enabled")
def step(context: any):
_settingsScreen.check_tenor_gif_preview_is_enabled()
@When("the user activates wallet and opens the wallet settings")
def step(context: any):
_settingsScreen.activate_open_wallet_settings()
@ -80,27 +95,11 @@ def step(context, native):
def step(context, native):
_languageScreen.search_language(native)
@Then("the address |any| is displayed in the wallet")
def step(context: any, address: str):
_settingsScreen.verify_address(address)
@Then("the account |any| is not in the list of accounts")
def step(context: any, account_name):
_settingsScreen.verify_no_account(account_name)
@Then("the new account with name |any| and color |any| is updated")
def step(context, new_name: str, new_color: str):
_settingsScreen.verify_editedAccount(new_name, new_color)
@When("the user clicks on Sign out and Quit")
def step(context: any):
ctx = currentApplicationContext()
_settingsScreen.sign_out_and_quit_the_app(ctx.pid)
@Then("the app is closed")
def step(context: any):
_settingsScreen.verify_the_app_is_closed()
@When("the user opens the communities settings")
def step(context: any):
_settingsScreen.open_communities_section()
@ -117,14 +116,66 @@ def step(context: any):
def step(context, display_name):
_settingsScreen.set_display_name(display_name)
@Then("the user's display name should be \"|any|\"")
def step(context, display_name):
_settingsScreen.verify_display_name(display_name)
@When("the user backs up the wallet seed phrase")
def step(context):
_settingsScreen.check_backup_seed_phrase_workflow()
@When("the user sets display links to twitter: \"|any|\", personal site: \"|any|\", \"|any|\": \"|any|\"")
def step(context, twitter, personal_site, custom_link_name, custom_link):
_settingsScreen.set_social_links(twitter, personal_site, custom_link_name, custom_link)
@When("the user sets bio to \"|any|\"")
def step(context, bio):
_settingsScreen.set_bio(bio)
@When("the users switches state to offline")
def step(context: any):
_statusMain.set_user_state_offline()
@When("the users switches state to online")
def step(context: any):
_statusMain.set_user_state_online()
@When("the users switches state to automatic")
def step(context: any):
_statusMain.set_user_state_to_automatic()
@When("the user opens own profile popup")
def step(context: any):
_statusMain.open_own_profile_popup()
@When("in profile popup the user sets display name to \"|any|\"")
def step(context, display_name):
_statusMain.set_profile_popup_display_name(display_name)
@When("the user changes the password from |any| to |any|")
def step(context: any, oldPassword: str, newPassword: str):
_settingsScreen.change_user_password(oldPassword, newPassword)
#########################
### VERIFICATIONS region:
#########################
@Then("the address |any| is displayed in the wallet")
def step(context: any, address: str):
_settingsScreen.verify_address(address)
@Then("the account |any| is not in the list of accounts")
def step(context: any, account_name):
_settingsScreen.verify_no_account(account_name)
@Then("the new account with name |any| and color |any| is updated")
def step(context, new_name: str, new_color: str):
_settingsScreen.verify_editedAccount(new_name, new_color)
@Then("the app is closed")
def step(context: any):
_settingsScreen.verify_the_app_is_closed()
@Then("the user's display name should be \"|any|\"")
def step(context, display_name):
_settingsScreen.verify_display_name(display_name)
@Then("the user's bio should be empty")
def step(context):
_settingsScreen.verify_bio("")
@ -133,10 +184,6 @@ def step(context):
def step(context, bio):
_settingsScreen.verify_bio(bio)
@When("the user sets display links to twitter: \"|any|\", personal site: \"|any|\", \"|any|\": \"|any|\"")
def step(context, twitter, personal_site, custom_link_name, custom_link):
_settingsScreen.set_social_links(twitter, personal_site, custom_link_name, custom_link)
@Then("the user's social links should be empty")
def step(context):
_settingsScreen.verify_social_links("", "", "", "")
@ -151,26 +198,10 @@ def step(context, native):
# TODO: Verify some texts have been changed in the application (not done now bc translations are inconsistent
# and not all expected languages have the same texts translated
@When("the user backs up the wallet seed phrase")
def step(context):
_settingsScreen.check_backup_seed_phrase_workflow()
@Then("the backup seed phrase indicator is not displayed")
def step(context):
_settingsScreen.verify_seed_phrase_indicator_not_visible()
@When("the users switches state to offline")
def step(context: any):
_statusMain.set_user_state_offline()
@When("the users switches state to online")
def step(context: any):
_statusMain.set_user_state_online()
@When("the users switches state to automatic")
def step(context: any):
_statusMain.set_user_state_to_automatic()
@Then("the user appears offline")
def step(context: any):
_statusMain.user_is_offline()
@ -183,18 +214,16 @@ def step(context: any):
def step(context: any):
_statusMain.user_is_set_to_automatic()
@When("the user opens own profile popup")
def step(context: any):
_statusMain.open_own_profile_popup()
@Then("in profile popup the user's display name should be \"|any|\"")
def step(context, display_name):
_statusMain.verify_profile_popup_display_name(display_name)
@When("in profile popup the user sets display name to \"|any|\"")
def step(context, display_name):
_statusMain.set_profile_popup_display_name(display_name)
###########################################################################
### COMMON methods used in different steps given/when/then region:
###########################################################################
@When("the user changes the password from |any| to |any|")
def step(context: any, oldPassword: str, newPassword: str):
_settingsScreen.change_user_password(oldPassword, newPassword)
def the_user_opens_app_settings_screen():
_statusMain.open_settings()
def the_user_opens_the_messaging_settings():
_settingsScreen.open_messaging_settings()

View File

@ -0,0 +1,81 @@
"""It defines starting-up or driving-the-app-into-an-idle-state static methods outside bdd context that can be reused in different `hooks` as well as in specific bdd steps files."""
from utils.FileManager import *
from common.Common import *
from screens.StatusWelcomeScreen import StatusWelcomeScreen
from screens.StatusMainScreen import StatusMainScreen
from screens.StatusChatScreen import StatusChatScreen
# Project settings properties:
_status_desktop_app_name = "nim_status_client"
_status_data_folder_path = "../../../../../Status/data"
_status_fixtures_folder_path = "../../../fixtures/"
_status_shared_images_path = "../shared/searchImages/"
_status_qt_path = "../../../../../Status/qt"
_app_closure_timeout = 2 #[seconds]
# Test context properties names:
_aut_name = "aut_name"
_status_data_folder = "status_data_folder_path"
_fixtures_root = "fixtures_root"
_search_images = "search_images"
_scenario_name = "scenario_name"
# Test static objects creation:
_welcome_screen = StatusWelcomeScreen()
_main_screen = StatusMainScreen()
_chat_screen = StatusChatScreen()
def context_init(context):
erase_directory(_status_qt_path)
context.userData = {}
context.userData[_aut_name] = _status_desktop_app_name
context.userData[_status_data_folder] = _status_data_folder_path
context.userData[_fixtures_root] = os.path.join(os.path.dirname(__file__), _status_fixtures_folder_path)
context.userData[_search_images] = os.path.join(os.path.dirname(__file__), _status_shared_images_path)
context.userData[_scenario_name] = context._data["title"]
base_path = os.path.join(os.path.dirname(__file__))
split_path = base_path.split("/")
# Remove the last three parts of the path to go back to the fixtures
del split_path[len(split_path) - 1]
del split_path[len(split_path) - 1]
del split_path[len(split_path) - 1]
joined_path = ""
for path_part in split_path:
joined_path += path_part + "/"
context.userData[_fixtures_root] = os.path.join(joined_path, "fixtures/")
def given_a_first_time_user_lands_on_and_generates_new_key(context):
erase_directory(context.userData[_status_data_folder])
start_application(context.userData[_aut_name])
_welcome_screen.agree_terms_conditions_and_generate_new_key()
def given_a_first_time_user_lands_on_and_navigates_to_import_seed_phrase(context):
erase_directory(context.userData[_status_data_folder])
start_application(context.userData[_aut_name])
_welcome_screen.agree_terms_conditions_and_navigate_to_import_seed_phrase()
def when_the_user_signs_up(user, password):
_welcome_screen = StatusWelcomeScreen()
_welcome_screen.input_username_and_password_and_finalize_sign_up(user, password)
def when_the_user_lands_on_the_signed_in_app():
_main_screen.is_ready()
def signs_up_process_steps(context, user, password):
given_a_first_time_user_lands_on_and_generates_new_key(context)
when_the_user_signs_up(user, password)
when_the_user_lands_on_the_signed_in_app()
def when_the_user_joins_chat_room(_chat_room):
_main_screen.join_chat_room(_chat_room)
_chat_screen.verify_chat_title(_chat_room)
def when_the_user_opens_the_chat_section():
_main_screen.open_chat_section()

View File

@ -16,41 +16,60 @@
from common.Common import *
import time
from steps.startupSteps import *
from screens.StatusMainScreen import StatusMainScreen
from screens.StatusChatScreen import StatusChatScreen
_statusMain = StatusMainScreen()
_statusChat = StatusChatScreen()
#########################
### PRECONDITIONS region:
#########################
@Given("the user starts the application with a specific data folder |any|")
def step(context, data_folder_path):
waitFor(lambda: currentApplicationContext().detach(), 500)
time.sleep(5)
clear_directory(context.userData["status_data_folder_path"])
copy_directory(data_folder_path, context.userData["status_data_folder_path"])
startApplication(context.userData["aut_name"])
@Given("the user restarts the app")
def step(context):
the_user_restarts_the_app(context)
#########################
### ACTIONS region:
#########################
@When("the user restarts the app")
def step(context):
waitFor(lambda: currentApplicationContext().detach(), 500)
time.sleep(5)
startApplication(context.userData["aut_name"])
the_user_restarts_the_app(context)
@When("user inputs the following |any| with ui-component |any|")
def step(context, text, obj):
input_text(text, obj)
@When("user clicks on the following ui-component |any|")
def step(context, obj):
click_on_an_object(obj)
@When("user joins chat room |any|")
@When("the user joins chat room |any|")
def step(context, room):
_statusMain.join_chat_room(room)
_statusChat.verify_chat_title(room)
when_the_user_joins_chat_room(room)
#########################
### VERIFICATIONS region:
#########################
@Then("the following ui-component |any| is not enabled")
def step(context, obj):
object_not_enabled(obj)
###########################################################################
### COMMON methods used in different steps given/when/then region:
###########################################################################
def the_user_restarts_the_app(context: any):
waitFor(lambda: currentApplicationContext().detach(), 500)
time.sleep(5)
startApplication(context.userData["aut_name"])

View File

@ -1,121 +1,221 @@
from random import randint
from drivers.SquishDriver import *
from steps.startupSteps import *
from screens.StatusMainScreen import StatusMainScreen
from screens.StatusChatScreen import StatusChatScreen
from screens.StatusCreateChatScreen import StatusCreateChatScreen
# Screen's creation:
_statusMain = StatusMainScreen()
_statusChat = StatusChatScreen()
_statusCreateChatView = StatusCreateChatScreen()
@When("the user opens the chat section")
def step(context):
_statusMain.open_chat_section()
#########################
### PRECONDITIONS region:
#########################
@When("the user creates a group chat adding users")
def step(context):
_statusMain.open_start_chat_view()
_statusCreateChatView.create_chat(context.table)
@Given("the user sends a chat message |any|")
def step(context, message):
the_user_sends_a_chat_message(message)
@When("the user clicks on |any| chat")
@Given("the image |any| is not unfurled in the chat")
def step(context: any, image_link: str):
_statusChat.verify_image_unfurled_status(image_link, False)
@Given("the user types |any|")
def step(context, message):
_statusChat.type_message(message)
@Given("the user selects the emoji in the suggestion's list")
def step(contenxt):
_statusChat.select_the_emoji_in_suggestion_list()
@Given("the user installs the sticker pack at position |any|")
def step(context, pack_index):
_statusChat.install_sticker_pack(pack_index)
@Given("the user creates a group chat adding users")
def step(context):
the_user_creates_a_group_chat_adding_users(context)
@Given("the group chat is created")
def step(context):
the_group_chat_is_created()
@Given("the user clicks on |any| chat")
def step(context, chatName):
_statusMain.open_chat(chatName)
@When("the user inputs a mention to |any| with message |any|")
def step(context,displayName,message):
_statusChat.send_message_with_mention(displayName, message)
@Given("the user opens the edit group chat popup")
def step(context):
_statusChat.open_group_chat_edit_popup()
@Given("the user changes the group name to |any|")
def step(context, groupName):
_statusChat.group_chat_edit_name(groupName)
@Given("the user changes the group color to |any|")
def step(context, groupColor):
_statusChat.group_chat_edit_color(groupColor)
@Given("the user changes the group image")
def step(context):
_statusChat.group_chat_edit_image(context.userData["fixtures_root"])
@Given("the group chat history contains \"|any|\" message")
def step(context, createdTxt):
_statusChat.verify_chat_created_message_is_displayed_in_history(createdTxt)
@Given("the group chat contains the following members")
def step(context):
_statusChat.verify_members_added(context.table)
#########################
### ACTIONS region:
#########################
@When("the user opens the chat section")
def step(context):
when_the_user_opens_the_chat_section()
@When("the user sends a chat message |any|")
def step(context, message):
the_user_sends_a_chat_message(message)
@When("the user replies to the message at index |any| with |any|")
def step(context, message_index, message):
_statusChat.reply_to_message_at_index(message_index, message)
@When("the user edits the message at index |any| and changes it to |any|" )
def step(context, message_index, message):
_statusChat.edit_message_at_index(message_index, message)
@When("the user marks the channel |any| as read")
def step(context, channel):
_statusMain.mark_as_read(channel)
@When("the user deletes the message at index |any|")
def step(context, message_index):
_statusChat.delete_message_at_index(message_index)
time.sleep(1)
@When("the user clears chat history")
def step(context):
_statusChat.clear_history()
@When("the user opens the edit group chat popup")
@When("the user sends a GIF message")
def step(context):
_statusChat.open_group_chat_edit_popup()
_statusChat.send_gif()
@When("the user types \"|any|\"")
def step(context, message):
_statusChat.type_message_in_chat_input(message)
@When("the user changes the group name to |any|")
def step(context, groupName):
_statusChat.group_chat_edit_name(groupName)
@When("the user changes the group color to |any|")
def step(context, groupColor):
_statusChat.group_chat_edit_color(groupColor)
@When("the user changes the group image")
@When("the user presses enter")
def step(context):
_statusChat.group_chat_edit_image(context.userData["fixtures_root"])
_statusChat.press_enter()
@When("the user inputs a mention to |any| with message |any|")
def step(context,displayName,message):
_statusChat.send_message_with_mention(displayName, message)
@When("the user sends the emoji |any| as a message")
def step(context, emoji_short_name):
_statusChat.send_emoji(emoji_short_name, "")
@When("the user sends the emoji |any| with message |any|")
def step(context, emoji_short_name, message):
_statusChat.send_emoji(emoji_short_name, message)
# Using position of sticker because stickers don't have ids, only hashes and it feels weird to type hashes in Gherkin
@When("the user sends the sticker at position |any| in the list")
def step(context, sticker_index):
_statusChat.send_sticker(sticker_index)
@When("the user sends a random chat message")
def step(context):
random_int = randint(0, 10000)
message = "random message " + str(random_int)
_statusChat.send_message(message)
context.userData["randomMessage"] = message
@When("the user switches to |any| chat")
def step(context, chatName):
_statusChat.switch_to_chat(chatName)
@When("the user creates a group chat adding users")
def step(context):
the_user_creates_a_group_chat_adding_users(context)
@When("the user saves changes")
def step(context):
_statusChat.group_chat_edit_save()
@When("the user pressed enter")
@When("the user leaves current chat")
def step(context):
_statusChat.press_enter_in_chat_input()
_statusChat.leave_chat()
@Then("user is able to send chat message")
def step(context):
table = context.table
for row in table[1:]:
_statusChat.send_message(row[0])
_statusChat.verify_last_message_sent(row[0])
#########################
### VERIFICATIONS region:
#########################
@Then("The user is able to send a gif message")
def step(context):
_statusChat.send_gif()
_statusChat.verify_last_message_sent("tenor.gif")
@When("the user opens app settings screen from chat")
def step(context):
_statusChat.open_settings_from_message()
@Then("the image |any| is unfurled in the chat")
def step(context: any, image_link: str):
_statusChat.verify_image_unfurled_status(image_link, True)
@Then("the image |any| is not unfurled in the chat")
def step(context: any, image_link: str):
_statusChat.verify_image_unfurled_status(image_link, False)
@Then("the user selects emoji in the suggestion list")
def step(contenxt):
_statusChat.select_the_emoji_in_suggestion_list()
@Then("the user is able to send chat message \"|any|\"")
@Then("the last chat message contains |any|")
def step(context, message):
_statusChat.send_message(message)
@When("the user sends the chat message |any|")
def step(context, message):
_statusChat.send_message(message)
_statusChat.verify_last_message_sent(message)
@Then("the user is able to send a random chat message")
def step(context):
random_int = randint(0, 10000)
message = "random message " + str(random_int)
_statusChat.send_message(message)
@Then("the chat message |any| is displayed as a reply")
def step(context, message):
# TODO: Check the last message is really a reply.
_statusChat.verify_last_message_sent(message)
context.userData["randomMessage"] = message
@Then("the chat message |any| is displayed as an edited one")
def step(context, message):
# TODO: Check last message is an edited one.
_statusChat.verify_last_message_sent(message)
@Then("the last message displayed is not |any|")
def step(context, message):
_statusChat.verify_last_message_sent_is_not(message)
@Then("the chat is cleared")
def step(context):
_statusChat.verify_last_message_is_not_loaded()
@Then("the GIF message is displayed")
def step(context):
# TODO: It should be a specific verification call instead of adding here a string (Screen layer responsibility)
_statusChat.verify_last_message_sent("tenor.gif")
@Then("the image |any| is unfurled in the chat")
def step(context: any, image_link: str):
_statusChat.verify_image_unfurled_status(image_link, True)
@Then("the user cannot delete the last message")
def step(context):
_statusChat.cannot_delete_last_message()
@Then("the |any| mention with message |any| have been sent")
def step(context,displayName,message):
_statusChat.verify_last_message_sent_contains_mention(displayName, message)
@Then("the user cannot input a mention to a not existing user |any|")
def step(context, displayName):
_statusChat.cannot_do_mention(displayName)
@Then("the last chat message is a sticker")
def step(context):
_statusChat.verify_last_message_is_sticker()
@Then("the user chats are sorted accordingly")
def step(context):
table = context.table
for i, row in enumerate(table):
chatName = row[0]
_statusChat.verify_chat_order(i, chatName)
@Then("the random chat message is displayed")
def step(context):
message = context.userData["randomMessage"]
_statusChat.verify_last_message_sent(message)
@Then("the group chat is created")
def step(context):
_statusChat = StatusChatScreen()
@Then("the group chat history contains \"|any|\" message")
def step(context, createdTxt):
_statusChat.verify_chat_created_message_is_displayed_in_history(createdTxt)
the_group_chat_is_created()
@Then("the chat title is |any|")
def step(context, title):
@ -129,95 +229,20 @@ def step(context, color):
def step(context):
_statusChat.verify_chat_image(context.userData["fixtures_root"])
@Then("the group chat contains the following members")
def step(context):
_statusChat.verify_members_added(context.table)
@Then("the group chat is up to chat sending \"|any|\" message")
def step(context, message):
_statusChat.send_message(message)
_statusChat.verify_last_message_sent(message)
@Then("the user can reply to the message at index |any| with \"|any|\"")
def step(context, message_index, message):
_statusChat.reply_to_message_at_index(message_index, message)
_statusChat.verify_last_message_sent(message)
@When("the user edits the message at index |any| and changes it to \"|any|\"" )
def step(context, message_index, message):
_statusChat.edit_message_at_index(message_index, message)
_statusChat.verify_last_message_sent(message)
@Then("the user can mark the channel |any| as read")
def step(context, channel):
_statusMain.mark_as_read(channel)
@Then("the user can delete the message at index |any|")
def step(context, message_index):
_statusChat.delete_message_at_index(message_index)
time.sleep(1)
@Then("the user cannot delete the last message")
def step(context):
_statusChat.cannot_delete_last_message()
@Then("the last message is not \"|any|\"")
def step(context, message):
_statusChat.verify_last_message_sent_is_not(message)
@Then("the last message is not the random message")
def step(context):
_statusChat.verify_last_message_sent_is_not(context.userData["randomMessage"])
@When("user sends the emoji |any| as a message")
def step(context, emoji_short_name):
_statusChat.send_emoji(emoji_short_name, "")
@When("user sends the emoji |any| with message |any|")
def step(context, emoji_short_name, message):
_statusChat.send_emoji(emoji_short_name, message)
@Then("the emoji |any| is displayed in the last message")
def step(context, emoji):
_statusChat.verify_last_message_sent(emoji)
@Then("the message |any| is displayed in the last message")
def step(context, message):
_statusChat.verify_last_message_sent(message)
@Then("the user can install the sticker pack at position |any|")
def step(context, pack_index):
_statusChat.install_sticker_pack(pack_index)
# Using position of sticker because stickers don't have ids, only hashes and it feels weird to type hashes in Gherkin
@Then("the user can send the sticker at position |any| in the list")
def step(context, sticker_index):
_statusChat.send_sticker(sticker_index)
@Then("the user cannot input a mention to a not existing user |any|")
def step(context, displayName):
_statusChat.cannot_do_mention(displayName)
@Then("the |any| mention with message |any| have been sent")
def step(context,displayName,message):
_statusChat.verify_last_message_sent_contains_mention(displayName, message)
@Then("user chats are sorted accordingly")
def step(context):
table = context.table
for i, row in enumerate(table):
chatName = row[0]
_statusChat.verify_chat_order(i, chatName)
@When("user switches to |any| chat")
def step(context, chatName):
_statusChat.switch_to_chat(chatName)
@When("the user leaves current chat")
def step(context):
_statusChat.leave_chat()
@Then("chat |any| does not exist")
@Then("the chat |any| does not exist")
def step(context, chatName):
_statusMain.verify_chat_does_not_exist(chatName)
###########################################################################
### COMMON methods used in different steps given/when/then region:
###########################################################################
def the_user_sends_a_chat_message(message: str):
_statusChat.send_message(message)
def the_user_creates_a_group_chat_adding_users(context: any):
_statusMain.open_start_chat_view()
_statusCreateChatView.create_chat(context.table)
def the_group_chat_is_created():
_statusChat = StatusChatScreen()

View File

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# This file contains hook functions to run as the .feature file is executed
sys.path.append(os.path.join(os.path.dirname(__file__), "../../../testSuites/global_shared/"))
sys.path.append(os.path.join(os.path.dirname(__file__), "../../../src/"))
from steps.startupSteps import *
# Global properties for the specific feature
_user = "tester123"
_password = "TesTEr16843/!@00"
_chat_room = "test"
@OnFeatureStart
def hook(context):
context_init(context)
signs_up_process_steps(context, _user, _password)
when_the_user_joins_chat_room(_chat_room)
@OnFeatureEnd
def hook(context):
currentApplicationContext().detach()
snooze(_app_closure_timeout)
@OnScenarioStart
def hook(context):
when_the_user_opens_the_chat_section()
@OnStepEnd
def hook(context):
context.userData["step_name"] = context._data["text"]

View File

@ -1,169 +1,175 @@
# This is a sample .feature file
# Squish feature files use the Gherkin language for describing features, a short example
# is given below. You can find a more extensive introduction to the Gherkin format at
# https://cucumber.io/docs/gherkin/reference/
Feature: Status Desktop Chat
Feature: Status Desktop Chat Basic Flows
# TODO The complete feature / all scenarios have a chance to fail since they rely on the mailserver (at least, to verify a chat is loaded, something in the history needs to be displayed).
As a user I want to join a room and chat and do basic interactions.
As a user I want to join the public chat room "test" and do basic interactions.
The following scenarios cover basic chat flows.
The following scenarios cover basic chat flows on "test" public channel.
Background:
Given A first time user lands on the status desktop and generates new key
When user signs up with username tester123 and password TesTEr16843/!@00
Then the user lands on the signed in app
The feature start sequence is the following (setup on its own `bdd_hooks`):
** given A first time user lands on the status desktop and generates new key
** when user signs up with username "tester123" and password "TesTEr16843/!@00"
** and the user lands on the signed in app
** and user joins chat room "test"
Scenario: User joins a public room and chats
When user joins chat room test
Then user is able to send chat message
[Cleanup] Also each scenario starts with:
** when the user opens the chat section
# TODO: Add scenario end -> clear chat input.
Scenario Outline: The user can chat in a public room
When the user sends a chat message <message>
Then the last chat message contains <message>
Examples:
| message |
| Hello |
| How are you |
| I am from status |
| tell me how you do? |
@merge
Scenario: User can reply to their own message
When user joins chat room test
Then the user is able to send a random chat message
Then the user can reply to the message at index 0 with "This is a reply"
# TODO: Scenario: The user can reply to their OWN message
@mayfail
# TODO: It works standalone but when it runs as part of the sequence, the action of reply is not done always. The popup option does not appear.
Scenario Outline: The user can reply to the last message
Given the user sends a chat message <message>
When the user replies to the message at index 0 with <reply>
# TODO: Check the last message is really a reply, now just checking the last message is the expected one but could not be a reply. The popup option does not appear.
Then the chat message <reply> is displayed as a reply
Examples:
| message | reply |
| random chat message | This is a reply |
@merge
Scenario: User can edit a message
When user joins chat room test
Then user is able to send chat message
@mayfail
# TODO: It works standalone but when it runs as part of the sequence, the action of edit is not done always. The popup option does not appear.
Scenario Outline: The user can edit a message
Given the user sends a chat message <message>
When the user edits the message at index 0 and changes it to <edited>
# TODO: Check last message is an edited one, now just checking the last message is the expected one but could not be an edited one.
Then the chat message <edited> is displayed as an edited one
Examples:
| message | edited |
| Edit me | Edited by me |
@relyon-mailserver
Scenario Outline: The user can reply to another message
When the user replies to the message at index 0 with <reply>
Then the chat message <reply> is displayed as a reply
Examples:
| reply |
| This is a reply |
# TODO: This scenario should be extracted to a different feature file bc it doesn't accomplish the background steps since it needs to change/specify the chat room
# Scenario Outline: The user joins a room and marks it as read
# When the user joins chat room test
# And the user marks the channel <channel> as read
# # TODO find a way to validate that it worked
# Examples:
# | channel |
# | test |
@mayfail
# TODO: It works standalone but when it runs as part of the sequence, the action of delete is not done always. The popup option does not appear.
Scenario Outline: The user can delete his/her own message
Given the user sends a chat message <message>
When the user deletes the message at index 0
Then the last message displayed is not <message>
Examples:
| message |
| Edit me |
When the user edits the message at index 0 and changes it to "Edited by me"
Then the message (edited) is displayed in the last message
| random chat message |
@mayfail @merge
Scenario: User can reply to another user's message
When user joins chat room test
Then the user can reply to the message at index 0 with "This is a reply to another user"
@mayfail @merge
Scenario: User joins a room and marks it as read
When user joins chat room test
Then the user can mark the channel test as read
# TODO find a way to validate that it worked
@merge
Scenario: User can delete their own message
When user joins chat room automation-test
Then the user is able to send a random chat message
Then the user can delete the message at index 0
Then the last message is not the random message
@merge
Scenario: User can clear chat history
When user joins chat room test
Then user is able to send chat message
| message |
| Hello |
| How are you |
| I am from status |
| tell me how you do? |
Scenario: The user can clear chat history
Given the user sends a chat message Hi hi
And the user sends a chat message testing chat
And the user sends a chat message history
When the user clears chat history
Then the chat is cleared
@mayfail @merge
Scenario: User can send a gif
When the user opens the chat section
And user joins chat room automation-test
Then The user is able to send a gif message
When the user opens app settings screen
@mayfail
# TODO: Verification of gif sent fails. And also `tenor GIFs preview is enabled` step doesn't work. Review it.
Scenario: The user can send a GIF
Given the user opens app settings screen
And the user opens the messaging settings
Then tenor GIFs preview is enabled
And tenor GIFs preview is enabled
When the user sends a GIF message
Then the GIF message is displayed
@mayfail @merge
Scenario Outline: User can activate image unfurling
When the user opens the chat section
And user joins chat room automation-test
And the user sends the chat message <image_url>
Then the image <image_url> is not unfurled in the chat
When the user opens app settings screen from chat
@mayfail
# TODO: It works standalone but when it runs as part of the sequence, the action of activates link preview doesn't work.
Scenario Outline: The user can activate image unfurling
Given the user sends a chat message <image_url>
And the image <image_url> is not unfurled in the chat
When the user opens app settings screen
And the user opens the messaging settings
And the user activates link preview
And the user activates image unfurling
And the user opens the chat section
Then the image <image_url> is unfurled in the chat
Examples:
| image_url |
| https://github.com/status-im/status-desktop/raw/master/test/ui-test/fixtures/images/doggo.jpeg |
@mayfail @merge
Scenario: The user is able to use emoji suggestions
When user joins chat room automation-test
When the user types "hello :thumbs"
Then the user selects emoji in the suggestion list
When the user pressed enter
Then the message 👍 is displayed in the last message
Scenario Outline: The user is able to use emoji suggestions
Given the user types <message>
And the user selects the emoji in the suggestion's list
When the user presses enter
Then the last chat message contains <emoji>
Examples:
| message | emoji |
| hello :thumbs | 👍 |
@mayfail @merge
Scenario: User cannot delete another user's message
When user joins chat room test
@relyon-mailserver
Scenario: The user cannot delete another user's message
Then the user cannot delete the last message
@mayfail @merge
@relyon-mailserver
Scenario Outline: The user can do a mention
When user joins chat room test
And the user inputs a mention to <displayName> with message <message>
When the user inputs a mention to <displayName> with message <message>
Then the <displayName> mention with message <message> have been sent
Examples:
| displayName | message |
| tester123 | testing mention |
@mayfail @merge
Scenario Outline: The user can not do a mention to not existing users
When user joins chat room test
@relyon-mailserver
Scenario Outline: The user can not do a mention to a not existing users
Then the user cannot input a mention to a not existing user <displayName>
Examples:
| displayName |
| notExistingAccount |
| asdfgNoNo |
@mayfail @merge
Scenario: User can send an emoji in a message
When user joins chat room automation-test
When user sends the emoji heart_eyes as a message
Then the emoji 😍 is displayed in the last message
When user sends the emoji sunglasses with message wow I'm so cool
Then the emoji 😎 is displayed in the last message
And the message wow I'm so cool is displayed in the last message
Scenario: The user can send an emoji as a message
When the user sends the emoji heart_eyes as a message
Then the last chat message contains 😍
@merge
Scenario: User sees chats sorted by most recent activity
When user joins chat room first-chat
And user joins chat room second-chat
And user joins chat room third-chat
Then user chats are sorted accordingly
| third-chat |
| second-chat |
| first-chat |
When user switches to second-chat chat
Then the user is able to send a random chat message
And user chats are sorted accordingly
| second-chat |
| third-chat |
| first-chat |
Scenario Outline: The user can send an emoji in a message
When the user sends the emoji sunglasses with message <message>
Then the last chat message contains 😎
And the last chat message contains <message>
Examples:
| message |
| wow I'm so cool |
@mayfail @merge
Scenario: User can type message with emoji autoreplace
When user joins chat room automation-test
Then the user is able to send chat message "Hello :)"
Then the message 🙂 is displayed in the last message
And the message Hello is displayed in the last message
# TODO: This scenario should be extracted to a different feature file bc it doesn't accomplish the background steps since it needs to change/specify the chat room
# @merge
# Scenario: The user sees chats sorted by most recent activity
# When the user joins chat room first-chat
# And the user joins chat room second-chat
# And the user joins chat room third-chat
# Then the user chats are sorted accordingly
# | third-chat |
# | second-chat |
# | first-chat |
# When the user switches to second-chat chat
# And the user sends a random chat message
# Then the random chat message is displayed
# And the user chats are sorted accordingly
# | second-chat |
# | third-chat |
# | first-chat |
Scenario: The user can type message with emoji autoreplace
When the user sends a chat message Hello :)
Then the last chat message contains 🙂
And the last chat message contains Hello
@merge
Scenario: User can send a sticker after installing a free pack
When user joins chat room automation-test
Then the user can install the sticker pack at position 4
Then the user can send the sticker at position 2 in the list
Scenario: The user can send a sticker after installing a free pack
Given the user installs the sticker pack at position 4
When the user sends the sticker at position 2 in the list
Then the last chat message is a sticker

View File

@ -1,6 +1,6 @@
source(findFile('scripts', 'python/bdd.py'))
setupHooks('../../global_shared/scripts/bdd_hooks.py')
setupHooks('bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/')
def main():

View File

@ -2,63 +2,72 @@ Feature: Status Desktop Group Chat
As a user I want to use group chat functionality.
The feature start sequence follows the global one (setup on global `bdd_hooks`):
Background:
Given the user starts the application with a specific data folder ../../../fixtures/group_chat
When the user tester123 logs in with password TesTEr16843/!@00
Then the user lands on the signed in app
@mayfail
Scenario: As an admin user I want to create a group chat with my contacts and the invited users can send messages
@relyon-mailserver
Scenario Outline: As an admin user I want to create a group chat with my contacts and the invited users can send messages
When the user creates a group chat adding users
Given the user creates a group chat adding users
| Athletic |
| Nervous |
Then the group chat is created
And the group chat is created
And the group chat history contains "created the group" message
And the chat title is Athletic&Nervous
And the group chat contains the following members
| Athletic |
| Nervous |
And the group chat is up to chat sending "Admin user message sent" message
When the user sends a chat message <message1>
Then the chat title is Athletic&Nervous
And the last chat message contains <message1>
# Invited user 1
When the user restarts the app
Given the user restarts the app
And the user Nervous logs in with password TesTEr16843/!@00
Then the user lands on the signed in app
When the user clicks on Athletic&Nervous chat
Then the group chat is up to chat sending "Invited user 1 message sent!!" message
And the user lands on the signed in app
And the user clicks on Athletic&Nervous chat
When the user sends a chat message <message2>
Then the last chat message contains <message2>
# Invited user 2
When the user restarts the app
Given the user restarts the app
And the user Athletic logs in with password TesTEr16843/!@00
Then the user lands on the signed in app
When the user clicks on Athletic&Nervous chat
Then the group chat is up to chat sending "Invited user 2 message sent!!" message
And the user lands on the signed in app
And the user clicks on Athletic&Nervous chat
When the user sends a chat message <message3>
Then the last chat message contains <message3>
Examples:
| message1 | message2 | message3 |
| Admin user message sent | Invited user 1 message sent!! | Invited user 2 message sent!! |
# TODO: Add cleanup scenario. Leave, one by one, the chat
@mayfail @merge
Scenario: As an admin user I want to change group chat's name, color and image
When the user creates a group chat adding users
| Athletic |
| Nervous |
Then the group chat is created
When the user opens the edit group chat popup
Given the user opens the edit group chat popup
And the user changes the group name to Fat&Lazy
And the user saves changes
When the user saves changes
Then the chat title is Fat&Lazy
When the user opens the edit group chat popup
Given the user opens the edit group chat popup
And the user changes the group color to #7CDA00
And the user saves changes
When the user saves changes
Then the chat color is #7CDA00
When the user opens the edit group chat popup
Given the user opens the edit group chat popup
And the user changes the group image
And the user saves changes
When the user saves changes
Then the chat image is changed
When the user leaves current chat
Then chat Fat&Lazy does not exist
Then the chat Fat&Lazy does not exist

View File

@ -2,10 +2,31 @@ from screens.StatusLoginScreen import StatusLoginScreen
_loginScreen = StatusLoginScreen()
#########################
### PRECONDITIONS region:
#########################
@Given("the user |any| logs in with password |any|")
def step(context, username, password):
the_user_any_logs_in_with_password(username, password)
#########################
### ACTIONS region:
#########################
@When("the user |any| logs in with password |any|")
def step(context, username, password):
_loginScreen.login(username, password)
the_user_any_logs_in_with_password(username, password)
#########################
### VERIFICATIONS region:
#########################
@Then("the user is NOT able to login to Status Desktop application")
def step(context):
_loginScreen.verify_error_message_is_displayed()
###########################################################################
### COMMON methods used in different steps given/when/then region:
###########################################################################
def the_user_any_logs_in_with_password(username: str, password: str):
_loginScreen.login(username, password)

View File

@ -1,29 +1,33 @@
from steps.startupSteps import *
from screens.StatusWelcomeScreen import StatusWelcomeScreen
from screens.StatusMainScreen import StatusMainScreen
_welcomeScreen = StatusWelcomeScreen()
_mainScreen = StatusMainScreen()
#########################
### PRECONDITIONS region:
#########################
@Given("A first time user lands on the status desktop and generates new key")
def step(context):
erase_directory(context.userData["status_data_folder_path"])
startApplication(context.userData["aut_name"])
_welcomeScreen.agree_terms_conditions_and_generate_new_key()
given_a_first_time_user_lands_on_and_generates_new_key(context)
@Given("A first time user lands on the status desktop and navigates to import seed phrase")
def step(context):
erase_directory(context.userData["status_data_folder_path"])
startApplication(context.userData["aut_name"])
_welcomeScreen.agree_terms_conditions_and_navigate_to_import_seed_phrase()
given_a_first_time_user_lands_on_and_navigates_to_import_seed_phrase(context)
@Given("the user lands on the signed in app")
def step(context):
when_the_user_lands_on_the_signed_in_app()
#########################
### ACTIONS region:
#########################
@When("user signs up with username |any| and password |any|")
def step(context, username, password):
_welcomeScreen.input_username_and_password_and_finalize_sign_up(username, password)
when_the_user_signs_up(username, password)
@When("the user inputs username |any|")
def step(context, username):
@ -33,26 +37,34 @@ def step(context, username):
def step(context, seed_phrase):
_welcomeScreen.input_seed_phrase(seed_phrase)
@When("the user logs in with password |any|")
def step(context, password: str):
_welcomeScreen.enter_password(password)
@When("the user signs up with profileImage |any|, username |any| and password |any|")
def step(context, profileImageUrl, username, password):
_welcomeScreen.input_username_profileImage_password_and_finalize_sign_up("file:///"+context.userData["fixtures_root"]+"images/"+profileImageUrl, username, password)
@When("a screenshot of the profileImage is taken")
def step(context):
_welcomeScreen.grab_screenshot()
#########################
### VERIFICATIONS region:
#########################
@Then("the user lands on the signed in app")
def step(context):
_mainScreen.is_ready()
when_the_user_lands_on_the_signed_in_app()
@Then("the invalid seed text is visible")
def step(context):
_welcomeScreen.seed_phrase_visible()
@When("the user logs in with password |any|")
def step(context, password: str):
_welcomeScreen.enter_password(password)
@Then("the user is online")
def step(context):
_mainScreen.user_is_online()
@When("the user signs up with profileImage |any|, username |any| and password |any|")
def step(context, profileImageUrl, username, password):
_welcomeScreen.input_username_profileImage_password_and_finalize_sign_up("file:///"+context.userData["fixtures_root"]+"images/"+profileImageUrl, username, password)
@Then("my profile modal has the updated profile image")
def step(context):
_welcomeScreen.profile_modal_image_is_updated()
@ -61,13 +73,13 @@ def step(context):
def step(context):
_welcomeScreen.profile_settings_image_is_updated()
@When("a screenshot of the profileImage is taken")
def step(context):
_welcomeScreen.grab_screenshot()
@Then("the profile navigation bar has the updated profile image")
def step(context):
_welcomeScreen.profile_image_is_updated()
delete_created_searchImage(context.userData["search_images"] +"profiletestimage.png")
delete_created_searchImage(context.userData["search_images"]+"loginUserName.png")
###########################################################################
### COMMON methods used in different steps given/when/then region:
###########################################################################