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: [POM] Migrate dapp interaction e2e tests to TS and Page Object Model (part1) #30090

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions test/e2e/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const DEFAULT_GANACHE_ETH_BALANCE_DEC = '25';

/* Dapp host addresses and URL*/
export const DAPP_HOST_ADDRESS = '127.0.0.1:8080';
export const DAPP_ONE_ADDRESS = '127.0.0.1:8081';
export const DAPP_URL_LOCALHOST = 'http://localhost:8080';
export const DAPP_URL = `http://${DAPP_HOST_ADDRESS}`;
export const DAPP_ONE_URL = 'http://127.0.0.1:8081';
Expand Down
18 changes: 18 additions & 0 deletions test/e2e/page-objects/pages/account-list-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ class AccountListPage {
private readonly selectAccountSelector =
'.multichain-account-list-item__account-name';

private readonly viewAccountOnExplorerButton = {
text: 'View on explorer',
tag: 'p',
};

constructor(driver: Driver) {
this.driver = driver;
}
Expand Down Expand Up @@ -378,6 +383,19 @@ class AccountListPage {
);
}

/**
* View the account on explorer for the specified account in account list.
*
* @param accountLabel - The label of the account to view on explorer.
*/
async viewAccountOnExplorer(accountLabel: string): Promise<void> {
console.log(
`View account on explorer in account list for account ${accountLabel}`,
);
await this.openAccountOptionsInAccountList(accountLabel);
await this.driver.clickElement(this.viewAccountOnExplorerButton);
}

/**
* Checks that the account value and suffix is displayed in the account list.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Driver } from '../../../../webdriver/driver';

class AddNetworkConfirmation {
driver: Driver;

constructor(driver: Driver) {
this.driver = driver;
}

/**
* @param networkName - The name of the network to check for in the confirmation page
*/
async check_pageIsLoaded(networkName: string): Promise<void> {
try {
await this.driver.waitForSelector({
text: `Add ${networkName}`,
tag: 'h3',
});
} catch (e) {
console.log(
`Timeout while waiting for Add network ${networkName} confirmation page to be loaded`,
e,
);
throw e;
}
console.log(`Add network ${networkName} confirmation page is loaded`);
}
}

export default AddNetworkConfirmation;
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Driver } from '../../../../webdriver/driver';

class ConnectAccountConfirmation {
driver: Driver;

private readonly connectAccountConfirmationButton = {
text: 'Connect',
tag: 'button',
};

private readonly connectAccountConfirmationTitle = {
text: 'Connect with MetaMask',
tag: 'h2',
};

constructor(driver: Driver) {
this.driver = driver;
}

async check_pageIsLoaded(): Promise<void> {
try {
await this.driver.waitForMultipleSelectors([
this.connectAccountConfirmationTitle,
this.connectAccountConfirmationButton,
]);
} catch (e) {
console.log(
`Timeout while waiting for Connect Account confirmation page to be loaded`,
e,
);
throw e;
}
console.log(`Connect Account confirmation page is loaded`);
}

async confirmConnect(): Promise<void> {
console.log('Confirm connection on Connect Account confirmation page');
await this.driver.clickElement(this.connectAccountConfirmationButton);
}
}

export default ConnectAccountConfirmation;
62 changes: 46 additions & 16 deletions test/e2e/page-objects/pages/home/activity-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,35 +19,43 @@ class ActivityListPage {
css: '.transaction-status-label--failed',
};

private readonly tooltip = '.tippy-tooltip-content';

private readonly transactionAmountsInActivity =
'[data-testid="transaction-list-item-primary-currency"]';

private readonly tooltip = '.tippy-tooltip-content';
private readonly viewTransactionOnExplorerButton = {
text: 'View on block explorer',
tag: 'a',
};

constructor(driver: Driver) {
this.driver = driver;
}

