From 0383ec9055e3d16965573edeed0329984b5a50ad Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Fri, 16 Aug 2024 14:36:00 +0200 Subject: [PATCH 01/23] Add code to reduce flakiness --- .../shared/pageObjects/wallet-page.ts | 1 + .../playwright/swap/pageObjects/swap-page.ts | 35 ++++++++++++++----- test/e2e/playwright/swap/specs/swap.spec.ts | 29 +++++++++------ 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/test/e2e/playwright/shared/pageObjects/wallet-page.ts b/test/e2e/playwright/shared/pageObjects/wallet-page.ts index 47a9b667c96c..5bab83a68c4c 100644 --- a/test/e2e/playwright/shared/pageObjects/wallet-page.ts +++ b/test/e2e/playwright/shared/pageObjects/wallet-page.ts @@ -29,6 +29,7 @@ export class WalletPage { await this.importTokensButton.click(); await this.importButton.waitFor({ state: 'visible' }); await this.importButton.click(); + await this.page.waitForTimeout(6000); } async selectTokenWallet() { diff --git a/test/e2e/playwright/swap/pageObjects/swap-page.ts b/test/e2e/playwright/swap/pageObjects/swap-page.ts index 094d92b0d116..0aa49f97ac9c 100644 --- a/test/e2e/playwright/swap/pageObjects/swap-page.ts +++ b/test/e2e/playwright/swap/pageObjects/swap-page.ts @@ -2,6 +2,7 @@ import { type Locator, type Page } from '@playwright/test'; export class SwapPage { private page: Page; + private swapQty: string; readonly toggleSmartSwap: Locator; @@ -29,6 +30,7 @@ export class SwapPage { constructor(page: Page) { this.page = page; + this.swapQty = ''; this.toggleSmartSwap = this.page.locator('text="On"'); this.updateSettingsButton = this.page.getByTestId( 'update-transaction-settings-button', @@ -55,9 +57,10 @@ export class SwapPage { this.backButton = this.page.locator('[title="Cancel"]'); } - async fetchQuote(options: { from?: string; to: string; qty: string }) { + async enterQuote(options: { from?: string; to: string; qty: string }) { // Enter Swap Quantity await this.tokenQty.fill(options.qty); + this.swapQty = options.qty; // Enter source token if (options.from) { @@ -72,18 +75,34 @@ export class SwapPage { await this.selectTokenFromList(options.to); } + async waitForQuote() { + do { + // Clear Swap Anyway button if present + const swapAnywayButton = await this.page.$('text=/Swap anyway/'); + if (swapAnywayButton) { + await swapAnywayButton.click(); + } + + // No quotes available + const noQuotes = await this.page.$('text=/No quotes available/'); + if (noQuotes) { + //re-entering the qty will trigger new quote + await this.tokenQty.fill(''); + await this.tokenQty.fill(this.swapQty); + } + + if (await this.page.$('text=/New quotes in/')) break; + + await this.page.waitForTimeout(500); + } while (true); + } + async swap() { await this.waitForCountDown(); - - // Clear Swap Anyway button if present - const swapAnywayButton = await this.page.$('text=/Swap anyway/'); - if (swapAnywayButton) { - await swapAnywayButton.click(); - } await this.swapTokenButton.click(); } - async switchTokens() { + async switchTokenOrder() { // Wait for swap button to appear await this.swapTokenButton.waitFor(); await this.switchTokensButton.click(); diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index a795f67b2753..5763cfc0ded5 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -15,11 +15,12 @@ let activityListPage: ActivityListPage; const Tenderly = { Mainnet: { name: 'Tenderly', - url: 'https://rpc.tenderly.co/fork/cdbcd795-097d-4624-aa16-680374d89a43', + url: 'https://rpc.tenderly.co/fork/eb5b1b8b-b19e-425e-8197-03b75d680576', chainID: '1', symbol: 'ETH', }, }; +//url: 'https://rpc.tenderly.co/fork/cdbcd795-097d-4624-aa16-680374d89a43' test.beforeEach( 'Initialize extension, import wallet and add custom networks', @@ -43,7 +44,8 @@ test.beforeEach( test('Swap ETH to DAI - Switch to Arbitrum and fetch quote - Switch ETH - WETH', async () => { await walletPage.importTokens(); await walletPage.selectSwapAction(); - await swapPage.fetchQuote({ from: 'ETH', to: 'DAI', qty: '.001' }); + await swapPage.enterQuote({ from: 'ETH', to: 'DAI', qty: '.001' }); + await swapPage.waitForQuote() await swapPage.swap(); await swapPage.waitForTransactionToComplete(); await walletPage.selectActivityList(); @@ -53,7 +55,7 @@ test('Swap ETH to DAI - Switch to Arbitrum and fetch quote - Switch ETH - WETH', await networkController.addPopularNetwork({ networkName: 'Arbitrum One' }); await walletPage.selectSwapAction(); - await swapPage.fetchQuote({ to: 'MATIC', qty: '.001' }); + await swapPage.enterQuote({ to: 'MATIC', qty: '.001' }); await swapPage.waitForInsufficentBalance(); await swapPage.gotBack(); @@ -62,9 +64,11 @@ test('Swap ETH to DAI - Switch to Arbitrum and fetch quote - Switch ETH - WETH', activity: 'Swap ETH to DAI', }); await walletPage.selectTokenWallet(); - await walletPage.importTokens(); + //await walletPage.importTokens(); + await walletPage.selectSwapAction(); - await swapPage.fetchQuote({ from: 'ETH', to: 'WETH', qty: '.001' }); + await swapPage.enterQuote({ from: 'ETH', to: 'WETH', qty: '.001' }); + await swapPage.waitForQuote() await swapPage.swap(); await swapPage.waitForTransactionToComplete(); await walletPage.selectActivityList(); @@ -75,8 +79,10 @@ test('Swap ETH to DAI - Switch to Arbitrum and fetch quote - Switch ETH - WETH', test('Swap WETH to ETH - Switch to Avalanche and fetch quote - Switch DAI - USDC', async () => { await walletPage.importTokens(); + await walletPage.selectSwapAction(); - await swapPage.fetchQuote({ from: 'ETH', to: 'WETH', qty: '.001' }); + await swapPage.enterQuote({ from: 'ETH', to: 'WETH', qty: '.001' }); + await swapPage.waitForQuote() await swapPage.swap(); await swapPage.waitForTransactionToComplete(); await walletPage.selectActivityList(); @@ -88,7 +94,7 @@ test('Swap WETH to ETH - Switch to Avalanche and fetch quote - Switch DAI - USDC networkName: 'Avalanche Network C-Chain', }); await walletPage.selectSwapAction(); - await swapPage.fetchQuote({ to: 'USDC', qty: '.001' }); + await swapPage.enterQuote({ to: 'BNB', qty: '.001' }); await swapPage.waitForInsufficentBalance(); await swapPage.gotBack(); @@ -98,10 +104,13 @@ test('Swap WETH to ETH - Switch to Avalanche and fetch quote - Switch DAI - USDC activity: 'Swap ETH to WETH', }); await walletPage.selectTokenWallet(); - await walletPage.importTokens(); + //await walletPage.importTokens(); + await walletPage.selectSwapAction(); - await swapPage.fetchQuote({ from: 'DAI', to: 'USDC', qty: '.5' }); - await swapPage.switchTokens(); + await swapPage.enterQuote({ from: 'DAI', to: 'USDC', qty: '.5' }); + await swapPage.waitForQuote() + await swapPage.switchTokenOrder(); + await swapPage.waitForQuote() await swapPage.swap(); await swapPage.waitForTransactionToComplete(); await walletPage.selectActivityList(); From 9cedc90d0fe043137a31ba94891b9231acb569bc Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Mon, 19 Aug 2024 13:53:27 +0200 Subject: [PATCH 02/23] More fixes --- .../playwright/shared/pageObjects/wallet-page.ts | 1 - test/e2e/playwright/swap/pageObjects/swap-page.ts | 13 ++++++++++--- test/e2e/playwright/swap/specs/swap.spec.ts | 15 +++++++-------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/test/e2e/playwright/shared/pageObjects/wallet-page.ts b/test/e2e/playwright/shared/pageObjects/wallet-page.ts index 5bab83a68c4c..47a9b667c96c 100644 --- a/test/e2e/playwright/shared/pageObjects/wallet-page.ts +++ b/test/e2e/playwright/shared/pageObjects/wallet-page.ts @@ -29,7 +29,6 @@ export class WalletPage { await this.importTokensButton.click(); await this.importButton.waitFor({ state: 'visible' }); await this.importButton.click(); - await this.page.waitForTimeout(6000); } async selectTokenWallet() { diff --git a/test/e2e/playwright/swap/pageObjects/swap-page.ts b/test/e2e/playwright/swap/pageObjects/swap-page.ts index 0aa49f97ac9c..19f965ae3358 100644 --- a/test/e2e/playwright/swap/pageObjects/swap-page.ts +++ b/test/e2e/playwright/swap/pageObjects/swap-page.ts @@ -2,6 +2,7 @@ import { type Locator, type Page } from '@playwright/test'; export class SwapPage { private page: Page; + private swapQty: string; readonly toggleSmartSwap: Locator; @@ -65,17 +66,20 @@ export class SwapPage { // Enter source token if (options.from) { this.swapFromDropDown.click(); + await this.page.waitForTimeout(2000); await this.tokenSearch.fill(options.from); await this.selectTokenFromList(options.from); } // Enter destionation token await this.swapToDropDown.click(); + await this.page.waitForTimeout(2000); await this.tokenSearch.fill(options.to); await this.selectTokenFromList(options.to); } async waitForQuote() { + let quoteFound = false; do { // Clear Swap Anyway button if present const swapAnywayButton = await this.page.$('text=/Swap anyway/'); @@ -86,15 +90,18 @@ export class SwapPage { // No quotes available const noQuotes = await this.page.$('text=/No quotes available/'); if (noQuotes) { - //re-entering the qty will trigger new quote + // re-entering the qty will trigger new quote await this.tokenQty.fill(''); await this.tokenQty.fill(this.swapQty); } - if (await this.page.$('text=/New quotes in/')) break; + if (await this.page.$('text=/New quotes in/')) { + quoteFound = true; + break; + } await this.page.waitForTimeout(500); - } while (true); + } while (!quoteFound); } async swap() { diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index 5763cfc0ded5..f11c40e0d1c1 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -20,7 +20,6 @@ const Tenderly = { symbol: 'ETH', }, }; -//url: 'https://rpc.tenderly.co/fork/cdbcd795-097d-4624-aa16-680374d89a43' test.beforeEach( 'Initialize extension, import wallet and add custom networks', @@ -45,7 +44,7 @@ test('Swap ETH to DAI - Switch to Arbitrum and fetch quote - Switch ETH - WETH', await walletPage.importTokens(); await walletPage.selectSwapAction(); await swapPage.enterQuote({ from: 'ETH', to: 'DAI', qty: '.001' }); - await swapPage.waitForQuote() + await swapPage.waitForQuote(); await swapPage.swap(); await swapPage.waitForTransactionToComplete(); await walletPage.selectActivityList(); @@ -64,11 +63,11 @@ test('Swap ETH to DAI - Switch to Arbitrum and fetch quote - Switch ETH - WETH', activity: 'Swap ETH to DAI', }); await walletPage.selectTokenWallet(); - //await walletPage.importTokens(); + // await walletPage.importTokens(); await walletPage.selectSwapAction(); await swapPage.enterQuote({ from: 'ETH', to: 'WETH', qty: '.001' }); - await swapPage.waitForQuote() + await swapPage.waitForQuote(); await swapPage.swap(); await swapPage.waitForTransactionToComplete(); await walletPage.selectActivityList(); @@ -82,7 +81,7 @@ test('Swap WETH to ETH - Switch to Avalanche and fetch quote - Switch DAI - USDC await walletPage.selectSwapAction(); await swapPage.enterQuote({ from: 'ETH', to: 'WETH', qty: '.001' }); - await swapPage.waitForQuote() + await swapPage.waitForQuote(); await swapPage.swap(); await swapPage.waitForTransactionToComplete(); await walletPage.selectActivityList(); @@ -104,13 +103,13 @@ test('Swap WETH to ETH - Switch to Avalanche and fetch quote - Switch DAI - USDC activity: 'Swap ETH to WETH', }); await walletPage.selectTokenWallet(); - //await walletPage.importTokens(); + // await walletPage.importTokens(); await walletPage.selectSwapAction(); await swapPage.enterQuote({ from: 'DAI', to: 'USDC', qty: '.5' }); - await swapPage.waitForQuote() + await swapPage.waitForQuote(); await swapPage.switchTokenOrder(); - await swapPage.waitForQuote() + await swapPage.waitForQuote(); await swapPage.swap(); await swapPage.waitForTransactionToComplete(); await walletPage.selectActivityList(); From f968288af85a3e9b7e9acbde3d8c88d34fd5099c Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Tue, 20 Aug 2024 10:17:12 +0200 Subject: [PATCH 03/23] Fix wait for Token --- test/e2e/playwright/swap/pageObjects/swap-page.ts | 8 ++++++-- test/e2e/playwright/swap/specs/swap.spec.ts | 4 ---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/e2e/playwright/swap/pageObjects/swap-page.ts b/test/e2e/playwright/swap/pageObjects/swap-page.ts index 19f965ae3358..f0b99b16ed22 100644 --- a/test/e2e/playwright/swap/pageObjects/swap-page.ts +++ b/test/e2e/playwright/swap/pageObjects/swap-page.ts @@ -66,14 +66,12 @@ export class SwapPage { // Enter source token if (options.from) { this.swapFromDropDown.click(); - await this.page.waitForTimeout(2000); await this.tokenSearch.fill(options.from); await this.selectTokenFromList(options.from); } // Enter destionation token await this.swapToDropDown.click(); - await this.page.waitForTimeout(2000); await this.tokenSearch.fill(options.to); await this.selectTokenFromList(options.to); } @@ -147,6 +145,12 @@ export class SwapPage { let searchItem; do { searchItem = await this.tokenList.first().textContent(); + const listCount = await this.tokenList.count(); + + if (listCount > 1 && searchItem !== symbol) { + await this.tokenQty.fill(''); + await this.tokenQty.fill(symbol); + } } while (searchItem !== symbol); return await this.tokenList.first().click(); diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index f11c40e0d1c1..e3d85c12bfa1 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -63,8 +63,6 @@ test('Swap ETH to DAI - Switch to Arbitrum and fetch quote - Switch ETH - WETH', activity: 'Swap ETH to DAI', }); await walletPage.selectTokenWallet(); - // await walletPage.importTokens(); - await walletPage.selectSwapAction(); await swapPage.enterQuote({ from: 'ETH', to: 'WETH', qty: '.001' }); await swapPage.waitForQuote(); @@ -103,8 +101,6 @@ test('Swap WETH to ETH - Switch to Avalanche and fetch quote - Switch DAI - USDC activity: 'Swap ETH to WETH', }); await walletPage.selectTokenWallet(); - // await walletPage.importTokens(); - await walletPage.selectSwapAction(); await swapPage.enterQuote({ from: 'DAI', to: 'USDC', qty: '.5' }); await swapPage.waitForQuote(); From d90630288ab41d9714d6788c3b1303cd5d83fffc Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Thu, 22 Aug 2024 19:02:32 +0200 Subject: [PATCH 04/23] Added forks for Arbitrum and Avalanche --- .circleci/config.yml | 3 ++ .../pageObjects/network-controller-page.ts | 1 + .../playwright/swap/pageObjects/swap-page.ts | 15 +++--- test/e2e/playwright/swap/specs/swap.spec.ts | 54 ++++++++++++------- 4 files changed, 47 insertions(+), 26 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3836d5e4048e..29354572a778 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -234,6 +234,9 @@ workflows: - test-e2e-mmi-playwright: requires: - prep-build-test-mmi-playwright + - test-e2e-swap-playwright - OPTIONAL: + requires: + - prep-build - test-e2e-chrome-rpc-mmi: requires: - prep-build-test-mmi diff --git a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts index aed0e7377b16..2a0e022a47df 100644 --- a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts +++ b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts @@ -64,6 +64,7 @@ export class NetworkController { await this.networkTicker.fill(options.symbol); await this.saveBtn.click(); await this.switchToNetworkBtn.click(); + await this.page.$(`text=/${options.name}/`); } async addPopularNetwork(options: { networkName: string }) { diff --git a/test/e2e/playwright/swap/pageObjects/swap-page.ts b/test/e2e/playwright/swap/pageObjects/swap-page.ts index f0b99b16ed22..d9eeab400322 100644 --- a/test/e2e/playwright/swap/pageObjects/swap-page.ts +++ b/test/e2e/playwright/swap/pageObjects/swap-page.ts @@ -59,20 +59,18 @@ export class SwapPage { } async enterQuote(options: { from?: string; to: string; qty: string }) { - // Enter Swap Quantity - await this.tokenQty.fill(options.qty); - this.swapQty = options.qty; - // Enter source token if (options.from) { this.swapFromDropDown.click(); - await this.tokenSearch.fill(options.from); await this.selectTokenFromList(options.from); } - // Enter destionation token + // Enter Swap Quantity + await this.tokenQty.fill(options.qty); + this.swapQty = options.qty; + + // Enter destination token await this.swapToDropDown.click(); - await this.tokenSearch.fill(options.to); await this.selectTokenFromList(options.to); } @@ -134,6 +132,9 @@ export class SwapPage { async selectTokenFromList(symbol: string) { let searchItem; + + await this.page.waitForTimeout(500); + await this.tokenSearch.fill(symbol); do { searchItem = await this.tokenList.first().textContent(); } while (searchItem !== symbol); diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index e3d85c12bfa1..a49223c24c2b 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -14,11 +14,23 @@ let activityListPage: ActivityListPage; const Tenderly = { Mainnet: { - name: 'Tenderly', - url: 'https://rpc.tenderly.co/fork/eb5b1b8b-b19e-425e-8197-03b75d680576', + name: 'Tenderly - Mainnet', + url: 'https://virtual.mainnet.rpc.tenderly.co/e63e2a2e-a04c-4f32-8379-c1fca19e82b6', chainID: '1', symbol: 'ETH', }, + Arbitrum: { + name: 'Tenderly - Arbitrum', + url: 'https://virtual.arbitrum.rpc.tenderly.co/70c7bde4-54e7-46a6-9053-9c3c539dcecf', + chainID: '42161', + symbol: 'ETH', + }, + Avalanche: { + name: 'Tenderly - Avalanche', + url: 'https://virtual.avalanche.rpc.tenderly.co/ff17f1b4-f8ef-456e-be68-07481bc853ec', + chainID: '43114', + symbol: 'AVAX', + }, }; test.beforeEach( @@ -42,6 +54,7 @@ test.beforeEach( test('Swap ETH to DAI - Switch to Arbitrum and fetch quote - Switch ETH - WETH', async () => { await walletPage.importTokens(); + await walletPage.selectSwapAction(); await swapPage.enterQuote({ from: 'ETH', to: 'DAI', qty: '.001' }); await swapPage.waitForQuote(); @@ -52,16 +65,19 @@ test('Swap ETH to DAI - Switch to Arbitrum and fetch quote - Switch ETH - WETH', activity: 'Swap ETH to DAI', }); - await networkController.addPopularNetwork({ networkName: 'Arbitrum One' }); + await networkController.addCustomNetwork(Tenderly.Arbitrum); + await walletPage.selectTokenWallet(); await walletPage.selectSwapAction(); - await swapPage.enterQuote({ to: 'MATIC', qty: '.001' }); - await swapPage.waitForInsufficentBalance(); - await swapPage.gotBack(); - - await networkController.selectNetwork({ networkName: 'Tenderly' }); + await swapPage.enterQuote({ from: 'ETH', to: 'MATIC', qty: '.001' }); + await swapPage.waitForQuote(); + await swapPage.swap(); + await swapPage.waitForTransactionToComplete(); + await walletPage.selectActivityList(); await activityListPage.checkActivityIsConfirmed({ - activity: 'Swap ETH to DAI', + activity: 'Swap ETH to MATIC', }); + + await networkController.selectNetwork({ networkName: 'Tenderly - Mainnet' }); await walletPage.selectTokenWallet(); await walletPage.selectSwapAction(); await swapPage.enterQuote({ from: 'ETH', to: 'WETH', qty: '.001' }); @@ -87,19 +103,19 @@ test('Swap WETH to ETH - Switch to Avalanche and fetch quote - Switch DAI - USDC activity: 'Swap ETH to WETH', }); - await networkController.addPopularNetwork({ - networkName: 'Avalanche Network C-Chain', - }); + await networkController.addCustomNetwork(Tenderly.Avalanche); + await walletPage.selectTokenWallet(); await walletPage.selectSwapAction(); - await swapPage.enterQuote({ to: 'BNB', qty: '.001' }); - await swapPage.waitForInsufficentBalance(); - - await swapPage.gotBack(); - - await networkController.selectNetwork({ networkName: 'Tenderly' }); + await swapPage.enterQuote({ from: 'AVAX', to: 'BNB', qty: '.001' }); + await swapPage.waitForQuote(); + await swapPage.swap(); + await swapPage.waitForTransactionToComplete(); + await walletPage.selectActivityList(); await activityListPage.checkActivityIsConfirmed({ - activity: 'Swap ETH to WETH', + activity: 'Swap AVAX to BNB', }); + + await networkController.selectNetwork({ networkName: 'Tenderly - Mainnet' }); await walletPage.selectTokenWallet(); await walletPage.selectSwapAction(); await swapPage.enterQuote({ from: 'DAI', to: 'USDC', qty: '.5' }); From 0ad50e859ab563771415afac12f328ffe0724c30 Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Mon, 26 Aug 2024 19:00:20 +0200 Subject: [PATCH 05/23] Remove forked network --- playwright.config.ts | 1 + test/e2e/playwright/swap/specs/swap.spec.ts | 31 ++++++++------------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/playwright.config.ts b/playwright.config.ts index 6632e1983e79..0145cd3dcc49 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -71,6 +71,7 @@ const config: PlaywrightTestConfig = { ...devices['Desktop Chrome'], headless: true, }, + fullyParallel: false, }, // Global: universal, common, shared, and non feature related tests { diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index a49223c24c2b..c359016ad431 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -65,17 +65,11 @@ test('Swap ETH to DAI - Switch to Arbitrum and fetch quote - Switch ETH - WETH', activity: 'Swap ETH to DAI', }); - await networkController.addCustomNetwork(Tenderly.Arbitrum); - await walletPage.selectTokenWallet(); + await networkController.addPopularNetwork({ networkName: 'Arbitrum One' }); await walletPage.selectSwapAction(); - await swapPage.enterQuote({ from: 'ETH', to: 'MATIC', qty: '.001' }); - await swapPage.waitForQuote(); - await swapPage.swap(); - await swapPage.waitForTransactionToComplete(); - await walletPage.selectActivityList(); - await activityListPage.checkActivityIsConfirmed({ - activity: 'Swap ETH to MATIC', - }); + await swapPage.enterQuote({ to: 'MATIC', qty: '.001' }); + await swapPage.waitForInsufficentBalance(); + await swapPage.gotBack(); await networkController.selectNetwork({ networkName: 'Tenderly - Mainnet' }); await walletPage.selectTokenWallet(); @@ -103,17 +97,14 @@ test('Swap WETH to ETH - Switch to Avalanche and fetch quote - Switch DAI - USDC activity: 'Swap ETH to WETH', }); - await networkController.addCustomNetwork(Tenderly.Avalanche); - await walletPage.selectTokenWallet(); - await walletPage.selectSwapAction(); - await swapPage.enterQuote({ from: 'AVAX', to: 'BNB', qty: '.001' }); - await swapPage.waitForQuote(); - await swapPage.swap(); - await swapPage.waitForTransactionToComplete(); - await walletPage.selectActivityList(); - await activityListPage.checkActivityIsConfirmed({ - activity: 'Swap AVAX to BNB', + await networkController.addPopularNetwork({ + networkName: 'Avalanche Network C-Chain', }); + await walletPage.selectSwapAction(); + await swapPage.enterQuote({ to: 'USDC', qty: '.001' }); + await swapPage.waitForInsufficentBalance(); + + await swapPage.gotBack(); await networkController.selectNetwork({ networkName: 'Tenderly - Mainnet' }); await walletPage.selectTokenWallet(); From 6a431fa398f8d06ff0f84eb9c8a38bbcf8ab0397 Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Tue, 27 Aug 2024 12:55:02 +0200 Subject: [PATCH 06/23] Improved search item --- .../pageObjects/network-controller-page.ts | 8 +++++++- .../e2e/playwright/swap/pageObjects/swap-page.ts | 16 +++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts index 2a0e022a47df..b25c8b1c3568 100644 --- a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts +++ b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts @@ -64,7 +64,7 @@ export class NetworkController { await this.networkTicker.fill(options.symbol); await this.saveBtn.click(); await this.switchToNetworkBtn.click(); - await this.page.$(`text=/${options.name}/`); + await this.waitForNetworkToSwitch(options.name); } async addPopularNetwork(options: { networkName: string }) { @@ -75,11 +75,17 @@ export class NetworkController { await this.approveBtn.click(); await this.switchToNetworkBtn.click(); await this.gotItBtn.click(); + await this.waitForNetworkToSwitch(options.networkName); } async selectNetwork(options: { networkName: string }) { await this.networkDisplay.click(); await this.networkSearch.fill(options.networkName); await this.page.getByText(options.networkName).click(); + await this.waitForNetworkToSwitch(options.networkName); + } + + async waitForNetworkToSwitch(networkName: string) { + await this.page.waitForSelector(`button:has-text("${networkName}")`); } } diff --git a/test/e2e/playwright/swap/pageObjects/swap-page.ts b/test/e2e/playwright/swap/pageObjects/swap-page.ts index d9eeab400322..aada24a0aac9 100644 --- a/test/e2e/playwright/swap/pageObjects/swap-page.ts +++ b/test/e2e/playwright/swap/pageObjects/swap-page.ts @@ -131,15 +131,17 @@ export class SwapPage { } async selectTokenFromList(symbol: string) { - let searchItem; - - await this.page.waitForTimeout(500); - await this.tokenSearch.fill(symbol); + let count; + // wait for the list to populate do { - searchItem = await this.tokenList.first().textContent(); - } while (searchItem !== symbol); + count = await this.tokenList.count(); + await this.page.waitForTimeout(500); + } while (count !== (await this.tokenList.count())); - await this.tokenList.first().click(); + await this.tokenSearch.fill(symbol); + const regex = new RegExp(`^${symbol}$`, 'u'); + const searchItem = await this.tokenList.filter({ hasText: regex }); + await searchItem.click({ timeout: 5000 }); } async waitForSearchListToPopulate(symbol: string): Promise { From c4b466fd3c95a245a5d2abc71246de7f91ec33fc Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Thu, 19 Sep 2024 17:02:43 +0800 Subject: [PATCH 07/23] Added network tests --- .../pageObjects/network-controller-page.ts | 38 ++-- .../shared/pageObjects/signup-page.ts | 38 +++- .../shared/pageObjects/wallet-page.ts | 26 +++ .../playwright/swap/pageObjects/swap-page.ts | 3 +- test/e2e/playwright/swap/specs/swap.spec.ts | 168 ++++++++---------- test/e2e/playwright/swap/tenderly-network.ts | 48 +++++ 6 files changed, 217 insertions(+), 104 deletions(-) create mode 100644 test/e2e/playwright/swap/tenderly-network.ts diff --git a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts index b25c8b1c3568..9f5e4902126d 100644 --- a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts +++ b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts @@ -27,6 +27,8 @@ export class NetworkController { readonly networkTicker: Locator; + readonly dismissBtn: Locator; + constructor(page: Page) { this.page = page; this.networkDisplay = this.page.getByTestId('network-display'); @@ -45,26 +47,35 @@ export class NetworkController { this.networkRpc = this.page.getByTestId('network-form-rpc-url'); this.networkChainId = this.page.getByTestId('network-form-chain-id'); this.networkTicker = this.page.getByTestId('network-form-ticker-input'); + this.dismissBtn = this.page.getByRole('button', { name: 'Dismiss' }); } - async addCustomNetwork(options: { - name: string; - url: string; - chainID: string; - symbol: string; - }) { + async addCustomNetwork( + options: { + name: string; + url: string; + chainID: string; + symbol: string; + }, + switchToNetwork: boolean, + ) { await this.networkDisplay.click(); await this.addNetworkButton.click(); await this.addNetworkManuallyButton.click(); - await this.networkName.waitFor(); await this.networkName.fill(options.name); await this.networkRpc.fill(options.url); await this.networkChainId.fill(options.chainID); await this.networkTicker.fill(options.symbol); await this.saveBtn.click(); - await this.switchToNetworkBtn.click(); - await this.waitForNetworkToSwitch(options.name); + + if (switchToNetwork) { + await this.switchToNetworkBtn.click(); + await this.waitForNetworkToSwitch(options.name); + try { + await this.gotItBtn.click({ timeout: 2000 }); + } catch (e) {} + } else await this.dismissBtn.click(); } async addPopularNetwork(options: { networkName: string }) { @@ -75,14 +86,17 @@ export class NetworkController { await this.approveBtn.click(); await this.switchToNetworkBtn.click(); await this.gotItBtn.click(); - await this.waitForNetworkToSwitch(options.networkName); } async selectNetwork(options: { networkName: string }) { - await this.networkDisplay.click(); + const network = await this.page.$(`text=/${options.networkName}/`); + if (network) return; // if already selected we exit + await this.networkDisplay.getAttribute; + await this.networkDisplay.first().click(); await this.networkSearch.fill(options.networkName); - await this.page.getByText(options.networkName).click(); + await this.page.getByText(options.networkName).first().click(); await this.waitForNetworkToSwitch(options.networkName); + await this.page.waitForTimeout(1000); } async waitForNetworkToSwitch(networkName: string) { diff --git a/test/e2e/playwright/shared/pageObjects/signup-page.ts b/test/e2e/playwright/shared/pageObjects/signup-page.ts index e4165fc1ab89..28909f23ba20 100644 --- a/test/e2e/playwright/shared/pageObjects/signup-page.ts +++ b/test/e2e/playwright/shared/pageObjects/signup-page.ts @@ -11,6 +11,10 @@ export class SignUpPage { readonly importWalletBtn: Locator; + readonly createWalletBtn: Locator; + + readonly metametricsBtn: Locator; + readonly confirmSecretBtn: Locator; readonly agreeBtn: Locator; @@ -21,6 +25,8 @@ export class SignUpPage { readonly passwordConfirmTxt: Locator; + readonly createPasswordBtn: Locator; + readonly agreeCheck: Locator; readonly agreeTandCCheck: Locator; @@ -35,30 +41,42 @@ export class SignUpPage { readonly nextBtn: Locator; - readonly enableButton: Locator; + readonly enableBtn: Locator; + + readonly secureWalletBtn: Locator; + + readonly skipBackupBtn: Locator; + + readonly skipSrpBackupBtn: Locator; constructor(page: Page) { this.page = page; this.getStartedBtn = page.locator('button:has-text("Get started")'); + this.createWalletBtn = page.getByTestId('onboarding-create-wallet'); this.importWalletBtn = page.locator( 'button:has-text("Import an existing wallet")', ); this.confirmSecretBtn = page.locator( 'button:has-text("Confirm Secret Recovery Phrase")', ); + this.metametricsBtn = page.getByTestId('metametrics-no-thanks'); this.agreeBtn = page.locator('button:has-text("I agree")'); + this.createPasswordBtn = page.getByTestId('create-password-wallet'); this.noThanksBtn = page.locator('button:has-text("No thanks")'); this.passwordTxt = page.getByTestId('create-password-new'); this.passwordConfirmTxt = page.getByTestId('create-password-confirm'); this.agreeCheck = page.getByTestId('create-new-vault__terms-checkbox'); this.agreeTandCCheck = page.getByTestId('onboarding-terms-checkbox'); this.agreePasswordTermsCheck = page.getByTestId('create-password-terms'); + this.secureWalletBtn = page.getByTestId('secure-wallet-later'); + this.skipBackupBtn = page.getByTestId('skip-srp-backup-popover-checkbox'); + this.skipSrpBackupBtn = page.getByTestId('skip-srp-backup'); this.importBtn = page.getByTestId('create-password-import'); this.doneBtn = page.getByTestId('pin-extension-done'); this.gotItBtn = page.getByTestId('onboarding-complete-done'); this.nextBtn = page.getByTestId('pin-extension-next'); this.agreeBtn = page.locator('button:has-text("I agree")'); - this.enableButton = page.locator('button:has-text("Enable")'); + this.enableBtn = page.locator('button:has-text("Enable")'); } async importWallet() { @@ -81,4 +99,20 @@ export class SignUpPage { await this.nextBtn.click(); await this.doneBtn.click(); } + + async createWallet() { + await this.agreeTandCCheck.click(); + await this.createWalletBtn.click(); + await this.metametricsBtn.click(); + await this.passwordTxt.fill(ACCOUNT_PASSWORD as string); + await this.passwordConfirmTxt.fill(ACCOUNT_PASSWORD as string); + await this.agreePasswordTermsCheck.click(); + await this.createPasswordBtn.click(); + await this.secureWalletBtn.click(); + await this.skipBackupBtn.click(); + await this.skipSrpBackupBtn.click(); + await this.gotItBtn.click(); + await this.nextBtn.click(); + await this.doneBtn.click(); + } } diff --git a/test/e2e/playwright/shared/pageObjects/wallet-page.ts b/test/e2e/playwright/shared/pageObjects/wallet-page.ts index 47a9b667c96c..4e31441451bf 100644 --- a/test/e2e/playwright/shared/pageObjects/wallet-page.ts +++ b/test/e2e/playwright/shared/pageObjects/wallet-page.ts @@ -13,15 +13,31 @@ export class WalletPage { readonly tokenTab: Locator; + readonly accountMenu: Locator; + + readonly addAccountButton: Locator; + + readonly importAccountButton: Locator; + + readonly importAccountConfirmBtn: Locator; + constructor(page: Page) { this.page = page; this.swapButton = this.page.getByTestId('token-overview-button-swap'); this.importTokensButton = this.page.getByText('Import tokens').first(); + this.accountMenu = this.page.getByTestId('account-menu-icon'); + this.importAccountButton = this.page.getByText('Import account'); this.importButton = this.page.getByText('Import ('); this.tokenTab = this.page.getByTestId('account-overview__asset-tab'); + this.addAccountButton = this.page.getByTestId( + 'multichain-account-menu-popover-action-button', + ); this.activityListTab = this.page.getByTestId( 'account-overview__activity-tab', ); + this.importAccountConfirmBtn = this.page.getByTestId( + 'import-account-confirm-button', + ); } async importTokens() { @@ -31,11 +47,21 @@ export class WalletPage { await this.importButton.click(); } + async importAccount(accountPK: string) { + await this.accountMenu.waitFor({ state: 'visible' }); + await this.accountMenu.click(); + await this.addAccountButton.click(); + await this.importAccountButton.click(); + await this.page.fill('#private-key-box', accountPK); + await this.importAccountConfirmBtn.click(); + } + async selectTokenWallet() { await this.tokenTab.click(); } async selectSwapAction() { + await this.swapButton.waitFor({ state: 'visible' }); await this.swapButton.click(); } diff --git a/test/e2e/playwright/swap/pageObjects/swap-page.ts b/test/e2e/playwright/swap/pageObjects/swap-page.ts index aada24a0aac9..acb091a6f14c 100644 --- a/test/e2e/playwright/swap/pageObjects/swap-page.ts +++ b/test/e2e/playwright/swap/pageObjects/swap-page.ts @@ -60,7 +60,8 @@ export class SwapPage { async enterQuote(options: { from?: string; to: string; qty: string }) { // Enter source token - if (options.from) { + const native = await this.page.$(`text=/${options.from}/`); + if (!native && options.from) { this.swapFromDropDown.click(); await this.selectTokenFromList(options.from); } diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index c359016ad431..f4eb7f196021 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -1,3 +1,4 @@ +import { ethers } from 'ethers'; import { test } from '@playwright/test'; import { ChromeExtensionPage } from '../../shared/pageObjects/extension-page'; @@ -6,117 +7,106 @@ import { NetworkController } from '../../shared/pageObjects/network-controller-p import { SwapPage } from '../pageObjects/swap-page'; import { WalletPage } from '../../shared/pageObjects/wallet-page'; import { ActivityListPage } from '../../shared/pageObjects/activity-list-page'; +import { Tenderly, addFundsToAccount } from '../tenderly-network'; let swapPage: SwapPage; let networkController: NetworkController; let walletPage: WalletPage; let activityListPage: ActivityListPage; -const Tenderly = { - Mainnet: { - name: 'Tenderly - Mainnet', - url: 'https://virtual.mainnet.rpc.tenderly.co/e63e2a2e-a04c-4f32-8379-c1fca19e82b6', - chainID: '1', - symbol: 'ETH', +const testSet = [ + { + quantity: '.5', + source: 'ETH', + type: 'native', + destination: 'DAI', + network: Tenderly.Mainnet.name, }, - Arbitrum: { - name: 'Tenderly - Arbitrum', - url: 'https://virtual.arbitrum.rpc.tenderly.co/70c7bde4-54e7-46a6-9053-9c3c539dcecf', - chainID: '42161', - symbol: 'ETH', + { + quantity: '.5', + source: 'ETH', + type: 'native', + destination: 'USDC', + network: Tenderly.Optimism.name, }, - Avalanche: { - name: 'Tenderly - Avalanche', - url: 'https://virtual.avalanche.rpc.tenderly.co/ff17f1b4-f8ef-456e-be68-07481bc853ec', - chainID: '43114', - symbol: 'AVAX', + { + quantity: '.5', + source: 'ETH', + type: 'native', + destination: 'USDT', + network: Tenderly.Abritrum.name, }, -}; + { + quantity: '50', + source: 'DAI', + type: 'unapproved', + destination: 'ETH', + network: Tenderly.Mainnet.name, + }, + { + source: 'ETH', + quantity: '.5', + type: 'native', + destination: 'WETH', + network: Tenderly.Mainnet.name, + }, + { + quantity: '.3', + source: 'WETH', + type: 'wrapped', + destination: 'ETH', + network: Tenderly.Mainnet.name, + }, + { + quantity: '50', + source: 'DAI', + type: 'ERC20->ERC20', + destination: 'USDC', + network: Tenderly.Mainnet.name, + }, +]; -test.beforeEach( +test.beforeAll( 'Initialize extension, import wallet and add custom networks', async () => { const extension = new ChromeExtensionPage(); const page = await extension.initExtension(); + const wallet = ethers.Wallet.createRandom(); + + await addFundsToAccount(Tenderly.Mainnet.url, wallet.address); + await addFundsToAccount(Tenderly.Optimism.url, wallet.address); + await addFundsToAccount(Tenderly.Abritrum.url, wallet.address); + const signUp = new SignUpPage(page); - await signUp.importWallet(); + await signUp.createWallet(); networkController = new NetworkController(page); swapPage = new SwapPage(page); activityListPage = new ActivityListPage(page); - - await networkController.addCustomNetwork(Tenderly.Mainnet); walletPage = new WalletPage(page); - await page.waitForTimeout(2000); + + await networkController.addCustomNetwork(Tenderly.Optimism, false); + await networkController.addCustomNetwork(Tenderly.Abritrum, false); + await networkController.addCustomNetwork(Tenderly.Mainnet, true); + await walletPage.importAccount(wallet.privateKey); }, ); - -test('Swap ETH to DAI - Switch to Arbitrum and fetch quote - Switch ETH - WETH', async () => { - await walletPage.importTokens(); - - await walletPage.selectSwapAction(); - await swapPage.enterQuote({ from: 'ETH', to: 'DAI', qty: '.001' }); - await swapPage.waitForQuote(); - await swapPage.swap(); - await swapPage.waitForTransactionToComplete(); - await walletPage.selectActivityList(); - await activityListPage.checkActivityIsConfirmed({ - activity: 'Swap ETH to DAI', - }); - - await networkController.addPopularNetwork({ networkName: 'Arbitrum One' }); - await walletPage.selectSwapAction(); - await swapPage.enterQuote({ to: 'MATIC', qty: '.001' }); - await swapPage.waitForInsufficentBalance(); - await swapPage.gotBack(); - - await networkController.selectNetwork({ networkName: 'Tenderly - Mainnet' }); - await walletPage.selectTokenWallet(); - await walletPage.selectSwapAction(); - await swapPage.enterQuote({ from: 'ETH', to: 'WETH', qty: '.001' }); - await swapPage.waitForQuote(); - await swapPage.swap(); - await swapPage.waitForTransactionToComplete(); - await walletPage.selectActivityList(); - await activityListPage.checkActivityIsConfirmed({ - activity: 'Swap ETH to WETH', - }); -}); - -test('Swap WETH to ETH - Switch to Avalanche and fetch quote - Switch DAI - USDC', async () => { - await walletPage.importTokens(); - - await walletPage.selectSwapAction(); - await swapPage.enterQuote({ from: 'ETH', to: 'WETH', qty: '.001' }); - await swapPage.waitForQuote(); - await swapPage.swap(); - await swapPage.waitForTransactionToComplete(); - await walletPage.selectActivityList(); - await activityListPage.checkActivityIsConfirmed({ - activity: 'Swap ETH to WETH', - }); - - await networkController.addPopularNetwork({ - networkName: 'Avalanche Network C-Chain', - }); - await walletPage.selectSwapAction(); - await swapPage.enterQuote({ to: 'USDC', qty: '.001' }); - await swapPage.waitForInsufficentBalance(); - - await swapPage.gotBack(); - - await networkController.selectNetwork({ networkName: 'Tenderly - Mainnet' }); - await walletPage.selectTokenWallet(); - await walletPage.selectSwapAction(); - await swapPage.enterQuote({ from: 'DAI', to: 'USDC', qty: '.5' }); - await swapPage.waitForQuote(); - await swapPage.switchTokenOrder(); - await swapPage.waitForQuote(); - await swapPage.swap(); - await swapPage.waitForTransactionToComplete(); - await walletPage.selectActivityList(); - await activityListPage.checkActivityIsConfirmed({ - activity: 'Swap USDC to DAI', +testSet.forEach((options) => { + test(`should swap ${options.type} token ${options.source} to ${options.destination} on ${options.network}'`, async () => { + await networkController.selectNetwork({ networkName: options.network }); + await walletPage.selectSwapAction(); + await swapPage.enterQuote({ + from: options.source, + to: options.destination, + qty: options.quantity, + }); + await swapPage.waitForQuote(); + await swapPage.swap(); + await swapPage.waitForTransactionToComplete(); + await walletPage.selectActivityList(); + await activityListPage.checkActivityIsConfirmed({ + activity: `Swap ${options.source} to ${options.destination}`, + }); }); }); diff --git a/test/e2e/playwright/swap/tenderly-network.ts b/test/e2e/playwright/swap/tenderly-network.ts new file mode 100644 index 000000000000..f07b34c35410 --- /dev/null +++ b/test/e2e/playwright/swap/tenderly-network.ts @@ -0,0 +1,48 @@ +import axios from 'axios'; + +export const Tenderly = { + Mainnet: { + name: 'Tenderly - Mainnet', + url: 'https://virtual.mainnet.rpc.tenderly.co/6c80ca53-d96a-49e8-967d-e184bb51d325', + chainID: '1', + symbol: 'ETH', + }, + Optimism: { + name: 'Tenderly - Optimism', + url: 'https://virtual.optimism.rpc.tenderly.co/8a89a4ef-a0b6-4c79-86bb-6a7ed56be4bc', + chainID: '10', + symbol: 'ETH', + }, + Abritrum: { + name: 'Tenderly - Arbitrum', + url: 'https://virtual.arbitrum.rpc.tenderly.co/903b3e51-8d9b-4ced-b594-d1ee6b99681c', + chainID: '42161', + symbol: 'ETH', + }, +}; + +export async function addFundsToAccount( + rpcURL: string, + account: string, + amount: string = '0xDE0B6B3A7640000', //1 ETH +) { + const data = { + jsonrpc: '2.0', + method: 'tenderly_setBalance', + params: [[account], amount], + id: '1234', + }; + const response = await axios.post(rpcURL, data, { + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (response.data.error) { + // eslint-disable-next-line no-console + console.log( + `ERROR: Failed to add funds to Tenderly VirtualTestNet\n${response.data.error}`, + ); + return null; + } +} From f5e2579d388807e9cbeb390013a6e6026237d8f3 Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Fri, 20 Sep 2024 14:04:12 +0800 Subject: [PATCH 08/23] Lint fixes --- .../pageObjects/network-controller-page.ts | 24 +++++++++---------- test/e2e/playwright/swap/tenderly-network.ts | 3 +-- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts index 9f5e4902126d..aa61de2f2c3a 100644 --- a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts +++ b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts @@ -72,10 +72,9 @@ export class NetworkController { if (switchToNetwork) { await this.switchToNetworkBtn.click(); await this.waitForNetworkToSwitch(options.name); - try { - await this.gotItBtn.click({ timeout: 2000 }); - } catch (e) {} - } else await this.dismissBtn.click(); + } else { + await this.dismissBtn.click({ timeout: 2000 }); + } } async addPopularNetwork(options: { networkName: string }) { @@ -89,14 +88,15 @@ export class NetworkController { } async selectNetwork(options: { networkName: string }) { - const network = await this.page.$(`text=/${options.networkName}/`); - if (network) return; // if already selected we exit - await this.networkDisplay.getAttribute; - await this.networkDisplay.first().click(); - await this.networkSearch.fill(options.networkName); - await this.page.getByText(options.networkName).first().click(); - await this.waitForNetworkToSwitch(options.networkName); - await this.page.waitForTimeout(1000); + const currentNetwork = await this.page.$(`text=/${options.networkName}/`); + if (!currentNetwork) { + // if already selected we exit + await this.networkDisplay.getAttribute; + await this.networkDisplay.first().click(); + await this.networkSearch.fill(options.networkName); + await this.page.getByText(options.networkName).first().click(); + await this.waitForNetworkToSwitch(options.networkName); + } } async waitForNetworkToSwitch(networkName: string) { diff --git a/test/e2e/playwright/swap/tenderly-network.ts b/test/e2e/playwright/swap/tenderly-network.ts index f07b34c35410..3f1813691158 100644 --- a/test/e2e/playwright/swap/tenderly-network.ts +++ b/test/e2e/playwright/swap/tenderly-network.ts @@ -24,7 +24,7 @@ export const Tenderly = { export async function addFundsToAccount( rpcURL: string, account: string, - amount: string = '0xDE0B6B3A7640000', //1 ETH + amount: string = '0xDE0B6B3A7640000', // 1 ETH by default ) { const data = { jsonrpc: '2.0', @@ -43,6 +43,5 @@ export async function addFundsToAccount( console.log( `ERROR: Failed to add funds to Tenderly VirtualTestNet\n${response.data.error}`, ); - return null; } } From c516b78571c9d1e736134f494282a37d68272283 Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Fri, 20 Sep 2024 14:40:51 +0800 Subject: [PATCH 09/23] Added testnets with syncstate on --- test/e2e/playwright/swap/tenderly-network.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/playwright/swap/tenderly-network.ts b/test/e2e/playwright/swap/tenderly-network.ts index 3f1813691158..7984aa371485 100644 --- a/test/e2e/playwright/swap/tenderly-network.ts +++ b/test/e2e/playwright/swap/tenderly-network.ts @@ -9,13 +9,13 @@ export const Tenderly = { }, Optimism: { name: 'Tenderly - Optimism', - url: 'https://virtual.optimism.rpc.tenderly.co/8a89a4ef-a0b6-4c79-86bb-6a7ed56be4bc', + url: 'https://virtual.optimism.rpc.tenderly.co/3170a58e-fa67-4ccc-9697-b13aff0f5c1a', chainID: '10', symbol: 'ETH', }, Abritrum: { name: 'Tenderly - Arbitrum', - url: 'https://virtual.arbitrum.rpc.tenderly.co/903b3e51-8d9b-4ced-b594-d1ee6b99681c', + url: 'https://virtual.arbitrum.rpc.tenderly.co/7d364996-41a7-4da6-a552-a19ab1ef9173', chainID: '42161', symbol: 'ETH', }, From 9b3216c8116daaeccd28f61ce4a11a1efa635aab Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Fri, 20 Sep 2024 16:29:51 +0800 Subject: [PATCH 10/23] Changed Mainnet rpc --- test/e2e/playwright/swap/tenderly-network.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/playwright/swap/tenderly-network.ts b/test/e2e/playwright/swap/tenderly-network.ts index 7984aa371485..cc8c33bc8357 100644 --- a/test/e2e/playwright/swap/tenderly-network.ts +++ b/test/e2e/playwright/swap/tenderly-network.ts @@ -3,7 +3,7 @@ import axios from 'axios'; export const Tenderly = { Mainnet: { name: 'Tenderly - Mainnet', - url: 'https://virtual.mainnet.rpc.tenderly.co/6c80ca53-d96a-49e8-967d-e184bb51d325', + url: 'https://virtual.mainnet.rpc.tenderly.co/03bb8912-7505-4856-839f-52819a26d0cd', chainID: '1', symbol: 'ETH', }, From a530c7d2afd4bf1deebdcb620b0bb3cd5eb288ca Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Mon, 23 Sep 2024 20:28:01 +0800 Subject: [PATCH 11/23] Changed code to adapt to new network UI --- .../pageObjects/network-controller-page.ts | 110 +++++++++++------- .../playwright/swap/pageObjects/swap-page.ts | 9 +- test/e2e/playwright/swap/specs/swap.spec.ts | 48 ++++---- test/e2e/playwright/swap/tenderly-network.ts | 9 +- 4 files changed, 104 insertions(+), 72 deletions(-) diff --git a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts index aa61de2f2c3a..e8ac4da96c97 100644 --- a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts +++ b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts @@ -1,4 +1,5 @@ import { type Locator, type Page } from '@playwright/test'; +import { Tenderly } from '../../swap/tenderly-network'; export class NetworkController { readonly page: Page; @@ -7,18 +8,12 @@ export class NetworkController { readonly addNetworkButton: Locator; - readonly addNetworkManuallyButton: Locator; - readonly approveBtn: Locator; readonly saveBtn: Locator; - readonly switchToNetworkBtn: Locator; - readonly gotItBtn: Locator; - readonly networkSearch: Locator; - readonly networkName: Locator; readonly networkRpc: Locator; @@ -29,52 +24,69 @@ export class NetworkController { readonly dismissBtn: Locator; + readonly networkList: Locator; + + readonly networkListEdit: Locator; + + readonly rpcName: Locator; + + readonly addRpcDropDown: Locator; + + readonly addRpcURLBtn: Locator; + + readonly addURLBtn: Locator; + constructor(page: Page) { this.page = page; this.networkDisplay = this.page.getByTestId('network-display'); - this.addNetworkButton = this.page.getByText('Add network'); - this.addNetworkManuallyButton = this.page.getByTestId( - 'add-network-manually', + this.networkList = this.page.getByTestId( + 'network-list-item-options-button-0x1', + ); + this.networkListEdit = this.page.getByTestId( + 'network-list-item-options-edit', ); + this.addNetworkButton = this.page.getByText('Add a custom network'); + this.addRpcDropDown = this.page.getByTestId('test-add-rpc-drop-down'); + this.addRpcURLBtn = this.page.getByRole('button', { name: 'Add RPC URL' }); + this.addURLBtn = this.page.getByRole('button', { name: 'Add URL' }); this.saveBtn = this.page.getByRole('button', { name: 'Save' }); this.approveBtn = this.page.getByTestId('confirmation-submit-button'); - this.switchToNetworkBtn = this.page.locator('button', { - hasText: 'Switch to', - }); this.gotItBtn = this.page.getByRole('button', { name: 'Got it' }); - this.networkSearch = this.page.locator('input[type="search"]'); this.networkName = this.page.getByTestId('network-form-network-name'); - this.networkRpc = this.page.getByTestId('network-form-rpc-url'); + this.rpcName = this.page.getByTestId('rpc-name-input-test'); + this.networkRpc = this.page.getByTestId('rpc-url-input-test'); this.networkChainId = this.page.getByTestId('network-form-chain-id'); this.networkTicker = this.page.getByTestId('network-form-ticker-input'); this.dismissBtn = this.page.getByRole('button', { name: 'Dismiss' }); } - async addCustomNetwork( - options: { - name: string; - url: string; - chainID: string; - symbol: string; - }, - switchToNetwork: boolean, - ) { + async addCustomNetwork(options: { + name: string; + rpcName: string; + url: string; + chainID: string; + symbol: string; + }) { + let rpcName = options.name; await this.networkDisplay.click(); - await this.addNetworkButton.click(); - await this.addNetworkManuallyButton.click(); - - await this.networkName.fill(options.name); + if (options.name === Tenderly.Mainnet.name) { + rpcName = options.rpcName; + await this.networkList.click(); + await this.networkListEdit.click(); + } else { + await this.addNetworkButton.click(); + await this.networkName.fill(rpcName); + } + await this.addRpcDropDown.click(); + await this.addRpcURLBtn.click(); await this.networkRpc.fill(options.url); - await this.networkChainId.fill(options.chainID); + await this.rpcName.fill(rpcName); + await this.addURLBtn.click(); + if (options.name !== Tenderly.Mainnet.name) { + await this.networkChainId.fill(options.chainID); + } await this.networkTicker.fill(options.symbol); await this.saveBtn.click(); - - if (switchToNetwork) { - await this.switchToNetworkBtn.click(); - await this.waitForNetworkToSwitch(options.name); - } else { - await this.dismissBtn.click({ timeout: 2000 }); - } } async addPopularNetwork(options: { networkName: string }) { @@ -83,23 +95,31 @@ export class NetworkController { const addBtn = this.page.getByTestId(`add-network-${options.networkName}`); await addBtn.click(); await this.approveBtn.click(); - await this.switchToNetworkBtn.click(); await this.gotItBtn.click(); } - async selectNetwork(options: { networkName: string }) { - const currentNetwork = await this.page.$(`text=/${options.networkName}/`); - if (!currentNetwork) { - // if already selected we exit - await this.networkDisplay.getAttribute; - await this.networkDisplay.first().click(); - await this.networkSearch.fill(options.networkName); - await this.page.getByText(options.networkName).first().click(); - await this.waitForNetworkToSwitch(options.networkName); + async selectNetwork(options: { + name: string; + rpcName: string; + url: string; + chainID: string; + symbol: string; + }) { + const currentNetwork = await this.networkDisplay.textContent(); + if (currentNetwork !== options.name) { + await this.networkDisplay.click(); + if (options.name === Tenderly.Mainnet.name) { + await this.page.getByText(options.rpcName).click(); + await this.page.getByText(options.rpcName).click(); + } else { + await this.page.getByTestId(options.name).click(); + } + await this.waitForNetworkToSwitch(options.name); } } async waitForNetworkToSwitch(networkName: string) { + await this.page.waitForTimeout(3000) await this.page.waitForSelector(`button:has-text("${networkName}")`); } } diff --git a/test/e2e/playwright/swap/pageObjects/swap-page.ts b/test/e2e/playwright/swap/pageObjects/swap-page.ts index acb091a6f14c..dbb6bee2c400 100644 --- a/test/e2e/playwright/swap/pageObjects/swap-page.ts +++ b/test/e2e/playwright/swap/pageObjects/swap-page.ts @@ -87,9 +87,7 @@ export class SwapPage { // No quotes available const noQuotes = await this.page.$('text=/No quotes available/'); if (noQuotes) { - // re-entering the qty will trigger new quote - await this.tokenQty.fill(''); - await this.tokenQty.fill(this.swapQty); + break; } if (await this.page.$('text=/New quotes in/')) { @@ -99,6 +97,7 @@ export class SwapPage { await this.page.waitForTimeout(500); } while (!quoteFound); + return quoteFound; } async swap() { @@ -122,7 +121,9 @@ export class SwapPage { } async waitForTransactionToComplete() { - await this.page.waitForSelector('text=/Transaction complete/'); + await this.page.waitForSelector('text=/Transaction complete/', { + timeout: 90000, + }); await this.closeButton.click(); // Close button } diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index f4eb7f196021..2d10edeeb542 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -20,49 +20,50 @@ const testSet = [ source: 'ETH', type: 'native', destination: 'DAI', - network: Tenderly.Mainnet.name, + network: Tenderly.Mainnet, }, { quantity: '.5', source: 'ETH', type: 'native', destination: 'USDC', - network: Tenderly.Optimism.name, + network: Tenderly.Abritrum, }, { - quantity: '.5', + quantity: '.3', source: 'ETH', type: 'native', destination: 'USDT', - network: Tenderly.Abritrum.name, + network: Tenderly.Abritrum, }, { quantity: '50', source: 'DAI', type: 'unapproved', destination: 'ETH', - network: Tenderly.Mainnet.name, + network: Tenderly.Mainnet, }, + { source: 'ETH', quantity: '.5', type: 'native', destination: 'WETH', - network: Tenderly.Mainnet.name, + network: Tenderly.Mainnet, }, { quantity: '.3', source: 'WETH', type: 'wrapped', destination: 'ETH', - network: Tenderly.Mainnet.name, + network: Tenderly.Mainnet, }, { quantity: '50', source: 'DAI', type: 'ERC20->ERC20', destination: 'USDC', - network: Tenderly.Mainnet.name, + network: Tenderly.Mainnet, }, ]; @@ -71,6 +72,7 @@ test.beforeAll( async () => { const extension = new ChromeExtensionPage(); const page = await extension.initExtension(); + page.setDefaultTimeout(15000); const wallet = ethers.Wallet.createRandom(); @@ -86,27 +88,33 @@ test.beforeAll( activityListPage = new ActivityListPage(page); walletPage = new WalletPage(page); - await networkController.addCustomNetwork(Tenderly.Optimism, false); - await networkController.addCustomNetwork(Tenderly.Abritrum, false); - await networkController.addCustomNetwork(Tenderly.Mainnet, true); + // await networkController.addCustomNetwork(Tenderly.Optimism, false); + // await networkController.addCustomNetwork(Tenderly.Abritrum, false); + // await networkController.addCustomNetwork(Tenderly.Mainnet, true); + await networkController.addCustomNetwork(Tenderly.Mainnet); + await networkController.addCustomNetwork(Tenderly.Abritrum); await walletPage.importAccount(wallet.privateKey); }, ); testSet.forEach((options) => { - test(`should swap ${options.type} token ${options.source} to ${options.destination} on ${options.network}'`, async () => { - await networkController.selectNetwork({ networkName: options.network }); + test(`should swap ${options.type} token ${options.source} to ${options.destination} on ${options.network.name}'`, async () => { + await networkController.selectNetwork(options.network); await walletPage.selectSwapAction(); await swapPage.enterQuote({ from: options.source, to: options.destination, qty: options.quantity, }); - await swapPage.waitForQuote(); - await swapPage.swap(); - await swapPage.waitForTransactionToComplete(); - await walletPage.selectActivityList(); - await activityListPage.checkActivityIsConfirmed({ - activity: `Swap ${options.source} to ${options.destination}`, - }); + const quoteFound = await swapPage.waitForQuote(); + if (quoteFound) { + await swapPage.swap(); + await swapPage.waitForTransactionToComplete(); + await walletPage.selectActivityList(); + await activityListPage.checkActivityIsConfirmed({ + activity: `Swap ${options.source} to ${options.destination}`, + }); + } else { + await swapPage.gotBack(); + } }); }); diff --git a/test/e2e/playwright/swap/tenderly-network.ts b/test/e2e/playwright/swap/tenderly-network.ts index cc8c33bc8357..f3bdd3573da5 100644 --- a/test/e2e/playwright/swap/tenderly-network.ts +++ b/test/e2e/playwright/swap/tenderly-network.ts @@ -2,19 +2,22 @@ import axios from 'axios'; export const Tenderly = { Mainnet: { - name: 'Tenderly - Mainnet', + name: 'Ethereum Mainnet', + rpcName: 'Tenderly - Mainnet', url: 'https://virtual.mainnet.rpc.tenderly.co/03bb8912-7505-4856-839f-52819a26d0cd', chainID: '1', symbol: 'ETH', }, Optimism: { - name: 'Tenderly - Optimism', + name: 'OP Mainnet', + rpcName: '', url: 'https://virtual.optimism.rpc.tenderly.co/3170a58e-fa67-4ccc-9697-b13aff0f5c1a', chainID: '10', symbol: 'ETH', }, Abritrum: { - name: 'Tenderly - Arbitrum', + name: 'Arbitrum One', + rpcName: '', url: 'https://virtual.arbitrum.rpc.tenderly.co/7d364996-41a7-4da6-a552-a19ab1ef9173', chainID: '42161', symbol: 'ETH', From 6e390822c9a211db5f1b0eda08b7757b26ed8dd5 Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Tue, 24 Sep 2024 11:48:33 +0200 Subject: [PATCH 12/23] Added skip test if no quote found --- .../shared/pageObjects/network-controller-page.ts | 2 +- test/e2e/playwright/swap/specs/swap.spec.ts | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts index e8ac4da96c97..32733bdc33cb 100644 --- a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts +++ b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts @@ -119,7 +119,7 @@ export class NetworkController { } async waitForNetworkToSwitch(networkName: string) { - await this.page.waitForTimeout(3000) + await this.page.waitForTimeout(3000); await this.page.waitForSelector(`button:has-text("${networkName}")`); } } diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index 2d10edeeb542..f70d40f9c659 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -27,7 +27,7 @@ const testSet = [ source: 'ETH', type: 'native', destination: 'USDC', - network: Tenderly.Abritrum, + network: Tenderly.Optimism, }, { quantity: '.3', @@ -88,11 +88,10 @@ test.beforeAll( activityListPage = new ActivityListPage(page); walletPage = new WalletPage(page); - // await networkController.addCustomNetwork(Tenderly.Optimism, false); - // await networkController.addCustomNetwork(Tenderly.Abritrum, false); - // await networkController.addCustomNetwork(Tenderly.Mainnet, true); - await networkController.addCustomNetwork(Tenderly.Mainnet); + await networkController.addCustomNetwork(Tenderly.Optimism); await networkController.addCustomNetwork(Tenderly.Abritrum); + await networkController.addCustomNetwork(Tenderly.Mainnet); + await walletPage.importAccount(wallet.privateKey); }, ); @@ -115,6 +114,11 @@ testSet.forEach((options) => { }); } else { await swapPage.gotBack(); + // eslint-disable-next-line no-console + console.error( + `\t\tERROR: No quotes found on ${options.network.name} network' Skipping the test`, + ); + test.skip(); } }); }); From 9c963ad1f4359a0aa550eb8f1aa6529aacf0ebdb Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Tue, 24 Sep 2024 17:28:09 +0200 Subject: [PATCH 13/23] Removed Optimism --- .../shared/pageObjects/network-controller-page.ts | 3 ++- test/e2e/playwright/swap/specs/swap.spec.ts | 9 --------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts index 32733bdc33cb..dba8020be9c8 100644 --- a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts +++ b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts @@ -86,7 +86,8 @@ export class NetworkController { await this.networkChainId.fill(options.chainID); } await this.networkTicker.fill(options.symbol); - await this.saveBtn.click(); + await this.saveBtn.waitFor({ state: 'visible' }); + await this.saveBtn.click({ timeout: 60000 }); } async addPopularNetwork(options: { networkName: string }) { diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index f70d40f9c659..ffbf4bdd2ca6 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -22,13 +22,6 @@ const testSet = [ destination: 'DAI', network: Tenderly.Mainnet, }, - { - quantity: '.5', - source: 'ETH', - type: 'native', - destination: 'USDC', - network: Tenderly.Optimism, - }, { quantity: '.3', source: 'ETH', @@ -77,7 +70,6 @@ test.beforeAll( const wallet = ethers.Wallet.createRandom(); await addFundsToAccount(Tenderly.Mainnet.url, wallet.address); - await addFundsToAccount(Tenderly.Optimism.url, wallet.address); await addFundsToAccount(Tenderly.Abritrum.url, wallet.address); const signUp = new SignUpPage(page); @@ -88,7 +80,6 @@ test.beforeAll( activityListPage = new ActivityListPage(page); walletPage = new WalletPage(page); - await networkController.addCustomNetwork(Tenderly.Optimism); await networkController.addCustomNetwork(Tenderly.Abritrum); await networkController.addCustomNetwork(Tenderly.Mainnet); From d58e3a81b5be56e20a36fa70bda88d4ae39b8b6e Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Tue, 24 Sep 2024 18:35:34 +0200 Subject: [PATCH 14/23] Remove Arbitrum tests --- test/e2e/playwright/swap/specs/swap.spec.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index ffbf4bdd2ca6..9936cc56af4a 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -22,13 +22,6 @@ const testSet = [ destination: 'DAI', network: Tenderly.Mainnet, }, - { - quantity: '.3', - source: 'ETH', - type: 'native', - destination: 'USDT', - network: Tenderly.Abritrum, - }, { quantity: '50', source: 'DAI', @@ -68,9 +61,7 @@ test.beforeAll( page.setDefaultTimeout(15000); const wallet = ethers.Wallet.createRandom(); - await addFundsToAccount(Tenderly.Mainnet.url, wallet.address); - await addFundsToAccount(Tenderly.Abritrum.url, wallet.address); const signUp = new SignUpPage(page); await signUp.createWallet(); @@ -80,9 +71,7 @@ test.beforeAll( activityListPage = new ActivityListPage(page); walletPage = new WalletPage(page); - await networkController.addCustomNetwork(Tenderly.Abritrum); await networkController.addCustomNetwork(Tenderly.Mainnet); - await walletPage.importAccount(wallet.privateKey); }, ); From ca1d88fc2b24da4775e31c5d33360d8a6ba9f18d Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Tue, 24 Sep 2024 19:23:10 +0200 Subject: [PATCH 15/23] Readed network tests --- test/e2e/playwright/swap/specs/swap.spec.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index 9936cc56af4a..493770992406 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -22,6 +22,20 @@ const testSet = [ destination: 'DAI', network: Tenderly.Mainnet, }, + { + quantity: '.5', + source: 'ETH', + type: 'native', + destination: 'USDC', + network: Tenderly.Abritrum, + }, + { + quantity: '.5', + source: 'ETH', + type: 'native', + destination: 'OP', + network: Tenderly.Optimism, + }, { quantity: '50', source: 'DAI', @@ -62,6 +76,8 @@ test.beforeAll( const wallet = ethers.Wallet.createRandom(); await addFundsToAccount(Tenderly.Mainnet.url, wallet.address); + await addFundsToAccount(Tenderly.Abritrum.url, wallet.address); + await addFundsToAccount(Tenderly.Optimism.url, wallet.address); const signUp = new SignUpPage(page); await signUp.createWallet(); @@ -72,6 +88,8 @@ test.beforeAll( walletPage = new WalletPage(page); await networkController.addCustomNetwork(Tenderly.Mainnet); + await networkController.addCustomNetwork(Tenderly.Abritrum); + await networkController.addCustomNetwork(Tenderly.Optimism); await walletPage.importAccount(wallet.privateKey); }, ); From 724098f3e9dff1f081253c0f54235f92b39c2e88 Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Wed, 25 Sep 2024 11:01:57 +0200 Subject: [PATCH 16/23] Improved stability --- .../pageObjects/network-controller-page.ts | 11 ++++- .../playwright/swap/pageObjects/swap-page.ts | 45 ++++++++++++++++--- test/e2e/playwright/swap/specs/swap.spec.ts | 35 +++++++++------ 3 files changed, 68 insertions(+), 23 deletions(-) diff --git a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts index dba8020be9c8..76202abea21f 100644 --- a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts +++ b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts @@ -116,11 +116,18 @@ export class NetworkController { await this.page.getByTestId(options.name).click(); } await this.waitForNetworkToSwitch(options.name); + await this.page.waitForTimeout(5000); } } async waitForNetworkToSwitch(networkName: string) { - await this.page.waitForTimeout(3000); - await this.page.waitForSelector(`button:has-text("${networkName}")`); + let currentNetwork; + do { + currentNetwork = await this.networkDisplay.textContent(); + if (currentNetwork === networkName) { + break; + } + await this.page.waitForTimeout(1000); + } while (currentNetwork); } } diff --git a/test/e2e/playwright/swap/pageObjects/swap-page.ts b/test/e2e/playwright/swap/pageObjects/swap-page.ts index dbb6bee2c400..ba89325698ab 100644 --- a/test/e2e/playwright/swap/pageObjects/swap-page.ts +++ b/test/e2e/playwright/swap/pageObjects/swap-page.ts @@ -29,6 +29,8 @@ export class SwapPage { readonly closeButton: Locator; + readonly viewInActivityBtn: Locator; + constructor(page: Page) { this.page = page; this.swapQty = ''; @@ -56,6 +58,9 @@ export class SwapPage { this.swapTokenButton = this.page.locator('button', { hasText: 'Swap' }); this.closeButton = this.page.getByText('Close'); this.backButton = this.page.locator('[title="Cancel"]'); + this.viewInActivityBtn = this.page.getByTestId( + 'page-container-footer-next', + ); } async enterQuote(options: { from?: string; to: string; qty: string }) { @@ -66,6 +71,18 @@ export class SwapPage { await this.selectTokenFromList(options.from); } + const balanceString = await this.page + .locator('[class*="balance"]') + .first() + .textContent(); + if (balanceString) { + if (parseFloat(balanceString.split(' ')[1]) <= parseFloat(options.qty)) { + await this.gotBack(); + // not enough balance so cancel out + return false; + } + } + // Enter Swap Quantity await this.tokenQty.fill(options.qty); this.swapQty = options.qty; @@ -73,6 +90,7 @@ export class SwapPage { // Enter destination token await this.swapToDropDown.click(); await this.selectTokenFromList(options.to); + return true; } async waitForQuote() { @@ -87,6 +105,7 @@ export class SwapPage { // No quotes available const noQuotes = await this.page.$('text=/No quotes available/'); if (noQuotes) { + await this.gotBack(); break; } @@ -94,9 +113,9 @@ export class SwapPage { quoteFound = true; break; } - - await this.page.waitForTimeout(500); + await this.page.waitForTimeout(1000); } while (!quoteFound); + return quoteFound; } @@ -120,11 +139,23 @@ export class SwapPage { await this.page.waitForSelector(`text=/New quotes in 0:${second}/`); } - async waitForTransactionToComplete() { - await this.page.waitForSelector('text=/Transaction complete/', { - timeout: 90000, - }); - await this.closeButton.click(); // Close button + async waitForTransactionToComplete(options: { seconds: number }) { + let countSecond = options.seconds; + let trasnsactionCompleted; + do { + trasnsactionCompleted = await this.page.$('text=/Transaction complete/'); + if (trasnsactionCompleted) { + await this.closeButton.click(); + break; + } + + await this.page.waitForTimeout(1000); + countSecond -= 1; + } while (countSecond); + + if (!trasnsactionCompleted && !countSecond) { + await this.viewInActivityBtn.click(); + } } async waitForInsufficentBalance() { diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index 493770992406..b10e10e68d4c 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -29,6 +29,7 @@ const testSet = [ destination: 'USDC', network: Tenderly.Abritrum, }, + /* { quantity: '.5', source: 'ETH', @@ -36,6 +37,7 @@ const testSet = [ destination: 'OP', network: Tenderly.Optimism, }, + */ { quantity: '50', source: 'DAI', @@ -95,27 +97,32 @@ test.beforeAll( ); testSet.forEach((options) => { test(`should swap ${options.type} token ${options.source} to ${options.destination} on ${options.network.name}'`, async () => { + await walletPage.selectTokenWallet(); await networkController.selectNetwork(options.network); await walletPage.selectSwapAction(); - await swapPage.enterQuote({ + const quoteEntered = await swapPage.enterQuote({ from: options.source, to: options.destination, qty: options.quantity, }); - const quoteFound = await swapPage.waitForQuote(); - if (quoteFound) { - await swapPage.swap(); - await swapPage.waitForTransactionToComplete(); - await walletPage.selectActivityList(); - await activityListPage.checkActivityIsConfirmed({ - activity: `Swap ${options.source} to ${options.destination}`, - }); + + if (quoteEntered) { + const quoteFound = await swapPage.waitForQuote(); + if (quoteFound) { + await swapPage.swap(); + await swapPage.waitForTransactionToComplete({ seconds: 60 }); + await walletPage.selectActivityList(); + await activityListPage.checkActivityIsConfirmed({ + activity: `Swap ${options.source} to ${options.destination}`, + }); + } else { + // eslint-disable-next-line no-console + console.error( + `\t\tERROR: No quotes found on ${options.network.name} network' Skipping the test`, + ); + test.skip(); + } } else { - await swapPage.gotBack(); - // eslint-disable-next-line no-console - console.error( - `\t\tERROR: No quotes found on ${options.network.name} network' Skipping the test`, - ); test.skip(); } }); From 0da57efa0054376d718d7c483d17a3d4da6ce767 Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Wed, 25 Sep 2024 18:34:23 +0200 Subject: [PATCH 17/23] Added loglevel messages --- .../playwright/swap/pageObjects/swap-page.ts | 2 ++ test/e2e/playwright/swap/specs/swap.spec.ts | 26 +++++++++++-------- test/e2e/playwright/swap/tenderly-network.ts | 6 ++--- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/test/e2e/playwright/swap/pageObjects/swap-page.ts b/test/e2e/playwright/swap/pageObjects/swap-page.ts index ba89325698ab..1c021cc65465 100644 --- a/test/e2e/playwright/swap/pageObjects/swap-page.ts +++ b/test/e2e/playwright/swap/pageObjects/swap-page.ts @@ -155,7 +155,9 @@ export class SwapPage { if (!trasnsactionCompleted && !countSecond) { await this.viewInActivityBtn.click(); + return false; } + return true; } async waitForInsufficentBalance() { diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index b10e10e68d4c..dcfe1c5b8d69 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -1,5 +1,6 @@ import { ethers } from 'ethers'; import { test } from '@playwright/test'; +import log from 'loglevel'; import { ChromeExtensionPage } from '../../shared/pageObjects/extension-page'; import { SignUpPage } from '../../shared/pageObjects/signup-page'; @@ -29,7 +30,6 @@ const testSet = [ destination: 'USDC', network: Tenderly.Abritrum, }, - /* { quantity: '.5', source: 'ETH', @@ -37,7 +37,7 @@ const testSet = [ destination: 'OP', network: Tenderly.Optimism, }, - */ + { quantity: '50', source: 'DAI', @@ -110,19 +110,23 @@ testSet.forEach((options) => { const quoteFound = await swapPage.waitForQuote(); if (quoteFound) { await swapPage.swap(); - await swapPage.waitForTransactionToComplete({ seconds: 60 }); - await walletPage.selectActivityList(); - await activityListPage.checkActivityIsConfirmed({ - activity: `Swap ${options.source} to ${options.destination}`, - }); + const transactionCompleted = + await swapPage.waitForTransactionToComplete({ seconds: 60 }); + if (transactionCompleted) { + await walletPage.selectActivityList(); + await activityListPage.checkActivityIsConfirmed({ + activity: `Swap ${options.source} to ${options.destination}`, + }); + } else { + log.error(`\tERROR: Transaction did not complete. Skipping test`); + test.skip(); + } } else { - // eslint-disable-next-line no-console - console.error( - `\t\tERROR: No quotes found on ${options.network.name} network' Skipping the test`, - ); + log.error(`\tERROR: No quotes found on. Skipping test`); test.skip(); } } else { + log.error(`\tERROR: Error while entering the quote. Skipping test`); test.skip(); } }); diff --git a/test/e2e/playwright/swap/tenderly-network.ts b/test/e2e/playwright/swap/tenderly-network.ts index f3bdd3573da5..24ec2154d84c 100644 --- a/test/e2e/playwright/swap/tenderly-network.ts +++ b/test/e2e/playwright/swap/tenderly-network.ts @@ -1,4 +1,5 @@ import axios from 'axios'; +import log from 'loglevel'; export const Tenderly = { Mainnet: { @@ -42,9 +43,8 @@ export async function addFundsToAccount( }); if (response.data.error) { - // eslint-disable-next-line no-console - console.log( - `ERROR: Failed to add funds to Tenderly VirtualTestNet\n${response.data.error}`, + log.error( + `\tERROR: RROR: Failed to add funds to Tenderly VirtualTestNet\n${response.data.error}`, ); } } From bed04fdd579603038c96851991fb76e5adba1254 Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Tue, 22 Oct 2024 20:57:55 +0200 Subject: [PATCH 18/23] Replace Arbitrum test with Polygon --- test/e2e/playwright/swap/specs/swap.spec.ts | 29 +++++++++++++++----- test/e2e/playwright/swap/tenderly-network.ts | 8 +++--- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index dcfe1c5b8d69..183c4f1b8687 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -1,5 +1,5 @@ import { ethers } from 'ethers'; -import { test } from '@playwright/test'; +import { Page, test } from '@playwright/test'; import log from 'loglevel'; import { ChromeExtensionPage } from '../../shared/pageObjects/extension-page'; @@ -24,11 +24,11 @@ const testSet = [ network: Tenderly.Mainnet, }, { - quantity: '.5', - source: 'ETH', + quantity: '50', + source: 'POL', type: 'native', destination: 'USDC', - network: Tenderly.Abritrum, + network: Tenderly.Polygon, }, { quantity: '.5', @@ -37,7 +37,13 @@ const testSet = [ destination: 'OP', network: Tenderly.Optimism, }, - + { + quantity: '100', + source: 'OP', + type: 'unapproved', + destination: 'USDC', + network: Tenderly.Optimism, + }, { quantity: '50', source: 'DAI', @@ -69,16 +75,22 @@ const testSet = [ }, ]; +let a: Page; test.beforeAll( 'Initialize extension, import wallet and add custom networks', async () => { const extension = new ChromeExtensionPage(); const page = await extension.initExtension(); page.setDefaultTimeout(15000); + a = page; const wallet = ethers.Wallet.createRandom(); await addFundsToAccount(Tenderly.Mainnet.url, wallet.address); - await addFundsToAccount(Tenderly.Abritrum.url, wallet.address); + await addFundsToAccount( + Tenderly.Polygon.url, + wallet.address, + '0x1043561A8829300000', + ); await addFundsToAccount(Tenderly.Optimism.url, wallet.address); const signUp = new SignUpPage(page); @@ -90,7 +102,7 @@ test.beforeAll( walletPage = new WalletPage(page); await networkController.addCustomNetwork(Tenderly.Mainnet); - await networkController.addCustomNetwork(Tenderly.Abritrum); + await networkController.addCustomNetwork(Tenderly.Polygon); await networkController.addCustomNetwork(Tenderly.Optimism); await walletPage.importAccount(wallet.privateKey); }, @@ -119,14 +131,17 @@ testSet.forEach((options) => { }); } else { log.error(`\tERROR: Transaction did not complete. Skipping test`); + await a.waitForTimeout(100000); test.skip(); } } else { log.error(`\tERROR: No quotes found on. Skipping test`); + await a.waitForTimeout(100000); test.skip(); } } else { log.error(`\tERROR: Error while entering the quote. Skipping test`); + await a.waitForTimeout(100000); test.skip(); } }); diff --git a/test/e2e/playwright/swap/tenderly-network.ts b/test/e2e/playwright/swap/tenderly-network.ts index 24ec2154d84c..996dee47a81a 100644 --- a/test/e2e/playwright/swap/tenderly-network.ts +++ b/test/e2e/playwright/swap/tenderly-network.ts @@ -16,11 +16,11 @@ export const Tenderly = { chainID: '10', symbol: 'ETH', }, - Abritrum: { - name: 'Arbitrum One', + Polygon: { + name: 'Polygon', rpcName: '', - url: 'https://virtual.arbitrum.rpc.tenderly.co/7d364996-41a7-4da6-a552-a19ab1ef9173', - chainID: '42161', + url: 'https://virtual.polygon.rpc.tenderly.co/e834a81e-69ba-49e9-a6a5-be5b6eea3cdc', + chainID: '137', symbol: 'ETH', }, }; From 36010b95713175779ded3082d0869d43a21be1f7 Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Mon, 28 Oct 2024 12:10:53 +0100 Subject: [PATCH 19/23] Removed Polygon and Optimism test because of Tenderly issues --- test/e2e/playwright/swap/specs/swap.spec.ts | 29 --------------------- 1 file changed, 29 deletions(-) diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index 183c4f1b8687..2ddfa1cb7a64 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -23,27 +23,6 @@ const testSet = [ destination: 'DAI', network: Tenderly.Mainnet, }, - { - quantity: '50', - source: 'POL', - type: 'native', - destination: 'USDC', - network: Tenderly.Polygon, - }, - { - quantity: '.5', - source: 'ETH', - type: 'native', - destination: 'OP', - network: Tenderly.Optimism, - }, - { - quantity: '100', - source: 'OP', - type: 'unapproved', - destination: 'USDC', - network: Tenderly.Optimism, - }, { quantity: '50', source: 'DAI', @@ -86,12 +65,6 @@ test.beforeAll( const wallet = ethers.Wallet.createRandom(); await addFundsToAccount(Tenderly.Mainnet.url, wallet.address); - await addFundsToAccount( - Tenderly.Polygon.url, - wallet.address, - '0x1043561A8829300000', - ); - await addFundsToAccount(Tenderly.Optimism.url, wallet.address); const signUp = new SignUpPage(page); await signUp.createWallet(); @@ -102,8 +75,6 @@ test.beforeAll( walletPage = new WalletPage(page); await networkController.addCustomNetwork(Tenderly.Mainnet); - await networkController.addCustomNetwork(Tenderly.Polygon); - await networkController.addCustomNetwork(Tenderly.Optimism); await walletPage.importAccount(wallet.privateKey); }, ); From cf7c652397e47a1fd9794c437e203327d3033c28 Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Tue, 29 Oct 2024 12:40:48 +0100 Subject: [PATCH 20/23] Added changes based on feedbac --- .../pageObjects/network-controller-page.ts | 2 - .../playwright/swap/pageObjects/swap-page.ts | 37 ++++--------------- 2 files changed, 8 insertions(+), 31 deletions(-) diff --git a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts index 76202abea21f..6f6ef06aad18 100644 --- a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts +++ b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts @@ -115,8 +115,6 @@ export class NetworkController { } else { await this.page.getByTestId(options.name).click(); } - await this.waitForNetworkToSwitch(options.name); - await this.page.waitForTimeout(5000); } } diff --git a/test/e2e/playwright/swap/pageObjects/swap-page.ts b/test/e2e/playwright/swap/pageObjects/swap-page.ts index 1c021cc65465..c10536d37f05 100644 --- a/test/e2e/playwright/swap/pageObjects/swap-page.ts +++ b/test/e2e/playwright/swap/pageObjects/swap-page.ts @@ -77,7 +77,7 @@ export class SwapPage { .textContent(); if (balanceString) { if (parseFloat(balanceString.split(' ')[1]) <= parseFloat(options.qty)) { - await this.gotBack(); + await this.goBack(); // not enough balance so cancel out return false; } @@ -105,7 +105,7 @@ export class SwapPage { // No quotes available const noQuotes = await this.page.$('text=/No quotes available/'); if (noQuotes) { - await this.gotBack(); + await this.goBack(); break; } @@ -131,7 +131,7 @@ export class SwapPage { await this.waitForCountDown(); } - async gotBack() { + async goBack() { await this.backButton.click(); } @@ -141,10 +141,10 @@ export class SwapPage { async waitForTransactionToComplete(options: { seconds: number }) { let countSecond = options.seconds; - let trasnsactionCompleted; + let transactionCompleted; do { - trasnsactionCompleted = await this.page.$('text=/Transaction complete/'); - if (trasnsactionCompleted) { + transactionCompleted = await this.page.$('text=/Transaction complete/'); + if (transactionCompleted) { await this.closeButton.click(); break; } @@ -153,7 +153,7 @@ export class SwapPage { countSecond -= 1; } while (countSecond); - if (!trasnsactionCompleted && !countSecond) { + if (!transactionCompleted && !countSecond) { await this.viewInActivityBtn.click(); return false; } @@ -166,31 +166,10 @@ export class SwapPage { } async selectTokenFromList(symbol: string) { - let count; - // wait for the list to populate - do { - count = await this.tokenList.count(); - await this.page.waitForTimeout(500); - } while (count !== (await this.tokenList.count())); - + await this.tokenSearch.waitFor(); await this.tokenSearch.fill(symbol); const regex = new RegExp(`^${symbol}$`, 'u'); const searchItem = await this.tokenList.filter({ hasText: regex }); await searchItem.click({ timeout: 5000 }); } - - async waitForSearchListToPopulate(symbol: string): Promise { - let searchItem; - do { - searchItem = await this.tokenList.first().textContent(); - const listCount = await this.tokenList.count(); - - if (listCount > 1 && searchItem !== symbol) { - await this.tokenQty.fill(''); - await this.tokenQty.fill(symbol); - } - } while (searchItem !== symbol); - - return await this.tokenList.first().click(); - } } From f42e0e96d4cd65d5172f032c1aebad9ecfa2f0cf Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Wed, 30 Oct 2024 17:22:35 +0100 Subject: [PATCH 21/23] Remove unneeded code --- .../shared/pageObjects/network-controller-page.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts index 6f6ef06aad18..1986de15dd88 100644 --- a/test/e2e/playwright/shared/pageObjects/network-controller-page.ts +++ b/test/e2e/playwright/shared/pageObjects/network-controller-page.ts @@ -117,15 +117,4 @@ export class NetworkController { } } } - - async waitForNetworkToSwitch(networkName: string) { - let currentNetwork; - do { - currentNetwork = await this.networkDisplay.textContent(); - if (currentNetwork === networkName) { - break; - } - await this.page.waitForTimeout(1000); - } while (currentNetwork); - } } From d4b5e341c4480fa0b21454ccd554d087cef530b9 Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Wed, 30 Oct 2024 17:39:33 +0100 Subject: [PATCH 22/23] Removed wait in no quote is found --- test/e2e/playwright/swap/specs/swap.spec.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index 2ddfa1cb7a64..310ee67b8b44 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -54,14 +54,12 @@ const testSet = [ }, ]; -let a: Page; test.beforeAll( 'Initialize extension, import wallet and add custom networks', async () => { const extension = new ChromeExtensionPage(); const page = await extension.initExtension(); page.setDefaultTimeout(15000); - a = page; const wallet = ethers.Wallet.createRandom(); await addFundsToAccount(Tenderly.Mainnet.url, wallet.address); @@ -78,6 +76,7 @@ test.beforeAll( await walletPage.importAccount(wallet.privateKey); }, ); + testSet.forEach((options) => { test(`should swap ${options.type} token ${options.source} to ${options.destination} on ${options.network.name}'`, async () => { await walletPage.selectTokenWallet(); @@ -102,17 +101,14 @@ testSet.forEach((options) => { }); } else { log.error(`\tERROR: Transaction did not complete. Skipping test`); - await a.waitForTimeout(100000); test.skip(); } } else { log.error(`\tERROR: No quotes found on. Skipping test`); - await a.waitForTimeout(100000); test.skip(); } } else { log.error(`\tERROR: Error while entering the quote. Skipping test`); - await a.waitForTimeout(100000); test.skip(); } }); From 3b28b3e2013f65cba81fabecf1aac35cd54bb5d3 Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Wed, 30 Oct 2024 21:49:04 +0100 Subject: [PATCH 23/23] Fixed lint error --- test/e2e/playwright/swap/specs/swap.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/playwright/swap/specs/swap.spec.ts b/test/e2e/playwright/swap/specs/swap.spec.ts index 310ee67b8b44..73a85620eabf 100644 --- a/test/e2e/playwright/swap/specs/swap.spec.ts +++ b/test/e2e/playwright/swap/specs/swap.spec.ts @@ -1,5 +1,5 @@ import { ethers } from 'ethers'; -import { Page, test } from '@playwright/test'; +import { test } from '@playwright/test'; import log from 'loglevel'; import { ChromeExtensionPage } from '../../shared/pageObjects/extension-page';