Skip to content

Commit 0766b03

Browse files
feat(accounts): add end-to-end tests for changing account names in multichain setup (MetaMask#19283)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR adds comprehensive end-to-end tests for the multichain account details feature, specifically testing account name changes with the new multichain UI. ### What was added: - New E2E test file: e2e/specs/accounts/change-account-name-multichain.spec.ts - Feature flag testing: Tests with remoteFeatureMultichainAccountsAccountDetails(true) enabled - Complete test coverage: Both main account and imported account renaming scenarios - Persistence validation: Lock/unlock cycle testing to ensure name changes persist across app sessions - Cross-platform support: Validated on both iOS and Android platforms <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MUL-281 ## **Manual testing steps** ```gherkin Feature: Multichain Account Name Changes Scenario 1: User renames main account with multichain details enabled Given the app is launched with remoteFeatureMultichainAccountsAccountDetails enabled When user taps account icon, selects main account actions, and renames account Then the new name should be saved and persist after lock/unlock cycle Scenario 2: User renames imported account with multichain details enabled Given the app has an imported account with multichain details enabled When user selects imported account, opens account actions, and renames account Then the new name should be saved and persist after lock/unlock cycle ``` ## **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 Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] 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-mobile/blob/main/.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.
1 parent fb7b81d commit 0766b03

4 files changed

Lines changed: 209 additions & 0 deletions

File tree

e2e/pages/wallet/AccountActionsBottomSheet.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ class AccountActionsBottomSheet {
3030
);
3131
}
3232

33+
get multichainEditName(): DetoxElement {
34+
return Matchers.getElementByID(
35+
AccountActionsBottomSheetSelectorsIDs.MULTICHAIN_EDIT_NAME,
36+
);
37+
}
38+
3339
async tapEditAccount(): Promise<void> {
3440
await Gestures.waitAndTap(this.editAccount, {
3541
elemDescription: 'Edit account button',
@@ -54,6 +60,12 @@ class AccountActionsBottomSheet {
5460
});
5561
}
5662

63+
async tapRenameAccount(): Promise<void> {
64+
await Gestures.waitAndTap(this.multichainEditName, {
65+
elemDescription: 'Edit Account Name button in V2 account actions modal',
66+
});
67+
}
68+
5769
/**
5870
* This method adapts to feature flag changes for multichain accounts.
5971
*/

e2e/pages/wallet/AccountListBottomSheet.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
} from '../../selectors/wallet/AccountListBottomSheet.selectors';
66
import { WalletViewSelectorsIDs } from '../../selectors/wallet/WalletView.selectors';
77
import { ConnectAccountBottomSheetSelectorsIDs } from '../../selectors/Browser/ConnectAccountBottomSheet.selectors';
8+
import { AccountCellIds } from '../../selectors/MultichainAccounts/AccountCell.selectors';
89
import Matchers from '../../framework/Matchers';
910
import Gestures from '../../framework/Gestures';
1011

@@ -172,6 +173,34 @@ class AccountListBottomSheet {
172173
speed: 'fast',
173174
});
174175
}
176+
177+
// V2 Multichain Accounts Methods
178+
get ellipsisMenuButton(): DetoxElement {
179+
return Matchers.getElementByID(AccountCellIds.MENU);
180+
}
181+
182+
/**
183+
* Tap the ellipsis menu button for a specific account in V2 multichain accounts
184+
* @param accountIndex - The index of the account to tap (0-based)
185+
*/
186+
async tapAccountEllipsisButtonV2(accountIndex: number): Promise<void> {
187+
await Gestures.tapAtIndex(this.ellipsisMenuButton, accountIndex, {
188+
elemDescription: `V2 ellipsis menu button for account at index ${accountIndex}`,
189+
});
190+
}
191+
192+
/**
193+
* Dismiss the account list modal in V2 multichain accounts
194+
* Note: EditAccountName screen auto-dismisses after save in V2, so no manual close needed
195+
* V2 has multiple modal layers - need to swipe twice to fully dismiss
196+
*/
197+
async dismissAccountListModalV2(): Promise<void> {
198+
// First swipe to dismiss the MultichainAccountActions modal
199+
await this.swipeToDismissAccountsModal();
200+
201+
// Second swipe to dismiss the AccountListBottomSheet
202+
await this.swipeToDismissAccountsModal();
203+
}
175204
}
176205

