Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Swap e2e tests improvements #26493

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ workflows:
- test-e2e-mmi-playwright - OPTIONAL:
requires:
- prep-build-test-mmi-playwright
- test-e2e-swap-playwright - OPTIONAL:
requires:
- prep-build
- test-e2e-chrome-rpc-mmi:
requires:
- prep-build-test-mmi
Expand Down
1 change: 1 addition & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const config: PlaywrightTestConfig = {
...devices['Desktop Chrome'],
headless: true,
},
fullyParallel: false,
},
// Global: universal, common, shared, and non feature related tests
{
Expand Down
43 changes: 32 additions & 11 deletions test/e2e/playwright/shared/pageObjects/network-controller-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -45,25 +47,34 @@ 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();

if (switchToNetwork) {
await this.switchToNetworkBtn.click();
await this.waitForNetworkToSwitch(options.name);
} else {
await this.dismissBtn.click({ timeout: 2000 });
}
}

async addPopularNetwork(options: { networkName: string }) {
Expand All @@ -77,8 +88,18 @@ export class NetworkController {
}

async selectNetwork(options: { networkName: string }) {
await this.networkDisplay.click();
await this.networkSearch.fill(options.networkName);
await this.page.getByText(options.networkName).click();
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) {
await this.page.waitForSelector(`button:has-text("${networkName}")`);
}
}
38 changes: 36 additions & 2 deletions test/e2e/playwright/shared/pageObjects/signup-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export class SignUpPage {

readonly importWalletBtn: Locator;

readonly createWalletBtn: Locator;

readonly metametricsBtn: Locator;

readonly confirmSecretBtn: Locator;

readonly agreeBtn: Locator;
Expand All @@ -21,6 +25,8 @@ export class SignUpPage {

readonly passwordConfirmTxt: Locator;

readonly createPasswordBtn: Locator;

readonly agreeCheck: Locator;

readonly agreeTandCCheck: Locator;
Expand All @@ -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() {
Expand All @@ -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();
}
}
26 changes: 26 additions & 0 deletions test/e2e/playwright/shared/pageObjects/wallet-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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();
}

Expand Down
74 changes: 54 additions & 20 deletions test/e2e/playwright/swap/pageObjects/swap-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { type Locator, type Page } from '@playwright/test';
export class SwapPage {
private page: Page;

private swapQty: string;

readonly toggleSmartSwap: Locator;

readonly updateSettingsButton: Locator;
Expand All @@ -29,6 +31,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',
Expand All @@ -55,35 +58,55 @@ export class SwapPage {
this.backButton = this.page.locator('[title="Cancel"]');
}

async fetchQuote(options: { from?: string; to: string; qty: string }) {
// Enter Swap Quantity
await this.tokenQty.fill(options.qty);

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.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);
}

async waitForQuote() {
let quoteFound = false;
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/')) {
quoteFound = true;
break;
}

await this.page.waitForTimeout(500);
} while (!quoteFound);
}

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();
Expand All @@ -109,18 +132,29 @@ export class SwapPage {
}

async selectTokenFromList(symbol: string) {
let searchItem;
let count;
// wait for the list to populate
do {
searchItem = await this.tokenList.first().textContent();
} while (searchItem !== symbol);

await this.tokenList.first().click();
count = await this.tokenList.count();
await this.page.waitForTimeout(500);
} while (count !== (await this.tokenList.count()));

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<void> {
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();
Expand Down
Loading