diff --git a/test/helpers/actions.ts b/test/helpers/actions.ts index 430e78d..26d362b 100644 --- a/test/helpers/actions.ts +++ b/test/helpers/actions.ts @@ -170,7 +170,15 @@ export async function expectText( export async function expectTextWithin( ancestorId: string, text: string, - { visible = true, timeout = 30_000 }: { visible?: boolean; timeout?: number } = {} + { + visible = true, + timeout = 30_000, + strategy = 'contains', + }: { + visible?: boolean; + timeout?: number; + strategy?: RetrieveStrategy; + } = {} ) { const parent = elementById(ancestorId); await parent.waitForDisplayed(); @@ -178,9 +186,18 @@ export async function expectTextWithin( if (driver.isIOS) { const parentLabel = await parent.getAttribute('label'); const parentValue = await parent.getAttribute('value'); - const matchesParent = - (typeof parentLabel === 'string' && parentLabel.includes(text)) || - (typeof parentValue === 'string' && parentValue.includes(text)); + const matchesParent = (() => { + if (strategy === 'exact') { + return ( + (typeof parentLabel === 'string' && parentLabel === text) || + (typeof parentValue === 'string' && parentValue === text) + ); + } + return ( + (typeof parentLabel === 'string' && parentLabel.includes(text)) || + (typeof parentValue === 'string' && parentValue.includes(text)) + ); + })(); if (matchesParent) { if (!visible) { @@ -190,9 +207,15 @@ export async function expectTextWithin( } } - const needle = driver.isAndroid - ? `.//*[contains(@text,'${text}')]` - : `.//*[self::XCUIElementTypeStaticText or self::XCUIElementTypeTextView or self::XCUIElementTypeTextField][contains(@label,'${text}') or contains(@value,'${text}')]`; + const needle = (() => { + if (driver.isAndroid) { + return strategy === 'exact' ? `.//*[@text='${text}']` : `.//*[contains(@text,'${text}')]`; + } + + 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}')]`; + })(); if (!visible) { await parent.$(needle).waitForDisplayed({ reverse: true, timeout }); @@ -201,6 +224,10 @@ export async function expectTextWithin( } } +export async function expectNoTextWithin(ancestorId: string, text: string) { + await expectTextWithin(ancestorId, text, { visible: false, strategy: 'exact' }); +} + type Index = number | 'first' | 'last'; /** * Get text from a descendant text element under a container. @@ -711,6 +738,15 @@ export async function acknowledgeReceivedPayment() { await sleep(300); } +/** Acknowledges the external success notification by tapping the button. + */ +export async function acknowledgeExternalSuccess() { + await elementById('ExternalSuccess').waitForDisplayed(); + await sleep(500); + await tap('ExternalSuccess-button'); + await sleep(300); +} + /** * Triggers the timed backup sheet by navigating to settings and back. * Since timed sheets are sometimes triggered by user behavior (when user goes back to home screen), diff --git a/test/specs/lnurl.e2e.ts b/test/specs/lnurl.e2e.ts index 1addb05..f1768c9 100644 --- a/test/specs/lnurl.e2e.ts +++ b/test/specs/lnurl.e2e.ts @@ -24,6 +24,7 @@ import { dismissBackgroundPaymentsTimedSheet, enterAddressViaScanPrompt, acknowledgeReceivedPayment, + acknowledgeExternalSuccess, } from '../helpers/actions'; import { reinstallApp } from '../helpers/setup'; import { ciIt } from '../helpers/suite'; @@ -142,8 +143,7 @@ describe('@lnurl - LNURL', () => { // Success toast/flow if (driver.isIOS) await waitForToast('SpendingBalanceReadyToast'); if (driver.isAndroid) await dismissQuickPayIntro(); - await elementById('ExternalSuccess').waitForDisplayed({ timeout: 30_000 }); - await tap('ExternalSuccess-button'); + await acknowledgeExternalSuccess(); if (driver.isIOS) { await dismissBackgroundPaymentsTimedSheet(); await dismissQuickPayIntro({ triggerTimedSheet: driver.isIOS }); diff --git a/test/specs/numberpad.e2e.ts b/test/specs/numberpad.e2e.ts index 7cadef3..bf0eb60 100644 --- a/test/specs/numberpad.e2e.ts +++ b/test/specs/numberpad.e2e.ts @@ -7,6 +7,7 @@ import { sleep, tap, doNavigationClose, + expectTextWithin, } from '../helpers/actions'; import { launchFreshApp, reinstallApp } from '../helpers/setup'; import { ciIt } from '../helpers/suite'; @@ -78,8 +79,11 @@ async function modernDenominationChecks(mode: NumberpadMode) { await tap(`${mode}NumberPadUnit`); // reset to 0 await multiTap('NRemove', 8); - await expectText('0.00'); - + if (mode === 'Send') { + await expectTextWithin('SendNumberField', '0.00'); + } else { + await expectTextWithin('ReceiveNumberPadTextField', '0.00'); + } await tap('N0'); await tap('N0'); await tap('N1'); @@ -110,7 +114,11 @@ async function classicDenominationChecks(mode: NumberpadMode) { // reset to 0 await multiTap('NRemove', 2); - await expectText('0.00000000'); + if (mode === 'Send') { + await expectTextWithin('SendNumberField', '0.00000000'); + } else { + await expectTextWithin('ReceiveNumberPadTextField', '0.00000000'); + } await tap('N4'); await tap('NDecimal'); await tap('N2'); diff --git a/test/specs/transfer.e2e.ts b/test/specs/transfer.e2e.ts index 26ac4cc..24e8c55 100644 --- a/test/specs/transfer.e2e.ts +++ b/test/specs/transfer.e2e.ts @@ -20,6 +20,10 @@ import { dismissQuickPayIntro, doNavigationClose, waitForToast, + getTextUnder, + acknowledgeExternalSuccess, + dismissBackgroundPaymentsTimedSheet, + expectNoTextWithin, } from '../helpers/actions'; import { checkChannelStatus, @@ -83,40 +87,36 @@ describe('@transfer - Transfer', () => { await elementByText('EUR (€)').click(); await doNavigationClose(); - await launchFreshApp(); + if (driver.isAndroid) await launchFreshApp(); await tap('Suggestion-lightning'); await tap('TransferIntro-button'); await tap('FundTransfer'); await tap('SpendingIntro-button'); await sleep(3000); // let the animation finish - //--- skip due to: https://github.com/synonymdev/bitkit-android/issues/425 ---// - //// can continue with default client balance (0) - //await tap('SpendingAmountContinue'); - //await sleep(100); - //await tap('SpendingConfirmAdvanced'); - //await tap('SpendingAdvancedMin'); - //await expectTextVisible('100 000'); - //await tap('SpendingAdvancedDefault'); - //await tap('SpendingAdvancedNumberField'); // change to fiat - //const label = await getTextUnder('SpendingAdvancedNumberField'); - //const eurBalance = Number.parseInt(label, 10); - //await expect(eurBalance).toBeGreaterThan(440); - //await expect(eurBalance).toBeLessThan(460); - //await tap('SpendingAdvancedNumberField'); // change back to sats - //await tap('SpendingAdvancedContinue'); - //await tap('NavigationBack'); - //--- skip due to: https://github.com/synonymdev/bitkit-android/issues/425 ---// - - //--- skip due to: https://github.com/synonymdev/bitkit-android/issues/424 ---// + // can continue with default client balance (0) + await tap('SpendingAmountContinue'); + await sleep(100); + await tap('SpendingConfirmAdvanced'); + await tap('SpendingAdvancedMin'); + await expectText('100 000', { strategy: 'contains' }); + await tap('SpendingAdvancedDefault'); + await tap('SpendingAdvancedNumberField'); // change to fiat + const label = await getTextUnder('SpendingAdvancedNumberField'); + const eurBalance = Number.parseInt(label, 10); + await expect(eurBalance).toBeGreaterThan(440); + await expect(eurBalance).toBeLessThan(460); + await tap('SpendingAdvancedNumberField'); // change back to sats + await tap('SpendingAdvancedContinue'); + await tap('NavigationBack'); + // can continue with max client balance - //await tap('SpendingAmountMax'); - //await elementById('SpendingAmountContinue').waitForEnabled(); - //await sleep(500); - //await tap('SpendingAmountContinue'); - //await elementById('SpendingConfirmAdvanced').waitForDisplayed(); - //await tap('NavigationBack'); - //--- skip due to: https://github.com/synonymdev/bitkit-android/issues/424 ---// + await tap('SpendingAmountMax'); + await elementById('SpendingAmountContinue').waitForEnabled(); + await sleep(500); + await tap('SpendingAmountContinue'); + await elementById('SpendingConfirmAdvanced').waitForDisplayed(); + await tap('NavigationBack'); // can continue with 25% client balance await elementById('SpendingAmountQuarter').waitForEnabled(); @@ -133,7 +133,7 @@ describe('@transfer - Transfer', () => { await tap('N2'); await multiTap('N0', 5); await tap('SpendingAmountContinue'); - await expectText('200 000'); + await expectText('200 000', { strategy: 'contains' }); await tap('SpendingConfirmMore'); await expectText('200 000'); await tap('LiquidityContinue'); @@ -145,6 +145,7 @@ describe('@transfer - Transfer', () => { // verify transfer activity on savings await tap('ActivitySavings'); await elementById('Activity-1').waitForDisplayed(); + await elementById('Activity-2').waitForDisplayed(); await expectTextWithin('Activity-1', 'Transfer', { timeout: 60_000 }); await expectTextWithin('Activity-1', '-'); await tap('NavigationBack'); @@ -158,7 +159,7 @@ describe('@transfer - Transfer', () => { await tap('N1'); await multiTap('N0', 5); await tap('SpendingAmountContinue'); - await expectText('100 000'); + await expectText('100 000', { strategy: 'contains' }); await sleep(500); await tap('SpendingConfirmAdvanced'); await sleep(500); @@ -213,6 +214,8 @@ describe('@transfer - Transfer', () => { // verify both transfers activities on savings await tap('ActivitySavings'); await elementById('Activity-1').waitForDisplayed(); + await elementById('Activity-2').waitForDisplayed(); + await elementById('Activity-3').waitForDisplayed(); await expectTextWithin('Activity-1', 'Transfer'); await expectTextWithin('Activity-1', '-'); await elementById('Activity-2').waitForDisplayed(); @@ -228,7 +231,7 @@ describe('@transfer - Transfer', () => { await tap('AdvancedSettings'); await tap('Channels'); const channels = await elementsById('Channel'); - channels[1].click(); + channels[driver.isAndroid ? 1 : 0].click(); await expectTextWithin('TotalSize', '₿ 250 000'); await expectText('Processing payment'); await doNavigationClose(); @@ -298,23 +301,28 @@ describe('@transfer - Transfer', () => { await sleep(500); // change fee - await tap('SetCustomFee'); - await sleep(500); - await tap('NRemove'); - await sleep(1000); // wait for input to register - await tap('FeeCustomContinue'); - await tap('N5'); - await sleep(1000); // wait for input to register - await tap('FeeCustomContinue'); - - // Swipe to confirm (set x offset to avoid navigating back) + // this should be removed from Andorid: + // https://github.com/synonymdev/bitkit-android/issues/548 + if (driver.isAndroid) { + await tap('SetCustomFee'); + await sleep(500); + await tap('NRemove'); + await sleep(1000); // wait for input to register + await tap('FeeCustomContinue'); + await tap('N5'); + await sleep(1000); // wait for input to register + await tap('FeeCustomContinue'); + } + + // Swipe to confirm await dragOnElement('GRAB', 'right', 0.95); console.info('channel opening...'); await sleep(1000); - await elementById('ExternalSuccess').waitForDisplayed(); - await tap('ExternalSuccess-button'); - await tap('NavigationBack'); - await doNavigationClose(); + await acknowledgeExternalSuccess(); + if (driver.isAndroid) { + await tap('NavigationBack'); + await doNavigationClose(); + } // check transfer card // await elementById('Suggestion-lightning_setting_up').waitForDisplayed(); @@ -334,7 +342,14 @@ describe('@transfer - Transfer', () => { await mineBlocks(rpc, 6); await electrum?.waitForSync(); await waitForToast('SpendingBalanceReadyToast'); - await dismissQuickPayIntro(); + await sleep(1000); + if (driver.isIOS) { + await dismissBackgroundPaymentsTimedSheet({ triggerTimedSheet: driver.isIOS }); + await dismissQuickPayIntro({ triggerTimedSheet: driver.isIOS }); + } else { + await dismissQuickPayIntro(); + } + await expectNoTextWithin('ActivitySpending', '0'); await waitForActiveChannel(lnd, ldkNodeId); // check transfer card @@ -364,7 +379,7 @@ describe('@transfer - Transfer', () => { await dragOnElement('GRAB', 'right', 0.95); await elementById('TransferSuccess').waitForDisplayed(); await tap('TransferSuccess-button'); - await tap('NavigationBack'); + if (driver.isAndroid) await tap('NavigationBack'); // check channel is closed await tap('HeaderMenu');