177206
export default new AccountListBottomSheet();

e2e/selectors/wallet/AccountActionsBottomSheet.selectors.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ export const AccountActionsBottomSheetSelectorsIDs = {
77
REMOVE_HARDWARE_ACCOUNT: 'remove-hardware-account-action',
88
REMOVE_SNAP_ACCOUNT: 'remove-snap-account-action',
99
SHOW_SECRET_RECOVERY_PHRASE: 'show-secret-recovery-phrase-action',
10+
MULTICHAIN_EDIT_NAME: 'multichain-account-actions-edit-name',
1011
};
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
import FixtureBuilder from '../../framework/fixtures/FixtureBuilder';
2+
import { RegressionAccounts } from '../../tags.js';
3+
import WalletView from '../../pages/wallet/WalletView';
4+
import Assertions from '../../framework/Assertions';
5+
import TabBarComponent from '../../pages/wallet/TabBarComponent';
6+
import SettingsView from '../../pages/Settings/SettingsView';
7+
import LoginView from '../../pages/wallet/LoginView';
8+
import AccountListBottomSheet from '../../pages/wallet/AccountListBottomSheet';
9+
import AccountActionsBottomSheet from '../../pages/wallet/AccountActionsBottomSheet';
10+
import Matchers from '../../framework/Matchers';
11+
import EditAccountName from '../../pages/MultichainAccounts/EditAccountName';
12+
import { withFixtures } from '../../framework/fixtures/FixtureHelper';
13+
import { loginToApp } from '../../viewHelper';
14+
import { Mockttp } from 'mockttp';
15+
import { setupRemoteFeatureFlagsMock } from '../../api-mocking/helpers/remoteFeatureFlagsHelper';
16+
import { remoteFeatureMultichainAccountsAccountDetailsV2 } from '../../api-mocking/mock-responses/feature-flags-mocks';
17+
import Gestures from '../../framework/Gestures';
18+
19+
const NEW_ACCOUNT_NAME = 'Edited Name';
20+
const NEW_IMPORTED_ACCOUNT_NAME = 'New Imported Account';
21+
const MAIN_ACCOUNT_INDEX = 0;
22+
const IMPORTED_ACCOUNT_INDEX = 1;
23+
24+
const testSpecificMock = async (mockServer: Mockttp) => {
25+
await setupRemoteFeatureFlagsMock(
26+
mockServer,
27+
remoteFeatureMultichainAccountsAccountDetailsV2(true),
28+
);
29+
};
30+
31+
// TODO: With this migration we also removed the need for ganache options and everything is simplified.
32+
describe(
33+
RegressionAccounts('Change Account Name - Multichain Account Details V2'),
34+
() => {
35+
it('renames an account and verifies the new name persists after locking and unlocking the wallet with multichain account details V2 enabled', async () => {
36+
await withFixtures(
37+
{
38+
fixture: new FixtureBuilder()
39+
.withImportedAccountKeyringController()
40+
.build(),
41+
restartDevice: true,
42+
testSpecificMock,
43+
},
44+
async () => {
45+
await loginToApp();
46+
// V2 approach: Use correct ellipsis button selector
47+
await WalletView.tapIdenticon();
48+
49+
// Tap the V2 ellipsis button (3-dot menu) for the main account
50+
await AccountListBottomSheet.tapAccountEllipsisButtonV2(
51+
MAIN_ACCOUNT_INDEX,
52+
);
53+
54+
// V2 flow: Navigate through MultichainAccountActions modal
55+
await AccountActionsBottomSheet.tapRenameAccount();
56+
57+
// Now use the EditAccountName screen
58+
await EditAccountName.updateAccountName(NEW_ACCOUNT_NAME);
59+
await EditAccountName.tapSave();
60+
61+
// EditAccountName screen auto-dismisses after save in V2
62+
// Only need to dismiss the AccountList bottom sheet
63+
await AccountListBottomSheet.dismissAccountListModalV2();
64+
65+
// Verify updated name appears in wallet view
66+
await Assertions.expectElementToHaveText(
67+
WalletView.accountName,
68+
NEW_ACCOUNT_NAME,
69+
{
70+
description: 'verify account name was updated in wallet view',
71+
},
72+
);
73+
74+
// Lock wallet
75+
await Assertions.expectElementToBeVisible(
76+
TabBarComponent.tabBarSettingButton,
77+
);
78+
await TabBarComponent.tapSettings();
79+
await SettingsView.scrollToLockButton();
80+
await SettingsView.tapLock();
81+
await SettingsView.tapYesAlertButton();
82+
await Assertions.expectElementToBeVisible(LoginView.container);
83+
84+
// Unlock wallet and verify updated name persists
85+
await loginToApp();
86+
await Assertions.expectElementToHaveText(
87+
WalletView.accountName,
88+
NEW_ACCOUNT_NAME,
89+
);
90+
},
91+
);
92+
});
93+
94+
it('import an account, edits the name, and verifies the new name persists after locking and unlocking the wallet with multichain account details V2 enabled', async () => {
95+
await withFixtures(
96+
{
97+
fixture: new FixtureBuilder()
98+
.withImportedAccountKeyringController()
99+
.build(),
100+
restartDevice: true,
101+
testSpecificMock,
102+
},
103+
async () => {
104+
await loginToApp();
105+
// V2 approach: Select imported account using V2 selectors
106+
await WalletView.tapIdenticon();
107+
108+
// Use V2 account cell selector for imported account selection
109+
const importedAccountCell = Matchers.getElementByID(
110+
'multichain-account-cell-container',
111+
);
112+
await Gestures.tapAtIndex(
113+
importedAccountCell,
114+
IMPORTED_ACCOUNT_INDEX,
115+
{
116+
elemDescription: 'select imported account using V2 account cell',
117+
},
118+
);
119+
120+
// Navigate to imported account details using V2 ellipsis button
121+
await WalletView.tapIdenticon();
122+
await AccountListBottomSheet.tapAccountEllipsisButtonV2(
123+
IMPORTED_ACCOUNT_INDEX,
124+
);
125+
126+
// V2 flow: Navigate through MultichainAccountActions modal
127+
await AccountActionsBottomSheet.tapRenameAccount();
128+
129+
// Now use the EditAccountName screen
130+
await EditAccountName.updateAccountName(NEW_IMPORTED_ACCOUNT_NAME);
131+
await EditAccountName.tapSave();
132+
133+
// EditAccountName screen auto-dismisses after save in V2
134+
// Only need to dismiss the AccountList bottom sheet
135+
await AccountListBottomSheet.dismissAccountListModalV2();
136+
137+
// Verify updated name appears in wallet view
138+
await Assertions.expectElementToHaveText(
139+
WalletView.accountName,
140+
NEW_IMPORTED_ACCOUNT_NAME,
141+
{
142+
description:
143+
'verify imported account name was updated in wallet view',
144+
},
145+
);
146+
147+
// Lock wallet
148+
await Assertions.expectElementToBeVisible(
149+
TabBarComponent.tabBarSettingButton,
150+
);
151+
await TabBarComponent.tapSettings();
152+
await SettingsView.scrollToLockButton();
153+
await SettingsView.tapLock();
154+
await SettingsView.tapYesAlertButton();
155+
await Assertions.expectElementToBeVisible(LoginView.container);
156+
157+
// Unlock wallet and verify updated name persists
158+
await loginToApp();
159+
await Assertions.expectElementToHaveText(
160+
WalletView.accountName,
161+
NEW_IMPORTED_ACCOUNT_NAME,
162+
);
163+
},
164+
);
165+
});
166+
},
167+
);

0 commit comments

Comments
 (0)