Skip to content

Commit

Permalink
Phantom support - Cypress tests and some refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
zgz2020 committed Dec 28, 2024
1 parent a783db3 commit 22d7fcb
Show file tree
Hide file tree
Showing 18 changed files with 132 additions and 31 deletions.
2 changes: 1 addition & 1 deletion packages/cache/src/cli/cliEntrypoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
37 changes: 32 additions & 5 deletions wallets/phantom/src/cypress/Phantom.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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

Expand All @@ -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
}

Expand All @@ -42,6 +44,8 @@ export default class Phantom {
* @returns The current account address
*/
async getAccountAddress(network: Networks): Promise<string> {
// Grant clipboard permissions to browser context
await this.phantomContext.grantPermissions(['clipboard-read'])
return await this.phantomPlaywright.getAccountAddress(network)
}

Expand Down Expand Up @@ -165,7 +169,7 @@ export default class Phantom {
async lock(): Promise<boolean> {
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
}
Expand Down Expand Up @@ -255,10 +259,7 @@ export default class Phantom {
* @returns True if the navigation was successful
*/
async goBackToHomePage(): Promise<boolean> {
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
}

Expand All @@ -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<boolean> {
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
}
}
13 changes: 11 additions & 2 deletions wallets/phantom/src/cypress/configureSynpress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
}
Expand Down Expand Up @@ -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 {
Expand Down
37 changes: 30 additions & 7 deletions wallets/phantom/src/cypress/support/synpressCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<void>
importWalletFromPrivateKey(privateKey: string): Chainable<void>
importWalletFromPrivateKey(network: Networks, privateKey: string, walletName?: string): Chainable<void>

getAccount(): Chainable<string>

Expand All @@ -24,7 +25,7 @@ declare global {
addNewAccount(accountName: string): Chainable<void>
switchAccount(accountName: string): Chainable<void>
renameAccount(currentAccountName: string, newAccountName: string): Chainable<void>
getAccountAddress(): Chainable<string>
getAccountAddress(network: Networks): Chainable<string>
resetApp(): Chainable<void>

approveTokenPermission(options?: {
Expand All @@ -48,6 +49,7 @@ declare global {
goToHomePage(): Chainable<void>
goBackToHomePage(): Chainable<void>
openSettings(): Chainable<void>
shouldHavePhantomPageElement(selector: string, visible: boolean, options?: { timeout: number }): Chainable<void>
}
}
}
Expand Down Expand Up @@ -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
})
})

/**
Expand Down Expand Up @@ -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)
})

/**
Expand Down Expand Up @@ -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
})
}
)
}
8 changes: 4 additions & 4 deletions wallets/phantom/src/playwright/Phantom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -166,7 +166,7 @@ export class Phantom extends PhantomAbstract {
* Unlocks the Phantom wallet.
*/
async unlock(): Promise<void> {
await this.lockPage.unlock(this.password)
await this.unlockPage.unlock(this.password)
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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

Expand Down
2 changes: 1 addition & 1 deletion wallets/phantom/src/playwright/pages/index.ts
Original file line number Diff line number Diff line change
@@ -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'
2 changes: 1 addition & 1 deletion wallets/phantom/src/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
3 changes: 3 additions & 0 deletions wallets/phantom/test/cypress/getAccountAddress.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
it('should should get account address for Solana network', () => {
cy.getAccountAddress('solana').should('eq', 'oeYf6KAJkLYhBuR8CiGc6L4D4Xtfepr85fuDgA9kq96')
})
11 changes: 11 additions & 0 deletions wallets/phantom/test/cypress/goBackToHomepage.cy.ts
Original file line number Diff line number Diff line change
@@ -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)
})
5 changes: 5 additions & 0 deletions wallets/phantom/test/cypress/importWalletFromPrivateKey.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
it('should import a new wallet from private key', () => {
cy.importWalletFromPrivateKey('ethereum', 'ea084c575a01e2bbefcca3db101eaeab1d8af15554640a510c73692db24d0a6a')

cy.getAccountAddress('ethereum').should('eq', '0xa2ce797cA71d0EaE1be5a7EffD27Fd6C38126801')
})
13 changes: 13 additions & 0 deletions wallets/phantom/test/cypress/lock.cy.ts
Original file line number Diff line number Diff line change
@@ -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)
})
13 changes: 13 additions & 0 deletions wallets/phantom/test/cypress/toggleTestnetMode.cy.ts
Original file line number Diff line number Diff line change
@@ -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)
})
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion wallets/phantom/test/playwright/e2e/lock.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
})

0 comments on commit 22d7fcb

Please sign in to comment.