From b8e992d1c959d0a3e943933841d2bb3ebf398c4f Mon Sep 17 00:00:00 2001 From: matstyler Date: Tue, 17 Sep 2024 19:15:47 +0200 Subject: [PATCH 1/2] feat: import wallets using Cypress --- wallets/metamask/cypress-no-wallet.config.ts | 16 ++++++++++ wallets/metamask/package.json | 1 + wallets/metamask/src/cypress/MetaMask.ts | 31 ++++++++++++++++--- .../metamask/src/cypress/configureSynpress.ts | 20 +++++++++--- .../cypress/support/importMetaMaskWallet.ts | 4 +-- .../src/cypress/support/synpressCommands.ts | 25 ++++++++++++--- .../test/cypress/importWallet.cy.no-wallet.ts | 10 ++++++ .../cypress/importWalletFromPrivateKey.cy.ts | 7 +++++ 8 files changed, 100 insertions(+), 14 deletions(-) create mode 100644 wallets/metamask/cypress-no-wallet.config.ts create mode 100644 wallets/metamask/test/cypress/importWallet.cy.no-wallet.ts create mode 100644 wallets/metamask/test/cypress/importWalletFromPrivateKey.cy.ts diff --git a/wallets/metamask/cypress-no-wallet.config.ts b/wallets/metamask/cypress-no-wallet.config.ts new file mode 100644 index 000000000..bc2c214e7 --- /dev/null +++ b/wallets/metamask/cypress-no-wallet.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from 'cypress' +import configureSynpress from './src/cypress/configureSynpress' + +export default defineConfig({ + userAgent: 'synpress', + chromeWebSecurity: true, + e2e: { + baseUrl: 'http://localhost:9999', + specPattern: 'test/cypress/**/importWallet.cy.no-wallet.{js,jsx,ts,tsx}', + supportFile: 'src/cypress/support/e2e.{js,jsx,ts,tsx}', + testIsolation: false, + async setupNodeEvents(on, config) { + return configureSynpress(on, config, false) + } + } +}) diff --git a/wallets/metamask/package.json b/wallets/metamask/package.json index 51f8db104..749c0874a 100644 --- a/wallets/metamask/package.json +++ b/wallets/metamask/package.json @@ -30,6 +30,7 @@ "test": "vitest run", "test:coverage": "vitest run --coverage", "test:cypress:headful": "cypress run --browser chrome --headed", + "test:cypress:headful:no-wallet": "cypress run --browser chrome --headed --config-file ./cypress-no-wallet.config.ts", "test:playwright:headful": "playwright test", "test:playwright:headless": "HEADLESS=true playwright test", "test:playwright:headless:ui": "HEADLESS=true playwright test --ui", diff --git a/wallets/metamask/src/cypress/MetaMask.ts b/wallets/metamask/src/cypress/MetaMask.ts index 16cded469..e11dfc377 100644 --- a/wallets/metamask/src/cypress/MetaMask.ts +++ b/wallets/metamask/src/cypress/MetaMask.ts @@ -37,10 +37,21 @@ export default class MetaMask { } async connectToDapp(accounts?: string[]) { - return this.metamaskPlaywright - .connectToDapp(accounts) - .then(() => true) - .catch(() => false) + await this.metamaskPlaywright.connectToDapp(accounts) + + return true + } + + async importWallet(seedPhrase: string) { + await this.metamaskPlaywright.importWallet(seedPhrase) + + return true + } + + async importWalletFromPrivateKey(privateKey: string) { + await this.metamaskPlaywright.importWalletFromPrivateKey(privateKey) + + return true } async addNewAccount(accountName: string) { @@ -316,4 +327,16 @@ export default class MetaMask { return false }) } + + async goBackToHomePage() { + await this.metamaskPlaywright.openSettings() + + await expect(this.metamaskExtensionPage.locator(HomePageSelectors.copyAccountAddressButton)).not.toBeVisible() + + await this.metamaskPlaywright.goBackToHomePage() + + await expect(this.metamaskExtensionPage.locator(HomePageSelectors.copyAccountAddressButton)).toBeVisible() + + return true + } } diff --git a/wallets/metamask/src/cypress/configureSynpress.ts b/wallets/metamask/src/cypress/configureSynpress.ts index 464190cf6..51cd93db3 100644 --- a/wallets/metamask/src/cypress/configureSynpress.ts +++ b/wallets/metamask/src/cypress/configureSynpress.ts @@ -19,7 +19,11 @@ let metamaskExtensionPage: Page // TODO: Implement if needed to change the focus between pages // let cypressPage: Page -export default function configureSynpress(on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) { +export default function configureSynpress( + on: Cypress.PluginEvents, + config: Cypress.PluginConfigOptions, + importDefaultWallet = true +) { const browsers = config.browsers.filter((b) => b.name === 'chrome') if (browsers.length === 0) { throw new Error('No Chrome browser found in the configuration') @@ -47,7 +51,7 @@ export default function configureSynpress(on: Cypress.PluginEvents, config: Cypr metamaskExtensionId: _metamaskExtensionId, extensionPage: _extensionPage, cypressPage: _cypressPage - } = await importMetaMaskWallet(rdpPort) + } = await importMetaMaskWallet(rdpPort, importDefaultWallet) if (_extensionPage && _metamaskExtensionId) { context = _context metamaskExtensionId = _metamaskExtensionId @@ -63,8 +67,12 @@ export default function configureSynpress(on: Cypress.PluginEvents, config: Cypr // Synpress API on('task', { - // Account + // Wallet connectToDapp: () => metamask?.connectToDapp(), + importWallet: (seedPhrase: string) => metamask?.importWallet(seedPhrase), + importWalletFromPrivateKey: (privateKey: string) => metamask?.importWalletFromPrivateKey(privateKey), + + // Account getAccount: () => metamask?.getAccount(), getAccountAddress: () => metamask?.getAccountAddress(), addNewAccount: (accountName: string) => metamask?.addNewAccount(accountName), @@ -120,7 +128,11 @@ export default function configureSynpress(on: Cypress.PluginEvents, config: Cypr rejectTransaction: () => metamask?.rejectTransaction(), confirmTransactionAndWaitForMining: () => metamask?.confirmTransactionAndWaitForMining(), openTransactionDetails: (txIndex: number) => metamask?.openTransactionDetails(txIndex), - closeTransactionDetails: () => metamask?.closeTransactionDetails() + closeTransactionDetails: () => metamask?.closeTransactionDetails(), + + // Others + + goBackToHomePage: () => metamask?.goBackToHomePage() }) return { diff --git a/wallets/metamask/src/cypress/support/importMetaMaskWallet.ts b/wallets/metamask/src/cypress/support/importMetaMaskWallet.ts index b69ab35d3..b4b82e1a1 100644 --- a/wallets/metamask/src/cypress/support/importMetaMaskWallet.ts +++ b/wallets/metamask/src/cypress/support/importMetaMaskWallet.ts @@ -4,7 +4,7 @@ import getPlaywrightMetamask from '../getPlaywrightMetamask' const SEED_PHRASE = 'test test test test test test test test test test test junk' -export default async function importMetaMaskWallet(port: number) { +export default async function importMetaMaskWallet(port: number, importDefaultWallet = true) { const debuggerDetails = await fetch(`http://127.0.0.1:${port}/json/version`) const debuggerDetailsConfig = (await debuggerDetails.json()) as { @@ -28,7 +28,7 @@ export default async function importMetaMaskWallet(port: number) { const metamask = getPlaywrightMetamask(context, extensionPage, metamaskExtensionId) - await metamask.importWallet(SEED_PHRASE) + if (importDefaultWallet) await metamask.importWallet(SEED_PHRASE) cypressPage = context.pages()[extensionPageIndex === 1 ? 0 : 1] as Page await cypressPage.bringToFront() diff --git a/wallets/metamask/src/cypress/support/synpressCommands.ts b/wallets/metamask/src/cypress/support/synpressCommands.ts index 089863af3..a83791253 100644 --- a/wallets/metamask/src/cypress/support/synpressCommands.ts +++ b/wallets/metamask/src/cypress/support/synpressCommands.ts @@ -16,6 +16,9 @@ import type { Network } from '../../type/Network' declare global { namespace Cypress { interface Chainable { + importWallet(seedPhrase: string): Chainable + importWalletFromPrivateKey(privateKey: string): Chainable + getAccount(): Chainable getNetwork(): Chainable @@ -57,16 +60,21 @@ declare global { confirmTransactionAndWaitForMining(): Chainable openTransactionDetails(txIndex: number): Chainable closeTransactionDetails(): Chainable + + goBackToHomePage(): Chainable } } } export default function synpressCommands() { - Cypress.Commands.add('getAccount', () => { - return cy.task('getAccount') + // Wallet + + Cypress.Commands.add('importWallet', (seedPhrase: string) => { + return cy.task('importWallet', seedPhrase) }) - Cypress.Commands.add('getNetwork', () => { - return cy.task('getNetwork') + + Cypress.Commands.add('importWalletFromPrivateKey', (privateKey: string) => { + return cy.task('importWalletFromPrivateKey', privateKey) }) Cypress.Commands.add('connectToDapp', () => { @@ -75,6 +83,9 @@ export default function synpressCommands() { // Account + Cypress.Commands.add('getAccount', () => { + return cy.task('getAccount') + }) Cypress.Commands.add('addNewAccount', (accountName: string) => { return cy.task('addNewAccount', accountName) }) @@ -90,6 +101,9 @@ export default function synpressCommands() { // Network + Cypress.Commands.add('getNetwork', () => { + return cy.task('getNetwork') + }) Cypress.Commands.add('switchNetwork', (networkName: string, isTestnet = false) => { return cy.task('switchNetwork', { networkName, isTestnet }) }) @@ -184,4 +198,7 @@ export default function synpressCommands() { Cypress.Commands.add('closeTransactionDetails', () => { return cy.task('closeTransactionDetails') }) + Cypress.Commands.add('goBackToHomePage', () => { + return cy.task('goBackToHomePage') + }) } diff --git a/wallets/metamask/test/cypress/importWallet.cy.no-wallet.ts b/wallets/metamask/test/cypress/importWallet.cy.no-wallet.ts new file mode 100644 index 000000000..a2ff04efe --- /dev/null +++ b/wallets/metamask/test/cypress/importWallet.cy.no-wallet.ts @@ -0,0 +1,10 @@ +const SEED_PHRASE = 'test test test test test test test test test test test junk' + +describe('MetaMask Wallet Import', () => { + it('should go through the onboarding flow and import wallet from seed phrase', () => { + cy.importWallet(SEED_PHRASE) + + cy.getAccount().should('eq', 'Account 1') + cy.getAccountAddress().should('eq', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266') + }) +}) diff --git a/wallets/metamask/test/cypress/importWalletFromPrivateKey.cy.ts b/wallets/metamask/test/cypress/importWalletFromPrivateKey.cy.ts new file mode 100644 index 000000000..21b9f6c9f --- /dev/null +++ b/wallets/metamask/test/cypress/importWalletFromPrivateKey.cy.ts @@ -0,0 +1,7 @@ +describe('Import wallet from private key', () => { + it('should import a new wallet from private key', () => { + cy.importWalletFromPrivateKey('ea084c575a01e2bbefcca3db101eaeab1d8af15554640a510c73692db24d0a6a') + + cy.getAccountAddress().should('eq', '0xa2ce797cA71d0EaE1be5a7EffD27Fd6C38126801') + }) +}) From c764a433e17d7b22b474c4601b06278a7ff885f2 Mon Sep 17 00:00:00 2001 From: matstyler Date: Tue, 17 Sep 2024 19:23:01 +0200 Subject: [PATCH 2/2] fix: format --- wallets/metamask/src/cypress/MetaMask.ts | 2 +- wallets/metamask/src/cypress/configureSynpress.ts | 2 +- wallets/metamask/src/cypress/support/synpressCommands.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wallets/metamask/src/cypress/MetaMask.ts b/wallets/metamask/src/cypress/MetaMask.ts index ed06b3d7b..865955949 100644 --- a/wallets/metamask/src/cypress/MetaMask.ts +++ b/wallets/metamask/src/cypress/MetaMask.ts @@ -344,7 +344,7 @@ export default class MetaMask { await expect(this.metamaskExtensionPage.locator(HomePageSelectors.copyAccountAddressButton)).toBeVisible() } - + // Lock/Unlock async lock() { diff --git a/wallets/metamask/src/cypress/configureSynpress.ts b/wallets/metamask/src/cypress/configureSynpress.ts index 5cdebda02..20f12c2a0 100644 --- a/wallets/metamask/src/cypress/configureSynpress.ts +++ b/wallets/metamask/src/cypress/configureSynpress.ts @@ -132,7 +132,7 @@ export default function configureSynpress( // Lock/Unlock lock: () => metamask?.lock(), - unlock: () => metamask?.unlock() + unlock: () => metamask?.unlock(), // Others diff --git a/wallets/metamask/src/cypress/support/synpressCommands.ts b/wallets/metamask/src/cypress/support/synpressCommands.ts index 24ffbbb7e..cb4308b75 100644 --- a/wallets/metamask/src/cypress/support/synpressCommands.ts +++ b/wallets/metamask/src/cypress/support/synpressCommands.ts @@ -171,7 +171,7 @@ export default function synpressCommands() { Cypress.Commands.add('rejectTokenPermission', () => { return cy.task('rejectTokenPermission') }) - + // Lock/Unlock Cypress.Commands.add('lock', () => {