diff --git a/wallets/phantom/playwright.config.ts b/wallets/phantom/playwright.config.ts index c21d990b..86ddab65 100644 --- a/wallets/phantom/playwright.config.ts +++ b/wallets/phantom/playwright.config.ts @@ -26,7 +26,15 @@ export default defineConfig({ // Concise 'dot' for CI, default 'html' when running locally. // See https://playwright.dev/docs/test-reporters. reporter: process.env.CI - ? [['html', { open: 'never', outputFolder: `playwright-report-${process.env.HEADLESS ? 'headless' : 'headful'}` }]] + ? [ + [ + 'html', + { + open: 'never', + outputFolder: `playwright-report-${process.env.HEADLESS ? 'headless' : 'headful'}` + } + ] + ] : 'html', // Shared settings for all the projects below. @@ -37,7 +45,9 @@ export default defineConfig({ // Collect all traces on CI, and only traces for failed tests when running locally. // See https://playwright.dev/docs/trace-viewer. - trace: process.env.CI ? 'on' : 'retain-on-failure' + trace: process.env.CI ? 'on' : 'retain-on-failure', + // Added for getting account address + permissions: ['clipboard-read'] }, // Configure projects for major browsers. diff --git a/wallets/phantom/src/playwright/pages/HomePage/actions/getAccountAddress.ts b/wallets/phantom/src/playwright/pages/HomePage/actions/getAccountAddress.ts index 4c0427c3..276eb572 100644 --- a/wallets/phantom/src/playwright/pages/HomePage/actions/getAccountAddress.ts +++ b/wallets/phantom/src/playwright/pages/HomePage/actions/getAccountAddress.ts @@ -1,13 +1,15 @@ import type { Page } from '@playwright/test' import Selectors from '../../../../selectors/pages/HomePage' +// TODO - .getAccountAddress() to be updated for all networks export default async function getAccountAddress(page: Page): Promise { - await page.locator(Selectors.threeDotsMenu.threeDotsButton).click() - await page.locator(Selectors.threeDotsMenu.accountDetailsButton).click() + // Copy account address to clipboard + await page.locator(Selectors.accountMenu.accountName).hover() + await page.locator(Selectors.ethereumWalletAddress).click() - const account = await page.locator(Selectors.copyAccountAddressButton).last().innerText() - - await page.locator(Selectors.threeDotsMenu.accountDetailsCloseButton).click() + // Get clipboard content + const handle = await page.evaluateHandle(() => navigator.clipboard.readText()) + const account = await handle.jsonValue() return account } diff --git a/wallets/phantom/src/playwright/pages/HomePage/actions/importWalletFromPrivateKey.ts b/wallets/phantom/src/playwright/pages/HomePage/actions/importWalletFromPrivateKey.ts index 038bcc2c..4febda63 100644 --- a/wallets/phantom/src/playwright/pages/HomePage/actions/importWalletFromPrivateKey.ts +++ b/wallets/phantom/src/playwright/pages/HomePage/actions/importWalletFromPrivateKey.ts @@ -25,26 +25,22 @@ export async function importWalletFromPrivateKey( await page .locator(Selectors.accountMenu.addAccountMenu.importAccountMenu.nameInput) - .fill(walletName ?? 'MyImportedWallet') + .fill(walletName ?? 'ImportedWallet') await page.locator(Selectors.accountMenu.addAccountMenu.importAccountMenu.privateKeyInput).fill(privateKey) const importButton = page.locator(Selectors.accountMenu.addAccountMenu.importAccountMenu.importButton) - await importButton.click() - - // TO DO - // Verify that header account name contains `name` or `MyImportedWallet` - // [data-testid="home-header-account-name"] - // // TODO: Extract & make configurable - const isImportButtonHidden = await waitFor(() => importButton.isHidden(), 1_000, false) + const isImportButtonEnabled = await waitFor(() => importButton.isEnabled(), 1_000, false) - if (!isImportButtonHidden) { + if (!isImportButtonEnabled) { const errorText = await page.locator(Selectors.accountMenu.addAccountMenu.importAccountMenu.error).textContent({ timeout: 1_000 // TODO: Extract & make configurable }) throw new Error(`[ImportWalletFromPrivateKey] Importing failed due to error: ${errorText}`) } + + await importButton.click() } diff --git a/wallets/phantom/src/selectors/pages/HomePage/index.ts b/wallets/phantom/src/selectors/pages/HomePage/index.ts index 8b28a62c..9b8233ba 100644 --- a/wallets/phantom/src/selectors/pages/HomePage/index.ts +++ b/wallets/phantom/src/selectors/pages/HomePage/index.ts @@ -20,7 +20,8 @@ const importAccountMenu = { bitcoinNetwork: `[data-label="Bitcoin"]`, nameInput: `input[name="name"]`, privateKeyInput: `textarea[placeholder="Private key"]`, - importButton: `button:has-text("Import")` + importButton: `button:has-text("Import")`, + error: `textarea[placeholder="Private key"] + div` } const addAccountMenu = { @@ -90,6 +91,7 @@ const activityTab = { const singleToken = '.multichain-token-list-item' export default { + ethereumWalletAddress: createDataTestSelector('account-header-chain-eip155:1'), logo: `button${createDataTestSelector('app-header-logo')}`, copyAccountAddressButton: createDataTestSelector('address-copy-button-text'), currentNetwork: `${createDataTestSelector('network-display')} span:nth-of-type(1)`, diff --git a/wallets/phantom/test/playwright/e2e/getAccountAddress.spec.ts b/wallets/phantom/test/playwright/e2e/getAccountAddress.spec.ts new file mode 100644 index 00000000..dab5fa89 --- /dev/null +++ b/wallets/phantom/test/playwright/e2e/getAccountAddress.spec.ts @@ -0,0 +1,22 @@ +import { testWithSynpress } from '@synthetixio/synpress-core' +import { Phantom, phantomFixtures } from '../../../src/playwright' + +import basicSetup from '../wallet-setup/basic.setup' + +const test = testWithSynpress(phantomFixtures(basicSetup)) + +const { expect } = test + +// TODO - .getAccountAddress() and Tests to be updated for all networks +test('should get account address', async ({ context, phantomPage }) => { + const phantom = new Phantom(context, phantomPage, basicSetup.walletPassword) + + await phantom.importWalletFromPrivateKey( + 'ethereum', + 'ea084c575a01e2bbefcca3db101eaeab1d8af15554640a510c73692db24d0a6a' + ) + + const accountAddress = await phantom.getAccountAddress() + + expect(accountAddress).toEqual('0xa2ce797cA71d0EaE1be5a7EffD27Fd6C38126801') +}) diff --git a/wallets/phantom/test/playwright/e2e/importWalletFromPrivateKey.spec.ts b/wallets/phantom/test/playwright/e2e/importWalletFromPrivateKey.spec.ts new file mode 100644 index 00000000..e004dbdd --- /dev/null +++ b/wallets/phantom/test/playwright/e2e/importWalletFromPrivateKey.spec.ts @@ -0,0 +1,44 @@ +import { testWithSynpress } from '@synthetixio/synpress-core' +import { Phantom, phantomFixtures } from '../../../src/playwright' + +import basicSetup from '../wallet-setup/basic.setup' + +const test = testWithSynpress(phantomFixtures(basicSetup)) + +const { expect } = test + +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 phantomPage.locator(phantom.homePage.selectors.accountMenu.accountName).hover() + await expect(phantomPage.locator(phantom.homePage.selectors.ethereumWalletAddress)).toContainText('0xa2ce...6801') +}) + +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) + + await expect(importWalletPromise).rejects.toThrowError( + '[ImportWalletFromPrivateKey] Importing failed due to error: This account already exists in your wallet' + ) +}) + +test('should throw an error if the private key is invalid', async ({ context, phantomPage }) => { + const phantom = new Phantom(context, phantomPage, basicSetup.walletPassword) + + const importWalletPromise = phantom.importWalletFromPrivateKey('ethereum', '0xdeadbeef') + + await expect(importWalletPromise).rejects.toThrowError( + '[ImportWalletFromPrivateKey] Importing failed due to error: Incorrect format' + ) +}) diff --git a/wallets/phantom/test/playwright/e2e/switchAccount.spec.ts b/wallets/phantom/test/playwright/e2e/switchAccount.spec.ts new file mode 100644 index 00000000..ea5fc5d8 --- /dev/null +++ b/wallets/phantom/test/playwright/e2e/switchAccount.spec.ts @@ -0,0 +1,38 @@ +import { testWithSynpress } from '@synthetixio/synpress-core' +import { Phantom, phantomFixtures } from '../../../src/playwright' + +import basicSetup from '../wallet-setup/basic.setup' + +const test = testWithSynpress(phantomFixtures(basicSetup)) + +const { expect } = test + +test('should switch account', async ({ context, phantomPage }) => { + const phantom = new Phantom(context, phantomPage, basicSetup.walletPassword) + + await phantom.importWalletFromPrivateKey( + 'ethereum', + 'ea084c575a01e2bbefcca3db101eaeab1d8af15554640a510c73692db24d0a6a' + ) + + await phantom.importWalletFromPrivateKey( + 'ethereum', + '7dd4aab86170c0edbdcf97600eff0ae319fdc94149c5e8c33d5439f8417a40bf' + ) + + await phantom.switchAccount('Account 1') + + await expect(phantomPage.getByText('Account 1')).toBeVisible() + + await phantomPage.locator(phantom.homePage.selectors.accountMenu.accountName).hover() + await expect(phantomPage.locator(phantom.homePage.selectors.ethereumWalletAddress)).toContainText('0xf39F...2266') +}) + +test('should throw an error if there is no account with target name', async ({ context, phantomPage }) => { + const phantom = new Phantom(context, phantomPage, basicSetup.walletPassword) + + const accountName = 'Account 420' + const switchAccountPromise = phantom.switchAccount(accountName) + + await expect(switchAccountPromise).rejects.toThrowError(`[SwitchAccount] Account with name ${accountName} not found`) +})