/**
* This function checks if the specified number of failed transactions are displayed in the activity list on homepage.
* It waits up to 10 seconds for the expected number of failed transactions to be visible.
* This function clicks on the activity at the specified index.
* Note: this function need to be called after check_completedTxNumberDisplayedInActivity to reduce flakiness.
*
* @param expectedNumber - The number of failed transactions expected to be displayed in activity list. Defaults to 1.
* @returns A promise that resolves if the expected number of failed transactions is displayed within the timeout period.
* @param expectedNumber - The 1-based index of the activity to be clicked.
*/
async check_failedTxNumberDisplayedInActivity(
expectedNumber: number = 1,
): Promise<void> {
console.log(
`Wait for ${expectedNumber} failed transactions to be displayed in activity list`,
);
await this.driver.wait(async () => {
const failedTxs = await this.driver.findElements(this.failedTransactions);
return failedTxs.length === expectedNumber;
}, 10000);
async clickOnActivity(expectedNumber: number): Promise<void> {
console.log(`Clicking on activity ${expectedNumber}`);
const activities = await this.driver.findElements(this.activityListAction);
await activities[expectedNumber - 1].click();
}

/**
* This function clicks on the "View on block explorer" button for the specified transaction.
*
* @param expectedNumber - The 1-based index of the transaction to be clicked.
*/
async viewTransactionOnExplorer(expectedNumber: number): Promise<void> {
console.log(
`${expectedNumber} failed transactions found in activity list on homepage`,
`Viewing transaction on explorer for transaction ${expectedNumber}`,
);
await this.clickOnActivity(expectedNumber);
await this.driver.clickElement(this.viewTransactionOnExplorerButton);
}

/**
Expand Down Expand Up @@ -98,6 +106,28 @@ class ActivityListPage {
);
}

/**
* This function checks if the specified number of failed transactions are displayed in the activity list on homepage.
* It waits up to 10 seconds for the expected number of failed transactions to be visible.
*
* @param expectedNumber - The number of failed transactions expected to be displayed in activity list. Defaults to 1.
* @returns A promise that resolves if the expected number of failed transactions is displayed within the timeout period.
*/
async check_failedTxNumberDisplayedInActivity(
expectedNumber: number = 1,
): Promise<void> {
console.log(
`Wait for ${expectedNumber} failed transactions to be displayed in activity list`,
);
await this.driver.wait(async () => {
const failedTxs = await this.driver.findElements(this.failedTransactions);
return failedTxs.length === expectedNumber;
}, 10000);
console.log(
`${expectedNumber} failed transactions found in activity list on homepage`,
);
}

async check_noTxInActivity(): Promise<void> {
await this.driver.assertElementNotPresent(this.completedTransactions);
}
Expand Down
24 changes: 24 additions & 0 deletions test/e2e/page-objects/pages/mocked-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Driver } from '../../webdriver/driver';

class MockedPage {
private driver: Driver;

constructor(driver: Driver) {
this.driver = driver;
}

/**
* This method checks if message is displayed on the mocked page.
*
* @param message - The message to check if it is displayed on the mocked page.
*/
async check_displayedMessage(message: string): Promise<void> {
console.log('Checking if message is displayed on mocked page', message);
await this.driver.waitForSelector({
text: message,
tag: 'body',
});
}
}

export default MockedPage;
12 changes: 11 additions & 1 deletion test/e2e/page-objects/pages/test-dapp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class TestDapp {
tag: 'button',
};

private readonly addNetworkButton = '#addEthereumChain';

private readonly approveTokensButton = '#approveTokens';

private readonly approveTokensButtonWithoutGas = '#approveTokensWithoutGas';
Expand Down Expand Up @@ -501,6 +503,14 @@ class TestDapp {
await this.driver.clickElement(this.addTokensToWalletButton);
}

async clickAddNetworkButton() {
await this.driver.clickElement(this.addNetworkButton);
}

async clickConnectAccountButton() {
await this.driver.clickElement(this.connectAccountButton);
}

async clickApproveTokens() {
await this.driver.clickElement(this.approveTokensButton);
}
Expand Down Expand Up @@ -621,7 +631,7 @@ class TestDapp {
publicAddress?: string;
}) {
console.log('Connect account to test dapp');
await this.driver.clickElement(this.connectAccountButton);
await this.clickConnectAccountButton();
if (connectAccountButtonEnabled) {
await this.confirmConnectAccountModal();
} else {
Expand Down
18 changes: 18 additions & 0 deletions test/e2e/page-objects/pages/token-overview-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { Driver } from '../../webdriver/driver';
class TokenOverviewPage {
private driver: Driver;

private readonly assetOptionsButton = '[data-testid="asset-options__button"]';

private readonly receiveButton = {
text: 'Receive',
css: '.icon-button',
Expand All @@ -18,6 +20,11 @@ class TokenOverviewPage {
css: '.icon-button',
};

private readonly viewAssetInExplorerButton = {
text: 'View Asset in explorer',
tag: 'div',
};

constructor(driver: Driver) {
this.driver = driver;
}
Expand Down Expand Up @@ -49,6 +56,17 @@ class TokenOverviewPage {
async clickSwap(): Promise<void> {
await this.driver.clickElement(this.swapButton);
}

/**
* This method opens the asset in explorer.
*/
async viewAssetInExplorer(): Promise<void> {
console.log('Viewing asset in explorer');
await this.driver.clickElement(this.assetOptionsButton);
await this.driver.clickElementAndWaitToDisappear(
this.viewAssetInExplorerButton,
);
}
}

export default TokenOverviewPage;
Loading
Loading