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

[LLM][Detox][Speculos] First Speculos delegate tests #8942

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
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
6 changes: 3 additions & 3 deletions apps/ledger-live-mobile/e2e/models/send.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ export async function verifyAppValidationSendInfo(
const addressSender = transaction.accountToDebit.address;

if (currenciesForValidationAmount.includes(currency)) {
await app.send.expectValidationAmount(amount);
await app.deviceValidation.expectAmount(amount);
}

if (currenciesForValidationRecipient.includes(currency)) {
await app.send.expectValidationAddress(addressRecipient);
await app.deviceValidation.expectAddress(addressRecipient);
}

if (currenciesForValidationSender.includes(currency)) {
await app.send.expectValidationAddress(addressSender);
await app.deviceValidation.expectAddress(addressSender);
}
}
60 changes: 60 additions & 0 deletions apps/ledger-live-mobile/e2e/models/stake.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Currency } from "@ledgerhq/live-common/e2e/enum/Currency";
import { Application } from "../page";
import { Delegate } from "@ledgerhq/live-common/e2e/models/Delegate";

export async function verifyAppValidationStakeInfo(
app: Application,
delegation: Delegate,
amount: string,
) {
const currenciesForValidationAmount = [Currency.ATOM, Currency.NEAR];
const currenciesForValidationProvider = [Currency.ATOM];

const currency = delegation.account.currency;
const provider = delegation.provider;

if (currenciesForValidationAmount.includes(currency)) {
await app.deviceValidation.expectAmount(amount);
}
if (currenciesForValidationProvider.includes(currency)) {
await app.deviceValidation.expectProvider(provider);
}
}

export async function verifyStakeOperationDetailsInfo(
app: Application,
delegation: Delegate,
amount: string,
) {
const currenciesForProvider = [Currency.ATOM];
const currenciesForRecipientAsProvider = [Currency.NEAR];
const currenciesForSender = [Currency.NEAR];
const currenciesForAmount = [Currency.ATOM, Currency.NEAR];
const currenciesForDelegateType = [Currency.ATOM, Currency.SOL];
const currenciesForStakeType = [Currency.NEAR];

const currency = delegation.account.currency;
const provider = delegation.provider;

await app.operationDetails.waitForOperationDetails();
await app.operationDetails.checkAccount(delegation.account.accountName);

if (currenciesForAmount.includes(currency)) {
await app.operationDetails.checkDelegatedAmount(amount);
}
if (currenciesForProvider.includes(currency)) {
await app.operationDetails.checkProvider(provider);
}
if (currenciesForRecipientAsProvider.includes(currency)) {
await app.operationDetails.checkRecipient(provider);
}
if (currenciesForSender.includes(currency)) {
await app.operationDetails.checkSender(delegation.account.address);
}
if (currenciesForDelegateType.includes(currency)) {
await app.operationDetails.checkTransactionType("DELEGATE");
}
if (currenciesForStakeType.includes(currency)) {
await app.operationDetails.checkTransactionType("STAKE");
}
}
13 changes: 10 additions & 3 deletions apps/ledger-live-mobile/e2e/page/accounts/account.page.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getElementById, getTextOfElement, scrollToId, tapByElement } from "../../helpers";
import { getElementById, getTextOfElement, scrollToId, tapByElement, tapById } from "../../helpers";
import { expect } from "detox";
import jestExpect from "expect";

