test(@wallet): send transaction

This commit is contained in:
Anthony Laibe 2022-07-21 14:15:02 +02:00 committed by Anthony Laibe
parent d4a02bb4c4
commit 03b3b0c6f5
23 changed files with 148 additions and 101 deletions

View File

@ -31,6 +31,8 @@ class WalletSettingsScreen(Enum):
GENERATED_ACCOUNTS: str = "settings_Wallet_MainView_GeneratedAccounts"
DELETE_ACCOUNT: str = "settings_Wallet_AccountView_DeleteAccount"
DELETE_ACCOUNT_CONFIRM: str = "settings_Wallet_AccountView_DeleteAccount_Confirm"
NETWORKS_ITEM: str = "settings_Wallet_MainView_Networks"
TESTNET_TOGGLE: str = "settings_Wallet_NetworksView_TestNet_Toggle"
class SettingsScreen:
@ -83,7 +85,10 @@ class SettingsScreen:
if phrase == '12':
verify_text_matching(WalletSettingsScreen.TWELVE_SEED_PHRASE.value, address)
def toggle_test_networks(self):
click_obj_by_name(WalletSettingsScreen.NETWORKS_ITEM.value)
click_obj_by_name(WalletSettingsScreen.TESTNET_TOGGLE.value)
def _find_account_index(self, account_name: str) -> int:
accounts = get_obj(WalletSettingsScreen.GENERATED_ACCOUNTS.value)
for index in range(accounts.count):

View File

@ -72,3 +72,6 @@ class StatusMainScreen:
right_click_obj(chat_button)
click_obj_by_name(MainScreenComponents.MARK_AS_READ_BUTTON.value)
def open_wallet(self):
click_obj_by_name(MainScreenComponents.WALLET_BUTTON.value)

View File

@ -12,7 +12,17 @@ class SigningPhrasePopUp(Enum):
class MainWalletScreen(Enum):
ADD_ACCOUNT_BUTTON: str = "mainWallet_Add_Account"
ACCOUNT_NAME: str = "mainWallet_Account_Name"
SEND_BUTTON_FOOTER: str = "mainWallet_Footer_Send_Button"
class SendPopup(Enum):
SCROLL_BAR: str = "mainWallet_Send_Popup_Main"
HEADER_ACCOUNTS_LIST: str = "mainWallet_Send_Popup_Header_Accounts"
AMOUNT_INPUT: str = "mainWallet_Send_Popup_Amount_Input"
MY_ACCOUNTS_TAB: str = "mainWallet_Send_Popup_My_Accounts_Tab"
MY_ACCOUNTS_LIST: str = "mainWallet_Send_Popup_My_Accounts_List"
NETWORKS_LIST: str = "mainWallet_Send_Popup_Networks_List"
SEND_BUTTON: str = "mainWallet_Send_Popup_Send_Button"
PASSWORD_INPUT: str = "mainWallet_Send_Popup_Password_Input"
class AddAccountPopup(Enum):
SCROLL_BAR: str = "mainWallet_Add_Account_Popup_Main"
@ -121,3 +131,44 @@ class StatusWalletScreen:
def verify_account_name_is_present(self, account_name: str):
verify_text_matching(MainWalletScreen.ACCOUNT_NAME.value, account_name)
def send_transaction(self, account_name, amount, token, chain_name, password):
click_obj_by_name(MainWalletScreen.SEND_BUTTON_FOOTER.value)
self._click_repeater(SendPopup.HEADER_ACCOUNTS_LIST.value, account_name)
time.sleep(1)
type(SendPopup.AMOUNT_INPUT.value, amount)
if token != "ETH":
print("TODO: switch token")
click_obj_by_name(SendPopup.MY_ACCOUNTS_TAB.value)
accounts = get_obj(SendPopup.MY_ACCOUNTS_LIST.value)
for index in range(accounts.count):
if(accounts.itemAtIndex(index).objectName == account_name):
click_obj(accounts.itemAtIndex(index))
break
scroll_obj_by_name(SendPopup.SCROLL_BAR.value)
time.sleep(2)
scroll_obj_by_name(SendPopup.SCROLL_BAR.value)
time.sleep(2)
scroll_obj_by_name(SendPopup.SCROLL_BAR.value)
time.sleep(2)
self._click_repeater(SendPopup.NETWORKS_LIST.value, chain_name)
click_obj_by_name(SendPopup.SEND_BUTTON.value)
type(SendPopup.PASSWORD_INPUT.value, password)
click_obj_by_name(SendPopup.SEND_BUTTON.value)
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):
click_obj(repeater.itemAt(index))
break
def verify_transaction(self):
print("TODO: fix notification and ensure there is one")

