From a2d72e866fc18af6fa844f198e778c97e6a8a1ff Mon Sep 17 00:00:00 2001 From: Piotr Stachyra Date: Fri, 4 Sep 2026 16:46:35 +0200 Subject: [PATCH 1/3] test: wait for spending confirm after advanced continue The affordability re-check before createOrder made this transition slower than the old 500ms sleep, so Back could pop Advanced before dismiss() and desync the stack. Co-authored-by: Cursor --- test/specs/transfer.e2e.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/specs/transfer.e2e.ts b/test/specs/transfer.e2e.ts index 3f44d694..5e579c37 100644 --- a/test/specs/transfer.e2e.ts +++ b/test/specs/transfer.e2e.ts @@ -102,7 +102,7 @@ describe('@transfer - Transfer', () => { await sleep(1000); await tap('SpendingAdvancedNumberField'); // change back to sats await tap('SpendingAdvancedContinue'); - await sleep(500); + await elementById('SpendingConfirmAdvanced').waitForDisplayed(); await tap('NavigationBack'); await sleep(1000); @@ -179,7 +179,7 @@ describe('@transfer - Transfer', () => { await expectText('2 500'); await expectText('—', { visible: false }); await tap('SpendingAdvancedContinue'); - await sleep(500); + await elementById('SpendingConfirmDefault').waitForDisplayed(); await tap('SpendingConfirmDefault'); await sleep(500); await tap('SpendingConfirmAdvanced'); @@ -190,7 +190,7 @@ describe('@transfer - Transfer', () => { await sleep(500); await expectText('—', { visible: false }); await tap('SpendingAdvancedContinue'); - await sleep(500); + await elementById('SpendingConfirmDefault').waitForDisplayed(); await tap('SpendingConfirmDefault'); await sleep(500); await tap('SpendingConfirmAdvanced'); @@ -201,7 +201,7 @@ describe('@transfer - Transfer', () => { await sleep(500); await expectText('—', { visible: false }); await tap('SpendingAdvancedContinue'); - await sleep(500); + await elementById('SpendingConfirmDefault').waitForDisplayed(); await tap('SpendingConfirmDefault'); await sleep(500); await tap('SpendingConfirmAdvanced'); From f16f313d01973db4c5295e2b1941b01b6aa80c71 Mon Sep 17 00:00:00 2001 From: Piotr Stachyra Date: Mon, 7 Sep 2026 11:10:13 +0200 Subject: [PATCH 2/3] test: stabilize @transfer_1 after spending confirm --- test/specs/transfer.e2e.ts | 44 ++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/test/specs/transfer.e2e.ts b/test/specs/transfer.e2e.ts index 5e579c37..92560555 100644 --- a/test/specs/transfer.e2e.ts +++ b/test/specs/transfer.e2e.ts @@ -38,6 +38,19 @@ import { reinstallApp } from '../helpers/setup'; import { ciIt } from '../helpers/suite'; import { openSettings } from '../helpers/navigation'; +/** One Back should leave Confirm. iOS sometimes needs a second Back; Android does not. */ +async function backToSpendingAmount() { + await tap('NavigationBack'); + await sleep(500); + if (driver.isIOS && (await elementById('SpendingConfirmMore').isDisplayed().catch(() => false))) { + console.info('→ Still on spending confirm, tapping Back again...'); + await tap('NavigationBack'); + await sleep(500); + } + await elementById('SpendingAmountAvailable').waitForDisplayed(); + await sleep(1000); +} + describe('@transfer - Transfer', () => { let electrum: { waitForSync: () => any; stop: () => void }; @@ -89,8 +102,10 @@ describe('@transfer - Transfer', () => { // can continue with default client balance (0) await elementById('SpendingAmountContinue').waitForEnabled(); await tap('SpendingAmountContinue'); - await sleep(700); + await elementById('SpendingConfirmAdvanced').waitForDisplayed(); + await sleep(500); await tap('SpendingConfirmAdvanced'); + await sleep(500); await tap('SpendingAdvancedMin'); await expectText('100 000', { strategy: 'contains' }); await tap('SpendingAdvancedDefault'); @@ -102,9 +117,9 @@ describe('@transfer - Transfer', () => { await sleep(1000); await tap('SpendingAdvancedNumberField'); // change back to sats await tap('SpendingAdvancedContinue'); - await elementById('SpendingConfirmAdvanced').waitForDisplayed(); - await tap('NavigationBack'); - await sleep(1000); + await elementById('SpendingConfirmDefault').waitForDisplayed(); + await sleep(500); + await backToSpendingAmount(); // can continue with max client balance await tap('SpendingAmountMax').catch(async () => { @@ -117,25 +132,30 @@ describe('@transfer - Transfer', () => { await sleep(500); await tap('SpendingAmountContinue'); await elementById('SpendingConfirmAdvanced').waitForDisplayed(); - await tap('NavigationBack'); - await sleep(1000); + await backToSpendingAmount(); // can continue with 25% client balance - await elementById('SpendingAmountQuarter').waitForEnabled(); await tap('SpendingAmountQuarter'); await elementById('SpendingAmountContinue').waitForEnabled(); await sleep(500); await tap('SpendingAmountContinue'); await elementById('SpendingConfirmAdvanced').waitForDisplayed(); - await tap('NavigationBack'); + await backToSpendingAmount(); await tap('NavigationBack'); await sleep(1000); await tap('SpendingIntro-button'); await sleep(2000); + await elementById('SpendingAmountAvailable').waitForDisplayed(); + await elementById('N2').waitForEnabled(); + await sleep(500); // can change client balance await enterAmount(200000); + await sleep(500); + await expectText('200 000', { strategy: 'contains' }); await tap('SpendingAmountContinue'); + await elementById('SpendingConfirmMore').waitForDisplayed(); + await sleep(500); await expectText('200 000', { strategy: 'contains' }); await tap('SpendingConfirmMore'); await expectText('200 000'); @@ -166,10 +186,12 @@ describe('@transfer - Transfer', () => { await elementById('SpendingAmountContinue').waitForEnabled(); await sleep(2000); await enterAmount(100000); + await sleep(500); await tap('SpendingAmountContinue'); await expectText('100 000', { strategy: 'contains' }); await sleep(500); await tap('SpendingConfirmAdvanced'); + await elementById('SpendingAdvancedMin').waitForDisplayed(); await sleep(500); // Receiving Capacity @@ -183,7 +205,7 @@ describe('@transfer - Transfer', () => { await tap('SpendingConfirmDefault'); await sleep(500); await tap('SpendingConfirmAdvanced'); - await sleep(500); + await elementById('SpendingAdvancedDefault').waitForDisplayed(); // can continue with default amount await tap('SpendingAdvancedDefault'); @@ -194,7 +216,7 @@ describe('@transfer - Transfer', () => { await tap('SpendingConfirmDefault'); await sleep(500); await tap('SpendingConfirmAdvanced'); - await sleep(500); + await elementById('SpendingAdvancedMax').waitForDisplayed(); // can continue with max amount await tap('SpendingAdvancedMax'); @@ -205,7 +227,7 @@ describe('@transfer - Transfer', () => { await tap('SpendingConfirmDefault'); await sleep(500); await tap('SpendingConfirmAdvanced'); - await sleep(2000); + await elementById('SpendingAdvancedNumberField').waitForDisplayed(); // can set custom amount await enterAmount(150000); From e393c8925fb2aeb8bcdd3beabd616e535a5fb6a8 Mon Sep 17 00:00:00 2001 From: Piotr Stachyra Date: Mon, 7 Sep 2026 17:56:40 +0200 Subject: [PATCH 3/3] test: trasnfer_max --- test/helpers/actions.ts | 4 ++-- test/specs/transfer.e2e.ts | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/test/helpers/actions.ts b/test/helpers/actions.ts index f40e6121..dcf551b5 100644 --- a/test/helpers/actions.ts +++ b/test/helpers/actions.ts @@ -234,8 +234,8 @@ export async function expectTextWithin( } return strategy === 'exact' - ? `.//*[self::XCUIElementTypeStaticText or self::XCUIElementTypeTextView or self::XCUIElementTypeTextField][@label='${text}' or @value='${text}']` - : `.//*[self::XCUIElementTypeStaticText or self::XCUIElementTypeTextView or self::XCUIElementTypeTextField][contains(@label,'${text}') or contains(@value,'${text}')]`; + ? `.//*[self::XCUIElementTypeStaticText or self::XCUIElementTypeTextView or self::XCUIElementTypeTextField or self::XCUIElementTypeButton][@label='${text}' or @value='${text}']` + : `.//*[self::XCUIElementTypeStaticText or self::XCUIElementTypeTextView or self::XCUIElementTypeTextField or self::XCUIElementTypeButton][contains(@label,'${text}') or contains(@value,'${text}')]`; })(); if (!visible) { diff --git a/test/specs/transfer.e2e.ts b/test/specs/transfer.e2e.ts index 92560555..0edd2c7b 100644 --- a/test/specs/transfer.e2e.ts +++ b/test/specs/transfer.e2e.ts @@ -22,6 +22,7 @@ import { dismissBackgroundPaymentsTimedSheet, expectNoTextWithin, enterAmount, + expectSavingsBalance, } from '../helpers/actions'; import { checkChannelStatus, @@ -75,6 +76,7 @@ describe('@transfer - Transfer', () => { // - can change amount // Advanced // - can change amount + // Can fund a channel at the settled Max (happy path; fee-direction math is unit-tested) // Can open a channel to external node // - open channel to LND // - send payment @@ -296,6 +298,41 @@ describe('@transfer - Transfer', () => { } ); + ciIt('@transfer_max - Can fund a Blocktank channel at the settled maximum', async () => { + await receiveOnchainFunds({ sats: 100_000 }); + + await tap('ActivitySavings'); + await elementById('TransferToSpending').waitForDisplayed(); + await tap('TransferToSpending'); + if (await elementById('SpendingIntro-button').isDisplayed().catch(() => false)) { + await tap('SpendingIntro-button'); + } + + await elementById('SpendingAmountAvailable').waitForDisplayed(); + await elementById('SpendingAmountContinue').waitForEnabled(); + await elementById('SpendingAmountMax').waitForEnabled(); + await sleep(500); + + await tap('SpendingAmountMax'); + await elementById('SpendingAmountContinue').waitForEnabled(); + await tap('SpendingAmountContinue'); + await elementById('SpendingConfirmMore').waitForDisplayed(); + await sleep(500); + + await dragOnElement('GRAB', 'right', 0.95); + await elementById('LightningSettingUp').waitForDisplayed(); + await tap('TransferSuccess-button'); + + await expectSavingsBalance(0); + + // Short-0 is already the receive row from `receiveOnchainFunds`. Wait until that + // row becomes Short-1 so Short-0 is the transfer, same as @onchain / @transfer_2. + await elementById('ActivityShort-0').waitForDisplayed(); + await elementById('ActivityShort-1').waitForDisplayed(); + await expectTextWithin('ActivityShort-0', 'Transfer'); + await expectTextWithin('ActivityShort-1', 'Received'); + }); + ciIt('@transfer_2 - Can open a channel to external node', async () => { const rpc = getBitcoinRpc(); await receiveOnchainFunds({ sats: 100_000 });