From ab23701edffdc6ab121b30b6d9020ca92593befa Mon Sep 17 00:00:00 2001 From: Eunji Song <32075932+eunjisong@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:36:43 -0400 Subject: [PATCH] QA New: Stake duration selections (#2036) --- .../app/components/CalendarInput.tsx | 12 +-- packages/core-mobile/e2e/helpers/actions.ts | 9 +++ .../e2e/locators/Stake/stakeScreen.loc.ts | 4 +- .../core-mobile/e2e/locators/commonEls.loc.ts | 5 +- .../core-mobile/e2e/pages/Stake/stake.page.ts | 56 ++++++++++++-- .../core-mobile/e2e/pages/commonEls.page.ts | 12 +++ .../e2e/tests/stake/stakingTestnet.e2e.ts | 76 +++++++++++-------- 7 files changed, 129 insertions(+), 45 deletions(-) diff --git a/packages/core-mobile/app/components/CalendarInput.tsx b/packages/core-mobile/app/components/CalendarInput.tsx index c2f275930a..fb21b7256a 100644 --- a/packages/core-mobile/app/components/CalendarInput.tsx +++ b/packages/core-mobile/app/components/CalendarInput.tsx @@ -17,7 +17,7 @@ interface CalendarInputProps { maximumDate?: Date } -const EmptyComponent = () => null +const EmptyComponent: React.FC = () => null export const CalendarInput: React.FC = ({ date, @@ -32,7 +32,7 @@ export const CalendarInput: React.FC = ({ const positionRef = useRef(null) const [position, setPosition] = useState(0) - const handleDateConfirm = (dateInput: Date) => { + const handleDateConfirm = (dateInput: Date): void => { onDateSelected(dateInput) if (Platform.OS === 'android') { @@ -41,15 +41,16 @@ export const CalendarInput: React.FC = ({ setIsDatePickerVisible(false) } } - const showDatePicker = () => { + const showDatePicker = (): void => { setIsDatePickerVisible(true) } - const handleCancel = () => { + const handleCancel = (): void => { setIsDatePickerVisible(false) } - const handlOnLayout = () => { + const handlOnLayout = (): void => { + // eslint-disable-next-line max-params positionRef.current?.measure((x, y, width, height, pageX, pageY) => { setPosition(pageY + height) }) @@ -74,6 +75,7 @@ export const CalendarInput: React.FC = ({ { await element(item).tap() } +const tapAtXAndY = async ( + item: Detox.NativeMatcher, + xOffset = 0, + yOffset = 0 +) => { + await element(item).tap({ x: xOffset, y: yOffset }) +} + const multiTap = async ( item: Detox.NativeMatcher, count: number, @@ -351,6 +359,7 @@ const shuffleArray = (array: T[]): T[] => export default { balanceToNumber, tap, + tapAtXAndY, multiTap, longPress, waitForElement, diff --git a/packages/core-mobile/e2e/locators/Stake/stakeScreen.loc.ts b/packages/core-mobile/e2e/locators/Stake/stakeScreen.loc.ts index edbb56a9ae..cc1e2bbb8e 100644 --- a/packages/core-mobile/e2e/locators/Stake/stakeScreen.loc.ts +++ b/packages/core-mobile/e2e/locators/Stake/stakeScreen.loc.ts @@ -61,5 +61,7 @@ export default { timeRemainingId: 'time_remaining', stakedAmountId: 'staked_amount', endDateId: 'end_date', - earnedRewardsId: 'earned_rewards' + earnedRewardsId: 'earned_rewards', + stakingSuccessful: 'Staking successful!', + customRadio: 'Custom' } diff --git a/packages/core-mobile/e2e/locators/commonEls.loc.ts b/packages/core-mobile/e2e/locators/commonEls.loc.ts index 6d2d0f8d66..e6a792a0ee 100644 --- a/packages/core-mobile/e2e/locators/commonEls.loc.ts +++ b/packages/core-mobile/e2e/locators/commonEls.loc.ts @@ -12,5 +12,8 @@ export default { bitcoinSVG: 'bitcoin_svg', avaSVG: 'ava_logo', reloadSVG: 'reload_svg', - carrotSVG: 'carrot_svg' + carrotSVG: 'carrot_svg', + calendarSVG: 'calendarSVG', + datePicker: 'dateTimePicker', + okBtn: 'OK' } diff --git a/packages/core-mobile/e2e/pages/Stake/stake.page.ts b/packages/core-mobile/e2e/pages/Stake/stake.page.ts index c44232d1f5..e3fea2ccee 100644 --- a/packages/core-mobile/e2e/pages/Stake/stake.page.ts +++ b/packages/core-mobile/e2e/pages/Stake/stake.page.ts @@ -2,6 +2,8 @@ import stakeScreenLoc from '../../locators/Stake/stakeScreen.loc' import Assert from '../../helpers/assertions' import Actions from '../../helpers/actions' import { Platform } from '../../helpers/constants' +import commonElsPage from '../commonEls.page' +import confirmStakingPage from './confirmStaking.page' type StakeCard = { title: string @@ -259,6 +261,14 @@ class StakePage { return by.id(stakeScreenLoc.earnedRewardsId) } + get stakingSuccessful() { + return by.text(stakeScreenLoc.stakingSuccessful) + } + + get customRadio() { + return by.text(stakeScreenLoc.customRadio) + } + async tapActiveTab() { await Actions.tap(this.activeTab) } @@ -294,12 +304,12 @@ class StakePage { async tapStakeButton() { try { - await Actions.waitForElement(this.stakeSecondaryButton, 5000) - await Actions.tapElementAtIndex(this.stakeSecondaryButton, 0) - } catch { - console.log('there is no claim button, tap primary button') - await Actions.waitForElement(this.stakePrimaryButton, 5000) + await Actions.waitForElement(this.stakePrimaryButton) await Actions.tapElementAtIndex(this.stakePrimaryButton, 0) + console.log('there is no claim button, tap primary button') + } catch { + await Actions.waitForElement(this.stakeSecondaryButton) + await Actions.tapElementAtIndex(this.stakeSecondaryButton, 0) } } @@ -473,6 +483,42 @@ class StakePage { time: time ?? '' } } + + async stake(amount: string, duration: string, custom = false) { + await this.tapStakeButton() + await this.tapNextButton() + await this.inputStakingAmount(amount) + await this.tapNextButton() + if (custom) { + await Actions.tap(this.customRadio) + await Actions.tap(commonElsPage.calendarSVG) + const datePicker = element(commonElsPage.datePicker) + await datePicker.setDatePickerDate(duration, 'MMMM dd, yyyy') + if (Actions.platform() === Platform.Android) { + await Actions.tap(commonElsPage.okBtn) + } else { + await Actions.tapAtXAndY(commonElsPage.datePicker, 0, -20) + } + } else { + await Actions.tap(by.text(duration)) + } + await this.tapNextButton() + await Actions.waitForElementNoSync( + confirmStakingPage.confirmStakingTitle, + 30000, + 0 + ) + await this.tapStakeNow() + } + + async verifyStakeSuccessToast() { + await Actions.waitForElement(this.stakingSuccessful, 60000, 0) + try { + await this.tapNotNowButton() + } catch (e) { + console.log('No stake notification prompt is displayed') + } + } } export default new StakePage() diff --git a/packages/core-mobile/e2e/pages/commonEls.page.ts b/packages/core-mobile/e2e/pages/commonEls.page.ts index c49fd8ddb7..8064d80d79 100644 --- a/packages/core-mobile/e2e/pages/commonEls.page.ts +++ b/packages/core-mobile/e2e/pages/commonEls.page.ts @@ -62,6 +62,18 @@ class CommonElsPage { return by.id(commonEls.carrotSVG) } + get calendarSVG() { + return by.id(commonEls.calendarSVG) + } + + get datePicker() { + return by.id(commonEls.datePicker) + } + + get okBtn() { + return by.text(commonEls.okBtn) + } + async tapCarrotSVG(index = 0) { await Actions.tapElementAtIndex(this.carrotSVG, index) } diff --git a/packages/core-mobile/e2e/tests/stake/stakingTestnet.e2e.ts b/packages/core-mobile/e2e/tests/stake/stakingTestnet.e2e.ts index f12727e576..0ee8ac6f1d 100644 --- a/packages/core-mobile/e2e/tests/stake/stakingTestnet.e2e.ts +++ b/packages/core-mobile/e2e/tests/stake/stakingTestnet.e2e.ts @@ -3,15 +3,11 @@ import Actions from '../../helpers/actions' import Assert from '../../helpers/assertions' import AccountManagePage from '../../pages/accountManage.page' import AdvancedPage from '../../pages/burgerMenu/advanced.page' -import ConfirmStakingPage from '../../pages/Stake/confirmStaking.page' import BottomTabsPage from '../../pages/bottomTabs.page' -import DurationPage from '../../pages/Stake/duration.page' import { warmup } from '../../helpers/warmup' -import GetStartedScreenPage from '../../pages/Stake/getStartedScreen.page' import StakePage from '../../pages/Stake/stake.page' import ClaimPage from '../../pages/Stake/claim.page' import { cleanup } from '../../helpers/cleanup' -import accountManagePage from '../../pages/accountManage.page' describe('Stake on Testnet', () => { beforeAll(async () => { @@ -23,43 +19,50 @@ describe('Stake on Testnet', () => { await cleanup() }) - it('should test a staking flow for a new account on testnet', async () => { - await BottomTabsPage.tapPortfolioTab() - await AccountManagePage.createNthAccountAndSwitchToNth(3) + it('should stake one day', async () => { await BottomTabsPage.tapStakeTab() - await StakePage.verifyNoActiveStakesScreenItems() + await StakePage.stake('1', '1 Day') + await StakePage.verifyStakeSuccessToast() }) - it('should test a staking flow on testnet for an existing account', async () => { - await BottomTabsPage.tapPortfolioTab() - await accountManagePage.switchToFirstAccount() + it('should stake one month', async () => { + await BottomTabsPage.tapStakeTab() + await StakePage.stake('1', '1 Month') + await StakePage.verifyStakeSuccessToast() + }) + + it('should stake three months', async () => { + await BottomTabsPage.tapStakeTab() + await StakePage.stake('1', '3 Months') + await StakePage.verifyStakeSuccessToast() + }) + + it('should stake six months', async () => { await BottomTabsPage.tapStakeTab() - await StakePage.tapStakeButton() - await GetStartedScreenPage.verifyGetStartedScreenItems() - await GetStartedScreenPage.tapNextButton() - await StakePage.verifyStakingAmountScreenItems() - await StakePage.inputStakingAmount('1') - await StakePage.tapNextButton() - await DurationPage.verifyDurationScreenItems(true) - await StakePage.tapNextButton() - await Actions.waitForElement( - ConfirmStakingPage.confirmStakingTitle, - 30000, - 0 - ) - await ConfirmStakingPage.verifyConfirmStakingScreenItems() + await StakePage.stake('1', '6 Months') + await StakePage.verifyStakeSuccessToast() }) - it('should complete the stake on testnet', async () => { - await StakePage.tapStakeNow() - await Actions.waitForElement(StakePage.notNowButton, 60000, 0) - await StakePage.tapNotNowButton() - await Actions.waitForElement(StakePage.newStakeTimeRemaining, 15000, 0) - await Assert.isVisible(StakePage.newStakeTimeRemaining) - await StakePage.verifyActiveTabItems() + it('should stake one year', async () => { + await BottomTabsPage.tapStakeTab() + await StakePage.stake('1', '1 Year') + await StakePage.verifyStakeSuccessToast() + }) + + it('should stake custom duration', async () => { + await BottomTabsPage.tapStakeTab() + const maximumDuration = new Date( + new Date().setFullYear(new Date().getFullYear() + 2) + ).toLocaleDateString('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric' + }) + await StakePage.stake('1', maximumDuration, true) + await StakePage.verifyStakeSuccessToast() }) - it('should claim the stake on testnet', async () => { + it('should claim the testnet stake', async () => { await BottomTabsPage.tapPortfolioTab() await BottomTabsPage.tapStakeTab() if (await Actions.isVisible(StakePage.stakeClaimButton, 0)) { @@ -75,4 +78,11 @@ describe('Stake on Testnet', () => { } } }) + + it('should test a staking flow for a new account on testnet', async () => { + await BottomTabsPage.tapPortfolioTab() + await AccountManagePage.createNthAccountAndSwitchToNth(3) + await BottomTabsPage.tapStakeTab() + await StakePage.verifyNoActiveStakesScreenItems() + }) })