View File

@ -163,8 +163,19 @@ navBarListView_Wallet_navbar_StatusNavBarTabButton = {"checkable": True, "contai
wallet_navbar_wallet_icon_StatusIcon = {"container": navBarListView_Wallet_navbar_StatusNavBarTabButton, "objectName": "wallet-icon", "type": "StatusIcon", "visible": True}
mainWallet_Account_Name = {"container": statusDesktop_mainWindow, "objectName": "accountName", "type": "StatusBaseText", "visible": True}
mainWallet_Add_Account = {"container": statusDesktop_mainWindow, "text": "Add account", "type": "StatusBaseText", "unnamed": 1, "visible": True}
mainWallet_Footer_Send_Button = {"container": statusDesktop_mainWindow, "objectName": "walletFooterSendButton", "type": "StatusFlatButton"}
mainWallet_Send_Popup_Main = {"container": statusDesktop_mainWindow, "objectName": "sendModalScroll", "type": "StatusScrollView"}
mainWallet_Send_Popup_Amount_Input = {"container": statusDesktop_mainWindow, "objectName": "amountInput", "type": "TextEdit"}
mainWallet_Send_Popup_My_Accounts_Tab = {"container": statusDesktop_mainWindow, "objectName": "myAccountsTab", "type": "StatusTabButton"}
mainWallet_Send_Popup_My_Accounts_List = {"container": statusDesktop_mainWindow, "objectName": "myAccountsList", "type": "StatusListView"}
mainWallet_Send_Popup_Header_Accounts = {"container": statusDesktop_mainWindow, "objectName": "accountsListFloatingHeader", "type": "Repeater"}
mainWallet_Send_Popup_Networks_List = {"container": statusDesktop_mainWindow, "objectName": "networksList", "type": "Repeater"}
mainWallet_Send_Popup_Send_Button = {"container": statusDesktop_mainWindow, "objectName": "sendModalFooterSendButton", "type": "StatusFlatButton"}
mainWallet_Send_Popup_Password_Input = {"container": statusDesktop_mainWindow, "objectName": "transactionSignerPasswordInput", "type": "StyledTextField"}
mainWallet_Add_Account = {"container": statusDesktop_mainWindow, "text": "Add account", "type": "StatusBaseText", "unnamed": 1, "visible": True}
mainWallet_Add_Account_Popup_Main = {"container": statusDesktop_mainWindow, "objectName": "AddAccountModalContent", "type": "StatusScrollView", "visible": True}
mainWallet_Add_Account_Popup_Password = {"container": mainWallet_Add_Account_Popup_Main, "text": "Enter your password...", "type": "PlaceholderText", "unnamed": 1, "visible": True}
mainWallet_Add_Account_Popup_Advanced = {"container": mainWallet_Add_Account_Popup_Main, "text": "Advanced", "type": "StatusBaseText", "unnamed": 1, "visible": True}
@ -192,6 +203,9 @@ mainWallet_Add_Account_Popup_Footer = {"container": statusDesktop_mainWindow, "t
mainWallet_Add_Account_Popup_Footer_Add_Account = {"container": mainWallet_Add_Account_Popup_Footer, "text": "Add account", "type": "StatusBaseText", "unnamed": 1, "visible": True}
settings_Wallet_MainView_GeneratedAccounts = {"container": statusDesktop_mainWindow, "objectName":'generatedAccounts', "type": 'ListView'}
settings_Wallet_MainView_Networks = {"container": statusDesktop_mainWindow, "objectName": "networksItem", "type": "StatusListItem"}
settings_Wallet_NetworksView_TestNet_Toggle = {"container": statusDesktop_mainWindow, "objectName": "testnetModeSwitch", "type": "StatusSwitch"}
settings_Wallet_AccountView_DeleteAccount = {"container": statusDesktop_mainWindow, "type": "StatusButton", "objectName": "deleteAccountButton"}
settings_Wallet_AccountView_DeleteAccount_Confirm = {"container": statusDesktop_mainWindow, "type": "StatusButton", "objectName": "confirmDeleteAccountButton"}
mainWindow_communityColumnView_CommunityColumnView = {"container": statusDesktop_mainWindow, "objectName": "communityColumnView", "type": "CommunityColumnView"}

View File

@ -3,7 +3,7 @@ from screens.StatusMainScreen import StatusMainScreen
from screens.SettingsScreen import SettingsScreen
_statusMain = StatusMainScreen()
_settingsScreen =SettingsScreen()
_settingsScreen = SettingsScreen()
@When("the user opens app settings screen")
@ -23,6 +23,10 @@ def step(context: any, account_name: str):
_statusMain.open_settings()
_settingsScreen.delete_account(account_name)
@When("the user toggles test networks")
def step(context: any):
_settingsScreen.toggle_test_networks()
@Then("the |any| seed phrase address is |any| displayed in the wallet")
def step(context: any, phrase :str, address: str):
_settingsScreen.verify_address(phrase, address)

View File

@ -1,8 +1,13 @@
from screens.StatusWalletScreen import StatusWalletScreen
_statusMain = StatusMainScreen()
_walletScreen = StatusWalletScreen()
@When("the user accept the signing phrase")
@When("the user opens wallet screen")
def step(context):
_statusMain.open_wallet()
@When("the user accepts the signing phrase")
def step(context):
_walletScreen.accept_signing_phrase()
@ -22,6 +27,15 @@ def step(context, account_name, password, private_key):
def step(context, account_name, password, mnemonic):
_walletScreen.import_seed_phrase(account_name, password, mnemonic)
@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)
@Then("the new account |any| is added")
def step(context, account_name):
_walletScreen.verify_account_name_is_present(account_name)
_walletScreen.verify_account_name_is_present(account_name)
@Then("the transaction is in progress")
def step(context):
_walletScreen.verify_transaction()

View File

@ -4,6 +4,6 @@ HOOK_SUB_PROCESSES=false
IMPLICITAUTSTART=0
LANGUAGE=Python
OBJECTMAPSTYLE=script
TEST_CASES=tst_statusLoginPassword tst_basicChatFlow tst_wallet tst_communityFlows tst_groupChat
TEST_CASES=tst_statusLoginPassword tst_basicChatFlow tst_wallet tst_communityFlows tst_groupChat tst_transaction
VERSION=3
WRAPPERS=Qt

View File

@ -0,0 +1,23 @@
Feature: Status Desktop Transaction
As a user I want to perform transaction
Background: Sign up & Enable wallet section & Toggle test networks
Given A first time user lands on the status desktop and generates new key
When user signs up with username tester123 and password TesTEr16843/!@00
Then the user lands on the signed in app
When the user opens app settings screen
When the user activates wallet and opens the wallet settings
When the user toggles test networks
When the user opens wallet screen
When the user accepts the signing phrase
When the user imports a seed phrase with one and TesTEr16843/!@00 and pelican chief sudden oval media rare swamp elephant lawsuit wheat knife initial
Scenario Outline: User sends a transaction
When the user sends a transaction to himself from account one of <amount> <token> on <chain_name> with password TesTEr16843/!@00
Then the transaction is in progress
Examples:
| amount | token | chain_name |
| 0.000001 | ETH | Ropsten |
| 0 | ETH | Ropsten |

View File

@ -0,0 +1,8 @@
source(findFile('scripts', 'python/bdd.py'))
setupHooks('../shared/scripts/bdd_hooks.py')
collectStepDefinitions('./steps', '../shared/steps')
def main():
testSettings.throwOnFailure = True
runFeatureFile('test.feature')

View File

@ -8,7 +8,7 @@ Feature: Status Desktop Wallet
Then the user lands on the signed in app
When the user opens app settings screen
When the user activates wallet and opens the wallet section
When the user accept the signing phrase
When the user accepts the signing phrase
Scenario Outline: User adds a watch only account
When the user adds watch only account with <account_name> and <address>

View File

@ -104,6 +104,7 @@ SettingsContentBase {
Component {
id: testnetModeSwitchComponent
StatusSwitch {
objectName: "testnetModeSwitch"
text: qsTr("Testnet Mode")
checked: walletStore.areTestNetworksEnabled
onClicked: walletStore.toggleTestNetworksEnabled()

View File

@ -70,6 +70,7 @@ Column {
}
StatusListItem {
objectName: "networksItem"
title: qsTr("Networks")
height: 64
width: parent.width

View File

@ -37,11 +37,9 @@ StatusGridView {
if (!Utils.isMnemonic(mnemonicString)) {
_internal.errorString = qsTr("Invalid seed phrase")
} else {
_internal.errorString = RootStore.vaildateMnemonic(mnemonicString)
const regex = new RegExp('word [a-z]+ not found in the dictionary', 'i');
if (regex.test(_internal.errorString)) {
if (!RootStore.validMnemonic(mnemonicString)) {
_internal.errorString = qsTr("Invalid seed phrase") + '. ' +
qsTr("This seed phrase doesn't match our supported dictionary. Check for misspelled words.")
qsTr("This seed phrase doesn't match our supported dictionary. Check for misspelled words.")
}
}
return _internal.errorString === ""

View File

@ -30,6 +30,7 @@ Rectangle {
spacing: Style.current.padding
StatusFlatButton {
objectName: "walletFooterSendButton"
icon.name: "send"
text: qsTr("Send")
onClicked: function() {

View File

@ -213,8 +213,8 @@ QtObject {
walletSectionAccounts.resetDerivedAddressModel()
}
function vaildateMnemonic(mnemonic) {
return onboardingModule.validateMnemonic(mnemonic)
function validMnemonic(mnemonic) {
return startupModule.validMnemonic(mnemonic)
}
function getNextSelectableDerivedAddressIndex() {

View File

@ -14,6 +14,7 @@ StatusInput {
rightPadding: 0
placeholderText: ""
input.edit.objectName: "amountInput"
input.edit.cursorVisible: true
input.edit.font.pixelSize: 32
input.placeholderFont.pixelSize: 32

View File

@ -1,88 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import utils 1.0
import "./"
import "../"
import "../panels"
Item {
property bool correctWordCount: Utils.seedPhraseValidWordCount(mnemonicTextField.text)
property alias textArea: mnemonicTextField.textField
signal enterPressed()
property var nextComponentTab
property bool hideRectangle: false
id: root
// Width controlled by parent component
height: childrenRect.height
function validateSeed() {
errorText.text = "";
if (!Utils.isMnemonic(mnemonicTextField.textField.text)) {
errorText.text = qsTr("Invalid seed phrase")
} else {
errorText.text = onboardingModule.validateMnemonic(mnemonicTextField.textField.text)
const regex = new RegExp('word [a-z]+ not found in the dictionary', 'i');
if (regex.test(errorText.text)) {
errorText.text = qsTr("Invalid seed phrase") + '. ' +
qsTr("This seed phrase doesn't match our supported dictionary. Check for misspelled words.")
}
}
return errorText.text === ""
}
StyledTextArea {
id: mnemonicTextField
customHeight: textField.implicitHeight >= 150 ? 150 : textField.implicitHeight + 30
hideRectangle: root.hideRectangle
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
textField.wrapMode: Text.WordWrap
textField.horizontalAlignment: TextEdit.AlignHCenter
textField.verticalAlignment: TextEdit.AlignVCenter
textField.font.pixelSize: 15
textField.font.weight: Font.DemiBold
placeholderText: qsTr("Start with the first word")
textField.placeholderTextColor: Style.current.secondaryText
textField.selectByMouse: true
textField.selectByKeyboard: true
textField.selectionColor: Style.current.secondaryBackground
textField.selectedTextColor: Style.current.secondaryText
onKeyPressed: {
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
event.accepted = true
root.enterPressed()
return
}
errorText.text = ""
}
textField.color: Style.current.textColor
}
StyledText {
visible: errorText.text === ""
text: Utils.seedPhraseWordCountText(mnemonicTextField.textField.text)
anchors.right: parent.right
anchors.top: mnemonicTextField.bottom
anchors.topMargin: Style.current.smallPadding
color: correctWordCount ? Style.current.textColor : Style.current.secondaryText
}
StyledText {
id: errorText
visible: !!text && text !== ""
wrapMode: Text.WordWrap
color: Style.current.danger
anchors.left: parent.left
anchors.right: parent.right
anchors.top: mnemonicTextField.bottom
anchors.topMargin: Style.current.smallPadding
horizontalAlignment: Text.AlignHCenter
}
}

View File

@ -272,6 +272,7 @@ StatusDialog {
anchors.top: border.bottom
anchors.left: parent.left
z: 0
objectName: "sendModalScroll"
ColumnLayout {
width: scrollView.availableWidth

View File

@ -69,9 +69,11 @@ RowLayout {
spacing: Style.current.padding
Repeater {
id: repeater
objectName: "networksList"
model: networksSimpleRoutingView.suggestedRoutes
StatusListItem {
id: item
objectName: modelData.chainName
leftPadding: 5
rightPadding: 5
implicitWidth: 126

View File

@ -91,6 +91,7 @@ Rectangle {
StatusFlatButton {
icon.name: isLastGroup ? "" : "password"
text: qsTr("Send")
objectName: "sendModalFooterSendButton"
size: StatusBaseButton.Size.Large
normalColor: Theme.palette.primaryColor2
disaledColor: Theme.palette.baseColor2

View File

@ -20,6 +20,8 @@ StatusFloatingButtonsSelector {
property var selectedAccount
repeater.objectName: "accountsListFloatingHeader"
signal updatedSelectedAccount(var account)
QtObject {
@ -40,6 +42,7 @@ StatusFloatingButtonsSelector {
implicitHeight: 32
defaultLeftPadding: 4
text: name
objectName: name
icon.emoji: !!emoji ? emoji: ""
icon.emojiSize: StatusQUtils.Emoji.size.middle
icon.name: !emoji ? "filled-account": ""

View File

@ -45,6 +45,7 @@ Item {
StatusTabButton {
id: collectiblesBtn
width: implicitWidth
objectName: "myAccountsTab"
text: qsTr("My Accounts")
}
StatusTabButton {
@ -141,6 +142,7 @@ Item {
StatusListView {
id: myAccounts
objectName: "myAccountsList"
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
width: parent.width
@ -148,6 +150,7 @@ Item {
delegate: StatusListItem {
implicitWidth: parent.width
objectName: model.name
height: visible ? 64 : 0
title: !!model.name ? model.name : ""
subTitle: Utils.toLocaleString(model.currencyBalance.toFixed(2), store.locale, {"model.currency": true}) + " " + store.currentCurrency.toUpperCase()

View File

@ -98,6 +98,7 @@ Item {
id: txtPassword
anchors.top: signingPhrase.bottom
anchors.topMargin: Style.current.bigPadding
textField.objectName: "transactionSignerPasswordInput"
focus: true
customHeight: 56
label: qsTr("Password")