Skip to content

Commit

Permalink
test: [POM] migrate Account Custom Name to page object model (#27283)
Browse files Browse the repository at this point in the history
## **Description**

This pull request migrate account custom name interactions to page
object model(POM) pattern, enhancing code maintainability, and improving
test reliability. It also includes migration for the test file
`test/e2e/tests/account/account-custom-name.spec.ts` as example

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27155?quickstart=1)

## **Related issues**

Fixes: #27163 

## **Manual testing steps**
Check code readability, make sure tests pass.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Chloe Gao <[email protected]>
Co-authored-by: chloeYue <[email protected]>
Co-authored-by: seaona <[email protected]>
  • Loading branch information
4 people authored Sep 23, 2024
1 parent b2cb568 commit 4b4d8d5
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 115 deletions.
92 changes: 0 additions & 92 deletions test/e2e/accounts/account-custom-name.spec.ts

This file was deleted.

108 changes: 100 additions & 8 deletions test/e2e/page-objects/pages/account-list-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Driver } from '../../webdriver/driver';
class AccountListPage {
private driver: Driver;

private accountListItem: object;
private accountListItem: string;

private accountOptionsMenuButton: string;

Expand All @@ -17,6 +17,24 @@ class AccountListPage {

private pinUnpinAccountButton: string;

private createAccountButton: string;

private addEthereumAccountButton: string;

private accountNameInput: string;

private addAccountConfirmButton: string;

private accountMenuButton: string;

private editableLabelButton: string;

private editableLabelInput: string;

private saveAccountLabelButton: string;

private closeEditLabelButton: string;

constructor(driver: Driver) {
this.driver = driver;
this.accountOptionsMenuButton =
Expand All @@ -25,12 +43,64 @@ class AccountListPage {
this.pinUnpinAccountButton = '[data-testid="account-list-menu-pin"]';
this.hiddenAccountsList = '[data-testid="hidden-accounts-list"]';
this.pinnedIcon = '[data-testid="account-pinned-icon"]';
this.accountListItem = {
text: 'Account',
css: '.multichain-account-menu-popover__list--menu-item',
};
this.hiddenAccountOptionsMenuButton =
'.multichain-account-menu-popover__list--menu-item-hidden-account [data-testid="account-list-item-menu-button"]';
this.createAccountButton =
'[data-testid="multichain-account-menu-popover-action-button"]';
this.addEthereumAccountButton =
'[data-testid="multichain-account-menu-popover-add-account"]';
this.accountNameInput = '#account-name';
this.addAccountConfirmButton =
'[data-testid="submit-add-account-with-name"]';
this.accountMenuButton = '[data-testid="account-list-menu-details"]';
this.editableLabelButton = '[data-testid="editable-label-button"]';
this.editableLabelInput = '[data-testid="editable-input"] input';
this.saveAccountLabelButton = '[data-testid="save-account-label-input"]';
this.closeEditLabelButton = 'button[aria-label="Close"]';
// this selector needs to be used in combination with an account label text.
this.accountListItem = '.multichain-account-menu-popover__list--menu-item';
}

async check_pageIsLoaded(): Promise<void> {
try {
await this.driver.waitForMultipleSelectors([
this.createAccountButton,
this.accountOptionsMenuButton,
]);
} catch (e) {
console.log('Timeout while waiting for account list to be loaded', e);
throw e;
}
console.log('Account list is loaded');
}

/**
* Adds a new account with a custom label.
*
* @param customLabel - The custom label for the new account.
*/
async addNewAccountWithCustomLabel(customLabel: string): Promise<void> {
console.log(`Adding new account with custom label: ${customLabel}`);
await this.driver.clickElement(this.createAccountButton);
await this.driver.clickElement(this.addEthereumAccountButton);
await this.driver.fill(this.accountNameInput, customLabel);
await this.driver.clickElementAndWaitToDisappear(
this.addAccountConfirmButton,
);
}

/**
* Changes the label of the current account.
*
* @param newLabel - The new label to set for the account.
*/
async changeAccountLabel(newLabel: string): Promise<void> {
console.log(`Changing account label to: ${newLabel}`);
await this.driver.clickElement(this.accountMenuButton);
await this.driver.clickElement(this.editableLabelButton);
await this.driver.fill(this.editableLabelInput, newLabel);
await this.driver.clickElement(this.saveAccountLabelButton);
await this.driver.clickElement(this.closeEditLabelButton);
}

async check_pageIsLoaded(): Promise<void> {
Expand Down Expand Up @@ -81,9 +151,31 @@ class AccountListPage {
await this.driver.clickElement(this.pinUnpinAccountButton);
}

async check_accountIsDisplayed(): Promise<void> {
console.log(`Check that account is displayed in account list`);
await this.driver.waitForSelector(this.accountListItem);
async switchToAccount(expectedLabel: string): Promise<void> {
console.log(
`Switch to account with label ${expectedLabel} in account list`,
);
await this.driver.clickElement({
css: this.accountListItem,
text: expectedLabel,
});
}

/**
* Check account is displayed in account list.
*
* @param expectedLabel - The expected account label to be displayed in accouunt list.
*/
async check_accountDisplayedInAccountList(
expectedLabel: string = 'Account',
): Promise<void> {
console.log(
`Check that account label ${expectedLabel} is displayed in account list`,
);
await this.driver.waitForSelector({
css: this.accountListItem,
text: expectedLabel,
});
}

async check_accountIsPinned(): Promise<void> {
Expand Down
15 changes: 15 additions & 0 deletions test/e2e/page-objects/pages/header-navbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ class HeaderNavbar {
await this.driver.clickElement(this.accountOptionMenu);
await this.driver.clickElement(this.lockMetaMaskButton);
}

/**
* Verifies that the displayed account label in header matches the expected label.
*
* @param expectedLabel - The expected label of the account.
*/
async check_accountLabel(expectedLabel: string): Promise<void> {
console.log(
`Verify the displayed account label in header is: ${expectedLabel}`,
);
await this.driver.waitForSelector({
css: this.accountMenuButton,
text: expectedLabel,
});
}
}

export default HeaderNavbar;
8 changes: 0 additions & 8 deletions test/e2e/page-objects/pages/homepage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ class HomePage {

private transactionAmountsInActivity: string;

private accountMenuButton: string;

public headerNavbar: HeaderNavbar;

constructor(driver: Driver) {
Expand All @@ -38,7 +36,6 @@ class HomePage {
this.completedTransactions = '[data-testid="activity-list-item"]';
this.transactionAmountsInActivity =
'[data-testid="transaction-list-item-primary-currency"]';
this.accountMenuButton = '[data-testid="account-menu-icon"]';
}

async check_pageIsLoaded(): Promise<void> {
Expand Down Expand Up @@ -84,11 +81,6 @@ class HomePage {
await this.driver.clickElement(this.activityTab);
}

async openAccountMenu(): Promise<void> {
console.log(`Opening account menu`);
await this.driver.clickElement(this.accountMenuButton);
}

/**
* This function checks if the specified number of confirmed transactions are displayed in the activity list on homepage.
* It waits up to 10 seconds for the expected number of confirmed transactions to be visible.
Expand Down
61 changes: 61 additions & 0 deletions test/e2e/tests/account/account-custom-name.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Suite } from 'mocha';
import { Driver } from '../../webdriver/driver';
import { defaultGanacheOptions, withFixtures } from '../../helpers';
import FixtureBuilder from '../../fixture-builder';
import { loginWithBalanceValidation } from '../../page-objects/flows/login.flow';
import AccountListPage from '../../page-objects/pages/account-list-page';
import HeaderNavbar from '../../page-objects/pages/header-navbar';

const newAccountLabel = 'Custom name';
const anotherAccountLabel = '2nd custom name';

describe('Account Custom Name Persistence', function (this: Suite) {
it('persists custom account label through account change and wallet lock', async function () {
await withFixtures(
{
fixtures: new FixtureBuilder().build(),
ganacheOptions: defaultGanacheOptions,
title: this.test?.fullTitle(),
},
async ({ driver }: { driver: Driver }) => {
await loginWithBalanceValidation(driver);

const headerNavbar = new HeaderNavbar(driver);
await headerNavbar.openAccountMenu();

// Change account label for existing account and verify edited account label
const accountListPage = new AccountListPage(driver);
await accountListPage.check_pageIsLoaded();
await accountListPage.openAccountOptionsMenu();
await accountListPage.changeAccountLabel(newAccountLabel);
await headerNavbar.check_accountLabel(newAccountLabel);

// Add new account with custom label and verify new added account label
await headerNavbar.openAccountMenu();
await accountListPage.check_pageIsLoaded();
await accountListPage.addNewAccountWithCustomLabel(anotherAccountLabel);
await headerNavbar.check_accountLabel(anotherAccountLabel);

// Switch back to the first account and verify first custom account persists
await headerNavbar.openAccountMenu();
await accountListPage.check_pageIsLoaded();
await accountListPage.check_accountDisplayedInAccountList(
newAccountLabel,
);
await accountListPage.switchToAccount(newAccountLabel);

// Lock and unlock wallet
await headerNavbar.lockMetaMask();
await loginWithBalanceValidation(driver);

// Verify both account labels persist after unlock
await headerNavbar.check_accountLabel(newAccountLabel);
await headerNavbar.openAccountMenu();
await accountListPage.check_pageIsLoaded();
await accountListPage.check_accountDisplayedInAccountList(
anotherAccountLabel,
);
},
);
});
});
6 changes: 3 additions & 3 deletions test/e2e/tests/account/account-hide-unhide.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { Driver } from '../../webdriver/driver';
import { withFixtures, defaultGanacheOptions } from '../../helpers';
import FixtureBuilder from '../../fixture-builder';
import { loginWithBalanceValidation } from '../../page-objects/flows/login.flow';
import HomePage from '../../page-objects/pages/homepage';
import AccountListPage from '../../page-objects/pages/account-list-page';
import HeaderNavbar from '../../page-objects/pages/header-navbar';

describe('Account list - hide/unhide functionality', function (this: Suite) {
it('hide and unhide account by clicking hide and unhide button', async function () {
Expand All @@ -16,7 +16,7 @@ describe('Account list - hide/unhide functionality', function (this: Suite) {
},
async ({ driver }: { driver: Driver }) => {
await loginWithBalanceValidation(driver);
new HomePage(driver).openAccountMenu();
new HeaderNavbar(driver).openAccountMenu();

// hide account
const accountListPage = new AccountListPage(driver);
Expand All @@ -29,7 +29,7 @@ describe('Account list - hide/unhide functionality', function (this: Suite) {
await accountListPage.openHiddenAccountsList();
await accountListPage.openHiddenAccountOptions();
await accountListPage.unhideAccount();
await accountListPage.check_accountIsDisplayed();
await accountListPage.check_accountDisplayedInAccountList();
},
);
});
Expand Down
Loading

0 comments on commit 4b4d8d5

Please sign in to comment.