diff --git a/test/ui-test/src/constants/__init__.py b/test/ui-test/src/constants/__init__.py new file mode 100644 index 0000000000..6ff53662c3 --- /dev/null +++ b/test/ui-test/src/constants/__init__.py @@ -0,0 +1,2 @@ +from . import user_account +from . import wallet diff --git a/test/ui-test/src/constants/user_account.py b/test/ui-test/src/constants/user_account.py new file mode 100644 index 0000000000..b656a670dd --- /dev/null +++ b/test/ui-test/src/constants/user_account.py @@ -0,0 +1,2 @@ +LOGIN = '' +PASSWORD = 'TesTEr16843/!@00' diff --git a/test/ui-test/src/constants/wallet.py b/test/ui-test/src/constants/wallet.py new file mode 100644 index 0000000000..6e87919cf6 --- /dev/null +++ b/test/ui-test/src/constants/wallet.py @@ -0,0 +1,14 @@ +from collections import namedtuple +from enum import Enum + +DEFAULT_ACCOUNT_NAME = 'Status account' + +account_list_item = namedtuple('AccountListItem', ['name', 'color', 'emoji']) + + +class DerivationPath(Enum): + CUSTOM = 'Custom' + ETHEREUM = 'Ethereum' + ETHEREUM_ROPSTEN = 'Ethereum Testnet (Ropsten)' + ETHEREUM_LEDGER = 'Ethereum (Ledger)' + ETHEREUM_LEDGER_LIVE = 'Ethereum (Ledger Live/KeepKey)' diff --git a/test/ui-test/src/drivers/SquishDriver.py b/test/ui-test/src/drivers/SquishDriver.py index fcdc849f80..f1ff0e0098 100755 --- a/test/ui-test/src/drivers/SquishDriver.py +++ b/test/ui-test/src/drivers/SquishDriver.py @@ -12,8 +12,10 @@ import sys import test import time +import configs import names import object +import objectMap # IMPORTANT: It is necessary to import manually the Squish drivers module by module. # More info in: https://kb.froglogic.com/display/KB/Article+-+Using+Squish+functions+in+your+own+Python+modules+or+packages import squish @@ -503,9 +505,13 @@ def sleep_test(seconds: float): squish.snooze(seconds) -def wait_for(py_condition_to_check: str, timeout_msec: int = 500) -> bool: +def wait_for(py_condition_to_check, timeout_msec: int = configs.squish.UI_LOAD_TIMEOUT_MSEC) -> bool: return squish.waitFor(lambda: py_condition_to_check, timeout_msec) def wait_until_hidden(object_name: str, timeout_msec: int = _MAX_WAIT_OBJ_TIMEOUT) -> bool: return squish.waitFor(lambda: not is_displayed(object_name), timeout_msec) + + +def get_real_name(obj): + return objectMap.realName(obj) diff --git a/test/ui-test/src/drivers/elements/__init__.py b/test/ui-test/src/drivers/elements/__init__.py index 58e7ce6ef7..c469ea1563 100755 --- a/test/ui-test/src/drivers/elements/__init__.py +++ b/test/ui-test/src/drivers/elements/__init__.py @@ -1,5 +1,8 @@ from .base_element import BaseElement from .button import Button +from .checkbox import CheckBox +from .list import List +from .menu import Menu from .scroll import Scroll from .text_edit import TextEdit from .text_label import TextLabel diff --git a/test/ui-test/src/drivers/elements/base_element.py b/test/ui-test/src/drivers/elements/base_element.py index 2964d8eb7b..7c858dc44f 100644 --- a/test/ui-test/src/drivers/elements/base_element.py +++ b/test/ui-test/src/drivers/elements/base_element.py @@ -4,24 +4,26 @@ import configs import names import object import squish +from utils.decorators import attempt class BaseElement: def __init__(self, object_name): self.symbolic_name = object_name - self.object_name = getattr(names, object_name) - - def __str__(self): - return f'{type(self).__qualname__}({self.symbolic_name})' + self.object_name = getattr(names, object_name, object_name) + self._object_name_updates = {} + + def __str__(self): + return f'{type(self).__qualname__}({self.symbolic_name})' @property def object(self): - return squish.waitForObject(self.object_name) - + return squish.waitForObject(self.object_name, configs.squish.UI_LOAD_TIMEOUT_MSEC) + @property def existent(self): - return squish.waitForObjectExists(self.object_name) + return squish.waitForObjectExists(self.object_name, configs.squish.UI_LOAD_TIMEOUT_MSEC) @property def bounds(self) -> squish.UiTypes.ScreenRectangle: @@ -43,6 +45,10 @@ class BaseElement: def is_selected(self) -> bool: return self.object.selected + @property + def is_checked(self) -> bool: + return self.object.checked + @property def is_visible(self) -> bool: try: @@ -50,6 +56,7 @@ class BaseElement: except (AttributeError, LookupError, RuntimeError): return False + @attempt(2) def click( self, x: typing.Union[int, squish.UiTypes.ScreenPoint] = None, @@ -60,12 +67,26 @@ class BaseElement: self.object, x or self.width // 2, y or self.height // 2, - button or squish.MouseButton.LeftButton + button or squish.Qt.LeftButton + ) + + def hover(self): + squish.mouseMove(self.center.x, self.center.y) + + def open_context_menu( + self, + x: typing.Union[int, squish.UiTypes.ScreenPoint] = None, + y: typing.Union[int, squish.UiTypes.ScreenPoint] = None, + ): + self.click( + x or self.width // 2, + y or self.height // 2, + squish.Qt.RightButton ) @property def is_enabled(self) -> bool: - return self.object.enabled + return self.object.enabled def wait_until_appears(self, timeout_msec: int = configs.squish.UI_LOAD_TIMEOUT_MSEC): assert squish.waitFor(lambda: self.is_visible, timeout_msec), f'Object {self} is not visible' diff --git a/test/ui-test/src/drivers/elements/checkbox.py b/test/ui-test/src/drivers/elements/checkbox.py new file mode 100644 index 0000000000..b4f96fab31 --- /dev/null +++ b/test/ui-test/src/drivers/elements/checkbox.py @@ -0,0 +1,13 @@ +import configs +import squish + +from .base_element import BaseElement + + +class CheckBox(BaseElement): + + def set(self, value: bool, x: int = None, y: int = None): + if self.is_checked is not value: + self.click(x, y) + assert squish.waitFor( + lambda: self.is_checked is value, configs.squish.UI_LOAD_TIMEOUT_MSEC), 'Value not changed' diff --git a/test/ui-test/src/drivers/elements/list.py b/test/ui-test/src/drivers/elements/list.py new file mode 100644 index 0000000000..a6635017e0 --- /dev/null +++ b/test/ui-test/src/drivers/elements/list.py @@ -0,0 +1,18 @@ +import squish + +from .base_element import BaseElement + + +class List(BaseElement): + + @property + def items(self): + return [self.object.itemAtIndex(index) for index in range(self.object.count)] + + def select(self, attribute_value: str, attribute_name: str = 'text'): + for index in range(self.object.count): + list_item = self.object.itemAt(index) + if str(getattr(list_item, attribute_value, '')) == attribute_name: + squish.mouseClick(list_item) + return + raise LookupError(f'List item: {attribute_value}:{attribute_name} not found in {self.items}') diff --git a/test/ui-test/src/drivers/elements/menu.py b/test/ui-test/src/drivers/elements/menu.py new file mode 100644 index 0000000000..1f71abc886 --- /dev/null +++ b/test/ui-test/src/drivers/elements/menu.py @@ -0,0 +1,11 @@ +import configs +import squish + +from .base_element import BaseElement + + +class Menu(BaseElement): + + def select(self, menu_item: str): + squish.activateItem(squish.waitForObjectItem(self.object_name, menu_item, configs.squish.UI_LOAD_TIMEOUT_MSEC)) + self.wait_until_hidden() diff --git a/test/ui-test/src/drivers/elements/scroll.py b/test/ui-test/src/drivers/elements/scroll.py index 1de41d3cfb..3e4ac45d24 100644 --- a/test/ui-test/src/drivers/elements/scroll.py +++ b/test/ui-test/src/drivers/elements/scroll.py @@ -18,3 +18,11 @@ class Scroll(BaseElement): time.sleep(0.1) if time.monotonic() - started_at > timeout_sec: raise LookupError(f'Object not found: {element.object_name}') + + def vertical_down_to(self, element: BaseElement, timeout_sec: int = 5): + started_at = time.monotonic() + step = 100 + while not element.is_visible: + squish.flick(self.object, 0, step) + if time.monotonic() - started_at > timeout_sec: + raise LookupError(f'Object not found: {element.object_name}') \ No newline at end of file diff --git a/test/ui-test/src/drivers/elements/text_edit.py b/test/ui-test/src/drivers/elements/text_edit.py index 6b4ce131da..8031825412 100644 --- a/test/ui-test/src/drivers/elements/text_edit.py +++ b/test/ui-test/src/drivers/elements/text_edit.py @@ -1,3 +1,4 @@ +import configs import squish from .base_element import BaseElement @@ -13,17 +14,17 @@ class TextEdit(BaseElement): def text(self, value: str): self.clear() self.type_text(value) - assert squish.waitFor(lambda: self.text == value) + assert squish.waitFor(lambda: self.text == value, configs.squish.UI_LOAD_TIMEOUT_MSEC), \ + f'Type text failed, value in field: "{self.text}", expected: {value}' def type_text(self, value: str): self.click() squish.type(self.object, value) - assert squish.waitFor(lambda: self.text == value), \ - f'Type text failed, value in field: "{self.text}", expected: {value}' return self - def clear(self): + def clear(self, verify: bool = True): self.object.clear() - assert squish.waitFor(lambda: not self.text), \ - f'Field did not cleared, value in field: "{self.text}"' + if verify: + assert squish.waitFor(lambda: not self.text, configs.squish.UI_LOAD_TIMEOUT_MSEC), \ + f'Field did not cleared, value in field: "{self.text}"' return self diff --git a/test/ui-test/src/screens/StatusWalletScreen.py b/test/ui-test/src/screens/StatusWalletScreen.py index 676b566bee..756213f5a3 100644 --- a/test/ui-test/src/screens/StatusWalletScreen.py +++ b/test/ui-test/src/screens/StatusWalletScreen.py @@ -1,66 +1,282 @@ +import time +import typing from ast import Tuple from enum import Enum -import time -import os -import sys -import common.Common as common + +import configs +import constants +import squish from common.SeedUtils import * -from .StatusMainScreen import StatusMainScreen -from .StatusMainScreen import authenticate_popup_enter_password +from drivers.SquishDriver import * +from objectmaphelper import * +from utils.ObjectAccess import * +from utils.decorators import close_exists + from .SettingsScreen import SidebarComponents -from drivers.SquishDriver import type_text as type_text +from .StatusMainScreen import authenticate_popup_enter_password +from .components.base_popup import BasePopup +from .components.confirmation_popup import ConfirmationPopup +from .components.context_menu import ContextMenu +from .components.remove_wallet_account_popup import RemoveWalletAccountPopup +from .components.saved_address_popup import AddSavedAddressPopup, EditSavedAddressPopup +from .components.wallet_account_popups import AccountPopup NOT_APPLICABLE = "N/A" VALUE_YES = "yes" VALUE_NO = "no" + +class MainWalletContextMenu(ContextMenu): + + def __init__(self): + super(MainWalletContextMenu, self).__init__() + self._copy_address_menu_item = BaseElement('mainWallet_CopyAddress_MenuItem') + self._edit_account_menu_item = BaseElement('mainWallet_EditAccount_MenuItem') + self._add_new_account_menu_item = BaseElement('mainWallet_AddNewAccount_MenuItem') + self._add_watch_only_account_menu_item = BaseElement('mainWallet_AddWatchOnlyAccount_MenuItem') + self._delete_menu_item = BaseElement('mainWallet_DeleteAccount_MenuItem') + + def wait_until_appears(self, timeout_msec: int = configs.squish.UI_LOAD_TIMEOUT_MSEC): + self._add_new_account_menu_item.wait_until_appears(timeout_msec) + return self + + def select(self, menu_item: BaseElement): + menu_item.wait_until_appears() + menu_item.click() + menu_item.wait_until_hidden() + + def select_copy_address(self): + self.select(self._copy_address_menu_item) + + def select_edit_account(self): + self.select(self._edit_account_menu_item) + + def select_add_new_account(self): + self.select(self._add_new_account_menu_item) + + def select_add_watch_anly_account(self): + self.select(self._add_watch_only_account_menu_item) + + def select_delete(self): + self.select(self._delete_menu_item) + + +class LeftPanel(BaseElement): + + def __init__(self): + super(LeftPanel, self).__init__('mainWallet_LeftTab') + self._saved_addresses_button = BaseElement('mainWallet_Saved_Addresses_Button') + self._wallet_account_item = BaseElement('walletAccount_StatusListItem') + self._add_account_button = Button('mainWallet_Add_Account_Button') + + @property + def accounts(self) -> typing.List[constants.wallet.account_list_item]: + if 'title' in self._wallet_account_item.object_name.keys(): + del self._wallet_account_item.object_name['title'] + + accounts = [] + for account_item in squish.findAllObjects(self._wallet_account_item.object_name): + try: + name = str(account_item.title) + color = str(account_item.asset.color.name).lower() + emoji = '' + for child in walk_children(account_item): + if hasattr(child, 'emojiId'): + emoji = str(child.emojiId) + break + accounts.append(constants.wallet.account_list_item(name, color, emoji)) + except (AttributeError, RuntimeError): + continue + + return accounts + + @close_exists(BasePopup()) + def open_saved_addresses(self) -> 'AddressesView': + self._saved_addresses_button.click() + return AddressesView().wait_until_appears() + + @close_exists(BasePopup()) + def select_account(self, account_name: str) -> 'WalletAccountView': + self._wallet_account_item.object_name['title'] = account_name + self._wallet_account_item.click() + return WalletAccountView().wait_until_appears() + + @close_exists(BasePopup()) + def _open_context_menu(self) -> MainWalletContextMenu: + super(LeftPanel, self).open_context_menu() + return MainWalletContextMenu().wait_until_appears() + + @close_exists(BasePopup()) + def _open_context_menu_for_account(self, account_name: str) -> MainWalletContextMenu: + self._wallet_account_item.object_name['title'] = account_name + self._wallet_account_item.wait_until_appears().open_context_menu() + return MainWalletContextMenu().wait_until_appears() + + def open_edit_account_popup(self, account_name: str, attempt: int = 2) -> AccountPopup: + try: + self._open_context_menu_for_account(account_name).select_edit_account() + return AccountPopup().wait_until_appears() + except: + if attempt: + return self.open_edit_account_popup(account_name, attempt - 1) + else: + raise + + def open_add_watch_anly_account_popup(self, attempt: int = 2) -> AccountPopup: + try: + self._open_context_menu().select_add_watch_anly_account() + return AccountPopup().wait_until_appears() + except: + if attempt: + return self.open_add_watch_anly_account_popup(attempt - 1) + else: + raise + + def open_add_new_account_popup(self, attempt: int = 2): + try: + self._open_context_menu().select_add_new_account() + return AccountPopup().wait_until_appears() + except: + if attempt: + return self.open_add_new_account_popup(attempt - 1) + else: + raise + + def open_add_account_popup(self): + self._add_account_button.click() + return AccountPopup().wait_until_appears() + + def delete_account(self, account_name: str, attempt: int = 2) -> RemoveWalletAccountPopup: + try: + self._open_context_menu_for_account(account_name).select_delete() + return RemoveWalletAccountPopup().wait_until_appears() + except: + if attempt: + return self.delete_account(account_name, attempt - 1) + else: + raise + + +class SavedAddressListItem(BaseElement): + + def __init__(self, object_name: str): + super(SavedAddressListItem, self).__init__(object_name) + self._send_button = Button('send_StatusRoundButton') + self._open_menu_button = Button('savedAddressView_Delegate_menuButton') + + @property + def name(self) -> str: + return self.object.name + + @property + def address(self) -> str: + return self.object.address + + def open_send_popup(self): + self._send_button.object_name['container'] = self.object_name + self._send_button.click() + # TODO: return popup) + + def open_context_menu(self) -> ContextMenu: + self._open_menu_button.object_name['container'] = self.object_name + self._open_menu_button.click() + return ContextMenu().wait_until_appears() + + +class AddressesView(BaseElement): + + def __init__(self): + super(AddressesView, self).__init__('mainWindow_SavedAddressesView') + self._add_new_address_button = Button('mainWallet_Saved_Addreses_Add_Buttton') + self._address_list_item = BaseElement('savedAddressView_Delegate') + + @property + def saved_addresses(self): + items = get_objects(self._address_list_item.symbolic_name) + addresses = [SavedAddressListItem(get_real_name(item)) for item in items] + return addresses + + @property + def address_names(self): + names = [address.name for address in get_objects(self._address_list_item.symbolic_name)] + return names + + def _get_saved_address_by_name(self, name): + for address in self.saved_addresses: + if address.name == name: + return address + raise LookupError(f'Address: {name} not found ') + + def open_add_address_popup(self, attempt=2) -> 'AddSavedAddressPopup': + self._add_new_address_button.click() + try: + return AddSavedAddressPopup().wait_until_appears() + except AssertionError as err: + if attempt: + self.open_add_address_popup(attempt - 1) + else: + raise err + + def open_edit_address_popup(self, address_name: str) -> 'EditSavedAddressPopup': + address = self._get_saved_address_by_name(address_name) + address.open_context_menu().select('Edit') + return EditSavedAddressPopup().wait_until_appears() + + def delete_saved_address(self, address_name): + address = self._get_saved_address_by_name(address_name) + address.open_context_menu().select('Delete') + ConfirmationPopup().wait_until_appears().confirm() + + +class WalletAccountView(BaseElement): + + def __init__(self): + super(WalletAccountView, self).__init__('mainWindow_StatusSectionLayout_ContentItem') + self._account_name_text_label = TextLabel('mainWallet_Account_Name') + self._addresses_panel = BaseElement('mainWallet_Address_Panel') + + @property + def name(self) -> str: + return self._account_name_text_label.text + + @property + def address(self) -> str: + return str(self._addresses_panel.object.value) + + def wait_until_appears(self, timeout_msec: int = configs.squish.UI_LOAD_TIMEOUT_MSEC): + self._account_name_text_label.wait_until_appears(timeout_msec) + return self + + class Tokens(Enum): ETH: str = "ETH" + class SigningPhrasePopUp(Enum): OK_GOT_IT_BUTTON: str = "signPhrase_Ok_Button" + class MainWalletScreen(Enum): WALLET_LEFT_TAB: str = "mainWallet_LeftTab" ADD_ACCOUNT_BUTTON: str = "mainWallet_Add_Account_Button" ACCOUNT_NAME: str = "mainWallet_Account_Name" ACCOUNT_ADDRESS_PANEL: str = "mainWallet_Address_Panel" SEND_BUTTON_FOOTER: str = "mainWallet_Footer_Send_Button" - SAVED_ADDRESSES_BUTTON: str = "mainWallet_Saved_Addresses_Button" NETWORK_SELECTOR_BUTTON: str = "mainWallet_Network_Selector_Button" RIGHT_SIDE_TABBAR: str = "mainWallet_Right_Side_Tab_Bar" WALLET_ACCOUNTS_LIST: str = "walletAccounts_StatusListView" WALLET_ACCOUNT_ITEM_PLACEHOLDER = "walletAccounts_WalletAccountItem_Placeholder" EPHEMERAL_NOTIFICATION_LIST: str = "mainWallet_Ephemeral_Notification_List" TOTAL_CURRENCY_BALANCE: str = "mainWallet_totalCurrencyBalance" - -class MainWalletRightClickMenu(Enum): - COPY_ADDRESS_ACTION_PLACEHOLDER: str = "mainWallet_RightClick_CopyAddress_MenuItem_Placeholder" - EDIT_ACCOUNT_ACTION_PLACEHOLDER: str = "mainWallet_RightClick_EditAccount_MenuItem_Placeholder" - DELETE_ACCOUNT_ACTION_PLACEHOLDER: str = "mainWallet_RightClick_DeleteAccount_MenuItem_Placeholder" - ADD_NEW_ACCOUNT_ACTION_PLACEHOLDER: str = "mainWallet_RightClick_AddNewAccount_MenuItem_Placeholder" - ADD_WATCH_ONLY_ACCOUNT_ACTION_PLACEHOLDER: str = "mainWallet_RightClick_AddWatchOnlyAccount_MenuItem_Placeholder" + class AssetView(Enum): LIST: str = "mainWallet_Assets_View_List" + class NetworkSelectorPopup(Enum): LAYER_1_REPEATER: str = "mainWallet_Network_Popup_Chain_Repeater_1" -class SavedAddressesScreen(Enum): - ADD_BUTTON: str = "mainWallet_Saved_Addreses_Add_Buttton" - SAVED_ADDRESSES_LIST: str = "mainWallet_Saved_Addreses_List" - EDIT: str = "mainWallet_Saved_Addreses_More_Edit" - DELETE: str = "mainWallet_Saved_Addreses_More_Delete" - CONFIRM_DELETE: str = "mainWallet_Saved_Addreses_More_Confirm_Delete" - DELEGATE_MENU_BUTTON_OBJECT_NAME: str = "savedAddressView_Delegate_menuButton" - DELEGATE_FAVOURITE_BUTTON_OBJECT_NAME: str = "savedAddressView_Delegate_favouriteButton" - -class AddSavedAddressPopup(Enum): - NAME_INPUT: str = "mainWallet_Saved_Addreses_Popup_Name_Input" - ADDRESS_INPUT: str = "mainWallet_Saved_Addreses_Popup_Address_Input" - ADDRESS_INPUT_EDIT: str = "mainWallet_Saved_Addreses_Popup_Address_Input_Edit" - ADD_BUTTON: str = "mainWallet_Saved_Addreses_Popup_Address_Add_Button" class SendPopup(Enum): SCROLL_BAR: str = "mainWallet_Send_Popup_Main" @@ -74,69 +290,27 @@ class SendPopup(Enum): ASSET_LIST: str = "mainWallet_Send_Popup_Asset_List" HIGH_GAS_BUTTON: str = "mainWallet_Send_Popup_GasSelector_HighGas_Button" -class AddEditAccountPopup(Enum): - CONTENT = "mainWallet_AddEditAccountPopup_Content" - ACCOUNT_NAME = "mainWallet_AddEditAccountPopup_AccountName" - ACCOUNT_COLOR_SELECTOR = "mainWallet_AddEditAccountPopup_AccountColorSelector" - SELECTED_ORIGIN = "mainWallet_AddEditAccountPopup_SelectedOrigin" - EMOJI_PUPUP_BUTTON = "mainWallet_AddEditAccountPopup_AccountEmojiPopupButton" - EMOJI_PUPUP_SEARCH = "mainWallet_AddEditAccountPopup_AccountEmojiSearchBox" - EMOJI_PUPUP_EMOJI = "mainWallet_AddEditAccountPopup_AccountEmoji" - ORIGIN_OPTION_PLACEHOLDER = "mainWallet_AddEditAccountPopup_OriginOption_Placeholder" - ORIGIN_OPTION_NEW_MASTER_KEY = "mainWallet_AddEditAccountPopup_OriginOptionNewMasterKey" - ORIGIN_OPTION_WATCH_ONLY_ACC = "mainWallet_AddEditAccountPopup_OriginOptionWatchOnlyAcc" - WATCH_ONLY_ADDRESS = "mainWallet_AddEditAccountPopup_AccountWatchOnlyAddress" - PRIMARY_BUTTON = "mainWallet_AddEditAccountPopup_PrimaryButton" - BACK_BUTTON = "mainWallet_AddEditAccountPopup_BackButton" - EDIT_DERIVATION_PATH_BUTTON = "mainWallet_AddEditAccountPopup_EditDerivationPathButton" - RESET_DERIVATION_PATH_BUTTON = "mainWallet_AddEditAccountPopup_ResetDerivationPathButton" - DERIVATION_PATH = "mainWallet_AddEditAccountPopup_DerivationPathInput" - PREDEFINED_DERIVATION_PATHS_BUTTON = "mainWallet_AddEditAccountPopup_PreDefinedDerivationPathsButton" - PREDEFINED_TESTNET_ROPSTEN_PATH = "mainWallet_AddEditAccountPopup_PreDefinedPathsOptionTestnetRopsten" - SELECTED_GENERATED_ADDRESS = "mainWallet_AddEditAccountPopup_GeneratedAddressComponent" - GENERATED_ADDDRESS_99 = "mainWallet_AddEditAccountPopup_GeneratedAddress_99" - GENERATED_ADDRESSES_PAGE_20 = "mainWallet_AddEditAccountPopup_PageIndicatorPage_20" - NON_ETH_DERIVATION_PATH = "mainWallet_AddEditAccountPopup_NonEthDerivationPathCheckBox" - MASTER_KEY_IMPORT_PRIVATE_KEY_OPTION = "mainWallet_AddEditAccountPopup_MasterKey_ImportPrivateKeyOption" - MASTER_KEY_IMPORT_SEED_PHRASE_OPTION = "mainWallet_AddEditAccountPopup_MasterKey_ImportSeedPhraseOption" - MASTER_KEY_GENERATE_SEED_PHRASE_OPTION = "mainWallet_AddEditAccountPopup_MasterKey_GenerateSeedPhraseOption" - MASTER_KEY_GO_TO_KEYCARD_SETTINGS_OPTION = "mainWallet_AddEditAccountPopup_MasterKey_GoToKeycardSettingsOption" - PRIVATE_KEY = "mainWallet_AddEditAccountPopup_PrivateKey" - PRIVATE_KEY_KEY_NAME = "mainWallet_AddEditAccountPopup_PrivateKeyName" - IMPORTED_SEED_PHRASE_KEY_NAME = "mainWallet_AddEditAccountPopup_ImportedSeedPhraseKeyName" - GENERATED_SEED_PHRASE_KEY_NAME = "mainWallet_AddEditAccountPopup_GeneratedSeedPhraseKeyName" - SEED_PHRASE_12_WORDS: str = "mainWallet_AddEditAccountPopup_12WordsButton" - SEED_PHRASE_18_WORDS: str = "mainWallet_AddEditAccountPopup_18WordsButton" - SEED_PHRASE_24_WORDS: str = "mainWallet_AddEditAccountPopup_24WordsButton" - SEED_PHRASE_WORD_PATTERN: str = "mainWallet_AddEditAccountPopup_SPWord_" - HAVE_PEN_AND_PAPER = "mainWallet_AddEditAccountPopup_HavePenAndPaperCheckBox" - SEED_PHRASE_WRITTEN = "mainWallet_AddEditAccountPopup_SeedPhraseWrittenCheckBox" - STORING_SEED_PHRASE_CONFIRMED = "mainWallet_AddEditAccountPopup_StoringSeedPhraseConfirmedCheckBox" - SEED_BACKUP_ACKNOWLEDGE = "mainWallet_AddEditAccountPopup_SeedBackupAknowledgeCheckBox" - REVEAL_SEED_PHRASE_BUTTON = "mainWallet_AddEditAccountPopup_RevealSeedPhraseButton" - SEED_PHRASE_WORD_AT_INDEX_PLACEHOLDER = "mainWallet_AddEditAccountPopup_SeedPhraseWordAtIndex_Placeholder" - ENTER_SEED_PHRASE_WORD_COMPONENT = "mainWallet_AddEditAccountPopup_EnterSeedPhraseWordComponent" - ENTER_SEED_PHRASE_WORD = "mainWallet_AddEditAccountPopup_EnterSeedPhraseWord" -class RemoveAccountPopup(Enum): - ACCOUNT_NOTIFICATION = "mainWallet_Remove_Account_Popup_Account_Notification" - ACCOUNT_PATH = "mainWallet_Remove_Account_Popup_Account_Path" - HAVE_PEN_PAPER = "mainWallet_Remove_Account_Popup_HavePenPaperCheckBox" - CONFIRM_BUTTON = "mainWallet_Remove_Account_Popup_ConfirmButton" - CANCEL_BUTTON = "mainWallet_Remove_Account_Popup_CancelButton" +class AddEditAccountPopup(Enum): + ORIGIN_OPTION_NEW_MASTER_KEY = "mainWallet_AddEditAccountPopup_OriginOptionNewMasterKey" + MASTER_KEY_GO_TO_KEYCARD_SETTINGS_OPTION = "mainWallet_AddEditAccountPopup_MasterKey_GoToKeycardSettingsOption" + class CollectiblesView(Enum): - COLLECTIONS_REPEATER: str = "mainWallet_Collections_Repeater" - COLLECTIBLES_REPEATER: str = "mainWallet_Collectibles_Repeater" + COLLECTIONS_REPEATER: str = "mainWallet_Collections_Repeater" + COLLECTIBLES_REPEATER: str = "mainWallet_Collectibles_Repeater" + class WalletTabBar(Enum): - ASSET_TAB = 0 - COLLECTION_TAB = 1 + ASSET_TAB = 0 + COLLECTION_TAB = 1 ACTIVITY_TAB = 2 + class TransactionsView(Enum): - TRANSACTIONS_LISTVIEW: str = "mainWallet_Transactions_List" - TRANSACTIONS_DETAIL_VIEW_HEADER: str = "mainWallet_Transactions_Detail_View_Header" + TRANSACTIONS_LISTVIEW: str = "mainWallet_Transactions_List" + TRANSACTIONS_DETAIL_VIEW_HEADER: str = "mainWallet_Transactions_Detail_View_Header" + class StatusWalletScreen: @@ -144,225 +318,25 @@ class StatusWalletScreen: ### Screen actions region: ##################################### + def __init__(self): + super(StatusWalletScreen, self).__init__() + self.left_panel: LeftPanel = LeftPanel() + def accept_signing_phrase(self): click_obj_by_name(SigningPhrasePopUp.OK_GOT_IT_BUTTON.value) - - def open_add_account_popup(self): - click_obj_by_name(MainWalletScreen.ADD_ACCOUNT_BUTTON.value) - - def add_account_popup_do_primary_action(self, password: str = NOT_APPLICABLE): - click_obj_by_name(AddEditAccountPopup.PRIMARY_BUTTON.value) - if password != NOT_APPLICABLE: - authenticate_popup_enter_password(password) - - def add_account_popup_open_edit_derivation_path_section(self, password: str): - click_obj_by_name(AddEditAccountPopup.EDIT_DERIVATION_PATH_BUTTON.value) - authenticate_popup_enter_password(password) - - def add_account_popup_change_account_name(self, name: str): - is_loaded_visible_and_enabled(AddEditAccountPopup.ACCOUNT_NAME.value, 1000) - setText(AddEditAccountPopup.ACCOUNT_NAME.value, name) - - def add_account_popup_change_account_color(self, color: str): - colorList = get_obj(AddEditAccountPopup.ACCOUNT_COLOR_SELECTOR.value) - for index in range(colorList.count): - c = colorList.itemAt(index) - if(c.radioButtonColor == color): - click_obj(colorList.itemAt(index)) - - def add_account_popup_change_origin(self, origin_object_name: str): - click_obj_by_name(AddEditAccountPopup.SELECTED_ORIGIN.value) - click_obj_by_name(origin_object_name) - - def add_account_popup_change_origin_by_keypair_name(self, keypair_name): - click_obj_by_name(AddEditAccountPopup.SELECTED_ORIGIN.value) - originObj = wait_by_wildcards(AddEditAccountPopup.ORIGIN_OPTION_PLACEHOLDER.value, "%NAME%", keypair_name) - click_obj(originObj) - def add_account_popup_change_derivation_path(self, index: str, order: str, is_ethereum_root: str): - # initially we set derivation path to other than default eth path, in order to test reset button functionality - click_obj_by_name(AddEditAccountPopup.PREDEFINED_DERIVATION_PATHS_BUTTON.value) - hover_and_click_object_by_name(AddEditAccountPopup.PREDEFINED_TESTNET_ROPSTEN_PATH.value) - if is_ethereum_root == VALUE_YES: - click_obj_by_name(AddEditAccountPopup.RESET_DERIVATION_PATH_BUTTON.value) - else: - scroll_item_until_item_is_visible(AddEditAccountPopup.CONTENT.value, AddEditAccountPopup.NON_ETH_DERIVATION_PATH.value) - click_obj_by_name(AddEditAccountPopup.NON_ETH_DERIVATION_PATH.value) - - [compLoaded, selectedAccount] = is_loaded(AddEditAccountPopup.SELECTED_GENERATED_ADDRESS.value) - if not compLoaded: - verify_failure("cannot find selected address") - return - - if index != NOT_APPLICABLE or order != NOT_APPLICABLE: - click_obj_by_name(AddEditAccountPopup.DERIVATION_PATH.value) - common.clear_input_text(AddEditAccountPopup.DERIVATION_PATH.value) - if index != NOT_APPLICABLE: - type_text(AddEditAccountPopup.DERIVATION_PATH.value, index) - elif order != NOT_APPLICABLE: - do_until_validation_with_timeout( - lambda: time.sleep(0.5), - lambda: not selectedAccount.loading, - "generating addresses to offer after path is cleared", - 5000) - click_obj(selectedAccount) - is_loaded_visible_and_enabled(AddEditAccountPopup.GENERATED_ADDRESSES_PAGE_20.value) - click_obj_by_name(AddEditAccountPopup.GENERATED_ADDRESSES_PAGE_20.value) - is_loaded_visible_and_enabled(AddEditAccountPopup.GENERATED_ADDDRESS_99.value) - click_obj_by_name(AddEditAccountPopup.GENERATED_ADDDRESS_99.value) - - do_until_validation_with_timeout( - lambda: time.sleep(0.5), - lambda: not selectedAccount.loading, - "resolving an address after path is finally chosen", - 5000) - - def add_account_popup_change_account_emoji(self, emoji: str): - click_obj_by_name(AddEditAccountPopup.EMOJI_PUPUP_BUTTON.value) - wait_for_object_and_type(AddEditAccountPopup.EMOJI_PUPUP_SEARCH.value, emoji) - click_obj(wait_by_wildcards(AddEditAccountPopup.EMOJI_PUPUP_EMOJI.value, "%NAME%", "*")) - - def add_account_popup_set_watch_only_account_as_selected_origin(self, address: str): - self.add_account_popup_change_origin(AddEditAccountPopup.ORIGIN_OPTION_WATCH_ONLY_ACC.value) - wait_for_object_and_type(AddEditAccountPopup.WATCH_ONLY_ADDRESS.value, address) - - def add_account_popup_set_new_private_key_as_selected_origin(self, private_key: str, keypair_name: str): - self.add_account_popup_change_origin(AddEditAccountPopup.ORIGIN_OPTION_NEW_MASTER_KEY.value) - is_loaded_visible_and_enabled(AddEditAccountPopup.MASTER_KEY_IMPORT_PRIVATE_KEY_OPTION.value) - click_obj_by_name(AddEditAccountPopup.MASTER_KEY_IMPORT_PRIVATE_KEY_OPTION.value) - type_text(AddEditAccountPopup.PRIVATE_KEY.value, private_key) - wait_for_object_and_type(AddEditAccountPopup.PRIVATE_KEY_KEY_NAME.value, keypair_name) - self.add_account_popup_do_primary_action() - - def add_account_popup_set_new_seed_phrase_as_selected_origin(self, seed_phrase: str, keypair_name: str): - self.add_account_popup_change_origin(AddEditAccountPopup.ORIGIN_OPTION_NEW_MASTER_KEY.value) - is_loaded_visible_and_enabled(AddEditAccountPopup.MASTER_KEY_IMPORT_SEED_PHRASE_OPTION.value) - click_obj_by_name(AddEditAccountPopup.MASTER_KEY_IMPORT_SEED_PHRASE_OPTION.value) - sp_words = seed_phrase.split() - if len(sp_words) == 12: - click_obj_by_name(AddEditAccountPopup.SEED_PHRASE_12_WORDS.value) - elif len(sp_words) == 18: - click_obj_by_name(AddEditAccountPopup.SEED_PHRASE_18_WORDS.value) - elif len(sp_words) == 24: - click_obj_by_name(AddEditAccountPopup.SEED_PHRASE_24_WORDS.value) - else: - test.fail("Wrong amount of seed words", len(words)) - input_seed_phrase(AddEditAccountPopup.SEED_PHRASE_WORD_PATTERN.value, sp_words) - wait_for_object_and_type(AddEditAccountPopup.IMPORTED_SEED_PHRASE_KEY_NAME.value, keypair_name) - self.add_account_popup_do_primary_action() - - def add_account_popup_set_generated_seed_phrase_as_selected_origin(self, keypair_name: str): - self.add_account_popup_change_origin(AddEditAccountPopup.ORIGIN_OPTION_NEW_MASTER_KEY.value) - is_loaded_visible_and_enabled(AddEditAccountPopup.MASTER_KEY_IMPORT_SEED_PHRASE_OPTION.value) - click_obj_by_name(AddEditAccountPopup.MASTER_KEY_GENERATE_SEED_PHRASE_OPTION.value) - - click_obj_by_name(AddEditAccountPopup.HAVE_PEN_AND_PAPER.value) - click_obj_by_name(AddEditAccountPopup.SEED_PHRASE_WRITTEN.value) - click_obj_by_name(AddEditAccountPopup.STORING_SEED_PHRASE_CONFIRMED.value) - self.add_account_popup_do_primary_action() - - click_obj_by_name(AddEditAccountPopup.REVEAL_SEED_PHRASE_BUTTON.value) - seed_phrase = [wait_by_wildcards(AddEditAccountPopup.SEED_PHRASE_WORD_AT_INDEX_PLACEHOLDER.value, "%WORD-INDEX%", str(i + 1)).textEdit.input.edit.text for i in range(12)] - self.add_account_popup_do_primary_action() - - enterWordObj = wait_and_get_obj(AddEditAccountPopup.ENTER_SEED_PHRASE_WORD_COMPONENT.value) - label = str(enterWordObj.label) - index = int(label[len("Word #"):len(label)]) - 1 - wordToEnter = str(seed_phrase[index]) - wait_for_object_and_type(AddEditAccountPopup.ENTER_SEED_PHRASE_WORD.value, wordToEnter) - self.add_account_popup_do_primary_action() - - enterWordObj = wait_and_get_obj(AddEditAccountPopup.ENTER_SEED_PHRASE_WORD_COMPONENT.value) - label = str(enterWordObj.label) - index = int(label[len("Word #"):len(label)]) - 1 - wordToEnter = str(seed_phrase[index]) - wait_for_object_and_type(AddEditAccountPopup.ENTER_SEED_PHRASE_WORD.value, wordToEnter) - self.add_account_popup_do_primary_action() - - click_obj_by_name(AddEditAccountPopup.SEED_BACKUP_ACKNOWLEDGE.value) - self.add_account_popup_do_primary_action() - - wait_for_object_and_type(AddEditAccountPopup.GENERATED_SEED_PHRASE_KEY_NAME.value, keypair_name) - self.add_account_popup_do_primary_action() - def add_account_popup_go_to_keycard_settings(self): self.add_account_popup_change_origin(AddEditAccountPopup.ORIGIN_OPTION_NEW_MASTER_KEY.value) is_loaded_visible_and_enabled(AddEditAccountPopup.MASTER_KEY_GO_TO_KEYCARD_SETTINGS_OPTION.value) click_obj_by_name(AddEditAccountPopup.MASTER_KEY_GO_TO_KEYCARD_SETTINGS_OPTION.value) - - def remove_account_popup_do_cancel_action(self): - click_obj_by_name(RemoveAccountPopup.CANCEL_BUTTON.value) - - def remove_account_popup_do_remove_action(self, confirmHavingPenAndPaper, password: str): - if confirmHavingPenAndPaper: - click_obj_by_name(RemoveAccountPopup.HAVE_PEN_PAPER.value) - click_obj_by_name(RemoveAccountPopup.CONFIRM_BUTTON.value) - if password != NOT_APPLICABLE: - authenticate_popup_enter_password(password) - - def click_option_from_left_part_right_click_menu(self, option: str): - right_click_obj_by_name(MainWalletScreen.WALLET_LEFT_TAB.value) - optionObj = wait_by_wildcards(option, "%NAME%", "wallet-background") - hover_obj(optionObj) - click_obj(optionObj) - - def click_option_from_right_click_menu_of_account_with_name(self, option: str, name: str): - time.sleep(2) - ########################################## - # Sometimes this function fails to open right click menu on form the wallet account item, - # or because of missed option from the right click menu - # - # NEEDS SOME INSPECTION WHAT'S REALLY HAPPENING - # - ########################################## - - # OPTION-1 - # accounts = wait_and_get_obj(MainWalletScreen.WALLET_ACCOUNTS_LIST.value) - # for index in range(accounts.count): - # accountObj = accounts.itemAtIndex(index) - # if(accountObj.objectName == "walletAccount-" + name): - # right_click_obj(accountObj) - # do_until_validation_with_timeout( - # lambda: time.sleep(1), - # lambda: accountObj.itemLoaded, - # "loading address", - # 5000) - # optionObj = wait_by_wildcards(option, "%NAME%", name) - # hover_obj(optionObj) - # click_obj(optionObj) - # return - - # OPTION-2 - accountObj = wait_by_wildcards(MainWalletScreen.WALLET_ACCOUNT_ITEM_PLACEHOLDER.value, "%NAME%", name) - if accountObj is None: - objName = copy.deepcopy(getattr(names, MainWalletScreen.WALLET_ACCOUNT_ITEM_PLACEHOLDER.value)) - realObjName = objName["objectName"].replace("%NAME%", name) - [compLoaded, accountObj] = is_loaded_visible_and_enabled(realObjName) - if not compLoaded: - verify_failure("cannot find wallet account component with objectName = " + realObjName) - return - if accountObj is None: - verify_failure("cannot find wallet account component with name = " + name) - return - do_until_validation_with_timeout( - lambda: time.sleep(0.5), - lambda: false if accountObj is None else accountObj.itemLoaded, - "loading address", - 5000) - right_click_obj(accountObj) - time.sleep(1) - optionObj = wait_by_wildcards(option, "%NAME%", name) - if optionObj is None: - verify_failure("cannot find option in wallet account right click menu with name = " + name) - return - hover_obj(optionObj) - click_obj(optionObj) - + def send_transaction(self, account_name, amount, token, chain_name, password): is_loaded_visible_and_enabled(AssetView.LIST.value, 2000) list = get_obj(AssetView.LIST.value) # LoadingTokenDelegate will be visible until the balance is loaded verify_account_balance_is_positive checks for TokenDelegate - do_until_validation_with_timeout(lambda: time.sleep(0.1), lambda: self.verify_account_balance_is_positive(list, "ETH")[0], "Wait for tokens to load", 10000) + do_until_validation_with_timeout(lambda: time.sleep(0.1), + lambda: self.verify_account_balance_is_positive(list, "ETH")[0], + "Wait for tokens to load", 10000) click_obj_by_name(MainWalletScreen.SEND_BUTTON_FOOTER.value) @@ -374,7 +348,7 @@ class StatusWalletScreen: asset_list = get_obj(SendPopup.ASSET_LIST.value) for index in range(asset_list.count): tokenObj = asset_list.itemAtIndex(index) - if(not is_null(tokenObj) and tokenObj.objectName == "AssetSelector_ItemDelegate_" + token): + if (not is_null(tokenObj) and tokenObj.objectName == "AssetSelector_ItemDelegate_" + token): click_obj(asset_list.itemAtIndex(index)) break @@ -382,7 +356,7 @@ class StatusWalletScreen: accounts = get_obj(SendPopup.MY_ACCOUNTS_LIST.value) for index in range(accounts.count): - if(accounts.itemAtIndex(index).objectName == account_name): + if (accounts.itemAtIndex(index).objectName == account_name): print("WE FOUND THE ACCOUNT") click_obj(accounts.itemAtIndex(index)) break @@ -396,54 +370,18 @@ class StatusWalletScreen: def _click_repeater(self, repeater_object_name: str, object_name: str): repeater = get_obj(repeater_object_name) for index in range(repeater.count): - if(repeater.itemAt(index).objectName == object_name): + if (repeater.itemAt(index).objectName == object_name): click_obj(repeater.itemAt(index)) break def add_saved_address(self, name: str, address: str): - click_obj_by_name(MainWalletScreen.SAVED_ADDRESSES_BUTTON.value) - click_obj_by_name(SavedAddressesScreen.ADD_BUTTON.value) - type_text(AddSavedAddressPopup.NAME_INPUT.value, name) - - type_text(AddSavedAddressPopup.ADDRESS_INPUT_EDIT.value, address) - addressInput = get_obj(AddSavedAddressPopup.ADDRESS_INPUT.value) - verify_equal(addressInput.plainText, address) - is_loaded_visible_and_enabled(AddSavedAddressPopup.ADD_BUTTON.value) - click_obj_by_name(AddSavedAddressPopup.ADD_BUTTON.value) - - def _get_saved_address_delegate_item(self, name: str): - list = wait_and_get_obj(SavedAddressesScreen.SAVED_ADDRESSES_LIST.value) - found = -1 - for index in range(list.count): - if list.itemAtIndex(index).objectName == f"savedAddressView_Delegate_{name}": - found = index - - assert found != -1, "saved address not found" - return list.itemAtIndex(found) - - def _find_saved_address_and_open_menu(self, name: str): - item = self._get_saved_address_delegate_item(name) - menuButton = get_child_item_with_object_name(item, f"{SavedAddressesScreen.DELEGATE_MENU_BUTTON_OBJECT_NAME.value}_{name}") - is_object_loaded_visible_and_enabled(menuButton) - click_obj(menuButton) + self.left_panel.open_saved_addresses().open_add_address_popup().add_saved_address(name, address) def edit_saved_address(self, name: str, new_name: str): - self._find_saved_address_and_open_menu(name) - - click_obj_by_name(SavedAddressesScreen.EDIT.value) - - # Delete existing text - type_text(AddSavedAddressPopup.NAME_INPUT.value, "") - type_text(AddSavedAddressPopup.NAME_INPUT.value, "") - - type_text(AddSavedAddressPopup.NAME_INPUT.value, new_name) - click_obj_by_name(AddSavedAddressPopup.ADD_BUTTON.value) + self.left_panel.open_saved_addresses().open_edit_address_popup(name).edit_saved_address(new_name) def delete_saved_address(self, name: str): - self._find_saved_address_and_open_menu(name) - - click_obj_by_name(SavedAddressesScreen.DELETE.value) - click_obj_by_name(SavedAddressesScreen.CONFIRM_DELETE.value) + self.left_panel.open_saved_addresses().delete_saved_address(name) def toggle_favourite_for_saved_address(self, name: str): # Find the saved address and click favourite to toggle @@ -473,103 +411,58 @@ class StatusWalletScreen: assert False, "network name not found" - def click_default_wallet_account(self): - accounts = get_obj(MainWalletScreen.WALLET_ACCOUNTS_LIST.value) - click_obj(accounts.itemAtIndex(0)) - - def click_wallet_account(self, account_name: str): - accounts = get_obj(MainWalletScreen.WALLET_ACCOUNTS_LIST.value) - for index in range(accounts.count): - if(accounts.itemAtIndex(index).objectName == "walletAccount-" + account_name): - click_obj(accounts.itemAtIndex(index)) - return - ##################################### ### Verifications region: ##################################### - def remove_account_popup_verify_account_account_to_be_removed(self, name: str, path: str): - objNotification = wait_and_get_obj(RemoveAccountPopup.ACCOUNT_NOTIFICATION.value) - displayedNotification = str(objNotification.text) - if name not in displayedNotification: - verify_failure("Remove account popup doesn't refer to an account with name: " + name) - if path != NOT_APPLICABLE: - objPath = get_obj(RemoveAccountPopup.ACCOUNT_PATH.value) - if path != objPath.text: - verify_failure("Remove account popup doesn't refer to an account with path: " + path) - def verify_account_existence(self, name: str, color: str, emoji_unicode: str): - [compLoaded, accNameObj] = is_loaded_visible_and_enabled(MainWalletScreen.ACCOUNT_NAME.value) - if not compLoaded: - verify_failure("cannot find account name on the right, most likely the account we're searching for is not selected") - return - do_until_validation_with_timeout( - lambda: time.sleep(0.5), - lambda: accNameObj.text == name, - "selected account match", - 5000) + expected_account = constants.wallet.account_list_item(name, color.lower(), emoji_unicode) + started_at = time.monotonic() + while not expected_account in self.left_panel.accounts: + time.sleep(1) + if time.monotonic() - started_at > 5: + raise LookupError(f'Account {expected_account} not found in {self.left_panel.accounts}') - is_loaded_visible_and_enabled(MainWalletScreen.WALLET_ACCOUNTS_LIST.value) - accounts = get_obj(MainWalletScreen.WALLET_ACCOUNTS_LIST.value) - for index in range(accounts.count): - acc = accounts.itemAtIndex(index) - if(acc.objectName == "walletAccount-" + name): - verify_equal(str(acc.title), name, "Account displays the expected name") - verify_equal(str(acc.asset.color.name), str(color.lower()), "Account displays the expected color") - verify_equal((True if emoji_unicode in str(acc.asset.emoji) else False), True, "Account displays the expected emoji") - return - def verify_account_doesnt_exist(self, name: str): - is_loaded_visible_and_enabled(MainWalletScreen.WALLET_ACCOUNTS_LIST.value) - accounts = get_obj(MainWalletScreen.WALLET_ACCOUNTS_LIST.value) - for index in range(accounts.count): - acc = accounts.itemAtIndex(index) - if(acc.objectName == "walletAccount-" + name): - verify_failure("Account with " + name + " is still displayed even it should not be") - + assert name not in [account.name for account in self.left_panel.accounts], \ + f'Account with {name} is still displayed even it should not be' + + def verify_account_address_correct(self, account_name: str, address: str): + actual_address = self.left_panel.select_account(account_name).address + assert actual_address.lower() == address.lower(), f'Account {account_name} has unexpected address {actual_address}' + def verify_keycard_settings_is_opened(self): [compLoaded, accNameObj] = is_loaded_visible_and_enabled(SidebarComponents.KEYCARD_OPTION.value) if not compLoaded: verify_failure("keycard option from the app settings cannot be found") return verify(bool(accNameObj.selected), "keycard option from the app settings is displayed") - + def verify_account_balance_is_positive(self, list, symbol: str) -> Tuple(bool, ): if list is None: - return (False, ) + return (False,) for index in range(list.count): tokenListItem = list.itemAtIndex(index) - if tokenListItem != None and tokenListItem.item != None and tokenListItem.item.objectName == "AssetView_LoadingTokenDelegate_"+str(index): - return (False, ) + if tokenListItem != None and tokenListItem.item != None and tokenListItem.item.objectName == "AssetView_LoadingTokenDelegate_" + str( + index): + return (False,) if tokenListItem != None and tokenListItem.item != None and tokenListItem.item.objectName == "AssetView_TokenListItem_" + symbol and tokenListItem.item.balance != "0": return (True, tokenListItem) - return (False, ) + return (False,) def verify_positive_balance(self, symbol: str): is_loaded_visible_and_enabled(AssetView.LIST.value, 5000) list = get_obj(AssetView.LIST.value) - do_until_validation_with_timeout(lambda: time.sleep(0.1), lambda: self.verify_account_balance_is_positive(list, symbol)[0], "Symbol " + symbol + " not found in the asset list", 5000) + do_until_validation_with_timeout(lambda: time.sleep(0.1), + lambda: self.verify_account_balance_is_positive(list, symbol)[0], + "Symbol " + symbol + " not found in the asset list", 5000) def verify_saved_address_exists(self, name: str): - list = wait_and_get_obj(SavedAddressesScreen.SAVED_ADDRESSES_LIST.value) - for index in range(list.count): - if list.itemAtIndex(index).objectName == f"savedAddressView_Delegate_{name}": - return - - verify_failure(f'FAIL: saved address {name} not found"') + assert wait_for(name in self.left_panel.open_saved_addresses().address_names), f'Address: {name} not found' def verify_saved_address_doesnt_exist(self, name: str): - # The list should be hidden when there are no saved addresses - try: - list = wait_and_get_obj(SavedAddressesScreen.SAVED_ADDRESSES_LIST.value, 250) - except LookupError: - return - - list = wait_and_get_obj(SavedAddressesScreen.SAVED_ADDRESSES_LIST.value) - for index in range(list.count): - if list.itemAtIndex(index).objectName == f"savedAddressView_Delegate_{name}": - verify_failure(f'FAIL: saved address {name} exists') + assert wait_for(name not in self.left_panel.open_saved_addresses().address_names), f'Address: {name} found' def verify_transaction(self): pass @@ -582,7 +475,7 @@ class StatusWalletScreen: tabbar = get_obj(MainWalletScreen.RIGHT_SIDE_TABBAR.value) click_obj(tabbar.itemAt(WalletTabBar.COLLECTION_TAB.value)) collectionsRepeater = get_obj(CollectiblesView.COLLECTIONS_REPEATER.value) - if(collectionsRepeater.count > 0): + if (collectionsRepeater.count > 0): collectionsRepeater.itemAt(0).expanded = True collectiblesRepeater = get_obj(CollectiblesView.COLLECTIBLES_REPEATER.value) verify(collectiblesRepeater.count > 0, "Collectibles not retrieved for the account") @@ -593,7 +486,7 @@ class StatusWalletScreen: transaction_list_view = get_obj(TransactionsView.TRANSACTIONS_LISTVIEW.value) - wait_for("transaction_list_view.count > 0", 60*1000) + wait_for("transaction_list_view.count > 0", 60 * 1000) verify(transaction_list_view.count > 1, "Transactions not retrieved for the account") transaction_item = transaction_list_view.itemAtIndex(1) @@ -606,4 +499,3 @@ class StatusWalletScreen: verify_equal(transaction_item.item.shortTimeStamp, transaction_detail_header.shortTimeStamp) verify_equal(transaction_item.item.fiatValue, transaction_detail_header.fiatValue) verify_equal(transaction_item.item.symbol, transaction_detail_header.symbol) - diff --git a/test/ui-test/src/screens/components/authenticate_popup.py b/test/ui-test/src/screens/components/authenticate_popup.py new file mode 100644 index 0000000000..db3ac0506e --- /dev/null +++ b/test/ui-test/src/screens/components/authenticate_popup.py @@ -0,0 +1,20 @@ +import constants +from drivers.SquishDriver import * + + +class AuthenticatePopup(BaseElement): + + def __init__(self): + super(AuthenticatePopup, self).__init__('contextMenu_PopupItem') + self._password_text_edit = TextEdit('sharedPopup_Password_Input') + self._primary_button = Button('sharedPopup_Primary_Button') + self._cancel_buttom = Button('sharedPopup_Cancel_Button') + + def authenticate(self, password: str = constants.user_account.PASSWORD): + self._password_text_edit.text = password + self._primary_button.click() + self._primary_button.wait_until_hidden() + + def cancel(self): + self._cancel_buttom.click() + self._cancel_buttom.wait_until_hidden() diff --git a/test/ui-test/src/screens/components/back_up_your_seed_phrase_popup.py b/test/ui-test/src/screens/components/back_up_your_seed_phrase_popup.py new file mode 100644 index 0000000000..137dd3c9f7 --- /dev/null +++ b/test/ui-test/src/screens/components/back_up_your_seed_phrase_popup.py @@ -0,0 +1,79 @@ +import typing + +import configs +from drivers.SquishDriver import * + +from .base_popup import BasePopup + + +class BackUpYourSeedPhrasePopUp(BasePopup): + + def __init__(self): + super(BackUpYourSeedPhrasePopUp, self).__init__() + self._i_have_a_pen_and_paper_check_box = CheckBox('mainWallet_AddEditAccountPopup_HavePenAndPaperCheckBox') + self._i_know_where_i_ll_store_it_check_box = CheckBox( + 'mainWallet_AddEditAccountPopup_StoringSeedPhraseConfirmedCheckBox') + self._i_am_ready_to_write_down_seed_phrase_check_box = CheckBox( + 'mainWallet_AddEditAccountPopup_SeedPhraseWrittenCheckBox') + self._primary_button = Button('mainWallet_AddEditAccountPopup_PrimaryButton') + self._reveal_seed_phrase_button = Button('mainWallet_AddEditAccountPopup_RevealSeedPhraseButton') + self._seed_phrase_panel = BaseElement('confirmSeedPhrasePanel_StatusSeedPhraseInput') + self._seed_phrase_word_component = BaseElement('mainWallet_AddEditAccountPopup_EnterSeedPhraseWordComponent') + self._prove_word_seed_phrase_text_edit = TextEdit('mainWallet_AddEditAccountPopup_EnterSeedPhraseWord') + self._acknowledge_check_box = CheckBox('mainWallet_AddEditAccountPopup_SeedBackupAknowledgeCheckBox') + self._seed_phrase_name_text_edit = TextEdit('mainWallet_AddEditAccountPopup_GeneratedSeedPhraseKeyName') + + def set_have_pen_and_paper(self, value: bool): + self._i_have_a_pen_and_paper_check_box.set(value) + return self + + def set_ready_to_write_seed_phrase(self, value: bool): + self._i_am_ready_to_write_down_seed_phrase_check_box.set(value) + return self + + def set_know_where_store_it(self, value: bool): + self._i_know_where_i_ll_store_it_check_box.set(value) + return self + + def next(self): + self._primary_button.click() + return self + + def reveal_seed_phrase(self): + self._reveal_seed_phrase_button.click() + return self + + def get_seed_phrases(self): + phrases = [] + for phrase_n in range(1, 13): + object_name = f'SeedPhraseWordAtIndex-{phrase_n}' + self._seed_phrase_panel.object_name['objectName'] = object_name + phrases.append(str(self._seed_phrase_panel.object.textEdit.input.edit.text)) + return phrases + + def confirm_word(self, seed_phrase: typing.List[str]): + word_index = int(str(self._seed_phrase_word_component.object.label).split('Word #')[1]) + seed_word = seed_phrase[word_index - 1] + self._prove_word_seed_phrase_text_edit.text = seed_word + return self + + def set_acknowledge(self, value: bool): + self._acknowledge_check_box.set(value) + return self + + def set_seed_phrase_name(self, value: str): + self._seed_phrase_name_text_edit.text = value + return self + + def wait_until_hidden(self, timeout_msec: int = configs.squish.UI_LOAD_TIMEOUT_MSEC): + self._seed_phrase_name_text_edit.wait_until_hidden() + + def generate_seed_phrase(self, name: str): + self.set_have_pen_and_paper(True).set_ready_to_write_seed_phrase(True).set_know_where_store_it(True) + self.next().reveal_seed_phrase() + seed_phrases = self.get_seed_phrases() + self.next().confirm_word(seed_phrases) + self.next().confirm_word(seed_phrases) + self.next().set_acknowledge(True) + self.next().set_seed_phrase_name(name) + self.next().wait_until_hidden() diff --git a/test/ui-test/src/screens/components/base_popup.py b/test/ui-test/src/screens/components/base_popup.py new file mode 100644 index 0000000000..fd8bcc7275 --- /dev/null +++ b/test/ui-test/src/screens/components/base_popup.py @@ -0,0 +1,11 @@ +from drivers.SquishDriver import * + + +class BasePopup(BaseElement): + + def __init__(self): + super(BasePopup, self).__init__('statusDesktop_mainWindow_overlay') + + def close(self): + squish.nativeType('') + self.wait_until_hidden() diff --git a/test/ui-test/src/screens/components/cahange_password_popup.py b/test/ui-test/src/screens/components/cahange_password_popup.py index 8f7e77c10f..9abe30eef5 100644 --- a/test/ui-test/src/screens/components/cahange_password_popup.py +++ b/test/ui-test/src/screens/components/cahange_password_popup.py @@ -1,10 +1,12 @@ from drivers.SquishDriver import * +from .base_popup import BasePopup -class ChangePasswordPopup(BaseElement): + +class ChangePasswordPopup(BasePopup): def __init__(self): - super(ChangePasswordPopup, self).__init__('statusDesktop_mainWindow_overlay') + super(ChangePasswordPopup, self).__init__() self._current_password_text_field = TextEdit('change_password_menu_current_password') self._new_password_text_field = TextEdit('change_password_menu_new_password') self._confirm_password_text_field = TextEdit('change_password_menu_new_password_confirm') @@ -16,4 +18,4 @@ class ChangePasswordPopup(BaseElement): self._new_password_text_field.text = new_pwd self._confirm_password_text_field.text = new_pwd self._submit_button.click() - self._quit_button.wait_until_appears(15000).click() \ No newline at end of file + self._quit_button.wait_until_appears(15000).click() diff --git a/test/ui-test/src/screens/components/confirmation_popup.py b/test/ui-test/src/screens/components/confirmation_popup.py new file mode 100644 index 0000000000..6cb0b76f67 --- /dev/null +++ b/test/ui-test/src/screens/components/confirmation_popup.py @@ -0,0 +1,12 @@ +from drivers.SquishDriver import * + + +class ConfirmationPopup(BaseElement): + + def __init__(self): + super(ConfirmationPopup, self).__init__('contextMenu_PopupItem') + self._confirm_button = Button('confirmButton') + + def confirm(self): + self._confirm_button.click() + self.wait_until_hidden() diff --git a/test/ui-test/src/screens/components/context_menu.py b/test/ui-test/src/screens/components/context_menu.py new file mode 100644 index 0000000000..87302f47df --- /dev/null +++ b/test/ui-test/src/screens/components/context_menu.py @@ -0,0 +1,12 @@ +from drivers.SquishDriver import * + + +class ContextMenu(BaseElement): + + def __init__(self): + super(ContextMenu, self).__init__('contextMenu_PopupItem') + self._menu_item = BaseElement('contextMenuItem') + + def select(self, value: str): + self._menu_item.object_name['text'] = value + self._menu_item.click() diff --git a/test/ui-test/src/screens/components/emoji_popup.py b/test/ui-test/src/screens/components/emoji_popup.py new file mode 100644 index 0000000000..e702816f5c --- /dev/null +++ b/test/ui-test/src/screens/components/emoji_popup.py @@ -0,0 +1,21 @@ +import configs +from drivers.SquishDriver import * + +from .base_popup import BasePopup + + +class EmojiPopup(BasePopup): + def __init__(self): + super(EmojiPopup, self).__init__() + self._search_text_edit = TextEdit('mainWallet_AddEditAccountPopup_AccountEmojiSearchBox') + self._emoji_item = BaseElement('mainWallet_AddEditAccountPopup_AccountEmoji') + + def wait_until_appears(self, timeout_msec: int = configs.squish.UI_LOAD_TIMEOUT_MSEC): + self._search_text_edit.wait_until_appears(timeout_msec) + return self + + def select(self, name: str): + self._search_text_edit.text = name + self._emoji_item.object_name['objectName'] = 'statusEmoji_' + name + self._emoji_item.click() + self._search_text_edit.wait_until_hidden() diff --git a/test/ui-test/src/screens/components/remove_wallet_account_popup.py b/test/ui-test/src/screens/components/remove_wallet_account_popup.py new file mode 100644 index 0000000000..0e38b9d701 --- /dev/null +++ b/test/ui-test/src/screens/components/remove_wallet_account_popup.py @@ -0,0 +1,29 @@ +from drivers.SquishDriver import * + +from .authenticate_popup import AuthenticatePopup +from .base_popup import BasePopup + + +class RemoveWalletAccountPopup(BasePopup): + + def __init__(self): + super(RemoveWalletAccountPopup, self).__init__() + self._confirm_button = Button('mainWallet_Remove_Account_Popup_ConfirmButton') + self._cancel_button = Button('mainWallet_Remove_Account_Popup_CancelButton') + self._have_pen_paper_checkbox = CheckBox('mainWallet_Remove_Account_Popup_HavePenPaperCheckBox') + + def wait_until_appears(self, timeout_msec: int = configs.squish.UI_LOAD_TIMEOUT_MSEC): + self._cancel_button.wait_until_appears(timeout_msec) + return self + + def confirm(self): + self._confirm_button.click() + self._confirm_button.wait_until_hidden() + + def cancel(self): + self._cancel_button.click() + self._cancel_button.wait_until_hidden() + + def agree_and_confirm(self): + self._have_pen_paper_checkbox.wait_until_appears().set(True) + self.confirm() diff --git a/test/ui-test/src/screens/components/saved_address_popup.py b/test/ui-test/src/screens/components/saved_address_popup.py new file mode 100644 index 0000000000..65ce37cdc8 --- /dev/null +++ b/test/ui-test/src/screens/components/saved_address_popup.py @@ -0,0 +1,35 @@ +from drivers.SquishDriver import * + +from .base_popup import BasePopup + + +class SavedAddressPopup(BasePopup): + def __init__(self): + super(SavedAddressPopup, self).__init__() + self._name_text_edit = TextEdit('mainWallet_Saved_Addreses_Popup_Name_Input') + self._save_add_address_button = Button('mainWallet_Saved_Addreses_Popup_Address_Add_Button') + + +class AddSavedAddressPopup(SavedAddressPopup): + def __init__(self): + super(AddSavedAddressPopup, self).__init__() + self._address_text_edit = TextEdit('mainWallet_Saved_Addreses_Popup_Address_Input_Edit') + + def add_saved_address(self, name: str, address: str): + self._name_text_edit.text = name + self._address_text_edit.clear(verify=False) + self._address_text_edit.type_text(address) + self._save_add_address_button.click() + self.wait_until_hidden() + + +class EditSavedAddressPopup(SavedAddressPopup): + + def __init__(self): + super(EditSavedAddressPopup, self).__init__() + self._address_text_label = TextLabel('mainWallet_Saved_Addreses_Popup_Address_Input_Edit') + + def edit_saved_address(self, name: str): + self._name_text_edit.text = name + self._save_add_address_button.click() + self.wait_until_hidden() diff --git a/test/ui-test/src/screens/components/social_links_popup.py b/test/ui-test/src/screens/components/social_links_popup.py index ce8a412eb9..ddca133556 100644 --- a/test/ui-test/src/screens/components/social_links_popup.py +++ b/test/ui-test/src/screens/components/social_links_popup.py @@ -2,11 +2,13 @@ import typing from drivers.SquishDriver import * +from .base_popup import BasePopup -class SocialLinksPopup(BaseElement): + +class SocialLinksPopup(BasePopup): def __init__(self): - super(SocialLinksPopup, self).__init__('statusDesktop_mainWindow_overlay') + super(SocialLinksPopup, self).__init__() self._add_social_link_list_item = BaseElement('socialLink_StatusListItem') self._social_link_text_field = TextEdit('edit_TextEdit') self._add_button = Button('add_StatusButton') diff --git a/test/ui-test/src/screens/components/wallet_account_popups.py b/test/ui-test/src/screens/components/wallet_account_popups.py new file mode 100644 index 0000000000..30c91ef7a5 --- /dev/null +++ b/test/ui-test/src/screens/components/wallet_account_popups.py @@ -0,0 +1,195 @@ +import typing + +import configs +import constants +import squish +from drivers.SquishDriver import * + +from .authenticate_popup import AuthenticatePopup +from .back_up_your_seed_phrase_popup import BackUpYourSeedPhrasePopUp +from .base_popup import BasePopup +from .emoji_popup import EmojiPopup + +GENERATED_LPAGES_LIMIT = 20 + + +class GeneratedAddressesList(BaseElement): + + def __init__(self): + super(GeneratedAddressesList, self).__init__('statusDesktop_mainWindow_overlay_popup2') + self._address_list_item = BaseElement('addAccountPopup_GeneratedAddress') + self._paginator_page = BaseElement('page_StatusBaseButton') + + @property + def is_paginator_load(self) -> bool: + try: + return str(squish.findAllObjects(self._paginator_page.object_name)[0].text) == '1' + except IndexError: + return False + + def wait_until_appears(self, timeout_msec: int = configs.squish.UI_LOAD_TIMEOUT_MSEC): + if 'text' in self._paginator_page.object_name: + del self._paginator_page.object_name['text'] + assert squish.waitFor(lambda: self.is_paginator_load, timeout_msec), 'Generated address list not load' + return self + + def select(self, index: int): + self._address_list_item.object_name['objectName'] = f'AddAccountPopup-GeneratedAddress-{index}' + + selected_page_number = 1 + while selected_page_number != GENERATED_LPAGES_LIMIT: + if self._address_list_item.is_visible: + self._address_list_item.click() + self._paginator_page.wait_until_hidden() + break + else: + selected_page_number += 1 + self._paginator_page.object_name['text'] = selected_page_number + self._paginator_page.click() + + +class AddNewAccountPopup(BasePopup): + + def __init__(self): + super(AddNewAccountPopup, self).__init__() + self._import_private_key_button = Button('mainWallet_AddEditAccountPopup_MasterKey_ImportPrivateKeyOption') + self._import_seed_phrase_button = Button('mainWallet_AddEditAccountPopup_MasterKey_ImportSeedPhraseOption') + self._private_key_text_edit = TextEdit('mainWallet_AddEditAccountPopup_PrivateKey') + self._private_key_name_text_edit = TextEdit('mainWallet_AddEditAccountPopup_PrivateKeyName') + self._generate_master_key_button = Button('mainWallet_AddEditAccountPopup_MasterKey_GenerateSeedPhraseOption') + self._continue_button = Button('mainWallet_AddEditAccountPopup_PrimaryButton') + self._seed_phrase_12_words_button = Button("mainWallet_AddEditAccountPopup_12WordsButton") + self._seed_phrase_18_words_button = Button("mainWallet_AddEditAccountPopup_18WordsButton") + self._seed_phrase_24_words_button = Button("mainWallet_AddEditAccountPopup_24WordsButton") + self._seed_phrase_word_text_edit = TextEdit('mainWallet_AddEditAccountPopup_SPWord') + self._seed_phrase_phrase_key_name_text_edit = TextEdit( + 'mainWallet_AddEditAccountPopup_ImportedSeedPhraseKeyName') + + def import_private_key(self, private_key: str) -> str: + self._import_private_key_button.click() + self._private_key_text_edit.text = private_key + self._private_key_name_text_edit.text = private_key[:5] + self._continue_button.click() + return private_key[:5] + + def import_new_seed_phrase(self, seed_phrase_words: list) -> str: + self._import_seed_phrase_button.click() + if len(seed_phrase_words) == 12: + self._seed_phrase_12_words_button.click() + elif len(seed_phrase_words) == 18: + self._seed_phrase_18_words_button.click() + elif len(seed_phrase_words) == 24: + self._seed_phrase_24_words_button.click() + else: + raise RuntimeError("Wrong amount of seed words", len(seed_phrase_words)) + for count, word in enumerate(seed_phrase_words, start=1): + self._seed_phrase_word_text_edit.object_name['objectName'] = f'statusSeedPhraseInputField{count}' + self._seed_phrase_word_text_edit.text = word + seed_phrase_name = ''.join([word[0] for word in seed_phrase_words[:10]]) + self._seed_phrase_phrase_key_name_text_edit.text = seed_phrase_name + self._continue_button.click() + return seed_phrase_name + + def generate_new_master_key(self, name: str): + self._generate_master_key_button.click() + BackUpYourSeedPhrasePopUp().wait_until_appears().generate_seed_phrase(name) + + +class AccountPopup(BasePopup): + def __init__(self): + super(AccountPopup, self).__init__() + self._scroll = Scroll('scrollView_StatusScrollView') + self._name_text_edit = TextEdit('mainWallet_AddEditAccountPopup_AccountName') + self._emoji_button = Button('mainWallet_AddEditAccountPopup_AccountEmojiPopupButton') + self._color_radiobutton = BaseElement('color_StatusColorRadioButton') + # origin + self._origin_combobox = BaseElement('mainWallet_AddEditAccountPopup_SelectedOrigin') + self._watch_only_account_origin_item = BaseElement("mainWallet_AddEditAccountPopup_OriginOptionWatchOnlyAcc") + self._new_master_key_origin_item = BaseElement('mainWallet_AddEditAccountPopup_OriginOptionNewMasterKey') + self._existing_origin_item = BaseElement('addAccountPopup_OriginOption_StatusListItem') + # derivation + self._address_text_edit = TextEdit('mainWallet_AddEditAccountPopup_AccountWatchOnlyAddress') + self._add_account_button = Button('mainWallet_AddEditAccountPopup_PrimaryButton') + self._edit_derivation_path_button = Button('mainWallet_AddEditAccountPopup_EditDerivationPathButton') + self._derivation_path_combobox_button = Button('mainWallet_AddEditAccountPopup_PreDefinedDerivationPathsButton') + self._derivation_path_list_item = BaseElement('mainWallet_AddEditAccountPopup_derivationPath') + self._reset_derivation_path_button = Button('mainWallet_AddEditAccountPopup_ResetDerivationPathButton') + self._derivation_path_text_edit = TextEdit('mainWallet_AddEditAccountPopup_DerivationPathInput') + self._address_combobox_button = Button('mainWallet_AddEditAccountPopup_GeneratedAddressComponent') + self._non_eth_checkbox = CheckBox('mainWallet_AddEditAccountPopup_NonEthDerivationPathCheckBox') + + def set_name(self, value: str): + self._name_text_edit.text = value + return self + + def set_color(self, value: str): + if 'radioButtonColor' in self._color_radiobutton.object_name.keys(): + del self._color_radiobutton.object_name['radioButtonColor'] + colors = [str(item.radioButtonColor) for item in squish.findAllObjects(self._color_radiobutton.object_name)] + assert value in colors, f'Color {value} not found in {colors}' + self._color_radiobutton.object_name['radioButtonColor'] = value + self._color_radiobutton.click() + return self + + def set_emoji(self, value: str): + self._emoji_button.click() + EmojiPopup().wait_until_appears().select(value) + return self + + def set_origin_eth_address(self, value: str): + self._origin_combobox.click() + self._watch_only_account_origin_item.click() + self._address_text_edit.text = value + return self + + def set_origin_keypair(self, value: str): + self._origin_combobox.click() + self._existing_origin_item.object_name['objectName'] = f'AddAccountPopup-OriginOption-{value}' + self._existing_origin_item.click() + return self + + def set_origin_seed_phrase(self, value: typing.List[str]): + self._origin_combobox.click() + self._new_master_key_origin_item.click() + AddNewAccountPopup().wait_until_appears().import_new_seed_phrase(value) + return self + + def set_origin_new_seed_phrase(self, value: str): + self._origin_combobox.click() + self._new_master_key_origin_item.click() + AddNewAccountPopup().wait_until_appears().generate_new_master_key(value) + return self + + def set_origin_private_key(self, value: str): + self._origin_combobox.click() + self._new_master_key_origin_item.click() + AddNewAccountPopup().wait_until_appears().import_private_key(value) + return self + + def set_derivation_path(self, value: str, index: int): + self._edit_derivation_path_button.click() + AuthenticatePopup().wait_until_appears().authenticate() + if value in [_.value for _ in constants.wallet.DerivationPath]: + self._derivation_path_combobox_button.click() + self._derivation_path_list_item.object_name['title'] = value + self._derivation_path_list_item.click() + del self._derivation_path_list_item.object_name['title'] + self._address_combobox_button.click() + GeneratedAddressesList().wait_until_appears().select(index) + if value != constants.wallet.DerivationPath.ETHEREUM.value: + self._scroll.vertical_down_to(self._non_eth_checkbox) + self._non_eth_checkbox.set(True) + else: + self._derivation_path_text_edit.type_text(str(index)) + return self + + def save(self): + self._add_account_button.click() + return self + + def wait_until_appears(self, timeout_msec: int = configs.squish.UI_LOAD_TIMEOUT_MSEC): + assert squish.waitFor(lambda: self._name_text_edit.is_visible, timeout_msec), f'Object {self} is not visible' + return self + + def wait_until_hidden(self, timeout_msec: int = configs.squish.UI_LOAD_TIMEOUT_MSEC): + assert squish.waitFor(lambda: not self._name_text_edit.is_visible, timeout_msec), f'Object {self} is visible' diff --git a/test/ui-test/src/utils/decorators.py b/test/ui-test/src/utils/decorators.py new file mode 100644 index 0000000000..67db71f801 --- /dev/null +++ b/test/ui-test/src/utils/decorators.py @@ -0,0 +1,40 @@ +import time + +count = 2 + + +def attempt(count): + _count = count + + def _wrapper(method_to_decorate): + + def wrapper(*args, **kwargs): + try: + return method_to_decorate(*args, **kwargs) + except: + + global count + if count: + count -= 1 + time.sleep(1) + return wrapper(*args, **kwargs) + else: + raise + + return wrapper + + return _wrapper + + +def close_exists(element): + + def _wrapper(method_to_decorate): + + def wrapper(*args, **kwargs): + if element.is_visible: + element.close() + return method_to_decorate(*args, **kwargs) + + return wrapper + + return _wrapper \ No newline at end of file diff --git a/test/ui-test/testSuites/global_shared/scripts/decorators.py b/test/ui-test/testSuites/global_shared/scripts/decorators.py index 573323cf8b..e08020134b 100644 --- a/test/ui-test/testSuites/global_shared/scripts/decorators.py +++ b/test/ui-test/testSuites/global_shared/scripts/decorators.py @@ -1,6 +1,6 @@ -import drivers.SquishDriverVerification as verifier import os from typing import Dict, Any + from .global_names import mainWindow_RighPanel @@ -8,11 +8,12 @@ def verify_screenshot(func, obj: Dict[str, Any] = mainWindow_RighPanel): def inner(*args, **kwargs): context = args[0] func(*args, **kwargs) - + scenario = context.userData["feature_name"].lower().replace(" ", "_") - step = context.userData["step_name"].lower().replace(" ", "_") + step = getattr(context.userData, "step_name", '').lower().replace(" ", "_") filename = f"{step}_{'_'.join(args[1:])}" path = os.path.join(scenario, filename) -# verifier.verify_or_create_screenshot(path, obj) - + + # verifier.verify_or_create_screenshot(path, obj) + return inner diff --git a/test/ui-test/testSuites/global_shared/scripts/global_names.py b/test/ui-test/testSuites/global_shared/scripts/global_names.py index fc379bdb39..e345c78e77 100644 --- a/test/ui-test/testSuites/global_shared/scripts/global_names.py +++ b/test/ui-test/testSuites/global_shared/scripts/global_names.py @@ -1,6 +1,10 @@ +from objectmaphelper import * statusDesktop_mainWindow = {"name": "mainWindow", "type": "StatusWindow", "visible": True} statusDesktop_mainWindow_overlay = {"container": statusDesktop_mainWindow, "type": "Overlay", "unnamed": 1, "visible": True} +scrollView_StatusScrollView = {"container": statusDesktop_mainWindow_overlay, "id": "scrollView", "type": "StatusScrollView", "unnamed": 1, "visible": True} +statusDesktop_mainWindow_overlay_popup = {"container": statusDesktop_mainWindow_overlay, "type": "PopupItem", "unnamed": 1, "visible": True} +statusDesktop_mainWindow_overlay_popup2 = {"container": statusDesktop_mainWindow_overlay, "occurrence": 2, "type": "PopupItem", "unnamed": 1, "visible": True} mainWindow_navBarListView_ListView = {"container": statusDesktop_mainWindow, "objectName": "statusMainNavBarListView", "type": "ListView", "visible": True} mainWindow_communityNavBarListView_ListView = {"container": statusDesktop_mainWindow, "objectName": "statusCommunityMainNavBarListView", "type": "ListView", "visible": True} chatView_log = {"container": statusDesktop_mainWindow, "objectName": "chatLogView", "type": "StatusListView", "visible": True} @@ -18,7 +22,7 @@ viewProfile_MenuItem = {"container": statusDesktop_mainWindow_overlay, "objectNa mainWindow_ContactsColumn_Messages_Headline = {"container": statusDesktop_mainWindow, "objectName": "ContactsColumnView_MessagesHeadline", "type": "StatusNavigationPanelHeadline"} # main right panel -mainWindow_RighPanel= {"container": statusDesktop_mainWindow, "type": "ColumnLayout", "objectName": "mainRightView", "visible": True} +mainWindow_RighPanel = {"container": statusDesktop_mainWindow, "type": "ColumnLayout", "objectName": "mainRightView", "visible": True} # Navigation Panel mainWindow_StatusAppNavBar = {"container": statusDesktop_mainWindow, "type": "StatusAppNavBar", "unnamed": 1, "visible": True} @@ -68,3 +72,14 @@ ProfilePopup_SendContactRequestButton = {"container": statusDesktop_mainWindow_o # Banners mainWindow_secureYourSeedPhraseBanner_ModuleWarning = {"container": statusDesktop_mainWindow, "objectName": "secureYourSeedPhraseBanner", "type": "ModuleWarning", "visible": True} + +# Context Menu +contextMenu_PopupItem = {"container": statusDesktop_mainWindow_overlay, "type": "PopupItem", "unnamed": 1, "visible": True} +contextMenuItem = {"container": statusDesktop_mainWindow_overlay, "type": "StatusBaseText", "unnamed": 1, "visible": True} + +# Confirmation Popup +confirmButton = {"container": statusDesktop_mainWindow_overlay, "objectName": RegularExpression("confirm*"), "type": "StatusButton"} + +# 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} diff --git a/test/ui-test/testSuites/global_shared/scripts/onboarding_names.py b/test/ui-test/testSuites/global_shared/scripts/onboarding_names.py index 6b79e3cf94..231faec582 100644 --- a/test/ui-test/testSuites/global_shared/scripts/onboarding_names.py +++ b/test/ui-test/testSuites/global_shared/scripts/onboarding_names.py @@ -60,4 +60,4 @@ onboarding_SeedPhrase_Input_TextField_20 = {"container": statusDesktop_mainWindo onboarding_SeedPhrase_Input_TextField_21 = {"container": statusDesktop_mainWindow, "type": "TextEdit", "objectName": "statusSeedPhraseInputField21"} onboarding_SeedPhrase_Input_TextField_22 = {"container": statusDesktop_mainWindow, "type": "TextEdit", "objectName": "statusSeedPhraseInputField22"} onboarding_SeedPhrase_Input_TextField_23 = {"container": statusDesktop_mainWindow, "type": "TextEdit", "objectName": "statusSeedPhraseInputField23"} -onboarding_SeedPhrase_Input_TextField_24 = {"container": statusDesktop_mainWindow, "type": "TextEdit", "objectName": "statusSeedPhraseInputField24"} +onboarding_SeedPhrase_Input_TextField_24 = {"container": statusDesktop_mainWindow, "type": "TextEdit", "objectName": "statusSeedPhraseInputField24"} \ No newline at end of file diff --git a/test/ui-test/testSuites/global_shared/scripts/settings_names.py b/test/ui-test/testSuites/global_shared/scripts/settings_names.py index 6a468f9fc4..45170b4237 100644 --- a/test/ui-test/testSuites/global_shared/scripts/settings_names.py +++ b/test/ui-test/testSuites/global_shared/scripts/settings_names.py @@ -1,3 +1,4 @@ +from objectmaphelper import * from scripts.global_names import * from enum import Enum @@ -36,6 +37,7 @@ settingsContentBaseScrollView_Item = {"container": settingsContentBase_ScrollVie mainWindow_LeftTabView = {"container": statusDesktop_mainWindow, "type": "LeftTabView", "unnamed": 1, "visible": True} LeftTabView_ScrollView = {"container": mainWindow_LeftTabView, "type": "StatusScrollView", "unnamed": 1, "visible": True} + # ENS view; settings_ENS_Start_Button = {"container": statusDesktop_mainWindow, "objectName": "ensStartButton", "type": "StatusButton"} settings_ENS_Search_Input = {"container": statusDesktop_mainWindow, "objectName": "ensUsernameInput", "type": "StyledTextField"} @@ -86,7 +88,10 @@ linksView = {"container": statusDesktop_mainWindow, "id": "linksView", "type": " edit_TextEdit = {"container": statusDesktop_mainWindow_overlay, "id": "edit", "type": "TextEdit", "unnamed": 1, "visible": True} # Wallet Settings: -settings_Wallet_MainView_GeneratedAccounts = {"container": statusDesktop_mainWindow, "objectName":'generatedAccounts', "type": 'ListView'} +mainWallet_Saved_Addreses_More_Edit = {"container": statusDesktop_mainWindow, "objectName": "editroot", "type": "StatusMenuItem"} +mainWallet_Saved_Addreses_More_Delete = {"container": statusDesktop_mainWindow, "objectName": "deleteSavedAddress", "type": "StatusMenuItem"} +mainWallet_Saved_Addreses_More_Confirm_Delete = {"container": statusDesktop_mainWindow, "objectName": "confirmDeleteSavedAddress", "type": "StatusButton"} +settings_Wallet_MainView_GeneratedAccounts = {"container": statusDesktop_mainWindow, "objectName": 'generatedAccounts', "type": 'ListView'} settings_Wallet_AccountView_DeleteAccount = {"container": statusDesktop_mainWindow, "type": "StatusButton", "objectName": "deleteAccountButton"} settings_Wallet_AccountView_DeleteAccount_Confirm = {"container": statusDesktop_mainWindow, "type": "StatusButton", "objectName": "confirmDeleteAccountButton"} mainWindow_ScrollView_2 = {"container": statusDesktop_mainWindow, "occurrence": 2, "type": "StatusScrollView", "unnamed": 1, "visible": True} diff --git a/test/ui-test/testSuites/suite_wallet/shared/scripts/wallet_names.py b/test/ui-test/testSuites/global_shared/scripts/wallet_names.py similarity index 80% rename from test/ui-test/testSuites/suite_wallet/shared/scripts/wallet_names.py rename to test/ui-test/testSuites/global_shared/scripts/wallet_names.py index 03aa7ea693..ea1658132f 100644 --- a/test/ui-test/testSuites/suite_wallet/shared/scripts/wallet_names.py +++ b/test/ui-test/testSuites/global_shared/scripts/wallet_names.py @@ -1,27 +1,53 @@ +from objectmaphelper import * from scripts.global_names import * +from scripts.settings_names import * + # Main: +mainWindow_WalletLayout = {"container": statusDesktop_mainWindow, "type": "WalletLayout", "unnamed": 1, "visible": True} +mainWallet_LeftTab = {"container": statusDesktop_mainWindow, "objectName": "walletLeftTab", "type": "LeftTabView", "visible": True} +mainWallet_Saved_Addresses_Button = {"container": mainWindow_RighPanel, "objectName": "savedAddressesBtn", "type": "StatusButton"} +walletAccounts_StatusListView = {"container": statusDesktop_mainWindow, "objectName": "walletAccountsListView", "type": "StatusListView", "visible": True} +walletAccounts_WalletAccountItem_Placeholder = {"container": walletAccounts_StatusListView, "objectName": "walletAccount-%NAME%", "type": "StatusListItem", "visible": True} +walletAccount_StatusListItem = {"container": walletAccounts_StatusListView, "objectName": RegularExpression("walletAccount*"), "type": "StatusListItem", "visible": True} + +# Context Menu +mainWallet_CopyAddress_MenuItem = {"container": contextMenu_PopupItem, "enabled": True, "objectName": RegularExpression("AccountMenu-CopyAddressAction*"), "type": "StatusMenuItem"} +mainWallet_EditAccount_MenuItem = {"container": contextMenu_PopupItem, "enabled": True, "objectName": RegularExpression("AccountMenu-EditAction*"), "type": "StatusMenuItem"} +mainWallet_DeleteAccount_MenuItem = {"container": contextMenu_PopupItem, "enabled": True, "objectName": RegularExpression("AccountMenu-DeleteAction*"), "type": "StatusMenuItem"} +mainWallet_AddNewAccount_MenuItem = {"container": contextMenu_PopupItem, "enabled": True, "objectName": RegularExpression("AccountMenu-AddNewAccountAction*"), "type": "StatusMenuItem"} +mainWallet_AddWatchOnlyAccount_MenuItem = {"container": contextMenu_PopupItem, "enabled": True, "objectName": RegularExpression("AccountMenu-AddWatchOnlyAccountAction*"), "type": "StatusMenuItem"} + +# Saved Address View +mainWindow_SavedAddressesView = {"container": mainWindow_WalletLayout, "type": "SavedAddressesView", "unnamed": 1, "visible": True} +mainWallet_Saved_Addreses_Add_Buttton = {"container": mainWindow_SavedAddressesView, "objectName": "addNewAddressBtn", "type": "StatusButton"} +mainWallet_Saved_Addreses_List = {"container": mainWindow_SavedAddressesView, "objectName": "SavedAddressesView_savedAddresses", "type": "StatusListView"} +savedAddressView_Delegate = {"container": mainWallet_Saved_Addreses_List, "objectName": RegularExpression("savedAddressView_Delegate*"), "type": "SavedAddressesDelegate", "visible": True} +send_StatusRoundButton = {"container": "", "type": "StatusRoundButton", "unnamed": 1, "visible": True} +savedAddressView_Delegate_menuButton = {"container": "", "objectName": RegularExpression("savedAddressView_Delegate_menuButton*"), "type": "StatusRoundButton", "visible": True} + +# Wallet Account View +mainWindow_StatusSectionLayout_ContentItem = {"container": statusDesktop_mainWindow, "objectName": "StatusSectionLayout", "type": "ContentItem", "visible": True} +mainWallet_Account_Name = {"container": mainWindow_StatusSectionLayout_ContentItem, "objectName": "accountName", "type": "StatusBaseText", "visible": True} + + +# Wallet Account Popup +mainWallet_AddEditAccountPopup_derivationPath = {"container": statusDesktop_mainWindow, "objectName": RegularExpression("AddAccountPopup-PreDefinedDerivationPath*"), "type": "StatusListItem", "visible": True} +addAccountPopup_GeneratedAddress = {"container": statusDesktop_mainWindow_overlay_popup2, "type": "Rectangle", "visible": True} +address_0x_StatusBaseText = {"container": statusDesktop_mainWindow_overlay_popup2, "text": RegularExpression("0x*"), "type": "StatusBaseText", "unnamed": 1, "visible": True} +addAccountPopup_GeneratedAddressesListPageIndicatior_StatusPageIndicator = {"container": statusDesktop_mainWindow_overlay_popup2, "objectName": "AddAccountPopup-GeneratedAddressesListPageIndicatior", "type": "StatusPageIndicator", "visible": True} +page_StatusBaseButton = {"checkable": False, "container": addAccountPopup_GeneratedAddressesListPageIndicatior_StatusPageIndicator, "objectName": RegularExpression("Page-*"), "type": "StatusBaseButton", "visible": True} + navBarListView_Wallet_navbar_StatusNavBarTabButton = {"checkable": True, "container": mainWindow_navBarListView_ListView, "objectName": "Wallet-navbar", "type": "StatusNavBarTabButton", "visible": True} wallet_navbar_wallet_icon_StatusIcon = {"container": navBarListView_Wallet_navbar_StatusNavBarTabButton, "objectName": "wallet-icon", "type": "StatusIcon", "visible": True} -mainWallet_LeftTab = {"container": statusDesktop_mainWindow, "objectName": "walletLeftTab", "type": "LeftTabView", "visible": True} -mainWallet_Account_Name = {"container": statusDesktop_mainWindow, "objectName": "accountName", "type": "StatusBaseText", "visible": True} + mainWallet_Address_Panel = {"container": statusDesktop_mainWindow, "objectName": "addressPanel", "type": "StatusAddressPanel", "visible": True} mainWallet_Add_Account_Button = {"container": statusDesktop_mainWindow, "objectName": "addAccountButton", "type": "StatusRoundButton", "visible": True} signPhrase_Ok_Button = {"container": statusDesktop_mainWindow, "type": "StatusFlatButton", "objectName": "signPhraseModalOkButton", "visible": True} -mainWallet_Saved_Addresses_Button = {"container": statusDesktop_mainWindow, "objectName": "savedAddressesBtn", "type": "StatusButton"} mainWallet_Network_Selector_Button = {"container": statusDesktop_mainWindow, "objectName": "networkSelectorButton", "type": "StatusListItem"} mainWallet_Right_Side_Tab_Bar = {"container": statusDesktop_mainWindow, "objectName": "rightSideWalletTabBar", "type": "StatusTabBar"} mainWallet_Ephemeral_Notification_List = {"container": statusDesktop_mainWindow, "objectName": "ephemeralNotificationList", "type": "StatusListView"} -mainWallet_RightClick_CopyAddress_MenuItem_Placeholder = {"container": statusDesktop_mainWindow, "enabled": True, "objectName": "AccountMenu-CopyAddressAction-%NAME%", "type": "StatusMenuItem"} -mainWallet_RightClick_EditAccount_MenuItem_Placeholder = {"container": statusDesktop_mainWindow, "enabled": True, "objectName": "AccountMenu-EditAction-%NAME%", "type": "StatusMenuItem"} -mainWallet_RightClick_DeleteAccount_MenuItem_Placeholder = {"container": statusDesktop_mainWindow, "enabled": True, "objectName": "AccountMenu-DeleteAction-%NAME%", "type": "StatusMenuItem"} -mainWallet_RightClick_AddNewAccount_MenuItem_Placeholder = {"container": statusDesktop_mainWindow, "enabled": True, "objectName": "AccountMenu-AddNewAccountAction-%NAME%", "type": "StatusMenuItem"} -mainWallet_RightClick_AddWatchOnlyAccount_MenuItem_Placeholder = {"container": statusDesktop_mainWindow, "enabled": True, "objectName": "AccountMenu-AddWatchOnlyAccountAction-%NAME%", "type": "StatusMenuItem"} - -walletAccounts_StatusListView = {"container": statusDesktop_mainWindow, "objectName": "walletAccountsListView", "type": "StatusListView", "visible": True} -walletAccounts_WalletAccountItem_Placeholder = {"container": walletAccounts_StatusListView, "objectName": "walletAccount-%NAME%", "type": "StatusListItem", "visible": True} - # Assets view: mainWallet_Assets_View_List = {"container": statusDesktop_mainWindow, "objectName": "assetViewStatusListView", "type": "StatusListView"} @@ -43,19 +69,24 @@ mainWallet_Send_Popup_Asset_List = {"container": statusDesktop_mainWindow, "obje mainWallet_Send_Popup_GasPrice_Input = {"container": statusDesktop_mainWindow, "objectName": "gasPriceSelectorInput", "type": "StyledTextField"} # Add/Edit account popup: +grid_Grid = {"container": statusDesktop_mainWindow_overlay, "id": "grid", "type": "Grid", "unnamed": 1, "visible": True} +color_StatusColorRadioButton = {"checkable": True, "container": statusDesktop_mainWindow_overlay, "type": "StatusColorRadioButton", "unnamed": 1, "visible": True} + + mainWallet_AddEditAccountPopup_Content = {"container": statusDesktop_mainWindow, "objectName": "AddAccountPopup-Content", "type": "Item", "visible": True} mainWallet_AddEditAccountPopup_PrimaryButton = {"container": statusDesktop_mainWindow, "objectName": "AddAccountPopup-PrimaryButton", "type": "StatusButton", "visible": True} mainWallet_AddEditAccountPopup_BackButton = {"container": statusDesktop_mainWindow, "objectName": "AddAccountPopup-BackButton", "type": "StatusBackButton", "visible": True} mainWallet_AddEditAccountPopup_AccountNameComponent = {"container": mainWallet_AddEditAccountPopup_Content, "objectName": "AddAccountPopup-AccountName", "type": "StatusInput", "visible": True} mainWallet_AddEditAccountPopup_AccountName = {"container": mainWallet_AddEditAccountPopup_AccountNameComponent, "id": "edit", "type": "TextEdit", "unnamed": 1, "visible": True} mainWallet_AddEditAccountPopup_AccountColorComponent = {"container": mainWallet_AddEditAccountPopup_Content, "objectName": "AddAccountPopup-AccountColor", "type": "StatusColorSelectorGrid", "visible": True} -mainWallet_AddEditAccountPopup_AccountColorSelector = {"container": mainWallet_AddEditAccountPopup_AccountColorComponent, "type": "Repeater", "objectName": "statusColorRepeater", "visible": True} +mainWallet_AddEditAccountPopup_AccountColorSelector = {"container": mainWallet_AddEditAccountPopup_AccountColorComponent, "type": "Repeater", "objectName": "statusColorRepeater", "visible": True, "enabled": True} mainWallet_AddEditAccountPopup_AccountEmojiPopupButton = {"container": mainWallet_AddEditAccountPopup_Content, "objectName": "AddAccountPopup-AccountEmoji", "type": "StatusFlatRoundButton", "visible": True} -mainWallet_AddEditAccountPopup_AccountEmojiSearchBox = {"container": statusDesktop_mainWindow, "objectName": "StatusEmojiPopup_searchBox", "type": "TextEdit", "visible": True} -mainWallet_AddEditAccountPopup_AccountEmoji = {"container": statusDesktop_mainWindow, "objectName": "statusEmoji_%NAME%", "type": "StatusEmoji", "visible": True} mainWallet_AddEditAccountPopup_SelectedOrigin = {"container": mainWallet_AddEditAccountPopup_Content, "objectName": "AddAccountPopup-SelectedOrigin", "type": "StatusListItem", "visible": True} mainWallet_AddEditAccountPopup_OriginOption_Placeholder = {"container": statusDesktop_mainWindow, "objectName": "AddAccountPopup-OriginOption-%NAME%", "type": "StatusListItem", "visible": True} mainWallet_AddEditAccountPopup_OriginOptionNewMasterKey = {"container": statusDesktop_mainWindow, "objectName": "AddAccountPopup-OriginOption-LABEL-OPTION-ADD-NEW-MASTER-KEY", "type": "StatusListItem", "visible": True} +addAccountPopup_OriginOption_StatusListItem = {"container": statusDesktop_mainWindow_overlay, "type": "StatusListItem", "visible": True} + + mainWallet_AddEditAccountPopup_OriginOptionWatchOnlyAcc = {"container": statusDesktop_mainWindow, "objectName": "AddAccountPopup-OriginOption-LABEL-OPTION-ADD-WATCH-ONLY-ACC", "type": "StatusListItem", "visible": True} mainWallet_AddEditAccountPopup_AccountWatchOnlyAddressComponent = {"container": mainWallet_AddEditAccountPopup_Content, "objectName": "AddAccountPopup-WatchOnlyAddress", "type": "StatusInput", "visible": True} mainWallet_AddEditAccountPopup_AccountWatchOnlyAddress = {"container": mainWallet_AddEditAccountPopup_AccountWatchOnlyAddressComponent, "id": "edit", "type": "TextEdit", "unnamed": 1, "visible": True} @@ -89,7 +120,8 @@ mainWallet_AddEditAccountPopup_RevealSeedPhraseButton = {"container": mainWallet mainWallet_AddEditAccountPopup_SeedPhraseWordAtIndex_Placeholder = {"container": mainWallet_AddEditAccountPopup_Content, "objectName": "SeedPhraseWordAtIndex-%WORD-INDEX%", "type": "StatusSeedPhraseInput", "visible": True} mainWallet_AddEditAccountPopup_EnterSeedPhraseWordComponent = {"container": mainWallet_AddEditAccountPopup_Content, "objectName": "AddAccountPopup-EnterSeedPhraseWord", "type": "StatusInput", "visible": True} mainWallet_AddEditAccountPopup_EnterSeedPhraseWord = {"container": mainWallet_AddEditAccountPopup_EnterSeedPhraseWordComponent, "id": "edit", "type": "TextEdit", "unnamed": 1, "visible": True} - +confirmSeedPhrasePanel_StatusSeedPhraseInput = {"container": statusDesktop_mainWindow, "type": "StatusSeedPhraseInput", "visible": True} +mainWallet_AddEditAccountPopup_SPWord = {"container": mainWallet_AddEditAccountPopup_Content, "type": "TextEdit", "objectName": RegularExpression("statusSeedPhraseInputField*")} mainWallet_AddEditAccountPopup_12WordsButton = {"container": mainWallet_AddEditAccountPopup_Content, "objectName": "12SeedButton", "type": "StatusSwitchTabButton"} mainWallet_AddEditAccountPopup_18WordsButton = {"container": mainWallet_AddEditAccountPopup_Content, "objectName": "18SeedButton", "type": "StatusSwitchTabButton"} mainWallet_AddEditAccountPopup_24WordsButton = {"container": mainWallet_AddEditAccountPopup_Content, "objectName": "24SeedButton", "type": "StatusSwitchTabButton"} @@ -126,13 +158,6 @@ mainWallet_Remove_Account_Popup_HavePenPaperCheckBox = {"checkable": True, "cont mainWallet_Remove_Account_Popup_ConfirmButton = {"container": statusDesktop_mainWindow, "objectName": "RemoveAccountPopup-ConfirmButton", "type": "StatusButton", "visible": True} mainWallet_Remove_Account_Popup_CancelButton = {"container": statusDesktop_mainWindow, "objectName": "RemoveAccountPopup-CancelButton", "type": "StatusFlatButton", "visible": True} -# saved address view -mainWallet_Saved_Addreses_Add_Buttton = {"container": statusDesktop_mainWindow, "objectName": "addNewAddressBtn", "type": "StatusButton"} -mainWallet_Saved_Addreses_List = {"container": statusDesktop_mainWindow, "objectName": "SavedAddressesView_savedAddresses", "type": "StatusListView"} -mainWallet_Saved_Addreses_More_Edit = {"container": statusDesktop_mainWindow, "objectName": "editroot", "type": "StatusMenuItem"} -mainWallet_Saved_Addreses_More_Delete = {"container": statusDesktop_mainWindow, "objectName": "deleteSavedAddress", "type": "StatusMenuItem"} -mainWallet_Saved_Addreses_More_Confirm_Delete = {"container": statusDesktop_mainWindow, "objectName": "confirmDeleteSavedAddress", "type": "StatusButton"} - # saved address add popup mainWallet_Saved_Addreses_Popup_Name_Input = {"container": statusDesktop_mainWindow, "objectName": "savedAddressNameInput", "type": "TextEdit"} mainWallet_Saved_Addreses_Popup_Address_Input = {"container": statusDesktop_mainWindow, "objectName": "savedAddressAddressInput", "type": "StatusInput"} @@ -146,7 +171,8 @@ mainWallet_Collectibles_Repeater = {"container": statusDesktop_mainWindow, "obje # Shared Popup sharedPopup_Popup_Content = {"container": statusDesktop_mainWindow, "objectName": "KeycardSharedPopupContent", "type": "Item"} sharedPopup_Password_Input = {"container": sharedPopup_Popup_Content, "objectName": "keycardPasswordInput", "type": "TextField"} -sharedPopup_Primary_Button = {"container": statusDesktop_mainWindow, "objectName": "PrimaryButton", "type": "StatusButton"} +sharedPopup_Primary_Button = {"container": statusDesktop_mainWindow, "objectName": "PrimaryButton", "type": "StatusButton", "visible": True, "enabled": True} +sharedPopup_Cancel_Button = {"container": statusDesktop_mainWindow_overlay, "type": "StatusButton", "id": "cancelButton", "visible": True} # Transactions view mainWallet_Transactions_List = {"container": statusDesktop_mainWindow, "objectName": "walletAccountTransactionList", "type": "StatusListView"} diff --git a/test/ui-test/testSuites/suite_wallet/shared/scripts/names.py b/test/ui-test/testSuites/suite_wallet/shared/scripts/names.py index c0d02abefe..b0d51a206f 100644 --- a/test/ui-test/testSuites/suite_wallet/shared/scripts/names.py +++ b/test/ui-test/testSuites/suite_wallet/shared/scripts/names.py @@ -1,9 +1,7 @@ # encoding: UTF-8 from objectmaphelper import * - +from scripts.login_names import * from scripts.onboarding_names import * from scripts.settings_names import * -from scripts.login_names import * - -from wallet_names import * \ No newline at end of file +from scripts.wallet_names import * diff --git a/test/ui-test/testSuites/suite_wallet/shared/steps/walletSteps.py b/test/ui-test/testSuites/suite_wallet/shared/steps/walletSteps.py index cab0adf02f..9ddaa399fe 100644 --- a/test/ui-test/testSuites/suite_wallet/shared/steps/walletSteps.py +++ b/test/ui-test/testSuites/suite_wallet/shared/steps/walletSteps.py @@ -1,15 +1,16 @@ -import walletInitSteps as wallet_init_steps - +from common.Common import str_to_bool from screens.StatusMainScreen import StatusMainScreen from screens.StatusWalletScreen import StatusWalletScreen -from screens.StatusWalletScreen import MainWalletRightClickMenu -from screens.StatusWalletScreen import NOT_APPLICABLE, VALUE_YES +from screens.StatusWalletScreen import VALUE_YES +from screens.components.authenticate_popup import AuthenticatePopup from scripts.decorators import verify_screenshot -from common.Common import str_to_bool + +import walletInitSteps as wallet_init_steps _statusMain = StatusMainScreen() _walletScreen = StatusWalletScreen() + ######################### ### PRECONDITIONS region: ######################### @@ -18,6 +19,7 @@ _walletScreen = StatusWalletScreen() def step(context): the_user_accepts_the_signing_phrase() + ######################### ### ACTIONS region: ######################### @@ -30,98 +32,125 @@ def step(context): def step(context): _walletScreen.click_default_wallet_account() + +@When("the user selects wallet account with \"|any|\"") +def step(context, name): + _walletScreen.left_panel.select_account(name) + + @When("the user adds a watch only account \"|any|\" with \"|any|\" color \"|any|\" and emoji \"|any|\" via \"|any|\"") @verify_screenshot def step(context, address, name, color, emoji, via_right_click_menu): if via_right_click_menu == VALUE_YES: - _walletScreen.click_option_from_left_part_right_click_menu(MainWalletRightClickMenu.ADD_WATCH_ONLY_ACCOUNT_ACTION_PLACEHOLDER.value) + account_popup = _walletScreen.left_panel.open_add_watch_anly_account_popup() else: - _walletScreen.open_add_account_popup() - _walletScreen.add_account_popup_change_account_name(name) - _walletScreen.add_account_popup_change_account_color(color) - _walletScreen.add_account_popup_change_account_emoji(emoji) - _walletScreen.add_account_popup_set_watch_only_account_as_selected_origin(address) - _walletScreen.add_account_popup_do_primary_action() + account_popup = _walletScreen.left_panel.open_add_account_popup() + account_popup.set_name(name).set_emoji(emoji).set_color(color).set_origin_eth_address(address).save() + account_popup.wait_until_hidden() -@When("the user adds a generated account with \"|any|\" color \"|any|\" and emoji \"|any|\" via \"|any|\" using password \"|any|\"") + +@When("the user adds a generated account with \"|any|\" color \"|any|\" and emoji \"|any|\" via \"|any|\"") @verify_screenshot -def step(context, name, color, emoji, via_right_click_menu, password): +def step(context, name, color, emoji, via_right_click_menu): if via_right_click_menu == VALUE_YES: - _walletScreen.click_option_from_left_part_right_click_menu(MainWalletRightClickMenu.ADD_NEW_ACCOUNT_ACTION_PLACEHOLDER.value) + account_popup = _walletScreen.left_panel.open_add_new_account_popup() else: - _walletScreen.open_add_account_popup() - _walletScreen.add_account_popup_change_account_name(name) - _walletScreen.add_account_popup_change_account_color(color) - _walletScreen.add_account_popup_change_account_emoji(emoji) - _walletScreen.add_account_popup_do_primary_action(password) + account_popup = _walletScreen.left_panel.open_add_account_popup() + account_popup.set_name(name).set_emoji(emoji).set_color(color).save() + AuthenticatePopup().wait_until_appears().authenticate() + account_popup.wait_until_hidden() -@When("the user adds to \"|any|\" a custom generated account with \"|any|\" color \"|any|\" and emoji \"|any|\" using password \"|any|\" and setting custom path index \"|any|\" or selecting address with \"|any|\" using \"|any|\"") -@verify_screenshot -def step(context, keypair_name, name, color, emoji, password, index, order, is_ethereum_root): - _walletScreen.open_add_account_popup() - _walletScreen.add_account_popup_change_account_name(name) - _walletScreen.add_account_popup_change_account_color(color) - _walletScreen.add_account_popup_change_account_emoji(emoji) - if keypair_name != NOT_APPLICABLE: - _walletScreen.add_account_popup_change_origin_by_keypair_name(keypair_name) - _walletScreen.add_account_popup_open_edit_derivation_path_section(password) - _walletScreen.add_account_popup_change_derivation_path(index, order, is_ethereum_root) - _walletScreen.add_account_popup_do_primary_action() -@When("the user adds a private key account \"|any|\" with \"|any|\" color \"|any|\" and emoji \"|any|\" using password \"|any|\" making keypair with name \"|any|\"") +@When("the user adds a private key account \"|any|\" with \"|any|\" color \"|any|\" and emoji \"|any|\"") @verify_screenshot -def step(context, private_key, name, color, emoji, password, keypair_name): - _walletScreen.open_add_account_popup() - _walletScreen.add_account_popup_change_account_name(name) - _walletScreen.add_account_popup_change_account_color(color) - _walletScreen.add_account_popup_change_account_emoji(emoji) - _walletScreen.add_account_popup_set_new_private_key_as_selected_origin(private_key, keypair_name) - _walletScreen.add_account_popup_do_primary_action(password) +def step(context, private_key, name, color, emoji): + account_popup = _walletScreen.left_panel.open_add_account_popup() + account_popup.set_name(name).set_emoji(emoji).set_color(color).set_origin_private_key(private_key).save() + AuthenticatePopup().wait_until_appears().authenticate() + account_popup.wait_until_hidden() -@When("the user adds an imported seed phrase account \"|any|\" with \"|any|\" color \"|any|\" and emoji \"|any|\" using password \"|any|\" making keypair with name \"|any|\"") -@verify_screenshot -def step(context, seed_phrase, name, color, emoji, password, keypair_name): - _walletScreen.open_add_account_popup() - _walletScreen.add_account_popup_change_account_name(name) - _walletScreen.add_account_popup_change_account_color(color) - _walletScreen.add_account_popup_change_account_emoji(emoji) - _walletScreen.add_account_popup_set_new_seed_phrase_as_selected_origin(seed_phrase, keypair_name) - _walletScreen.add_account_popup_do_primary_action(password) -@When("the user adds a generated seed phrase account with \"|any|\" color \"|any|\" and emoji \"|any|\" using password \"|any|\" making keypair with name \"|any|\"") +@When("the user adds an imported seed phrase account \"|any|\" with \"|any|\" color \"|any|\" and emoji \"|any|\"") @verify_screenshot -def step(context, name, color, emoji, password, keypair_name): - _walletScreen.open_add_account_popup() - _walletScreen.add_account_popup_change_account_name(name) - _walletScreen.add_account_popup_change_account_color(color) - _walletScreen.add_account_popup_change_account_emoji(emoji) - _walletScreen.add_account_popup_set_generated_seed_phrase_as_selected_origin(keypair_name) - _walletScreen.add_account_popup_do_primary_action(password) +def step(context, seed_phrase, name, color, emoji): + account_popup = _walletScreen.left_panel.open_add_account_popup() + account_popup \ + .set_name(name) \ + .set_emoji(emoji) \ + .set_color(color) \ + .set_origin_seed_phrase(seed_phrase.split()) \ + .save() + AuthenticatePopup().wait_until_appears().authenticate() + account_popup.wait_until_hidden() + + +@When("the user adds a custom generated account with \"|any|\" color \"|any|\" emoji \"|any|\" and derivation \"|any|\" \"|any|\"") +@verify_screenshot +def step(context, name, color, emoji, derivation_path, generated_address_index): + account_popup = _walletScreen.left_panel.open_add_account_popup() + account_popup \ + .set_name(name) \ + .set_emoji(emoji) \ + .set_color(color) \ + .set_derivation_path(derivation_path, generated_address_index) \ + .save() + +@When("the user adds to \"|any|\" a custom generated account with \"|any|\" color \"|any|\" emoji \"|any|\" and derivation \"|any|\" \"|any|\"") +@verify_screenshot +def step(context, keypair_name, name, color, emoji, derivation_path, generated_address_index): + account_popup = _walletScreen.left_panel.open_add_account_popup() + account_popup \ + .set_name(name) \ + .set_emoji(emoji) \ + .set_color(color) \ + .set_derivation_path(derivation_path, generated_address_index) \ + .set_origin_keypair(keypair_name) \ + .save() + + +@When( + "the user adds a generated seed phrase account with \"|any|\" color \"|any|\" emoji \"|any|\" and keypair \"|any|\"") +def step(context, name, color, emoji, keypair_name): + account_popup = _walletScreen.left_panel.open_add_account_popup() + account_popup \ + .set_name(name) \ + .set_emoji(emoji) \ + .set_color(color) \ + .set_origin_new_seed_phrase(keypair_name) \ + .save() + AuthenticatePopup().wait_until_appears().authenticate() + account_popup.wait_until_hidden() + @When("the user adds new master key and go to use a Keycard") def step(context): - _walletScreen.open_add_account_popup() + _walletScreen.left_panel.open_add_account_popup() _walletScreen.add_account_popup_go_to_keycard_settings() + @When("the user edits an account with \"|any|\" to \"|any|\" with color \"|any|\" and emoji \"|any|\"") def step(context, name, new_name, new_color, new_emoji): - _walletScreen.click_option_from_right_click_menu_of_account_with_name(MainWalletRightClickMenu.EDIT_ACCOUNT_ACTION_PLACEHOLDER.value, name) - _walletScreen.add_account_popup_change_account_name(new_name) - _walletScreen.add_account_popup_change_account_color(new_color) - _walletScreen.add_account_popup_change_account_emoji(new_emoji) - _walletScreen.add_account_popup_do_primary_action() + account_popup = _walletScreen.left_panel.open_edit_account_popup(name) + account_popup.set_name(new_name).set_emoji(new_emoji).set_color(new_color).save() -@When("the user removes an account with name \"|any|\" and path \"|any|\" using password \"|any|\" and test cancel \"|any|\"") -def step(context, name, path, password, test_cancel): - _walletScreen.click_option_from_right_click_menu_of_account_with_name(MainWalletRightClickMenu.DELETE_ACCOUNT_ACTION_PLACEHOLDER.value, name) - _walletScreen.remove_account_popup_verify_account_account_to_be_removed(name, path) - if test_cancel == VALUE_YES: - _walletScreen.remove_account_popup_do_cancel_action() - _walletScreen.click_option_from_right_click_menu_of_account_with_name(MainWalletRightClickMenu.DELETE_ACCOUNT_ACTION_PLACEHOLDER.value, name) - _walletScreen.remove_account_popup_verify_account_account_to_be_removed(name, path) - _walletScreen.remove_account_popup_do_remove_action(True if path != NOT_APPLICABLE else False, password) -@When("the user sends a transaction to himself from account \"|any|\" of \"|any|\" \"|any|\" on \"|any|\" with password \"|any|\"") +@When("the user removes account \"|any|\"") +def step(context, name): + _walletScreen.left_panel.delete_account(name).confirm() + + +@When("the user start removing account \"|any|\" and cancel it") +def step(context, name): + _walletScreen.left_panel.delete_account(name).cancel() + + +@When("the user removes account \"|any|\" with agreement") +def step(context, name): + _walletScreen.left_panel.delete_account(name).agree_and_confirm() + + +@When( + "the user sends a transaction to himself from account \"|any|\" of \"|any|\" \"|any|\" on \"|any|\" with password \"|any|\"") def step(context, account_name, amount, token, chain_name, password): _walletScreen.send_transaction(account_name, amount, token, chain_name, password) @@ -137,14 +166,17 @@ def step(context, name, ens_name): def step(context, name, new_name): _walletScreen.edit_saved_address(name, new_name) + @When("the user deletes the saved address with name \"|any|\"") def step(context, name): _walletScreen.delete_saved_address(name) + @When("the user toggles favourite for the saved address with name \"|any|\"") def step(context, name): _walletScreen.toggle_favourite_for_saved_address(name) + @When("the user toggles the network |any|") def step(context, network_name): _walletScreen.toggle_network(network_name) @@ -154,7 +186,7 @@ def step(context, network_name): ### VERIFICATIONS region: ######################### -@Then("the account is correctly displayed with \"|any|\" and \"|any|\" and emoji unicode \"|any|\"") +@Then("the account is correctly displayed with \"|any|\" and \"|any|\" and emoji unicode \"|any|\" in accounts list") def step(context, name, color, emoji_unicode): _walletScreen.verify_account_existence(name, color, emoji_unicode) @@ -166,6 +198,7 @@ def step(context): def step(context, name): _walletScreen.verify_account_doesnt_exist(name) + @Then("the user has a positive balance of \"|any|\"") def step(context, symbol): _walletScreen.verify_positive_balance(symbol) diff --git a/test/ui-test/testSuites/suite_wallet/tst_wallet/bdd_hooks.py b/test/ui-test/testSuites/suite_wallet/tst_wallet/bdd_hooks.py index b7ed9a5b93..d8e4ce1ac1 100644 --- a/test/ui-test/testSuites/suite_wallet/tst_wallet/bdd_hooks.py +++ b/test/ui-test/testSuites/suite_wallet/tst_wallet/bdd_hooks.py @@ -12,17 +12,20 @@ import walletInitSteps as wallet_init_steps _user = "tester123" _password = "TesTEr16843/!@00" + @OnFeatureStart def hook(context): init_steps.context_init(context, testSettings) init_steps.signs_up_process_steps(context, _user, _password) wallet_init_steps.open_wallet() + @OnFeatureEnd def hook(context): currentApplicationContext().detach() snooze(_app_closure_timeout) - + + @OnStepEnd def hook(context): context.userData["step_name"] = context._data["text"] diff --git a/test/ui-test/testSuites/suite_wallet/tst_wallet_section_accounts_management/bdd_hooks.py b/test/ui-test/testSuites/suite_wallet/tst_wallet_section_accounts_management/bdd_hooks.py index b7ed9a5b93..85e4206938 100644 --- a/test/ui-test/testSuites/suite_wallet/tst_wallet_section_accounts_management/bdd_hooks.py +++ b/test/ui-test/testSuites/suite_wallet/tst_wallet_section_accounts_management/bdd_hooks.py @@ -6,23 +6,28 @@ sys.path.append(os.path.join(os.path.dirname(__file__), "../../../src/")) sys.path.append(os.path.join(os.path.dirname(__file__), "../shared/steps/")) import steps.commonInitSteps as init_steps -import walletInitSteps as wallet_init_steps # Global properties for the specific feature _user = "tester123" _password = "TesTEr16843/!@00" + @OnFeatureStart def hook(context): init_steps.context_init(context, testSettings) - init_steps.signs_up_process_steps(context, _user, _password) - wallet_init_steps.open_wallet() + @OnFeatureEnd def hook(context): currentApplicationContext().detach() snooze(_app_closure_timeout) - + + @OnStepEnd def hook(context): context.userData["step_name"] = context._data["text"] + + +@OnScenarioEnd +def hook(context): + [ctx.detach() for ctx in squish.applicationContextList()] diff --git a/test/ui-test/testSuites/suite_wallet/tst_wallet_section_accounts_management/test.feature b/test/ui-test/testSuites/suite_wallet/tst_wallet_section_accounts_management/test.feature index 81ac2580c4..c5593ae75f 100644 --- a/test/ui-test/testSuites/suite_wallet/tst_wallet_section_accounts_management/test.feature +++ b/test/ui-test/testSuites/suite_wallet/tst_wallet_section_accounts_management/test.feature @@ -2,175 +2,150 @@ Feature: Status Desktop Wallet Section Wallet Account Management As a user I want to add edit remove different types of wallet accounts - The feature start sequence is the following (setup on its own `bdd_hooks`): + Background: + Given A first time user lands on the status desktop and generates new key + Given the user signs up with username "tester123" and password "TesTEr16843/!@00" + And the user lands on the signed in app + And the user opens the wallet section + And the user accepts the signing phrase - ** 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 the user opens the wallet section - ** and the user accepts the signing phrase - - @mayfail - Scenario Outline: The user edits default wallet account - When the user clicks on the default wallet account + Scenario Outline: The user edits default wallet account + When the user selects wallet account with "" And the user edits an account with "" to "" with color "#" and emoji "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" - + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list Examples: - | name | new_name | new_color | new_emoji | new_emoji_unicode | - | Status account | My Primary Account | 7CDA00 | sunglasses | 1f60e | + | name | new_name | new_color | new_emoji | new_emoji_unicode | + | Status account | MyPrimaryAccount | 7CDA00 | sunglasses | 1f60e | - @mayfail - Scenario Outline: The user manages a watch only account + Scenario Outline: The user manages a watch only account When the user adds a watch only account "
" with "" color "#" and emoji "" via "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list When the user edits an account with "" to "" with color "#" and emoji "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" - When the user removes an account with name "" and path "" using password "" and test cancel "yes" - Then the account with "" is not displayed + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + When the user removes account "" + Then the account with "" is not displayed + Examples: + | address | name | color | emoji | emoji_unicode | add_via_context_menu | new_name | new_color | new_emoji | new_emoji_unicode | + | 0xea123F7beFF45E3C9fdF54B324c29DBdA14a639A | AccWatch1 | 2946C4 | sunglasses | 1f60e | yes | AccWatch1edited | 7CDA00 | thumbsup | 1f44d | + | 0xea123F7beFF45E3C9fdF54B324c29DBdA14a639B | AccWatch2 | D37EF4 | sunglasses | 1f60e | no | AccWatch2edited | 26A69A | thumbsup | 1f44d | + + Scenario Outline: The user cancel deliting watch only account + When the user adds a watch only account "
" with "" color "#" and emoji "" via "" + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + When the user start removing account "" and cancel it + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + Examples: + | address | name | color | emoji | emoji_unicode | + | 0xea123F7beFF45E3C9fdF54B324c29DBdA14a639A | AccWatch1 | 2946C4 | sunglasses | 1f60e | + + + Scenario Outline: The user manages a generated account + When the user adds a generated account with "" color "#" and emoji "" via "" + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + When the user edits an account with "" to "" with color "#" and emoji "" + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + When the user removes account "" with agreement + Then the account with "" is not displayed Examples: - | password | address | path | name | color | emoji | emoji_unicode | add_via_context_menu | new_name | new_color | new_emoji | new_emoji_unicode | - | N/A | 0xea123F7beFF45E3C9fdF54B324c29DBdA14a639A | N/A | AccWatch_1 | 2946C4 | sunglasses | 1f60e | yes | AccWatch_1_edited | 7CDA00 | thumbsup | 1f44d | - | N/A | 0xea123F7beFF45E3C9fdF54B324c29DBdA14a639B | N/A | AccWatch_2 | D37EF4 | sunglasses | 1f60e | no | AccWatch_2_edited | 26A69A | thumbsup | 1f44d | + | name | color | emoji | emoji_unicode | add_via_context_menu | new_name | new_color | new_emoji | new_emoji_unicode | + | GenAcc1 | 2946C4 | sunglasses | 1f60e | yes | GenAcc1edited | 7CDA00 | thumbsup | 1f44d | + | GenAcc2 | D37EF4 | sunglasses | 1f60e | no | GenAcc2edited | 26A69A | thumbsup | 1f44d | - ################################################################## - # The following 2 scenarions have to be executed one after another, - # cause the second depends on the state made in the first one - # - # - Scenario Outline: The user manages a generated account - # - Scenario Outline: The user manages a custom generated account - ################################################################## - @mayfail - Scenario Outline: The user manages a generated account - When the user adds a generated account with "" color "#" and emoji "" via "" using password "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" - When the user edits an account with "" to "" with color "#" and emoji "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" - When the user removes an account with name "" and path "" using password "" and test cancel "yes" - Then the account with "" is not displayed + Scenario Outline: The user cancel deliting generated account + When the user adds a generated account with "" color "#" and emoji "" via "" + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + When the user start removing account "" and cancel it + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + Examples: + | name | color | emoji | emoji_unicode | add_via_context_menu | + | GenAcc1 | 2946C4 | sunglasses | 1f60e | yes | + + + Scenario Outline: The user manages a custom generated account + When the user adds a custom generated account with "" color "#" emoji "" and derivation "" "" + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + When the user removes account "" with agreement + Then the account with "" is not displayed Examples: - | password | path | name | color | emoji | emoji_unicode | add_via_context_menu | new_name | new_color | new_emoji | new_emoji_unicode | - | TesTEr16843/!@00 | m/44'/60'/0'/0/1 | GenAcc_1 | 2946C4 | sunglasses | 1f60e | yes | GenAcc_1_edited | 7CDA00 | thumbsup | 1f44d | - | TesTEr16843/!@00 | m/44'/60'/0'/0/2 | GenAcc_2 | D37EF4 | sunglasses | 1f60e | no | GenAcc_2_edited | 26A69A | thumbsup | 1f44d | + | address_index | path | name | color | emoji | emoji_unicode | + | 5 | Ethereum | CustomGenAcc1 | 7CDA00 | sunglasses | 1f60e | + | 10 | Ethereum Testnet (Ropsten) | CustomGenAcc2 | D37EF4 | sunglasses | 1f60e | + | 15 | Ethereum (Ledger) | CustomGenAcc3 | 26A69A | sunglasses | 1f60e | + | 20 | Ethereum (Ledger Live/KeepKey) | CustomGenAcc4 | D37EF4 | sunglasses | 1f60e | + | 95 | N/A | CustomGenAcc1 | 7CDA00 | sunglasses | 1f60e | - @mayfail - Scenario Outline: The user manages a custom generated account - When the user adds to "N/A" a custom generated account with "" color "#" and emoji "" using password "" and setting custom path index "" or selecting address with "" using "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" - When the user removes an account with name "" and path "" using password "" and test cancel "no" - Then the account with "" is not displayed + + Scenario Outline: The user manages a private key imported account + When the user adds a private key account "" with "" color "#" and emoji "" + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + When the user edits an account with "" to "" with color "#" and emoji "" + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + When the user removes account "" + Then the account with "" is not displayed Examples: - | is_ethereum_root | index | order | password | path | name | color | emoji | emoji_unicode | - | yes | N/A | N/A | TesTEr16843/!@00 | m/44'/60'/0'/0/3 | CustomGenAcc_1 | 7CDA00 | sunglasses | 1f60e | - | yes | 10 | N/A | TesTEr16843/!@00 | m/44'/60'/0'/0/10 | CustomGenAcc_2 | D37EF4 | sunglasses | 1f60e | - | yes | N/A | 99 | TesTEr16843/!@00 | m/44'/60'/0'/0/99 | CustomGenAcc_3 | 26A69A | sunglasses | 1f60e | - | no | 10 | N/A | TesTEr16843/!@00 | m/44'/1'/0'/0/10 | CustomGenAcc_4 | D37EF4 | sunglasses | 1f60e | - | no | N/A | 99 | TesTEr16843/!@00 | m/44'/1'/0'/0/99 | CustomGenAcc_5 | 26A69A | sunglasses | 1f60e | + | private_key | name | color | emoji | emoji_unicode | new_name | new_color | new_emoji | new_emoji_unicode | + | 2daa36a3abe381a9c01610bf10fda272fbc1b8a22179a39f782c512346e3e470 | PrivKeyAcc1 | 2946C4 | sunglasses | 1f60e | PrivKeyAcc1edited | 7CDA00 | thumbsup | 1f44d | - ################################################################## - @mayfail - Scenario Outline: The user manages a private key imported account - When the user adds a private key account "" with "" color "#" and emoji "" using password "" making keypair with name "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" + Scenario Outline: The user manages a seed phrase imported account + When the user adds an imported seed phrase account "" with "" color "#" and emoji "" + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list When the user edits an account with "" to "" with color "#" and emoji "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" - When the user removes an account with name "" and path "" using password "" and test cancel "no" - Then the account with "" is not displayed - - Examples: - | password | keypair_name | private_key | path | name | color | emoji | emoji_unicode | new_name | new_color | new_emoji | new_emoji_unicode | - | TesTEr16843/!@00 | PrivateKeyKeypair | 2daa36a3abe381a9c01610bf10fda272fbc1b8a22179a39f782c512346e3e470 | N/A | PrivKeyAcc_1 | 2946C4 | sunglasses | 1f60e | PrivKeyAcc_1_edited | 7CDA00 | thumbsup | 1f44d | - - @mayfail - Scenario Outline: The user manages a seed phrase imported account - When the user adds an imported seed phrase account "" with "" color "#" and emoji "" using password "" making keypair with name "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" - When the user edits an account with "" to "" with color "#" and emoji "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" - When the user removes an account with name "" and path "" using password "" and test cancel "no" - Then the account with "" is not displayed - - Examples: - | password | keypair_name | path | seed_phrase | name | color | emoji | emoji_unicode | new_name | new_color | new_emoji | new_emoji_unicode | - | TesTEr16843/!@00 | SPKeyPair24 | m/44'/60'/0'/0/0 | elite dinosaur flavor canoe garbage palace antique dolphin virtual mixed sand impact solution inmate hair pipe affair cage vote estate gloom lamp robust like | SPAcc_24 | 2946C4 | sunglasses | 1f60e | SPAcc_24_edited | 7CDA00 | thumbsup | 1f44d | - | TesTEr16843/!@00 | SPKeyPair18 | m/44'/60'/0'/0/0 | kitten tiny cup admit cactus shrug shuffle accident century faith roof plastic beach police barely vacant sign blossom | SPAcc_18 | 2946C4 | sunglasses | 1f60e | SPAcc_18_edited | 7CDA00 | thumbsup | 1f44d | - | TesTEr16843/!@00 | SPKeyPair12 | m/44'/60'/0'/0/0 | pelican chief sudden oval media rare swamp elephant lawsuit wheat knife initial | SPAcc_12 | 2946C4 | sunglasses | 1f60e | SPAcc_12_edited | 7CDA00 | thumbsup | 1f44d | - - ################################################################## - # The following 2 scenarions have to be executed one after another, - # cause the second depends on the state made in the first one - # - # - Scenario Outline: The user adds an account from the imported seed phrase - # - Scenario Outline: The user manages an account created from the imported seed phrase - ################################################################## - - @mayfail - Scenario Outline: The user adds an account from the imported seed phrase - When the user adds an imported seed phrase account "" with "" color "#" and emoji "" using password "" making keypair with name "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" - - Examples: - | password | keypair_name | path | seed_phrase | name | color | emoji | emoji_unicode | - | TesTEr16843/!@00 | SPKeyPair12 | m/44'/60'/0'/0/0 | pelican chief sudden oval media rare swamp elephant lawsuit wheat knife initial | SPAcc_12 | 2946C4 | sunglasses | 1f60e | - - @mayfail - Scenario Outline: The user manages an account created from the imported seed phrase - When the user adds to "" a custom generated account with "" color "#" and emoji "" using password "" and setting custom path index "" or selecting address with "" using "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" - When the user removes an account with name "" and path "" using password "" and test cancel "no" - Then the account with "" is not displayed + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + When the user removes account "" with agreement + Then the account with "" is not displayed Examples: - | keypair_name | is_ethereum_root | index | order | password | path | name | color | emoji | emoji_unicode | - | SPKeyPair12 | yes | N/A | N/A | TesTEr16843/!@00 | m/44'/60'/0'/0/1 | CustomGenAcc_1 | 7CDA00 | sunglasses | 1f60e | - | SPKeyPair12 | yes | 10 | N/A | TesTEr16843/!@00 | m/44'/60'/0'/0/10 | CustomGenAcc_2 | D37EF4 | sunglasses | 1f60e | - | SPKeyPair12 | yes | N/A | 99 | TesTEr16843/!@00 | m/44'/60'/0'/0/99 | CustomGenAcc_3 | 26A69A | sunglasses | 1f60e | - | SPKeyPair12 | no | 10 | N/A | TesTEr16843/!@00 | m/44'/1'/0'/0/10 | CustomGenAcc_4 | D37EF4 | sunglasses | 1f60e | - | SPKeyPair12 | no | N/A | 99 | TesTEr16843/!@00 | m/44'/1'/0'/0/99 | CustomGenAcc_5 | 26A69A | sunglasses | 1f60e | + | seed_phrase | name | color | emoji | emoji_unicode | new_name | new_color | new_emoji | new_emoji_unicode | + | elite dinosaur flavor canoe garbage palace antique dolphin virtual mixed sand impact solution inmate hair pipe affair cage vote estate gloom lamp robust like | SPAcc24 | 2946C4 | sunglasses | 1f60e | SPAcc24edited | 7CDA00 | thumbsup | 1f44d | + | kitten tiny cup admit cactus shrug shuffle accident century faith roof plastic beach police barely vacant sign blossom | SPAcc18 | 2946C4 | sunglasses | 1f60e | SPAcc18edited | 7CDA00 | thumbsup | 1f44d | + | pelican chief sudden oval media rare swamp elephant lawsuit wheat knife initial | SPAcc12 | 2946C4 | sunglasses | 1f60e | SPAcc12edited | 7CDA00 | thumbsup | 1f44d | - ################################################################## - ################################################################## - # The following 2 scenarions have to be executed one after another, - # cause the second depends on the state made in the first one - # - # - Scenario Outline: The user adds and edits an account from the generated seed phrase - # - Scenario Outline: The user manages an account created from the generated seed phrase - ################################################################## - - @mayfail - Scenario Outline: The user adds and edits an account from the generated seed phrase - When the user adds a generated seed phrase account with "" color "#" and emoji "" using password "" making keypair with name "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" - When the user edits an account with "" to "" with color "#" and emoji "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" - - Examples: - | password | keypair_name | name | color | emoji | emoji_unicode | new_name | new_color | new_emoji | new_emoji_unicode | - | TesTEr16843/!@00 | SPKeyPair | SPAcc | 2946C4 | sunglasses | 1f60e | SPAcc_edited | 7CDA00 | thumbsup | 1f44d | - - @mayfail - Scenario Outline: The user manages an account created from the generated seed phrase - When the user adds to "" a custom generated account with "" color "#" and emoji "" using password "" and setting custom path index "" or selecting address with "" using "" - Then the account is correctly displayed with "" and "#" and emoji unicode "" - When the user removes an account with name "" and path "" using password "" and test cancel "no" - Then the account with "" is not displayed + Scenario Outline: The user manages an account created from the imported seed phrase + When the user adds an imported seed phrase account "pelican chief sudden oval media rare swamp elephant lawsuit wheat knife initial" with "SPAcc12" color "#2946C4" and emoji "sunglasses" + And the user adds to "pcsomrselw" a custom generated account with "" color "#" emoji "" and derivation "" "" + And the user removes account "" with agreement + Then the account with "" is not displayed Examples: - | keypair_name | is_ethereum_root | index | order | password | path | name | color | emoji | emoji_unicode | - | SPKeyPair | yes | N/A | N/A | TesTEr16843/!@00 | m/44'/60'/0'/0/1 | CustomGenAcc_1 | 7CDA00 | sunglasses | 1f60e | - | SPKeyPair | yes | 10 | N/A | TesTEr16843/!@00 | m/44'/60'/0'/0/10 | CustomGenAcc_2 | D37EF4 | sunglasses | 1f60e | - | SPKeyPair | yes | N/A | 99 | TesTEr16843/!@00 | m/44'/60'/0'/0/99 | CustomGenAcc_3 | 26A69A | sunglasses | 1f60e | - | SPKeyPair | no | 10 | N/A | TesTEr16843/!@00 | m/44'/1'/0'/0/10 | CustomGenAcc_4 | D37EF4 | sunglasses | 1f60e | - | SPKeyPair | no | N/A | 99 | TesTEr16843/!@00 | m/44'/1'/0'/0/99 | CustomGenAcc_5 | 26A69A | sunglasses | 1f60e | - ################################################################## + | address_index | path | name | color | emoji | + | 5 | Ethereum | CustomGenAcc1 | 7CDA00 | sunglasses | + | 10 | Ethereum Testnet (Ropsten) | CustomGenAcc2 | D37EF4 | sunglasses | + | 15 | Ethereum (Ledger) | CustomGenAcc3 | 26A69A | sunglasses | + | 20 | Ethereum (Ledger Live/KeepKey) | CustomGenAcc4 | D37EF4 | sunglasses | + | 95 | N/A | CustomGenAcc1 | 7CDA00 | sunglasses | - @mayfail - Scenario: The user adds an account and then decides to use a Keycard - When the user adds new master key and go to use a Keycard - Then settings keycard section is opened \ No newline at end of file + + Scenario Outline: The user adds and edits an account from the generated seed phrase + When the user adds a generated seed phrase account with "" color "#" emoji "" and keypair "" + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + When the user edits an account with "" to "" with color "#" and emoji "" + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + + Examples: + | keypair_name | name | color | emoji | emoji_unicode | new_name | new_color | new_emoji | new_emoji_unicode | + | SPKeyPair | SPAcc | 2946C4 | sunglasses | 1f60e | SPAcc_edited | 7CDA00 | thumbsup | 1f44d | + + Scenario Outline: The user manages an account created from the generated seed phrase + When the user adds a generated seed phrase account with "SPKeyPair" color "#" emoji "" and keypair "" + And the user adds to "" a custom generated account with "" color "#" emoji "" and derivation "" "" + Then the account is correctly displayed with "" and "#" and emoji unicode "" in accounts list + When the user removes account "" with agreement + Then the account with "" is not displayed + Examples: + | address_index | path | name | color | emoji | emoji_unicode | keypair_name | + | 5 | Ethereum | CustomGenAcc1 | 7CDA00 | sunglasses | 1f60e | SPKeyPair | + | 10 | Ethereum Testnet (Ropsten) | CustomGenAcc2 | D37EF4 | sunglasses | 1f60e | SPKeyPair | + | 15 | Ethereum (Ledger) | CustomGenAcc3 | 26A69A | sunglasses | 1f60e | SPKeyPair | + | 20 | Ethereum (Ledger Live/KeepKey) | CustomGenAcc4 | D37EF4 | sunglasses | 1f60e | SPKeyPair | + | 95 | N/A | CustomGenAcc1 | 7CDA00 | sunglasses | 1f60e | SPKeyPair | + + @mayfail + Scenario: The user adds an account and then decides to use a Keycard + When the user adds new master key and go to use a Keycard + Then settings keycard section is opened \ No newline at end of file diff --git a/test/ui-test/testSuites/suite_wallet/tst_wallet_section_accounts_management/test.py b/test/ui-test/testSuites/suite_wallet/tst_wallet_section_accounts_management/test.py index e69956ffa6..6e5a030efe 100644 --- a/test/ui-test/testSuites/suite_wallet/tst_wallet_section_accounts_management/test.py +++ b/test/ui-test/testSuites/suite_wallet/tst_wallet_section_accounts_management/test.py @@ -1,7 +1,7 @@ source(findFile('scripts', 'python/bdd.py')) setupHooks('bdd_hooks.py') -collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/') +collectStepDefinitions('./steps', '../shared/steps/', '../../global_shared/steps/', '../../suite_onboarding/shared/steps/') def main(): testSettings.throwOnFailure = True