From e6f569753776584113cfef0e95500597fe6a844c Mon Sep 17 00:00:00 2001 From: Abdurrahman SASTIM Date: Fri, 3 Jan 2025 10:15:07 +0100 Subject: [PATCH] test: speculos detox send test --- apps/ledger-live-mobile/e2e/bridge/client.ts | 4 ++ apps/ledger-live-mobile/e2e/helpers.ts | 14 ++++ apps/ledger-live-mobile/e2e/models/send.ts | 43 ++++++++++++ .../e2e/page/accounts/account.page.ts | 15 ++++- .../e2e/page/common.page.ts | 7 ++ .../e2e/page/speculos.page.ts | 7 +- .../e2e/page/trade/operationDetails.page.ts | 15 ++++- .../e2e/page/trade/send.page.ts | 34 ++++++++++ .../e2e/specs/speculos/send/send.ts | 65 +++++++++++++++++++ .../e2e/specs/speculos/send/sendADA.spec.ts | 6 ++ .../e2e/specs/speculos/send/sendALGO.spec.ts | 6 ++ .../e2e/specs/speculos/send/sendATOM.spec.ts | 6 ++ .../e2e/specs/speculos/send/sendBCH.spec.ts | 6 ++ .../e2e/specs/speculos/send/sendDOGE.spec.ts | 6 ++ .../e2e/specs/speculos/send/sendDOT.spec.ts | 6 ++ .../e2e/specs/speculos/send/sendPOL.spec.ts | 6 ++ .../e2e/specs/speculos/send/sendSOL.spec.ts | 6 ++ .../specs/speculos/send/sendSepETH.spec.ts | 6 ++ .../e2e/specs/speculos/send/sendTRX.spec.ts | 6 ++ .../e2e/specs/speculos/send/sendXLM.spec.ts | 6 ++ .../e2e/specs/speculos/send/sendXRP.spec.ts | 6 ++ .../src/components/ConfirmationModal.tsx | 3 + .../src/components/ValidateOnDevice.tsx | 13 +++- .../components/ValidateOnDeviceDataRow.tsx | 9 ++- .../src/components/ValidateSuccess.tsx | 1 + .../src/screens/OperationDetails/Content.tsx | 1 + .../src/screens/OperationDetails/DataList.tsx | 11 ++-- .../screens/SendFunds/SummaryToSection.tsx | 2 + libs/coin-framework/src/transaction/common.ts | 1 + .../src/deviceTransactionConfig.ts | 2 +- .../src/deviceTransactionConfig.ts | 4 +- .../src/deviceTransactionConfig.ts | 2 +- .../src/bridge/deviceTransactionConfig.ts | 2 +- libs/ledger-live-common/src/e2e/speculos.ts | 2 +- 34 files changed, 309 insertions(+), 20 deletions(-) create mode 100644 apps/ledger-live-mobile/e2e/models/send.ts create mode 100644 apps/ledger-live-mobile/e2e/specs/speculos/send/send.ts create mode 100644 apps/ledger-live-mobile/e2e/specs/speculos/send/sendADA.spec.ts create mode 100644 apps/ledger-live-mobile/e2e/specs/speculos/send/sendALGO.spec.ts create mode 100644 apps/ledger-live-mobile/e2e/specs/speculos/send/sendATOM.spec.ts create mode 100644 apps/ledger-live-mobile/e2e/specs/speculos/send/sendBCH.spec.ts create mode 100644 apps/ledger-live-mobile/e2e/specs/speculos/send/sendDOGE.spec.ts create mode 100644 apps/ledger-live-mobile/e2e/specs/speculos/send/sendDOT.spec.ts create mode 100644 apps/ledger-live-mobile/e2e/specs/speculos/send/sendPOL.spec.ts create mode 100644 apps/ledger-live-mobile/e2e/specs/speculos/send/sendSOL.spec.ts create mode 100644 apps/ledger-live-mobile/e2e/specs/speculos/send/sendSepETH.spec.ts create mode 100644 apps/ledger-live-mobile/e2e/specs/speculos/send/sendTRX.spec.ts create mode 100644 apps/ledger-live-mobile/e2e/specs/speculos/send/sendXLM.spec.ts create mode 100644 apps/ledger-live-mobile/e2e/specs/speculos/send/sendXRP.spec.ts diff --git a/apps/ledger-live-mobile/e2e/bridge/client.ts b/apps/ledger-live-mobile/e2e/bridge/client.ts index 3a8586614751..a8c1e73f9d55 100644 --- a/apps/ledger-live-mobile/e2e/bridge/client.ts +++ b/apps/ledger-live-mobile/e2e/bridge/client.ts @@ -25,9 +25,13 @@ const retryDelay = 500; // Initial retry delay in milliseconds export function init() { const wsPort = LaunchArguments.value()["wsPort"] || "8099"; const mock = LaunchArguments.value()["mock"]; + const disable_broadcast = LaunchArguments.value()["disable_broadcast"]; + log(`[E2E Bridge Client]: wsPort=${wsPort}, mock=${mock}`); if (mock == "0") setEnv("MOCK", ""); + setEnv("DISABLE_TRANSACTION_BROADCAST", disable_broadcast != "0"); + if (ws) { ws.close(); } diff --git a/apps/ledger-live-mobile/e2e/helpers.ts b/apps/ledger-live-mobile/e2e/helpers.ts index c882035473f8..aa50ece3d831 100644 --- a/apps/ledger-live-mobile/e2e/helpers.ts +++ b/apps/ledger-live-mobile/e2e/helpers.ts @@ -63,6 +63,17 @@ export function getWebElementByTag(tag: string, index = 0) { return web.element(by.web.tag(tag)).atIndex(index); } +export async function IsIdVisible(id: string | RegExp) { + try { + await waitFor(element(by.id(id))) + .toBeVisible() + .withTimeout(1000); + return true; + } catch { + return false; + } +} + export async function tapById(id: string | RegExp, index = 0) { return getElementById(id, index).tap(); } @@ -180,6 +191,9 @@ export async function launchApp() { detoxURLBlacklistRegex: '\\(".*sdk.*.braze.*",".*.googleapis.com/.*",".*clients3.google.com.*"\\)', mock: getEnv("MOCK") ? getEnv("MOCK") : "0", + disable_broadcast: getEnv("DISABLE_TRANSACTION_BROADCAST") + ? getEnv("DISABLE_TRANSACTION_BROADCAST") + : "1", }, languageAndLocale: { language: "en-US", diff --git a/apps/ledger-live-mobile/e2e/models/send.ts b/apps/ledger-live-mobile/e2e/models/send.ts new file mode 100644 index 000000000000..371523bf66e0 --- /dev/null +++ b/apps/ledger-live-mobile/e2e/models/send.ts @@ -0,0 +1,43 @@ +import { Currency } from "@ledgerhq/live-common/e2e/enum/Currency"; +import { Application } from "../page"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; + +export async function verifyAppValidationSendInfo( + app: Application, + transaction: Transaction, + amount: string, +) { + const currenciesForValidationAmount = [ + Currency.sepETH, + Currency.DOT, + Currency.POL, + Currency.ALGO, + Currency.ADA, + Currency.DOGE, + Currency.SOL, + Currency.TRX, + Currency.XLM, + Currency.XRP, + Currency.ATOM, + Currency.BCH, + ]; + + const currenciesForValidationRecipient = [Currency.sepETH, Currency.POL]; + const currenciesForValidationSender = [Currency.ATOM]; + + const currency = transaction.accountToCredit.currency; + const addressRecipient = transaction.accountToCredit.address; + const addressSender = transaction.accountToDebit.address; + + if (currenciesForValidationAmount.includes(currency)) { + await app.send.expectValidationAmount(amount); + } + + if (currenciesForValidationRecipient.includes(currency)) { + await app.send.expectValidationAddress(addressRecipient); + } + + if (currenciesForValidationSender.includes(currency)) { + await app.send.expectValidationAddress(addressSender); + } +} diff --git a/apps/ledger-live-mobile/e2e/page/accounts/account.page.ts b/apps/ledger-live-mobile/e2e/page/accounts/account.page.ts index 66d2a749ef82..cb9e6d5e7f70 100644 --- a/apps/ledger-live-mobile/e2e/page/accounts/account.page.ts +++ b/apps/ledger-live-mobile/e2e/page/accounts/account.page.ts @@ -9,10 +9,13 @@ export default class AccountPage { accountAdvancedLogRow = () => getElementById("account-advanced-log-row"); accountDeleteRow = () => getElementById("account-settings-delete-row"); accountDeleteConfirm = () => getElementById("delete-account-confirmation-button"); - operationHistorySectionId = (accountId: string) => `operations-history-${accountId}`; + operationHistorySection = "operations-history-"; + operationHistorySectionRegexp = new RegExp(this.operationHistorySection + ".*"); + operationHistorySectionId = (accountId: string) => this.operationHistorySection + accountId; accountScreenScrollView = "account-screen-scrollView"; accountAdvancedLogsId = "account-advanced-logs"; receiveButton = () => getElementById("account-quick-action-button-Receive"); + sendButton = () => getElementById("account-quick-action-button-Send"); @Step("Open account settings") async openAccountSettings() { @@ -41,6 +44,11 @@ export default class AccountPage { await expect(getElementById(id)).toBeVisible(); } + @Step("Scroll to transaction history") + async scrollToTransactions() { + await scrollToId(this.operationHistorySectionRegexp, this.accountScreenScrollView); + } + @Step("Expect account balance to be visible") async expectAccountBalanceVisible(accountId: string) { await expect(this.accountGraph(accountId)).toBeVisible(); @@ -60,4 +68,9 @@ export default class AccountPage { async tapReceive() { await tapByElement(this.receiveButton()); } + + @Step("Tap on send button") + async tapSend() { + await tapByElement(this.sendButton()); + } } diff --git a/apps/ledger-live-mobile/e2e/page/common.page.ts b/apps/ledger-live-mobile/e2e/page/common.page.ts index 50fc13af7945..3eef14bb8bd1 100644 --- a/apps/ledger-live-mobile/e2e/page/common.page.ts +++ b/apps/ledger-live-mobile/e2e/page/common.page.ts @@ -21,6 +21,7 @@ export default class CommonPage { searchBarId = "common-search-field"; searchBar = () => getElementById(this.searchBarId); successCloseButtonId = "success-close-button"; + successViewDetailsButtonId = "success-view-details-button"; closeButton = () => getElementById("NavigationHeaderCloseButton"); accoundCardId = (id: string) => "account-card-" + id; @@ -53,6 +54,12 @@ export default class CommonPage { await tapById(this.successCloseButtonId); } + @Step("Tap on view details") + async successViewDetails() { + await waitForElementById(this.successViewDetailsButtonId); + await tapById(this.successViewDetailsButtonId); + } + async selectAccount(accountId: string) { const id = this.accoundCardId(accountId); await waitForElementById(id); diff --git a/apps/ledger-live-mobile/e2e/page/speculos.page.ts b/apps/ledger-live-mobile/e2e/page/speculos.page.ts index 7dbdb37596fc..c057c210f57d 100644 --- a/apps/ledger-live-mobile/e2e/page/speculos.page.ts +++ b/apps/ledger-live-mobile/e2e/page/speculos.page.ts @@ -1,9 +1,14 @@ -import { expectValidAddressDevice } from "@ledgerhq/live-common/e2e/speculos"; +import { expectValidAddressDevice, signSendTransaction } from "@ledgerhq/live-common/e2e/speculos"; import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; export default class SpeculosPage { @Step("Verify receive address correctness on device") async expectValidAddressDevice(account: Account, addressDisplayed: string) { await expectValidAddressDevice(account, addressDisplayed); } + + async signSendTransaction(tx: Transaction) { + await signSendTransaction(tx); + } } diff --git a/apps/ledger-live-mobile/e2e/page/trade/operationDetails.page.ts b/apps/ledger-live-mobile/e2e/page/trade/operationDetails.page.ts index 4b0db462e5ad..2c33cfbb5910 100644 --- a/apps/ledger-live-mobile/e2e/page/trade/operationDetails.page.ts +++ b/apps/ledger-live-mobile/e2e/page/trade/operationDetails.page.ts @@ -1,15 +1,21 @@ -import { getElementById } from "../../helpers"; +import { getElementById, scrollToId, waitForElementById } from "../../helpers"; import { expect } from "detox"; export default class OperationDetailsPage { - title = () => getElementById("operationDetails-title"); + titleId = "operationDetails-title"; + title = () => getElementById(this.titleId); account = () => getElementById("operationDetails-account"); amount = () => getElementById("operationDetails-amount"); + recipientId = "operationDetails-recipient0"; async isOpened() { await expect(this.title()).toBeVisible(); } + async waitForOperationDetails() { + await waitForElementById(this.titleId); + } + async checkAccount(account: string) { await expect(this.account()).toHaveText(account); } @@ -17,4 +23,9 @@ export default class OperationDetailsPage { async checkAmount(amount: string) { await expect(this.amount()).toHaveText(amount); } + + async checkRecipient(recipient: string) { + await scrollToId(this.recipientId); + await expect(getElementById(this.recipientId)).toHaveText(recipient); + } } diff --git a/apps/ledger-live-mobile/e2e/page/trade/send.page.ts b/apps/ledger-live-mobile/e2e/page/trade/send.page.ts index 86f2df633d1f..00457c16aa5f 100644 --- a/apps/ledger-live-mobile/e2e/page/trade/send.page.ts +++ b/apps/ledger-live-mobile/e2e/page/trade/send.page.ts @@ -6,6 +6,7 @@ import { openDeeplink, typeTextById, tapByElement, + IsIdVisible, } from "../../helpers"; import { expect } from "detox"; @@ -13,12 +14,16 @@ const baseLink = "send"; export default class SendPage { summaryAmount = () => getElementById("send-summary-amount"); + summaryRecipient = () => getElementById("send-summary-recipient"); + validationAmountId = "send-validation-amount"; + validationAddressId = "send-validation-address"; getStep1HeaderTitle = () => getElementById("send-header-step1-title"); recipientContinueButtonId = "recipient-continue-button"; recipientInputId = "recipient-input"; amountInputId = "amount-input"; amountContinueButton = () => getElementById("amount-continue-button"); summaryContinueButton = () => getElementById("summary-continue-button"); + highFreeConfirmButtonID = "confirmation-modal-confirm-button"; async openViaDeeplink() { await openDeeplink(baseLink); @@ -42,6 +47,11 @@ export default class SendPage { await tapById(this.recipientContinueButtonId); } + async setRecipientAndContinue(address: string) { + await this.setRecipient(address); + await this.recipientContinue(); + } + async setAmount(amount: string) { const element = getElementById(this.amountInputId); await element.replaceText(amount); @@ -52,6 +62,11 @@ export default class SendPage { await tapByElement(this.amountContinueButton()); } + async setAmountAndContinue(amount: string) { + await this.setAmount(amount); + await this.amountContinue(); + } + async summaryContinue() { await tapByElement(this.summaryContinueButton()); } @@ -59,4 +74,23 @@ export default class SendPage { async expectSummaryAmount(amount: string) { await expect(this.summaryAmount()).toHaveText(amount); } + + async expectSummaryRecepient(recipient: string) { + await expect(this.summaryRecipient()).toHaveText(recipient); + } + + async dismissHighFeeModal() { + if (await IsIdVisible(this.highFreeConfirmButtonID)) + await tapById(this.highFreeConfirmButtonID); + } + + async expectValidationAmount(amount: string) { + await waitForElementById(this.validationAmountId); + await expect(getElementById(this.validationAmountId)).toHaveText(amount); + } + + async expectValidationAddress(recipient: string) { + await waitForElementById(this.validationAddressId); + await expect(getElementById(this.validationAddressId)).toHaveText(recipient); + } } diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/send/send.ts b/apps/ledger-live-mobile/e2e/specs/speculos/send/send.ts new file mode 100644 index 000000000000..9064e49ffa00 --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/send/send.ts @@ -0,0 +1,65 @@ +import { verifyAppValidationSendInfo } from "../../../models/send"; +import { Application } from "../../../page"; +import { CLI } from "../../../utils/cliUtils"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; +import { device } from "detox"; + +export async function runSendTest(transaction: Transaction, tmsLink: string) { + const app = new Application(); + + $TmsLink(tmsLink); + describe(`Send flow on ${transaction.accountToCredit.currency.name}`, () => { + beforeAll(async () => { + await app.init({ + speculosApp: transaction.accountToCredit.currency.speculosApp, + cliCommands: [ + () => { + return CLI.liveData({ + currency: transaction.accountToCredit.currency.currencyId, + index: transaction.accountToCredit.index, + add: true, + appjson: app.userdataPath, + }); + }, + () => { + return CLI.liveData({ + currency: transaction.accountToDebit.currency.currencyId, + index: transaction.accountToDebit.index, + add: true, + appjson: app.userdataPath, + }); + }, + ], + }); + + await app.portfolio.waitForPortfolioPageToLoad(); + }); + + it(`Send from 1 account to another on ${transaction.accountToCredit.currency.name}`, async () => { + await app.accounts.openViaDeeplink(); + await app.common.goToAccountByName(transaction.accountToDebit.accountName); + await app.account.tapSend(); + + const amountWithCode = transaction.amount + " " + transaction.accountToCredit.currency.ticker; + + await app.send.setRecipientAndContinue(transaction.accountToCredit.address); + await app.send.setAmountAndContinue(transaction.amount); + + await app.send.expectSummaryAmount(amountWithCode); + await app.send.expectSummaryRecepient(transaction.accountToCredit.address); + await app.send.summaryContinue(); + await app.send.dismissHighFeeModal(); + + await verifyAppValidationSendInfo(app, transaction, amountWithCode); + + await app.speculos.signSendTransaction(transaction); + + await device.disableSynchronization(); + await app.common.successViewDetails(); + + await app.operationDetails.waitForOperationDetails(); + await app.operationDetails.checkAccount(transaction.accountToDebit.accountName); + await app.operationDetails.checkRecipient(transaction.accountToCredit.address); + }); + }); +} diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/send/sendADA.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendADA.spec.ts new file mode 100644 index 000000000000..0d8962efd476 --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendADA.spec.ts @@ -0,0 +1,6 @@ +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; +import { runSendTest } from "../send/send"; + +const transaction = new Transaction(Account.ADA_1, Account.ADA_2, "1"); +runSendTest(transaction, "B2CQA-2815"); diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/send/sendALGO.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendALGO.spec.ts new file mode 100644 index 000000000000..6e361e5b576d --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendALGO.spec.ts @@ -0,0 +1,6 @@ +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; +import { runSendTest } from "../send/send"; + +const transaction = new Transaction(Account.ALGO_1, Account.ALGO_2, "0.001"); +runSendTest(transaction, "B2CQA-2810"); diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/send/sendATOM.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendATOM.spec.ts new file mode 100644 index 000000000000..beb0868a3dee --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendATOM.spec.ts @@ -0,0 +1,6 @@ +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; +import { runSendTest } from "../send/send"; + +const transaction = new Transaction(Account.ATOM_1, Account.ATOM_2, "0.0001"); +runSendTest(transaction, "B2CQA-2814"); diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/send/sendBCH.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendBCH.spec.ts new file mode 100644 index 000000000000..a06e50efff40 --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendBCH.spec.ts @@ -0,0 +1,6 @@ +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; +import { runSendTest } from "../send/send"; + +const transaction = new Transaction(Account.BCH_1, Account.BCH_2, "0.0001"); +runSendTest(transaction, "B2CQA-2808"); diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/send/sendDOGE.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendDOGE.spec.ts new file mode 100644 index 000000000000..bf5db5cfac9a --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendDOGE.spec.ts @@ -0,0 +1,6 @@ +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; +import { runSendTest } from "../send/send"; + +const transaction = new Transaction(Account.DOGE_1, Account.DOGE_2, "0.01"); +runSendTest(transaction, "B2CQA-2573"); diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/send/sendDOT.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendDOT.spec.ts new file mode 100644 index 000000000000..9b025c7332b4 --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendDOT.spec.ts @@ -0,0 +1,6 @@ +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; +import { runSendTest } from "../send/send"; + +const transaction = new Transaction(Account.DOT_1, Account.DOT_2, "0.0001"); +runSendTest(transaction, "B2CQA-2809"); diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/send/sendPOL.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendPOL.spec.ts new file mode 100644 index 000000000000..22231f33c41f --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendPOL.spec.ts @@ -0,0 +1,6 @@ +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; +import { runSendTest } from "../send/send"; + +const transaction = new Transaction(Account.POL_1, Account.POL_2, "0.001"); +runSendTest(transaction, "B2CQA-2807"); diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/send/sendSOL.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendSOL.spec.ts new file mode 100644 index 000000000000..4e1ec0fc09dc --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendSOL.spec.ts @@ -0,0 +1,6 @@ +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; +import { runSendTest } from "../send/send"; + +const transaction = new Transaction(Account.SOL_1, Account.SOL_2, "0.000001"); +runSendTest(transaction, "B2CQA-2811"); diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/send/sendSepETH.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendSepETH.spec.ts new file mode 100644 index 000000000000..55d4c6ad357e --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendSepETH.spec.ts @@ -0,0 +1,6 @@ +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; +import { runSendTest } from "../send/send"; + +const transaction = new Transaction(Account.sep_ETH_1, Account.sep_ETH_2, "0.00001"); +runSendTest(transaction, "B2CQA-2574"); diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/send/sendTRX.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendTRX.spec.ts new file mode 100644 index 000000000000..59cb2300d7f8 --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendTRX.spec.ts @@ -0,0 +1,6 @@ +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; +import { runSendTest } from "../send/send"; + +const transaction = new Transaction(Account.TRX_1, Account.TRX_2, "0.01"); +runSendTest(transaction, "B2CQA-2812"); diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/send/sendXLM.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendXLM.spec.ts new file mode 100644 index 000000000000..5ddb612c8673 --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendXLM.spec.ts @@ -0,0 +1,6 @@ +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; +import { runSendTest } from "../send/send"; + +const transaction = new Transaction(Account.XLM_1, Account.XLM_2, "0.0001"); +runSendTest(transaction, "B2CQA-2813"); diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/send/sendXRP.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendXRP.spec.ts new file mode 100644 index 000000000000..40a6c9474c2f --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/send/sendXRP.spec.ts @@ -0,0 +1,6 @@ +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction"; +import { runSendTest } from "../send/send"; + +const transaction = new Transaction(Account.XRP_1, Account.XRP_2, "0.0001"); +runSendTest(transaction, "B2CQA-2816"); diff --git a/apps/ledger-live-mobile/src/components/ConfirmationModal.tsx b/apps/ledger-live-mobile/src/components/ConfirmationModal.tsx index 5d13fc67fb27..69f43fe90df3 100644 --- a/apps/ledger-live-mobile/src/components/ConfirmationModal.tsx +++ b/apps/ledger-live-mobile/src/components/ConfirmationModal.tsx @@ -24,6 +24,7 @@ type Props = { colors: Theme["colors"]; preventBackdropClick?: boolean; iconMarginBottom?: number; + testID?: string; }; class ConfirmationModal extends PureComponent { @@ -92,6 +93,7 @@ class ConfirmationModal extends PureComponent { containerStyle={styles.confirmationButton} type="secondary" title={rejectButtonText || } + testID={"confirmation-modal-cancel-button"} onPress={onClose} /> )} @@ -101,6 +103,7 @@ class ConfirmationModal extends PureComponent { containerStyle={[styles.confirmationButton, styles.confirmationLastButton]} type={alert ? "alert" : "primary"} title={confirmButtonText || } + testID={"confirmation-modal-confirm-button"} onPress={onConfirm} /> diff --git a/apps/ledger-live-mobile/src/components/ValidateOnDevice.tsx b/apps/ledger-live-mobile/src/components/ValidateOnDevice.tsx index 9736c734cb93..44b79de4f3a2 100644 --- a/apps/ledger-live-mobile/src/components/ValidateOnDevice.tsx +++ b/apps/ledger-live-mobile/src/components/ValidateOnDevice.tsx @@ -44,7 +44,14 @@ const AnimationContainer = styled(Flex).attrs({ function AmountField({ account, status, field }: FieldComponentProps) { const unit = useAccountUnit(account); - return ; + return ( + + ); } function FeesField({ account, parentAccount, status, field }: FieldComponentProps) { @@ -57,7 +64,9 @@ function FeesField({ account, parentAccount, status, field }: FieldComponentProp function AddressField({ field }: FieldComponentProps) { invariant(field.type === "address", "AddressField invalid"); - return ; + return ( + + ); } // NB Leaving AddressField although I think it's redundant at this point diff --git a/apps/ledger-live-mobile/src/components/ValidateOnDeviceDataRow.tsx b/apps/ledger-live-mobile/src/components/ValidateOnDeviceDataRow.tsx index 93e8462d4e11..08023a5480e7 100644 --- a/apps/ledger-live-mobile/src/components/ValidateOnDeviceDataRow.tsx +++ b/apps/ledger-live-mobile/src/components/ValidateOnDeviceDataRow.tsx @@ -77,10 +77,12 @@ export function TextValueField({ label, numberOfLines, value, + testID, }: { label: React.ReactNode; numberOfLines?: number; value: React.ReactNode; + testID?: string; }) { const { colors } = useTheme(); return ( @@ -95,7 +97,7 @@ export function TextValueField({ {label} - + {value} @@ -177,12 +179,13 @@ type Props = { label: React.ReactNode; value: BigNumber; unit: Unit; + testID?: string; }; -export const DataRowUnitValue = ({ label, value, unit }: Props) => { +export const DataRowUnitValue = ({ label, value, unit, testID }: Props) => { return ( - + diff --git a/apps/ledger-live-mobile/src/components/ValidateSuccess.tsx b/apps/ledger-live-mobile/src/components/ValidateSuccess.tsx index 54d99bfef8e3..da715c0c31e8 100644 --- a/apps/ledger-live-mobile/src/components/ValidateSuccess.tsx +++ b/apps/ledger-live-mobile/src/components/ValidateSuccess.tsx @@ -69,6 +69,7 @@ function ValidateSuccess({ outline={false} onPress={onViewDetails} mt={7} + testID="success-view-details-button" > diff --git a/apps/ledger-live-mobile/src/screens/OperationDetails/Content.tsx b/apps/ledger-live-mobile/src/screens/OperationDetails/Content.tsx index be3336956fa2..d605a44db92c 100644 --- a/apps/ledger-live-mobile/src/screens/OperationDetails/Content.tsx +++ b/apps/ledger-live-mobile/src/screens/OperationDetails/Content.tsx @@ -417,6 +417,7 @@ export default function Content({ } + testID="operationDetails-recipient" rightComp={ uniqueRecipients.length > 1 ? ( { +const DataList = ({ data, title, rightComp, colors, testID }: Props) => { const [showAll, setShowAll] = useState(false); const toggleShowAll = () => { @@ -61,14 +62,14 @@ const DataList = ({ data, title, rightComp, colors }: Props) => { )} - {(shouldShowMore ? data.slice(0, numToShow) : data).map(line => ( - + {(shouldShowMore ? data.slice(0, numToShow) : data).map((line, index) => ( + {line} ))} {showAll && - data.slice(numToShow).map(line => ( - + data.slice(numToShow).map((line, index) => ( + {line} ))} diff --git a/apps/ledger-live-mobile/src/screens/SendFunds/SummaryToSection.tsx b/apps/ledger-live-mobile/src/screens/SendFunds/SummaryToSection.tsx index 15e0163b134f..63c9d66b8f6f 100644 --- a/apps/ledger-live-mobile/src/screens/SendFunds/SummaryToSection.tsx +++ b/apps/ledger-live-mobile/src/screens/SendFunds/SummaryToSection.tsx @@ -30,6 +30,7 @@ const DefaultRecipientTemplate = memo(({ transaction }: Pick {recipient} @@ -56,6 +57,7 @@ const RecipientWithResolutionTemplate = memo(({ transaction }: Pick {recipient} diff --git a/libs/coin-framework/src/transaction/common.ts b/libs/coin-framework/src/transaction/common.ts index 33bf6b1d62db..4a1fa0bcf663 100644 --- a/libs/coin-framework/src/transaction/common.ts +++ b/libs/coin-framework/src/transaction/common.ts @@ -3,6 +3,7 @@ export type CommonDeviceTransactionField = | { type: "amount"; label: string; + value?: string; } | { type: "address"; diff --git a/libs/coin-modules/coin-algorand/src/deviceTransactionConfig.ts b/libs/coin-modules/coin-algorand/src/deviceTransactionConfig.ts index c203e5b7f214..8d844e9a3665 100644 --- a/libs/coin-modules/coin-algorand/src/deviceTransactionConfig.ts +++ b/libs/coin-modules/coin-algorand/src/deviceTransactionConfig.ts @@ -59,8 +59,8 @@ const getSendFields = ( if (amount) { fields.push({ - type: "text", label: account.type === "TokenAccount" ? "Asset amt" : "Amount", + type: "amount", value: formatCurrencyUnit(getAccountCurrency(account).units[0], amount, { showCode: true, disableRounding: true, diff --git a/libs/coin-modules/coin-cardano/src/deviceTransactionConfig.ts b/libs/coin-modules/coin-cardano/src/deviceTransactionConfig.ts index 84775707925e..8c910f2f15b9 100644 --- a/libs/coin-modules/coin-cardano/src/deviceTransactionConfig.ts +++ b/libs/coin-modules/coin-cardano/src/deviceTransactionConfig.ts @@ -82,7 +82,7 @@ function getDeviceTransactionConfig({ value: decodeTokenName(assetName), }); fields.push({ - type: "text", + type: "amount", label: "Amount", value: formatCurrencyUnit(getAccountCurrency(account).units[0], transactionAmount, { showCode: true, @@ -91,7 +91,7 @@ function getDeviceTransactionConfig({ }); } else if (account.type === "Account") { fields.push({ - type: "text", + type: "amount", label: "Amount", value: formatCurrencyUnit(getAccountCurrency(account).units[0], transaction.amount, { showCode: true, diff --git a/libs/coin-modules/coin-cosmos/src/deviceTransactionConfig.ts b/libs/coin-modules/coin-cosmos/src/deviceTransactionConfig.ts index 0bc470f1c91d..7b11710289c4 100644 --- a/libs/coin-modules/coin-cosmos/src/deviceTransactionConfig.ts +++ b/libs/coin-modules/coin-cosmos/src/deviceTransactionConfig.ts @@ -47,7 +47,7 @@ const getSendFields = ({ if (!amount.isZero()) { fields.push({ - type: "text", + type: "amount", label: "Amount", value: formatCurrencyUnit(getAccountCurrency(account).units[0], amount, { showCode: true, diff --git a/libs/coin-modules/coin-polkadot/src/bridge/deviceTransactionConfig.ts b/libs/coin-modules/coin-polkadot/src/bridge/deviceTransactionConfig.ts index fc43e672da40..e37298a2fb06 100644 --- a/libs/coin-modules/coin-polkadot/src/bridge/deviceTransactionConfig.ts +++ b/libs/coin-modules/coin-polkadot/src/bridge/deviceTransactionConfig.ts @@ -26,7 +26,7 @@ const getSendFields = ({ value: transaction && transaction.useAllAmount ? "Transfer" : "Transfer keep alive", }); fields.push({ - type: "text", + type: "amount", label: "Amount", value: formatCurrencyUnit(currency.units[0], amount, { showCode: true, diff --git a/libs/ledger-live-common/src/e2e/speculos.ts b/libs/ledger-live-common/src/e2e/speculos.ts index 21d29da34210..afc800c908f3 100644 --- a/libs/ledger-live-common/src/e2e/speculos.ts +++ b/libs/ledger-live-common/src/e2e/speculos.ts @@ -360,7 +360,7 @@ export async function waitFor(text: string, maxAttempts: number = 10): Promise event.text); - if (texts[0].includes(text)) { + if (texts[0] && texts[0].includes(text)) { textFound = true; return texts; }