diff --git a/packages/cache/src/cli/cliEntrypoint.ts b/packages/cache/src/cli/cliEntrypoint.ts index 8e5d5b969..104c262a8 100644 --- a/packages/cache/src/cli/cliEntrypoint.ts +++ b/packages/cache/src/cli/cliEntrypoint.ts @@ -49,7 +49,7 @@ export const cliEntrypoint = async () => { } if (flags.debug) { - console.log('[DEBUG] Running with the following options ===:') + console.log('[DEBUG] Running with the following options:') console.log( { cacheDir: walletSetupDir, diff --git a/wallets/phantom/src/cypress/Phantom.ts b/wallets/phantom/src/cypress/Phantom.ts index bfcd25483..1e42d5679 100644 --- a/wallets/phantom/src/cypress/Phantom.ts +++ b/wallets/phantom/src/cypress/Phantom.ts @@ -1,7 +1,6 @@ import { type BrowserContext, type Page, expect } from '@playwright/test' import { Phantom as PhantomPlaywright } from '../playwright/Phantom' import { waitFor } from '../playwright/utils/waitFor' -import HomePageSelectors from '../selectors/pages/HomePage' import TransactionPage from '../selectors/pages/NotificationPage/transactionPage' import type { GasSettings } from '../type/GasSettings' import type { Networks } from '../type/Networks' @@ -13,6 +12,8 @@ import getPlaywrightPhantom from './getPlaywrightPhantom' export default class Phantom { /** The Phantom instance for Playwright */ readonly phantomPlaywright: PhantomPlaywright + /** The Phantom extension context */ + readonly phantomContext: BrowserContext /** The Phantom extension page */ readonly phantomExtensionPage: Page @@ -24,6 +25,7 @@ export default class Phantom { */ constructor(context: BrowserContext, phantomExtensionPage: Page, phantomExtensionId: string) { this.phantomPlaywright = getPlaywrightPhantom(context, phantomExtensionPage, phantomExtensionId) + this.phantomContext = context this.phantomExtensionPage = phantomExtensionPage } @@ -42,6 +44,8 @@ export default class Phantom { * @returns The current account address */ async getAccountAddress(network: Networks): Promise { + // Grant clipboard permissions to browser context + await this.phantomContext.grantPermissions(['clipboard-read']) return await this.phantomPlaywright.getAccountAddress(network) } @@ -165,7 +169,7 @@ export default class Phantom { async lock(): Promise { await this.phantomPlaywright.lock() await expect( - this.phantomExtensionPage.locator(this.phantomPlaywright.lockPage.selectors.submitButton) + this.phantomExtensionPage.locator(this.phantomPlaywright.unlockPage.selectors.submitButton) ).toBeVisible() return true } @@ -255,10 +259,7 @@ export default class Phantom { * @returns True if the navigation was successful */ async goBackToHomePage(): Promise { - await this.phantomPlaywright.openSettings() - await expect(this.phantomExtensionPage.locator(HomePageSelectors.copyAccountAddressButton)).not.toBeVisible() await this.phantomPlaywright.goBackToHomePage() - await expect(this.phantomExtensionPage.locator(HomePageSelectors.copyAccountAddressButton)).toBeVisible() return true } @@ -270,4 +271,30 @@ export default class Phantom { await this.phantomPlaywright.openSettings() return true } + + /** + * Gets an element in Phantpm page + * @returns Element in Phantom page + */ + async shouldHavePhantomPageElement({ + selector, + visible, + options + }: { + selector: string + visible: boolean + options?: { timeout: number } | undefined + }): Promise { + if (visible) { + await expect(this.phantomExtensionPage.locator(selector)).toBeVisible({ + timeout: options?.timeout ?? 5_000 + }) + } else { + await expect(this.phantomExtensionPage.locator(selector)).not.toBeVisible({ + timeout: options?.timeout ?? 5_000 + }) + } + + return true + } } diff --git a/wallets/phantom/src/cypress/configureSynpress.ts b/wallets/phantom/src/cypress/configureSynpress.ts index 86c883c7d..81d3cb863 100644 --- a/wallets/phantom/src/cypress/configureSynpress.ts +++ b/wallets/phantom/src/cypress/configureSynpress.ts @@ -55,7 +55,7 @@ export default function configureSynpress( config: Cypress.PluginConfigOptions, importDefaultWallet = true ) { - const browsers = config.browsers.filter((b) => b.name === 'chrome') + const browsers = config.browsers.filter((b) => b.name === 'chrome') // b.name === "chrome" if (browsers.length === 0) { throw new Error('No Chrome browser found in the configuration') } @@ -148,7 +148,16 @@ export default function configureSynpress( // Others goToHomePage: () => phantom?.goToHomePage(), goBackToHomePage: () => phantom?.goBackToHomePage(), - openSettings: () => phantom?.openSettings() + openSettings: () => phantom?.openSettings(), + shouldHavePhantomPageElement: ({ + selector, + visible, + options + }: { + selector: string + visible: boolean + options?: { timeout: number } + }) => phantom?.shouldHavePhantomPageElement({ selector, visible, options }) }) return { diff --git a/wallets/phantom/src/cypress/support/synpressCommands.ts b/wallets/phantom/src/cypress/support/synpressCommands.ts index dbd191a95..4385afe52 100644 --- a/wallets/phantom/src/cypress/support/synpressCommands.ts +++ b/wallets/phantom/src/cypress/support/synpressCommands.ts @@ -10,12 +10,13 @@ // *********************************************** import type { GasSettings } from '../../type/GasSettings' +import type { Networks } from '../../type/Networks' declare global { namespace Cypress { interface Chainable { importWallet(seedPhrase: string): Chainable - importWalletFromPrivateKey(privateKey: string): Chainable + importWalletFromPrivateKey(network: Networks, privateKey: string, walletName?: string): Chainable getAccount(): Chainable @@ -24,7 +25,7 @@ declare global { addNewAccount(accountName: string): Chainable switchAccount(accountName: string): Chainable renameAccount(currentAccountName: string, newAccountName: string): Chainable - getAccountAddress(): Chainable + getAccountAddress(network: Networks): Chainable resetApp(): Chainable approveTokenPermission(options?: { @@ -48,6 +49,7 @@ declare global { goToHomePage(): Chainable goBackToHomePage(): Chainable openSettings(): Chainable + shouldHavePhantomPageElement(selector: string, visible: boolean, options?: { timeout: number }): Chainable } } } @@ -91,8 +93,12 @@ export default function synpressCommandsForPhantom(): void { * Imports a wallet using a private key * @param privateKey - The private key to import */ - Cypress.Commands.add('importWalletFromPrivateKey', (privateKey: string) => { - return cy.task('importWalletFromPrivateKey', privateKey) + Cypress.Commands.add('importWalletFromPrivateKey', (network: Networks, privateKey: string, walletName?: string) => { + return cy.task('importWalletFromPrivateKey', { + network, + privateKey, + walletName + }) }) /** @@ -137,11 +143,11 @@ export default function synpressCommandsForPhantom(): void { }) /** - * Gets the address of the current account + * Gets the address of the current account for a specific network * @returns The account address */ - Cypress.Commands.add('getAccountAddress', () => { - return cy.task('getAccountAddress') + Cypress.Commands.add('getAccountAddress', (network: Networks) => { + return cy.task('getAccountAddress', network) }) /** @@ -250,4 +256,21 @@ export default function synpressCommandsForPhantom(): void { Cypress.Commands.add('openSettings', () => { return cy.task('openSettings') }) + + /** + * Verifies if an element is visible (or not) in Phantom page + * @param selector - Selector of the element to be asserted + * @param selector - Whether the element should be visible or not + * @param options.timeout - Optional custom timeout + */ + Cypress.Commands.add( + 'shouldHavePhantomPageElement', + (selector: string, visible: boolean, options?: { timeout: number }) => { + return cy.task('shouldHavePhantomPageElement', { + selector, + visible, + options + }) + } + ) } diff --git a/wallets/phantom/src/playwright/Phantom.ts b/wallets/phantom/src/playwright/Phantom.ts index 9352e0d8d..d23dcd10c 100644 --- a/wallets/phantom/src/playwright/Phantom.ts +++ b/wallets/phantom/src/playwright/Phantom.ts @@ -2,7 +2,7 @@ import type { BrowserContext, Page } from '@playwright/test' import type { GasSettings } from '../type/GasSettings' import type { Networks } from '../type/Networks' import { PhantomAbstract } from '../type/PhantomAbstract' -import { CrashPage, HomePage, LockPage, NotificationPage, OnboardingPage } from './pages' +import { CrashPage, HomePage, NotificationPage, OnboardingPage, UnlockPage } from './pages' const NO_EXTENSION_ID_ERROR = new Error('Phantom extensionId is not set') @@ -38,7 +38,7 @@ export class Phantom extends PhantomAbstract { * @public * @readonly */ - readonly lockPage: LockPage + readonly unlockPage: UnlockPage /** * This property can be used to access selectors for the home page. @@ -74,7 +74,7 @@ export class Phantom extends PhantomAbstract { this.crashPage = new CrashPage() this.onboardingPage = new OnboardingPage(page) - this.lockPage = new LockPage(page) + this.unlockPage = new UnlockPage(page) this.homePage = new HomePage(page) this.notificationPage = new NotificationPage(page) } @@ -166,7 +166,7 @@ export class Phantom extends PhantomAbstract { * Unlocks the Phantom wallet. */ async unlock(): Promise { - await this.lockPage.unlock(this.password) + await this.unlockPage.unlock(this.password) } /** diff --git a/wallets/phantom/src/playwright/pages/LockPage/actions/index.ts b/wallets/phantom/src/playwright/pages/UnlockPage/actions/index.ts similarity index 100% rename from wallets/phantom/src/playwright/pages/LockPage/actions/index.ts rename to wallets/phantom/src/playwright/pages/UnlockPage/actions/index.ts diff --git a/wallets/phantom/src/playwright/pages/LockPage/actions/unlock.ts b/wallets/phantom/src/playwright/pages/UnlockPage/actions/unlock.ts similarity index 84% rename from wallets/phantom/src/playwright/pages/LockPage/actions/unlock.ts rename to wallets/phantom/src/playwright/pages/UnlockPage/actions/unlock.ts index 79e3956df..7130b3fbe 100644 --- a/wallets/phantom/src/playwright/pages/LockPage/actions/unlock.ts +++ b/wallets/phantom/src/playwright/pages/UnlockPage/actions/unlock.ts @@ -1,5 +1,5 @@ import type { Page } from '@playwright/test' -import Selectors from '../../../../selectors/pages/LockPage' +import Selectors from '../../../../selectors/pages/UnlockPage' import { waitForSpinnerToVanish } from '../../../utils/waitForSpinnerToVanish' export async function unlock(page: Page, password: string) { diff --git a/wallets/phantom/src/playwright/pages/LockPage/page.ts b/wallets/phantom/src/playwright/pages/UnlockPage/page.ts similarity index 78% rename from wallets/phantom/src/playwright/pages/LockPage/page.ts rename to wallets/phantom/src/playwright/pages/UnlockPage/page.ts index 1b14d06e6..85e197742 100644 --- a/wallets/phantom/src/playwright/pages/LockPage/page.ts +++ b/wallets/phantom/src/playwright/pages/UnlockPage/page.ts @@ -1,8 +1,8 @@ import type { Page } from '@playwright/test' -import Selectors from '../../../selectors/pages/LockPage' +import Selectors from '../../../selectors/pages/UnlockPage' import { unlock } from './actions' -export class LockPage { +export class UnlockPage { static readonly selectors = Selectors readonly selectors = Selectors diff --git a/wallets/phantom/src/playwright/pages/index.ts b/wallets/phantom/src/playwright/pages/index.ts index 9388f7d49..78f98ea2c 100644 --- a/wallets/phantom/src/playwright/pages/index.ts +++ b/wallets/phantom/src/playwright/pages/index.ts @@ -1,5 +1,5 @@ export * from './OnboardingPage/page' export * from './CrashPage/page' -export * from './LockPage/page' +export * from './UnlockPage/page' export * from './HomePage/page' export * from './NotificationPage/page' diff --git a/wallets/phantom/src/selectors/index.ts b/wallets/phantom/src/selectors/index.ts index dcba70893..e98e7d7de 100644 --- a/wallets/phantom/src/selectors/index.ts +++ b/wallets/phantom/src/selectors/index.ts @@ -3,7 +3,7 @@ export * from './error' export { default as crashPage } from './pages/CrashPage' export { default as homePage } from './pages/HomePage' -export { default as lockPage } from './pages/LockPage' +export { default as unlockPage } from './pages/UnlockPage' export { default as notificationPage } from './pages/NotificationPage' export { default as onboardingPage } from './pages/OnboardingPage' export { default as settingsPage } from './pages/SettingsPage' diff --git a/wallets/phantom/src/selectors/pages/LockPage/index.ts b/wallets/phantom/src/selectors/pages/UnlockPage/index.ts similarity index 100% rename from wallets/phantom/src/selectors/pages/LockPage/index.ts rename to wallets/phantom/src/selectors/pages/UnlockPage/index.ts diff --git a/wallets/phantom/test/cypress/getAccountAddress.cy.ts b/wallets/phantom/test/cypress/getAccountAddress.cy.ts new file mode 100644 index 000000000..6c93cbd64 --- /dev/null +++ b/wallets/phantom/test/cypress/getAccountAddress.cy.ts @@ -0,0 +1,3 @@ +it('should should get account address for Solana network', () => { + cy.getAccountAddress('solana').should('eq', 'oeYf6KAJkLYhBuR8CiGc6L4D4Xtfepr85fuDgA9kq96') +}) diff --git a/wallets/phantom/test/cypress/goBackToHomepage.cy.ts b/wallets/phantom/test/cypress/goBackToHomepage.cy.ts new file mode 100644 index 000000000..a43b66e86 --- /dev/null +++ b/wallets/phantom/test/cypress/goBackToHomepage.cy.ts @@ -0,0 +1,11 @@ +import * as selectors from '../../src/selectors/' + +it('should open settings and go back to homepage', () => { + cy.openSettings() + + cy.shouldHavePhantomPageElement(selectors.homePage.settings.lockWallet, true) + + cy.goBackToHomePage() + + cy.shouldHavePhantomPageElement(selectors.homePage.settings.lockWallet, false) +}) diff --git a/wallets/phantom/test/cypress/importWalletFromPrivateKey.cy.ts b/wallets/phantom/test/cypress/importWalletFromPrivateKey.cy.ts new file mode 100644 index 000000000..a1a0da5f0 --- /dev/null +++ b/wallets/phantom/test/cypress/importWalletFromPrivateKey.cy.ts @@ -0,0 +1,5 @@ +it('should import a new wallet from private key', () => { + cy.importWalletFromPrivateKey('ethereum', 'ea084c575a01e2bbefcca3db101eaeab1d8af15554640a510c73692db24d0a6a') + + cy.getAccountAddress('ethereum').should('eq', '0xa2ce797cA71d0EaE1be5a7EffD27Fd6C38126801') +}) diff --git a/wallets/phantom/test/cypress/lock.cy.ts b/wallets/phantom/test/cypress/lock.cy.ts new file mode 100644 index 000000000..37c083d7e --- /dev/null +++ b/wallets/phantom/test/cypress/lock.cy.ts @@ -0,0 +1,13 @@ +import * as selectors from '../../src/selectors/' + +it('should lock & unlock the wallet without any errors', () => { + cy.shouldHavePhantomPageElement(selectors.homePage.accountMenu.accountName, true) + + cy.lock() + + cy.shouldHavePhantomPageElement(selectors.unlockPage.submitButton, true) + + cy.unlock() + + cy.shouldHavePhantomPageElement(selectors.homePage.accountMenu.accountName, true) +}) diff --git a/wallets/phantom/test/cypress/toggleTestnetMode.cy.ts b/wallets/phantom/test/cypress/toggleTestnetMode.cy.ts new file mode 100644 index 000000000..f5d5f099f --- /dev/null +++ b/wallets/phantom/test/cypress/toggleTestnetMode.cy.ts @@ -0,0 +1,13 @@ +it('should toggle Testnet mode', () => { + // Turn Testnet mode ON + cy.toggleTestnetMode() + + cy.goToHomePage() + cy.shouldHavePhantomPageElement('text=You are currently in Testnet Mode', true) + + // Turn Testnet mode OFF + cy.toggleTestnetMode() + + cy.goToHomePage() + cy.shouldHavePhantomPageElement('text=You are currently in Testnet Mode', false) +}) diff --git a/wallets/phantom/test/playwright/e2e/importWalletFromPrivateKey.spec.ts b/wallets/phantom/test/playwright/e2e/importWalletFromPrivateKey.spec.ts index e004dbddf..e6cafef2a 100644 --- a/wallets/phantom/test/playwright/e2e/importWalletFromPrivateKey.spec.ts +++ b/wallets/phantom/test/playwright/e2e/importWalletFromPrivateKey.spec.ts @@ -7,13 +7,12 @@ const test = testWithSynpress(phantomFixtures(basicSetup)) const { expect } = test +const privateKey = 'ea084c575a01e2bbefcca3db101eaeab1d8af15554640a510c73692db24d0a6a' + test('should import a new wallet from private key', async ({ context, phantomPage }) => { const phantom = new Phantom(context, phantomPage, basicSetup.walletPassword) - await phantom.importWalletFromPrivateKey( - 'ethereum', - 'ea084c575a01e2bbefcca3db101eaeab1d8af15554640a510c73692db24d0a6a' - ) + await phantom.importWalletFromPrivateKey('ethereum', privateKey) await phantomPage.locator(phantom.homePage.selectors.accountMenu.accountName).hover() await expect(phantomPage.locator(phantom.homePage.selectors.ethereumWalletAddress)).toContainText('0xa2ce...6801') @@ -22,8 +21,6 @@ test('should import a new wallet from private key', async ({ context, phantomPag test('should throw an error if trying to import private key for the 2nd time', async ({ context, phantomPage }) => { const phantom = new Phantom(context, phantomPage, basicSetup.walletPassword) - const privateKey = 'ea084c575a01e2bbefcca3db101eaeab1d8af15554640a510c73692db24d0a6a' - await phantom.importWalletFromPrivateKey('ethereum', privateKey) const importWalletPromise = phantom.importWalletFromPrivateKey('ethereum', privateKey) diff --git a/wallets/phantom/test/playwright/e2e/lock.spec.ts b/wallets/phantom/test/playwright/e2e/lock.spec.ts index 8a4b4f843..e6b748038 100644 --- a/wallets/phantom/test/playwright/e2e/lock.spec.ts +++ b/wallets/phantom/test/playwright/e2e/lock.spec.ts @@ -12,5 +12,5 @@ test('should lock the wallet', async ({ context, phantomPage }) => { await phantom.lock() - await expect(phantomPage.locator(phantom.lockPage.selectors.submitButton)).toBeVisible() + await expect(phantomPage.locator(phantom.unlockPage.selectors.submitButton)).toBeVisible() })