From b0073ab42d1bb3bf9a82d11ca2daeceb4853015a Mon Sep 17 00:00:00 2001 From: Vlad Novak Date: Mon, 1 Jul 2024 21:36:26 +0300 Subject: [PATCH 1/5] verify mnemonic step --- e2e/playwright.config.ts | 1 + e2e/src/classes/page.class.ts | 2 +- e2e/src/fixtures/extension.ts | 3 +- e2e/src/page-objects/index.ts | 4 +- .../pages/manage-assets-tokens.page.ts | 1 + .../pages/manual-backup-modal.page.ts | 27 +++++++++ .../pages/setWalletPassword.page.ts | 2 + e2e/src/tests/import-wallet-2.test.ts | 59 ++++++++++++++++--- src/app/atoms/PageModal/index.tsx | 6 +- src/app/atoms/PageModal/scroll-view.tsx | 12 +++- .../backup-options-modal.tsx | 8 ++- src/app/templates/ManualBackupModal/index.tsx | 1 + .../ManualBackupModal/mnemonic-view.tsx | 15 +++-- .../templates/ManualBackupModal/selectors.ts | 5 +- .../verify-seed-phrase-input/index.tsx | 6 ++ .../verify-seed-phrase-input/word-input.tsx | 14 ++++- .../words-box-item.tsx | 7 ++- 17 files changed, 146 insertions(+), 27 deletions(-) create mode 100644 e2e/src/page-objects/pages/manual-backup-modal.page.ts diff --git a/e2e/playwright.config.ts b/e2e/playwright.config.ts index 5fb527eba5..75bad46f55 100644 --- a/e2e/playwright.config.ts +++ b/e2e/playwright.config.ts @@ -1,6 +1,7 @@ import { PlaywrightTestConfig } from '@playwright/test'; const config: PlaywrightTestConfig = { + timeout: 1000 * 5 * 60, fullyParallel: false, testDir: './src', workers: 1, diff --git a/e2e/src/classes/page.class.ts b/e2e/src/classes/page.class.ts index 7a242f5dfc..68c649717a 100644 --- a/e2e/src/classes/page.class.ts +++ b/e2e/src/classes/page.class.ts @@ -1,7 +1,7 @@ import { CustomBrowserContext } from './browser-context.class'; export abstract class Page { - abstract isVisible(timeout?: number): void; + abstract isVisible(...args: any[]): void; scrollTo(topPositionPx: number) { return CustomBrowserContext.page.evaluate(top => { diff --git a/e2e/src/fixtures/extension.ts b/e2e/src/fixtures/extension.ts index 2fa4795fe4..0211d04115 100644 --- a/e2e/src/fixtures/extension.ts +++ b/e2e/src/fixtures/extension.ts @@ -34,7 +34,8 @@ export async function openBrowser() { browser = await chromium.launchPersistentContext('', { headless: false, args: [`--disable-extensions-except=${pathToExtension}`, `--load-extension=${pathToExtension}`], - recordVideo: { dir: 'test-results/' } + recordVideo: { dir: 'test-results/' }, + slowMo: 500 }); return browser; diff --git a/e2e/src/page-objects/index.ts b/e2e/src/page-objects/index.ts index 32c8a9a9f1..1710807065 100644 --- a/e2e/src/page-objects/index.ts +++ b/e2e/src/page-objects/index.ts @@ -6,6 +6,7 @@ import { ConfirmationModalPage } from '../page-objects/pages/confirmation-modal. import { GeneralSettingsPage } from '../page-objects/pages/general-settings.page'; import { ManageAssetsCollectiblesPage } from '../page-objects/pages/manage-assets-collectibles.page'; import { ManageAssetsTokensPage } from '../page-objects/pages/manage-assets-tokens.page'; +import { ManualBackupModalPage } from '../page-objects/pages/manual-backup-modal.page'; import { NetworksPage } from '../page-objects/pages/networks.page'; import { NewsletterModalPage } from '../page-objects/pages/newsletter-modal.page'; import { NotificationContentPage } from '../page-objects/pages/notification-content.page'; @@ -50,5 +51,6 @@ export const Pages = { CollectiblesTabPage: new CollectiblesTabPage(), NotificationsList: new NotificationsListPage(), NotificationContent: new NotificationContentPage(), - GeneralSettings: new GeneralSettingsPage() + GeneralSettings: new GeneralSettingsPage(), + ManualBackupModal: new ManualBackupModalPage() }; diff --git a/e2e/src/page-objects/pages/manage-assets-tokens.page.ts b/e2e/src/page-objects/pages/manage-assets-tokens.page.ts index 596afcb56b..4d02d36043 100644 --- a/e2e/src/page-objects/pages/manage-assets-tokens.page.ts +++ b/e2e/src/page-objects/pages/manage-assets-tokens.page.ts @@ -8,6 +8,7 @@ export class ManageAssetsTokensPage extends Page { searchAssetsInput = createPageElement(ManageAssetsSelectors.searchAssetsInput); assetItem = createPageElement(ManageAssetsSelectors.assetItem); deleteAssetButton = createPageElement(ManageAssetsSelectors.deleteAssetButton); + deleteAssetButton = createPageElement(ManageAssetsSelectors.deleteAssetButton); async isVisible() { await this.addAssetButton.waitForDisplayed(); diff --git a/e2e/src/page-objects/pages/manual-backup-modal.page.ts b/e2e/src/page-objects/pages/manual-backup-modal.page.ts new file mode 100644 index 0000000000..647e1283c2 --- /dev/null +++ b/e2e/src/page-objects/pages/manual-backup-modal.page.ts @@ -0,0 +1,27 @@ +import { ManualBackupModalSelectors } from 'src/app/templates/ManualBackupModal/selectors'; + +import { Page } from '../../classes/page.class'; +import { createPageElement } from '../../utils/search.utils'; + +export class ManualBackupModalPage extends Page { + confirmButton = createPageElement(ManualBackupModalSelectors.confirmButton); + cancelButton = createPageElement(ManualBackupModalSelectors.cancelButton); + notedDownButton = createPageElement(ManualBackupModalSelectors.notedDownButton); + protectedMask = createPageElement(ManualBackupModalSelectors.protectedMask); + wordIndex = createPageElement(ManualBackupModalSelectors.wordIndex); + seedWordButton = createPageElement(ManualBackupModalSelectors.seedWordButton); + + async isVisible(modalPage: string) { + if (modalPage == 'Backup your Seed Phrase') { + await this.notedDownButton.waitForDisplayed(); + await this.protectedMask.waitForDisplayed(); + } + + if (modalPage == 'Verify Seed Phrase') { + await this.confirmButton.waitForDisplayed(); + await this.cancelButton.waitForDisplayed(); + await this.wordIndex.waitForDisplayed(); + await this.seedWordButton.waitForDisplayed(); + } + } +} diff --git a/e2e/src/page-objects/pages/setWalletPassword.page.ts b/e2e/src/page-objects/pages/setWalletPassword.page.ts index e883666e2b..76fa7b14b0 100644 --- a/e2e/src/page-objects/pages/setWalletPassword.page.ts +++ b/e2e/src/page-objects/pages/setWalletPassword.page.ts @@ -9,11 +9,13 @@ export class setWalletPage extends Page { analyticsCheckbox = createPageElement(setWalletPasswordSelectors.analyticsCheckBox); acceptTerms = createPageElement(setWalletPasswordSelectors.acceptTermsCheckbox); importButton = createPageElement(setWalletPasswordSelectors.importButton); + createButton = createPageElement(setWalletPasswordSelectors.createButton); async isVisible() { await this.passwordField.waitForDisplayed(); await this.repeatPasswordField.waitForDisplayed(); await this.analyticsCheckbox.waitForDisplayed(); await this.acceptTerms.waitForDisplayed(); + await this.createButton.waitForDisplayed(); } } diff --git a/e2e/src/tests/import-wallet-2.test.ts b/e2e/src/tests/import-wallet-2.test.ts index d057c4ffae..c1a31b2f44 100644 --- a/e2e/src/tests/import-wallet-2.test.ts +++ b/e2e/src/tests/import-wallet-2.test.ts @@ -1,21 +1,62 @@ +import { setWalletPasswordSelectors } from 'src/app/pages/NewWallet/setWalletPassword/SetWalletPassword.selectors'; +import { ManualBackupModalSelectors } from 'src/app/templates/ManualBackupModal/selectors'; + +import { CustomBrowserContext } from 'e2e/src/classes/browser-context.class'; +import { findElements } from 'e2e/src/utils/search.utils'; +import { sleep } from 'e2e/src/utils/timing.utils'; + import { test } from '../fixtures/extension'; import { describeScenario } from '../fixtures/hooks'; import { Pages } from '../page-objects'; import { envVars } from '../utils/env.utils'; -describeScenario('Import Wallet 2', () => { - test('Import Wallet: positive scenario (clone)', async () => { - await Pages.Welcome.importExistingWalletButton.waitForDisplayed(); - await Pages.Welcome.importExistingWalletButton.click(); - await Pages.ImportExistingWallet.enterSeedPhrase(envVars.DEFAULT_HD_ACCOUNT_SEED_PHRASE); - await Pages.ImportExistingWallet.nextButton.click(); +describeScenario('Create new wallet', () => { + test('Create new wallet: positive', { tag: '@create' }, async () => { + await Pages.Welcome.isVisible(); + await Pages.Welcome.createNewWalletButton.waitForDisplayed(); + await Pages.Welcome.createNewWalletButton.click(); await Pages.SetWallet.passwordField.fill(envVars.DEFAULT_PASSWORD); await Pages.SetWallet.repeatPasswordField.fill(envVars.DEFAULT_PASSWORD); + await Pages.SetWallet.createButton.click(); + + await CustomBrowserContext.page.getByTestId('Backup Options Modal/Manual Backup Button').click(); + await CustomBrowserContext.page.getByTestId('lalala').focus(); + await CustomBrowserContext.page.getByTestId('lalala').click(); + await sleep(2000); + const seedValue = (await CustomBrowserContext.page.getByTestId('lalala').textContent()) as string; + console.log('seed: ', seedValue); + const seedValueArray = seedValue?.split(' '); + + await Pages.ManualBackupModal.notedDownButton.click(); + await sleep(2000); + + const wordsButtonArray = await findElements(ManualBackupModalSelectors.seedWordButton); + console.log('words buutons count is ', wordsButtonArray.length); + + const wordsIndexArray = await findElements(ManualBackupModalSelectors.wordIndex); + console.log('index count is ', wordsIndexArray.length); + + for (let wordIndex = 0; wordIndex < wordsButtonArray.length; wordIndex++) { + const wordIndexValue = await wordsIndexArray[wordIndex].textContent().then((text: string) => { + return Number(text.replace('.', '')); + }); + + console.log('pure index is', wordIndexValue); - await Pages.SetWallet.acceptTerms.click(); - await Pages.SetWallet.importButton.click(); + for (let wordIndex = 1; wordIndex < seedValueArray.length * 3; wordIndex++) { + if (wordIndex === wordIndexValue) { + console.log('match??', seedValueArray[wordIndexValue - 1]); - await Pages.NewsletterModal.closeButton.click(); + for (let seedWordIndex = 0; seedWordIndex < wordsButtonArray.length; seedWordIndex++) { + const seedWordButtonValue = wordsButtonArray[seedWordIndex]; + if ((await seedWordButtonValue.textContent()) == seedValueArray[wordIndexValue - 1]) { + await seedWordButtonValue.click(); + } + } + } + } + } + await sleep(500000); }); }); diff --git a/src/app/atoms/PageModal/index.tsx b/src/app/atoms/PageModal/index.tsx index df6d3c4e00..043c338722 100644 --- a/src/app/atoms/PageModal/index.tsx +++ b/src/app/atoms/PageModal/index.tsx @@ -9,11 +9,12 @@ import { ReactComponent as ChevronLeftIcon } from 'app/icons/base/chevron_left.s import { ReactComponent as ExIcon } from 'app/icons/base/x.svg'; import { LAYOUT_CONTAINER_CLASSNAME } from 'app/layouts/containers'; +import { TestIDProps } from '../../../lib/analytics'; import { IconBase } from '../IconBase'; import ModStyles from './styles.module.css'; -interface Props { +interface Props extends TestIDProps { title: string; opened: boolean; shouldShowBackButton?: boolean; @@ -22,7 +23,7 @@ interface Props { } export const PageModal = memo>( - ({ title, opened, shouldShowBackButton, onRequestClose, onGoBack, children }) => { + ({ title, opened, shouldShowBackButton, onRequestClose, onGoBack, children, testID }) => { const { fullPage } = useAppEnv(); return ( @@ -49,6 +50,7 @@ export const PageModal = memo>( }} appElement={document.getElementById('root')!} onRequestClose={onRequestClose} + testId={testID} >
diff --git a/src/app/atoms/PageModal/scroll-view.tsx b/src/app/atoms/PageModal/scroll-view.tsx index 9bae942a03..bea9bb2fd9 100644 --- a/src/app/atoms/PageModal/scroll-view.tsx +++ b/src/app/atoms/PageModal/scroll-view.tsx @@ -4,7 +4,9 @@ import clsx from 'clsx'; import { useScrollEdgesVisibility } from 'app/hooks/use-scroll-edges-visibility'; -interface ScrollViewProps extends HTMLAttributes { +import { setTestID, TestIDProps } from '../../../lib/analytics'; + +interface ScrollViewProps extends HTMLAttributes, TestIDProps { onBottomEdgeVisibilityChange?: SyncFn; bottomEdgeThreshold?: number; onTopEdgeVisibilityChange?: SyncFn; @@ -18,6 +20,7 @@ export const ScrollView = memo( bottomEdgeThreshold, onTopEdgeVisibilityChange, topEdgeThreshold, + testID, ...restProps }) => { const rootRef = useRef(null); @@ -31,7 +34,12 @@ export const ScrollView = memo( ); return ( -
+
); } ); diff --git a/src/app/layouts/PageLayout/BackupMnemonicOverlay/backup-options-modal.tsx b/src/app/layouts/PageLayout/BackupMnemonicOverlay/backup-options-modal.tsx index b4fde13f8c..146c02b387 100644 --- a/src/app/layouts/PageLayout/BackupMnemonicOverlay/backup-options-modal.tsx +++ b/src/app/layouts/PageLayout/BackupMnemonicOverlay/backup-options-modal.tsx @@ -24,7 +24,13 @@ export const BackupOptionsModal = memo(({ onSelect }) = {t('useGoogleDrive')} - + {t('backupManually')} diff --git a/src/app/templates/ManualBackupModal/index.tsx b/src/app/templates/ManualBackupModal/index.tsx index b44674fbca..e27ab84624 100644 --- a/src/app/templates/ManualBackupModal/index.tsx +++ b/src/app/templates/ManualBackupModal/index.tsx @@ -36,6 +36,7 @@ export const ManualBackupModal = memo(({ mnemonic, onSuc isNewMnemonic={isNewMnemonic} onCancel={onCancel} onConfirm={goToVerifySeedPhrase} + testID={'vlad'} /> )} diff --git a/src/app/templates/ManualBackupModal/mnemonic-view.tsx b/src/app/templates/ManualBackupModal/mnemonic-view.tsx index 419f0a3e90..6010b29490 100644 --- a/src/app/templates/ManualBackupModal/mnemonic-view.tsx +++ b/src/app/templates/ManualBackupModal/mnemonic-view.tsx @@ -7,16 +7,18 @@ import { ReadOnlySecretField } from 'app/atoms/ReadOnlySecretField'; import { StyledButton } from 'app/atoms/StyledButton'; import { T, TID } from 'lib/i18n'; +import { TestIDProps } from '../../../lib/analytics'; + import { ManualBackupModalSelectors } from './selectors'; -interface MnemonicViewProps { +interface MnemonicViewProps extends TestIDProps { mnemonic: string; isNewMnemonic: boolean; onCancel?: EmptyFn; onConfirm: EmptyFn; } -export const MnemonicView = memo(({ mnemonic, isNewMnemonic, onCancel, onConfirm }) => { +export const MnemonicView = memo(({ mnemonic, isNewMnemonic, onCancel, onConfirm, testID }) => { const [bottomEdgeIsVisible, setBottomEdgeIsVisible] = useState(true); const manualBackupSubstitutions = useMemo(() => { @@ -31,7 +33,12 @@ export const MnemonicView = memo(({ mnemonic, isNewMnemonic, return ( <> - + (({ mnemonic, isNewMnemonic, } /> - + diff --git a/src/app/templates/ManualBackupModal/selectors.ts b/src/app/templates/ManualBackupModal/selectors.ts index 1ea66fc35d..f6cf5e2758 100644 --- a/src/app/templates/ManualBackupModal/selectors.ts +++ b/src/app/templates/ManualBackupModal/selectors.ts @@ -1,5 +1,8 @@ export enum ManualBackupModalSelectors { cancelButton = 'Manual Backup Modal/Cancel Button', confirmButton = 'Manual Backup Modal/Confirm Button', - notedDownButton = 'Manual Backup Modal/Noted Down Button' + notedDownButton = 'Manual Backup Modal/Noted Down Button', + protectedMask = 'Manual Backup Modal/Protected Mask', + wordIndex = 'Manual Backup Modal/Word Index', + seedWordButton = 'Manual Backup Modal/Seed Word Button' } diff --git a/src/app/templates/ManualBackupModal/verify-seed-phrase-input/index.tsx b/src/app/templates/ManualBackupModal/verify-seed-phrase-input/index.tsx index 6d52904b41..7122e8cfb0 100644 --- a/src/app/templates/ManualBackupModal/verify-seed-phrase-input/index.tsx +++ b/src/app/templates/ManualBackupModal/verify-seed-phrase-input/index.tsx @@ -7,6 +7,9 @@ import { FieldLabel } from 'app/atoms/FieldLabel'; import { ReactComponent as XCircleFillIcon } from 'app/icons/base/x_circle_fill.svg'; import { T } from 'lib/i18n'; +import { setTestID } from '../../../../lib/analytics'; +import { ManualBackupModalSelectors } from '../selectors'; + import { WordInput } from './word-input'; import { WordsBoxItem, WordsBoxItemData } from './words-box-item'; @@ -37,6 +40,7 @@ export const VerifySeedPhraseInput = memo( 'relative grid grid-cols-2 rounded-lg p-1.5 bg-grey-4 mb-1 gap-2', error && 'border border-error' )} + {...setTestID('second1')} > {wordsIndices.map((wordIndex, inputIndex) => ( ( wordIndex={wordIndex} active={activeInputIndex === inputIndex} value={value[inputIndex]?.word ?? ''} + testID={'word input hz'} /> ))}
diff --git a/src/app/templates/ManualBackupModal/verify-seed-phrase-input/word-input.tsx b/src/app/templates/ManualBackupModal/verify-seed-phrase-input/word-input.tsx index 0f7d9ffe2f..02f0596b66 100644 --- a/src/app/templates/ManualBackupModal/verify-seed-phrase-input/word-input.tsx +++ b/src/app/templates/ManualBackupModal/verify-seed-phrase-input/word-input.tsx @@ -4,19 +4,27 @@ import clsx from 'clsx'; import { FormField } from 'app/atoms'; -interface WordInputProps { +import { setTestID, TestIDProps } from '../../../../lib/analytics'; +import { ManualBackupModalSelectors } from '../selectors'; + +interface WordInputProps extends TestIDProps { wordIndex: number; active: boolean; value?: string; } -export const WordInput = memo(({ wordIndex, active, value }) => ( +export const WordInput = memo(({ wordIndex, active, value, testID }) => ( {wordIndex + 1}.} + extraLeftInner={ + + {wordIndex + 1}. + + } value={value} readOnly + testID={testID || ''} /> )); diff --git a/src/app/templates/ManualBackupModal/verify-seed-phrase-input/words-box-item.tsx b/src/app/templates/ManualBackupModal/verify-seed-phrase-input/words-box-item.tsx index ff0d368024..fe65b886a7 100644 --- a/src/app/templates/ManualBackupModal/verify-seed-phrase-input/words-box-item.tsx +++ b/src/app/templates/ManualBackupModal/verify-seed-phrase-input/words-box-item.tsx @@ -2,18 +2,20 @@ import React, { memo, useCallback } from 'react'; import { StyledButton } from 'app/atoms/StyledButton'; +import { TestIDProps } from '../../../../lib/analytics'; + export interface WordsBoxItemData { index: number; word: string; } -interface WordsBoxItemProps { +interface WordsBoxItemProps extends TestIDProps { data: WordsBoxItemData; selected: boolean; onSelect: (data: WordsBoxItemData) => void; } -export const WordsBoxItem = memo(({ data, selected, onSelect }) => { +export const WordsBoxItem = memo(({ data, selected, onSelect, testID }) => { const handleClick = useCallback(() => onSelect(data), [data, onSelect]); return ( @@ -23,6 +25,7 @@ export const WordsBoxItem = memo(({ data, selected, onSelect disabled={selected} size="M" onClick={handleClick} + testID={testID || ''} > {data.word} From 210752fe3a80996408f97105113b285c9d440221 Mon Sep 17 00:00:00 2001 From: Vlad Novak Date: Wed, 21 Aug 2024 11:59:03 +0300 Subject: [PATCH 2/5] TW-1525 first stage --- e2e/src/page-objects/index.ts | 6 +++- .../import-account-mnemonic-tab.page.ts | 28 +++++++++++++++++++ .../import-account-private-key-tab.page.ts | 14 ++++++++++ .../import-account-tab-switcher.page.ts | 23 +++++++++++++++ .../import-account-watch-only-tab.page.ts | 14 ++++++++++ .../pages/lists/add-new-wallet-list.page.ts | 18 ++++++++++++ .../pages/modal/accounts-modal.page.ts | 18 ++++++++++++ e2e/src/tests/import-wallet-2.test.ts | 0 e2e/src/tests/import-wallet-internal.test.ts | 17 +++++++++++ e2e/src/utils/search.utils.ts | 6 ++++ e2e/src/utils/shared.utils.ts | 17 +++++++++++ src/app/atoms/PageModal/index.tsx | 1 - src/app/atoms/PageModal/scroll-view.tsx | 16 +++++------ src/app/templates/AppHeader/AccountsModal.tsx | 1 + 14 files changed, 169 insertions(+), 10 deletions(-) create mode 100644 e2e/src/page-objects/pages/import-account-tabs/import-account-mnemonic-tab.page.ts create mode 100644 e2e/src/page-objects/pages/import-account-tabs/import-account-private-key-tab.page.ts create mode 100644 e2e/src/page-objects/pages/import-account-tabs/import-account-tab-switcher.page.ts create mode 100644 e2e/src/page-objects/pages/import-account-tabs/import-account-watch-only-tab.page.ts create mode 100644 e2e/src/page-objects/pages/lists/add-new-wallet-list.page.ts create mode 100644 e2e/src/page-objects/pages/modal/accounts-modal.page.ts delete mode 100644 e2e/src/tests/import-wallet-2.test.ts create mode 100644 e2e/src/tests/import-wallet-internal.test.ts diff --git a/e2e/src/page-objects/index.ts b/e2e/src/page-objects/index.ts index 874df24101..ddd64c44a1 100644 --- a/e2e/src/page-objects/index.ts +++ b/e2e/src/page-objects/index.ts @@ -15,6 +15,8 @@ import { DelegateFormPage } from './pages/delegate-form.page'; import { DelegateTab } from './pages/delegate-tab.page'; import { ImportExistingWalletPage } from './pages/importing-existing-wallet.page'; import { InternalConfirmationPage } from './pages/internal-confirmation.page'; +import { AddNewWalletListPage } from './pages/lists/add-new-wallet-list.page'; +import { AccountsModalPage } from './pages/modal/accounts-modal.page'; import { ManualBackupModalPage } from './pages/modal/manual-backup-modal.page'; import { NewsletterModalPage } from './pages/modal/newsletter-modal.page'; import { OnRumModalPage } from './pages/modal/on-rum-modal.page'; @@ -50,5 +52,7 @@ export const Pages = { GeneralSettings: new GeneralSettingsPage(), ManualBackupModal: new ManualBackupModalPage(), BackupOptionsModal: new BackupOptionsModalPage(), - Home: new HomePage() + Home: new HomePage(), + AccountsModal: new AccountsModalPage(), + AddNewWalletList: new AddNewWalletListPage() }; diff --git a/e2e/src/page-objects/pages/import-account-tabs/import-account-mnemonic-tab.page.ts b/e2e/src/page-objects/pages/import-account-tabs/import-account-mnemonic-tab.page.ts new file mode 100644 index 0000000000..08e2672206 --- /dev/null +++ b/e2e/src/page-objects/pages/import-account-tabs/import-account-mnemonic-tab.page.ts @@ -0,0 +1,28 @@ +import { ImportAccountSelectors } from 'src/app/pages/ImportAccount/selectors'; + +import { Page } from '../../../classes/page.class'; +import { createPageElement, findElements } from '../../../utils/search.utils'; + +export class ImportAccountMnemonicTab extends Page { + mnemonicWordInput = createPageElement(ImportAccountSelectors.mnemonicWordInput); + mnemonicPasswordField = createPageElement(ImportAccountSelectors.mnemonicPasswordInput); + mnemonicImportButton = createPageElement(ImportAccountSelectors.mnemonicImportButton); + + async isVisible() { + await this.mnemonicWordInput.waitForDisplayed(); + await this.mnemonicPasswordField.waitForDisplayed(); + await this.mnemonicImportButton.waitForDisplayed(); + } + + async enterSeedPhrase(seedPhrase: string) { + const wordsArray = seedPhrase.split(' '); + const wordsInputs = await findElements(ImportAccountSelectors.mnemonicWordInput); + + for (let i = 0; i < wordsArray.length; i++) { + const word = wordsArray[i]; + const input = wordsInputs[i]; + + await input.fill(word); + } + } +} diff --git a/e2e/src/page-objects/pages/import-account-tabs/import-account-private-key-tab.page.ts b/e2e/src/page-objects/pages/import-account-tabs/import-account-private-key-tab.page.ts new file mode 100644 index 0000000000..a284f05bf1 --- /dev/null +++ b/e2e/src/page-objects/pages/import-account-tabs/import-account-private-key-tab.page.ts @@ -0,0 +1,14 @@ +import { ImportAccountSelectors } from 'src/app/pages/ImportAccount/selectors'; + +import { Page } from 'e2e/src/classes/page.class'; +import { createPageElement } from 'e2e/src/utils/search.utils'; + +export class ImportAccountPrivateKeyTab extends Page { + privateKeyInput = createPageElement(ImportAccountSelectors.privateKeyInput); + privateKeyImportButton = createPageElement(ImportAccountSelectors.privateKeyImportButton); + + async isVisible() { + await this.privateKeyInput.waitForDisplayed(); + await this.privateKeyImportButton.waitForDisplayed(); + } +} diff --git a/e2e/src/page-objects/pages/import-account-tabs/import-account-tab-switcher.page.ts b/e2e/src/page-objects/pages/import-account-tabs/import-account-tab-switcher.page.ts new file mode 100644 index 0000000000..1e8e9a4b21 --- /dev/null +++ b/e2e/src/page-objects/pages/import-account-tabs/import-account-tab-switcher.page.ts @@ -0,0 +1,23 @@ +import { ImportAccountSelectors } from 'src/app/pages/ImportAccount/selectors'; + +import { Page } from '../../../classes/page.class'; +import { createPageElement, findElements, getElementText } from '../../../utils/search.utils'; + +export class ImportAccountTab extends Page { + tabSwitcher = createPageElement(ImportAccountSelectors.tabSwitcher); + + async isVisible() { + await this.tabSwitcher.waitForDisplayed(); + } + async selectTab(tabName: string) { + const tabElements = await findElements(ImportAccountSelectors.tabSwitcher); + + for (const tabElement of tabElements) { + const getTabValue = await getElementText(tabElement); + + if (getTabValue === tabName) { + await tabElement.click(); + } + } + } +} diff --git a/e2e/src/page-objects/pages/import-account-tabs/import-account-watch-only-tab.page.ts b/e2e/src/page-objects/pages/import-account-tabs/import-account-watch-only-tab.page.ts new file mode 100644 index 0000000000..743ae65e62 --- /dev/null +++ b/e2e/src/page-objects/pages/import-account-tabs/import-account-watch-only-tab.page.ts @@ -0,0 +1,14 @@ +import { ImportAccountSelectors } from 'src/app/pages/ImportAccount/selectors'; + +import { Page } from 'e2e/src/classes/page.class'; +import { createPageElement } from 'e2e/src/utils/search.utils'; + +export class ImportAccountWatchOnlyTab extends Page { + watchOnlyInput = createPageElement(ImportAccountSelectors.watchOnlyInput); + watchOnlyImportButton = createPageElement(ImportAccountSelectors.watchOnlyImportButton); + + async isVisible() { + await this.watchOnlyInput.waitForDisplayed(); + await this.watchOnlyImportButton.waitForDisplayed(); + } +} diff --git a/e2e/src/page-objects/pages/lists/add-new-wallet-list.page.ts b/e2e/src/page-objects/pages/lists/add-new-wallet-list.page.ts new file mode 100644 index 0000000000..85a05607f6 --- /dev/null +++ b/e2e/src/page-objects/pages/lists/add-new-wallet-list.page.ts @@ -0,0 +1,18 @@ +import { NewWalletActionsPopperSelectors } from 'src/app/templates/NewWalletActionsPopper/selectors'; + +import { Page } from '../../../classes/page.class'; +import { createPageElement } from '../../../utils/search.utils'; + +export class AddNewWalletListPage extends Page { + createWallet = createPageElement(NewWalletActionsPopperSelectors.createWallet); + importWallet = createPageElement(NewWalletActionsPopperSelectors.importWallet); + ledgerConnect = createPageElement(NewWalletActionsPopperSelectors.ledgerConnect); + watchOnlyAccount = createPageElement(NewWalletActionsPopperSelectors.watchOnlyAccount); + + async isVisible() { + await this.createWallet.waitForDisplayed(); + await this.importWallet.waitForDisplayed(); + await this.ledgerConnect.waitForDisplayed(); + await this.watchOnlyAccount.waitForDisplayed(); + } +} diff --git a/e2e/src/page-objects/pages/modal/accounts-modal.page.ts b/e2e/src/page-objects/pages/modal/accounts-modal.page.ts new file mode 100644 index 0000000000..88329cf901 --- /dev/null +++ b/e2e/src/page-objects/pages/modal/accounts-modal.page.ts @@ -0,0 +1,18 @@ +import { AccountsModalSelectors } from 'src/app/templates/AppHeader/selectors'; + +import { Page } from '../../../classes/page.class'; +import { createPageElement } from '../../../utils/search.utils'; + +export class AccountsModalPage extends Page { + searchField = createPageElement(AccountsModalSelectors.searchField); + accountsManagementButton = createPageElement(AccountsModalSelectors.accountsManagementButton); + newWalletActionsButton = createPageElement(AccountsModalSelectors.newWalletActionsButton); + cancelButton = createPageElement(AccountsModalSelectors.cancelButton); + + async isVisible() { + await this.searchField.waitForDisplayed(); + await this.accountsManagementButton.waitForDisplayed(); + await this.newWalletActionsButton.waitForDisplayed(); + await this.cancelButton.waitForDisplayed(); + } +} diff --git a/e2e/src/tests/import-wallet-2.test.ts b/e2e/src/tests/import-wallet-2.test.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/e2e/src/tests/import-wallet-internal.test.ts b/e2e/src/tests/import-wallet-internal.test.ts new file mode 100644 index 0000000000..e18ff91426 --- /dev/null +++ b/e2e/src/tests/import-wallet-internal.test.ts @@ -0,0 +1,17 @@ +import { test } from '../fixtures/extension'; +import { describeScenario } from '../fixtures/hooks'; +import { Pages } from '../page-objects'; +import { envVars } from '../utils/env.utils'; +import { importWalletPrecondition } from '../utils/shared.utils'; + +describeScenario('Import Wallet Internal @internal', () => { + test('Import Wallet Internal: positive scenario', async () => { + await importWalletPrecondition(); + + await Pages.Home.accountIcon.click(); + await Pages.AccountsModal.isVisible(); + await Pages.AccountsModal.newWalletActionsButton.click(); + await Pages.AddNewWalletList.isVisible(); + await Pages.AddNewWalletList.importWallet.click(); + }); +}); diff --git a/e2e/src/utils/search.utils.ts b/e2e/src/utils/search.utils.ts index 4da4da107e..a0ab15df10 100644 --- a/e2e/src/utils/search.utils.ts +++ b/e2e/src/utils/search.utils.ts @@ -89,3 +89,9 @@ export class PageElement { return await element.innerText({ timeout }); } } + +export const getElementText = async (selector: string) => { + const element = await findElement(selector); + + return await element.textContent(); +}; diff --git a/e2e/src/utils/shared.utils.ts b/e2e/src/utils/shared.utils.ts index e8ff30dc96..6c774b3359 100644 --- a/e2e/src/utils/shared.utils.ts +++ b/e2e/src/utils/shared.utils.ts @@ -1,4 +1,7 @@ import { CustomBrowserContext } from '../classes/browser-context.class'; +import { Pages } from '../page-objects'; + +import { envVars } from './env.utils'; export const switchToPage = async (pageUrl: string) => { const pages = CustomBrowserContext.browser.pages(); @@ -11,3 +14,17 @@ export const switchToPage = async (pageUrl: string) => { } } }; + +export const importWalletPrecondition = async () => { + await Pages.Welcome.importExistingWalletButton.waitForDisplayed(); + await Pages.Welcome.importExistingWalletButton.click(); + await Pages.ImportExistingWallet.enterSeedPhrase(envVars.DEFAULT_HD_ACCOUNT_SEED_PHRASE); + await Pages.ImportExistingWallet.nextButton.click(); + + await Pages.SetWallet.passwordField.fill(envVars.DEFAULT_PASSWORD); + await Pages.SetWallet.repeatPasswordField.fill(envVars.DEFAULT_PASSWORD); + await Pages.SetWallet.acceptTerms.click(); + await Pages.SetWallet.importButton.click(); + + await Pages.NewsletterModal.closeButton.click(); +}; diff --git a/src/app/atoms/PageModal/index.tsx b/src/app/atoms/PageModal/index.tsx index 1d16e5e35c..5d97116b4e 100644 --- a/src/app/atoms/PageModal/index.tsx +++ b/src/app/atoms/PageModal/index.tsx @@ -10,7 +10,6 @@ import { ReactComponent as ExIcon } from 'app/icons/base/x.svg'; import { LAYOUT_CONTAINER_CLASSNAME } from 'app/layouts/containers'; import { TestIDProps } from 'lib/analytics'; -import { TestIDProps } from '../../../lib/analytics'; import { IconBase } from '../IconBase'; import ModStyles from './styles.module.css'; diff --git a/src/app/atoms/PageModal/scroll-view.tsx b/src/app/atoms/PageModal/scroll-view.tsx index c7f39ab77e..e9b66ea29f 100644 --- a/src/app/atoms/PageModal/scroll-view.tsx +++ b/src/app/atoms/PageModal/scroll-view.tsx @@ -14,14 +14,14 @@ interface ScrollViewProps extends HTMLAttributes, TestIDProps { export const ScrollView = memo( ({ - className, - onBottomEdgeVisibilityChange, - bottomEdgeThreshold, - onTopEdgeVisibilityChange, - topEdgeThreshold, - testID, - ...restProps - }) => { + className, + onBottomEdgeVisibilityChange, + bottomEdgeThreshold, + onTopEdgeVisibilityChange, + topEdgeThreshold, + testID, + ...restProps + }) => { const rootRef = useRef(null); useScrollEdgesVisibility( diff --git a/src/app/templates/AppHeader/AccountsModal.tsx b/src/app/templates/AppHeader/AccountsModal.tsx index 93ac4a79b2..fef7f3c47d 100644 --- a/src/app/templates/AppHeader/AccountsModal.tsx +++ b/src/app/templates/AppHeader/AccountsModal.tsx @@ -25,6 +25,7 @@ import { navigate } from 'lib/woozie'; import { searchAndFilterAccounts, useAccountsGroups, useCurrentAccountId, useVisibleAccounts } from 'temple/front'; import { useSetAccountId } from 'temple/front/ready'; +import { setTestID } from '../../../lib/analytics'; import { CreateHDWalletModal } from '../CreateHDWalletModal'; import { AccountsModalSelectors } from './selectors'; From 82e3c0b4c4224bdd4992ebafd83a8bf0c95d7f53 Mon Sep 17 00:00:00 2001 From: Vlad Novak Date: Tue, 27 Aug 2024 11:24:08 +0300 Subject: [PATCH 3/5] TW-1525 second stage --- e2e/src/page-objects/index.ts | 4 ++- ...mport-account-wallet-from-seed-tab.page.ts | 26 +++++++++++++++++++ e2e/src/tests/import-wallet-internal.test.ts | 4 +++ src/app/pages/ImportAccount/selectors.ts | 5 +++- .../wallet-from-mnemonic-form.tsx | 3 +++ 5 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 e2e/src/page-objects/pages/import-account-tabs/import-account-wallet-from-seed-tab.page.ts diff --git a/e2e/src/page-objects/index.ts b/e2e/src/page-objects/index.ts index ddd64c44a1..3eaa2d8f45 100644 --- a/e2e/src/page-objects/index.ts +++ b/e2e/src/page-objects/index.ts @@ -13,6 +13,7 @@ import { SwapPage } from '../page-objects/pages/swap.page'; import { OperationStatusAlert } from './pages/alerts/operation-status.alert'; import { DelegateFormPage } from './pages/delegate-form.page'; import { DelegateTab } from './pages/delegate-tab.page'; +import { ImportAccountMnemonicTab } from './pages/import-account-tabs/import-account-wallet-from-seed-tab.page'; import { ImportExistingWalletPage } from './pages/importing-existing-wallet.page'; import { InternalConfirmationPage } from './pages/internal-confirmation.page'; import { AddNewWalletListPage } from './pages/lists/add-new-wallet-list.page'; @@ -54,5 +55,6 @@ export const Pages = { BackupOptionsModal: new BackupOptionsModalPage(), Home: new HomePage(), AccountsModal: new AccountsModalPage(), - AddNewWalletList: new AddNewWalletListPage() + AddNewWalletList: new AddNewWalletListPage(), + ImportAccountMnemonicTab: new ImportAccountMnemonicTab() }; diff --git a/e2e/src/page-objects/pages/import-account-tabs/import-account-wallet-from-seed-tab.page.ts b/e2e/src/page-objects/pages/import-account-tabs/import-account-wallet-from-seed-tab.page.ts new file mode 100644 index 0000000000..eef28a3bd2 --- /dev/null +++ b/e2e/src/page-objects/pages/import-account-tabs/import-account-wallet-from-seed-tab.page.ts @@ -0,0 +1,26 @@ +import { ImportAccountSelectors } from 'src/app/pages/ImportAccount/selectors'; + +import { Page } from '../../../classes/page.class'; +import { createPageElement, findElements } from '../../../utils/search.utils'; + +export class ImportAccountMnemonicTab extends Page { + walletFromMnemonicWordInput = createPageElement(ImportAccountSelectors.walletFromMnemonicWordInput); + walletFromMnemonicImportButton = createPageElement(ImportAccountSelectors.walletFromMnemonicImportButton); + + async isVisible() { + await this.walletFromMnemonicWordInput.waitForDisplayed(); + await this.walletFromMnemonicImportButton.waitForDisplayed(); + } + + async enterSeedPhrase(seedPhrase: string) { + const wordsArray = seedPhrase.split(' '); + const wordsInputs = await findElements(ImportAccountSelectors.walletFromMnemonicWordInput); + + for (let i = 0; i < wordsArray.length; i++) { + const word = wordsArray[i]; + const input = wordsInputs[i]; + + await input.fill(word); + } + } +} diff --git a/e2e/src/tests/import-wallet-internal.test.ts b/e2e/src/tests/import-wallet-internal.test.ts index e18ff91426..27530221d5 100644 --- a/e2e/src/tests/import-wallet-internal.test.ts +++ b/e2e/src/tests/import-wallet-internal.test.ts @@ -3,6 +3,7 @@ import { describeScenario } from '../fixtures/hooks'; import { Pages } from '../page-objects'; import { envVars } from '../utils/env.utils'; import { importWalletPrecondition } from '../utils/shared.utils'; +import { sleep } from '../utils/timing.utils'; describeScenario('Import Wallet Internal @internal', () => { test('Import Wallet Internal: positive scenario', async () => { @@ -13,5 +14,8 @@ describeScenario('Import Wallet Internal @internal', () => { await Pages.AccountsModal.newWalletActionsButton.click(); await Pages.AddNewWalletList.isVisible(); await Pages.AddNewWalletList.importWallet.click(); + await Pages.ImportAccountMnemonicTab.enterSeedPhrase(envVars.IMPORTED_HD_ACCOUNT_SEED_PHRASE); + await Pages.ImportAccountMnemonicTab.walletFromMnemonicImportButton.click(); + await sleep(5000); }); }); diff --git a/src/app/pages/ImportAccount/selectors.ts b/src/app/pages/ImportAccount/selectors.ts index 1e30461186..b166584bb5 100644 --- a/src/app/pages/ImportAccount/selectors.ts +++ b/src/app/pages/ImportAccount/selectors.ts @@ -23,7 +23,10 @@ export enum ImportAccountSelectors { fundraiserImportButton = 'Import Account(Fundraiser)/Import Button', managedContractInput = 'Import Account(ManagedKT)/Managed Contract Input', - managedKTImportButton = 'Import Account(ManagedKT)/Import Account Button' + managedKTImportButton = 'Import Account(ManagedKT)/Import Account Button', + + walletFromMnemonicWordInput = 'Import Account(Mnemonic)/Wallet From Mnemonic Word Input', + walletFromMnemonicImportButton = 'Import Account(Mnemonic)/Wallet From Mnemonic Import Button' } export enum ImportAccountFormType { diff --git a/src/app/pages/ImportAccount/wallet-from-mnemonic-form.tsx b/src/app/pages/ImportAccount/wallet-from-mnemonic-form.tsx index 917cc08b3c..1e93de00c8 100644 --- a/src/app/pages/ImportAccount/wallet-from-mnemonic-form.tsx +++ b/src/app/pages/ImportAccount/wallet-from-mnemonic-form.tsx @@ -9,6 +9,7 @@ import { T, t } from 'lib/i18n'; import { useTempleClient } from 'lib/temple/front'; import { defaultNumberOfWords } from './constants'; +import { ImportAccountSelectors } from './selectors'; export const WalletFromMnemonicForm = memo(() => { const { createOrImportWallet } = useTempleClient(); @@ -70,6 +71,7 @@ export const WalletFromMnemonicForm = memo(() => { reset={reset} numberOfWords={numberOfWords} setNumberOfWords={setNumberOfWords} + testID={ImportAccountSelectors.walletFromMnemonicWordInput} /> From 7dd5131801d2d43bc1c4b0e82bc4bb059bd76472 Mon Sep 17 00:00:00 2001 From: Vlad Novak Date: Tue, 27 Aug 2024 18:07:17 +0300 Subject: [PATCH 4/5] fix linter + ts --- e2e/src/page-objects/index.ts | 6 +++++- .../import-account-private-key-tab.page.ts | 4 ++-- .../import-account-watch-only-tab.page.ts | 4 ++-- src/app/templates/AppHeader/AccountsModal.tsx | 1 - src/app/templates/ManualBackupModal/index.tsx | 1 - 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/e2e/src/page-objects/index.ts b/e2e/src/page-objects/index.ts index 3eaa2d8f45..dbbcb18cec 100644 --- a/e2e/src/page-objects/index.ts +++ b/e2e/src/page-objects/index.ts @@ -13,7 +13,9 @@ import { SwapPage } from '../page-objects/pages/swap.page'; import { OperationStatusAlert } from './pages/alerts/operation-status.alert'; import { DelegateFormPage } from './pages/delegate-form.page'; import { DelegateTab } from './pages/delegate-tab.page'; +import { ImportAccountPrivateKeyTab } from './pages/import-account-tabs/import-account-private-key-tab.page'; import { ImportAccountMnemonicTab } from './pages/import-account-tabs/import-account-wallet-from-seed-tab.page'; +import { ImportAccountWatchOnlyTab } from './pages/import-account-tabs/import-account-watch-only-tab.page'; import { ImportExistingWalletPage } from './pages/importing-existing-wallet.page'; import { InternalConfirmationPage } from './pages/internal-confirmation.page'; import { AddNewWalletListPage } from './pages/lists/add-new-wallet-list.page'; @@ -56,5 +58,7 @@ export const Pages = { Home: new HomePage(), AccountsModal: new AccountsModalPage(), AddNewWalletList: new AddNewWalletListPage(), - ImportAccountMnemonicTab: new ImportAccountMnemonicTab() + ImportAccountMnemonicTab: new ImportAccountMnemonicTab(), + ImportAccountPrivateKeyTab: new ImportAccountPrivateKeyTab(), + ImportAccountWatchOnlyTab: new ImportAccountWatchOnlyTab() }; diff --git a/e2e/src/page-objects/pages/import-account-tabs/import-account-private-key-tab.page.ts b/e2e/src/page-objects/pages/import-account-tabs/import-account-private-key-tab.page.ts index a284f05bf1..2c686d6107 100644 --- a/e2e/src/page-objects/pages/import-account-tabs/import-account-private-key-tab.page.ts +++ b/e2e/src/page-objects/pages/import-account-tabs/import-account-private-key-tab.page.ts @@ -1,7 +1,7 @@ import { ImportAccountSelectors } from 'src/app/pages/ImportAccount/selectors'; -import { Page } from 'e2e/src/classes/page.class'; -import { createPageElement } from 'e2e/src/utils/search.utils'; +import { Page } from '../../../classes/page.class'; +import { createPageElement } from '../../../utils/search.utils'; export class ImportAccountPrivateKeyTab extends Page { privateKeyInput = createPageElement(ImportAccountSelectors.privateKeyInput); diff --git a/e2e/src/page-objects/pages/import-account-tabs/import-account-watch-only-tab.page.ts b/e2e/src/page-objects/pages/import-account-tabs/import-account-watch-only-tab.page.ts index 743ae65e62..51b6e83d93 100644 --- a/e2e/src/page-objects/pages/import-account-tabs/import-account-watch-only-tab.page.ts +++ b/e2e/src/page-objects/pages/import-account-tabs/import-account-watch-only-tab.page.ts @@ -1,7 +1,7 @@ import { ImportAccountSelectors } from 'src/app/pages/ImportAccount/selectors'; -import { Page } from 'e2e/src/classes/page.class'; -import { createPageElement } from 'e2e/src/utils/search.utils'; +import { Page } from '../../../classes/page.class'; +import { createPageElement } from '../../../utils/search.utils'; export class ImportAccountWatchOnlyTab extends Page { watchOnlyInput = createPageElement(ImportAccountSelectors.watchOnlyInput); diff --git a/src/app/templates/AppHeader/AccountsModal.tsx b/src/app/templates/AppHeader/AccountsModal.tsx index fef7f3c47d..93ac4a79b2 100644 --- a/src/app/templates/AppHeader/AccountsModal.tsx +++ b/src/app/templates/AppHeader/AccountsModal.tsx @@ -25,7 +25,6 @@ import { navigate } from 'lib/woozie'; import { searchAndFilterAccounts, useAccountsGroups, useCurrentAccountId, useVisibleAccounts } from 'temple/front'; import { useSetAccountId } from 'temple/front/ready'; -import { setTestID } from '../../../lib/analytics'; import { CreateHDWalletModal } from '../CreateHDWalletModal'; import { AccountsModalSelectors } from './selectors'; diff --git a/src/app/templates/ManualBackupModal/index.tsx b/src/app/templates/ManualBackupModal/index.tsx index e27ab84624..b44674fbca 100644 --- a/src/app/templates/ManualBackupModal/index.tsx +++ b/src/app/templates/ManualBackupModal/index.tsx @@ -36,7 +36,6 @@ export const ManualBackupModal = memo(({ mnemonic, onSuc isNewMnemonic={isNewMnemonic} onCancel={onCancel} onConfirm={goToVerifySeedPhrase} - testID={'vlad'} /> )} From 07c76cd2dedfcfde275c06821d304e96fc146a5e Mon Sep 17 00:00:00 2001 From: Vlad Novak Date: Tue, 27 Aug 2024 18:19:25 +0300 Subject: [PATCH 5/5] fix linter + ts --- .../import-account-tabs/import-account-tab-switcher.page.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e/src/page-objects/pages/import-account-tabs/import-account-tab-switcher.page.ts b/e2e/src/page-objects/pages/import-account-tabs/import-account-tab-switcher.page.ts index 1e8e9a4b21..fb99234845 100644 --- a/e2e/src/page-objects/pages/import-account-tabs/import-account-tab-switcher.page.ts +++ b/e2e/src/page-objects/pages/import-account-tabs/import-account-tab-switcher.page.ts @@ -1,3 +1,4 @@ +import { Locator } from '@playwright/test'; import { ImportAccountSelectors } from 'src/app/pages/ImportAccount/selectors'; import { Page } from '../../../classes/page.class'; @@ -13,7 +14,7 @@ export class ImportAccountTab extends Page { const tabElements = await findElements(ImportAccountSelectors.tabSwitcher); for (const tabElement of tabElements) { - const getTabValue = await getElementText(tabElement); + const getTabValue = await tabElement.textContent(); if (getTabValue === tabName) { await tabElement.click();