diff --git a/.e2e.env.example b/.e2e.env.example index 598025493a6..3ea582afd72 100644 --- a/.e2e.env.example +++ b/.e2e.env.example @@ -20,4 +20,12 @@ export MULTICHAIN_DAPP_URL="https://metamask.github.io/test-dapp-multichain/late # E2E prebuild paths export PREBUILT_IOS_APP_PATH='build/MetaMask.app' export PREBUILT_ANDROID_APK_PATH='build/MetaMask.apk' -export PREBUILT_ANDROID_TEST_APK_PATH='build/MetaMask-Test.apk' \ No newline at end of file +export PREBUILT_ANDROID_TEST_APK_PATH='build/MetaMask-Test.apk' + +export TEST_SRP_1= +export TEST_SRP_2= +export TEST_SRP_3= +export BROWSERSTACK_USERNAME= +export BROWSERSTACK_ACCESS_KEY= +export SEEDLESS_ONBOARDING_ENABLED= +export SOLANA_MODAL_ENABLED= \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 19bd4fdcbc7..68f853d2ed7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,7 +21,7 @@ module.exports = { ], overrides: [ { - files: ['e2e/**/*.{js,ts}'], + files: ['e2e/**/*.{js,ts}', 'appwright/**/*.{js,ts}'], extends: ['./e2e/framework/.eslintrc.js'], }, { diff --git a/.gitignore b/.gitignore index d4691b9b43a..da0dc065213 100644 --- a/.gitignore +++ b/.gitignore @@ -65,8 +65,6 @@ buck-out/ # bundle artifact *.jsbundle -# testing -tests # app-specific /scripts/inpage-bridge/dist @@ -110,6 +108,15 @@ e2e/reports # Performance test results e2e/specs/performance/reports/*-performance-results.json +# appwright +appwright/report +playwright-report/* +appwright/test-reports/ +test-results/ +test-reports/ +appwright/reporters/reports/* +*.apk + # anvil binaries .metamask/* # ppom diff --git a/appwright/appwright.config.ts b/appwright/appwright.config.ts new file mode 100644 index 00000000000..944e605e5d3 --- /dev/null +++ b/appwright/appwright.config.ts @@ -0,0 +1,70 @@ +// In appwright.config.ts +import dotenv from 'dotenv'; +dotenv.config({ path: '.e2e.env' }); +import { defineConfig, Platform } from 'appwright'; +export default defineConfig({ + testMatch: '**/tests/performance/*.spec.js', + timeout: 7 * 60 * 1000, //7 minutes until we introduce fixtures + expect: { + timeout: 30 * 1000, //30 seconds + }, + reporter: [ + // The default HTML reporter from Appwright + [ + 'html', + { open: 'never', outputFolder: './test-reports/appwright-report' }, + ], + ['./reporters/custom-reporter.js'], + ['list'], + ], + + projects: [ + { + name: 'android', + use: { + platform: Platform.ANDROID, + device: { + provider: 'emulator', + name: 'Samsung Galaxy S24 Ultra', // this can be changed to your emulator name + osVersion: '14', // this can be changed to your emulator version + }, + buildPath: 'PATH-TO-BUILD', // Path to your .apk file + }, + }, + { + name: 'ios', + use: { + platform: Platform.IOS, + device: { + provider: 'emulator', + osVersion: '16.0', // this can be changed to your simulator version + }, + buildPath: 'PATH-TO-BUILD', // Path to your .app file + }, + }, + { + name: 'browserstack-android', + use: { + platform: Platform.ANDROID, + device: { + provider: 'browserstack', + name: process.env.BROWSERSTACK_DEVICE || 'Samsung Galaxy S23 Ultra', // this can changed + osVersion: process.env.BROWSERSTACK_OS_VERSION || '13.0', // this can changed + }, + buildPath: process.env.BROWSERSTACK_ANDROID_APP_URL, // Path to Browserstack url + }, + }, + { + name: 'browserstack-ios', + use: { + platform: Platform.IOS, + device: { + provider: 'browserstack', + name: process.env.BROWSERSTACK_DEVICE || 'iPhone 14 Pro Max', + osVersion: process.env.BROWSERSTACK_OS_VERSION || '16.0', + }, + buildPath: process.env.BROWSERSTACK_IOS_APP_URL, // Path to Browserstack url + }, + }, + ], +}); diff --git a/appwright/reporters/custom-reporter.js b/appwright/reporters/custom-reporter.js index 48a065d0608..b172a07f49a 100644 --- a/appwright/reporters/custom-reporter.js +++ b/appwright/reporters/custom-reporter.js @@ -1,6 +1,6 @@ -/* eslint-disable */ -// import fs from 'fs'; -// import path from 'path'; +/* eslint-disable import/no-nodejs-modules */ +import fs from 'fs'; +import path from 'path'; class CustomReporter { constructor() { @@ -72,6 +72,7 @@ class CustomReporter { ); fs.writeFileSync(jsonPath, JSON.stringify(this.metrics, null, 2)); // Generate HTML report + /* eslint-disable */ const html = ` @@ -82,10 +83,10 @@ class CustomReporter { @@ -120,6 +121,7 @@ class CustomReporter { `; } + return ''; // Return empty string for device key }) .join('')} @@ -130,6 +132,7 @@ class CustomReporter { `; + /* eslint-enable */ const reportPath = path.join( reportsDir, diff --git a/appwright/tests/performance/scenario1.spec.js b/appwright/tests/performance/scenario1.spec.js new file mode 100644 index 00000000000..a4a25d43f6e --- /dev/null +++ b/appwright/tests/performance/scenario1.spec.js @@ -0,0 +1,74 @@ +import { test, expect } from 'appwright'; + +import TimerHelper from '../../utils/TimersHelper.js'; +import { PerformanceTracker } from '../../reporters/PerformanceTracker.js'; +import WelcomeScreen from '../../../wdio/screen-objects/Onboarding/OnboardingCarousel.js'; +import TermOfUseScreen from '../../../wdio/screen-objects/Modals/TermOfUseScreen.js'; +import OnboardingScreen from '../../../wdio/screen-objects/Onboarding/OnboardingScreen.js'; +import CreateNewWalletScreen from '../../../wdio/screen-objects/Onboarding/CreateNewWalletScreen.js'; +import MetaMetricsScreen from '../../../wdio/screen-objects/Onboarding/MetaMetricsScreen.js'; +import OnboardingSucessScreen from '../../../wdio/screen-objects/OnboardingSucessScreen.js'; +import OnboardingSheet from '../../../wdio/screen-objects/Onboarding/OnboardingSheet.js'; +import SolanaFeatureSheet from '../../../wdio/screen-objects/Modals/SolanaFeatureSheet.js'; +import WalletAccountModal from '../../../wdio/screen-objects/Modals/WalletAccountModal.js'; +import SkipAccountSecurityModal from '../../../wdio/screen-objects/Modals/SkipAccountSecurityModal.js'; +import ImportFromSeedScreen from '../../../wdio/screen-objects/Onboarding/ImportFromSeedScreen.js'; +import CreatePasswordScreen from '../../../wdio/screen-objects/Onboarding/CreatePasswordScreen.js'; +import AccountListComponent from '../../../wdio/screen-objects/AccountListComponent.js'; +import AddAccountModal from '../../../wdio/screen-objects/Modals/AddAccountModal.js'; +import WalletMainScreen from '../../../wdio/screen-objects/WalletMainScreen.js'; +import { importSRPFlow, onboardingFlowImportSRP } from '../../utils/Flows.js'; + +test('Account creation with 50+ accounts, SRP 1 + SRP 2 + SRP 3', async ({ + device, +}, testInfo) => { + WelcomeScreen.device = device; + TermOfUseScreen.device = device; + OnboardingScreen.device = device; + CreateNewWalletScreen.device = device; + MetaMetricsScreen.device = device; + OnboardingSucessScreen.device = device; + OnboardingSheet.device = device; + SolanaFeatureSheet.device = device; + WalletAccountModal.device = device; + SkipAccountSecurityModal.device = device; + ImportFromSeedScreen.device = device; + CreatePasswordScreen.device = device; + WalletMainScreen.device = device; + AccountListComponent.device = device; + AddAccountModal.device = device; + + await onboardingFlowImportSRP(device, process.env.TEST_SRP_1); + await importSRPFlow(device, process.env.TEST_SRP_2); + await importSRPFlow(device, process.env.TEST_SRP_3); + + const screen1Timer = new TimerHelper( + 'Time since the user clicks on "Account list" button until the account list is visible', + ); + const screen2Timer = new TimerHelper( + 'Time since the user clicks on "Add account" button until the next modal is visible', + ); + const screen3Timer = new TimerHelper( + 'Time since the user clicks on "Create Ethereum account" button until the Token list is visible', + ); + + await WalletMainScreen.isTokenVisible('Ethereum'); + screen1Timer.start(); + await WalletMainScreen.tapIdenticon(); + await AccountListComponent.isComponentDisplayed(); + screen1Timer.stop(); + screen2Timer.start(); + await AccountListComponent.tapAddAccountButton(); + screen2Timer.stop(); + screen3Timer.start(); + await AddAccountModal.tapCreateEthereumAccountButton(); + await WalletMainScreen.isTokenVisible('Ethereum'); + screen3Timer.stop(); + + const performanceTracker = new PerformanceTracker(); + performanceTracker.addTimer(screen1Timer); + performanceTracker.addTimer(screen2Timer); + performanceTracker.addTimer(screen3Timer); + + await performanceTracker.attachToTest(testInfo); +}); diff --git a/appwright/tests/performance/scenario2.spec.js b/appwright/tests/performance/scenario2.spec.js new file mode 100644 index 00000000000..29eb09a5d34 --- /dev/null +++ b/appwright/tests/performance/scenario2.spec.js @@ -0,0 +1,115 @@ +import { test, expect } from 'appwright'; + +import TimerHelper from '../../utils/TimersHelper.js'; +import { PerformanceTracker } from '../../reporters/PerformanceTracker.js'; +import WelcomeScreen from '../../../wdio/screen-objects/Onboarding/OnboardingCarousel.js'; +import TermOfUseScreen from '../../../wdio/screen-objects/Modals/TermOfUseScreen.js'; +import OnboardingScreen from '../../../wdio/screen-objects/Onboarding/OnboardingScreen.js'; +import CreateNewWalletScreen from '../../../wdio/screen-objects/Onboarding/CreateNewWalletScreen.js'; +import MetaMetricsScreen from '../../../wdio/screen-objects/Onboarding/MetaMetricsScreen.js'; +import OnboardingSucessScreen from '../../../wdio/screen-objects/OnboardingSucessScreen.js'; +import OnboardingSheet from '../../../wdio/screen-objects/Onboarding/OnboardingSheet.js'; +import SolanaFeatureSheet from '../../../wdio/screen-objects/Modals/SolanaFeatureSheet.js'; +import WalletAccountModal from '../../../wdio/screen-objects/Modals/WalletAccountModal.js'; +import SkipAccountSecurityModal from '../../../wdio/screen-objects/Modals/SkipAccountSecurityModal.js'; +import WalletMainScreen from '../../../wdio/screen-objects/WalletMainScreen.js'; + +const SOLANA_MODAL_ENABLED = process.env.SOLANA_MODAL_ENABLED + ? process.env.SOLANA_MODAL_ENABLED + : false; +test('Onboarding new wallet, SRP 1 + SRP 2 + SRP 3', async ({ + device, +}, testInfo) => { + const screen1Timer = new TimerHelper( + 'Time until the user clicks on the "Get Started" button', + ); + screen1Timer.start(); + WelcomeScreen.device = device; + TermOfUseScreen.device = device; + OnboardingScreen.device = device; + CreateNewWalletScreen.device = device; + MetaMetricsScreen.device = device; + OnboardingSucessScreen.device = device; + OnboardingSheet.device = device; + SolanaFeatureSheet.device = device; + WalletAccountModal.device = device; + SkipAccountSecurityModal.device = device; + WalletMainScreen.device = device; + + const timer1 = new TimerHelper( + 'Time since the user clicks on "Get Started" button until the Term of Use screen is visible', + ); + const timer2 = new TimerHelper( + 'Time since the user clicks on "Aggree to T&C" button until the Onboarding screen is visible', + ); + const timer3 = new TimerHelper( + 'Time since the user clicks on "Create new wallet" button until "continue with SRP" button is visible', + ); + const timer4 = new TimerHelper( + 'Time since the user clicks on "Continue with SRP" button until password fields are visible', + ); + const timer5 = new TimerHelper( + 'Time since the user clicks on "Create Password" button until "Remind me later" shows up', + ); + const timer6 = new TimerHelper( + 'Time since the user clicks on "Proceed without wallet secure" button until Metrics screen is displayed', + ); + const timer7 = new TimerHelper( + 'Time since the user clicks on "Aggree" button on Metrics screen until Onboarding Success screen is visible', + ); + const timer8 = new TimerHelper( + 'Time since the user clicks on "Done" button until Solana feature sheet is visible', + ); + + timer1.start(); + await WelcomeScreen.clickGetStartedButton(); + await TermOfUseScreen.isDisplayed(); + timer1.stop(); + await TermOfUseScreen.tapAgreeCheckBox(); + await TermOfUseScreen.tapScrollEndButton(); + timer2.start(); + await TermOfUseScreen.tapAcceptButton(); + await OnboardingScreen.isScreenTitleVisible(); + timer2.stop(); + timer3.start(); + await OnboardingScreen.tapCreateNewWalletButton(); + await OnboardingSheet.isVisible(); + timer3.stop(); + timer4.start(); + await OnboardingSheet.tapImportSeedButton(); + await CreateNewWalletScreen.isNewAccountScreenFieldsVisible(); + timer4.stop(); + await CreateNewWalletScreen.inputPasswordInFirstField('123456789'); + await CreateNewWalletScreen.inputConfirmPasswordField('123456789'); + timer5.start(); + await CreateNewWalletScreen.tapSubmitButton(); + await CreateNewWalletScreen.tapRemindMeLater(); + await SkipAccountSecurityModal.isVisible(); + timer5.stop(); + timer6.start(); + await SkipAccountSecurityModal.proceedWithoutWalletSecure(); + await MetaMetricsScreen.isScreenTitleVisible(); + timer6.stop(); + timer7.start(); + await MetaMetricsScreen.tapIAgreeButton(); + await OnboardingSucessScreen.isVisible(); + timer7.stop(); + timer8.start(); + await OnboardingSucessScreen.tapDone(); + if (SOLANA_MODAL_ENABLED) { + await SolanaFeatureSheet.isVisible(); + await SolanaFeatureSheet.tapNotNowButton(); + } + timer8.stop(); + + const performanceTracker = new PerformanceTracker(); + performanceTracker.addTimer(timer1); + performanceTracker.addTimer(timer2); + performanceTracker.addTimer(timer3); + performanceTracker.addTimer(timer4); + performanceTracker.addTimer(timer5); + performanceTracker.addTimer(timer6); + performanceTracker.addTimer(timer7); + performanceTracker.addTimer(timer8); + await performanceTracker.attachToTest(testInfo); +}); diff --git a/appwright/tests/performance/scenario3.spec.js b/appwright/tests/performance/scenario3.spec.js new file mode 100644 index 00000000000..7c4d4f4364e --- /dev/null +++ b/appwright/tests/performance/scenario3.spec.js @@ -0,0 +1,144 @@ +import { test, expect } from 'appwright'; + +import TimerHelper from '../../utils/TimersHelper.js'; +import { PerformanceTracker } from '../../reporters/PerformanceTracker.js'; +import WelcomeScreen from '../../../wdio/screen-objects/Onboarding/OnboardingCarousel.js'; +import TermOfUseScreen from '../../../wdio/screen-objects/Modals/TermOfUseScreen.js'; +import OnboardingScreen from '../../../wdio/screen-objects/Onboarding/OnboardingScreen.js'; +import CreateNewWalletScreen from '../../../wdio/screen-objects/Onboarding/CreateNewWalletScreen.js'; +import MetaMetricsScreen from '../../../wdio/screen-objects/Onboarding/MetaMetricsScreen.js'; +import OnboardingSucessScreen from '../../../wdio/screen-objects/OnboardingSucessScreen.js'; +import OnboardingSheet from '../../../wdio/screen-objects/Onboarding/OnboardingSheet.js'; +import SolanaFeatureSheet from '../../../wdio/screen-objects/Modals/SolanaFeatureSheet.js'; +import WalletAccountModal from '../../../wdio/screen-objects/Modals/WalletAccountModal.js'; +import SkipAccountSecurityModal from '../../../wdio/screen-objects/Modals/SkipAccountSecurityModal.js'; +import WalletMainScreen from '../../../wdio/screen-objects/WalletMainScreen.js'; +import CreatePasswordScreen from '../../../wdio/screen-objects/Onboarding/CreatePasswordScreen.js'; +import ImportFromSeedScreen from '../../../wdio/screen-objects/Onboarding/ImportFromSeedScreen.js'; + +const SOLANA_MODAL_ENABLED = process.env.SOLANA_MODAL_ENABLED === 'false'; + +test('Onboarding Import SRP with +50 accounts, SRP 3', async ({ + device, +}, testInfo) => { + const screen1Timer = new TimerHelper( + 'Time until the user clicks on the "Get Started" button', + ); + screen1Timer.start(); + WelcomeScreen.device = device; + TermOfUseScreen.device = device; + OnboardingScreen.device = device; + CreateNewWalletScreen.device = device; + MetaMetricsScreen.device = device; + OnboardingSucessScreen.device = device; + OnboardingSheet.device = device; + SolanaFeatureSheet.device = device; + WalletAccountModal.device = device; + SkipAccountSecurityModal.device = device; + WalletMainScreen.device = device; + ImportFromSeedScreen.device = device; + CreatePasswordScreen.device = device; + + const timer1 = new TimerHelper( + 'Time since the user clicks on "Get Started" button until the Term of Use screen is visible', + ); + const timer2 = new TimerHelper( + 'Time since the user clicks on "Aggree to T&C" button until the Onboarding screen is visible', + ); + const timer3 = new TimerHelper( + 'Time since the user clicks on "Create new wallet" button until "Social sign up" is visible', + ); + const timer4 = new TimerHelper( + 'Time since the user clicks on "Import using SRP" button until SRP field is displayed', + ); + const timer5 = new TimerHelper( + 'Time since the user clicks on "Continue" button on SRP screen until Password fields are visible', + ); + const timer6 = new TimerHelper( + 'Time since the user clicks on "Create Password" button until Metrics screen is displayed', + ); + const timer7 = new TimerHelper( + 'Time since the user clicks on "I agree" button on Metrics screen until Onboarding Success screen is visible', + ); + const timer8 = new TimerHelper( + 'Time since the user clicks on "Done" button until Solana feature sheet is visible', + ); + const timer9 = new TimerHelper( + 'Time since the user clicks on "Not now" button On Solana feature sheet until native token is visible', + ); + const timer10 = new TimerHelper( + 'Time since the user clicks on "Account list" button until the account list is visible', + ); + + timer1.start(); + await WelcomeScreen.clickGetStartedButton(); + await TermOfUseScreen.isDisplayed(); + timer1.stop(); + await TermOfUseScreen.tapAgreeCheckBox(); + await TermOfUseScreen.tapScrollEndButton(); + + timer2.start(); + await TermOfUseScreen.tapAcceptButton(); + await OnboardingScreen.isScreenTitleVisible(); + timer2.stop(); + + timer3.start(); + await OnboardingScreen.tapHaveAnExistingWallet(); + await OnboardingSheet.isVisible(); + timer3.stop(); + + timer4.start(); + await OnboardingSheet.tapImportSeedButton(); + await ImportFromSeedScreen.isScreenTitleVisible(); + timer4.stop(); + await ImportFromSeedScreen.typeSecretRecoveryPhrase( + process.env.TEST_SRP_3, + true, + ); + await ImportFromSeedScreen.tapImportScreenTitleToDismissKeyboard(); + + timer5.start(); + await ImportFromSeedScreen.tapContinueButton(); + + await CreatePasswordScreen.isVisible(); + timer5.stop(); + await CreatePasswordScreen.enterPassword('123456789'); + await CreatePasswordScreen.reEnterPassword('123456789'); + await CreatePasswordScreen.tapIUnderstandCheckBox(); + await CreatePasswordScreen.tapCreatePasswordButton(); + + timer6.start(); + await MetaMetricsScreen.isScreenTitleVisible(); + timer6.stop(); + + timer7.start(); + await MetaMetricsScreen.tapIAgreeButton(); + await OnboardingSucessScreen.isVisible(); + timer7.stop(); + + timer8.start(); + await OnboardingSucessScreen.tapDone(); + if (SOLANA_MODAL_ENABLED) { + await SolanaFeatureSheet.isVisible(); + await SolanaFeatureSheet.tapNotNowButton(); + } + timer8.stop(); + timer9.start(); + await WalletMainScreen.isTokenVisible('Ethereum'); + timer9.stop(); + + timer10.start(); + await WalletMainScreen.tapIdenticon(); + timer10.stop(); + const performanceTracker = new PerformanceTracker(); + performanceTracker.addTimer(timer1); + performanceTracker.addTimer(timer2); + performanceTracker.addTimer(timer3); + performanceTracker.addTimer(timer4); + performanceTracker.addTimer(timer5); + performanceTracker.addTimer(timer6); + performanceTracker.addTimer(timer7); + performanceTracker.addTimer(timer8); + performanceTracker.addTimer(timer9); + await performanceTracker.attachToTest(testInfo); +}); diff --git a/appwright/tests/performance/scenario4.spec.js b/appwright/tests/performance/scenario4.spec.js new file mode 100644 index 00000000000..c3655d76289 --- /dev/null +++ b/appwright/tests/performance/scenario4.spec.js @@ -0,0 +1,51 @@ +import { test, expect } from 'appwright'; + +import TimerHelper from '../../utils/TimersHelper.js'; +import { PerformanceTracker } from '../../reporters/PerformanceTracker.js'; +import WelcomeScreen from '../../../wdio/screen-objects/Onboarding/OnboardingCarousel.js'; +import TermOfUseScreen from '../../../wdio/screen-objects/Modals/TermOfUseScreen.js'; +import OnboardingScreen from '../../../wdio/screen-objects/Onboarding/OnboardingScreen.js'; +import CreateNewWalletScreen from '../../../wdio/screen-objects/Onboarding/CreateNewWalletScreen.js'; +import MetaMetricsScreen from '../../../wdio/screen-objects/Onboarding/MetaMetricsScreen.js'; +import OnboardingSucessScreen from '../../../wdio/screen-objects/OnboardingSucessScreen.js'; +import OnboardingSheet from '../../../wdio/screen-objects/Onboarding/OnboardingSheet.js'; +import SolanaFeatureSheet from '../../../wdio/screen-objects/Modals/SolanaFeatureSheet.js'; +import WalletAccountModal from '../../../wdio/screen-objects/Modals/WalletAccountModal.js'; +import SkipAccountSecurityModal from '../../../wdio/screen-objects/Modals/SkipAccountSecurityModal.js'; +import WalletMainScreen from '../../../wdio/screen-objects/WalletMainScreen.js'; +import CreatePasswordScreen from '../../../wdio/screen-objects/Onboarding/CreatePasswordScreen.js'; +import ImportFromSeedScreen from '../../../wdio/screen-objects/Onboarding/ImportFromSeedScreen.js'; +import { importSRPFlow, onboardingFlowImportSRP } from '../../utils/Flows.js'; + +test('Import SRP with +50 accounts, SRP 1, SRP 2, SRP 3', async ({ + device, +}, testInfo) => { + const screen1Timer = new TimerHelper( + 'Time until the user clicks on the "Get Started" button', + ); + screen1Timer.start(); + WelcomeScreen.device = device; + TermOfUseScreen.device = device; + OnboardingScreen.device = device; + CreateNewWalletScreen.device = device; + MetaMetricsScreen.device = device; + OnboardingSucessScreen.device = device; + OnboardingSheet.device = device; + SolanaFeatureSheet.device = device; + WalletAccountModal.device = device; + SkipAccountSecurityModal.device = device; + WalletMainScreen.device = device; + ImportFromSeedScreen.device = device; + CreatePasswordScreen.device = device; + + await onboardingFlowImportSRP(device, process.env.TEST_SRP_1); + await importSRPFlow(device, process.env.TEST_SRP_2); + await WalletMainScreen.isTokenVisible('Ethereum'); + const timers = await importSRPFlow(device, process.env.TEST_SRP_3); + await WalletMainScreen.isTokenVisible('Ethereum'); + + await WalletMainScreen.tapIdenticon(); + const performanceTracker = new PerformanceTracker(); + timers.forEach((timer) => performanceTracker.addTimer(timer)); + await performanceTracker.attachToTest(testInfo); +}); diff --git a/appwright/tests/performance/scenario6.spec.js b/appwright/tests/performance/scenario6.spec.js new file mode 100644 index 00000000000..98e81595a3f --- /dev/null +++ b/appwright/tests/performance/scenario6.spec.js @@ -0,0 +1,69 @@ +import { test, expect } from 'appwright'; + +import TimerHelper from '../../utils/TimersHelper.js'; +import { PerformanceTracker } from '../../reporters/PerformanceTracker.js'; +import WelcomeScreen from '../../../wdio/screen-objects/Onboarding/OnboardingCarousel.js'; +import TermOfUseScreen from '../../../wdio/screen-objects/Modals/TermOfUseScreen.js'; +import OnboardingScreen from '../../../wdio/screen-objects/Onboarding/OnboardingScreen.js'; +import CreateNewWalletScreen from '../../../wdio/screen-objects/Onboarding/CreateNewWalletScreen.js'; +import MetaMetricsScreen from '../../../wdio/screen-objects/Onboarding/MetaMetricsScreen.js'; +import OnboardingSucessScreen from '../../../wdio/screen-objects/OnboardingSucessScreen.js'; +import OnboardingSheet from '../../../wdio/screen-objects/Onboarding/OnboardingSheet.js'; +import SolanaFeatureSheet from '../../../wdio/screen-objects/Modals/SolanaFeatureSheet.js'; +import WalletAccountModal from '../../../wdio/screen-objects/Modals/WalletAccountModal.js'; +import SkipAccountSecurityModal from '../../../wdio/screen-objects/Modals/SkipAccountSecurityModal.js'; +import ImportFromSeedScreen from '../../../wdio/screen-objects/Onboarding/ImportFromSeedScreen.js'; +import CreatePasswordScreen from '../../../wdio/screen-objects/Onboarding/CreatePasswordScreen.js'; +import WalletMainScreen from '../../../wdio/screen-objects/WalletMainScreen.js'; +import AccountListComponent from '../../../wdio/screen-objects/AccountListComponent.js'; +import AddAccountModal from '../../../wdio/screen-objects/Modals/AddAccountModal.js'; +import WalletActionModal from '../../../wdio/screen-objects/Modals/WalletActionModal.js'; +import SwapScreen from '../../../wdio/screen-objects/SwapScreen.js'; +import TabBarModal from '../../../wdio/screen-objects/Modals/TabBarModal.js'; +import { onboardingFlowImportSRP } from '../../utils/Flows.js'; + +test('Swap flow - ETH to USDC, SRP 1 + SRP 2 + SRP 3', async ({ + device, +}, testInfo) => { + WelcomeScreen.device = device; + TermOfUseScreen.device = device; + OnboardingScreen.device = device; + CreateNewWalletScreen.device = device; + MetaMetricsScreen.device = device; + OnboardingSucessScreen.device = device; + OnboardingSheet.device = device; + SolanaFeatureSheet.device = device; + WalletAccountModal.device = device; + SkipAccountSecurityModal.device = device; + ImportFromSeedScreen.device = device; + CreatePasswordScreen.device = device; + WalletMainScreen.device = device; + AccountListComponent.device = device; + AddAccountModal.device = device; + WalletActionModal.device = device; + SwapScreen.device = device; + TabBarModal.device = device; + + await onboardingFlowImportSRP(device, process.env.TEST_SRP_2); + + const swapLoadTimer = new TimerHelper( + 'Time since the user clicks on the "Swap" button until the swap page is loaded', + ); + swapLoadTimer.start(); + // await TabBarModal.tapActionButton(); + await WalletActionModal.tapSwapButton(); + swapLoadTimer.stop(); + const swapTimer = new TimerHelper( + 'Time since the user enters the amount until the quote is displayed', + ); + await SwapScreen.selectNetworkAndTokenTo('Ethereum', 'USDC'); + await SwapScreen.enterSourceTokenAmount('1'); + await SwapScreen.tapGetQuotes('Ethereum'); + swapTimer.start(); + await SwapScreen.isQuoteDisplayed('Ethereum'); + swapTimer.stop(); + const performanceTracker = new PerformanceTracker(); + performanceTracker.addTimer(swapLoadTimer); + performanceTracker.addTimer(swapTimer); + await performanceTracker.attachToTest(testInfo); +}); diff --git a/appwright/tests/performance/scenario7.spec.js b/appwright/tests/performance/scenario7.spec.js new file mode 100644 index 00000000000..db1de20a61e --- /dev/null +++ b/appwright/tests/performance/scenario7.spec.js @@ -0,0 +1,77 @@ +import { test, expect } from 'appwright'; + +import TimerHelper from '../../utils/TimersHelper.js'; +import { PerformanceTracker } from '../../reporters/PerformanceTracker.js'; +import WelcomeScreen from '../../../wdio/screen-objects/Onboarding/OnboardingCarousel.js'; +import TermOfUseScreen from '../../../wdio/screen-objects/Modals/TermOfUseScreen.js'; +import OnboardingScreen from '../../../wdio/screen-objects/Onboarding/OnboardingScreen.js'; +import CreateNewWalletScreen from '../../../wdio/screen-objects/Onboarding/CreateNewWalletScreen.js'; +import MetaMetricsScreen from '../../../wdio/screen-objects/Onboarding/MetaMetricsScreen.js'; +import OnboardingSucessScreen from '../../../wdio/screen-objects/OnboardingSucessScreen.js'; +import OnboardingSheet from '../../../wdio/screen-objects/Onboarding/OnboardingSheet.js'; +import SolanaFeatureSheet from '../../../wdio/screen-objects/Modals/SolanaFeatureSheet.js'; +import WalletAccountModal from '../../../wdio/screen-objects/Modals/WalletAccountModal.js'; +import SkipAccountSecurityModal from '../../../wdio/screen-objects/Modals/SkipAccountSecurityModal.js'; +import ImportFromSeedScreen from '../../../wdio/screen-objects/Onboarding/ImportFromSeedScreen.js'; +import CreatePasswordScreen from '../../../wdio/screen-objects/Onboarding/CreatePasswordScreen.js'; +import WalletMainScreen from '../../../wdio/screen-objects/WalletMainScreen.js'; +import AccountListComponent from '../../../wdio/screen-objects/AccountListComponent.js'; +import AddAccountModal from '../../../wdio/screen-objects/Modals/AddAccountModal.js'; +import WalletActionModal from '../../../wdio/screen-objects/Modals/WalletActionModal.js'; +import SwapScreen from '../../../wdio/screen-objects/SwapScreen.js'; +import TabBarModal from '../../../wdio/screen-objects/Modals/TabBarModal.js'; +import { onboardingFlowImportSRP } from '../../utils/Flows.js'; +import NetworksScreen from '../../../wdio/screen-objects/NetworksScreen.js'; +import NetworkEducationModal from '../../../wdio/screen-objects/Modals/NetworkEducationModal.js'; +import BridgeScreen from '../../../wdio/screen-objects/BridgeScreen.js'; + +test('Cross-chain swap flow - ETH to SOL - 50+ accounts, SRP 1 + SRP 2 + SRP 3', async ({ + device, +}, testInfo) => { + WelcomeScreen.device = device; + TermOfUseScreen.device = device; + OnboardingScreen.device = device; + CreateNewWalletScreen.device = device; + MetaMetricsScreen.device = device; + OnboardingSucessScreen.device = device; + OnboardingSheet.device = device; + SolanaFeatureSheet.device = device; + WalletAccountModal.device = device; + SkipAccountSecurityModal.device = device; + ImportFromSeedScreen.device = device; + CreatePasswordScreen.device = device; + WalletMainScreen.device = device; + AccountListComponent.device = device; + AddAccountModal.device = device; + WalletActionModal.device = device; + SwapScreen.device = device; + TabBarModal.device = device; + NetworkEducationModal.device = device; + NetworksScreen.device = device; + BridgeScreen.device = device; + + await onboardingFlowImportSRP(device, process.env.TEST_SRP_2); + + const timer1 = new TimerHelper( + 'Time since the user clicks on the "Swap" button until the swap page is loaded', + ); + timer1.start(); + + await WalletActionModal.tapBridgeButton(); + await BridgeScreen.isVisible(); + timer1.stop(); + + await BridgeScreen.selectNetworkAndTokenTo('Solana', 'SOL'); + await BridgeScreen.enterSourceTokenAmount('0.0001'); + const timer2 = new TimerHelper( + 'Time since the user enters the amount until the quote is displayed', + ); + + timer2.start(); + await BridgeScreen.isQuoteDisplayed('Solana'); + timer2.stop(); + const performanceTracker = new PerformanceTracker(); + performanceTracker.addTimer(timer1); + performanceTracker.addTimer(timer2); + await performanceTracker.attachToTest(testInfo); +}); diff --git a/appwright/tests/performance/scenario8.spec.js b/appwright/tests/performance/scenario8.spec.js new file mode 100644 index 00000000000..8374a7a87df --- /dev/null +++ b/appwright/tests/performance/scenario8.spec.js @@ -0,0 +1,63 @@ +import { test, expect } from 'appwright'; + +import TimerHelper from '../../utils/TimersHelper.js'; +import { PerformanceTracker } from '../../reporters/PerformanceTracker.js'; +import WelcomeScreen from '../../../wdio/screen-objects/Onboarding/OnboardingCarousel.js'; +import TermOfUseScreen from '../../../wdio/screen-objects/Modals/TermOfUseScreen.js'; +import OnboardingScreen from '../../../wdio/screen-objects/Onboarding/OnboardingScreen.js'; +import CreateNewWalletScreen from '../../../wdio/screen-objects/Onboarding/CreateNewWalletScreen.js'; +import MetaMetricsScreen from '../../../wdio/screen-objects/Onboarding/MetaMetricsScreen.js'; +import OnboardingSucessScreen from '../../../wdio/screen-objects/OnboardingSucessScreen.js'; +import OnboardingSheet from '../../../wdio/screen-objects/Onboarding/OnboardingSheet.js'; +import SolanaFeatureSheet from '../../../wdio/screen-objects/Modals/SolanaFeatureSheet.js'; +import WalletAccountModal from '../../../wdio/screen-objects/Modals/WalletAccountModal.js'; +import SkipAccountSecurityModal from '../../../wdio/screen-objects/Modals/SkipAccountSecurityModal.js'; +import ImportFromSeedScreen from '../../../wdio/screen-objects/Onboarding/ImportFromSeedScreen.js'; +import CreatePasswordScreen from '../../../wdio/screen-objects/Onboarding/CreatePasswordScreen.js'; +import WalletMainScreen from '../../../wdio/screen-objects/WalletMainScreen.js'; +import AccountListComponent from '../../../wdio/screen-objects/AccountListComponent.js'; +import AddAccountModal from '../../../wdio/screen-objects/Modals/AddAccountModal.js'; +import TokenOverviewScreen from '../../../wdio/screen-objects/TokenOverviewScreen.js'; +import CommonScreen from '../../../wdio/screen-objects/CommonScreen.js'; +import WalletActionModal from '../../../wdio/screen-objects/Modals/WalletActionModal.js'; +import { importSRPFlow, onboardingFlowImportSRP } from '../../utils/Flows.js'; + +test('Asset View, SRP 1 + SRP 2 + SRP 3', async ({ device }, testInfo) => { + WelcomeScreen.device = device; + TermOfUseScreen.device = device; + OnboardingScreen.device = device; + CreateNewWalletScreen.device = device; + MetaMetricsScreen.device = device; + OnboardingSucessScreen.device = device; + OnboardingSheet.device = device; + SolanaFeatureSheet.device = device; + WalletAccountModal.device = device; + SkipAccountSecurityModal.device = device; + ImportFromSeedScreen.device = device; + CreatePasswordScreen.device = device; + WalletMainScreen.device = device; + AccountListComponent.device = device; + AddAccountModal.device = device; + TokenOverviewScreen.device = device; + CommonScreen.device = device; + WalletActionModal.device = device; + + await onboardingFlowImportSRP(device, process.env.TEST_SRP_3); + await importSRPFlow(device, process.env.TEST_SRP_2); + // await importSRPFlow(device, process.env.TEST_SRP_3); + + await WalletMainScreen.isMainWalletViewVisible(); + + const assetViewScreen = new TimerHelper( + 'Time since the user clicks on the asset view button until the user sees the token overview screen', + ); + assetViewScreen.start(); + await WalletMainScreen.tapOnToken('Ethereum'); + await TokenOverviewScreen.isTokenOverviewVisible(); + await TokenOverviewScreen.isTodaysChangeVisible(); + assetViewScreen.stop(); + + const performanceTracker = new PerformanceTracker(); + performanceTracker.addTimer(assetViewScreen); + await performanceTracker.attachToTest(testInfo); +}); diff --git a/appwright/tests/performance/scenario9.spec.js b/appwright/tests/performance/scenario9.spec.js new file mode 100644 index 00000000000..34d529b4cfe --- /dev/null +++ b/appwright/tests/performance/scenario9.spec.js @@ -0,0 +1,149 @@ +import { test, expect } from 'appwright'; + +import TimerHelper from '../../utils/TimersHelper.js'; +import { PerformanceTracker } from '../../reporters/PerformanceTracker.js'; +import WelcomeScreen from '../../../wdio/screen-objects/Onboarding/OnboardingCarousel.js'; +import TermOfUseScreen from '../../../wdio/screen-objects/Modals/TermOfUseScreen.js'; +import OnboardingScreen from '../../../wdio/screen-objects/Onboarding/OnboardingScreen.js'; +import CreateNewWalletScreen from '../../../wdio/screen-objects/Onboarding/CreateNewWalletScreen.js'; +import MetaMetricsScreen from '../../../wdio/screen-objects/Onboarding/MetaMetricsScreen.js'; +import OnboardingSucessScreen from '../../../wdio/screen-objects/OnboardingSucessScreen.js'; +import OnboardingSheet from '../../../wdio/screen-objects/Onboarding/OnboardingSheet.js'; +import SolanaFeatureSheet from '../../../wdio/screen-objects/Modals/SolanaFeatureSheet.js'; +import WalletAccountModal from '../../../wdio/screen-objects/Modals/WalletAccountModal.js'; +import SkipAccountSecurityModal from '../../../wdio/screen-objects/Modals/SkipAccountSecurityModal.js'; +import ImportFromSeedScreen from '../../../wdio/screen-objects/Onboarding/ImportFromSeedScreen.js'; +import CreatePasswordScreen from '../../../wdio/screen-objects/Onboarding/CreatePasswordScreen.js'; +import WalletMainScreen from '../../../wdio/screen-objects/WalletMainScreen.js'; +import AccountListComponent from '../../../wdio/screen-objects/AccountListComponent.js'; +import AddAccountModal from '../../../wdio/screen-objects/Modals/AddAccountModal.js'; +import TokenOverviewScreen from '../../../wdio/screen-objects/TokenOverviewScreen.js'; +import { importSRPFlow, onboardingFlowImportSRP } from '../../utils/Flows.js'; +import SendScreen from '../../../wdio/screen-objects/SendScreen.js'; +import ConfirmationScreen from '../../../wdio/screen-objects/ConfirmationScreen.js'; +import WalletActionModal from '../../../wdio/screen-objects/Modals/WalletActionModal.js'; +import AmountScreen from '../../../wdio/screen-objects/AmountScreen.js'; +import SendSolanaScreen from '../../../wdio/screen-objects/SendSolanaScreen.js'; +import NetworkEducationModal from '../../../wdio/screen-objects/Modals/NetworkEducationModal.js'; +import SolanaConfirmationScreen from '../../../wdio/screen-objects/SolanaConfirmationScreen.js'; +import NetworksScreen from '../../../wdio/screen-objects/NetworksScreen.js'; + +test('Send flow - Ethereum, SRP 1 + SRP 2 + SRP 3', async ({ + device, +}, testInfo) => { + WelcomeScreen.device = device; + TermOfUseScreen.device = device; + OnboardingScreen.device = device; + CreateNewWalletScreen.device = device; + MetaMetricsScreen.device = device; + OnboardingSucessScreen.device = device; + OnboardingSheet.device = device; + SolanaFeatureSheet.device = device; + WalletAccountModal.device = device; + SkipAccountSecurityModal.device = device; + ImportFromSeedScreen.device = device; + CreatePasswordScreen.device = device; + WalletMainScreen.device = device; + AccountListComponent.device = device; + AddAccountModal.device = device; + WalletActionModal.device = device; + SendScreen.device = device; + ConfirmationScreen.device = device; + AmountScreen.device = device; + await onboardingFlowImportSRP(device, process.env.TEST_SRP_1); + await importSRPFlow(device, process.env.TEST_SRP_2); + // await importSRPFlow(device, process.env.TEST_SRP_3); + + const timer1 = new TimerHelper( + 'Time since the user clicks on the send button, until the user is in the send screen', + ); + timer1.start(); + await WalletActionModal.tapSendButton(); + await SendScreen.isVisible(); + timer1.stop(); + await SendScreen.typeAddressInSendAddressField( + '0x8aBB895C61706f33060cDb40e7a2b496C3CA1Dcf', + ); + const timer2 = new TimerHelper( + 'Time since the user clicks on next button, until the user is in the send amount screen', + ); + timer2.start(); + await SendScreen.tapOnNextButton(); + await SendScreen.isAmountScreenDisplayed(); + timer2.stop(); + const timer3 = new TimerHelper( + 'Time since the user clicks on Next after entering the amount, until the user gets the confirmation screen', + ); + + await AmountScreen.enterAmount('0.00001'); + timer3.start(); + await AmountScreen.tapOnNextButton(); + await ConfirmationScreen.isAccountSendToVisible(); + await ConfirmationScreen.isNetworkDisplayed(); + await ConfirmationScreen.isAdvancedSettingsDisplayed(); + timer3.stop(); + + const performanceTracker = new PerformanceTracker(); + performanceTracker.addTimer(timer1); + performanceTracker.addTimer(timer2); + performanceTracker.addTimer(timer3); + await performanceTracker.attachToTest(testInfo); +}); + +test('Send flow - Solana, SRP 1 + SRP 2 + SRP 3', async ({ + device, +}, testInfo) => { + WelcomeScreen.device = device; + TermOfUseScreen.device = device; + OnboardingScreen.device = device; + CreateNewWalletScreen.device = device; + MetaMetricsScreen.device = device; + OnboardingSucessScreen.device = device; + OnboardingSheet.device = device; + SolanaFeatureSheet.device = device; + WalletAccountModal.device = device; + SkipAccountSecurityModal.device = device; + ImportFromSeedScreen.device = device; + CreatePasswordScreen.device = device; + WalletMainScreen.device = device; + AccountListComponent.device = device; + AddAccountModal.device = device; + WalletActionModal.device = device; + SendScreen.device = device; + ConfirmationScreen.device = device; + AmountScreen.device = device; + NetworkEducationModal.device = device; + SendSolanaScreen.device = device; + SolanaConfirmationScreen.device = device; + NetworksScreen.device = device; + + await onboardingFlowImportSRP(device, process.env.TEST_SRP_3); + // await importSRPFlow(device, process.env.TEST_SRP_2); + // await importSRPFlow(device, process.env.TEST_SRP_3); + + await WalletMainScreen.tapNetworkNavBar(); + await NetworksScreen.tapOnNetwork('Solana'); + await NetworkEducationModal.tapGotItButton(); + + const timer1 = new TimerHelper( + 'Time since the user clicks on the send button, until the user is in the send screen', + ); + timer1.start(); + await WalletActionModal.tapSendButton(); + await SendSolanaScreen.isAddressFieldVisible(); + timer1.stop(); + + await SendSolanaScreen.fillAddressField( + '3xTPAZxmpwd8GrNEKApaTw6VH4jqJ31WFXUvQzgwhR7c', + ); + await SendSolanaScreen.fillAmountField('0.001'); + + const timer2 = await SendSolanaScreen.tapContinueButton(); + await SolanaConfirmationScreen.isConfirmButtonDisplayed(); + + timer2.stop(); + const performanceTracker = new PerformanceTracker(); + performanceTracker.addTimer(timer1); + performanceTracker.addTimer(timer2); + await performanceTracker.attachToTest(testInfo); +}); diff --git a/appwright/utils/Flows.js b/appwright/utils/Flows.js new file mode 100644 index 00000000000..e5ad0590317 --- /dev/null +++ b/appwright/utils/Flows.js @@ -0,0 +1,106 @@ +import AccountListComponent from '../../wdio/screen-objects/AccountListComponent.js'; +import AddAccountModal from '../../wdio/screen-objects/Modals/AddAccountModal.js'; +import ImportFromSeedScreen from '../../wdio/screen-objects/Onboarding/ImportFromSeedScreen.js'; +import WalletMainScreen from '../../wdio/screen-objects/WalletMainScreen.js'; +import TimerHelper from './TimersHelper.js'; +import WelcomeScreen from '../../wdio/screen-objects/Onboarding/OnboardingCarousel.js'; +import TermOfUseScreen from '../../wdio/screen-objects/Modals/TermOfUseScreen.js'; +import OnboardingScreen from '../../wdio/screen-objects/Onboarding/OnboardingScreen.js'; +import OnboardingSheet from '../../wdio/screen-objects/Onboarding/OnboardingSheet.js'; +import CreatePasswordScreen from '../../wdio/screen-objects/Onboarding/CreatePasswordScreen.js'; +import MetaMetricsScreen from '../../wdio/screen-objects/Onboarding/MetaMetricsScreen.js'; +import OnboardingSucessScreen from '../../wdio/screen-objects/OnboardingSucessScreen.js'; +import SolanaFeatureSheet from '../../wdio/screen-objects/Modals/SolanaFeatureSheet.js'; + +export async function onboardingFlowImportSRP(device, srp) { + WelcomeScreen.device = device; + TermOfUseScreen.device = device; + OnboardingScreen.device = device; + OnboardingSheet.device = device; + ImportFromSeedScreen.device = device; + CreatePasswordScreen.device = device; + MetaMetricsScreen.device = device; + OnboardingSucessScreen.device = device; + SolanaFeatureSheet.device = device; + await WelcomeScreen.clickGetStartedButton(); + await TermOfUseScreen.isDisplayed(); + + await TermOfUseScreen.tapAgreeCheckBox(); + await TermOfUseScreen.tapScrollEndButton(); + + await TermOfUseScreen.tapAcceptButton(); + await OnboardingScreen.isScreenTitleVisible(); + + await OnboardingScreen.tapHaveAnExistingWallet(); + await OnboardingSheet.isVisible(); + await OnboardingSheet.tapImportSeedButton(); + await ImportFromSeedScreen.isScreenTitleVisible(); + + await ImportFromSeedScreen.typeSecretRecoveryPhrase(srp, true); + await ImportFromSeedScreen.tapImportScreenTitleToDismissKeyboard(); + + await ImportFromSeedScreen.tapContinueButton(); + + await CreatePasswordScreen.isVisible(); + + await CreatePasswordScreen.enterPassword('123456789'); + await CreatePasswordScreen.reEnterPassword('123456789'); + await CreatePasswordScreen.tapIUnderstandCheckBox(); + await CreatePasswordScreen.tapCreatePasswordButton(); + + await MetaMetricsScreen.isScreenTitleVisible(); + await MetaMetricsScreen.tapIAgreeButton(); + + await OnboardingSucessScreen.isVisible(); + await OnboardingSucessScreen.tapDone(); + + // await SolanaFeatureSheet.isVisible(); + // await SolanaFeatureSheet.tapNotNowButton(); + await WalletMainScreen.isMainWalletViewVisible(); +} + +export async function importSRPFlow(device, srp) { + WalletMainScreen.device = device; + AccountListComponent.device = device; + AddAccountModal.device = device; + ImportFromSeedScreen.device = device; + const timers = []; + const timer = new TimerHelper( + 'Time since the user clicks on "Account list" button until the account list is visible', + ); + const timer2 = new TimerHelper( + 'Time since the user clicks on "Add account" button until the next modal is visible', + ); + const timer3 = new TimerHelper( + 'Time since the user clicks on "Import SRP" button until SRP field is displayed', + ); + const timer4 = new TimerHelper( + 'Time since the user clicks on "Continue" button on SRP screen until Wallet main screen is visible', + ); + + timer.start(); + + await WalletMainScreen.tapIdenticon(); + await AccountListComponent.isComponentDisplayed(); + timer.stop(); + + timer2.start(); + await AccountListComponent.tapAddAccountButton(); + await AddAccountModal.isVisible(); + timer2.stop(); + + timer3.start(); + await AddAccountModal.tapImportSrpButton(); + await ImportFromSeedScreen.isScreenTitleVisible(false); + timer3.stop(); + await ImportFromSeedScreen.typeSecretRecoveryPhrase(srp, false); + await ImportFromSeedScreen.tapImportScreenTitleToDismissKeyboard(false); + + timer4.start(); + await ImportFromSeedScreen.tapContinueButton(false); + await WalletMainScreen.isMainWalletViewVisible(); + timer4.stop(); + + timers.push(timer, timer2, timer3, timer4); + return timers; +} diff --git a/docs/readme/testing.md b/docs/readme/testing.md index 6a8538fdbc5..fdbdd45c943 100644 --- a/docs/readme/testing.md +++ b/docs/readme/testing.md @@ -308,6 +308,95 @@ The API Spec tests use the `@open-rpc/test-coverage` tool to generate tests from yarn test:api-specs ``` +### Appwright + +This is a recent mobile framework which was built using appium and playwright. We adopted it to meet our need for running performance focused end to end tests on real iOS and Android devices through BrowserStack. + +#### Running Tests Against BrowserStack Devices + +You can get your BrowserStack username and access key from the Access key dropdown on the app automate screen in BrowserStack. + +##### Set Environment Variables for BrowserStack + +```bash +export BROWSERSTACK_USERNAME='your_username' +export BROWSERSTACK_ACCESS_KEY='your_access_key' +``` + +Update the config file with the appropriate BrowserStack app URL. You’ll need a BrowserStack URL first. To get it: + +1. Run `create_qa_builds_pipeline` on Bitrise +2. Once done, open the **Artifacts** tab and find `browserstack_uploaded_apps.json` (from `build_android_qa` and `build_ios_qa`). + +See this [build](https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/de2bf4ee-b000-4a7c-bd5b-c995ae0f3b4d?tab=artifacts) as an example. + +The first entry in that JSON will include your app’s URL (look for the bs:// prefix). + +Add it to the config file by replacing `process.env.BROWSERSTACK_ANDROID_APP_URL` in the `buildPath` with the appropriate BrowserStack application URL: + +```typescript +{ + name: 'browserstack-android', + use: { + platform: Platform.ANDROID, + device: { + provider: 'browserstack', + name: process.env.BROWSERSTACK_DEVICE || 'Samsung Galaxy S23 Ultra', // this can be changed + osVersion: process.env.BROWSERSTACK_OS_VERSION || '13.0', // this can be changed + }, + buildPath: process.env.BROWSERSTACK_ANDROID_APP_URL, // Path to BrowserStack URL bs:// link + }, +} +``` + +You can repeat the same for iOS builds by replacing `process.env.BROWSERSTACK_IOS_APP_URL` in the config. + +##### Run Android Tests on BrowserStack + +```bash +yarn run-appwright:android-bs +``` + +##### Run iOS Tests on BrowserStack + +```bash +yarn run-appwright:ios-bs +``` + +#### Testing Locally (Simulators/Emulators) + +You need to make sure that the artifact is created. Download the binary from the [runway](https://github.com/MetaMask/metamask-mobile/tree/MMQA-521-part-2?tab=readme-ov-file#download-and-install-the-development-build) and place it in a folder accessible to Appwright. + +Then update the build path in the `ios` or `android` config: + +```typescript +{ + name: 'ios', + use: { + platform: Platform.IOS, + device: { + provider: 'emulator', + osVersion: '16.0', // this can be changed to your simulator version + }, + buildPath: 'PATH-TO-BUILD', // Path to your .app file + }, +} +``` + +##### Test on Your Local Android Emulator + +```bash +yarn run-appwright:android +``` + +##### Test on Your Local iOS Simulator + +```bash +yarn run-appwright:ios +``` + +**Important**: If the test fail to start, double check the OS version your simulator/emulator is running and make sure the config has the correct version. + ### Bitrise Pipelines Overview Our CI/CD process is automated through various Bitrise pipelines, each designed to streamline and optimize different aspects of our E2E testing. diff --git a/e2e/selectors/Bridge/QuoteView.selectors.ts b/e2e/selectors/Bridge/QuoteView.selectors.ts index c7cf69dc607..b1ddeb31c26 100644 --- a/e2e/selectors/Bridge/QuoteView.selectors.ts +++ b/e2e/selectors/Bridge/QuoteView.selectors.ts @@ -8,6 +8,7 @@ export const QuoteViewSelectorText = { CONFIRM_SWAP: enContent.bridge.confirm_swap, SELECT_AMOUNT: enContent.bridge.select_amount, CANCEL: 'Cancel', + FEE_DISCLAIMER: enContent.bridge.fee_disclaimer, }; export const QuoteViewSelectorIDs = { diff --git a/e2e/selectors/Onboarding/Onboarding.selectors.ts b/e2e/selectors/Onboarding/Onboarding.selectors.ts index 3fd1c82a5e0..a32314532d0 100644 --- a/e2e/selectors/Onboarding/Onboarding.selectors.ts +++ b/e2e/selectors/Onboarding/Onboarding.selectors.ts @@ -5,6 +5,10 @@ export const OnboardingSelectorIDs = { NEW_WALLET_BUTTON: 'wallet-setup-screen-create-new-wallet-button-id', EXISTING_WALLET_BUTTON: 'wallet-setup-screen-have-an-existing-wallet-button-id', + /* + EXISTING_WALLET_BUTTON: + 'wallet-setup-screen-import-from-seed-button-id', + */ SCREEN_TITLE: 'wallet-setup-screen-title-id', SCREEN_DESCRIPTION: 'wallet-setup-screen-description-id', }; diff --git a/e2e/selectors/wallet/WalletActionsBottomSheet.selectors.ts b/e2e/selectors/wallet/WalletActionsBottomSheet.selectors.ts index c7619685fe5..261e603400a 100644 --- a/e2e/selectors/wallet/WalletActionsBottomSheet.selectors.ts +++ b/e2e/selectors/wallet/WalletActionsBottomSheet.selectors.ts @@ -1,11 +1,11 @@ export const WalletActionsBottomSheetSelectorsIDs = { - SEND_BUTTON: 'wallet-send-action', + SEND_BUTTON: 'wallet-send-button', RECEIVE_BUTTON: 'wallet-receive-action', - SWAP_BUTTON: 'wallet-swap-action', + SWAP_BUTTON: 'wallet-swap-button', BUY_BUTTON: 'wallet-buy-action', SELL_BUTTON: 'wallet-sell-action', DEPOSIT_BUTTON: 'wallet-deposit-action', - BRIDGE_BUTTON: 'wallet-bridge-action', + BRIDGE_BUTTON: 'wallet-bridge-button', EARN_BUTTON: 'wallet-earn-action', PERPS_BUTTON: 'wallet-perps-action', }; diff --git a/package.json b/package.json index dd060aa7fec..2c8c2c44436 100644 --- a/package.json +++ b/package.json @@ -108,6 +108,10 @@ "test:wdio:android": "yarn wdio ./wdio/config/android.config.debug.js", "test:wdio:android:browserstack": "yarn wdio ./wdio/config/android.config.browserstack.js", "test:wdio:android:browserstack:local": "yarn wdio ./wdio/config/android.config.browserstack.local.js", + "run-appwright:android-bs": "npx appwright test --project browserstack-android --config appwright/appwright.config.ts", + "run-appwright:ios-bs": "npx appwright test --project browserstack-ios --config appwright/appwright.config.ts", + "run-appwright:android": "npx appwright test --project android --config appwright/appwright.config.ts", + "run-appwright:ios": "npx appwright test --project ios --config appwright/appwright.config.ts", "test:depcheck": "yarn depcheck", "test:tgz-check": "./scripts/tgz-check.sh", "test:attribution-check": "./scripts/attributions-check.sh", diff --git a/patches/appwright+0.1.45.patch b/patches/appwright+0.1.45.patch index 5e5dc888cb9..af4b3da3922 100644 --- a/patches/appwright+0.1.45.patch +++ b/patches/appwright+0.1.45.patch @@ -1,3 +1,54 @@ +diff --git a/node_modules/appwright/dist/config.js b/node_modules/appwright/dist/config.js +index a51913b..8c0335c 100644 +--- a/node_modules/appwright/dist/config.js ++++ b/node_modules/appwright/dist/config.js +@@ -25,7 +25,7 @@ const defaultConfig = { + fullyParallel: false, + forbidOnly: false, + retries: process.env.CI ? 2 : 0, +- workers: 2, ++ workers: 1, + reporter: [["list"], ["html", { open: "always" }]], + use: { + // TODO: Use this for actions +diff --git a/node_modules/appwright/dist/providers/browserstack/index.js b/node_modules/appwright/dist/providers/browserstack/index.js +index 638c5df..1b9f5bb 100644 +--- a/node_modules/appwright/dist/providers/browserstack/index.js ++++ b/node_modules/appwright/dist/providers/browserstack/index.js +@@ -120,6 +120,12 @@ class BrowserStackDeviceProvider { + return this.sessionDetails?.app_details.app_name ?? ""; + } + static async downloadVideo(sessionId, outputDir, fileName) { ++ // Check if video download is disabled via environment variable ++ if (process.env.DISABLE_VIDEO_DOWNLOAD === 'true') { ++ logger_1.logger.log('Video download disabled by environment variable DISABLE_VIDEO_DOWNLOAD'); ++ return null; ++ } ++ + const sessionData = await getSessionDetails(sessionId); + const sessionDetails = sessionData?.automation_session; + const videoURL = sessionDetails?.video_url; +@@ -241,6 +247,7 @@ class BrowserStackDeviceProvider { + capabilities: { + "bstack:options": { + debug: true, ++ networkProfile : '4g-lte-advanced-good', + interactiveDebugging: true, + networkLogs: true, + appiumVersion: "2.6.0", +@@ -250,10 +257,10 @@ class BrowserStackDeviceProvider { + osVersion: this.project.use.device.osVersion, + platformName: platformName, + deviceOrientation: this.project.use.device?.orientation, +- buildName: `${projectName} ${platformName}`, ++ buildName: process.env.BROWSERSTACK_BUILD_NAME || `${projectName} ${platformName}`, + sessionName: `${projectName} ${platformName} test`, + buildIdentifier: process.env.GITHUB_ACTIONS === "true" +- ? `CI ${process.env.GITHUB_RUN_ID}` ++ ? "" + : process.env.USER, + }, + "appium:autoGrantPermissions": true, diff --git a/node_modules/appwright/dist/reporter.js b/node_modules/appwright/dist/reporter.js index 516da40..ae1895b 100644 --- a/node_modules/appwright/dist/reporter.js diff --git a/tsconfig.json b/tsconfig.json index 15cd772a141..4857c92f64f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -63,7 +63,8 @@ "app/**/*", "node_modules/expect-webdriverio", "node_modules/expect-webdriverio/jest", - "e2e/**/*" + "e2e/**/*", + "appwright/**/*" ], "exclude": [ "node_modules", diff --git a/wdio/helpers/AppwrightSelectors.js b/wdio/helpers/AppwrightSelectors.js new file mode 100644 index 00000000000..e77ec6406fd --- /dev/null +++ b/wdio/helpers/AppwrightSelectors.js @@ -0,0 +1,79 @@ +export default class AppwrightSelectors { + // The below three selectors are the primary selectors + static async getElementByID(device, id) { + return await device.getById(id,{ exact: true }); + } + + static async getElementByXpath(device, xpath) { + return await device.getByXpath(xpath); + } + + static async getElementByText(device, text) { + return await device.getByText(text); + } + + // This is a catch-all xpath selector that works on both platforms. Needed to identify deeply nested elements + static async getElementByCatchAll(device, identifier) { + const isAndroid = AppwrightSelectors.isAndroid(device); + + if (isAndroid) { + // Android: resource-id, text, content-desc (exact match for resource-id, contains for text/desc) + const xpath = `//*[@resource-id='${identifier}' or contains(@text,'${identifier}') or contains(@content-desc,'${identifier}')]`; + return await AppwrightSelectors.getElementByXpath(device, xpath); + } else { + // iOS: name, label, text (contains for all to handle partial matches) + const xpath = `//*[contains(@name,'${identifier}') or contains(@label,'${identifier}') or contains(@text,'${identifier}')]`; + return await AppwrightSelectors.getElementByXpath(device, xpath); + } + } + static isIOS(device) { + return device.webDriverClient.capabilities.platformName === 'iOS' || device.webDriverClient.capabilities.platformName === 'ios'; + } + + static isAndroid(device) { + return device.webDriverClient.capabilities.platformName === 'android' || device.webDriverClient.capabilities.platformName === 'Android'; + } + + static async hideKeyboard(device) { + if (AppwrightSelectors.isAndroid(device)) await device.webDriverClient.hideKeyboard(); // only needed for Android + } + + static async scrollIntoView(device, element) { + for (let i = 0; i < 5; i++) { + try { + const isVisible = await element.isVisible({ timeout: 2000 }); + + if (isVisible) { + return element; + } + } catch (error) { + // Element not found or not visible, continue scrolling + } + const driver = device.webDriverClient; + // Perform a scroll action + if (AppwrightSelectors.isAndroid(device)) { + // For Android, use a swipe gesture + //await driver.tap({ x: 500, y: 1500 }); + await driver.executeScript("mobile: swipeGesture", [ + { + left: 100, + top: 500, + width: 200, + height: 1000, + direction: "up", + percent: 0.75 + } + ]); + } else { + // For iOS + await driver.scroll(); + } + + // Wait a bit for the scroll to complete + await new Promise(resolve => setTimeout(resolve, 500)); + } + + throw new Error(`Element not found after 5 scroll attempts`); + + } +} \ No newline at end of file diff --git a/wdio/helpers/Selectors.js b/wdio/helpers/Selectors.js index 1ae3454947f..5dc793d19e3 100644 --- a/wdio/helpers/Selectors.js +++ b/wdio/helpers/Selectors.js @@ -1,4 +1,5 @@ class Selectors { + static async getElementByPlatform(id, isNested = false) { if (!isNested) { return $(`~${id}`); diff --git a/wdio/screen-objects/AccountListComponent.js b/wdio/screen-objects/AccountListComponent.js index 58bc04360ab..36cf1b4a5f2 100644 --- a/wdio/screen-objects/AccountListComponent.js +++ b/wdio/screen-objects/AccountListComponent.js @@ -3,29 +3,74 @@ import Selectors from '../helpers/Selectors'; import { AccountListBottomSheetSelectorsIDs, } from '../../e2e/selectors/wallet/AccountListBottomSheet.selectors'; +import AppwrightSelectors from '../helpers/AppwrightSelectors'; +import { expect, ScrollDirection } from 'appwright'; class AccountListComponent { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get accountListContainer() { - return Selectors.getXpathElementByResourceId(AccountListBottomSheetSelectorsIDs.ACCOUNT_LIST_ID); + if (!this._device) { + return Selectors.getXpathElementByResourceId(AccountListBottomSheetSelectorsIDs.ACCOUNT_LIST_ID); + } else { + return AppwrightSelectors.getElementByID(this._device, AccountListBottomSheetSelectorsIDs.ACCOUNT_LIST_ID); + } } get addAccountButton() { - return Selectors.getXpathElementByResourceId(AccountListBottomSheetSelectorsIDs.ACCOUNT_LIST_ADD_BUTTON_ID); + if (!this._device) { + return Selectors.getXpathElementByResourceId(AccountListBottomSheetSelectorsIDs.ACCOUNT_LIST_ADD_BUTTON_ID); + } else { + return AppwrightSelectors.getElementByID(this._device, AccountListBottomSheetSelectorsIDs.ACCOUNT_LIST_ADD_BUTTON_ID); + } } async tapAddAccountButton() { - await Gestures.waitAndTap(this.addAccountButton); + if (!this._device) { + await Gestures.waitAndTap(this.addAccountButton); + } else { + const element = await this.addAccountButton; + await element.tap(); + } } async isComponentDisplayed() { - const container = await this.accountListContainer; - await container.waitForDisplayed(); + if (!this._device) { + await this.accountListContainer.waitForDisplayed(); + } else { + const element = await this.accountListContainer; + await expect(element).toBeVisible({ timeout: 10000 }); + } } async isComponentNotDisplayed() { const element = await this.accountListContainer; await element.waitForExist({ reverse: true }); } + + async tapOnAccountByName(name) { + let account = await AppwrightSelectors.getElementByText(this.device, name); + await AppwrightSelectors.scrollIntoView(this.device, account); + await account.tap(); + /* + console.log('account ->', account); + try { + await account.tap(); + } catch (error) { + console.log('Error tapping on account ->', error); + await this.device.pause(10000000); + await this.device.scroll(); + account = await AppwrightSelectors.getElementByText(this.device, name); + + await account.tap(); + }*/ + } } export default new AccountListComponent(); diff --git a/wdio/screen-objects/AmountScreen.js b/wdio/screen-objects/AmountScreen.js index e01468e532c..c19300030d7 100644 --- a/wdio/screen-objects/AmountScreen.js +++ b/wdio/screen-objects/AmountScreen.js @@ -1,3 +1,4 @@ +import AppwrightSelectors from '../helpers/AppwrightSelectors'; import Gestures from '../helpers/Gestures'; import Selectors from '../helpers/Selectors'; import { @@ -8,12 +9,28 @@ import { } from './testIDs/Screens/AmountScreen.testIds'; class AmountScreen { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get amountInputField() { - return Selectors.getElementByPlatform(TRANSACTION_AMOUNT_INPUT); + if (!this._device) { + return Selectors.getElementByPlatform(TRANSACTION_AMOUNT_INPUT); + } else { + return AppwrightSelectors.getElementByID(this._device, TRANSACTION_AMOUNT_INPUT); + } } get amountScreen() { - return Selectors.getElementByPlatform(AMOUNT_SCREEN); + if (!this._device) { + return Selectors.getElementByPlatform(AMOUNT_SCREEN); + } else { + return AppwrightSelectors.getElementByID(this._device, AMOUNT_SCREEN); + } } get amountError() { @@ -21,12 +38,21 @@ class AmountScreen { } get nextButton() { - return Selectors.getElementByPlatform(NEXT_BUTTON); + if (!this._device) { + return Selectors.getElementByPlatform(NEXT_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, NEXT_BUTTON); + } } async enterAmount(text) { - await Gestures.waitAndTap(this.amountInputField); - await Gestures.typeText(this.amountInputField, text); + if (!this._device) { + await Gestures.waitAndTap(this.amountInputField); + await Gestures.typeText(this.amountInputField, text); + } else { + const element = await AppwrightSelectors.getElementByID(this._device, TRANSACTION_AMOUNT_INPUT); + await element.fill(text); + } } async isTokenCorrect(token) { @@ -42,6 +68,11 @@ class AmountScreen { const nextButton = await this.nextButton; await nextButton.waitForEnabled(); } + + async tapOnNextButton() { + const element = await this.nextButton; + await element.tap(); + } } export default new AmountScreen(); diff --git a/wdio/screen-objects/BridgeScreen.js b/wdio/screen-objects/BridgeScreen.js new file mode 100644 index 00000000000..ede90ef336e --- /dev/null +++ b/wdio/screen-objects/BridgeScreen.js @@ -0,0 +1,115 @@ +import AppwrightSelectors from '../helpers/AppwrightSelectors'; +import { SWAP_SCREEN_DESTINATION_TOKEN_INPUT_ID, SWAP_SCREEN_QUOTE_DISPLAYED_ID, SWAP_SCREEN_SOURCE_TOKEN_INPUT_ID } from './testIDs/Screens/SwapScreen.testIds'; +import { expect as appwrightExpect } from 'appwright'; +import { PerpsWithdrawViewSelectorsIDs } from '../../e2e/selectors/Perps/Perps.selectors'; +import { QuoteViewSelectorIDs,QuoteViewSelectorText } from '../../e2e/selectors/swaps/QuoteView.selectors'; +import { SwapsViewSelectorsIDs } from '../../e2e/selectors/swaps/SwapsView.selectors'; +import { QuoteViewSelectorText as BridgeQuotesSelectorText } from '../../e2e/selectors/Bridge/QuoteView.selectors'; + +class BridgeScreen { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get sourceTokenInput() { + return AppwrightSelectors.getElementByID(this._device, SWAP_SCREEN_SOURCE_TOKEN_INPUT_ID); + } + + get destTokenInput() { + return AppwrightSelectors.getElementByID(this._device, SWAP_SCREEN_DESTINATION_TOKEN_INPUT_ID); + } + + get quoteDisplayed() { + return AppwrightSelectors.getElementByID(this._device, SWAP_SCREEN_QUOTE_DISPLAYED_ID); + } + get destinationTokenArea(){ + return AppwrightSelectors.getElementByID(this._device, PerpsWithdrawViewSelectorsIDs.DEST_TOKEN_AREA); + + } + get seeAllDropDown(){ + return AppwrightSelectors.getElementByText(this._device, "See all"); + + } + + get getETHQuotesButton(){ + return AppwrightSelectors.getElementByText(this._device, QuoteViewSelectorText.GET_QUOTES); + } + + async isQuoteDisplayed(network) { + if (network == 'Ethereum'){ // legacy swap view only shows on etheruem network + const mmFee = await AppwrightSelectors.getElementByID(this._device, SwapsViewSelectorsIDs.QUOTE_SUMMARY); + await appwrightExpect(mmFee).toBeVisible({ timeout: 10000 }); + + } + else{ + const element = await this.quoteDisplayed; // bridge swap view shows on + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + const mmFee = await AppwrightSelectors.getElementByCatchAll(this._device, BridgeQuotesSelectorText.FEE_DISCLAIMER); + await appwrightExpect(mmFee).toBeVisible({ timeout: 30000 }); + } + + } + + async enterSourceTokenAmount(amount) { + // Split amount into digits + const digits = this.splitAmountIntoDigits(amount); + console.log('Amount digits:', digits); + digits.forEach(async digit => { + if (AppwrightSelectors.isAndroid(this._device)) { + if (digit != '.') { + const numberKey = await AppwrightSelectors.getElementByXpath(this._device, `//android.widget.Button[@content-desc='${digit}']`); + await numberKey.tap(); + } + else { + const numberKey = await AppwrightSelectors.getElementByXpath(this._device, `//android.view.ViewGroup[@content-desc="."]`); + await numberKey.tap(); + } + } + else { + const numberKey = await AppwrightSelectors.getElementByXpath(this._device, `//XCUIElementTypeButton[@name="${digit}"]`); + await numberKey.tap(); + } + }); + } + + async selectNetworkAndTokenTo(network, token) { + const bridgeButton = await AppwrightSelectors.getElementByText(this._device, 'Bridge to'); + await bridgeButton.tap(); + const networkButton = await AppwrightSelectors.getElementByCatchAll(this._device, network); + await networkButton.tap(); + const tokenButton = await AppwrightSelectors.getElementByCatchAll(this._device, token); + await tokenButton.tap(); + } + + async tapGetQuotes(network){ + if (network == 'Ethereum'){ + const quotesButton = await this.getETHQuotesButton; + await appwrightExpect(quotesButton).toBeVisible({ timeout: 10000 }); + await quotesButton.tap(); + } + } + + // Helper method to split amount into digits + splitAmountIntoDigits(amount) { + // Convert to string and split into array of digits + return amount.toString().split('').map(char => { + // Return only numeric digits, filter out decimal points, commas, etc. + return /\d/.test(char) ? parseInt(char, 10) : char; + }); + } + + async enterDestinationTokenAmount(amount) { + const element = await this.destTokenInput; + await element.fill(amount); + } + + async isVisible() { + const element = await this.sourceTokenInput; + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + } +} + +export default new BridgeScreen(); diff --git a/wdio/screen-objects/CommonScreen.js b/wdio/screen-objects/CommonScreen.js index 3cbf3138405..6be0cb37c06 100644 --- a/wdio/screen-objects/CommonScreen.js +++ b/wdio/screen-objects/CommonScreen.js @@ -5,8 +5,18 @@ import { ToastSelectorsText, } from '../../e2e/selectors/wallet/ToastModal.selectors'; import { CommonSelectorsIDs } from '../../e2e/selectors/Common.selectors'; +import AppwrightSelectors from '../helpers/AppwrightSelectors'; class CommonScreen { + + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get toast() { return Selectors.getXpathElementByResourceId(ToastSelectorsIDs.CONTAINER); } @@ -70,6 +80,17 @@ class CommonScreen { const notification = await this.TokenNotificationTitle; await notification.waitForExist({ reverse: true }); } + + + async tapOnAsset(asset) { + if (!this._device) { + await Gestures.getElementByResourceId(`asset-${asset}`); + } else { + console.log('tapOnAsset ->', this._device); + const assetElement = await AppwrightSelectors.getElementByID(this._device, `asset-${asset}`); + await assetElement.tap(); + } + } } export default new CommonScreen(); diff --git a/wdio/screen-objects/ConfirmationScreen.js b/wdio/screen-objects/ConfirmationScreen.js new file mode 100644 index 00000000000..46e3687eece --- /dev/null +++ b/wdio/screen-objects/ConfirmationScreen.js @@ -0,0 +1,57 @@ +import AppwrightSelectors from '../helpers/AppwrightSelectors'; +import { ConfirmationRowComponentIDs,ConfirmationFooterSelectorIDs } from '../../e2e/selectors/Confirmation/ConfirmationView.selectors'; +import { expect as appwrightExpect } from 'appwright'; + +class ConfirmationScreen { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + + get accountSendTo() { + return AppwrightSelectors.getElementByID(this._device, ConfirmationRowComponentIDs.FROM_TO); + } + + get network() { + return AppwrightSelectors.getElementByID(this._device, ConfirmationRowComponentIDs.GAS_FEES_DETAILS); + } + + get advancedSettings() { + return AppwrightSelectors.getElementByID(this._device, 'info-section'); + } + + get confirmButton() { + return AppwrightSelectors.getElementByID(this._device, ConfirmationFooterSelectorIDs.CONFIRM_BUTTON); + } + + async isAccountSendToVisible() { + const accountSendTo = await this.accountSendTo; + await appwrightExpect(accountSendTo).toBeVisible(); + } + + async isNetworkDisplayed() { + const network = await this.network; + await appwrightExpect(network).toBeVisible(); + } + + async isAdvancedSettingsDisplayed() { + const advancedSettings = await this.advancedSettings; + await appwrightExpect(advancedSettings).toBeVisible(); + } + + async isConfirmButtonClickable() { + const confirmButton = await this.confirmButton; + await AppwrightSelectors.isElementClickable(confirmButton); + } + + async tapOnConfirmButton() { + const confirmButton = await this.confirmButton; + console.log('confirmButton', confirmButton); + //await confirmButton.tap(); + } +} + +export default new ConfirmationScreen(); diff --git a/wdio/screen-objects/Modals/AddAccountModal.js b/wdio/screen-objects/Modals/AddAccountModal.js index bef953ac82d..cdd164348f0 100644 --- a/wdio/screen-objects/Modals/AddAccountModal.js +++ b/wdio/screen-objects/Modals/AddAccountModal.js @@ -1,24 +1,108 @@ import Selectors from '../../helpers/Selectors'; import { AddAccountBottomSheetSelectorsIDs } from '../../../e2e/selectors/wallet/AddAccountBottomSheet.selectors'; import Gestures from '../../helpers/Gestures'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; +import { expect as appwrightExpect } from 'appwright'; class AddAccountModal { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + + get importSrpButton() { + if (!this._device) { + return Selectors.getXpathElementByResourceId(AddAccountBottomSheetSelectorsIDs.IMPORT_SRP_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, AddAccountBottomSheetSelectorsIDs.IMPORT_SRP_BUTTON); + } + } + get newAccountButton() { - return Selectors.getXpathElementByResourceId(AddAccountBottomSheetSelectorsIDs.NEW_ACCOUNT_BUTTON); + if (!this._device) { + return Selectors.getXpathElementByResourceId(AddAccountBottomSheetSelectorsIDs.NEW_ACCOUNT_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, AddAccountBottomSheetSelectorsIDs.NEW_ACCOUNT_BUTTON); + } } get importAccountButton() { - return Selectors.getXpathElementByResourceId(AddAccountBottomSheetSelectorsIDs.IMPORT_ACCOUNT_BUTTON); + if (!this._device) { + return Selectors.getXpathElementByResourceId(AddAccountBottomSheetSelectorsIDs.IMPORT_ACCOUNT_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, AddAccountBottomSheetSelectorsIDs.IMPORT_ACCOUNT_BUTTON); + } + } + + get createSolanaAccountButton() { + if (!this._device) { + return Selectors.getXpathElementByResourceId(AddAccountBottomSheetSelectorsIDs.ADD_SOLANA_ACCOUNT_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, AddAccountBottomSheetSelectorsIDs.ADD_SOLANA_ACCOUNT_BUTTON); + } + } + + get createEthereumAccountButton() { + if (!this._device) { + return Selectors.getXpathElementByResourceId(AddAccountBottomSheetSelectorsIDs.ADD_ETHEREUM_ACCOUNT_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, AddAccountBottomSheetSelectorsIDs.ADD_ETHEREUM_ACCOUNT_BUTTON); + } } async tapNewAccountButton() { - await Gestures.waitAndTap(this.newAccountButton); - const newAccountButton = await this.newAccountButton; - await newAccountButton.waitForExist({ reverse: true }); + if (!this._device) { + await Gestures.waitAndTap(this.newAccountButton); + const newAccountButton = await this.newAccountButton; + await newAccountButton.waitForExist({ reverse: true }); + } else { + const element = await this.newAccountButton; + await element.tap(); + } } async tapImportAccountButton() { - await Gestures.waitAndTap(this.importAccountButton); + if (!this._device) { + await Gestures.waitAndTap(this.importAccountButton); + } else { + const element = await this.importAccountButton; + await element.tap(); + } + } + + async tapImportSrpButton() { + if (!this._device) { + await Gestures.waitAndTap(this.importSrpButton); + } else { + const element = await this.importSrpButton; + await element.tap(); + } + } + + async tapCreateSolanaAccountButton() { + if (!this._device) { + await Gestures.waitAndTap(this.createSolanaAccountButton); + } else { + const element = await this.createSolanaAccountButton; + await element.tap(); + } + } + + async tapCreateEthereumAccountButton() { + if (!this._device) { + await Gestures.waitAndTap(this.createEthereumAccountButton); + } else { + const element = await this.createEthereumAccountButton; + await element.tap(); + } + } + + async isVisible() { + const element = await this.importSrpButton; + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); } } diff --git a/wdio/screen-objects/Modals/AddNewHdAccountComponent.js b/wdio/screen-objects/Modals/AddNewHdAccountComponent.js new file mode 100644 index 00000000000..cc0c99b7b03 --- /dev/null +++ b/wdio/screen-objects/Modals/AddNewHdAccountComponent.js @@ -0,0 +1,82 @@ +import Gestures from '../../helpers/Gestures.js'; +import { AddNewAccountIds } from '../../../e2e/selectors/MultiSRP/AddHdAccount.selectors.js'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors.js'; + +class AddNewHdAccountComponent { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + + get container() { + if (!this._device) { + return Selectors.getXpathElementByResourceId(AddNewAccountIds.CONTAINER); + } else { + return AppwrightSelectors.getElementByID(this._device, AddNewAccountIds.CONTAINER); + } + } + + get srpSelector() { + if (!this._device) { + return Selectors.getXpathElementByResourceId(AddNewAccountIds.SRP_SELECTOR); + } else { + return AppwrightSelectors.getElementByID(this._device, AddNewAccountIds.SRP_SELECTOR); + } + } + + get cancelButton() { + if (!this._device) { + return Selectors.getXpathElementByResourceId(AddNewAccountIds.CANCEL); + } else { + return AppwrightSelectors.getElementByID(this._device, AddNewAccountIds.CANCEL); + } + } + + get confirmButton() { + if (!this._device) { + return Selectors.getXpathElementByResourceId(AddNewAccountIds.CONFIRM); + } else { + return AppwrightSelectors.getElementByID(this._device, AddNewAccountIds.CONFIRM); + } + } + + get nameInput() { + if (!this._device) { + return Selectors.getXpathElementByResourceId(AddNewAccountIds.NAME_INPUT); + } else { + return AppwrightSelectors.getElementByID(this._device, AddNewAccountIds.NAME_INPUT); + } + } + + async tapSrpSelector() { + if (!this._device) { + await Gestures.waitAndTap(this.srpSelector); + } else { + await this.srpSelector.tap(); + } + } + + async tapCancel() { + if (!this._device) { + await Gestures.waitAndTap(this.cancelButton); + } else { + await this.cancelButton.tap(); + } + } + + async tapConfirm() { + if (!this._device) { + await Gestures.waitAndTap(this.confirmButton, { + elemDescription: 'Confirm button on Add New HD Account screen', + }); + } else { + const confirmButton = await this.confirmButton; + await confirmButton.tap(); + } + } +} + +export default new AddNewHdAccountComponent(); diff --git a/wdio/screen-objects/Modals/NetworkEducationModal.js b/wdio/screen-objects/Modals/NetworkEducationModal.js index 0761983e951..a353c2339a1 100644 --- a/wdio/screen-objects/Modals/NetworkEducationModal.js +++ b/wdio/screen-objects/Modals/NetworkEducationModal.js @@ -5,22 +5,43 @@ import { NETWORK_EDUCATION_MODAL_NETWORK_NAME_ID, } from '../testIDs/Components/NetworkEducationModalTestIds'; import { NETWORK_EDUCATION_MODAL_CLOSE_BUTTON } from "../testIDs/Screens/NetworksScreen.testids"; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; class NetworkEducationModal { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get container() { - return Selectors.getXpathElementByResourceId(NETWORK_EDUCATION_MODAL_CONTAINER_ID); + if (!this._device) { + return Selectors.getXpathElementByResourceId(NETWORK_EDUCATION_MODAL_CONTAINER_ID); + } else { + return AppwrightSelectors.getElementByID(this._device, NETWORK_EDUCATION_MODAL_CONTAINER_ID); + } } get networkEducationCloseButton() { - return Selectors.getElementByPlatform( - NETWORK_EDUCATION_MODAL_CLOSE_BUTTON, - ); + if (!this._device) { + return Selectors.getElementByPlatform( + NETWORK_EDUCATION_MODAL_CLOSE_BUTTON, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, NETWORK_EDUCATION_MODAL_CLOSE_BUTTON); + } } get networkEducationNetworkName() { - return Selectors.getXpathElementByResourceId( - NETWORK_EDUCATION_MODAL_NETWORK_NAME_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + NETWORK_EDUCATION_MODAL_NETWORK_NAME_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, NETWORK_EDUCATION_MODAL_NETWORK_NAME_ID); + } } async waitForDisplayed() { @@ -29,7 +50,12 @@ class NetworkEducationModal { } async tapGotItButton() { - await Gestures.waitAndTap(this.networkEducationCloseButton); + if (!this._device) { + await Gestures.waitAndTap(this.networkEducationCloseButton); + } else { + const closeButton = await this.networkEducationCloseButton; + await closeButton.tap(); + } } async waitForDisappear() { @@ -38,7 +64,11 @@ class NetworkEducationModal { } async isNetworkEducationNetworkName(name) { - await expect(this.networkEducationNetworkName).toHaveText(name); + if (!this._device) { + await expect(this.networkEducationNetworkName).toHaveText(name); + } else { + await this.networkEducationNetworkName.toHaveText(name); + } } } diff --git a/wdio/screen-objects/Modals/SkipAccountSecurityModal.js b/wdio/screen-objects/Modals/SkipAccountSecurityModal.js index 111d5f90520..c66179a3be0 100644 --- a/wdio/screen-objects/Modals/SkipAccountSecurityModal.js +++ b/wdio/screen-objects/Modals/SkipAccountSecurityModal.js @@ -1,23 +1,46 @@ import Selectors from '../../helpers/Selectors'; import Gestures from '../../helpers/Gestures'; import { ChoosePasswordSelectorsIDs } from '../../../e2e/selectors/Onboarding/ChoosePassword.selectors'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; +import { SkipAccountSecurityModalSelectorsIDs } from '../../../e2e/selectors/Onboarding/SkipAccountSecurityModal.selectors'; +import { expect as appwrightExpect } from 'appwright'; class SkipAccountSecurityModal { + + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } get skipBackupText() { - return Selectors.getXpathElementByResourceId( - ChoosePasswordSelectorsIDs.ANDROID_I_UNDERSTAND_BUTTON_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + SkipAccountSecurityModalSelectorsIDs.ANDROID_SKIP_BACKUP_BUTTON_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, SkipAccountSecurityModalSelectorsIDs.ANDROID_SKIP_BACKUP_BUTTON_ID); + } } async proceedWithoutWalletSecure() { + if (!this._device) { const setTimeout = 2000; await driver.pause(setTimeout); await Gestures.waitAndTap(this.skipBackupText); await Gestures.tapTextByXpath('Skip'); + } else { + const button = await this.skipBackupText; + await button.tap(); + const skipButton = await AppwrightSelectors.getElementByID(this._device, 'Skip-button'); + await skipButton.tap(); + } } async isVisible() { - await expect(this.skipBackupText).toBeDisplayed(); + const element = await this.skipBackupText; + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); } } diff --git a/wdio/screen-objects/Modals/SolanaFeatureSheet.js b/wdio/screen-objects/Modals/SolanaFeatureSheet.js index 538df836383..db20cbe6a60 100644 --- a/wdio/screen-objects/Modals/SolanaFeatureSheet.js +++ b/wdio/screen-objects/Modals/SolanaFeatureSheet.js @@ -4,64 +4,128 @@ import { SolanaNewFeatureSheetSelectorsIDs } from '../../../e2e/selectors/wallet import { WalletViewSelectorsIDs } from '../../../e2e/selectors/wallet/WalletView.selectors'; import Selectors from '../../helpers/Selectors'; import Gestures from '../../helpers/Gestures'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; +import { expect as appwrightExpect } from 'appwright'; class SolanaNewFeatureSheet { + + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } // Sheet container get container() { - return Selectors.getXpathElementByResourceId(SolanaNewFeatureSheetSelectorsIDs.SOLANA_NEW_FEATURE_SHEET); + if (!this._device) { + return Selectors.getXpathElementByResourceId(SolanaNewFeatureSheetSelectorsIDs.SOLANA_NEW_FEATURE_SHEET); + } else { + return AppwrightSelectors.getElementByID(this._device, SolanaNewFeatureSheetSelectorsIDs.SOLANA_NEW_FEATURE_SHEET); + } } // Import Account button get importAccountButton() { - return Selectors.getXpathElementByResourceId(SolanaNewFeatureSheetSelectorsIDs.SOLANA_IMPORT_ACCOUNT_BUTTON); + if (!this._device) { + return Selectors.getXpathElementByResourceId(SolanaNewFeatureSheetSelectorsIDs.SOLANA_IMPORT_ACCOUNT_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, SolanaNewFeatureSheetSelectorsIDs.SOLANA_IMPORT_ACCOUNT_BUTTON); + } } get learnMoreButton() { - return Selectors.getXpathElementByResourceId(SolanaNewFeatureSheetSelectorsIDs.SOLANA_LEARN_MORE_BUTTON); + if (!this._device) { + return Selectors.getXpathElementByResourceId(SolanaNewFeatureSheetSelectorsIDs.SOLANA_LEARN_MORE_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, SolanaNewFeatureSheetSelectorsIDs.SOLANA_LEARN_MORE_BUTTON); + } } get notNowButton() { - return Selectors.getXpathElementByResourceId(SolanaNewFeatureSheetSelectorsIDs.SOLANA_NOT_NOW_BUTTON); + if (!this._device) { + return Selectors.getXpathElementByResourceId(SolanaNewFeatureSheetSelectorsIDs.SOLANA_NOT_NOW_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, SolanaNewFeatureSheetSelectorsIDs.SOLANA_NOT_NOW_BUTTON); + } } get addAccountButton() { - return Selectors.getXpathElementByResourceId(SolanaNewFeatureSheetSelectorsIDs.SOLANA_ADD_ACCOUNT_BUTTON_IN_SHEET); + if (!this._device) { + return Selectors.getXpathElementByResourceId(SolanaNewFeatureSheetSelectorsIDs.SOLANA_ADD_ACCOUNT_BUTTON_IN_SHEET); + } else { + return AppwrightSelectors.getElementByID(this._device, SolanaNewFeatureSheetSelectorsIDs.SOLANA_ADD_ACCOUNT_BUTTON_IN_SHEET); + } } get carouselLogo() { - return Selectors.getXpathElementByResourceId(WalletViewSelectorsIDs.CAROUSEL_SIXTH_SLIDE); + if (!this._device) { + return Selectors.getXpathElementByResourceId(WalletViewSelectorsIDs.CAROUSEL_SIXTH_SLIDE); + } else { + return AppwrightSelectors.getElementByID(this._device, WalletViewSelectorsIDs.CAROUSEL_SIXTH_SLIDE); + } } // Interaction methods async tapImportAccountButton() { - await Gestures.waitAndTap(this.importAccountButton); + if (!this._device) { + await Gestures.waitAndTap(this.importAccountButton); + } else { + await this.importAccountButton.tap(); + } } async tapViewAccountButton() { - await Gestures.waitAndTap(this.importAccountButton);//Create account testID is used for both create and view account actions + if (!this._device) { + await Gestures.waitAndTap(this.importAccountButton);//Create account testID is used for both create and view account actions + } else { + await this.importAccountButton.tap(); + } } async tapAddAccountButton() { - await Gestures.waitAndTap(this.addAccountButton); + if (!this._device) { + await Gestures.waitAndTap(this.addAccountButton); + } else { + await this.addAccountButton.tap(); + } } async tapLearnMoreButton() { - await Gestures.waitAndTap(this.learnMoreButton); + if (!this._device) { + await Gestures.waitAndTap(this.learnMoreButton); + } else { + await this.learnMoreButton.tap(); + } } async tapNotNowButton() { - await Gestures.waitAndTap(this.notNowButton); + if (!this._device) { + await Gestures.waitAndTap(this.notNowButton); + } else { + const button = await this.notNowButton; + await button.tap(); + } } async isVisible() { - await expect(this.container).toBeDisplayed(); + if (!this._device) { + await expect(this.importAccountButton).toBeDisplayed(); + } else { + const element = await this.importAccountButton; + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + } } async isNotVisible() { - await expect(this.container).not.toBeDisplayed(); + if (!this._device) { + await expect(this.container).not.toBeDisplayed(); + } else { + await expect(this.container).not.toBeVisible(); + } } } diff --git a/wdio/screen-objects/Modals/TabBarModal.js b/wdio/screen-objects/Modals/TabBarModal.js index c3159ee9b78..68727f8cbfc 100644 --- a/wdio/screen-objects/Modals/TabBarModal.js +++ b/wdio/screen-objects/Modals/TabBarModal.js @@ -1,64 +1,121 @@ import Selectors from '../../helpers/Selectors'; - +import AppwrightSelectors from '../../helpers/AppwrightSelectors.js'; import { TabBarSelectorIDs } from '../../../e2e/selectors/wallet/TabBar.selectors'; - import Gestures from '../../helpers/Gestures'; import BrowserScreen from '../BrowserObject/BrowserScreen'; +import { expect as appwrightExpect } from 'appwright'; class TabBarModal { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get walletButton() { - return Selectors.getXpathElementByResourceId(TabBarSelectorIDs.WALLET); + if (!this._device) { + return Selectors.getXpathElementByResourceId(TabBarSelectorIDs.WALLET); + } else { + return AppwrightSelectors.getElementByID(this._device, TabBarSelectorIDs.WALLET); + } } get browserButton() { - return Selectors.getXpathElementByResourceId(TabBarSelectorIDs.BROWSER); + if (!this._device) { + return Selectors.getXpathElementByResourceId(TabBarSelectorIDs.BROWSER); + } else { + return AppwrightSelectors.getElementByID(this._device, TabBarSelectorIDs.BROWSER); + } } get actionButton() { - return Selectors.getXpathElementByResourceId(TabBarSelectorIDs.ACTIONS); + if (!this._device) { + return Selectors.getXpathElementByResourceId(TabBarSelectorIDs.ACTIONS); + } else { + return AppwrightSelectors.getElementByID(this._device, TabBarSelectorIDs.ACTIONS); + } } get settingsButton() { - return Selectors.getXpathElementByResourceId(TabBarSelectorIDs.SETTING); + if (!this._device) { + return Selectors.getXpathElementByResourceId(TabBarSelectorIDs.SETTING); + } else { + return AppwrightSelectors.getElementByID(this._device, TabBarSelectorIDs.SETTING); + } } get activityButton() { - return Selectors.getXpathElementByResourceId(TabBarSelectorIDs.ACTIVITY); + if (!this._device) { + return Selectors.getXpathElementByResourceId(TabBarSelectorIDs.ACTIVITY); + } else { + return AppwrightSelectors.getElementByID(this._device, TabBarSelectorIDs.ACTIVITY); + } } async tapWalletButton() { - const walletButton = await this.walletButton; - await walletButton.waitForDisplayed(); + if (!this._device) { + const walletButton = await this.walletButton; + await walletButton.waitForDisplayed(); - const browserScreen = await BrowserScreen.container; - let isBrowserDisplayed = true; + const browserScreen = await BrowserScreen.container; + let isBrowserDisplayed = true; - while (isBrowserDisplayed) { - await walletButton.click(); - await driver.pause(3000); - isBrowserDisplayed = await browserScreen.isExisting(); + while (isBrowserDisplayed) { + await walletButton.click(); + await driver.pause(3000); + isBrowserDisplayed = await browserScreen.isExisting(); + } + } else { + const walletIcon = await this.walletButton; + await appwrightExpect(walletIcon).toBeVisible(); + + // For Appwright, we'll use a simpler approach + await walletIcon.tap(); } } async tapBrowserButton() { - await Gestures.waitAndTap(this.browserButton); + if (!this._device) { + await Gestures.waitAndTap(this.browserButton); + } else { + const browserIcon = await this.browserButton; + await browserIcon.tap(); + } } async tapActionButton() { - const actionButton = await this.actionButton; - await actionButton.waitForEnabled(); - await driver.pause(3000); - await Gestures.longPress(actionButton, 500); + if (!this._device) { + const actionButton = await this.actionButton; + await actionButton.waitForEnabled(); + await driver.pause(3000); + await Gestures.longPress(actionButton, 500); + } else { + const actionButton = await this.actionButton; + await appwrightExpect(actionButton).toBeVisible(); + await actionButton.tap(); + } } async tapSettingButton() { - await driver.pause(10000); - await Gestures.waitAndTap(this.settingsButton); + if (!this._device) { + await driver.pause(10000); + await Gestures.waitAndTap(this.settingsButton); + } else { + const settingsButton = await this.settingsButton; + await settingsButton.tap(); + } } async tapActivityButton() { - await Gestures.waitAndTap(this.activityButton); + if (!this._device) { + await Gestures.waitAndTap(this.activityButton); + } else { + const activityButton = await this.activityButton; + await activityButton.tap(); + } } } -export default new TabBarModal(); +export default new TabBarModal(); \ No newline at end of file diff --git a/wdio/screen-objects/Modals/TermOfUseScreen.js b/wdio/screen-objects/Modals/TermOfUseScreen.js index df8771ae644..4a2ffe34a28 100644 --- a/wdio/screen-objects/Modals/TermOfUseScreen.js +++ b/wdio/screen-objects/Modals/TermOfUseScreen.js @@ -1,33 +1,66 @@ import Selectors from '../../helpers/Selectors'; import Gestures from '../../helpers/Gestures'; import { TermsOfUseModalSelectorsIDs } from '../../../e2e/selectors/Onboarding/TermsOfUseModal.selectors'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; +import { expect as appwrightExpect } from 'appwright'; class TermOfUseScreen { + + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get container() { - return Selectors.getXpathElementByResourceId(TermsOfUseModalSelectorsIDs.CONTAINER); + if (!this._device) { + return Selectors.getXpathElementByResourceId(TermsOfUseModalSelectorsIDs.CONTAINER); + } else { + return AppwrightSelectors.getElementByID(this._device, TermsOfUseModalSelectorsIDs.CONTAINER); + } } get checkbox() { - return Selectors.getXpathElementByResourceId(TermsOfUseModalSelectorsIDs.CHECKBOX); + if (!this._device) { + return Selectors.getXpathElementByResourceId(TermsOfUseModalSelectorsIDs.CHECKBOX); + } else { + return AppwrightSelectors.getElementByID(this._device, TermsOfUseModalSelectorsIDs.CHECKBOX); + } } get scrollEndArrowButton() { - return Selectors.getXpathElementByResourceId( - TermsOfUseModalSelectorsIDs.SCROLL_ARROW_BUTTON, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId(TermsOfUseModalSelectorsIDs.SCROLL_ARROW_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, TermsOfUseModalSelectorsIDs.SCROLL_ARROW_BUTTON); + } } get acceptButton() { - return Selectors.getXpathElementByResourceId(TermsOfUseModalSelectorsIDs.ACCEPT_BUTTON); + if (!this._device) { + return Selectors.getXpathElementByResourceId(TermsOfUseModalSelectorsIDs.ACCEPT_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, TermsOfUseModalSelectorsIDs.ACCEPT_BUTTON); + } } get webview() { - return Selectors.getXpathElementByResourceId(TermsOfUseModalSelectorsIDs.WEBVIEW); + if (!this._device) { + return Selectors.getXpathElementByResourceId(TermsOfUseModalSelectorsIDs.WEBVIEW); + } else { + return AppwrightSelectors.getElementByID(this._device, TermsOfUseModalSelectorsIDs.WEBVIEW); + } } async isDisplayed() { - const container = await this.container; - await container.waitForDisplayed(); + if (!this._device) { + const container = await this.container; + await container.waitForDisplayed(); + } else { + await appwrightExpect(await this.container).toBeVisible(); + } } async textIsDisplayed() { @@ -43,11 +76,21 @@ class TermOfUseScreen { } async tapAgreeCheckBox() { - await Gestures.waitAndTap(this.checkbox); + if (!this._device) { + await Gestures.waitAndTap(this.checkbox); + } else { + const cb = await AppwrightSelectors.getElementByID(this._device, TermsOfUseModalSelectorsIDs.CHECKBOX); + await cb.tap(); + } } async tapScrollEndButton() { - await Gestures.waitAndTap(this.scrollEndArrowButton); + if (!this._device) { + await Gestures.waitAndTap(this.scrollEndArrowButton); + } else { + const button = await AppwrightSelectors.getElementByID(this._device, TermsOfUseModalSelectorsIDs.SCROLL_ARROW_BUTTON); + await button.tap(); + } } async acceptIsEnabled() { @@ -61,7 +104,12 @@ class TermOfUseScreen { } async tapAcceptButton() { - await Gestures.tap(this.acceptButton); + if (!this._device) { + await Gestures.tap(this.acceptButton); + } else { + const button = await AppwrightSelectors.getElementByID(this._device, TermsOfUseModalSelectorsIDs.ACCEPT_BUTTON); + await button.tap(); + } } } diff --git a/wdio/screen-objects/Modals/WalletAccountModal.js b/wdio/screen-objects/Modals/WalletAccountModal.js index a01bea88abd..6277009cf80 100644 --- a/wdio/screen-objects/Modals/WalletAccountModal.js +++ b/wdio/screen-objects/Modals/WalletAccountModal.js @@ -1,10 +1,24 @@ import { WalletViewSelectorsIDs } from '../../../e2e/selectors/wallet/WalletView.selectors'; import Selectors from '../../helpers/Selectors'; import Gestures from '../../helpers/Gestures'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; +import { expect as appwrightExpect } from 'appwright'; class WalletAccountModal { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get accountNameLabelText() { - return Selectors.getXpathElementByResourceId(WalletViewSelectorsIDs.ACCOUNT_NAME_LABEL_TEXT); + if (!this._device) { + return Selectors.getXpathElementByResourceId(WalletViewSelectorsIDs.ACCOUNT_NAME_LABEL_TEXT); + } else { + return AppwrightSelectors.getElementByID(this._device, WalletViewSelectorsIDs.ACCOUNT_NAME_LABEL_TEXT); + } } get accountNameLabelInput() { @@ -27,8 +41,23 @@ class WalletAccountModal { await expect(this.accountNameLabelInput).toBeDisplayed(); } + async isAccountNameLabelVisible(expectedName) { + if (!this._device) { + await expect(this.accountNameLabelText).toHaveText(expectedName); + } else { + const element = await AppwrightSelectors.getElementByText(this._device, expectedName); + await appwrightExpect(element).toBeVisible(); + } + } + async isAccountNameLabelEqualTo(expected) { - await expect(this.accountNameLabelText).toHaveText(expected); + if (!this._device) { + await expect(this.accountNameLabelText).toHaveText(expected); + } else { + const element = await this.accountNameLabelText; + const text = await element.getText(); + await appwrightExpect(text).toBe(expected); + } } async isAccountInputLabelEqualTo(expected) { diff --git a/wdio/screen-objects/Modals/WalletActionModal.js b/wdio/screen-objects/Modals/WalletActionModal.js index 98cd76f9a7a..271a37f23d8 100644 --- a/wdio/screen-objects/Modals/WalletActionModal.js +++ b/wdio/screen-objects/Modals/WalletActionModal.js @@ -1,23 +1,75 @@ import Selectors from '../../helpers/Selectors'; import Gestures from '../../helpers/Gestures'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; import { WalletActionsBottomSheetSelectorsIDs } from '../../../e2e/selectors/wallet/WalletActionsBottomSheet.selectors'; class WalletActionModal { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get sendButton() { - return Selectors.getElementByPlatform(WalletActionsBottomSheetSelectorsIDs.SEND_BUTTON); + if (!this._device) { + return Selectors.getElementByPlatform(WalletActionsBottomSheetSelectorsIDs.SEND_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, 'wallet-send-button'); + } } get receiveButton() { return Selectors.getElementByPlatform(WalletActionsBottomSheetSelectorsIDs.RECEIVE_BUTTON); } + get swapButton() { + if (!this._device) { + return Selectors.getElementByPlatform(WalletActionsBottomSheetSelectorsIDs.SWAP_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, WalletActionsBottomSheetSelectorsIDs.SWAP_BUTTON); + } + } + + get bridgeButton() { + if (!this._device) { + return Selectors.getElementByPlatform(WalletActionsBottomSheetSelectorsIDs.BRIDGE_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, WalletActionsBottomSheetSelectorsIDs.BRIDGE_BUTTON); + } + } + async tapSendButton() { - await Gestures.waitAndTap(this.sendButton); + if (!this._device) { + await Gestures.waitAndTap(this.sendButton); + } else { + const element = await this.sendButton; + await element.tap(); + } } async tapReceiveButton() { await Gestures.waitAndTap(this.receiveButton); } + + async tapSwapButton() { + if (!this._device) { + await Gestures.waitAndTap(this.swapButton); + } else { + const element = await this.swapButton; + await element.tap(); + } + } + + async tapBridgeButton() { + if (!this._device) { + await Gestures.waitAndTap(this.bridgeButton); + } else { + const element = await this.bridgeButton; + await element.tap(); + } + } } export default new WalletActionModal(); diff --git a/wdio/screen-objects/NetworksScreen.js b/wdio/screen-objects/NetworksScreen.js index f71a8fc3395..7a01418d04e 100644 --- a/wdio/screen-objects/NetworksScreen.js +++ b/wdio/screen-objects/NetworksScreen.js @@ -1,5 +1,7 @@ import Selectors from '../helpers/Selectors'; +import AppwrightSelectors from '../helpers/AppwrightSelectors'; import Gestures from '../helpers/Gestures'; +import { expect as appwrightExpect } from 'appwright'; import { ADD_NETWORK_BUTTON, BLOCK_EXPLORER_FIELD, @@ -12,215 +14,448 @@ import { import { NetworksViewSelectorsIDs } from '../../e2e/selectors/Settings/NetworksView.selectors'; class NetworksScreen { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get container() { - return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.NETWORK_CONTAINER); + if (!this._device) { + return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.NETWORK_CONTAINER); + } else { + return AppwrightSelectors.getElementByID(this._device, NetworksViewSelectorsIDs.NETWORK_CONTAINER); + } } get getPopularNetworksTab() { - return Selectors.getElementByPlatform('POPULAR'); + if (!this._device) { + return Selectors.getElementByPlatform('POPULAR'); + } else { + return AppwrightSelectors.getElementByText(this._device, 'POPULAR'); + } } get getCustomNetworks() { - return Selectors.getElementByPlatform('CUSTOM NETWORKS'); + if (!this._device) { + return Selectors.getElementByPlatform('CUSTOM NETWORKS'); + } else { + return AppwrightSelectors.getElementByText(this._device, 'CUSTOM NETWORKS'); + } } get addNetworkButton() { - return Selectors.getElementByPlatform(ADD_NETWORK_BUTTON); + if (!this._device) { + return Selectors.getElementByPlatform(ADD_NETWORK_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, ADD_NETWORK_BUTTON); + } } get addCustomNetworkButton() { - return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.ADD_CUSTOM_NETWORK_BUTTON); + if (!this._device) { + return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.ADD_CUSTOM_NETWORK_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, NetworksViewSelectorsIDs.ADD_CUSTOM_NETWORK_BUTTON); + } } get networkNameInputField() { - return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.NETWORK_NAME_INPUT); + if (!this._device) { + return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.NETWORK_NAME_INPUT); + } else { + return AppwrightSelectors.getElementByID(this._device, NetworksViewSelectorsIDs.NETWORK_NAME_INPUT); + } } get rpcURLInputField() { - return Selectors.getElementByPlatform(INPUT_RPC_URL_FIELD); + if (!this._device) { + return Selectors.getElementByPlatform(INPUT_RPC_URL_FIELD); + } else { + return AppwrightSelectors.getElementByID(this._device, INPUT_RPC_URL_FIELD); + } } get inputChainIdField() { - return Selectors.getElementByPlatform(INPUT_CHAIN_ID_FIELD); + if (!this._device) { + return Selectors.getElementByPlatform(INPUT_CHAIN_ID_FIELD); + } else { + return AppwrightSelectors.getElementByID(this._device, INPUT_CHAIN_ID_FIELD); + } } get inputNetworkSymbolField() { - return Selectors.getElementByPlatform(NETWORKS_SYMBOL_INPUT_FIELD); + if (!this._device) { + return Selectors.getElementByPlatform(NETWORKS_SYMBOL_INPUT_FIELD); + } else { + return AppwrightSelectors.getElementByID(this._device, NETWORKS_SYMBOL_INPUT_FIELD); + } } get blockExplorerInputField() { - return Selectors.getElementByPlatform(BLOCK_EXPLORER_FIELD); + if (!this._device) { + return Selectors.getElementByPlatform(BLOCK_EXPLORER_FIELD); + } else { + return AppwrightSelectors.getElementByID(this._device, BLOCK_EXPLORER_FIELD); + } } get removeNetworkButton() { - return Selectors.getElementByPlatform(REMOVE_NETWORK_BUTTON); + if (!this._device) { + return Selectors.getElementByPlatform(REMOVE_NETWORK_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, REMOVE_NETWORK_BUTTON); + } } get networkScreenBackButton() { - return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.BACK_ARROW_BUTTON); + if (!this._device) { + return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.BACK_ARROW_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, NetworksViewSelectorsIDs.BACK_ARROW_BUTTON); + } } get settingsPageAndroidBackButton() { - return Selectors.getElementByPlatform(NAV_ANDROID_BACK_BUTTON); + if (!this._device) { + return Selectors.getElementByPlatform(NAV_ANDROID_BACK_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, NAV_ANDROID_BACK_BUTTON); + } } get saveNetworkButton() { - return Selectors.getElementByPlatform(ADD_NETWORK_BUTTON); + if (!this._device) { + return Selectors.getElementByPlatform(ADD_NETWORK_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, ADD_NETWORK_BUTTON); + } } get closeNetworkScreen() { - return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.CLOSE_ICON); + if (!this._device) { + return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.CLOSE_ICON); + } else { + return AppwrightSelectors.getElementByID(this._device, NetworksViewSelectorsIDs.CLOSE_ICON); + } } async waitForDisplayed() { const element = await this.container; - await element.waitForDisplayed(); + if (!this._device) { + await element.waitForDisplayed(); + } else { + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + } } async isPopularNetworksTabVisible() { const element = await this.getPopularNetworksTab; - await element.waitForDisplayed(); + if (!this._device) { + await element.waitForDisplayed(); + } else { + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + } } async isCustomNetworksTabVisible() { const element = await this.getCustomNetworks; - await element.waitForDisplayed(); + if (!this._device) { + await element.waitForDisplayed(); + } else { + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + } } async selectNetwork(network) { - await Gestures.tapTextByXpath(network); + if (!this._device) { + await Gestures.tapTextByXpath(network); + } else { + const networkElement = await AppwrightSelectors.getElementByText(this._device, network); + await networkElement.tap(); + } } async tapAndHoldNetwork(network) { - await Gestures.tapTextByXpath(network); + if (!this._device) { + await Gestures.tapTextByXpath(network); + } else { + const networkElement = await AppwrightSelectors.getElementByText(this._device, network); + await networkElement.tap(); + } } async tapAddNetworkButton() { - await Gestures.waitAndTap(this.addNetworkButton); + const element = await this.addNetworkButton; + if (!this._device) { + await Gestures.waitAndTap(element); + } else { + await element.tap(); + } } async tapPopularNetworksTab() { - await Gestures.waitAndTap(this.getPopularNetworksTab); + const element = await this.getPopularNetworksTab; + if (!this._device) { + await Gestures.waitAndTap(element); + } else { + await element.tap(); + } } async tapCustomNetworksTab() { - await Gestures.waitAndTap(this.getCustomNetworks); + const element = await this.getCustomNetworks; + if (!this._device) { + await Gestures.waitAndTap(element); + } else { + await element.tap(); + } } async isNetworkNameVisible() { - await expect(this.networkNameInputField).toBeDisplayed(); + if (!this._device) { + await expect(this.networkNameInputField).toBeDisplayed(); + } else { + await appwrightExpect(this.networkNameInputField).toBeVisible({ timeout: 10000 }); + } } async typeIntoNetworkName(text) { - await Gestures.typeText(this.networkNameInputField, text); + const element = await this.networkNameInputField; + if (!this._device) { + await Gestures.typeText(element, text); + } else { + await element.fill(text); + } } async isRPCUrlFieldVisible() { - await expect(this.rpcURLInputField).toBeDisplayed(); + if (!this._device) { + await expect(this.rpcURLInputField).toBeDisplayed(); + } else { + await appwrightExpect(this.rpcURLInputField).toBeVisible({ timeout: 10000 }); + } } async typeIntoRPCURLField(text) { - await Gestures.typeText(this.rpcURLInputField, text); + const element = await this.rpcURLInputField; + if (!this._device) { + await Gestures.typeText(element, text); + } else { + await element.fill(text); + } } async isChainIDInputVisible() { - await expect(this.inputChainIdField).toBeDisplayed(); + if (!this._device) { + await expect(this.inputChainIdField).toBeDisplayed(); + } else { + await appwrightExpect(this.inputChainIdField).toBeVisible({ timeout: 10000 }); + } } async typeIntoCHAINIDInputField(text) { - await driver.touchPerform([{ action: 'tap', options: { x: 399, y: 400 } }]); // this eliminates some flakiness. The keyboard sometimes blocks the RPC url input - await Gestures.typeText(this.inputChainIdField, text); + if (!this._device) { + await driver.touchPerform([{ action: 'tap', options: { x: 399, y: 400 } }]); + await Gestures.typeText(this.inputChainIdField, text); + } else { + await this._device.tap({ x: 399, y: 400 }); + const element = await this.inputChainIdField; + await element.fill(text); + } } async isNetworkSymbolFieldVisible() { - await expect(this.inputNetworkSymbolField).toBeDisplayed(); + if (!this._device) { + await expect(this.inputNetworkSymbolField).toBeDisplayed(); + } else { + await appwrightExpect(this.inputNetworkSymbolField).toBeVisible({ timeout: 10000 }); + } } async typeIntoNetworkSymbol(text) { - await Gestures.typeText(this.inputNetworkSymbolField, text); + const element = await this.inputNetworkSymbolField; + if (!this._device) { + await Gestures.typeText(element, text); + } else { + await element.fill(text); + } } async isBlockExplorerUrlVisible() { - await expect(this.blockExplorerInputField).toBeDisplayed(); + if (!this._device) { + await expect(this.blockExplorerInputField).toBeDisplayed(); + } else { + await appwrightExpect(this.blockExplorerInputField).toBeVisible({ timeout: 10000 }); + } } async addButtonNetworkIsdisabled() { - await expect(this.addNetworkButton).toHaveAttrContaining( - 'clickable', - 'false', - ); + if (!this._device) { + await expect(this.addNetworkButton).toHaveAttrContaining( + 'clickable', + 'false', + ); + } else { + const element = await this.addNetworkButton; + await appwrightExpect(element).toHaveAttribute('clickable', 'false'); + } } async tapCustomAddButton() { - await Gestures.waitAndTap(this.addCustomNetworkButton); + const element = await this.addCustomNetworkButton; + if (!this._device) { + await Gestures.waitAndTap(element); + } else { + await element.tap(); + } } - async isDeleteNetworkButtonVisible() { - await expect(this.removeNetworkButton).toBeDisplayed(); + if (!this._device) { + await expect(this.removeNetworkButton).toBeDisplayed(); + } else { + await appwrightExpect(this.removeNetworkButton).toBeVisible({ timeout: 10000 }); + } } async tapDeleteNetworkButton() { - await Gestures.waitAndTap(this.removeNetworkButton); + const element = await this.removeNetworkButton; + if (!this._device) { + await Gestures.waitAndTap(element); + } else { + await element.tap(); + } } async tapSaveNetworkButton() { - await Gestures.tap(this.saveNetworkButton); + const element = await this.saveNetworkButton; + if (!this._device) { + await Gestures.tap(element); + } else { + await element.tap(); + } } async isSaveNetworkButtonVisible() { - await expect(this.saveNetworkButton).toBeDisplayed(); + if (!this._device) { + await expect(this.saveNetworkButton).toBeDisplayed(); + } else { + await appwrightExpect(this.saveNetworkButton).toBeVisible({ timeout: 10000 }); + } } async tapRemoveNetworkButton(text) { - await Gestures.tapTextByXpath(text); + if (!this._device) { + await Gestures.tapTextByXpath(text); + } else { + const element = await AppwrightSelectors.getElementByText(this._device, text); + await element.tap(); + } } async isButtonTextVisibleByXpath(text) { - expect(await Selectors.getXpathElementByText(text)).toBeDisplayed(); + if (!this._device) { + expect(await Selectors.getXpathElementByText(text)).toBeDisplayed(); + } else { + const element = await AppwrightSelectors.getElementByText(this._device, text); + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + } } async isNetworkRemoved(network) { - const element = await Selectors.getXpathElementByText(network); - await element.waitForExist({ reverse: true }); + if (!this._device) { + const element = await Selectors.getXpathElementByText(network); + await element.waitForExist({ reverse: true }); + } else { + const element = await AppwrightSelectors.getElementByText(this._device, network); + await appwrightExpect(element).not.toBeVisible({ timeout: 10000 }); + } } async tapOnNetwork(network) { - await Gestures.tapTextByXpath(network); + if (!this._device) { + await Gestures.tapTextByXpath(network); + } else { + const element = await AppwrightSelectors.getElementByText(this._device, network); + await element.tap(); + } } async isNetworkVisible(network) { - const networkElement = await Selectors.getXpathElementByText(network); - await networkElement.waitForDisplayed(); + if (!this._device) { + const networkElement = await Selectors.getXpathElementByText(network); + await networkElement.waitForDisplayed(); + } else { + const networkElement = await AppwrightSelectors.getElementByText(this._device, network); + await appwrightExpect(networkElement).toBeVisible({ timeout: 10000 }); + } } async isNetworkNotVisible(text) { - const networkElement = await Selectors.getXpathElementByText(text); - await networkElement.waitForExist({ reverse: true }); + if (!this._device) { + const networkElement = await Selectors.getXpathElementByText(text); + await networkElement.waitForExist({ reverse: true }); + } else { + const networkElement = await AppwrightSelectors.getElementByText(this._device, text); + await appwrightExpect(networkElement).not.toBeVisible({ timeout: 10000 }); + } } async tapOptionInSettings(text) { - await Gestures.tapTextByXpath(text); + if (!this._device) { + await Gestures.tapTextByXpath(text); + } else { + const element = await AppwrightSelectors.getElementByText(this._device, text); + await element.tap(); + } } async isNetworknameDisplayed(network) { - expect(await Selectors.getXpathElementByText(network)).toBeDisplayed(); + if (!this._device) { + expect(await Selectors.getXpathElementByText(network)).toBeDisplayed(); + } else { + const element = await AppwrightSelectors.getElementByText(this._device, network); + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + } } async tapBackButtonInNewScreen() { - await Gestures.waitAndTap(this.networkScreenBackButton); + const element = await this.networkScreenBackButton; + if (!this._device) { + await Gestures.waitAndTap(element); + } else { + await element.tap(); + } } async tapBackButtonInSettingsScreen() { - await Gestures.waitAndTap(this.settingsPageAndroidBackButton); + const element = await this.settingsPageAndroidBackButton; + if (!this._device) { + await Gestures.waitAndTap(element); + } else { + await element.tap(); + } } async tapCloseNetworkScreen() { - await Gestures.waitAndTap(this.closeNetworkScreen); + const element = await this.closeNetworkScreen; + if (!this._device) { + await Gestures.waitAndTap(element); + } else { + await element.tap(); + } } async tapBackButton() { - await Gestures.waitAndTap(this.networkScreenBackButton); + const element = await this.networkScreenBackButton; + if (!this._device) { + await Gestures.waitAndTap(element); + } else { + await element.tap(); + } } } diff --git a/wdio/screen-objects/Onboarding/CreateNewWalletScreen.js b/wdio/screen-objects/Onboarding/CreateNewWalletScreen.js index a8766213ef6..20314f82643 100644 --- a/wdio/screen-objects/Onboarding/CreateNewWalletScreen.js +++ b/wdio/screen-objects/Onboarding/CreateNewWalletScreen.js @@ -9,55 +9,107 @@ import { } from '../testIDs/Screens/WalletSetupScreen.testIds'; import Gestures from '../../helpers/Gestures'; import Selectors from '../../helpers/Selectors'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; +import { expect } from 'appwright'; + +class CreateNewWalletScreen{ + + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } -class CreateNewWalletScreen { get description() { - return Selectors.getXpathElementByResourceId( - WALLET_SETUP_SCREEN_DESCRIPTION_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + WALLET_SETUP_SCREEN_DESCRIPTION_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, WALLET_SETUP_SCREEN_DESCRIPTION_ID); + } } get secureWalletScreen() { - return Selectors.getXpathElementByResourceId( - PROTECT_YOUR_WALLET_CONTAINER_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + PROTECT_YOUR_WALLET_CONTAINER_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, PROTECT_YOUR_WALLET_CONTAINER_ID); + } } get remindMeLaterButton() { - return Selectors.getXpathElementByResourceId(REMIND_LATER_BUTTON_ID); + if (!this._device) { + return Selectors.getXpathElementByResourceId(REMIND_LATER_BUTTON_ID); + } else { + return AppwrightSelectors.getElementByID(this._device, REMIND_LATER_BUTTON_ID); + } } get newWalletPasswordField() { - return Selectors.getXpathElementByResourceId( - CREATE_PASSWORD_INPUT_FIRST_FIELD, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + CREATE_PASSWORD_INPUT_FIRST_FIELD, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, CREATE_PASSWORD_INPUT_FIRST_FIELD); + } } get newWalletPasswordConfirm() { - return Selectors.getXpathElementByResourceId( - CONFIRM_PASSWORD_INPUT_FIRST_FIELD, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + CONFIRM_PASSWORD_INPUT_FIRST_FIELD, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, CONFIRM_PASSWORD_INPUT_FIRST_FIELD); + } } get termsAndConditionCheckBox() { - return Selectors.getXpathElementByResourceId(I_UNDERSTAND_BUTTON_ID); + if (!this._device) { + return Selectors.getXpathElementByResourceId(I_UNDERSTAND_BUTTON_ID); + } else { + return AppwrightSelectors.getElementByID(this._device, I_UNDERSTAND_BUTTON_ID); + } } get newWalletSubmitButton() { - return Selectors.getXpathByContentDesc(SUBMIT_BUTTON); + if (!this._device) { + return Selectors.getXpathByContentDesc(SUBMIT_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, SUBMIT_BUTTON); + } } async inputPasswordInFirstField(firstPassword) { - await Gestures.typeText(this.newWalletPasswordField, firstPassword); + if (!this._device) { + await Gestures.typeText(this.newWalletPasswordField, firstPassword); + } else { + const field = await this.newWalletPasswordField; + await field.fill(firstPassword); + } } async inputConfirmPasswordField(secondPassword) { - await Gestures.typeText(this.newWalletPasswordConfirm, secondPassword); - await driver.hideKeyboard(); - await Gestures.waitAndTap(this.termsAndConditionCheckBox); - // await Gestures.waitAndTap(this.screenTitle); - await driver.pause(2500); - // await Gestures.tap('Create password'); + if (!this._device) { + await Gestures.typeText(this.newWalletPasswordConfirm, secondPassword); + await driver.hideKeyboard(); + await Gestures.waitAndTap(this.termsAndConditionCheckBox); + // await Gestures.waitAndTap(this.screenTitle); + await driver.pause(2500); + // await Gestures.tap('Create password'); + } else { + const field = await this.newWalletPasswordConfirm; + await field.fill(secondPassword); + const checkbox = await this.termsAndConditionCheckBox; + await checkbox.tap(); + + } } async inputConfirmResetPasswordField(secondPassword) { @@ -66,11 +118,21 @@ class CreateNewWalletScreen { } async tapSubmitButton() { - await Gestures.waitAndTap(this.newWalletSubmitButton); + if (!this._device) { + await Gestures.waitAndTap(this.newWalletSubmitButton); + } else { + const button = await this.newWalletSubmitButton; + await button.tap(); + } } async tapRemindMeLater() { - await Gestures.waitAndTap(this.remindMeLaterButton); + if (!this._device) { + await Gestures.waitAndTap(this.remindMeLaterButton); + } else { + const button = await this.remindMeLaterButton; + await button.tap(); + } } async isAccountCreated() { @@ -79,7 +141,12 @@ class CreateNewWalletScreen { } async isNewAccountScreenFieldsVisible() { - await expect(this.newWalletPasswordField).toBeDisplayed(); + if (!this._device) { + await expect(this.newWalletPasswordField).toBeVisible(); + } else { + const element = await this.newWalletPasswordField; + await expect(element).toBeVisible(); + } } async isNotVisible() { diff --git a/wdio/screen-objects/Onboarding/CreatePasswordScreen.js b/wdio/screen-objects/Onboarding/CreatePasswordScreen.js index 6750bbf5c00..0f78fa411db 100644 --- a/wdio/screen-objects/Onboarding/CreatePasswordScreen.js +++ b/wdio/screen-objects/Onboarding/CreatePasswordScreen.js @@ -2,56 +2,116 @@ import Selectors from '../../helpers/Selectors'; import Gestures from '../../helpers/Gestures'; import { ChoosePasswordSelectorsIDs } from '../../../e2e/selectors/Onboarding/ChoosePassword.selectors'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; +import { CONFIRM_PASSWORD_INPUT_FIRST_FIELD, CREATE_PASSWORD_INPUT_FIRST_FIELD } from '../testIDs/Screens/WalletSetupScreen.testIds'; +import { expect as appwrightExpect } from 'appwright'; class CreatePasswordScreen { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get container() { - return Selectors.getXpathElementByResourceId(ChoosePasswordSelectorsIDs.CONTAINER_ID); + if (!this._device) { + return Selectors.getXpathElementByResourceId(ChoosePasswordSelectorsIDs.CONTAINER_ID); + } else { + return AppwrightSelectors.getElementByID(this._device, ChoosePasswordSelectorsIDs.CONTAINER_ID); + } } get newPasswordInput() { - return Selectors.getXpathElementByResourceId( - ChoosePasswordSelectorsIDs.NEW_PASSWORD_INPUT_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + ChoosePasswordSelectorsIDs.NEW_PASSWORD_INPUT_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, CREATE_PASSWORD_INPUT_FIRST_FIELD); + } } get confirmPasswordInput() { - return Selectors.getXpathElementByResourceId( - ChoosePasswordSelectorsIDs.CONFIRM_PASSWORD_INPUT_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + ChoosePasswordSelectorsIDs.CONFIRM_PASSWORD_INPUT_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, CONFIRM_PASSWORD_INPUT_FIRST_FIELD); + } } get iUnderstandCheckbox() { - return Selectors.getXpathElementByResourceId( - ChoosePasswordSelectorsIDs.I_UNDERSTAND_CHECKBOX_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + ChoosePasswordSelectorsIDs.I_UNDERSTAND_CHECKBOX_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, ChoosePasswordSelectorsIDs.I_UNDERSTAND_CHECKBOX_ID); + } } get iUnderstandCheckboxNewWallet() { - return Selectors.getXpathElementByResourceId( - ChoosePasswordSelectorsIDs.I_UNDERSTAND_CHECKBOX_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + ChoosePasswordSelectorsIDs.I_UNDERSTAND_CHECKBOX_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, ChoosePasswordSelectorsIDs.I_UNDERSTAND_CHECKBOX_ID); + } } get submitButton() { - return Selectors.getXpathElementByResourceId( - ChoosePasswordSelectorsIDs.SUBMIT_BUTTON_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + ChoosePasswordSelectorsIDs.SUBMIT_BUTTON_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, ChoosePasswordSelectorsIDs.SUBMIT_BUTTON_ID); + } } async enterPassword(password) { - await Gestures.setValueWithoutTap(this.newPasswordInput, password); + if (!this._device) { + await Gestures.setValueWithoutTap(this.newPasswordInput, password); + } else { + const element = await this.newPasswordInput; + await element.fill(password); + } } async reEnterPassword(password) { - await Gestures.setValueWithoutTap(this.confirmPasswordInput, password); + if (!this._device) { + await Gestures.setValueWithoutTap(this.confirmPasswordInput, password); + } else { + const element = await this.confirmPasswordInput; + await element.fill(password); + } } async tapIUnderstandCheckBox() { - await Gestures.waitAndTap(this.iUnderstandCheckbox); + if (!this._device) { + await Gestures.waitAndTap(this.iUnderstandCheckbox); + } else { + const element = await this.iUnderstandCheckbox; + await element.tap(); + } } async tapCreatePasswordButton() { - await Gestures.waitAndTap(this.submitButton); + if (!this._device) { + await Gestures.waitAndTap(this.submitButton); + } else { + const element = await this.submitButton; + await element.tap(); + } + } + + async isVisible() { + const element = await this.newPasswordInput; + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); } } diff --git a/wdio/screen-objects/Onboarding/ImportFromSeedScreen.js b/wdio/screen-objects/Onboarding/ImportFromSeedScreen.js index 4273e70fdc4..a0661327a4f 100644 --- a/wdio/screen-objects/Onboarding/ImportFromSeedScreen.js +++ b/wdio/screen-objects/Onboarding/ImportFromSeedScreen.js @@ -1,38 +1,158 @@ import Selectors from '../../helpers/Selectors'; import Gestures from '../../helpers/Gestures'; import { ImportFromSeedSelectorsIDs } from '../../../e2e/selectors/Onboarding/ImportFromSeed.selectors'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; +import { expect as appwrightExpect, ScrollDirection } from 'appwright'; class ImportFromSeedScreen { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get screenTitle() { - return Selectors.getXpathElementByResourceId( - ImportFromSeedSelectorsIDs.SCREEN_TITLE_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + ImportFromSeedSelectorsIDs.SCREEN_TITLE_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, ImportFromSeedSelectorsIDs.SCREEN_TITLE_ID); + } } get seedPhraseInput() { - return Selectors.getXpathElementByResourceId( - ImportFromSeedSelectorsIDs.SEED_PHRASE_INPUT_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + ImportFromSeedSelectorsIDs.SEED_PHRASE_INPUT_ID, + ); + } else { + if (AppwrightSelectors.isAndroid(this._device)) { + return AppwrightSelectors.getElementByID(this._device, ImportFromSeedSelectorsIDs.SEED_PHRASE_INPUT_ID); + } else { + return AppwrightSelectors.getElementByXpath(this._device, '//XCUIElementTypeOther[@name="textfield"]'); + } + } } get continueButton() { - return Selectors.getXpathElementByResourceId(ImportFromSeedSelectorsIDs.CONTINUE_BUTTON_ID); + if (!this._device) { + return Selectors.getXpathElementByResourceId(ImportFromSeedSelectorsIDs.CONTINUE_BUTTON_ID); + } else { + return AppwrightSelectors.getElementByID(this._device, ImportFromSeedSelectorsIDs.CONTINUE_BUTTON_ID); + } } - async isScreenTitleVisible() { - await expect(this.screenTitle).toBeDisplayed(); + + async inputOfIndex(srpIndex, onboarding = true) { + if (onboarding) { + if (AppwrightSelectors.isAndroid(this._device)) { + return `import-from-seed-screen-seed-phrase-input-id_${String(srpIndex)}`; + } else { + return `//XCUIElementTypeOther[@name="textfield" and @label="${String(srpIndex)}."]`; + + } + } + else { + return `srp-input-word-${String(srpIndex)}`; + } + } + + + async isScreenTitleVisible(onboarding = true) { + if (!this._device) { + await expect(this.screenTitle).toBeDisplayed(); + } else { + if (onboarding) { + const element = await this.screenTitle; + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + } else { + const element = await AppwrightSelectors.getElementByText(this.device, 'Import Secret Recovery Phrase'); + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + } + } } - async typeSecretRecoveryPhrase(phrase) { - await Gestures.setValueWithoutTap(this.seedPhraseInput, phrase); + async typeSecretRecoveryPhrase(phrase, onboarding = true) { + const phraseArray = phrase.split(' '); + if (!this._device) { + await Gestures.setValueWithoutTap(this.seedPhraseInput, phrase); + } else { + if (onboarding) { + const firstWord = phraseArray[0]; + const lastWord = phraseArray[phraseArray.length - 1]; + const form = await this.seedPhraseInput + await form.fill(`${firstWord} `); + for (let i = 1; i < phraseArray.length - 1; i++) { + let index = i; + if (AppwrightSelectors.isIOS(this._device)) { // SRP fields on iOS starts from 1 + index = i + 1; + } + + const wordElement = await this.inputOfIndex(index); + let input; + if (AppwrightSelectors.isAndroid(this._device)) + input = await AppwrightSelectors.getElementByID(this.device, wordElement); + else + input = await AppwrightSelectors.getElementByXpath(this.device, wordElement); + await input.fill(`${phraseArray[i]} `); + } + const wordElement = await this.inputOfIndex(AppwrightSelectors.isAndroid(this._device) ? phraseArray.length - 1 : phraseArray.length); + const lastInput = AppwrightSelectors.isAndroid(this._device) ? await AppwrightSelectors.getElementByID(this.device, wordElement) : await AppwrightSelectors.getElementByXpath(this.device, wordElement); + await lastInput.fill(lastWord); + } else { + for (let i = 1; i <= phraseArray.length; i++) { + const wordElement = await this.inputOfIndex(i, false); + const input = await AppwrightSelectors.getElementByID(this.device, wordElement); + await input.fill(`${phraseArray[i-1]} `); + } + } + } } - async tapContinueButton() { - await Gestures.waitAndTap(this.continueButton); + async tapContinueButton(onboarding = true) { + if (onboarding) { + if (!this._device) { + await Gestures.waitAndTap(this.continueButton); + } else { + const element = await this.continueButton; + await AppwrightSelectors.hideKeyboard(this.device); + await element.tap(); + } + } else { + if (!this._device) { + await Gestures.waitAndTap(this.continueButton); + } else { + const isIOS = await AppwrightSelectors.isIOS(this.device); + if (isIOS) { + const element = await AppwrightSelectors.getElementByID(this.device, 'import-button'); + await element.tap(); + } else { + const element = await AppwrightSelectors.getElementByText(this.device, 'Continue'); + await element.tap(); + } + } + } } - async tapImportScreenTitleToDismissKeyboard() { - await Gestures.waitAndTap(this.screenTitle); + async tapImportScreenTitleToDismissKeyboard(onboarding = true) { + if (onboarding) { + if (!this._device) { + await Gestures.waitAndTap(this.screenTitle); + } else { + const element = await this.screenTitle; + await element.tap(); + } + } else { + if (!this._device) { + await Gestures.waitAndTap(this.screenTitle); + } else { + const element = await AppwrightSelectors.getElementByText(this.device, 'Import Secret Recovery Phrase'); + await element.tap(); + } + } } } diff --git a/wdio/screen-objects/Onboarding/MetaMetricsScreen.js b/wdio/screen-objects/Onboarding/MetaMetricsScreen.js index 00a6852b35a..d7bc99c15cd 100644 --- a/wdio/screen-objects/Onboarding/MetaMetricsScreen.js +++ b/wdio/screen-objects/Onboarding/MetaMetricsScreen.js @@ -6,42 +6,79 @@ import { } from '../testIDs/Screens/OptinMetricsScreen.testIds'; import Selectors from '../../helpers/Selectors'; import { MetaMetricsOptInSelectorsIDs } from '../../../e2e/selectors/Onboarding/MetaMetricsOptIn.selectors'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; +import { expect as appwrightExpect } from 'appwright'; + +class MetaMetricsScreen{ + + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } -class MetaMetricsScreen { get screenTitle() { - return Selectors.getXpathElementByResourceId(MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_TITLE_ID); + if (!this._device) { + return Selectors.getXpathElementByResourceId(MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_TITLE_ID); + } else { + return AppwrightSelectors.getElementByID(this._device, MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_TITLE_ID); + } } get iAgreeButton() { - return Selectors.getXpathElementByResourceId( - MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_I_AGREE_BUTTON_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_I_AGREE_BUTTON_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_I_AGREE_BUTTON_ID); + } } get noThanksButton() { - return Selectors.getXpathElementByResourceId( - MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_NO_THANKS_BUTTON_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_NO_THANKS_BUTTON_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_NO_THANKS_BUTTON_ID); + } } async isScreenTitleVisible() { - await expect(this.screenTitle).toBeDisplayed(); + if (!this._device) { + await expect(this.screenTitle).toBeDisplayed(); + } else { + const element = await this.screenTitle; + await appwrightExpect(element).toBeVisible({ timeout: 30000 }); // Some devices take longer to transition to this screen + } } async tapIAgreeButton() { - const element = await this.iAgreeButton; - await element.waitForDisplayed(); - await Gestures.swipeUp(0.5); - await Gestures.swipeUp(0.5); - await element.waitForEnabled(); - await Gestures.waitAndTap(this.iAgreeButton); + if (!this._device) { + const element = await this.iAgreeButton; + await element.waitForDisplayed(); + await Gestures.swipeUp(0.5); + await Gestures.swipeUp(0.5); + await element.waitForEnabled(); + await Gestures.waitAndTap(this.iAgreeButton); + } else { + const button = await this.iAgreeButton; + await button.tap(); + } } async tapNoThanksButton() { - await Gestures.swipeUp(0.5); - const element = await this.iAgreeButton; - await element.waitForEnabled(); - await Gestures.waitAndTap(this.noThanksButton); + if (!this._device) { + await Gestures.swipeUp(0.5); + const element = await this.iAgreeButton; + await element.waitForEnabled(); + await Gestures.waitAndTap(this.noThanksButton); + } else { + await this.noThanksButton.tap(); + } } } diff --git a/wdio/screen-objects/Onboarding/OnboardingCarousel.js b/wdio/screen-objects/Onboarding/OnboardingCarousel.js index 87405df1b91..2e9976e84ba 100644 --- a/wdio/screen-objects/Onboarding/OnboardingCarousel.js +++ b/wdio/screen-objects/Onboarding/OnboardingCarousel.js @@ -6,34 +6,60 @@ import { SPLASH_SCREEN_METAMASK_ANIMATION_ID } from '../testIDs/Components/MetaM import { OnboardingCarouselSelectorIDs } from '../../../e2e/selectors/Onboarding/OnboardingCarousel.selectors' import Gestures from '../../helpers/Gestures'; import Selectors from '../../helpers/Selectors'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; +import { expect as appwrightExpect } from 'appwright'; -class WelcomeScreen { +class WelcomeScreen { constructor() { this.CAROUSEL_RECTANGLES = null; } + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get splashScreenMetamaskAnimationId() { - return Selectors.getXpathElementByResourceId( - SPLASH_SCREEN_METAMASK_ANIMATION_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + SPLASH_SCREEN_METAMASK_ANIMATION_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, SPLASH_SCREEN_METAMASK_ANIMATION_ID); + } } get getStartedButton() { - return Selectors.getXpathElementByResourceId( - OnboardingCarouselSelectorIDs.GET_STARTED_BUTTON_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + OnboardingCarouselSelectorIDs.GET_STARTED_BUTTON_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, OnboardingCarouselSelectorIDs.GET_STARTED_BUTTON_ID); + } } get screen() { - return Selectors.getXpathElementByResourceId( - OnboardingCarouselSelectorIDs.CONTAINER_ID, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + OnboardingCarouselSelectorIDs.CONTAINER_ID, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, OnboardingCarouselSelectorIDs.CONTAINER_ID); + } } async getLaunchDuration() { - return await Selectors.getXpathElementByResourceId( - OnboardingCarouselSelectorIDs.APP_START_TIME_ID, - ); + if (!this._device) { + return await Selectors.getXpathElementByResourceId( + OnboardingCarouselSelectorIDs.APP_START_TIME_ID, + ); + } else { + return await AppwrightSelectors.getElementByID(this._device, OnboardingCarouselSelectorIDs.APP_START_TIME_ID); + } } async isGetLaunchDurationDisplayed() { @@ -61,11 +87,21 @@ class WelcomeScreen { } async isScreenDisplayed() { - expect(this.screen).toBeDisplayed(); + if (!this._device) { + expect(this.screen).toBeDisplayed(); + } else { + const element = await this.screen; + await appwrightExpect(element).toBeVisible(); + } } async isGetStartedButtonDisplayed() { - expect(this.getStartedButton).toBeDisplayed(); + if (!this._device) { + expect(this.getStartedButton).toBeDisplayed(); + } else { + const element = await this.getStartedButton; + await appwrightExpect(element).toBeVisible(); + } } async waitForSplashAnimationToNotExit() { @@ -111,17 +147,27 @@ class WelcomeScreen { } async clickGetStartedButton() { - const element = await this.screen; - let screenExist = await element.isExisting(); - - await Gestures.waitAndTap(this.getStartedButton); - await driver.pause(7000); - screenExist = await element.isExisting(); + if (!this._device) { + const element = await this.screen; + let screenExist = await element.isExisting(); + + await Gestures.waitAndTap(this.getStartedButton); + await driver.pause(7000); + screenExist = await element.isExisting(); + } else { + const button = await AppwrightSelectors.getElementByID(this._device, OnboardingCarouselSelectorIDs.GET_STARTED_BUTTON_ID); + await button.tap(); + } } async waitForScreenToDisplay() { - const element = await this.screen; - await element.waitForDisplayed({ interval: 500 }); + if (!this._device) { + const element = await this.screen; + await element.waitForDisplayed({ interval: 500 }); + } else { + const element = await this.screen; + await appwrightExpect(element).toBeVisible(); + } } } diff --git a/wdio/screen-objects/Onboarding/OnboardingScreen.js b/wdio/screen-objects/Onboarding/OnboardingScreen.js index b124a0c5f0d..5a9e68ac0d2 100644 --- a/wdio/screen-objects/Onboarding/OnboardingScreen.js +++ b/wdio/screen-objects/Onboarding/OnboardingScreen.js @@ -1,10 +1,25 @@ import Gestures from '../../helpers/Gestures'; import Selectors from '../../helpers/Selectors'; import { OnboardingSelectorIDs } from '../../../e2e/selectors/Onboarding/Onboarding.selectors'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; +import { expect as appwrightExpect } from 'appwright'; class OnBoardingScreen { + + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get title() { - return Selectors.getXpathElementByResourceId(OnboardingSelectorIDs.SCREEN_TITLE); + if (!this._device) { + return Selectors.getXpathElementByResourceId(OnboardingSelectorIDs.SCREEN_TITLE); + } else { + return AppwrightSelectors.getElementByID(this._device, OnboardingSelectorIDs.SCREEN_TITLE); + } } get description() { @@ -14,27 +29,50 @@ class OnBoardingScreen { } get createNewWalletButton() { - return Selectors.getXpathElementByResourceId( - OnboardingSelectorIDs.NEW_WALLET_BUTTON, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + OnboardingSelectorIDs.NEW_WALLET_BUTTON, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, OnboardingSelectorIDs.NEW_WALLET_BUTTON); + } } get existingWalletButton() { - return Selectors.getXpathElementByResourceId( - OnboardingSelectorIDs.EXISTING_WALLET_BUTTON, - ); + if (!this._device) { + return Selectors.getXpathElementByResourceId( + OnboardingSelectorIDs.EXISTING_WALLET_BUTTON, + ); + } else { + return AppwrightSelectors.getElementByID(this._device, OnboardingSelectorIDs.EXISTING_WALLET_BUTTON); + } } async isScreenTitleVisible() { - await expect(this.title).toBeDisplayed(); + if (!this._device) { + await expect(this.title).toBeDisplayed(); + } else { + const element = await this.title; + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + } } async tapHaveAnExistingWallet() { - await Gestures.waitAndTap(this.existingWalletButton); + if (!this._device) { + await Gestures.waitAndTap(this.existingWalletButton); + } else { + const button = await this.existingWalletButton; + await button.tap(); + } } async tapCreateNewWalletButton() { - await Gestures.waitAndTap(this.createNewWalletButton); + if (!this._device) { + await Gestures.waitAndTap(this.createNewWalletButton); + } else { + const button = await this.createNewWalletButton; + await button.tap(); + } } } diff --git a/wdio/screen-objects/Onboarding/OnboardingSheet.js b/wdio/screen-objects/Onboarding/OnboardingSheet.js index ad5ef02cc49..c1803c2d7df 100644 --- a/wdio/screen-objects/Onboarding/OnboardingSheet.js +++ b/wdio/screen-objects/Onboarding/OnboardingSheet.js @@ -1,8 +1,19 @@ import Gestures from '../../helpers/Gestures'; import Selectors from '../../helpers/Selectors'; import { OnboardingSheetSelectorIDs } from '../../../e2e/selectors/Onboarding/OnboardingSheet.selectors'; +import AppwrightSelectors from '../../helpers/AppwrightSelectors'; +import { expect as appwrightExpect } from 'appwright'; class OnboardingSheet { + + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get container() { return Selectors.getXpathElementByResourceId(OnboardingSheetSelectorIDs.CONTAINER_ID); } @@ -16,7 +27,11 @@ class OnboardingSheet { } get importSeedButton() { - return Selectors.getXpathElementByResourceId(OnboardingSheetSelectorIDs.IMPORT_SEED_BUTTON); + if (!this._device) { + return Selectors.getXpathElementByResourceId(OnboardingSheetSelectorIDs.IMPORT_SEED_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, OnboardingSheetSelectorIDs.IMPORT_SEED_BUTTON); + } } async tapGoogleLoginButton() { @@ -28,9 +43,18 @@ class OnboardingSheet { } async tapImportSeedButton() { - await Gestures.waitAndTap(this.importSeedButton); + if (!this.device) { + await Gestures.waitAndTap(this.importSeedButton); + } else { + const button = await this.importSeedButton; + await button.tap(); + } } + async isVisible() { + const element = await this.importSeedButton; + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + } } export default new OnboardingSheet(); diff --git a/wdio/screen-objects/OnboardingSucessScreen.js b/wdio/screen-objects/OnboardingSucessScreen.js index e3c8b8f1f6f..9f07e32c6ad 100644 --- a/wdio/screen-objects/OnboardingSucessScreen.js +++ b/wdio/screen-objects/OnboardingSucessScreen.js @@ -1,15 +1,39 @@ import { OnboardingSuccessSelectorIDs } from '../../e2e/selectors/Onboarding/OnboardingSuccess.selectors'; import Selectors from '../helpers/Selectors'; import Gestures from '../helpers/Gestures'; +import AppwrightSelectors from '../helpers/AppwrightSelectors'; +import { expect as appwrightExpect } from 'appwright'; + class OnboardingSuccessView { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } get doneButton() { - return Selectors.getXpathElementByResourceId(OnboardingSuccessSelectorIDs.DONE_BUTTON); + if (!this._device) { + return Selectors.getXpathElementByResourceId(OnboardingSuccessSelectorIDs.DONE_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, OnboardingSuccessSelectorIDs.DONE_BUTTON); + } + } + + async isVisible() { + const element = await this.doneButton; + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); } async tapDone() { - await Gestures.waitAndTap(this.doneButton); + if (!this.device) { + await Gestures.waitAndTap(this.doneButton); + } else { + const button = await this.doneButton; + await button.tap(); + } } } diff --git a/wdio/screen-objects/SendScreen.js b/wdio/screen-objects/SendScreen.js index 916a42d90f2..839dd1e3c29 100644 --- a/wdio/screen-objects/SendScreen.js +++ b/wdio/screen-objects/SendScreen.js @@ -10,10 +10,25 @@ import { UNDERSTAND_WARNING_CONTINUE, } from './testIDs/Screens/SendScreen.testIds'; import { TRANSACTION_AMOUNT_INPUT } from './testIDs/Screens/AmountScreen.testIds.js'; +import AppwrightSelectors from '../helpers/AppwrightSelectors'; +import { SendViewSelectorsIDs } from '../../e2e/selectors/SendFlow/SendView.selectors.js'; +import { expect as appwrightExpect } from 'appwright'; class SendScreen { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get container() { - return Selectors.getElementByPlatform(SEND_SCREEN_ID); + if (!this._device) { + return Selectors.getElementByPlatform(SEND_SCREEN_ID); + } else { + return AppwrightSelectors.getElementByID(this._device, SEND_SCREEN_ID); + } } get sendAddressInputField() { @@ -50,7 +65,12 @@ class SendScreen { } async typeAddressInSendAddressField(address) { - await Gestures.typeText(this.sendAddressInputField, address); + if (!this._device) { + await Gestures.typeText(this.sendAddressInputField, address); + } else { + const element = await AppwrightSelectors.getElementByID(this._device, SEND_ADDRESS_INPUT_FIELD); + await element.fill(address); + } } async isSendWarningMessageVisible(message) { @@ -65,6 +85,11 @@ class SendScreen { await expect(this.understandWarningcontinue).toBeDisplayed(); } + async isVisible() { + const element = await this.container; + await appwrightExpect(element).toBeVisible(); + } + async tapAddAddressButton() { await Gestures.tapTextByXpath(this.addAddressButton); } @@ -74,8 +99,13 @@ class SendScreen { } async isAmountScreenDisplayed() { - const amountScreen = await this.amountScreen; - await amountScreen.waitForDisplayed(); + if (!this._device) { + const amountScreen = await this.amountScreen; + await amountScreen.waitForDisplayed(); + } else { + const element = await AppwrightSelectors.getElementByID(this._device, AMOUNT_SCREEN); + await appwrightExpect(element).toBeVisible(); + } } async isChangedContactNameVisible(contactName) { @@ -94,6 +124,24 @@ class SendScreen { const screen = await this.container; await screen.waitForDisplayed(); } + + async tapOnContactAddress(contactName) { + if (!this._device) { + await Gestures.tapTextByXpath(contactName); + } else { + const element = await AppwrightSelectors.getElementByText(this._device, contactName); + await element.tap(); + } + } + + async tapOnNextButton() { + if (!this._device) { + await Gestures.tapTextByXpath(NEXT_BUTTON); + } else { + const element = await AppwrightSelectors.getElementByID(this._device, SendViewSelectorsIDs.ADDRESS_BOOK_NEXT_BUTTON); + await element.tap(); + } + } } export default new SendScreen(); diff --git a/wdio/screen-objects/SendSolanaScreen.js b/wdio/screen-objects/SendSolanaScreen.js new file mode 100644 index 00000000000..8039049e59f --- /dev/null +++ b/wdio/screen-objects/SendSolanaScreen.js @@ -0,0 +1,76 @@ +import AppwrightSelectors from '../helpers/AppwrightSelectors.js'; +import { expect as appwrightExpect } from 'appwright'; +import TimerHelper from '../../appwright/utils/TimersHelper.js'; +import { SendActionViewSelectorsIDs } from '../../e2e/selectors/SendFlow/SendActionView.selectors'; + +class SendSolanaScreen { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + + get addressField() { + if (AppwrightSelectors.isAndroid(this._device)) { + return AppwrightSelectors.getElementByID(this._device, SendActionViewSelectorsIDs.SOLANA_INPUT_ADDRESS_FIELD); + } + return AppwrightSelectors.getElementByID(this._device, 'textfield'); + } + + get amountField() { + if (AppwrightSelectors.isAndroid(this._device)) { + return AppwrightSelectors.getElementByID(this._device, SendActionViewSelectorsIDs.SOLANA_INPUT_AMOUNT_FIELD); + } + return AppwrightSelectors.getElementByXpath(this._device, '(//XCUIElementTypeOther[@name="textfield"])[2]'); + } + + get continueButton() { + return AppwrightSelectors.getElementByID(this._device, SendActionViewSelectorsIDs.CONTINUE_BUTTON); + } + + get cancelButton() { + return AppwrightSelectors.getElementByID(this._device, SendActionViewSelectorsIDs.CANCEL_BUTTON); + } + + async isAddressFieldVisible() { + const element = await this.addressField; + await appwrightExpect(element).toBeVisible(); + } + + async fillAddressField(address) { + const element = await this.addressField; + if (AppwrightSelectors.isIOS(this._device)) { + await element.fill(`${address}\n`); + } else{ + await element.fill(`${address}`); + + } + } + + async fillAmountField(amount) { + const element = await this.amountField; + await element.fill(amount); + const continueButton = await this.continueButton; + await appwrightExpect(continueButton).toBeVisible({ timeout: 10000 }); + } + + async tapContinueButton() { + const continueButton = await this.continueButton; + await appwrightExpect(continueButton).toBeVisible({ timeout: 10000 }); + const timer1 = new TimerHelper( + 'Time since the user is on the send amount screen until the user gets the confirmation screen', + ); + timer1.start(); + await continueButton.tap(); + return timer1; + } + + async tapCancelButton() { + const element = await this.cancelButton; + await element.tap(); + } +} + +export default new SendSolanaScreen(); diff --git a/wdio/screen-objects/SolanaConfirmationScreen.js b/wdio/screen-objects/SolanaConfirmationScreen.js new file mode 100644 index 00000000000..c9188ee48fb --- /dev/null +++ b/wdio/screen-objects/SolanaConfirmationScreen.js @@ -0,0 +1,33 @@ +import AppwrightSelectors from '../helpers/AppwrightSelectors'; +import { expect as appwrightExpect } from 'appwright'; +import { SendActionViewSelectorsIDs } from '../../e2e/selectors/SendFlow/SendActionView.selectors'; + +class SolanaConfirmationScreen { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + + get field() { + return AppwrightSelectors.getElementByID(this._device, 'snap-ui-info-row'); + } + + get confirmButton() { + return AppwrightSelectors.getElementByID(this._device, SendActionViewSelectorsIDs.SEND_TRANSACTION_BUTTON); + } + + async isFieldVisible() { + const field = await this.field; + await appwrightExpect(field).toBeVisible(); + } + + async isConfirmButtonDisplayed() { + const confirmButton = await this.confirmButton; + await appwrightExpect(confirmButton).toBeVisible({ timeout: 10000 }); + } +} + +export default new SolanaConfirmationScreen(); diff --git a/wdio/screen-objects/SwapScreen.js b/wdio/screen-objects/SwapScreen.js new file mode 100644 index 00000000000..2810e05c79e --- /dev/null +++ b/wdio/screen-objects/SwapScreen.js @@ -0,0 +1,135 @@ +import AppwrightSelectors from '../helpers/AppwrightSelectors'; +import { SWAP_SCREEN_DESTINATION_TOKEN_INPUT_ID, SWAP_SCREEN_QUOTE_DISPLAYED_ID, SWAP_SCREEN_SOURCE_TOKEN_INPUT_ID } from './testIDs/Screens/SwapScreen.testIds'; +import { expect as appwrightExpect } from 'appwright'; +import { PerpsWithdrawViewSelectorsIDs } from '../../e2e/selectors/Perps/Perps.selectors'; +import { QuoteViewSelectorIDs,QuoteViewSelectorText } from '../../e2e/selectors/swaps/QuoteView.selectors'; +import { SwapsViewSelectorsIDs } from '../../e2e/selectors/swaps/SwapsView.selectors'; +import { QuoteViewSelectorText as BridgeQuotesSelectorText } from '../../e2e/selectors/Bridge/QuoteView.selectors'; + +class SwapScreen { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get sourceTokenInput() { + return AppwrightSelectors.getElementByID(this._device, SWAP_SCREEN_SOURCE_TOKEN_INPUT_ID); + } + + get destTokenInput() { + return AppwrightSelectors.getElementByID(this._device, SWAP_SCREEN_DESTINATION_TOKEN_INPUT_ID); + } + + get quoteDisplayed() { + return AppwrightSelectors.getElementByID(this._device, SWAP_SCREEN_QUOTE_DISPLAYED_ID); + } + get destinationTokenArea(){ + return AppwrightSelectors.getElementByID(this._device, PerpsWithdrawViewSelectorsIDs.DEST_TOKEN_AREA); + + } + get seeAllDropDown(){ + return AppwrightSelectors.getElementByText(this._device, "See all"); + + } + + get getETHQuotesButton(){ + return AppwrightSelectors.getElementByText(this._device, QuoteViewSelectorText.GET_QUOTES); + } + + async isQuoteDisplayed(network) { + if (network == 'Ethereum'){ // legacy swap view only shows on etheruem network + const mmFee = await AppwrightSelectors.getElementByID(this._device, SwapsViewSelectorsIDs.QUOTE_SUMMARY); + await appwrightExpect(mmFee).toBeVisible({ timeout: 10000 }); + + } + else{ + const element = await this.quoteDisplayed; // bridge swap view shows on + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + const mmFee = await AppwrightSelectors.getElementByCatchAll(this._device, BridgeQuotesSelectorText.FEE_DISCLAIMER); + await appwrightExpect(mmFee).toBeVisible({ timeout: 10000 }); + } + + } + + async enterSourceTokenAmount(amount) { + // Split amount into digits + const digits = this.splitAmountIntoDigits(amount); + console.log('Amount digits:', digits); + digits.forEach(async digit => { + if (AppwrightSelectors.isAndroid(this._device)) { + if (digit != '.') { + const numberKey = await AppwrightSelectors.getElementByXpath(this._device, `//android.widget.Button[@content-desc='${digit}']`); + await numberKey.tap(); + } + else { + const numberKey = await AppwrightSelectors.getElementByXpath(this._device, `//android.view.ViewGroup[@content-desc="."]`); + await numberKey.tap(); + } + } + else { + const numberKey = await AppwrightSelectors.getElementByXpath(this._device, `//XCUIElementTypeButton[@name="${digit}"]`); + await numberKey.tap(); + } + }); + } + + async selectNetworkAndTokenTo(network, token) { + let tokenButton; + + if (network == 'Ethereum'){ + const tokenDropDown = await AppwrightSelectors.getElementByID(this._device, QuoteViewSelectorIDs.DEST_TOKEN) + await tokenDropDown.tap(); + if (AppwrightSelectors.isIOS(this._device)){ + tokenButton = await AppwrightSelectors.getElementByText(this._device, `${token} ${token}`); + await tokenButton.tap(); + } + else { + tokenButton = await AppwrightSelectors.getElementByCatchAll(this._device, token); + await tokenButton.tap(); + + } + } + else { + const destinationToken = await this.destinationTokenArea; + await destinationToken.tap(); + const selectAllDropDown = await this.seeAllDropDown; + await selectAllDropDown.tap(); + const networkName = await AppwrightSelectors.getElementByText(this._device, network); + await networkName.tap(); + const tokenButton = await AppwrightSelectors.getElementByText(this._device, token); + await tokenButton.tap(); + } + + } + + async tapGetQuotes(network){ + if (network == 'Ethereum'){ + const quotesButton = await this.getETHQuotesButton; + await appwrightExpect(quotesButton).toBeVisible({ timeout: 10000 }); + await quotesButton.tap(); + } + } + + // Helper method to split amount into digits + splitAmountIntoDigits(amount) { + // Convert to string and split into array of digits + return amount.toString().split('').map(char => { + // Return only numeric digits, filter out decimal points, commas, etc. + return /\d/.test(char) ? parseInt(char, 10) : char; + }); + } + + async enterDestinationTokenAmount(amount) { + const element = await this.destTokenInput; + await element.fill(amount); + } + + async isVisible() { + const element = await this.sourceTokenInput; + await appwrightExpect(element).toBeVisible({ timeout: 10000 }); + } +} + +export default new SwapScreen(); diff --git a/wdio/screen-objects/TokenOverviewScreen.js b/wdio/screen-objects/TokenOverviewScreen.js index 90b6435e2dc..53d04af58c6 100644 --- a/wdio/screen-objects/TokenOverviewScreen.js +++ b/wdio/screen-objects/TokenOverviewScreen.js @@ -1,10 +1,31 @@ import Selectors from '../helpers/Selectors'; import Gestures from '../helpers/Gestures'; import { TokenOverviewSelectorsIDs } from '../../e2e/selectors/wallet/TokenOverview.selectors'; - +import AppwrightSelectors from '../helpers/AppwrightSelectors'; +import { expect as expectAppwright } from 'appwright'; class TokenOverviewScreen { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + + get todaysChange() { + if (!this._device) { + return Selectors.getElementByPlatform(TokenOverviewSelectorsIDs.TODAYS_CHANGE); + } else { + return AppwrightSelectors.getElementByText(this._device, '%) Today'); + } + } + get tokenAssetOverview() { - return Selectors.getElementByPlatform(TokenOverviewSelectorsIDs.CONTAINER); + if (!this._device) { + return Selectors.getElementByPlatform(TokenOverviewSelectorsIDs.CONTAINER); + } else { + return AppwrightSelectors.getElementByID(this._device, TokenOverviewSelectorsIDs.CONTAINER); + } } get sendButton() { @@ -12,8 +33,24 @@ class TokenOverviewScreen { } async isTokenOverviewVisible() { - const element = await this.tokenAssetOverview; - await element.waitForDisplayed(); + if (!this._device) { + const element = await this.tokenAssetOverview; + await element.waitForDisplayed(); + } else { + const element = await this.tokenAssetOverview; + expectAppwright(element).toBeVisible(); + } + } + + async isTodaysChangeVisible() { + if (!this._device) { + const element = await this.todaysChange; + await element.waitForDisplayed(); + } else { + const element = await this.todaysChange; + expectAppwright(element).toBeVisible({ timeout: 10000 }); + await new Promise(resolve => setTimeout(resolve, 500)); + } } async tapSendButton() { diff --git a/wdio/screen-objects/WalletMainScreen.js b/wdio/screen-objects/WalletMainScreen.js index 26a36a2d30f..55a3ab71a1d 100644 --- a/wdio/screen-objects/WalletMainScreen.js +++ b/wdio/screen-objects/WalletMainScreen.js @@ -7,8 +7,18 @@ import { TabBarSelectorIDs } from '../../e2e/selectors/wallet/TabBar.selectors'; import { BACK_BUTTON_SIMPLE_WEBVIEW } from './testIDs/Components/SimpleWebView.testIds'; import { WalletViewSelectorsIDs } from '../../e2e/selectors/wallet/WalletView.selectors'; +import AppwrightSelectors from '../helpers/AppwrightSelectors.js'; +import { expect as appwrightExpect } from 'appwright'; class WalletMainScreen { + get device() { + return this._device; + } + + set device(device) { + this._device = device; + } + get ImportToken() { return Selectors.getElementByPlatform(WalletViewSelectorsIDs.IMPORT_TOKEN_BUTTON); } @@ -22,15 +32,27 @@ class WalletMainScreen { } get accountIcon() { - return Selectors.getXpathElementByResourceId(WalletViewSelectorsIDs.ACCOUNT_ICON); + if (!this._device) { + return Selectors.getXpathElementByResourceId(WalletViewSelectorsIDs.ACCOUNT_ICON); + } else { + return AppwrightSelectors.getElementByID(this._device, WalletViewSelectorsIDs.ACCOUNT_ICON); + } } get WalletScreenContainer() { - return Selectors.getXpathElementByResourceId(WalletViewSelectorsIDs.WALLET_CONTAINER); + if (!this._device) { + return Selectors.getXpathElementByResourceId(WalletViewSelectorsIDs.WALLET_CONTAINER); + } else { + return AppwrightSelectors.getElementByID(this._device, WalletViewSelectorsIDs.WALLET_CONTAINER); + } } get networkInNavBar() { - return Selectors.getXpathElementByResourceId(WalletViewSelectorsIDs.NAVBAR_NETWORK_BUTTON); + if (!this._device) { + return Selectors.getXpathElementByResourceId(WalletViewSelectorsIDs.NAVBAR_NETWORK_BUTTON); + } else { + return AppwrightSelectors.getElementByID(this._device, WalletViewSelectorsIDs.NAVBAR_NETWORK_BUTTON); + } } get remindMeLaterNotification() { @@ -48,7 +70,11 @@ class WalletMainScreen { } get accountActionsButton() { - return Selectors.getXpathElementByResourceId(WalletViewSelectorsIDs.ACCOUNT_ACTIONS); + if (!this._device) { + return Selectors.getXpathElementByResourceId(WalletViewSelectorsIDs.ACCOUNT_ACTIONS); + } else { + return AppwrightSelectors.getElementByID(this._device, WalletViewSelectorsIDs.ACCOUNT_ACTIONS); + } } get privateKeyActionButton() { @@ -64,7 +90,12 @@ class WalletMainScreen { } get walletButton() { - return Selectors.getXpathElementByResourceId(TabBarSelectorIDs.WALLET); + if (!this._device) { + return Selectors.getXpathElementByResourceId(TabBarSelectorIDs.WALLET); + } else { + return AppwrightSelectors.getElementByID(this._device, TabBarSelectorIDs.WALLET); + + } } get goBackSimpleWebViewButton() { @@ -99,12 +130,53 @@ class WalletMainScreen { await Gestures.tapTextByXpath('NFTs'); } + async tapOnToken(token) { + if (!this._device) { + await Gestures.waitAndTap(this.accountIcon); + } else { + const isAndroid = AppwrightSelectors.isAndroid(this._device); + + let tokenName; + if (isAndroid) { + // For Android: use asset-{token} approach + tokenName = await AppwrightSelectors.getElementByID(this._device, `asset-${token}`); + } else { + // For iOS: use catch-all selector + tokenName = await AppwrightSelectors.getElementByCatchAll(this._device, `${token}`); + } + + await tokenName.tap(); + } + } + + async isTokenVisible(token) { + const isAndroid = AppwrightSelectors.isAndroid(this._device); + if (isAndroid) { + const tokenName = await AppwrightSelectors.getElementByID(this._device, `asset-${token}`); + await tokenName.isVisible(); + } else { + const tokenName = await AppwrightSelectors.getElementByCatchAll(this._device, token); + await tokenName.isVisible(); + } + } + async tapIdenticon() { - await Gestures.waitAndTap(this.accountIcon); + if (!this._device) { + await Gestures.waitAndTap(this.accountIcon); + } else { + const element = await this.accountIcon; + await element.tap(); + } } async tapNetworkNavBar() { - await Gestures.waitAndTap(await this.networkInNavBar); + + if (!this._device) { + await Gestures.waitAndTap(await this.networkInNavBar); + } else { + const element = await this.networkInNavBar; + await element.tap(); + } } async tapRemindMeLaterOnNotification() { @@ -120,6 +192,14 @@ class WalletMainScreen { await expect(this.WalletScreenContainer).toBeDisplayed(); } + async clickOnMainScreen() { // to close account actions bottom sheet + if (!this._device) { + await Gestures.waitAndTap(this.WalletScreenContainer); + } else { + await this._device.tap({ x: 100, y: 100 }); + } + } + async isNetworkNameCorrect(network) { const networkName = await Selectors.getXpathElementByTextContains(network); await networkName.waitForDisplayed(); @@ -132,8 +212,12 @@ class WalletMainScreen { } async isMainWalletViewVisible() { - const element = await this.walletButton; - await expect(element).toBeDisplayed(); + if (!this._device) { + await this.walletButton.waitForDisplayed(); + } else { + const element = await this.walletButton; + await appwrightExpect(element).toBeVisible(); + } } async isSubmittedNotificationDisplayed() { @@ -156,7 +240,12 @@ class WalletMainScreen { } async tapAccountActions() { - await Gestures.waitAndTap(this.accountActionsButton); + if (!this._device) { + await Gestures.waitAndTap(this.accountActionsButton); + } else { + const element = await this.accountActionsButton; + await element.tap(); + } } async tapShowPrivateKey() { diff --git a/wdio/screen-objects/testIDs/Screens/SwapScreen.testIds.js b/wdio/screen-objects/testIDs/Screens/SwapScreen.testIds.js new file mode 100644 index 00000000000..07217c01dd6 --- /dev/null +++ b/wdio/screen-objects/testIDs/Screens/SwapScreen.testIds.js @@ -0,0 +1,3 @@ +export const SWAP_SCREEN_SOURCE_TOKEN_INPUT_ID = 'source-token-area-input'; +export const SWAP_SCREEN_DESTINATION_TOKEN_INPUT_ID = 'dest-token-area-input'; +export const SWAP_SCREEN_QUOTE_DISPLAYED_ID = 'bridge-view-scroll'; \ No newline at end of file