Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests(Settings): Can backup seed phrase #7050

Merged
merged 1 commit into from
Aug 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions test/ui-test/src/drivers/SquishDriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,16 @@ def click_obj_by_wildcards_name(objName: str, wildcardString: str):
obj = squish.waitForObject(wildcardRealName)
squish.mouseClick(obj, squish.Qt.LeftButton)

# Replaces all occurrences of objectNamePlaceholder with newValue in the objectName from the realName
# Then use the new objectName as a wildcard search pattern, waiting for the object with the new Real Name
# and return it if found. Raise an exception if not found.
def wait_by_wildcards(realNameVarName: str, objectNamePlaceholder: str, newValue: str, timeoutMSec: int = _MAX_WAIT_OBJ_TIMEOUT):
wildcardRealName = copy.deepcopy(getattr(names, realNameVarName))
newObjectName = wildcardRealName["objectName"].replace(objectNamePlaceholder, newValue)
wildcardRealName["objectName"] = Wildcard(newObjectName)

return squish.waitForObject(wildcardRealName, timeoutMSec)

# It executes the right-click action into object with given object name:
def right_click_obj_by_name(objName: str):
obj = squish.waitForObject(getattr(names, objName))
Expand Down Expand Up @@ -243,7 +253,7 @@ def _find_link(objName: str, link: str):
squish.uninstallSignalHandler(obj, "linkHovered(QString)", "_handle_link_hovered")
return [-1, -1]

def expectTrue(assertionValue: bool, message: str):
def expect_true(assertionValue: bool, message: str):
return test.verify(assertionValue, message)