Expand All @@ -14,8 +14,9 @@ export default class AccountPage {
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");
receiveButton = () => getElementById("account-quick-action-button-receive");
sendButton = () => getElementById("account-quick-action-button-send");
earnButtonId = "account-quick-action-button-earn";

@Step("Open account settings")
async openAccountSettings() {
Expand Down Expand Up @@ -73,4 +74,10 @@ export default class AccountPage {
async tapSend() {
await tapByElement(this.sendButton());
}

@Step("Tap on earn button")
async tapEarn() {
await scrollToId(this.earnButtonId, this.accountScreenScrollView);
await tapById(this.earnButtonId);
}
}
2 changes: 2 additions & 0 deletions apps/ledger-live-mobile/e2e/page/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import BuyDevicePage from "./discover/buyDevice.page";
import CommonPage from "./common.page";
import CryptoDrawer from "./liveApps/cryptoDrawer";
import CustomLockscreenPage from "./stax/customLockscreen.page";
import DeviceValidationPage from "./trade/deviceValidation.page";
import DiscoverPage from "./discover/discover.page";
import DummyWalletApp from "./liveApps/dummyWalletApp.webView";
import WalletAPIReceivePage from "./liveApps/walletAPIReceive";
Expand Down Expand Up @@ -60,6 +61,7 @@ export class Application {
public common = new CommonPage();
public cryptoDrawer = new CryptoDrawer();
public customLockscreen = new CustomLockscreenPage();
public deviceValidation = new DeviceValidationPage();
public discover = new DiscoverPage();
public dummyWalletApp = new DummyWalletApp();
public walletAPIReceive = new WalletAPIReceivePage();
Expand Down
12 changes: 11 additions & 1 deletion apps/ledger-live-mobile/e2e/page/speculos.page.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { expectValidAddressDevice, signSendTransaction } from "@ledgerhq/live-common/e2e/speculos";
import {
expectValidAddressDevice,
signSendTransaction,
signDelegationTransaction,
} from "@ledgerhq/live-common/e2e/speculos";
import { Account } from "@ledgerhq/live-common/e2e/enum/Account";
import { Transaction } from "@ledgerhq/live-common/e2e/models/Transaction";
import { Delegate } from "@ledgerhq/live-common/e2e/models/Delegate";

export default class SpeculosPage {
@Step("Verify receive address correctness on device")
Expand All @@ -12,4 +17,9 @@ export default class SpeculosPage {
async signSendTransaction(tx: Transaction) {
await signSendTransaction(tx);
}

@Step("Sign Delegation Transaction")
async signDelegationTransaction(delegation: Delegate) {
await signDelegationTransaction(delegation);
}
}
26 changes: 26 additions & 0 deletions apps/ledger-live-mobile/e2e/page/trade/deviceValidation.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { getElementById, waitForElementById } from "../../helpers";
import { expect } from "detox";

export default class DeviceValidationPage {
validationAmountId = "device-validation-amount";
validationAddressId = (fieldLabel = "To") => `device-validation-address${fieldLabel}`;
validationProviderId = "device-validation-provider";

@Step("Expect amount in device validation screen")
async expectAmount(amount: string) {
await waitForElementById(this.validationAmountId);
await expect(getElementById(this.validationAmountId)).toHaveText(amount);
}

@Step("Expect address in device validation screen")
async expectAddress(recipient: string, fieldLabel?: string) {
await waitForElementById(this.validationAddressId(fieldLabel));
await expect(getElementById(this.validationAddressId(fieldLabel))).toHaveText(recipient);
}

@Step("Expect provider in device validation screen")
async expectProvider(provider: string) {
await waitForElementById(this.validationProviderId);
await expect(getElementById(this.validationProviderId)).toHaveText(provider);
}
}
32 changes: 32 additions & 0 deletions apps/ledger-live-mobile/e2e/page/trade/operationDetails.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ export default class OperationDetailsPage {
account = () => getElementById("operationDetails-account");
amount = () => getElementById("operationDetails-amount");
recipientId = "operationDetails-recipient0";
delegatedAmountId = "operationDetails-delegatedAmount";
providerId = "operationDetails-delegatedTo";
senderId = "operationDetails-sender0";

"operationsType" = {
OUT: "Sent",
DELEGATE: "Delegated",
STAKE: "Staked",
};

async isOpened() {
await expect(this.title()).toBeVisible();
Expand All @@ -31,4 +40,27 @@ export default class OperationDetailsPage {
await scrollToId(this.recipientId);
await expect(getElementById(this.recipientId)).toHaveText(recipient);
}

@Step("Check delegated provider")
async checkProvider(provider: string) {
await scrollToId(this.providerId);
await expect(getElementById(this.providerId)).toHaveText(provider);
}

@Step("Check delegated amount")
async checkDelegatedAmount(amount: string) {
await scrollToId(this.delegatedAmountId);
await expect(getElementById(this.delegatedAmountId)).toHaveText(amount);
}

@Step("Check sender")
async checkSender(sender: string) {
await scrollToId(this.senderId);
await expect(getElementById(this.senderId)).toHaveText(sender);
}

@Step("Check transaction type")
async checkTransactionType(type: keyof typeof this.operationsType) {
await expect(getElementById(this.titleId)).toHaveText(this.operationsType[type]);
}
}
14 changes: 0 additions & 14 deletions apps/ledger-live-mobile/e2e/page/trade/send.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ 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";
Expand Down Expand Up @@ -88,16 +86,4 @@ export default class SendPage {
if (await IsIdVisible(this.highFreeConfirmButtonID))
await tapById(this.highFreeConfirmButtonID);
}

@Step("Expect amount in device validation screen")
async expectValidationAmount(amount: string) {
await waitForElementById(this.validationAmountId);
await expect(getElementById(this.validationAmountId)).toHaveText(amount);
}

@Step("Expect address in device validation screen")
async expectValidationAddress(recipient: string) {
await waitForElementById(this.validationAddressId);
await expect(getElementById(this.validationAddressId)).toHaveText(recipient);
}
}
87 changes: 59 additions & 28 deletions apps/ledger-live-mobile/e2e/page/trade/stake.page.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import { getTextOfElement, tapById, waitForElementById } from "../../helpers";
import {
getTextOfElement,
IsIdVisible,
tapById,
typeTextById,
waitForElementById,
} from "../../helpers";

export default class StakePage {
cosmosDelegationSummaryValidatorId = "cosmos-delegation-summary-validator";
cosmosDelegationSummaryValidator = () => getTextOfElement("cosmos-delegation-summary-validator");
cosmosDelegationSummaryAmountId = "cosmos-delegation-summary-amount";
cosmosDelegationAmountValue = () => getTextOfElement(this.cosmosDelegationSummaryAmountId);
cosmosAssestsRemainingId = "cosmos-assets-remaining";
cosmosDelegatedRatioId = (delegatedPercent: number) => `delegate-ratio-${delegatedPercent}%`;
cosmosAllAssestsUsedText = "cosmos-all-assets-used-text";
cosmosSummaryContinueButtonId = "cosmos-summary-continue-button";
cosmosDelegationStartId = "cosmos-delegation-start-button";
cosmosDelegationAmountContinueId = "cosmos-delegation-amount-continue";
delegationSummaryValidatorId = (currencyId: string) =>
`${currencyId}-delegation-summary-validator`;
delegationSummaryValidator = (currencyId: string) =>
getTextOfElement(`${currencyId}-delegation-summary-validator`);
delegationSummaryAmountId = (currencyId: string) => `${currencyId}-delegation-summary-amount`;
delegationAmountValue = (currencyId: string) =>
getTextOfElement(this.delegationSummaryAmountId(currencyId));
assestsRemainingId = (currencyId: string) => `${currencyId}-assets-remaining`;
delegatedRatioId = (currencyId: string, delegatedPercent: number) =>
`${currencyId}-delegate-ratio-${delegatedPercent}%`;
delegationAmountInput = (currencyId: string) => `${currencyId}-delegation-amount-input`;
allAssestsUsedText = (currencyId: string) => `${currencyId}-all-assets-used-text`;
summaryContinueButtonId = (currencyId: string) => `${currencyId}-summary-continue-button`;
delegationStartId = (currencyId: string) => `${currencyId}-delegation-start-button`;
delegationAmountContinueId = (currencyId: string) => `${currencyId}-delegation-amount-continue`;
currencyRow = (currencyId: string) => `currency-row-${currencyId}`;
zeroAssetText = "0\u00a0ATOM";

Expand All @@ -20,44 +31,64 @@ export default class StakePage {
await tapById(id);
}

async delegationStart() {
await tapById(this.cosmosDelegationStartId);
await waitForElementById(this.cosmosDelegationSummaryValidatorId);
@Step("Click on start delegation button")
async delegationStart(currencyId: string) {
await tapById(this.delegationStartId(currencyId));
await waitForElementById(this.delegationSummaryValidatorId(currencyId));
}

async setAmount(delegatedPercent: 25 | 50 | 75 | 100) {
await waitForElementById(this.cosmosDelegationSummaryAmountId);
await tapById(this.cosmosDelegationSummaryAmountId);
await tapById(this.cosmosDelegatedRatioId(delegatedPercent));
@Step("Dismiss delegation start page if displayed")
async dismissDelegationStart(currencyId: string) {
if (await IsIdVisible(this.delegationStartId(currencyId))) {
await this.delegationStart(currencyId);
}
}

async expectValidator(validator: string) {
expect(await this.cosmosDelegationSummaryValidator()).toEqual(validator);
@Step("Set delegated amount")
async setAmount(currencyId: string, amount: string) {
await waitForElementById(this.delegationSummaryAmountId(currencyId));
await tapById(this.delegationSummaryAmountId(currencyId));
await typeTextById(this.delegationAmountInput(currencyId), amount);
}

async setAmountPercent(currencyId: string, delegatedPercent: 25 | 50 | 75 | 100) {
await waitForElementById(this.delegationSummaryAmountId(currencyId));
await tapById(this.delegationSummaryAmountId(currencyId));
await tapById(this.delegatedRatioId(currencyId, delegatedPercent));
}

@Step("Expect provider in summary")
async expectProvider(currencyId: string, provider: string) {
expect(await this.delegationSummaryValidator(currencyId)).toEqual(provider);
}

async expectRemainingAmount(
currencyId: string,
delegatedPercent: 25 | 50 | 75 | 100,
remainingAmountFormated: string,
) {
const max = delegatedPercent == 100;
const id = max ? this.cosmosAllAssestsUsedText : this.cosmosAssestsRemainingId;
const id = max ? this.allAssestsUsedText(currencyId) : this.assestsRemainingId(currencyId);
await waitForElementById(id);
const assestsRemaining = max ? this.zeroAssetText : (await getTextOfElement(id)).split(": ")[1];

expect(assestsRemaining).toEqual(remainingAmountFormated);
}

async validateAmount() {
await tapById(this.cosmosDelegationAmountContinueId);
await waitForElementById(this.cosmosDelegationSummaryAmountId);
@Step("Validate the amount entered")
async validateAmount(currencyId: string) {
await tapById(this.delegationAmountContinueId(currencyId));
await waitForElementById(this.delegationSummaryAmountId(currencyId));
}

async expectDelegatedAmount(delegatedAmountFormated: string) {
const assestsDelagated = await this.cosmosDelegationAmountValue();
@Step("Expect delegated amount in summary")
async expectDelegatedAmount(currencyId: string, delegatedAmountFormated: string) {
const assestsDelagated = await this.delegationAmountValue(currencyId);
expect(assestsDelagated).toEqual(delegatedAmountFormated);
}

async summaryContinue() {
await tapById(this.cosmosSummaryContinueButtonId);
@Step("Click on continue button in summary")
async summaryContinue(currencyId: string) {
await tapById(this.summaryContinueButtonId(currencyId));
}
}
17 changes: 11 additions & 6 deletions apps/ledger-live-mobile/e2e/specs/delegate/cosmos.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const app = new Application();
let deviceAction: DeviceAction;

const testedCurrency = "cosmos";
const defaultValidator = "Ledger";
const defaultProvider = "Ledger";
const testAccount = initTestAccounts([testedCurrency])[0];
const knownDevice = knownDevices.nanoX;

Expand Down Expand Up @@ -53,14 +53,19 @@ describe("Cosmos delegate flow", () => {
await app.stake.selectCurrency(testedCurrency);
await app.common.selectAccount(testAccount.id);

await app.stake.setAmount(delegatedPercent);
await app.stake.expectRemainingAmount(delegatedPercent, formattedAmount(unit, remainingAmount));
await app.stake.validateAmount();
await app.stake.setAmountPercent(testedCurrency, delegatedPercent);
await app.stake.expectRemainingAmount(
testedCurrency,
delegatedPercent,
formattedAmount(unit, remainingAmount),
);
await app.stake.validateAmount(testedCurrency);
await app.stake.expectDelegatedAmount(
testedCurrency,
formattedAmount(unit, delegatedAmount, { showAllDigits: true, showCode: true }),
);
await app.stake.expectValidator(defaultValidator);
await app.stake.summaryContinue();
await app.stake.expectProvider(testedCurrency, defaultProvider);
await app.stake.summaryContinue(testedCurrency);
await deviceAction.selectMockDevice();
await deviceAction.openApp();
await app.common.successClose();
Expand Down
Loading
Loading