From 2e227520405d3716dba9ced0e59fe32472293367 Mon Sep 17 00:00:00 2001 From: Mat <63294765+matstyler@users.noreply.github.com> Date: Sat, 27 Jul 2024 21:46:43 +0200 Subject: [PATCH] :sparkles: feat: Cypress: `switchNetwork` and `switchAccount` functions (#1185) * feat: MetaMask setup in Cypress part 1 * feat: wallet setup is working as expected * fix: gitignore cleanup * fix: clean imports * fix: export from metamask package * fix: dependencies issues * fix: cleanup * fix: test scripts * fix: format * fix: renamed configureBeforeSynpress.ts to configureSynpress.ts * fix: improve metamask/cypress stability * fix: format * fix: cleanup * feat: Implemented getPlaywrightMetamask and addNewAccount * fix: cleanup * feat: Implemented switchNetwork and switchAccount for Cypress * feat: Added renameAccount for Cypress (#1187) --- .../metamask/src/cypress/configureSynpress.ts | 66 +++++++++++++++++-- wallets/metamask/src/cypress/constans.ts | 1 + .../src/cypress/support/synpressCommands.ts | 28 ++++++-- wallets/metamask/src/playwright/MetaMask.ts | 5 +- .../pages/HomePage/actions/renameAccount.ts | 21 +++++- .../src/playwright/pages/HomePage/page.ts | 4 +- .../metamask/test/cypress/renameAccount.cy.ts | 15 +++++ .../metamask/test/cypress/switchAccount.cy.ts | 13 ++++ .../metamask/test/cypress/switchNetwork.cy.ts | 21 ++++++ .../test/playwright/e2e/renameAccount.spec.ts | 2 +- 10 files changed, 161 insertions(+), 15 deletions(-) create mode 100644 wallets/metamask/src/cypress/constans.ts create mode 100644 wallets/metamask/test/cypress/renameAccount.cy.ts create mode 100644 wallets/metamask/test/cypress/switchAccount.cy.ts create mode 100644 wallets/metamask/test/cypress/switchNetwork.cy.ts diff --git a/wallets/metamask/src/cypress/configureSynpress.ts b/wallets/metamask/src/cypress/configureSynpress.ts index 59489a52d..d90b036b9 100644 --- a/wallets/metamask/src/cypress/configureSynpress.ts +++ b/wallets/metamask/src/cypress/configureSynpress.ts @@ -1,6 +1,7 @@ import type { BrowserContext, Page } from '@playwright/test' import { expect } from '@playwright/test' import { ensureRdpPort } from '@synthetixio/synpress-core' +import Selectors from '../selectors/pages/HomePage' import getPlaywrightMetamask from './getPlaywrightMetamask' import importMetaMaskWallet from './support/importMetaMaskWallet' import { initMetaMask } from './support/initMetaMask' @@ -61,11 +62,23 @@ export default function configureSynpress(on: Cypress.PluginEvents, config: Cypr on('task', { // Synpress API - async connectToDapp() { + async getAccount() { + const metamask = getPlaywrightMetamask(context, metamaskExtensionPage, metamaskExtensionId) + + return await metamaskExtensionPage.locator(metamask.homePage.selectors.accountMenu.accountButton).innerText() + }, + + async getNetwork() { + const metamask = getPlaywrightMetamask(context, metamaskExtensionPage, metamaskExtensionId) + + return await metamaskExtensionPage.locator(metamask.homePage.selectors.currentNetwork).innerText() + }, + + async connectToDapp(accounts?: string[]) { const metamask = getPlaywrightMetamask(context, metamaskExtensionPage, metamaskExtensionId) return metamask - .connectToDapp() + .connectToDapp(accounts) .then(() => true) .catch(() => false) }, @@ -82,10 +95,55 @@ export default function configureSynpress(on: Cypress.PluginEvents, config: Cypr return true }, - async getAccount() { + async switchAccount(accountName: string) { const metamask = getPlaywrightMetamask(context, metamaskExtensionPage, metamaskExtensionId) - return await metamaskExtensionPage.locator(metamask.homePage.selectors.accountMenu.accountButton).innerText() + await metamask.switchAccount(accountName) + + await expect(metamaskExtensionPage.locator(metamask.homePage.selectors.accountMenu.accountButton)).toHaveText( + accountName + ) + + return true + }, + + async renameAccount({ + currentAccountName, + newAccountName + }: { + currentAccountName: string + newAccountName: string + }) { + const metamask = getPlaywrightMetamask(context, metamaskExtensionPage, metamaskExtensionId) + + await metamask.renameAccount(currentAccountName, newAccountName) + + await metamaskExtensionPage.locator(Selectors.threeDotsMenu.accountDetailsCloseButton).click() + + await expect(metamaskExtensionPage.locator(metamask.homePage.selectors.accountMenu.accountButton)).toHaveText( + newAccountName + ) + + return true + }, + + async switchNetwork({ + networkName, + isTestnet + }: { + networkName: string + isTestnet?: boolean + }) { + const metamask = getPlaywrightMetamask(context, metamaskExtensionPage, metamaskExtensionId) + + return await metamask + .switchNetwork(networkName, isTestnet) + .then(() => { + return true + }) + .catch(() => { + return false + }) } }) diff --git a/wallets/metamask/src/cypress/constans.ts b/wallets/metamask/src/cypress/constans.ts new file mode 100644 index 000000000..d94424e0b --- /dev/null +++ b/wallets/metamask/src/cypress/constans.ts @@ -0,0 +1 @@ +export const defaultAccount = 'Account 1' diff --git a/wallets/metamask/src/cypress/support/synpressCommands.ts b/wallets/metamask/src/cypress/support/synpressCommands.ts index 3fc930e2d..0c4154d3e 100644 --- a/wallets/metamask/src/cypress/support/synpressCommands.ts +++ b/wallets/metamask/src/cypress/support/synpressCommands.ts @@ -12,21 +12,41 @@ declare global { namespace Cypress { interface Chainable { - connectToDapp(): Chainable - addNewAccount(accountName: string): Chainable getAccount(): Chainable + getNetwork(): Chainable + + connectToDapp(accounts?: string[]): Chainable + + addNewAccount(accountName: string): Chainable + switchAccount(accountName: string): Chainable + renameAccount(currentAccountName: string, newAccountName: string): Chainable + + switchNetwork(networkName: string, isTestnet?: boolean): Chainable } } } export default function synpressCommands() { + Cypress.Commands.add('getAccount', () => { + return cy.task('getAccount') + }) + Cypress.Commands.add('getNetwork', () => { + return cy.task('getNetwork') + }) + Cypress.Commands.add('connectToDapp', () => { return cy.task('connectToDapp') }) Cypress.Commands.add('addNewAccount', (accountName: string) => { return cy.task('addNewAccount', accountName) }) - Cypress.Commands.add('getAccount', () => { - return cy.task('getAccount') + Cypress.Commands.add('switchAccount', (accountName: string) => { + return cy.task('switchAccount', accountName) + }) + Cypress.Commands.add('renameAccount', (currentAccountName: string, newAccountName: string) => { + return cy.task('renameAccount', { currentAccountName, newAccountName }) + }) + Cypress.Commands.add('switchNetwork', (networkName: string, isTestnet = false) => { + return cy.task('switchNetwork', { networkName, isTestnet }) }) } diff --git a/wallets/metamask/src/playwright/MetaMask.ts b/wallets/metamask/src/playwright/MetaMask.ts index 94a278741..784f2322b 100644 --- a/wallets/metamask/src/playwright/MetaMask.ts +++ b/wallets/metamask/src/playwright/MetaMask.ts @@ -81,10 +81,11 @@ export class MetaMask extends MetaMaskAbstract { /** * Renames the currently selected account. * + * @param currentAccountName - The current account name. * @param newAccountName - The new name for the account. */ - async renameAccount(newAccountName: string) { - await this.homePage.renameAccount(newAccountName) + async renameAccount(currentAccountName: string, newAccountName: string) { + await this.homePage.renameAccount(currentAccountName, newAccountName) } /** diff --git a/wallets/metamask/src/playwright/pages/HomePage/actions/renameAccount.ts b/wallets/metamask/src/playwright/pages/HomePage/actions/renameAccount.ts index 466f7ded6..36cd7d69c 100644 --- a/wallets/metamask/src/playwright/pages/HomePage/actions/renameAccount.ts +++ b/wallets/metamask/src/playwright/pages/HomePage/actions/renameAccount.ts @@ -1,9 +1,26 @@ import type { Page } from '@playwright/test' import Selectors from '../../../../selectors/pages/HomePage' +import { allTextContents } from '../../../utils/allTextContents' -export async function renameAccount(page: Page, newAccountName: string) { +export async function renameAccount(page: Page, currentAccountName: string, newAccountName: string) { await page.locator(Selectors.accountMenu.accountButton).click() - await page.locator(Selectors.accountMenu.renameAccountMenu.listItemButton).nth(0).click() + + const accountNamesLocators = await page.locator(Selectors.accountMenu.accountNames).all() + + const accountNames = await allTextContents(accountNamesLocators) + + const seekedAccountNames = accountNames.filter( + (name) => name.toLocaleLowerCase() === currentAccountName.toLocaleLowerCase() + ) + + if (seekedAccountNames.length === 0) { + throw new Error(`[SwitchAccount] Account with name ${currentAccountName} not found`) + } + + // biome-ignore lint/style/noNonNullAssertion: this non-null assertion is intentional + const accountIndex = accountNames.indexOf(seekedAccountNames[0]!) + + await page.locator(Selectors.accountMenu.renameAccountMenu.listItemButton).nth(accountIndex).click() await page.locator(Selectors.threeDotsMenu.accountDetailsButton).click() await page.locator(Selectors.accountMenu.renameAccountMenu.renameButton).click() await page.locator(Selectors.accountMenu.renameAccountMenu.renameInput).fill(newAccountName) diff --git a/wallets/metamask/src/playwright/pages/HomePage/page.ts b/wallets/metamask/src/playwright/pages/HomePage/page.ts index 156de5e85..15ea8477b 100644 --- a/wallets/metamask/src/playwright/pages/HomePage/page.ts +++ b/wallets/metamask/src/playwright/pages/HomePage/page.ts @@ -38,8 +38,8 @@ export class HomePage { await addNewAccount(this.page, accountName) } - async renameAccount(newAccountName: string) { - await renameAccount(this.page, newAccountName) + async renameAccount(currentAccountName: string, newAccountName: string) { + await renameAccount(this.page, currentAccountName, newAccountName) } async getAccountAddress() { diff --git a/wallets/metamask/test/cypress/renameAccount.cy.ts b/wallets/metamask/test/cypress/renameAccount.cy.ts new file mode 100644 index 000000000..34bff2e2e --- /dev/null +++ b/wallets/metamask/test/cypress/renameAccount.cy.ts @@ -0,0 +1,15 @@ +import { defaultAccount } from '../../src/cypress/constans' + +const newAccountName = 'New Test Account Name' + +it('should rename currently connected account with specified name', () => { + cy.addNewAccount(newAccountName).then(() => { + cy.renameAccount(newAccountName, 'Renaming test').then(() => { + cy.getAccount().should('eq', 'Renaming test') + }) + }) +}) + +after(() => { + cy.switchAccount(defaultAccount) +}) diff --git a/wallets/metamask/test/cypress/switchAccount.cy.ts b/wallets/metamask/test/cypress/switchAccount.cy.ts new file mode 100644 index 000000000..96578c244 --- /dev/null +++ b/wallets/metamask/test/cypress/switchAccount.cy.ts @@ -0,0 +1,13 @@ +import { defaultAccount } from '../../src/cypress/constans' + +it('should switch back to the `Account 1` account', () => { + const accountName = 'New Account to test switch' + + cy.addNewAccount(accountName).then(() => { + cy.getAccount().should('eq', accountName) + }) +}) + +after(() => { + cy.switchAccount(defaultAccount) +}) diff --git a/wallets/metamask/test/cypress/switchNetwork.cy.ts b/wallets/metamask/test/cypress/switchNetwork.cy.ts new file mode 100644 index 000000000..cd771ee5f --- /dev/null +++ b/wallets/metamask/test/cypress/switchNetwork.cy.ts @@ -0,0 +1,21 @@ +it('should switch network', () => { + cy.getNetwork().should('eq', 'Ethereum Mainnet') + + const targetNetwork = 'Linea Mainnet' + cy.switchNetwork(targetNetwork).then(() => { + cy.getNetwork().should('eq', targetNetwork) + }) +}) + +it('should switch network to the testnet', () => { + cy.getNetwork().should('eq', 'Ethereum Mainnet') + + const targetNetwork = 'Sepolia' + cy.switchNetwork(targetNetwork, true).then(() => { + cy.getNetwork().should('eq', targetNetwork) + }) +}) + +afterEach(() => { + cy.switchNetwork('Ethereum Mainnet') +}) diff --git a/wallets/metamask/test/playwright/e2e/renameAccount.spec.ts b/wallets/metamask/test/playwright/e2e/renameAccount.spec.ts index 34356b762..0e2c35f0f 100644 --- a/wallets/metamask/test/playwright/e2e/renameAccount.spec.ts +++ b/wallets/metamask/test/playwright/e2e/renameAccount.spec.ts @@ -11,7 +11,7 @@ test('should rename current account with specified name', async ({ context, meta const metamask = new MetaMask(context, metamaskPage, basicSetup.walletPassword) const accountName = 'Test Account' - await metamask.renameAccount(accountName) + await metamask.renameAccount('Account 1', accountName) await expect(metamaskPage.locator(metamask.homePage.selectors.accountMenu.accountButton)).toHaveText(accountName) })