# Wait for the object to appear and, assuming it is already focused
Expand Down Expand Up @@ -273,4 +283,12 @@ def scroll_list_view_at_index(list_obj, index: int, timeout: int=_MAX_WAIT_OBJ_T
squish.mouseWheel(list_obj, int(list_obj.x + list_obj.width/2), int(list_obj.y + list_obj.height/2), 0, -1, squish.Qt.ControlModifier)
squish.snooze(1)
current_time = time.time() * 1000
return False
return False

# Fail if the object is found and pass if not found
def verify_not_found(realNameVarName: str, message: str, timeoutMSec: int = 500):
try:
squish.waitForObject(getattr(names, realNameVarName), timeoutMSec)
test.fail(message, f'Unexpected: the object "{realNameVarName}" was found.')
except LookupError as err:
test.passes(message, f'Expected: the object "{realNameVarName}" was not found. Exception: {str(err)}.')
58 changes: 57 additions & 1 deletion test/ui-test/src/screens/SettingsScreen.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class WalletSettingsScreen(Enum):
EDIT_ACCOUNT_COLOR_REPEATER: str = "settings_Wallet_AccountView_EditAccountColorRepeater"
EDIT_ACCOUNT_SAVE_BUTTON: str = "settings_Wallet_AccountView_EditAccountSaveButton"
ACCOUNT_VIEW_ACCOUNT_NAME: str = "settings_Wallet_AccountView_AccountName"
ACCOUNT_VIEW_ICON_SETTINGS: str = "settings_Wallet_AccountView_IconSettings"
ACCOUNT_VIEW_ICON_SETTINGS: str = "settings_Wallet_AccountView_IconSettings"
BACKUP_SEED_PHRASE_BUTTON: str = "settings_Wallet_MainView_BackupSeedPhrase"

class ProfileSettingsScreen(Enum):
DISPLAY_NAME: str = "displayName_TextEdit"
Expand All @@ -75,6 +76,20 @@ class CommunitiesSettingsScreen(Enum):
LEAVE_COMMUNITY_BUTTONS: str = "settings_Communities_MainView_LeaveCommunityButtons"
LEAVE_COMMUNITY_POPUP_LEAVE_BUTTON: str = "settings_Communities_MainView_LeavePopup_LeaveCommunityButton"

class BackupSeedPhrasePopup(Enum):
HAVE_PEN_CHECKBOX: str = "backup_seed_phrase_popup_Acknowledgements_havePen_checkbox"
WRITE_DOWN_CHECKBOX: str = "backup_seed_phrase_popup_Acknowledgements_writeDown_checkbox"
STORE_IT_CHECKBOX: str = "backup_seed_phrase_popup_Acknowledgements_storeIt_checkbox"
NEXT_BUTTON: str = "backup_seed_phrase_popup_nextButton"
REVEAL_SEED_PHRASE_BUTTON: str = "backup_seed_phrase_popup_ConfirmSeedPhrasePanel_RevealSeedPhraseButton"
SEED_PHRASE_WORD_PLACEHOLDER: str = "backup_seed_phrase_popup_ConfirmSeedPhrasePanel_StatusSeedPhraseInput_placeholder"
CONFIRM_FIRST_WORD_PAGE: str = "backup_seed_phrase_popup_BackupSeedStepBase_confirmFirstWord"
CONFIRM_FIRST_WORD_INPUT: str = "backup_seed_phrase_popup_BackupSeedStepBase_confirmFirstWord_inputText"
CONFIRM_SECOND_WORD_PAGE: str = "backup_seed_phrase_popup_BackupSeedStepBase_confirmSecondWord"
CONFIRM_SECOND_WORD_INPUT: str = "backup_seed_phrase_popup_BackupSeedStepBase_confirmSecondWord_inputText"
CONFIRM_YOU_STORED_CHECKBOX: str = "backup_seed_phrase_popup_ConfirmStoringSeedPhrasePanel_storeCheck"
CONFIRM_YOU_STORED_BUTTON: str = "backup_seed_phrase_popup_BackupSeedModal_completeAndDeleteSeedPhraseButton"

class SettingsScreen:
__pid = 0

Expand Down Expand Up @@ -244,3 +259,44 @@ def verify_social_links(self, twitter, personal_site, custom_link_name, custom_l
verify_text_matching(ProfileSettingsScreen.CUSTOM_LINK_IN_DIALOG.value, custom_link_name)
verify_text_matching(ProfileSettingsScreen.CUSTOM_URL_IN_DIALOG.value, custom_link)
click_obj_by_name(ProfileSettingsScreen.CLOSE_SOCIAL_LINKS_DIALOG.value)

def check_backup_seed_phrase_workflow(self):
self.open_wallet_settings()
click_obj_by_name(WalletSettingsScreen.BACKUP_SEED_PHRASE_BUTTON.value)

# Check all checkboxes and click next button
obj = wait_and_get_obj(BackupSeedPhrasePopup.HAVE_PEN_CHECKBOX.value)
obj.checked = True
obj = wait_and_get_obj(BackupSeedPhrasePopup.WRITE_DOWN_CHECKBOX.value)
obj.checked = True
obj = wait_and_get_obj(BackupSeedPhrasePopup.STORE_IT_CHECKBOX.value)
obj.checked = True
click_obj_by_name(BackupSeedPhrasePopup.NEXT_BUTTON.value)

# Show seed phrase
click_obj_by_name(BackupSeedPhrasePopup.REVEAL_SEED_PHRASE_BUTTON.value)

# Collect word phrases for the next random confirmation steps
seed_phrase = [wait_by_wildcards(BackupSeedPhrasePopup.SEED_PHRASE_WORD_PLACEHOLDER.value, "%WORD_NO%", str(i + 1)).textEdit.input.edit.text for i in range(12)]
click_obj_by_name(BackupSeedPhrasePopup.NEXT_BUTTON.value)

# Confirm first random word of the seed phrase
firstSeedBaseObj = wait_and_get_obj(BackupSeedPhrasePopup.CONFIRM_FIRST_WORD_PAGE.value)
firstSeedWord = str(seed_phrase[firstSeedBaseObj.wordRandomNumber])
wait_for_object_and_type(BackupSeedPhrasePopup.CONFIRM_FIRST_WORD_INPUT.value, firstSeedWord)
click_obj_by_name(BackupSeedPhrasePopup.NEXT_BUTTON.value)

# Confirm second random word of the seed phrase
secondSeedBaseObj = wait_and_get_obj(BackupSeedPhrasePopup.CONFIRM_SECOND_WORD_PAGE.value)
secondSeedWord = str(seed_phrase[secondSeedBaseObj.wordRandomNumber])
wait_for_object_and_type(BackupSeedPhrasePopup.CONFIRM_SECOND_WORD_INPUT.value, secondSeedWord)

click_obj_by_name(BackupSeedPhrasePopup.NEXT_BUTTON.value)

# Acknowledge and confirm that you won't have access to the seed phrase anymore
obj = wait_and_get_obj(BackupSeedPhrasePopup.CONFIRM_YOU_STORED_CHECKBOX.value)
obj.checked = True
click_obj_by_name(BackupSeedPhrasePopup.CONFIRM_YOU_STORED_BUTTON.value)

def verify_seed_phrase_indicator_not_visible(self):
verify_not_found(WalletSettingsScreen.BACKUP_SEED_PHRASE_BUTTON.value, "Check that backup seed phrase settings button is visible")
6 changes: 3 additions & 3 deletions test/ui-test/src/screens/StatusCommunityScreen.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ def edit_community(self, new_community_name: str, new_community_description: str
verify_text_matching(CommunitySettingsComponents.COMMUNITY_NAME_TEXT.value, new_community_name)
verify_text_matching(CommunitySettingsComponents.COMMUNITY_DESCRIPTION_TEXT.value, new_community_description)
obj = get_obj(CommunitySettingsComponents.COMMUNITY_LETTER_IDENTICON.value)
expectTrue(obj.color.name == new_community_color, "Community color was not changed correctly")
expect_true(obj.color.name == new_community_color, "Community color was not changed correctly")

def go_back_to_community(self):
click_obj_by_name(CommunitySettingsComponents.BACK_TO_COMMUNITY_BUTTON.value)
Expand All @@ -263,10 +263,10 @@ def search_and_change_community_channel_emoji(self, emoji_description: str):
# Search emoji
wait_for_object_and_type(CreateOrEditCommunityChannelPopup.EMOJI_SEARCH_TEXT_INPUT.value, emoji_description)
# Click on the first found emoji button
click_obj_by_wildcards_name(CreateOrEditCommunityChannelPopup.EMOJI_POPUP_EMOJI_PLACEHOLDER.value, "statusEmoji_*")
click_obj(wait_by_wildcards(CreateOrEditCommunityChannelPopup.EMOJI_POPUP_EMOJI_PLACEHOLDER.value, "%NAME%", "*"))
# save changes
click_obj_by_name(CreateOrEditCommunityChannelPopup.COMMUNITY_CHANNEL_SAVE_OR_CREATE_BUTTON.value)

def check_community_channel_emoji(self, emojiStr: str):
obj = wait_and_get_obj(CommunityScreenComponents.CHAT_IDENTIFIER_CHANNEL_ICON.value)
expectTrue(str(obj.icon.emoji).find(emojiStr) >= 0, "Same emoji check")
expect_true(str(obj.icon.emoji).find(emojiStr) >= 0, "Same emoji check")
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# encoding: UTF-8

import squish
import object
import names
import test

def debugWaitForObject(objRealName: dict, timeoutMSec: int = 1000):
return squish.waitForObject(objRealName, timeoutMSec)

def type_text(obj, text: str):
squish.type(obj, text)

def find_object(objRealName: dict):
obj = squish.findObject(objRealName)
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class SettingsSubsection(Enum):
settings_Wallet_AccountView_EditAccountColorRepeater = {"container": statusDesktop_mainWindow, "type": "Repeater", "objectName": "statusColorRepeater", "visible": True}
settings_Wallet_AccountView_AccountName = {"container": statusDesktop_mainWindow, "type": "StatusBaseText", "objectName": "walletAccountViewAccountName"}
settings_Wallet_AccountView_IconSettings = {"container": statusDesktop_mainWindow, "type": "StatusSmartIdenticon", "objectName": "walletAccountViewAccountImage" , "visible": True}
settings_Wallet_MainView_BackupSeedPhrase = {"container": mainWindow_ScrollView, "objectName": SettingsSubsection.BACKUP_SEED.value, "type": "StatusNavigationListItem", "visible": True}

generatedAccounts_ListView = {"container": statusDesktop_mainWindow, "objectName": "generatedAccounts", "type": "ListView"}

Expand All @@ -100,4 +101,18 @@ class SettingsSubsection(Enum):
languageView_language_StatusListPicker = {"container": statusDesktop_mainWindow, "objectName": "languagePicker", "type": "StatusListPicker"}
languageView_language_StatusPickerButton = {"container": languageView_language_StatusListPicker, "type": "StatusPickerButton", "unnamed": 1}
languageView_language_ListView = {"container": languageView_language_StatusListPicker, "type": "ListView", "unnamed": 1}
languageView_language_StatusInput = {"container": languageView_language_ListView, "type": "StatusInput", "unnamed": 1}
languageView_language_StatusInput = {"container": languageView_language_ListView, "type": "StatusInput", "unnamed": 1}

# Backup seed phrase:
backup_seed_phrase_popup_Acknowledgements_havePen_checkbox = {"container": statusDesktop_mainWindow_overlay, "objectName": "Acknowledgements_havePen", "type": "StatusCheckBox", "checkable": True, "visible": True}
backup_seed_phrase_popup_Acknowledgements_writeDown_checkbox = {"container": statusDesktop_mainWindow_overlay, "objectName": "Acknowledgements_writeDown", "type": "StatusCheckBox", "checkable": True, "visible": True}
backup_seed_phrase_popup_Acknowledgements_storeIt_checkbox = {"container": statusDesktop_mainWindow_overlay, "objectName": "Acknowledgements_storeIt", "type": "StatusCheckBox", "checkable": True, "visible": True}
backup_seed_phrase_popup_nextButton = {"container": statusDesktop_mainWindow_overlay, "objectName": "BackupSeedModal_nextButton", "type": "StatusButton", "visible": True, "enabled": True}
backup_seed_phrase_popup_ConfirmSeedPhrasePanel_RevealSeedPhraseButton = {"container": statusDesktop_mainWindow_overlay, "objectName": "ConfirmSeedPhrasePanel_RevealSeedPhraseButton", "type": "StatusButton", "visible": True}
backup_seed_phrase_popup_ConfirmSeedPhrasePanel_StatusSeedPhraseInput_placeholder = {"container": statusDesktop_mainWindow_overlay, "objectName": "ConfirmSeedPhrasePanel_StatusSeedPhraseInput_%WORD_NO%", "type": "StatusSeedPhraseInput", "visible": True}
backup_seed_phrase_popup_BackupSeedStepBase_confirmFirstWord = {"container": statusDesktop_mainWindow_overlay, "objectName": "BackupSeedModal_BackupSeedStepBase_confirmFirstWord", "type": "BackupSeedStepBase", "visible": True}
backup_seed_phrase_popup_BackupSeedStepBase_confirmFirstWord_inputText = {"container": backup_seed_phrase_popup_BackupSeedStepBase_confirmFirstWord, "objectName": "BackupSeedStepBase_inputText", "type": "TextEdit", "visible": True}
backup_seed_phrase_popup_BackupSeedStepBase_confirmSecondWord = {"container": statusDesktop_mainWindow_overlay, "objectName": "BackupSeedModal_BackupSeedStepBase_confirmSecondWord", "type": "BackupSeedStepBase", "visible": True}
backup_seed_phrase_popup_BackupSeedStepBase_confirmSecondWord_inputText = {"container": backup_seed_phrase_popup_BackupSeedStepBase_confirmSecondWord, "objectName": "BackupSeedStepBase_inputText", "type": "TextEdit", "visible": True}
backup_seed_phrase_popup_ConfirmStoringSeedPhrasePanel_storeCheck = {"container": statusDesktop_mainWindow_overlay, "objectName": "ConfirmStoringSeedPhrasePanel_storeCheck", "type": "StatusCheckBox", "checkable": True, "visible": True}
backup_seed_phrase_popup_BackupSeedModal_completeAndDeleteSeedPhraseButton = {"container": statusDesktop_mainWindow_overlay, "objectName": "BackupSeedModal_completeAndDeleteSeedPhraseButton", "type": "StatusButton", "visible": True}
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,12 @@ def step(context, twitter, personal_site, custom_link_name, custom_link):
def step(context, native):
_languageScreen.verify_current_language(native)
# TODO: Verify some texts have been changed in the application (not done now bc translations are inconsistent
# and not all expected languages have the same texts translated
# and not all expected languages have the same texts translated

@When("the user backs up the wallet seed phrase")
def step(context):
_settingsScreen.check_backup_seed_phrase_workflow()

@Then("the backup seed phrase indicator is not displayed")
def step(context):
_settingsScreen.verify_seed_phrase_indicator_not_visible()
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@ Feature: Status Desktop Settings Menu

Scenario: The user quits the app
When the user clicks on Sign out and Quit
Then the app is closed
Then the app is closed

Scenario: User can backup seed phrase
When the user activates wallet and opens the wallet settings
And the user backs up the wallet seed phrase
Then the backup seed phrase indicator is not displayed
4 changes: 4 additions & 0 deletions ui/app/AppLayouts/Profile/popups/BackupSeedModal.qml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ StatusStackModal {
rightButtons: [ d.skipButton, nextButton, finishButton ]

nextButton: StatusButton {
objectName: "BackupSeedModal_nextButton"
enabled: {
switch (root.currentIndex) {
case 0:
Expand Down Expand Up @@ -87,6 +88,7 @@ StatusStackModal {

finishButton: StatusButton {
text: qsTr("Complete & Delete My Seed Phrase")
objectName: "BackupSeedModal_completeAndDeleteSeedPhraseButton"
enabled: d.seedStored
onClicked: {
root.privacyStore.removeMnemonic();
Expand All @@ -112,12 +114,14 @@ StatusStackModal {
},
BackupSeedStepBase {
id: confirmFirstWord
objectName: "BackupSeedModal_BackupSeedStepBase_confirmFirstWord"
titleText: qsTr("Confirm word #%1 of your seed phrase").arg(d.firstRandomNo + 1)
wordRandomNumber: d.firstRandomNo
wordAtRandomNumber: root.privacyStore.getMnemonicWordAtIndex(d.firstRandomNo)
},
BackupSeedStepBase {
id: confirmSecondWord
objectName: "BackupSeedModal_BackupSeedStepBase_confirmSecondWord"
titleText: qsTr("Confirm word #%1 of your seed phrase").arg(d.secondRandomNo + 1)
wordRandomNumber: d.secondRandomNo
wordAtRandomNumber: root.privacyStore.getMnemonicWordAtIndex(d.secondRandomNo)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ ColumnLayout {

StatusCheckBox {
id: havePen
objectName: "Acknowledgements_havePen"
spacing: Style.current.padding
text: qsTr("I have a pen and paper")
font.pixelSize: Style.current.primaryTextFontSize
Expand All @@ -88,6 +89,7 @@ ColumnLayout {

StatusCheckBox {
id: writeDown
objectName: "Acknowledgements_writeDown"
spacing: Style.current.padding
text: qsTr("I am ready to write down my seed phrase")
font.pixelSize: Style.current.primaryTextFontSize
Expand All @@ -96,6 +98,7 @@ ColumnLayout {

StatusCheckBox {
id: storeIt
objectName: "Acknowledgements_storeIt"
spacing: Style.current.padding
text: qsTr("I know where I’ll store it")
font.pixelSize: Style.current.primaryTextFontSize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ StatusScrollView {

StatusInput {
id: inputText
input.edit.objectName: "BackupSeedStepBase_inputText"
visible: (wordRandomNumber > -1)
implicitWidth: 448
label: qsTr("Word #%1").arg(wordRandomNumber + 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ BackupSeedStepBase {
readonly property int spacing: 4
delegate: StatusSeedPhraseInput {
id: seedWordInput
objectName: "ConfirmSeedPhrasePanel_StatusSeedPhraseInput_" + grid.wordIndex[index]
width: (grid.cellWidth - grid.spacing)
height: (grid.cellHeight - grid.spacing)
textEdit.input.edit.enabled: false
Expand All @@ -61,6 +62,7 @@ BackupSeedStepBase {
}

StatusButton {
objectName: "ConfirmSeedPhrasePanel_RevealSeedPhraseButton"
anchors.centerIn: parent
visible: hideSeed
icon.name: "view"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ BackupSeedStepBase {

StatusCheckBox {
id: storeCheck
objectName: "ConfirmStoringSeedPhrasePanel_storeCheck"
spacing: Style.current.padding
font.pixelSize: Style.current.primaryTextFontSize
text: qsTr("I acknowledge that Status will not be able to show me my seed phrase again.")
Expand Down