From e29a4237090a30cb1a631338bde8d727febae131 Mon Sep 17 00:00:00 2001 From: SamuelSalas Date: Wed, 30 Nov 2022 11:07:29 -0600 Subject: [PATCH] add e2e start exploring flow (#5293) * add e2e start exploring flow * Remove the data from the test and replace it with the data from the accounts helpers class * Click remove for Tap in onboardingwizard methods. Updating Gherkin language in feature file --- wdio/features/SkipStartExploring.feature | 18 +++ wdio/features/StartExploring.feature | 41 +++++ wdio/features/helpers/Gestures.js | 13 +- wdio/features/helpers/Selectors.js | 6 +- .../Modals/OnboardingWizardModal.js | 141 +++++++++++++++++- .../Modals/WalletAccountModal.js | 38 +++++ .../features/step-definitions/network-flow.js | 2 +- .../step-definitions/start-exploring.js | 115 ++++++++++++++ .../Components/OnboardingWizard.testIds.js | 30 +++- .../testIDs/Screens/WalletAccount.testIds.js | 5 + 10 files changed, 393 insertions(+), 16 deletions(-) create mode 100644 wdio/features/SkipStartExploring.feature create mode 100644 wdio/features/StartExploring.feature create mode 100644 wdio/features/screen-objects/Modals/WalletAccountModal.js create mode 100644 wdio/features/step-definitions/start-exploring.js create mode 100644 wdio/features/testIDs/Screens/WalletAccount.testIds.js diff --git a/wdio/features/SkipStartExploring.feature b/wdio/features/SkipStartExploring.feature new file mode 100644 index 00000000000..aa023c72d79 --- /dev/null +++ b/wdio/features/SkipStartExploring.feature @@ -0,0 +1,18 @@ +@androidApp +Feature: Skip Start Exploring + + Scenario: A user should be able to tap the Skip button and the onboarding tutorial modal should disappear + Given I have imported my wallet + And the onboarding wizard is visible on wallet view + When I tap on "Take a Tour" button + Then the tutorial modal heading should read "Your Accounts" + And there should be an explanation of the accounts functionality. + And I should see the "Skip Tutorial" button + When I tap on "Got it" button + Then the tutorial modal heading should read "Edit Account Name" + And there should be an explanation about adding a nickname to your account. + And I should see the "Skip Tutorial" button + When I tap on "Skip" button + Then the onboarding wizard is no longer visible + And the "Skip" button is no longer visible + diff --git a/wdio/features/StartExploring.feature b/wdio/features/StartExploring.feature new file mode 100644 index 00000000000..e9dbd84ed93 --- /dev/null +++ b/wdio/features/StartExploring.feature @@ -0,0 +1,41 @@ +@androidApp +Feature: Start Exploring + + Scenario: A user should be able to go through the start exploring tutorial + Given I have imported my wallet + And the onboarding wizard is visible on wallet view + When I tap on "Take a Tour" button + Then the tutorial modal heading should read "Your Accounts" + And there should be an explanation of the accounts functionality. + And I should see the "Skip Tutorial" button + When I tap on "Got it" button + Then the tutorial modal heading should read "Edit Account Name" + And there should be an explanation about adding a nickname to your account. + And I should see the "Skip Tutorial" button + When I tap and hold on the account Name + Then I should be able to edit the account Name + When I enter "Big Bank" for account name + Then the account nickname should read "Big Bank" + When I tap on "Got it" button + Then the tutorial modal heading should read "Main Navigation" + And there should be an explanation of the what exists within the burger menu. + And I should see the "Skip Tutorial" button + When I tap on "Got it" button + Then the tutorial modal heading should read "Explore the Browser" + And there should be an explanation of the what the purpose of the browser. + And I should see the "Skip Tutorial" button + When I tap on "Back" button + Then the tutorial modal heading should read "Main Navigation" + And there should be an explanation of the what exists within the burger menu. + And I should see the "Skip Tutorial" button + When I tap on "Got it" button + Then the tutorial modal heading should read "Explore the Browser" + And there should be an explanation of the what the purpose of the browser. + And I should see the "Skip Tutorial" button + When I tap on "Got it" button + Then the tutorial modal heading should read "Search" + And there should be an explanation of the what the purpose of the search input box. + And I should see the "Skip Tutorial" button + When I tap on "Got it" button + Then the onboarding wizard is no longer visible + And the "Skip" button is no longer visible diff --git a/wdio/features/helpers/Gestures.js b/wdio/features/helpers/Gestures.js index 5f274b22e4f..40c877fe8c4 100644 --- a/wdio/features/helpers/Gestures.js +++ b/wdio/features/helpers/Gestures.js @@ -65,7 +65,7 @@ const Actions = { RELEASE: 'release', }; -class Gestures { +class Gestures { static async waitAndTap(element) { const elem = await element; await elem.waitForDisplayed(); @@ -112,6 +112,15 @@ class Gestures { } } + static async longPress(element, waitTime) { + const elem = await element; + (await elem).touchAction([ + Actions.PRESS, + {action: Actions.WAIT, ms: waitTime}, + Actions.RELEASE + ]) + } + static async typeText(element, text) { const elem = await element; await elem.waitForDisplayed(); @@ -205,7 +214,7 @@ class Gestures { const endPercentage = 0; const anchorPercentage = 50; - const { width, height } = await driver.getWindowSize(); + const {width, height} = await driver.getWindowSize(); const anchor = height * anchorPercentage / 100; const startPoint = width * startPercentage / 100; const endPoint = width * endPercentage / 100; diff --git a/wdio/features/helpers/Selectors.js b/wdio/features/helpers/Selectors.js index d56b0d6cc17..c48a906a2b9 100644 --- a/wdio/features/helpers/Selectors.js +++ b/wdio/features/helpers/Selectors.js @@ -24,10 +24,14 @@ class Selectors { return await element; } - static async getXpathElementByContentDecscription(text) { + static async getXpathElementByContentDescription(text) { const element = await $(`//android.view.ViewGroup[@content-desc='${text}']`); return await element; } + + static async getXpathElementByResourceId(text) { + return await $(`//*[@resource-id='${text}']`); + } } export default Selectors; diff --git a/wdio/features/screen-objects/Modals/OnboardingWizardModal.js b/wdio/features/screen-objects/Modals/OnboardingWizardModal.js index 00a8f9affaa..1966f4af8a8 100644 --- a/wdio/features/screen-objects/Modals/OnboardingWizardModal.js +++ b/wdio/features/screen-objects/Modals/OnboardingWizardModal.js @@ -1,9 +1,22 @@ - import { ONBOARDING_WIZARD_STEP_1_CONTAINER_ID, - ONBOARDING_WIZARD_STEP_1_NO_THANKS_ID } from '../../testIDs/Components/OnboardingWizard.testIds'; - - import Selectors from '../../helpers/Selectors'; - import Gestures from '../../helpers/Gestures'; +import { + ONBOARDING_WIZARD_STEP_1_CONTAINER_ID, + ONBOARDING_WIZARD_STEP_1_NO_THANKS_ID, + ONBOARDING_WIZARD_STEP_1_TAKE_THE_TOUR_ID, + ONBOARDING_WIZARD_YOUR_ACCOUNTS_DESC_1, + ONBOARDING_WIZARD_YOUR_ACCOUNTS_DESC_2, + ONBOARDING_WIZARD_BACK_BUTTON, + ONBOARDING_WIZARD_NEXT_GOT_IT_BUTTON, + ONBOARDING_WIZARD_SKIP_TUTORIAL_BUTTON, + ONBOARDING_WIZARD_EDIT_ACCOUNTS_NAME_DESC_1, + ONBOARDING_WIZARD_EDIT_ACCOUNTS_NAME_DESC_2, + ONBOARDING_WIZARD_MAIN_NAVIGATION_DESC_1, + ONBOARDING_WIZARD_MAIN_NAVIGATION_DESC_2, + ONBOARDING_WIZARD_EXPLORE_BROWSER_DESC, + ONBOARDING_WIZARD_SEARCH_DESC +} from '../../testIDs/Components/OnboardingWizard.testIds'; +import Selectors from '../../helpers/Selectors'; +import Gestures from '../../helpers/Gestures'; class OnboardingWizardModal { @@ -11,17 +24,129 @@ class OnboardingWizardModal { return Selectors.getElementByPlatform(ONBOARDING_WIZARD_STEP_1_CONTAINER_ID); } - get onBoardingWizardBackButton() { + get onBoardingWizardNoThanksButton() { return Selectors.getElementByPlatform(ONBOARDING_WIZARD_STEP_1_NO_THANKS_ID); } - async isVisible(){ + get onBoardingWizardBackButton() { + return Selectors.getXpathElementByText(ONBOARDING_WIZARD_BACK_BUTTON) + } + + get onBoardingWizardTakeTourButton() { + return Selectors.getElementByPlatform(ONBOARDING_WIZARD_STEP_1_TAKE_THE_TOUR_ID); + } + + get onBoardingWizardYourAccountDesc1() { + return Selectors.getXpathElementByText(ONBOARDING_WIZARD_YOUR_ACCOUNTS_DESC_1); + } + + get onBoardingWizardYourAccountDesc2() { + return Selectors.getXpathElementByText(ONBOARDING_WIZARD_YOUR_ACCOUNTS_DESC_2); + } + + get onBoardingWizardSkipTutorialButton() { + return Selectors.getXpathElementByText(ONBOARDING_WIZARD_SKIP_TUTORIAL_BUTTON); + } + + get onBoardingWizardGotItButton() { + return Selectors.getXpathElementByText(ONBOARDING_WIZARD_NEXT_GOT_IT_BUTTON); + } + + get onBoardingWizardEditAccountNameDesc1() { + return Selectors.getXpathElementByText(ONBOARDING_WIZARD_EDIT_ACCOUNTS_NAME_DESC_1); + } + + get onBoardingWizardEditAccountNameDesc2() { + return Selectors.getXpathElementByText(ONBOARDING_WIZARD_EDIT_ACCOUNTS_NAME_DESC_2); + } + + get onBoardingWizardMainNavDesc1() { + return Selectors.getXpathElementByText(ONBOARDING_WIZARD_MAIN_NAVIGATION_DESC_1); + } + + get onBoardingWizardMainNavDesc2() { + return Selectors.getXpathElementByText(ONBOARDING_WIZARD_MAIN_NAVIGATION_DESC_2); + } + + get onBoardingWizardExploreBrowserDesc() { + return Selectors.getXpathElementByText(ONBOARDING_WIZARD_EXPLORE_BROWSER_DESC); + } + + get onBoardingWizardSearchDesc() { + return Selectors.getXpathElementByText(ONBOARDING_WIZARD_SEARCH_DESC); + } + + async isVisible() { await expect(this.onBoardingWizardContainer).toBeDisplayed(); } - async clickBackButton(){ + async tapNoThanksButton() { + await Gestures.tap(this.onBoardingWizardNoThanksButton); + } + + async tapTakeTourButton() { + await Gestures.tap(this.onBoardingWizardTakeTourButton); + } + + async isHeaderDisplayedByXPath(text) { + await expect(await (Selectors.getXpathElementByText(text))).toBeDisplayed(); + } + + async isYourAccountDesc1Displayed() { + await expect(this.onBoardingWizardYourAccountDesc1).toBeDisplayed(); + } + + async isYourAccountDesc2Displayed() { + await expect(this.onBoardingWizardYourAccountDesc2).toBeDisplayed(); + } + + async isSkipTutorialButtonDisplayed() { + await expect(this.onBoardingWizardSkipTutorialButton).toBeDisplayed(); + } + + async isSkipTutorialButtonNotDisplayed() { + await expect(this.onBoardingWizardSkipTutorialButton).not.toBeDisplayed(); + } + + async tapSkipTutorialButton() { + await Gestures.tap(this.onBoardingWizardSkipTutorialButton); + } + + async tapGotItButton() { + await Gestures.tap(this.onBoardingWizardGotItButton); + } + + async isGotItButtonNotDisplayed() { + await expect(this.onBoardingWizardGotItButton).not.toBeDisplayed(); + } + + async tapBackButton() { await Gestures.tap(this.onBoardingWizardBackButton); } + async isEditAccountNameDesc1Displayed() { + await expect(this.onBoardingWizardEditAccountNameDesc1).toBeDisplayed(); + } + + async isEditAccountNameDesc2Displayed() { + await expect(this.onBoardingWizardEditAccountNameDesc2).toBeDisplayed(); + } + + async isMainNavDesc1Displayed() { + await expect(this.onBoardingWizardMainNavDesc1).toBeDisplayed(); + } + + async isMainNavDesc2Displayed() { + await expect(this.onBoardingWizardMainNavDesc2).toBeDisplayed(); + } + + async isExploreBrowserDescDisplayed() { + await expect(this.onBoardingWizardExploreBrowserDesc).toBeDisplayed(); + } + + async isSearchDescDisplayed() { + await expect(this.onBoardingWizardSearchDesc).toBeDisplayed(); + } } + export default new OnboardingWizardModal(); diff --git a/wdio/features/screen-objects/Modals/WalletAccountModal.js b/wdio/features/screen-objects/Modals/WalletAccountModal.js new file mode 100644 index 00000000000..92fadbb6e4b --- /dev/null +++ b/wdio/features/screen-objects/Modals/WalletAccountModal.js @@ -0,0 +1,38 @@ +import { + WALLET_ACCOUNT_NAME_LABEL_TEXT, + WALLET_ACCOUNT_NAME_LABEL_INPUT, + WALLET_ACCOUNT_ICON +} from '../../testIDs/Screens/WalletAccount.testIds' + +import Selectors from '../../helpers/Selectors'; +import Gestures from '../../helpers/Gestures'; + +class WalletAccountModal { + get accountNameLabelText() { + return Selectors.getXpathElementByResourceId(WALLET_ACCOUNT_NAME_LABEL_TEXT); + } + + get accountNameLabelInput() { + return Selectors.getXpathElementByResourceId(WALLET_ACCOUNT_NAME_LABEL_INPUT); + } + + async longPressAccountNameLabel() { + await Gestures.longPress(this.accountNameLabelText, 1000); + } + + async isAccountNameLabelEditable() { + await expect(this.accountNameLabelInput).toBeDisplayed(); + } + + async editAccountNameLabel(text) { + await Gestures.typeText(this.accountNameLabelInput, text); + } + + async isAccountNameLabelEqualTo(expected) { + const textFromElement = await this.accountNameLabelInput; + const accountName = await textFromElement.getText(); + await expect(accountName).toContain(expected); + } +} + +export default new WalletAccountModal(); diff --git a/wdio/features/step-definitions/network-flow.js b/wdio/features/step-definitions/network-flow.js index d2dc311519c..42434e9df1c 100644 --- a/wdio/features/step-definitions/network-flow.js +++ b/wdio/features/step-definitions/network-flow.js @@ -28,7 +28,7 @@ Given(/^I import wallet using seed phrase "([^"]*)?"/, async (phrase) => { Given(/^I tap No thanks on the onboarding welcome tutorial/, async () => { await OnboardingWizardModal.isVisible(); - await OnboardingWizardModal.clickBackButton(); + await OnboardingWizardModal.tapNoThanksButton(); }); Then(/^I tap on the navbar network title button/, async () => { diff --git a/wdio/features/step-definitions/start-exploring.js b/wdio/features/step-definitions/start-exploring.js new file mode 100644 index 00000000000..3a54d85776e --- /dev/null +++ b/wdio/features/step-definitions/start-exploring.js @@ -0,0 +1,115 @@ +import {Given, When, Then} from '@wdio/cucumber-framework'; +import OnboardingWizardModal from '../screen-objects/Modals/OnboardingWizardModal.js'; +import WalletAccountModal from "../screen-objects/Modals/WalletAccountModal.js"; +import WelcomeScreen from "../screen-objects/Onboarding/OnboardingCarousel"; +import OnboardingScreen from "../screen-objects/Onboarding/OnboardingScreen"; +import MetaMetricsScreen from "../screen-objects/Onboarding/MetaMetricsScreen"; +import ImportFromSeedScreen from "../screen-objects/Onboarding/ImportFromSeedScreen"; +import Accounts from "../helpers/Accounts"; + + +Given(/^I have imported my wallet$/, async () => { + const validAccount = Accounts.getValidAccount(); + await WelcomeScreen.isScreenTitleVisible(); + await driver.pause(7000); //TODO: Needs a smarter set timeout + await WelcomeScreen.clickGetStartedButton(); + await OnboardingScreen.isScreenTitleVisible(); + await OnboardingScreen.clickImportWalletButton(); + await MetaMetricsScreen.isScreenTitleVisible(); + await MetaMetricsScreen.tapIAgreeButton(); + await ImportFromSeedScreen.isScreenTitleVisible(); + await ImportFromSeedScreen.typeSecretRecoveryPhrase(validAccount.seedPhrase); + await ImportFromSeedScreen.typeNewPassword(validAccount.password); + await ImportFromSeedScreen.typeConfirmPassword(validAccount.password); + await ImportFromSeedScreen.clickImportButton(); +}); + +Given(/^the onboarding wizard is visible on wallet view$/, async () => { + await OnboardingWizardModal.isVisible(); +}); + +When(/^I tap on "([^"]*)" button$/, async (text) => { + switch (text) { + case 'Take a Tour': + await OnboardingWizardModal.tapTakeTourButton(); + break; + case 'Got it': + await OnboardingWizardModal.tapGotItButton(); + break; + case 'Back': + await OnboardingWizardModal.tapBackButton(); + break; + case 'Skip': + await OnboardingWizardModal.tapSkipTutorialButton(); + break; + default: + throw new Error('Button not found'); + } +}); + +When(/^I tap and hold on the account Name$/, async () => { + await WalletAccountModal.longPressAccountNameLabel(); +}); + +When(/^I enter "([^"]*)" for account name$/, async (text) => { + await WalletAccountModal.editAccountNameLabel(text); +}); + +Then(/^the tutorial modal heading should read "([^"]*)"$/, async (text) => { + await OnboardingWizardModal.isHeaderDisplayedByXPath(text); +}); + +Then(/^there should be an explanation of the accounts functionality.$/, async () => { + await OnboardingWizardModal.isYourAccountDesc1Displayed(); + await OnboardingWizardModal.isYourAccountDesc2Displayed(); +}); + +Then(/^I should see the "([^"]*)" button$/, async (text) => { + switch (text) { + case 'Skip Tutorial': + await OnboardingWizardModal.isSkipTutorialButtonDisplayed(); + break; + default: + throw new Error('Button not found'); + } +}); + +Then(/^there should be an explanation about adding a nickname to your account.$/, async () => { + await OnboardingWizardModal.isEditAccountNameDesc1Displayed(); + await OnboardingWizardModal.isEditAccountNameDesc2Displayed(); +}); + +Then(/^I should be able to edit the account Name$/, async () => { + await WalletAccountModal.isAccountNameLabelEditable(); +}); + +Then(/^the account nickname should read "([^"]*)"$/, async (text) => { + await WalletAccountModal.isAccountNameLabelEqualTo(text); +}); + +Then(/^there should be an explanation of the what exists within the burger menu.$/, async () => { + await OnboardingWizardModal.isMainNavDesc1Displayed(); + await OnboardingWizardModal.isMainNavDesc2Displayed(); +}); + +Then(/^there should be an explanation of the what the purpose of the browser.$/, async () => { + await OnboardingWizardModal.isExploreBrowserDescDisplayed(); +}); + +Then(/^there should be an explanation of the what the purpose of the search input box.$/, async () => { + await OnboardingWizardModal.isSearchDescDisplayed(); +}); + +Then(/^the onboarding wizard is no longer visible$/, async () => { + await OnboardingWizardModal.isGotItButtonNotDisplayed(); +}); + +Then(/^the "([^"]*)" button is no longer visible$/, async (text) => { + switch (text) { + case 'Skip': + await OnboardingWizardModal.isSkipTutorialButtonNotDisplayed(); + break; + default: + throw new Error('Button not found'); + } +}); diff --git a/wdio/features/testIDs/Components/OnboardingWizard.testIds.js b/wdio/features/testIDs/Components/OnboardingWizard.testIds.js index e884301c68b..62379c1a542 100644 --- a/wdio/features/testIDs/Components/OnboardingWizard.testIds.js +++ b/wdio/features/testIDs/Components/OnboardingWizard.testIds.js @@ -1,6 +1,28 @@ // eslint-disable-next-line import/prefer-default-export -export const ONBOARDING_WIZARD_STEP_1_CONTAINER_ID = - 'onboarding-wizard-step1-container-id'; +export const ONBOARDING_WIZARD_STEP_1_CONTAINER_ID = 'onboarding-wizard-step1-container-id'; - export const ONBOARDING_WIZARD_STEP_1_NO_THANKS_ID = - 'onboarding-wizard-back-button'; +export const ONBOARDING_WIZARD_STEP_1_NO_THANKS_ID = 'onboarding-wizard-back-button'; + +export const ONBOARDING_WIZARD_STEP_1_TAKE_THE_TOUR_ID = 'onboarding-wizard-next-button'; + +export const ONBOARDING_WIZARD_SKIP_TUTORIAL_BUTTON = 'Skip Tutorial'; + +export const ONBOARDING_WIZARD_YOUR_ACCOUNTS_DESC_1 = 'This is your first account, total value, and its unique public address (0x...).'; + +export const ONBOARDING_WIZARD_YOUR_ACCOUNTS_DESC_2 = 'You can create multiple accounts within this wallet by tapping on the profile icon.'; + +export const ONBOARDING_WIZARD_NEXT_GOT_IT_BUTTON = 'Got it!'; + +export const ONBOARDING_WIZARD_BACK_BUTTON = 'Back'; + +export const ONBOARDING_WIZARD_EDIT_ACCOUNTS_NAME_DESC_1 = 'Why not give your account a memorable and distinct name?'; + +export const ONBOARDING_WIZARD_EDIT_ACCOUNTS_NAME_DESC_2 = 'Long tap now to edit account name.'; + +export const ONBOARDING_WIZARD_MAIN_NAVIGATION_DESC_1 = 'Tap here to access your Wallet, Browser, and Transaction activity.'; + +export const ONBOARDING_WIZARD_MAIN_NAVIGATION_DESC_2 = 'You can take more actions with your accounts & access MetaMask settings.'; + +export const ONBOARDING_WIZARD_EXPLORE_BROWSER_DESC = 'You can explore web3 using the browser'; + +export const ONBOARDING_WIZARD_SEARCH_DESC = 'Search for sites, or type a URL if you know where you’re headed.'; diff --git a/wdio/features/testIDs/Screens/WalletAccount.testIds.js b/wdio/features/testIDs/Screens/WalletAccount.testIds.js new file mode 100644 index 00000000000..0ff81973fe3 --- /dev/null +++ b/wdio/features/testIDs/Screens/WalletAccount.testIds.js @@ -0,0 +1,5 @@ +export const WALLET_ACCOUNT_ICON = 'wallet-account-identicon'; + +export const WALLET_ACCOUNT_NAME_LABEL_TEXT = 'edit-account-label'; + +export const WALLET_ACCOUNT_NAME_LABEL_INPUT = 'account-label-text-input';