import QtQuick 2.15 import QtTest 1.15 import StatusQ 0.1 // See #10218 import StatusQ.Core 0.1 import StatusQ.Core.Utils 0.1 as SQUtils import StatusQ.Core.Theme 0.1 import StatusQ.Controls 0.1 import QtQuick.Controls 2.15 import Models 1.0 import Storybook 1.0 import utils 1.0 import shared.stores 1.0 import AppLayouts.Wallet.popups.swap 1.0 import AppLayouts.Wallet.stores 1.0 import AppLayouts.Wallet 1.0 import AppLayouts.Wallet.adaptors 1.0 Item { id: root width: 800 height: 600 readonly property var dummySwapTransactionRoutes: SwapTransactionRoutes {} readonly property var swapStore: SwapStore { signal suggestedRoutesReady(var txRoutes) readonly property var accounts: WalletAccountsModel {} readonly property var flatNetworks: NetworksModel.flatNetworks readonly property bool areTestNetworksEnabled: true function getWei2Eth(wei, decimals) { return wei/(10**decimals) } function fetchSuggestedRoutes(accountFrom, accountTo, amount, tokenFrom, tokenTo, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs, sendType, lockedInAmounts) {} } readonly property var swapAdaptor: SwapModalAdaptor { currencyStore: CurrenciesStore {} walletAssetsStore: WalletAssetsStore { id: thisWalletAssetStore walletTokensStore: TokensStore { plainTokensBySymbolModel: TokensBySymbolModel {} getDisplayAssetsBelowBalanceThresholdDisplayAmount: () => 0 } readonly property var baseGroupedAccountAssetModel: GroupedAccountsAssetsModel {} assetsWithFilteredBalances: thisWalletAssetStore.groupedAccountsAssetsModel } swapStore: root.swapStore swapFormData: root.swapFormData swapOutputData: SwapOutputData{} } readonly property var tokenSelectorAdaptor: TokenSelectorViewAdaptor { assetsModel: swapAdaptor.walletAssetsStore.groupedAccountAssetsModel flatNetworksModel: swapStore.flatNetworks currentCurrency: swapAdaptor.currencyStore.currentCurrency enabledChainIds: !!root.swapFormData && root.swapFormData.selectedNetworkChainId !== - 1 ? [root.swapFormData.selectedNetworkChainId] : [] accountAddress: !!root.swapFormData && root.swapFormData.selectedAccountAddress } property SwapInputParamsForm swapFormData: SwapInputParamsForm { defaultToTokenKey: "STT" } Component { id: componentUnderTest SwapModal { swapInputParamsForm: root.swapFormData swapAdaptor: root.swapAdaptor } } SignalSpy { id: formValuesChanged target: swapFormData signalName: "formValuesChanged" } TestCase { name: "SwapModal" when: windowShown property SwapModal controlUnderTest: null // helper functions ------------------------------------------------------------- function init() { swapAdaptor.swapFormData = root.swapFormData controlUnderTest = createTemporaryObject(componentUnderTest, root, { swapInputParamsForm: root.swapFormData}) } function cleanup() { root.swapFormData.resetFormData() formValuesChanged.clear() } function launchAndVerfyModal() { formValuesChanged.clear() verify(!!controlUnderTest) controlUnderTest.open() verify(!!controlUnderTest.opened) } function closeAndVerfyModal() { verify(!!controlUnderTest) controlUnderTest.close() verify(!controlUnderTest.opened) formValuesChanged.clear() root.swapFormData.resetFormData() } function getAndVerifyAccountsModalHeader() { const accountsModalHeader = findChild(controlUnderTest, "accountSelector") verify(!!accountsModalHeader) return accountsModalHeader } function launchAccountSelectionPopup(accountsModalHeader) { // Launch account selection popup verify(!accountsModalHeader.control.popup.opened) mouseClick(accountsModalHeader) waitForRendering(accountsModalHeader) verify(!!accountsModalHeader.control.popup.opened) return accountsModalHeader } function verifyLoadingAndNoErrorsState(payPanel, receivePanel) { // verify loading state was set and no errors currently verify(!root.swapAdaptor.validSwapProposalReceived) verify(root.swapAdaptor.swapProposalLoading) compare(root.swapAdaptor.swapOutputData.fromTokenAmount, "") compare(root.swapAdaptor.swapOutputData.toTokenAmount, "") compare(root.swapAdaptor.swapOutputData.totalFees, 0) compare(root.swapAdaptor.swapOutputData.bestRoutes, []) compare(root.swapAdaptor.swapOutputData.approvalNeeded, false) compare(root.swapAdaptor.swapOutputData.hasError, false) // verfy input and output panels verify(!payPanel.mainInputLoading) verify(!payPanel.bottomTextLoading) compare(payPanel.selectedHoldingId, root.swapFormData.fromTokensKey) compare(payPanel.value, Number(root.swapFormData.fromTokenAmount)) compare(payPanel.rawValue, SQUtils.AmountsArithmetic.fromNumber(root.swapFormData.fromTokenAmount, root.swapAdaptor.fromToken.decimals).toString()) verify(payPanel.valueValid) verify(receivePanel.mainInputLoading) verify(receivePanel.bottomTextLoading) verify(!receivePanel.interactive) compare(receivePanel.selectedHoldingId, root.swapFormData.toTokenKey) compare(receivePanel.value, 0) compare(receivePanel.rawValue, "0") } // end helper functions ------------------------------------------------------------- function test_floating_header_default_account() { verify(!!controlUnderTest) /* using a for loop set different accounts as default index and check if the correct values are displayed in the floating header*/ for (let i = 0; i< swapAdaptor.nonWatchAccounts.count; i++) { const nonWatchAccount = swapAdaptor.nonWatchAccounts.get(i) root.swapFormData.selectedAccountAddress = nonWatchAccount.address // Launch popup launchAndVerfyModal() const floatingHeaderBackground = findChild(controlUnderTest, "headerBackground") verify(!!floatingHeaderBackground) compare(floatingHeaderBackground.color.toString().toUpperCase(), Utils.getColorForId(nonWatchAccount.colorId).toString().toUpperCase()) const headerContentItemText = findChild(controlUnderTest, "textContent") verify(!!headerContentItemText) compare(headerContentItemText.text, nonWatchAccount.name) const headerContentItemEmoji = findChild(controlUnderTest, "assetContent") verify(!!headerContentItemEmoji) compare(headerContentItemEmoji.asset.emoji, nonWatchAccount.emoji) } closeAndVerfyModal() } function test_floating_header_doesnt_contain_watch_accounts() { // main input list from store should contian watch accounts let hasWatchAccount = false for(let i =0; i< swapStore.accounts.count; i++) { if(swapStore.accounts.get(i).walletType === Constants.watchWalletType) { hasWatchAccount = true break } } verify(!!hasWatchAccount) // launch modal and get the account selection header launchAndVerfyModal() const accountsModalHeader = getAndVerifyAccountsModalHeader() // header model should not contain watch accounts let floatingHeaderHasWatchAccount = false for(let i =0; i< accountsModalHeader.model.count; i++) { if(accountsModalHeader.model.get(i).walletType === Constants.watchWalletType) { floatingHeaderHasWatchAccount = true break } } verify(!floatingHeaderHasWatchAccount) closeAndVerfyModal() } function test_floating_header_list_items() { // Launch popup and account selection modal launchAndVerfyModal() const accountsModalHeader = getAndVerifyAccountsModalHeader() launchAccountSelectionPopup(accountsModalHeader) const comboBoxList = findChild(controlUnderTest, "accountSelectorList") verify(!!comboBoxList) waitForRendering(comboBoxList) for(let i =0; i< comboBoxList.model.count; i++) { let delegateUnderTest = comboBoxList.itemAtIndex(i) // check if the items are organized as per the position role if(!!delegateUnderTest && !!comboBoxList.itemAtIndex(i+1)) { verify(comboBoxList.itemAtIndex(i+1).model.position > delegateUnderTest.model.position) } compare(delegateUnderTest.title, swapAdaptor.nonWatchAccounts.get(i).name) compare(delegateUnderTest.subTitle, SQUtils.Utils.elideText(swapAdaptor.nonWatchAccounts.get(i).address, 6, 4)) compare(delegateUnderTest.asset.color.toString().toUpperCase(), swapAdaptor.nonWatchAccounts.get(i).color.toString().toUpperCase()) compare(delegateUnderTest.asset.emoji, swapAdaptor.nonWatchAccounts.get(i).emoji) const walletAccountCurrencyBalance = findChild(delegateUnderTest, "walletAccountCurrencyBalance") verify(!!walletAccountCurrencyBalance) verify(walletAccountCurrencyBalance.text, LocaleUtils.currencyAmountToLocaleString(swapAdaptor.nonWatchAccounts.get(i).currencyBalance)) // check if selected item in combo box is highlighted with the right color if(comboBoxList.currentIndex === i) { verify(delegateUnderTest.color, Theme.palette.statusListItem.highlightColor) } else { verify(delegateUnderTest.color, Theme.palette.transparent) } // TODO: always null not sure why // const walletAccountTypeIcon = findChild(delegateUnderTest, "walletAccountTypeIcon") // verify(!!walletAccountTypeIcon) // compare(walletAccountTypeIcon.icon, swapAdaptor.nonWatchAccounts.get(i).walletType === Constants.watchWalletType ? "show" : delegateUnderTest.model.migratedToKeycard ? "keycard": "") // Hover over the item and check hovered state mouseMove(delegateUnderTest, delegateUnderTest.width/2, delegateUnderTest.height/2) verify(delegateUnderTest.sensor.containsMouse) compare(delegateUnderTest.title, swapAdaptor.nonWatchAccounts.get(i).name) compare(delegateUnderTest.subTitle, WalletUtils.colorizedChainPrefix(root.swapAdaptor.getNetworkShortNames(swapAdaptor.nonWatchAccounts.get(i).preferredSharingChainIds)), "Randomly failing locally. Add a bug if you see this failing in CI") verify(delegateUnderTest.color, Theme.palette.baseColor2) } controlUnderTest.close() } function test_floating_header_after_setting_fromAsset() { // Launch popup launchAndVerfyModal() // launch account selection dropdown const accountsModalHeader = getAndVerifyAccountsModalHeader() launchAccountSelectionPopup(accountsModalHeader) const comboBoxList = findChild(accountsModalHeader, "accountSelectorList") verify(!!comboBoxList) // before setting network chainId and fromTokensKey the header should not have balances for(let i =0; i< comboBoxList.model.count; i++) { let delegateUnderTest = comboBoxList.itemAtIndex(i) verify(!delegateUnderTest.model.accountBalance) } // close account selection dropdown accountsModalHeader.control.popup.close() // set network chainId and fromTokensKey and verify balances in account selection dropdown root.swapFormData.selectedNetworkChainId = root.swapAdaptor.filteredFlatNetworksModel.get(0).chainId root.swapFormData.fromTokensKey = root.swapAdaptor.walletAssetsStore.walletTokensStore.plainTokensBySymbolModel.get(0).key compare(controlUnderTest.swapInputParamsForm.selectedNetworkChainId, root.swapFormData.selectedNetworkChainId) compare(controlUnderTest.swapInputParamsForm.fromTokensKey, root.swapFormData.fromTokensKey) // launch account selection dropdown launchAccountSelectionPopup(accountsModalHeader) verify(!!comboBoxList) for(let i =0; i< comboBoxList.model.count; i++) { let delegateUnderTest = comboBoxList.itemAtIndex(i) verify(!!delegateUnderTest.model.fromToken) verify(!!delegateUnderTest.model.accountBalance) compare(delegateUnderTest.inlineTagModel, 1) const inlineTagDelegate_0 = findChild(delegateUnderTest, "inlineTagDelegate_0") verify(!!inlineTagDelegate_0) compare(inlineTagDelegate_0.asset.name, Style.svg("tiny/%1".arg(delegateUnderTest.model.accountBalance.iconUrl))) compare(inlineTagDelegate_0.asset.color.toString().toUpperCase(), delegateUnderTest.model.accountBalance.chainColor.toString().toUpperCase()) compare(inlineTagDelegate_0.titleText.color, delegateUnderTest.model.accountBalance.balance === "0" ? Theme.palette.baseColor1 : Theme.palette.directColor1) let bigIntBalance = SQUtils.AmountsArithmetic.toNumber(delegateUnderTest.model.accountBalance.balance, delegateUnderTest.model.fromToken.decimals) compare(inlineTagDelegate_0.title, root.swapAdaptor.formatCurrencyAmount(bigIntBalance, delegateUnderTest.model.fromToken.symbol)) } closeAndVerfyModal() } function test_floating_header_selection() { // Launch popup launchAndVerfyModal() for(let i =0; i< swapAdaptor.nonWatchAccounts.count; i++) { // launch account selection dropdown const accountsModalHeader = getAndVerifyAccountsModalHeader() launchAccountSelectionPopup(accountsModalHeader) const comboBoxList = findChild(accountsModalHeader, "accountSelectorList") verify(!!comboBoxList) let delegateUnderTest = comboBoxList.itemAtIndex(i) mouseClick(delegateUnderTest) waitForRendering(delegateUnderTest) verify(accountsModalHeader.control.popup.closed) // The input params form's slected Index should be updated as per this selection compare(root.swapFormData.selectedAccountAddress, swapAdaptor.nonWatchAccounts.get(i).address) // The comboBox item should reflect chosen account const floatingHeaderBackground = findChild(accountsModalHeader, "headerBackground") verify(!!floatingHeaderBackground) compare(floatingHeaderBackground.color.toString().toUpperCase(), swapAdaptor.nonWatchAccounts.get(i).color.toString().toUpperCase()) const headerContentItemText = findChild(accountsModalHeader, "textContent") verify(!!headerContentItemText) compare(headerContentItemText.text, swapAdaptor.nonWatchAccounts.get(i).name) const headerContentItemEmoji = findChild(accountsModalHeader, "assetContent") verify(!!headerContentItemEmoji) compare(headerContentItemEmoji.asset.emoji, swapAdaptor.nonWatchAccounts.get(i).emoji) } closeAndVerfyModal() } function test_network_default_and_selection() { // Launch popup launchAndVerfyModal() // get network comboBox const networkComboBox = findChild(controlUnderTest, "networkFilter") verify(!!networkComboBox) // check default value of network comboBox, should be mainnet compare(root.swapFormData.selectedNetworkChainId, -1) compare(root.swapAdaptor.filteredFlatNetworksModel.get(0).chainId, 11155111 /*Sepolia Mainnet*/) // lets ensure that the selected one is correctly set for (let i=0; i balances.chainId === root.swapFormData.selectedNetworkChainId).filter(balances => balances.account === accountDelegateUnderTest.model.address) verify(!!filteredBalances) let accountBalance = filteredBalances.length > 0 ? filteredBalances[0]: { balance: "0", iconUrl: networkModelItem.iconUrl, chainColor: networkModelItem.chainColor} verify(!!accountBalance) let fromToken = SQUtils.ModelUtils.getByKey(root.swapAdaptor.walletAssetsStore.walletTokensStore.plainTokensBySymbolModel, "key", root.swapFormData.fromTokensKey) verify(!!fromToken) let bigIntBalance = SQUtils.AmountsArithmetic.toNumber(accountBalance.balance, fromToken.decimals) compare(inlineTagDelegate_0.title, root.swapAdaptor.formatCurrencyAmount(bigIntBalance, fromToken.symbol)) } // close account selection dropdown accountsModalHeader.control.popup.close() } root.swapFormData.selectedNetworkChainId = -1 networkComboBox.control.popup.close() closeAndVerfyModal() } function test_edit_slippage() { // Launch popup launchAndVerfyModal() // test default values for the various footer items for slippage const maxSlippageText = findChild(controlUnderTest, "maxSlippageText") verify(!!maxSlippageText) compare(maxSlippageText.text, qsTr("Max slippage:")) const maxSlippageValue = findChild(controlUnderTest, "maxSlippageValue") verify(!!maxSlippageValue) const editSlippageButton = findChild(controlUnderTest, "editSlippageButton") verify(!!editSlippageButton) const editSlippagePanel = findChild(controlUnderTest, "editSlippagePanel") verify(!!editSlippagePanel) verify(!editSlippagePanel.visible) // set swap proposal to ready and check state of the edit slippage buttons and max slippage values root.swapAdaptor.validSwapProposalReceived = true compare(maxSlippageValue.text, "%1%".arg(0.5)) verify(editSlippageButton.visible) // clicking on editSlippageButton should show the edit slippage panel mouseClick(editSlippageButton) verify(!editSlippageButton.visible) verify(editSlippagePanel.visible) const slippageSelector = findChild(editSlippagePanel, "slippageSelector") verify(!!slippageSelector) verify(slippageSelector.valid) compare(slippageSelector.value, 0.5) const buttonsRepeater = findChild(slippageSelector, "buttonsRepeater") verify(!!buttonsRepeater) waitForRendering(buttonsRepeater) for(let i =0; i< buttonsRepeater.count; i++) { let buttonUnderTest = buttonsRepeater.itemAt(i) verify(!!buttonUnderTest) // the mouseClick(buttonUnderTest) doesnt seem to work buttonUnderTest.clicked() verify(slippageSelector.valid) compare(slippageSelector.value, buttonUnderTest.value) compare(maxSlippageValue.text, "%1%".arg(buttonUnderTest.value)) } const signButton = findChild(controlUnderTest, "signButton") verify(!!signButton) verify(signButton.enabled) } function test_modal_swap_proposal_setup() { root.swapAdaptor.reset() // Launch popup launchAndVerfyModal() waitForItemPolished(controlUnderTest.contentItem) const maxFeesText = findChild(controlUnderTest, "maxFeesText") verify(!!maxFeesText) const maxFeesValue = findChild(controlUnderTest, "maxFeesValue") verify(!!maxFeesValue) const signButton = findChild(controlUnderTest, "signButton") verify(!!signButton) const errorTag = findChild(controlUnderTest, "errorTag") verify(!!errorTag) const payPanel = findChild(controlUnderTest, "payPanel") verify(!!payPanel) const receivePanel = findChild(controlUnderTest, "receivePanel") verify(!!receivePanel) // Check max fees values and sign button state when nothing is set compare(maxFeesText.text, qsTr("Max fees:")) compare(maxFeesValue.text, "--") verify(!signButton.enabled) verify(!errorTag.visible) // set input values in the form correctly root.swapFormData.fromTokensKey = root.swapAdaptor.walletAssetsStore.walletTokensStore.plainTokensBySymbolModel.get(0).key compare(formValuesChanged.count, 1) root.swapFormData.toTokenKey = root.swapAdaptor.walletAssetsStore.walletTokensStore.plainTokensBySymbolModel.get(1).key root.swapFormData.fromTokenAmount = "0.001" compare(formValuesChanged.count, 2) root.swapFormData.selectedNetworkChainId = root.swapAdaptor.filteredFlatNetworksModel.get(0).chainId compare(formValuesChanged.count, 3) root.swapFormData.selectedAccountAddress = root.swapAdaptor.nonWatchAccounts.get(0).address compare(formValuesChanged.count, 4) // wait for fetchSuggestedRoutes function to be called wait(1000) // verify loading state was set and no errors currently verifyLoadingAndNoErrorsState(payPanel, receivePanel) // emit event that no routes were found root.swapStore.suggestedRoutesReady(root.dummySwapTransactionRoutes.txNoRoutes) // verify loading state was removed and that error was displayed verify(!root.swapAdaptor.validSwapProposalReceived) verify(!root.swapAdaptor.swapProposalLoading) compare(root.swapAdaptor.swapOutputData.fromTokenAmount, "") compare(root.swapAdaptor.swapOutputData.toTokenAmount, "") compare(root.swapAdaptor.swapOutputData.totalFees, 0) compare(root.swapAdaptor.swapOutputData.bestRoutes, []) compare(root.swapAdaptor.swapOutputData.approvalNeeded, false) compare(root.swapAdaptor.swapOutputData.hasError, true) verify(errorTag.visible) verify(errorTag.text, qsTr("An error has occured, please try again")) verify(!signButton.enabled) compare(signButton.text, qsTr("Swap")) // verfy input and output panels verify(!payPanel.mainInputLoading) verify(!payPanel.bottomTextLoading) verify(!receivePanel.mainInputLoading) verify(!receivePanel.bottomTextLoading) verify(!receivePanel.interactive) compare(receivePanel.selectedHoldingId, root.swapFormData.toTokenKey) compare(receivePanel.value, 0) compare(receivePanel.rawValue, "0") // edit some params to retry swap root.swapFormData.fromTokenAmount = "0.00011" compare(formValuesChanged.count, 5) // wait for fetchSuggestedRoutes function to be called wait(1000) // verify loading state was set and no errors currently verifyLoadingAndNoErrorsState(payPanel, receivePanel) // emit event with route that needs no approval let txRoutes = root.dummySwapTransactionRoutes.txHasRouteNoApproval root.swapStore.suggestedRoutesReady(txRoutes) // verify loading state removed and data is displayed as expected on the Modal verify(root.swapAdaptor.validSwapProposalReceived) verify(!root.swapAdaptor.swapProposalLoading) compare(root.swapAdaptor.swapOutputData.fromTokenAmount, "") compare(root.swapAdaptor.swapOutputData.toTokenAmount, SQUtils.AmountsArithmetic.div( SQUtils.AmountsArithmetic.fromString(txRoutes.amountToReceive), SQUtils.AmountsArithmetic.fromNumber(1, root.swapAdaptor.toToken.decimals) ).toString()) // calculation needed for total fees let gasTimeEstimate = txRoutes.gasTimeEstimate let totalTokenFeesInFiat = gasTimeEstimate.totalTokenFees * root.swapAdaptor.fromToken.marketDetails.currencyPrice.amount let totalFees = root.swapAdaptor.currencyStore.getFiatValue(gasTimeEstimate.totalFeesInEth, Constants.ethToken) + totalTokenFeesInFiat compare(root.swapAdaptor.swapOutputData.totalFees, totalFees) compare(root.swapAdaptor.swapOutputData.bestRoutes, txRoutes.suggestedRoutes) compare(root.swapAdaptor.swapOutputData.approvalNeeded, false) compare(root.swapAdaptor.swapOutputData.hasError, false) verify(!errorTag.visible) verify(signButton.enabled) compare(signButton.text, qsTr("Swap")) // verfy input and output panels waitForRendering(receivePanel) verify(payPanel.valueValid) verify(!receivePanel.mainInputLoading) verify(!receivePanel.bottomTextLoading) verify(!receivePanel.interactive) compare(receivePanel.selectedHoldingId, root.swapFormData.toTokenKey) compare(receivePanel.value, root.swapStore.getWei2Eth(txRoutes.amountToReceive, root.swapAdaptor.toToken.decimals)) compare(receivePanel.rawValue, SQUtils.AmountsArithmetic.fromNumber( LocaleUtils.numberFromLocaleString(root.swapAdaptor.swapOutputData.toTokenAmount, Qt.locale()), root.swapAdaptor.toToken.decimals).toString()) // edit some params to retry swap root.swapFormData.fromTokenAmount = "0.012" compare(formValuesChanged.count, 6) // wait for fetchSuggestedRoutes function to be called wait(1000) // verify loading state was set and no errors currently verifyLoadingAndNoErrorsState(payPanel, receivePanel) // emit event with route that needs no approval let txRoutes2 = root.dummySwapTransactionRoutes.txHasRoutesApprovalNeeded root.swapStore.suggestedRoutesReady(txRoutes2) // verify loading state removed and data ius displayed as expected on the Modal verify(root.swapAdaptor.validSwapProposalReceived) verify(!root.swapAdaptor.swapProposalLoading) compare(root.swapAdaptor.swapOutputData.fromTokenAmount, "") compare(root.swapAdaptor.swapOutputData.toTokenAmount, SQUtils.AmountsArithmetic.div( SQUtils.AmountsArithmetic.fromString(txRoutes.amountToReceive), SQUtils.AmountsArithmetic.fromNumber(1, root.swapAdaptor.toToken.decimals)).toString()) // calculation needed for total fees gasTimeEstimate = txRoutes2.gasTimeEstimate totalTokenFeesInFiat = gasTimeEstimate.totalTokenFees * root.swapAdaptor.fromToken.marketDetails.currencyPrice.amount totalFees = root.swapAdaptor.currencyStore.getFiatValue(gasTimeEstimate.totalFeesInEth, Constants.ethToken) + totalTokenFeesInFiat compare(root.swapAdaptor.swapOutputData.totalFees, totalFees) compare(root.swapAdaptor.swapOutputData.bestRoutes, txRoutes2.suggestedRoutes) compare(root.swapAdaptor.swapOutputData.approvalNeeded, true) compare(root.swapAdaptor.swapOutputData.hasError, false) verify(!errorTag.visible) verify(signButton.enabled) compare(signButton.text, qsTr("Approve %1").arg(root.swapAdaptor.fromToken.symbol)) // verfy input and output panels waitForRendering(receivePanel) verify(payPanel.valueValid) verify(!receivePanel.mainInputLoading) verify(!receivePanel.bottomTextLoading) verify(!receivePanel.interactive) compare(receivePanel.selectedHoldingId, root.swapFormData.toTokenKey) compare(receivePanel.value, root.swapStore.getWei2Eth(txRoutes.amountToReceive, root.swapAdaptor.toToken.decimals)) compare(receivePanel.rawValue, SQUtils.AmountsArithmetic.fromNumber( LocaleUtils.numberFromLocaleString(root.swapAdaptor.swapOutputData.toTokenAmount, Qt.locale()), root.swapAdaptor.toToken.decimals).toString()) } function test_modal_pay_input_default() { // Launch popup launchAndVerfyModal() const payPanel = findChild(controlUnderTest, "payPanel") verify(!!payPanel) const amountToSendInput = findChild(payPanel, "amountToSendInput") verify(!!amountToSendInput) const bottomItemText = findChild(payPanel, "bottomItemText") verify(!!bottomItemText) const holdingSelector = findChild(payPanel, "holdingSelector") verify(!!holdingSelector) const maxTagButton = findChild(payPanel, "maxTagButton") verify(!!maxTagButton) const tokenSelectorContentItemText = findChild(payPanel, "tokenSelectorContentItemText") verify(!!tokenSelectorContentItemText) waitForRendering(payPanel) // check default states for the from input selector compare(amountToSendInput.caption, qsTr("Pay")) verify(amountToSendInput.interactive) compare(amountToSendInput.input.text, "") verify(amountToSendInput.input.input.edit.cursorVisible) compare(amountToSendInput.input.placeholderText, LocaleUtils.numberToLocaleString(0)) compare(bottomItemText.text, root.swapAdaptor.currencyStore.formatCurrencyAmount(0, root.swapAdaptor.currencyStore.currentCurrency)) compare(holdingSelector.currentTokensKey, "") compare(tokenSelectorContentItemText.text, qsTr("Select asset")) verify(!maxTagButton.visible) compare(payPanel.selectedHoldingId, "") compare(payPanel.value, 0) compare(payPanel.rawValue, "0") verify(!payPanel.valueValid) closeAndVerfyModal() } function test_modal_pay_input_presetValues() { // try setting value before popup is launched and check values let valueToExchange = 0.001 let valueToExchangeString = valueToExchange.toString() root.swapFormData.selectedAccountAddress = swapAdaptor.nonWatchAccounts.get(0).address root.swapFormData.selectedNetworkChainId = root.swapAdaptor.filteredFlatNetworksModel.get(0).chainId root.swapFormData.fromTokensKey = "ETH" root.swapFormData.fromTokenAmount = valueToExchangeString let expectedToken = SQUtils.ModelUtils.getByKey(root.tokenSelectorAdaptor.outputAssetsModel, "tokensKey", "ETH") // Launch popup launchAndVerfyModal() waitForItemPolished(controlUnderTest.contentItem) const payPanel = findChild(controlUnderTest, "payPanel") verify(!!payPanel) const amountToSendInput = findChild(payPanel, "amountToSendInput") verify(!!amountToSendInput) const bottomItemText = findChild(payPanel, "bottomItemText") verify(!!bottomItemText) const holdingSelector = findChild(payPanel, "holdingSelector") verify(!!holdingSelector) const maxTagButton = findChild(payPanel, "maxTagButton") verify(!!maxTagButton) const tokenSelectorContentItemText = findChild(payPanel, "tokenSelectorContentItemText") verify(!!tokenSelectorContentItemText) const tokenSelectorIcon = findChild(payPanel, "tokenSelectorIcon") verify(!!tokenSelectorIcon) compare(amountToSendInput.caption, qsTr("Pay")) verify(amountToSendInput.interactive) tryCompare(amountToSendInput.input.input, "text", valueToExchangeString) compare(amountToSendInput.input.placeholderText, LocaleUtils.numberToLocaleString(0)) tryCompare(amountToSendInput.input.input.edit, "cursorVisible", true) tryCompare(bottomItemText, "text", root.swapAdaptor.currencyStore.formatCurrencyAmount(valueToExchange * expectedToken.marketDetails.currencyPrice.amount, root.swapAdaptor.currencyStore.currentCurrency)) compare(holdingSelector.currentTokensKey, expectedToken.tokensKey) compare(tokenSelectorContentItemText.text, expectedToken.symbol) compare(tokenSelectorIcon.image.source, Constants.tokenIcon(expectedToken.symbol)) verify(tokenSelectorIcon.visible) verify(maxTagButton.visible) compare(maxTagButton.text, qsTr("Max. %1").arg(root.swapAdaptor.currencyStore.formatCurrencyAmount(WalletUtils.calculateMaxSafeSendAmount(expectedToken.currentBalance, expectedToken.symbol), expectedToken.symbol, {noSymbol: true}))) compare(payPanel.selectedHoldingId, expectedToken.symbol) compare(payPanel.value, valueToExchange) compare(payPanel.rawValue, SQUtils.AmountsArithmetic.fromNumber(valueToExchangeString, expectedToken.decimals).toString()) verify(payPanel.valueValid) closeAndVerfyModal() } function test_modal_pay_input_wrong_value_1() { let invalidValues = ["ABC", "0.0.010201", "12PASA", "100,9.01"] for (let i =0; i maxPossibleValue let errortext = amountEnteredGreaterThanMaxBalance ? qsTr("Insufficient funds for swap"): qsTr("An error has occured, please try again") compare(errorTag.visible, amountEnteredGreaterThanMaxBalance) compare(errorTag.text, errortext) compare(errorTag.buttonText, qsTr("Buy crypto")) compare(errorTag.buttonVisible, amountEnteredGreaterThanMaxBalance) } closeAndVerfyModal() } } function test_modal_exchange_button_default_state() { let default_test_data = [{fromToken: "", fromTokenAmount: "", toToken: "", toTokenAmount: ""}, {fromToken: "", fromTokenAmount: "", toToken: "STT", toTokenAmount: ""}, {fromToken: "ETH", fromTokenAmount: "", toToken: "", toTokenAmount: ""}, {fromToken: "ETH", fromTokenAmount: "", toToken: "STT", toTokenAmount: ""}, {fromToken: "ETH", fromTokenAmount: "100", toToken: "STT", toTokenAmount: ""}, {fromToken: "ETH", fromTokenAmount: "", toToken: "STT", toTokenAmount: "50"}, {fromToken: "ETH", fromTokenAmount: "100", toToken: "STT", toTokenAmount: "50"}, {fromToken: "", fromTokenAmount: "", toToken: "", toTokenAmount: "50"}, {fromToken: "", fromTokenAmount: "100", toToken: "", toTokenAmount: ""}] const payPanel = findChild(controlUnderTest, "payPanel") verify(!!payPanel) const receivePanel = findChild(controlUnderTest, "receivePanel") verify(!!receivePanel) const swapExchangeButton = findChild(controlUnderTest, "swapExchangeButton") verify(!!swapExchangeButton) const payAmountToSendInput = findChild(payPanel, "amountToSendInput") verify(!!payAmountToSendInput) const payBottomItemText = findChild(payPanel, "bottomItemText") verify(!!payBottomItemText) const maxTagButton = findChild(payPanel, "maxTagButton") verify(!!maxTagButton) const receiveAmountToSendInput = findChild(receivePanel, "amountToSendInput") verify(!!receiveAmountToSendInput) const receiveBottomItemText = findChild(receivePanel, "bottomItemText") verify(!!receiveBottomItemText) for (let i =0; i< default_test_data.length; i++) { root.swapAdaptor.reset() // set network and address by default same root.swapFormData.selectedNetworkChainId = root.swapAdaptor.filteredFlatNetworksModel.get(0).chainId root.swapFormData.selectedAccountAddress = root.swapAdaptor.nonWatchAccounts.get(0).address root.swapFormData.fromTokensKey = default_test_data[i].fromToken root.swapFormData.fromTokenAmount = default_test_data[i].fromTokenAmount root.swapFormData.toTokenKey = default_test_data[i].toToken root.swapFormData.toTokenAmount = default_test_data[i].toTokenAmount let expectedFromTokenIcon = !!root.swapAdaptor.fromToken && !!root.swapAdaptor.fromToken.symbol ? Constants.tokenIcon(root.swapAdaptor.fromToken.symbol): "" let expectedToTokenIcon = !!root.swapAdaptor.toToken && !!root.swapAdaptor.toToken.symbol ? Constants.tokenIcon(root.swapAdaptor.toToken.symbol): "" // Launch popup launchAndVerfyModal() waitForRendering(payPanel) waitForRendering(receivePanel) let paytokenSelectorContentItemText = findChild(payPanel, "tokenSelectorContentItemText") verify(!!paytokenSelectorContentItemText) let paytokenSelectorIcon = findChild(payPanel, "tokenSelectorIcon") compare(!!default_test_data[i].fromToken , !!paytokenSelectorIcon) let receivetokenSelectorContentItemText = findChild(receivePanel, "tokenSelectorContentItemText") verify(!!receivetokenSelectorContentItemText) let receivetokenSelectorIcon = findChild(receivePanel, "tokenSelectorIcon") compare(!!default_test_data[i].toToken, !!receivetokenSelectorIcon) // verify pay values compare(payPanel.tokenKey, default_test_data[i].fromToken) compare(payPanel.tokenAmount, default_test_data[i].fromTokenAmount) verify(payAmountToSendInput.input.input.edit.cursorVisible) compare(paytokenSelectorContentItemText.text, !!root.swapFormData.fromTokensKey ? root.swapFormData.fromTokensKey : qsTr("Select asset")) compare(!!default_test_data[i].fromToken , !!paytokenSelectorIcon) if(!!paytokenSelectorIcon) { compare(paytokenSelectorIcon.image.source, expectedFromTokenIcon) } verify(!!default_test_data[i].fromToken ? maxTagButton.visible: !maxTagButton.visible) // verify receive values compare(receivePanel.tokenKey, default_test_data[i].toToken) compare(receivePanel.tokenAmount, default_test_data[i].toTokenAmount) verify(!receiveAmountToSendInput.input.input.edit.cursorVisible) compare(receivetokenSelectorContentItemText.text, !!root.swapFormData.toTokenKey ? root.swapFormData.toTokenKey : qsTr("Select asset")) if(!!receivetokenSelectorIcon) { compare(receivetokenSelectorIcon.image.source, expectedToTokenIcon) } // click exchange button swapExchangeButton.clicked() waitForRendering(payPanel) waitForRendering(receivePanel) // verify form values compare(root.swapFormData.fromTokensKey, default_test_data[i].toToken) compare(root.swapFormData.fromTokenAmount, default_test_data[i].toTokenAmount) compare(root.swapFormData.toTokenKey, default_test_data[i].fromToken) compare(root.swapFormData.toTokenAmount, default_test_data[i].fromTokenAmount) paytokenSelectorContentItemText = findChild(payPanel, "tokenSelectorContentItemText") verify(!!paytokenSelectorContentItemText) paytokenSelectorIcon = findChild(payPanel, "tokenSelectorIcon") compare(!!root.swapFormData.fromTokensKey , !!paytokenSelectorIcon) receivetokenSelectorContentItemText = findChild(receivePanel, "tokenSelectorContentItemText") verify(!!receivetokenSelectorContentItemText) receivetokenSelectorIcon = findChild(receivePanel, "tokenSelectorIcon") compare(!!root.swapFormData.toTokenKey, !!receivetokenSelectorIcon) // verify pay values compare(payPanel.tokenKey, default_test_data[i].toToken) compare(payPanel.tokenAmount, default_test_data[i].toTokenAmount) verify(payAmountToSendInput.input.input.edit.cursorVisible) compare(paytokenSelectorContentItemText.text, !!default_test_data[i].toToken ? default_test_data[i].toToken : qsTr("Select asset")) if(!!paytokenSelectorIcon) { compare(paytokenSelectorIcon.image.source, expectedToTokenIcon) } verify(!!default_test_data[i].toToken ? maxTagButton.visible: !maxTagButton.visible) compare(maxTagButton.text, qsTr("Max. %1").arg(Qt.locale().zeroDigit)) compare(maxTagButton.type, (payAmountToSendInput.input.valid || !payAmountToSendInput.input.text) && maxTagButton.value > 0 ? StatusBaseButton.Type.Normal : StatusBaseButton.Type.Danger) // verify receive values compare(receivePanel.tokenKey, default_test_data[i].fromToken) compare(receivePanel.tokenAmount, default_test_data[i].fromTokenAmount) verify(!receiveAmountToSendInput.input.input.edit.cursorVisible) compare(receivetokenSelectorContentItemText.text, !!default_test_data[i].fromToken ? default_test_data[i].fromToken : qsTr("Select asset")) if(!!receivetokenSelectorIcon) { compare(receivetokenSelectorIcon.image.source, expectedFromTokenIcon) } closeAndVerfyModal() } } } }