diff --git a/tests/framework/PageObjectMigrationTestUtils.ts b/tests/framework/PageObjectMigrationTestUtils.ts index f7b5a5fc2bb..b0b0be8fbab 100644 --- a/tests/framework/PageObjectMigrationTestUtils.ts +++ b/tests/framework/PageObjectMigrationTestUtils.ts @@ -68,7 +68,9 @@ function atLeastOnePlaywrightMatcherWasCalled(): void { (PlaywrightMatchers.getElementById as jest.Mock).mock.calls.length + (PlaywrightMatchers.getElementByText as jest.Mock).mock.calls.length + (PlaywrightMatchers.getElementByAccessibilityId as jest.Mock).mock.calls - .length; + .length + + (PlaywrightMatchers.getElementByXPath as jest.Mock).mock.calls.length + + (PlaywrightMatchers.getElementByCatchAll as jest.Mock).mock.calls.length; expect(playwrightCallCount).toBeGreaterThan(0); } @@ -76,6 +78,8 @@ function noPlaywrightMatcherWasCalled(): void { expect(PlaywrightMatchers.getElementById).not.toHaveBeenCalled(); expect(PlaywrightMatchers.getElementByText).not.toHaveBeenCalled(); expect(PlaywrightMatchers.getElementByAccessibilityId).not.toHaveBeenCalled(); + expect(PlaywrightMatchers.getElementByXPath).not.toHaveBeenCalled(); + expect(PlaywrightMatchers.getElementByCatchAll).not.toHaveBeenCalled(); } function noDetoxMatcherWasCalled(): void { diff --git a/tests/framework/PlaywrightGestures.ts b/tests/framework/PlaywrightGestures.ts index c9d788fdee8..a017130365a 100644 --- a/tests/framework/PlaywrightGestures.ts +++ b/tests/framework/PlaywrightGestures.ts @@ -136,4 +136,9 @@ export default class PlaywrightGestures { throw new Error('Package name or app id is not available'); } } + + @boxedStep + static async tap(elem: PlaywrightElement): Promise { + await elem.click(); + } } diff --git a/tests/page-objects/Onboarding/CreatePasswordView.ts b/tests/page-objects/Onboarding/CreatePasswordView.ts index 0be566c45b7..3bfb876caa1 100644 --- a/tests/page-objects/Onboarding/CreatePasswordView.ts +++ b/tests/page-objects/Onboarding/CreatePasswordView.ts @@ -1,29 +1,73 @@ import { ChoosePasswordSelectorsIDs } from '../../../app/components/Views/ChoosePassword/ChoosePassword.testIds'; +import { + CREATE_PASSWORD_INPUT_FIRST_FIELD, + CONFIRM_PASSWORD_INPUT_FIRST_FIELD, +} from '../../../wdio/screen-objects/testIDs/Screens/WalletSetupScreen.testIds'; import Matchers from '../../framework/Matchers'; import Gestures from '../../framework/Gestures'; +import UnifiedGestures from '../../framework/UnifiedGestures'; +import { + encapsulated, + EncapsulatedElementType, + asPlaywrightElement, + asDetoxElement, +} from '../../framework/EncapsulatedElement'; +import { encapsulatedAction } from '../../framework/encapsulatedAction'; +import PlaywrightMatchers from '../../framework/PlaywrightMatchers'; +import { getDriver } from '../../framework/PlaywrightUtilities'; import enContent from '../../../locales/languages/en.json'; +import PlaywrightGestures from '../../framework/PlaywrightGestures'; class CreatePasswordView { get container(): DetoxElement { return Matchers.getElementByID(ChoosePasswordSelectorsIDs.CONTAINER_ID); } - get newPasswordInput(): DetoxElement { - return Matchers.getElementByID( - ChoosePasswordSelectorsIDs.NEW_PASSWORD_INPUT_ID, - ); + get newPasswordInput(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID( + ChoosePasswordSelectorsIDs.NEW_PASSWORD_INPUT_ID, + ), + appium: { + android: () => + PlaywrightMatchers.getElementById(CREATE_PASSWORD_INPUT_FIRST_FIELD), + ios: () => + PlaywrightMatchers.getElementByXPath( + '(//XCUIElementTypeOther[@name="textfield"])[1]', + ), + }, + }); } - get confirmPasswordInput(): DetoxElement { - return Matchers.getElementByID( - ChoosePasswordSelectorsIDs.CONFIRM_PASSWORD_INPUT_ID, - ); + get confirmPasswordInput(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID( + ChoosePasswordSelectorsIDs.CONFIRM_PASSWORD_INPUT_ID, + ), + appium: { + android: () => + PlaywrightMatchers.getElementById(CONFIRM_PASSWORD_INPUT_FIRST_FIELD), + ios: () => + PlaywrightMatchers.getElementByXPath( + '(//XCUIElementTypeOther[@name="textfield"])[2]', + ), + }, + }); } - get iUnderstandCheckbox(): DetoxElement { - return Matchers.getElementByID( - ChoosePasswordSelectorsIDs.I_UNDERSTAND_CHECKBOX_ID, - ); + get iUnderstandCheckbox(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID( + ChoosePasswordSelectorsIDs.I_UNDERSTAND_CHECKBOX_ID, + ), + appium: () => + PlaywrightMatchers.getElementById( + ChoosePasswordSelectorsIDs.I_UNDERSTAND_CHECKBOX_ID, + ), + }); } get iUnderstandCheckboxNewWallet(): DetoxElement { @@ -32,8 +76,15 @@ class CreatePasswordView { ); } - get submitButton(): DetoxElement { - return Matchers.getElementByID(ChoosePasswordSelectorsIDs.SUBMIT_BUTTON_ID); + get submitButton(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID(ChoosePasswordSelectorsIDs.SUBMIT_BUTTON_ID), + appium: () => + PlaywrightMatchers.getElementById( + ChoosePasswordSelectorsIDs.SUBMIT_BUTTON_ID, + ), + }); } get passwordError(): DetoxElement { @@ -41,37 +92,55 @@ class CreatePasswordView { } async resetPasswordInputs(): Promise { - await Gestures.typeText(this.newPasswordInput, '', { + await Gestures.typeText(this.newPasswordInput as DetoxElement, '', { hideKeyboard: true, }); - await Gestures.typeText(this.confirmPasswordInput, '', { + await Gestures.typeText(this.confirmPasswordInput as DetoxElement, '', { hideKeyboard: true, }); } async enterPassword(password: string): Promise { - await Gestures.typeText(this.newPasswordInput, password, { - elemDescription: 'Create Password New Password Input', - hideKeyboard: true, + await UnifiedGestures.typeText(this.newPasswordInput, password, { + description: 'Create Password New Password Input', }); } async reEnterPassword(password: string): Promise { - await Gestures.typeText(this.confirmPasswordInput, password, { - elemDescription: 'Create Password Confirm Password Input', - hideKeyboard: true, + await UnifiedGestures.typeText(this.confirmPasswordInput, password, { + description: 'Create Password Confirm Password Input', }); } async tapIUnderstandCheckBox(): Promise { - await Gestures.tap(this.iUnderstandCheckbox, { - elemDescription: 'Create Password - I Understand Checkbox', + await encapsulatedAction({ + detox: async () => { + await Gestures.tap(asDetoxElement(this.iUnderstandCheckbox), { + elemDescription: 'Create Password - I Understand Checkbox', + }); + }, + appium: async () => { + const drv = getDriver(); + await drv.hideKeyboard(); + await PlaywrightGestures.tap( + await asPlaywrightElement(this.iUnderstandCheckbox), + ); + }, }); } async tapCreatePasswordButton(): Promise { - await Gestures.waitAndTap(this.submitButton, { - elemDescription: 'Create Password Submit Button', + await UnifiedGestures.waitAndTap(this.submitButton, { + description: 'Create Password Submit Button', + }); + } + + async isVisible(): Promise { + await encapsulatedAction({ + appium: async () => { + const el = await asPlaywrightElement(this.newPasswordInput); + await el.waitForDisplayed({ timeout: 10000 }); + }, }); } } diff --git a/tests/page-objects/Onboarding/ImportWalletView.ts b/tests/page-objects/Onboarding/ImportWalletView.ts index 5352284c45c..6d635a1ba54 100644 --- a/tests/page-objects/Onboarding/ImportWalletView.ts +++ b/tests/page-objects/Onboarding/ImportWalletView.ts @@ -2,14 +2,44 @@ import { ChoosePasswordSelectorsIDs } from '../../../app/components/Views/Choose import { ImportFromSeedSelectorsIDs } from '../../../app/components/Views/ImportFromSecretRecoveryPhrase/ImportFromSeed.testIds'; import Matchers from '../../framework/Matchers'; import Gestures from '../../framework/Gestures'; +import { + encapsulated, + EncapsulatedElementType, + asPlaywrightElement, + asDetoxElement, +} from '../../framework/EncapsulatedElement'; +import { encapsulatedAction } from '../../framework/encapsulatedAction'; +import PlaywrightMatchers from '../../framework/PlaywrightMatchers'; +import { PlatformDetector } from '../../framework/PlatformLocator'; +import { getDriver } from '../../framework/PlaywrightUtilities'; +import { ImportSRPIDs } from '../../../app/components/Views/ImportNewSecretRecoveryPhrase/SRPImport.testIds'; +import { UnifiedGestures } from '../../framework'; class ImportWalletView { get container(): DetoxElement { return Matchers.getElementByID(ImportFromSeedSelectorsIDs.CONTAINER_ID); } - get title(): DetoxElement { - return Matchers.getElementByID(ImportFromSeedSelectorsIDs.SCREEN_TITLE_ID); + get title(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID(ImportFromSeedSelectorsIDs.SCREEN_TITLE_ID), + appium: () => + PlaywrightMatchers.getElementById( + ImportFromSeedSelectorsIDs.SCREEN_TITLE_ID, + ), + }); + } + + get continueButtonEncapsulated(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID(ImportFromSeedSelectorsIDs.CONTINUE_BUTTON_ID), + appium: () => + PlaywrightMatchers.getElementById( + ImportFromSeedSelectorsIDs.CONTINUE_BUTTON_ID, + ), + }); } get newPasswordInput(): DetoxElement { @@ -24,15 +54,39 @@ class ImportWalletView { ); } - seedPhraseInput(index: number): DetoxElement { - if (index !== 0) { - return Matchers.getElementByID( - `${ImportFromSeedSelectorsIDs.SEED_PHRASE_INPUT_ID}_${index}`, - ); - } - return Matchers.getElementByID( - ImportFromSeedSelectorsIDs.SEED_PHRASE_INPUT_ID, - ); + /** + * Returns the encapsulated element for the SRP input field at the given word index. + * + * iOS label convention: the first field (index 0) has no label filter; + * subsequent fields use 1-indexed labels offset by one from the word index + * (word 1 → label "2.", word 2 → label "3.", etc.). + * This matches the native iOS SRP form where the first labeled field is "2.". + */ + seedPhraseInput(index: number): EncapsulatedElementType { + return encapsulated({ + detox: () => + index !== 0 + ? Matchers.getElementByID( + `${ImportFromSeedSelectorsIDs.SEED_PHRASE_INPUT_ID}_${index}`, + ) + : Matchers.getElementByID( + ImportFromSeedSelectorsIDs.SEED_PHRASE_INPUT_ID, + ), + appium: { + android: () => + PlaywrightMatchers.getElementById( + index !== 0 + ? `${ImportFromSeedSelectorsIDs.SEED_PHRASE_INPUT_ID}_${index}` + : ImportFromSeedSelectorsIDs.SEED_PHRASE_INPUT_ID, + ), + ios: () => + PlaywrightMatchers.getElementByXPath( + index !== 0 + ? `//XCUIElementTypeOther[@name="textfield" and @label="${index + 1}."]` + : '//XCUIElementTypeOther[@name="textfield"]', + ), + }, + }); } get continueButton(): DetoxElement { @@ -54,35 +108,195 @@ class ImportWalletView { } async enterSecretRecoveryPhrase(secretRecoveryPhrase: string): Promise { - if (device.getPlatform() === 'ios') { - const srpArray = secretRecoveryPhrase.split(' '); - for (const [i, word] of srpArray.entries()) { - await Gestures.typeText(this.seedPhraseInput(i), `${word} `, { - elemDescription: 'Import Wallet Secret Recovery Phrase Input Box', - hideKeyboard: i === srpArray.length - 1, - }); - } - } else { - await Gestures.replaceText( - this.seedPhraseInput(0), - secretRecoveryPhrase, - { - elemDescription: 'Import Wallet Secret Recovery Phrase Input Box', - checkVisibility: false, - }, - ); - } + await encapsulatedAction({ + detox: async () => { + if (device.getPlatform() === 'ios') { + const srpArray = secretRecoveryPhrase.split(' '); + for (const [i, word] of srpArray.entries()) { + await Gestures.typeText( + asDetoxElement(this.seedPhraseInput(i)), + `${word} `, + { + elemDescription: + 'Import Wallet Secret Recovery Phrase Input Box', + hideKeyboard: i === srpArray.length - 1, + }, + ); + } + } else { + await Gestures.replaceText( + asDetoxElement(this.seedPhraseInput(0)), + secretRecoveryPhrase, + { + elemDescription: 'Import Wallet Secret Recovery Phrase Input Box', + checkVisibility: false, + }, + ); + } + }, + }); } async tapContinueButton(): Promise { - await Gestures.tap(this.continueButton, { - elemDescription: 'Import Wallet Continue Button', + await UnifiedGestures.tap(this.continueButton, { + description: 'Import Wallet Continue Button', }); } async tapTitle(): Promise { - await Gestures.tap(this.title, { - elemDescription: 'Import Wallet Title', + await UnifiedGestures.tap(this.title, { + description: 'Import Wallet Title', + }); + } + + // --- Appium-compatible methods (encapsulated) --- + + /** + * Waits for the screen title to be visible + * @param onboarding - Whether the screen is onboarding or not + * @returns void + */ + async isScreenTitleVisible(onboarding: boolean = true): Promise { + await encapsulatedAction({ + appium: async () => { + if (onboarding) { + const el = await asPlaywrightElement(this.title); + await el.waitForDisplayed({ timeout: 10000 }); + } else { + const el = + await PlaywrightMatchers.getElementByText('Import a wallet'); + await el.waitForDisplayed({ timeout: 10000 }); + } + }, + }); + } + + /** + * Returns the input element for the given SRP index + * @param srpIndex - The index of the SRP word + * @param onboarding - Whether the screen is onboarding or not + * @returns The input element for the given SRP index + */ + async inputOfIndex( + srpIndex: number, + onboarding: boolean = true, + ): Promise { + if (onboarding) { + if (await PlatformDetector.isAndroid()) { + return `${ImportFromSeedSelectorsIDs.SEED_PHRASE_INPUT_ID}_${srpIndex}`; + } + return `//XCUIElementTypeOther[@name="textfield" and @label="${srpIndex}."]`; + } + if (await PlatformDetector.isAndroid()) { + return `seed-phrase-input_${srpIndex}`; + } + return `//*[@label="${srpIndex + 1}."]`; + } + + /** + * Types a secret recovery phrase word-by-word into the SRP input fields. + * Uses seedPhraseInput(i) for consistent selector resolution across platforms. + * + * Onboarding flow matches wdio ImportFromSeedScreen.typeSecretRecoveryPhrase: + * - First word typed with trailing space into field 0 + * - Middle words typed with trailing space + tap into fields 1..n-2 + * - Last word typed WITHOUT trailing space into field n-1 + * + * @param phrase - The secret recovery phrase to type + * @param onboarding - Whether the screen is onboarding or not + */ + async typeSecretRecoveryPhrase( + phrase: string, + onboarding: boolean = true, + ): Promise { + await encapsulatedAction({ + appium: async () => { + const phraseArray = phrase.split(' '); + const isAndroid = await PlatformDetector.isAndroid(); + + if (onboarding) { + // Type first word into the first field (with trailing space) + const firstField = await asPlaywrightElement(this.seedPhraseInput(0)); + await firstField.type(`${phraseArray[0]} `); + + // Type middle words (with trailing space + tap) + for (let i = 1; i < phraseArray.length - 1; i++) { + const input = await asPlaywrightElement(this.seedPhraseInput(i)); + await input.type(`${phraseArray[i]} `); + await input.click(); + } + + // Type last word (without trailing space, no tap) + const lastIndex = phraseArray.length - 1; + const lastInput = await asPlaywrightElement( + this.seedPhraseInput(lastIndex), + ); + await lastInput.type(phraseArray[lastIndex]); + } else { + // Non-onboarding flow (adding additional SRP) + let firstInput; + if (isAndroid) { + firstInput = await PlaywrightMatchers.getElementById( + ImportSRPIDs.SEED_PHRASE_INPUT_ID, + ); + } else { + firstInput = await PlaywrightMatchers.getElementById('textfield'); + } + await firstInput.type(`${phraseArray[0]} `); + + for (let i = 1; i < phraseArray.length; i++) { + const fieldId = await this.inputOfIndex(i, false); + let input; + if (isAndroid) { + input = await PlaywrightMatchers.getElementById(fieldId); + } else { + input = await PlaywrightMatchers.getElementByXPath(fieldId); + } + await input.type(`${phraseArray[i]} `); + await input.click(); + } + } + }, + }); + } + + async tapImportScreenTitleToDismissKeyboard( + onboarding: boolean = true, + ): Promise { + await encapsulatedAction({ + appium: async () => { + if (onboarding) { + const el = await asPlaywrightElement(this.title); + await el.click(); + } else { + const drv = getDriver(); + await drv.hideKeyboard(); + } + }, + }); + } + + async tapContinueButtonForOnboarding( + onboarding: boolean = true, + ): Promise { + await encapsulatedAction({ + appium: async () => { + if (onboarding) { + const drv = getDriver(); + await drv.hideKeyboard(); + const el = await asPlaywrightElement(this.continueButtonEncapsulated); + await el.click(); + } else { + const isIOS = await PlatformDetector.isIOS(); + if (isIOS) { + const el = await PlaywrightMatchers.getElementById('import-button'); + await el.click(); + } else { + const el = await PlaywrightMatchers.getElementByText('Continue'); + await el.click(); + } + } + }, }); } } diff --git a/tests/page-objects/Onboarding/MetaMetricsOptInView.ts b/tests/page-objects/Onboarding/MetaMetricsOptInView.ts index 78e097447b6..6e9336136ab 100644 --- a/tests/page-objects/Onboarding/MetaMetricsOptInView.ts +++ b/tests/page-objects/Onboarding/MetaMetricsOptInView.ts @@ -1,6 +1,14 @@ import { MetaMetricsOptInSelectorsIDs } from '../../../app/components/UI/OptinMetrics/MetaMetricsOptIn.testIds'; import Matchers from '../../framework/Matchers'; import Gestures from '../../framework/Gestures'; +import UnifiedGestures from '../../framework/UnifiedGestures'; +import { + encapsulated, + EncapsulatedElementType, + asPlaywrightElement, +} from '../../framework/EncapsulatedElement'; +import { encapsulatedAction } from '../../framework/encapsulatedAction'; +import PlaywrightMatchers from '../../framework/PlaywrightMatchers'; class MetaMetricsOptIn { get container(): DetoxElement { @@ -9,16 +17,36 @@ class MetaMetricsOptIn { ); } + get screenTitle(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID( + MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_TITLE_ID, + ), + appium: () => + PlaywrightMatchers.getElementById( + MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_TITLE_ID, + ), + }); + } + get optInMetricsContent(): DetoxElement { return Matchers.getElementByID( MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_PRIVACY_POLICY_DESCRIPTION_CONTENT_1_ID, ); } - get iAgreeButton(): DetoxElement { - return Matchers.getElementByID( - MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_CONTINUE_BUTTON_ID, - ); + get iAgreeButton(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID( + MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_CONTINUE_BUTTON_ID, + ), + appium: () => + PlaywrightMatchers.getElementById( + MetaMetricsOptInSelectorsIDs.OPTIN_METRICS_CONTINUE_BUTTON_ID, + ), + }); } get metricsCheckbox(): DetoxElement { @@ -36,9 +64,16 @@ class MetaMetricsOptIn { } async tapAgreeButton(): Promise { - await this.swipeContentUp(); - await Gestures.waitAndTap(this.iAgreeButton, { - elemDescription: 'Opt-in Metrics Continue Button', + await encapsulatedAction({ + detox: async () => { + await this.swipeContentUp(); + await Gestures.waitAndTap(this.iAgreeButton as DetoxElement, { + elemDescription: 'Opt-in Metrics Continue Button', + }); + }, + appium: async () => { + await UnifiedGestures.tap(this.iAgreeButton); + }, }); } @@ -47,6 +82,15 @@ class MetaMetricsOptIn { elemDescription: 'Opt-in Metrics Metrics Checkbox', }); } + + async isScreenTitleVisible(): Promise { + await encapsulatedAction({ + appium: async () => { + const el = await asPlaywrightElement(this.screenTitle); + await el.waitForDisplayed({ timeout: 30000 }); + }, + }); + } } export default new MetaMetricsOptIn(); diff --git a/tests/page-objects/Onboarding/MultichainAccountEducationModal.ts b/tests/page-objects/Onboarding/MultichainAccountEducationModal.ts new file mode 100644 index 00000000000..f0520879dca --- /dev/null +++ b/tests/page-objects/Onboarding/MultichainAccountEducationModal.ts @@ -0,0 +1,42 @@ +import { MULTICHAIN_ACCOUNTS_INTRO_MODAL_TEST_IDS } from '../../../app/components/Views/MultichainAccounts/IntroModal/testIds'; +import Matchers from '../../framework/Matchers'; +import UnifiedGestures from '../../framework/UnifiedGestures'; +import { + encapsulated, + EncapsulatedElementType, + asPlaywrightElement, +} from '../../framework/EncapsulatedElement'; +import { encapsulatedAction } from '../../framework/encapsulatedAction'; +import PlaywrightMatchers from '../../framework/PlaywrightMatchers'; + +class MultichainAccountEducationModal { + get closeButton(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID( + MULTICHAIN_ACCOUNTS_INTRO_MODAL_TEST_IDS.CLOSE_BUTTON, + ), + appium: () => + PlaywrightMatchers.getElementById( + MULTICHAIN_ACCOUNTS_INTRO_MODAL_TEST_IDS.CLOSE_BUTTON, + ), + }); + } + + async isVisible(timeout?: number): Promise { + await encapsulatedAction({ + appium: async () => { + const el = await asPlaywrightElement(this.closeButton); + await el.waitForDisplayed({ timeout: timeout ?? 10000 }); + }, + }); + } + + async tapGotItButton(): Promise { + await UnifiedGestures.waitAndTap(this.closeButton, { + description: 'Multichain Account Education Modal Got It Button', + }); + } +} + +export default new MultichainAccountEducationModal(); diff --git a/tests/page-objects/Onboarding/OnboardingSheet.ts b/tests/page-objects/Onboarding/OnboardingSheet.ts index 4dd9b886804..7c4952b5020 100644 --- a/tests/page-objects/Onboarding/OnboardingSheet.ts +++ b/tests/page-objects/Onboarding/OnboardingSheet.ts @@ -1,6 +1,14 @@ import Matchers from '../../framework/Matchers'; import Gestures from '../../framework/Gestures'; +import UnifiedGestures from '../../framework/UnifiedGestures'; import { OnboardingSheetSelectorIDs } from '../../../app/components/Views/OnboardingSheet/OnboardingSheet.testIds'; +import { + encapsulated, + EncapsulatedElementType, + asPlaywrightElement, +} from '../../framework/EncapsulatedElement'; +import { encapsulatedAction } from '../../framework/encapsulatedAction'; +import PlaywrightMatchers from '../../framework/PlaywrightMatchers'; class OnboardingSheet { get container(): DetoxElement { @@ -19,10 +27,15 @@ class OnboardingSheet { ); } - get importSeedButton(): DetoxElement { - return Matchers.getElementByID( - OnboardingSheetSelectorIDs.IMPORT_SEED_BUTTON, - ); + get importSeedButton(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID(OnboardingSheetSelectorIDs.IMPORT_SEED_BUTTON), + appium: () => + PlaywrightMatchers.getElementById( + OnboardingSheetSelectorIDs.IMPORT_SEED_BUTTON, + ), + }); } async tapGoogleLoginButton(): Promise { @@ -38,8 +51,17 @@ class OnboardingSheet { } async tapImportSeedButton(): Promise { - await Gestures.waitAndTap(this.importSeedButton, { - elemDescription: 'Import Seed Button in Onboarding Sheet', + await UnifiedGestures.waitAndTap(this.importSeedButton, { + description: 'Import Seed Button in Onboarding Sheet', + }); + } + + async isVisible(): Promise { + await encapsulatedAction({ + appium: async () => { + const el = await asPlaywrightElement(this.importSeedButton); + await el.waitForDisplayed({ timeout: 10000 }); + }, }); } } diff --git a/tests/page-objects/Onboarding/OnboardingSuccessView.ts b/tests/page-objects/Onboarding/OnboardingSuccessView.ts index c61cbf3f343..68000e456e6 100644 --- a/tests/page-objects/Onboarding/OnboardingSuccessView.ts +++ b/tests/page-objects/Onboarding/OnboardingSuccessView.ts @@ -1,19 +1,42 @@ import { OnboardingSuccessSelectorIDs } from '../../../app/components/Views/OnboardingSuccess/OnboardingSuccess.testIds'; import Matchers from '../../framework/Matchers'; -import Gestures from '../../framework/Gestures'; +import UnifiedGestures from '../../framework/UnifiedGestures'; +import { + encapsulated, + EncapsulatedElementType, + asPlaywrightElement, +} from '../../framework/EncapsulatedElement'; +import { encapsulatedAction } from '../../framework/encapsulatedAction'; +import PlaywrightMatchers from '../../framework/PlaywrightMatchers'; class OnboardingSuccessView { get container(): DetoxElement { return Matchers.getElementByID(OnboardingSuccessSelectorIDs.CONTAINER_ID); } - get doneButton(): DetoxElement { - return Matchers.getElementByID(OnboardingSuccessSelectorIDs.DONE_BUTTON); + get doneButton(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID(OnboardingSuccessSelectorIDs.DONE_BUTTON), + appium: () => + PlaywrightMatchers.getElementById( + OnboardingSuccessSelectorIDs.DONE_BUTTON, + ), + }); } async tapDone(): Promise { - await Gestures.waitAndTap(this.doneButton, { - elemDescription: 'Onboarding Success Done Button', + await UnifiedGestures.waitAndTap(this.doneButton, { + description: 'Onboarding Success Done Button', + }); + } + + async isVisible(): Promise { + await encapsulatedAction({ + appium: async () => { + const el = await asPlaywrightElement(this.doneButton); + await el.waitForDisplayed({ timeout: 10000 }); + }, }); } } diff --git a/tests/page-objects/Onboarding/OnboardingView.ts b/tests/page-objects/Onboarding/OnboardingView.ts index d57a4cfa1bd..e14054653d1 100644 --- a/tests/page-objects/Onboarding/OnboardingView.ts +++ b/tests/page-objects/Onboarding/OnboardingView.ts @@ -1,31 +1,59 @@ import { OnboardingSelectorIDs } from '../../../app/components/Views/Onboarding/Onboarding.testIds'; import Matchers from '../../framework/Matchers'; -import Gestures from '../../framework/Gestures'; +import UnifiedGestures from '../../framework/UnifiedGestures'; +import { + encapsulated, + EncapsulatedElementType, + asPlaywrightElement, +} from '../../framework/EncapsulatedElement'; +import { encapsulatedAction } from '../../framework/encapsulatedAction'; +import PlaywrightMatchers from '../../framework/PlaywrightMatchers'; class OnboardingView { get container(): DetoxElement { return Matchers.getElementByID(OnboardingSelectorIDs.CONTAINER_ID); } - get existingWalletButton() { - return Matchers.getElementByID( - OnboardingSelectorIDs.EXISTING_WALLET_BUTTON, - ); + get existingWalletButton(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID(OnboardingSelectorIDs.EXISTING_WALLET_BUTTON), + appium: () => + PlaywrightMatchers.getElementById( + OnboardingSelectorIDs.EXISTING_WALLET_BUTTON, + ), + }); } - get newWalletButton(): DetoxElement { - return Matchers.getElementByID(OnboardingSelectorIDs.NEW_WALLET_BUTTON); + get newWalletButton(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID(OnboardingSelectorIDs.NEW_WALLET_BUTTON), + appium: () => + PlaywrightMatchers.getElementById( + OnboardingSelectorIDs.NEW_WALLET_BUTTON, + ), + }); } async tapCreateWallet(): Promise { - await Gestures.waitAndTap(this.newWalletButton, { - elemDescription: 'Onboarding - Create New Wallet Button', + await UnifiedGestures.waitAndTap(this.newWalletButton, { + description: 'Onboarding - Create New Wallet Button', + }); + } + + async tapHaveAnExistingWallet(): Promise { + await UnifiedGestures.waitAndTap(this.existingWalletButton, { + description: 'Onboarding Have an Existing Wallet Button', }); } - async tapHaveAnExistingWallet() { - await Gestures.waitAndTap(this.existingWalletButton, { - elemDescription: 'Onboarding Have an Existing Wallet Button', + async isScreenTitleVisible(): Promise { + await encapsulatedAction({ + appium: async () => { + const el = await asPlaywrightElement(this.newWalletButton); + await el.waitForDisplayed({ timeout: 30000 }); + }, }); } } diff --git a/tests/page-objects/Perps/PerpsGTMModal.ts b/tests/page-objects/Perps/PerpsGTMModal.ts new file mode 100644 index 00000000000..11d819e0f45 --- /dev/null +++ b/tests/page-objects/Perps/PerpsGTMModal.ts @@ -0,0 +1,57 @@ +import { PerpsGTMModalSelectorsIDs } from '../../../app/components/UI/Perps/Perps.testIds'; +import Matchers from '../../framework/Matchers'; +import UnifiedGestures from '../../framework/UnifiedGestures'; +import { + encapsulated, + EncapsulatedElementType, +} from '../../framework/EncapsulatedElement'; +import PlaywrightMatchers from '../../framework/PlaywrightMatchers'; + +class PerpsGTMModal { + get container(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID(PerpsGTMModalSelectorsIDs.PERPS_GTM_MODAL), + appium: () => + PlaywrightMatchers.getElementById( + PerpsGTMModalSelectorsIDs.PERPS_GTM_MODAL, + ), + }); + } + + get notNowButton(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID(PerpsGTMModalSelectorsIDs.PERPS_NOT_NOW_BUTTON), + appium: () => + PlaywrightMatchers.getElementById( + PerpsGTMModalSelectorsIDs.PERPS_NOT_NOW_BUTTON, + ), + }); + } + + get getStartedButton(): EncapsulatedElementType { + return encapsulated({ + detox: () => + Matchers.getElementByID(PerpsGTMModalSelectorsIDs.PERPS_TRY_NOW_BUTTON), + appium: () => + PlaywrightMatchers.getElementById( + PerpsGTMModalSelectorsIDs.PERPS_TRY_NOW_BUTTON, + ), + }); + } + + async tapNotNowButton(): Promise { + await UnifiedGestures.waitAndTap(this.notNowButton, { + description: 'Perps GTM Not Now Button', + }); + } + + async tapGetStartedButton(): Promise { + await UnifiedGestures.waitAndTap(this.getStartedButton, { + description: 'Perps GTM Get Started Button', + }); + } +} + +export default new PerpsGTMModal(); diff --git a/tests/page-objects/Rewards/RewardsGTMModal.ts b/tests/page-objects/Rewards/RewardsGTMModal.ts new file mode 100644 index 00000000000..bc3bfb6296d --- /dev/null +++ b/tests/page-objects/Rewards/RewardsGTMModal.ts @@ -0,0 +1,41 @@ +import UnifiedGestures from '../../framework/UnifiedGestures'; +import { + encapsulated, + EncapsulatedElementType, + asPlaywrightElement, +} from '../../framework/EncapsulatedElement'; +import { encapsulatedAction } from '../../framework/encapsulatedAction'; +import PlaywrightMatchers from '../../framework/PlaywrightMatchers'; +import { REWARDS_VIEW_SELECTORS } from '../../../app/components/UI/Rewards/Views/RewardsView.constants'; + +class RewardsGTMModal { + get notNowButton(): EncapsulatedElementType { + return encapsulated({ + appium: () => + PlaywrightMatchers.getElementById(REWARDS_VIEW_SELECTORS.SKIP_BUTTON), + }); + } + + get container(): EncapsulatedElementType { + return encapsulated({ + appium: () => PlaywrightMatchers.getElementByCatchAll('Rewards are here'), + }); + } + + async isVisible(): Promise { + await encapsulatedAction({ + appium: async () => { + const el = await asPlaywrightElement(this.container); + await el.waitForDisplayed(); + }, + }); + } + + async tapNotNowButton(): Promise { + await UnifiedGestures.tap(this.notNowButton, { + description: 'Rewards GTM Not Now Button', + }); + } +} + +export default new RewardsGTMModal(); diff --git a/tests/page-objects/migrated-page-objects.test.ts b/tests/page-objects/migrated-page-objects.test.ts index faf06c1296c..7a5422f64c1 100644 --- a/tests/page-objects/migrated-page-objects.test.ts +++ b/tests/page-objects/migrated-page-objects.test.ts @@ -23,6 +23,8 @@ jest.mock('../framework/PlaywrightMatchers.ts', () => ({ getElementById: jest.fn().mockResolvedValue({}), getElementByText: jest.fn().mockResolvedValue({}), getElementByAccessibilityId: jest.fn().mockResolvedValue({}), + getElementByXPath: jest.fn().mockResolvedValue({}), + getElementByCatchAll: jest.fn().mockResolvedValue({}), }, })); diff --git a/tests/page-objects/wallet/AccountListBottomSheet.ts b/tests/page-objects/wallet/AccountListBottomSheet.ts index c23494763e1..60ee104db72 100644 --- a/tests/page-objects/wallet/AccountListBottomSheet.ts +++ b/tests/page-objects/wallet/AccountListBottomSheet.ts @@ -12,8 +12,11 @@ import UnifiedGestures from '../../framework/UnifiedGestures'; import { encapsulated, EncapsulatedElementType, + asPlaywrightElement, } from '../../framework/EncapsulatedElement'; +import { encapsulatedAction } from '../../framework/encapsulatedAction'; import PlaywrightMatchers from '../../framework/PlaywrightMatchers'; +import PlaywrightGestures from '../../framework/PlaywrightGestures'; class AccountListBottomSheet { /** Account list container - wdio uses getElementByText('Accounts') for Appium */ @@ -61,6 +64,13 @@ class AccountListBottomSheet { }); } + get addWalletButton(): EncapsulatedElementType { + return encapsulated({ + appium: () => + PlaywrightMatchers.getElementById('account-list-add-account-button'), + }); + } + get addEthereumAccountButton(): DetoxElement { return Matchers.getElementByText( AccountListBottomSheetSelectorsText.ADD_ETHEREUM_ACCOUNT, @@ -282,6 +292,69 @@ class AccountListBottomSheet { // Second swipe to dismiss the AccountListBottomSheet await this.swipeToDismissAccountsModal(); } + + async isComponentDisplayed(): Promise { + await encapsulatedAction({ + appium: async () => { + const el = await asPlaywrightElement(this.accountList); + await el.waitForDisplayed({ timeout: 10000 }); + }, + }); + } + + async tapOnAddWalletButton(): Promise { + await UnifiedGestures.tap(this.addWalletButton, { + description: 'Add Wallet Button', + }); + } + + async tapOnAccountByName(name: string): Promise { + await encapsulatedAction({ + appium: async () => { + const account = await PlaywrightMatchers.getElementByText(name); + await PlaywrightGestures.scrollIntoView(account); + await account.click(); + }, + }); + } + + async waitForSyncingToComplete(timeout: number = 60000): Promise { + await encapsulatedAction({ + appium: async () => { + const syncingElement = + await PlaywrightMatchers.getElementByCatchAll('Syncing'); + const discoveringElement = + await PlaywrightMatchers.getElementByCatchAll('Discovering'); + + // Step 1: Wait up to 5s for either "Syncing" or "Discovering" to appear + const syncingDetected = await Promise.race([ + syncingElement + .waitForDisplayed({ timeout: 5000 }) + .then(() => true) + .catch(() => false), + discoveringElement + .waitForDisplayed({ timeout: 5000 }) + .then(() => true) + .catch(() => false), + ]); + + if (!syncingDetected) return; + + // Step 2: Wait for "Syncing" to disappear + await syncingElement + .waitForDisplayed({ timeout, reverse: true }) + .catch(() => undefined); + + // Step 3: Brief pause before checking discovery state + await new Promise((resolve) => setTimeout(resolve, 1000)); + + // Step 4: Wait for "Discovering" to disappear + await discoveringElement + .waitForDisplayed({ timeout, reverse: true }) + .catch(() => undefined); + }, + }); + } } export default new AccountListBottomSheet(); diff --git a/tests/page-objects/wallet/AddAccountBottomSheet.ts b/tests/page-objects/wallet/AddAccountBottomSheet.ts index 12fca277d59..380d22501ae 100644 --- a/tests/page-objects/wallet/AddAccountBottomSheet.ts +++ b/tests/page-objects/wallet/AddAccountBottomSheet.ts @@ -5,7 +5,9 @@ import UnifiedGestures from '../../framework/UnifiedGestures'; import { encapsulated, EncapsulatedElementType, + asPlaywrightElement, } from '../../framework/EncapsulatedElement'; +import { encapsulatedAction } from '../../framework/encapsulatedAction'; import PlaywrightMatchers from '../../framework/PlaywrightMatchers'; class AddAccountBottomSheet { @@ -64,6 +66,15 @@ class AddAccountBottomSheet { elemDescription: 'Add Solana Account button', }); } + + async isVisible(): Promise { + await encapsulatedAction({ + appium: async () => { + const el = await asPlaywrightElement(this.importSrpButton); + await el.waitForDisplayed({ timeout: 20000 }); + }, + }); + } } export default new AddAccountBottomSheet(); diff --git a/tests/page-objects/wallet/WalletView.ts b/tests/page-objects/wallet/WalletView.ts index 88f96ab29a5..00ac0f77fba 100644 --- a/tests/page-objects/wallet/WalletView.ts +++ b/tests/page-objects/wallet/WalletView.ts @@ -2,6 +2,7 @@ import { WalletViewSelectorsIDs, WalletViewSelectorsText, } from '../../../app/components/Views/Wallet/WalletView.testIds'; +import { TabBarSelectorIDs } from '../../../app/components/Nav/Main/TabBar.testIds'; import { EARN_TEST_IDS } from '../../../app/components/UI/Earn/constants/testIds'; import { SECONDARY_BALANCE_BUTTON_TEST_ID } from '../../../app/components/UI/AssetElement/index.constants'; import { @@ -95,8 +96,27 @@ class WalletView { ); } - get accountIcon(): DetoxElement { - return Matchers.getElementByID(WalletViewSelectorsIDs.ACCOUNT_ICON); + get accountIcon(): EncapsulatedElementType { + return encapsulated({ + detox: () => Matchers.getElementByID(WalletViewSelectorsIDs.ACCOUNT_ICON), + appium: { + android: () => + PlaywrightMatchers.getElementById( + WalletViewSelectorsIDs.ACCOUNT_ICON, + ), + ios: () => + PlaywrightMatchers.getElementByCatchAll( + WalletViewSelectorsIDs.ACCOUNT_ICON, + ), + }, + }); + } + + get walletButton(): EncapsulatedElementType { + return encapsulated({ + detox: () => Matchers.getElementByID(TabBarSelectorIDs.WALLET), + appium: () => PlaywrightMatchers.getElementById(TabBarSelectorIDs.WALLET), + }); } get eyeSlashIcon(): DetoxElement { @@ -299,8 +319,17 @@ class WalletView { } async tapIdenticon(): Promise { - await Gestures.waitAndTap(this.accountIcon, { - elemDescription: 'Top Account Icon', + await UnifiedGestures.waitAndTap(this.accountIcon, { + description: 'Top Account Icon', + }); + } + + async isMainWalletViewVisible(): Promise { + await encapsulatedAction({ + appium: async () => { + const el = await asPlaywrightElement(this.walletButton); + await el.waitForDisplayed({ timeout: 30000 }); + }, }); } diff --git a/wdio/screen-objects/AccountListComponent.js b/wdio/screen-objects/AccountListComponent.js index 7a1ea1b7000..4e4bec06b08 100644 --- a/wdio/screen-objects/AccountListComponent.js +++ b/wdio/screen-objects/AccountListComponent.js @@ -7,6 +7,7 @@ import AppwrightSelectors from '../../tests/framework/AppwrightSelectors'; import AppwrightGestures from '../../tests/framework/AppwrightGestures'; import { expect } from 'appwright'; +// Methods migrated to tests/page-objects/wallet/AccountListBottomSheet.ts: isComponentDisplayed, tapOnAddWalletButton, tapOnAccountByName, waitForSyncingToComplete class AccountListComponent { get device() { diff --git a/wdio/screen-objects/Modals/AddAccountModal.js b/wdio/screen-objects/Modals/AddAccountModal.js index f19ee206954..b10500c01aa 100644 --- a/wdio/screen-objects/Modals/AddAccountModal.js +++ b/wdio/screen-objects/Modals/AddAccountModal.js @@ -5,6 +5,7 @@ import AppwrightSelectors from '../../../tests/framework/AppwrightSelectors'; import AppwrightGestures from '../../../tests/framework/AppwrightGestures'; import { expect as appwrightExpect } from 'appwright'; +// Methods migrated to tests/page-objects/wallet/AddAccountBottomSheet.ts: isVisible, tapImportSrpButton class AddAccountModal { get device() { diff --git a/wdio/screen-objects/Modals/MultichainAccountEducationModal.js b/wdio/screen-objects/Modals/MultichainAccountEducationModal.js index e0d29a0a127..d88394bc8fb 100644 --- a/wdio/screen-objects/Modals/MultichainAccountEducationModal.js +++ b/wdio/screen-objects/Modals/MultichainAccountEducationModal.js @@ -5,6 +5,7 @@ import AppwrightGestures from "../../../tests/framework/AppwrightGestures"; import { expect } from 'appwright'; import { MULTICHAIN_ACCOUNTS_INTRO_MODAL_TEST_IDS } from '../../../app/components/Views/MultichainAccounts/IntroModal/testIds'; +// Methods migrated to tests/page-objects/Onboarding/MultichainAccountEducationModal.ts: isVisible, tapGotItButton class MultichainAccountEducationModal { get device() { diff --git a/wdio/screen-objects/Modals/PerpsGTMModal.js b/wdio/screen-objects/Modals/PerpsGTMModal.js index 46c02dc36fa..703bfaff0bb 100644 --- a/wdio/screen-objects/Modals/PerpsGTMModal.js +++ b/wdio/screen-objects/Modals/PerpsGTMModal.js @@ -5,6 +5,7 @@ import AppwrightGestures from "../../../tests/framework/AppwrightGestures"; import { expect } from 'appwright'; import { PerpsGTMModalSelectorsIDs } from '../../../app/components/UI/Perps/Perps.testIds'; +// Methods migrated to tests/page-objects/Perps/PerpsGTMModal.ts: tapNotNowButton, tapGetStartedButton class PerpsGTMModal { get device() { diff --git a/wdio/screen-objects/Modals/RewardsGTMModal.js b/wdio/screen-objects/Modals/RewardsGTMModal.js index b25db2ff411..23f4e90fbae 100644 --- a/wdio/screen-objects/Modals/RewardsGTMModal.js +++ b/wdio/screen-objects/Modals/RewardsGTMModal.js @@ -4,6 +4,7 @@ import AppwrightSelectors from '../../../tests/framework/AppwrightSelectors'; import AppwrightGestures from "../../../tests/framework/AppwrightGestures"; import { expect as appwrightExpect } from 'appwright'; +// Methods migrated to tests/page-objects/Rewards/RewardsGTMModal.ts: isVisible, tapNotNowButton class RewardsGTMModal { get device() { diff --git a/wdio/screen-objects/Onboarding/CreatePasswordScreen.js b/wdio/screen-objects/Onboarding/CreatePasswordScreen.js index b1c03b715e9..c96448c106f 100644 --- a/wdio/screen-objects/Onboarding/CreatePasswordScreen.js +++ b/wdio/screen-objects/Onboarding/CreatePasswordScreen.js @@ -7,6 +7,7 @@ import AppwrightGestures from '../../../tests/framework/AppwrightGestures'; import { CONFIRM_PASSWORD_INPUT_FIRST_FIELD, CREATE_PASSWORD_INPUT_FIRST_FIELD } from '../testIDs/Screens/WalletSetupScreen.testIds'; import { expect as appwrightExpect } from 'appwright'; +// Methods migrated to tests/page-objects/Onboarding/CreatePasswordView.ts: enterPassword, reEnterPassword, tapIUnderstandCheckBox, tapCreatePasswordButton, isVisible class CreatePasswordScreen { get device() { diff --git a/wdio/screen-objects/Onboarding/ImportFromSeedScreen.js b/wdio/screen-objects/Onboarding/ImportFromSeedScreen.js index 3b48c8be026..380da94422b 100644 --- a/wdio/screen-objects/Onboarding/ImportFromSeedScreen.js +++ b/wdio/screen-objects/Onboarding/ImportFromSeedScreen.js @@ -5,6 +5,7 @@ import AppwrightGestures from '../../../tests/framework/AppwrightGestures'; import AppwrightSelectors from '../../../tests/framework/AppwrightSelectors'; import { expect as appwrightExpect } from 'appwright'; +// Methods migrated to tests/page-objects/Onboarding/ImportWalletView.ts: isScreenTitleVisible, typeSecretRecoveryPhrase, tapImportScreenTitleToDismissKeyboard, tapContinueButton class ImportFromSeedScreen { get device() { diff --git a/wdio/screen-objects/Onboarding/MetaMetricsScreen.js b/wdio/screen-objects/Onboarding/MetaMetricsScreen.js index e46f88ee95c..e7704256b72 100644 --- a/wdio/screen-objects/Onboarding/MetaMetricsScreen.js +++ b/wdio/screen-objects/Onboarding/MetaMetricsScreen.js @@ -10,6 +10,7 @@ import AppwrightSelectors from '../../../tests/framework/AppwrightSelectors'; import AppwrightGestures from '../../../tests/framework/AppwrightGestures'; import { expect as appwrightExpect } from 'appwright'; +// Methods migrated to tests/page-objects/Onboarding/MetaMetricsOptInView.ts: isScreenTitleVisible, tapIAgreeButton class MetaMetricsScreen { get device() { diff --git a/wdio/screen-objects/Onboarding/OnboardingScreen.js b/wdio/screen-objects/Onboarding/OnboardingScreen.js index 5209a37cf7c..2ce5fcb551a 100644 --- a/wdio/screen-objects/Onboarding/OnboardingScreen.js +++ b/wdio/screen-objects/Onboarding/OnboardingScreen.js @@ -5,6 +5,7 @@ import AppwrightSelectors from '../../../tests/framework/AppwrightSelectors'; import AppwrightGestures from '../../../tests/framework/AppwrightGestures'; import { expect as appwrightExpect } from 'appwright'; +// Methods migrated to tests/page-objects/Onboarding/OnboardingView.ts: tapHaveAnExistingWallet, tapCreateNewWalletButton, isScreenTitleVisible class OnBoardingScreen { get device() { diff --git a/wdio/screen-objects/Onboarding/OnboardingSheet.js b/wdio/screen-objects/Onboarding/OnboardingSheet.js index 91fcdcf21d2..708534d09ac 100644 --- a/wdio/screen-objects/Onboarding/OnboardingSheet.js +++ b/wdio/screen-objects/Onboarding/OnboardingSheet.js @@ -5,6 +5,7 @@ import AppwrightSelectors from '../../../tests/framework/AppwrightSelectors'; import AppwrightGestures from '../../../tests/framework/AppwrightGestures'; import { expect as appwrightExpect } from 'appwright'; +// Methods migrated to tests/page-objects/Onboarding/OnboardingSheet.ts: tapImportSeedButton, isVisible class OnboardingSheet { get device() { diff --git a/wdio/screen-objects/OnboardingSucessScreen.js b/wdio/screen-objects/OnboardingSucessScreen.js index fb6ec9ea997..c24316fd0ca 100644 --- a/wdio/screen-objects/OnboardingSucessScreen.js +++ b/wdio/screen-objects/OnboardingSucessScreen.js @@ -4,6 +4,7 @@ import Gestures from '../helpers/Gestures'; import AppwrightSelectors from '../../tests/framework/AppwrightSelectors'; import { expect as appwrightExpect } from 'appwright'; +// Methods migrated to tests/page-objects/Onboarding/OnboardingSuccessView.ts: isVisible, tapDone class OnboardingSuccessView { diff --git a/wdio/screen-objects/WalletMainScreen.js b/wdio/screen-objects/WalletMainScreen.js index c6bc3351d42..4c248e65ba8 100644 --- a/wdio/screen-objects/WalletMainScreen.js +++ b/wdio/screen-objects/WalletMainScreen.js @@ -12,6 +12,7 @@ import AppwrightGestures from '../../tests/framework/AppwrightGestures'; import { expect as appwrightExpect } from 'appwright'; import TimerHelper from '../../tests/framework/TimerHelper'; +// Methods migrated to tests/page-objects/wallet/WalletView.ts: tapIdenticon, isMainWalletViewVisible, waitForBalanceToStabilize class WalletMainScreen { get device() {