Skip to content
Merged
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
151 changes: 107 additions & 44 deletions test/e2e/flask/multichain-api/evm/wallet_invokeMethod.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ describe('Multichain API', function () {
const DEFAULT_INITIAL_BALANCE_HEX = convertETHToHexGwei(
DEFAULT_LOCAL_NODE_ETH_BALANCE_DEC,
);
const SCOPE_TO_NETWORK_NAME: Record<string, string> = {
'eip155:1337': 'Localhost 8545',
'eip155:1338': 'Localhost 8546',
'eip155:1000': 'Localhost 7777',
};

describe('Calling `wallet_invokeMethod` with permissions granted from EIP-1193 provider', function () {
it('should allow the request to be made', async function () {
Expand Down Expand Up @@ -175,48 +180,66 @@ describe('Multichain API', function () {
}
await testDapp.clickInvokeAllMethodsButton();

// first confirmation page should display Account 1 as sender account
await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
const confirmation = new TransactionConfirmation(driver);
await confirmation.checkPageIsLoaded();
assert.equal(
await confirmation.checkIsSenderAccountDisplayed('Account 1'),
true,
);
await confirmation.clickFooterConfirmButton();
// Build expected confirmations
const expectedConfirmations: {
account: string;
network: string;
}[] = [];
for (const [i, scope] of GANACHE_SCOPES.entries()) {
expectedConfirmations.push({
account:
i === INDEX_FOR_ALTERNATE_ACCOUNT ? 'Account 2' : 'Account 1',
network: SCOPE_TO_NETWORK_NAME[scope],
});
}

// check which account confirmation page is displayed on second screen
const resultConfirmations: { account: string; network: string }[] =
[];
await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
await confirmation.checkPageIsLoaded();
const screenForAccount2 =
await confirmation.checkIsSenderAccountDisplayed('Account 2');
if (screenForAccount2) {
await confirmation.checkNetworkIsDisplayed('Localhost 8546');
await confirmation.clickFooterConfirmButton();

// third confirmation page should display Account 1 as sender account
await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
await confirmation.checkPageIsLoaded();
assert.equal(
await confirmation.checkIsSenderAccountDisplayed('Account 1'),
true,
);
await confirmation.checkNetworkIsDisplayed('Localhost 7777');
await confirmation.clickFooterConfirmButtonAndAndWaitForWindowToClose();
} else {
await confirmation.checkNetworkIsDisplayed('Localhost 7777');
await confirmation.clickFooterConfirmButton();
const firstConfirmation = new TransactionConfirmation(driver);
await firstConfirmation.checkPageIsLoaded();
let currentAccount = await firstConfirmation.getSenderAccountName();
let currentNetwork = await firstConfirmation.getNetworkName();
await firstConfirmation.clickFooterConfirmButton();
resultConfirmations.push({
account: currentAccount,
network: currentNetwork,
});

// third confirmation page should display Account 2 as sender account
// Collect actual confirmations from each confirmation screen
for (let i = 0; i < GANACHE_SCOPES.length - 1; i++) {
await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
const confirmation = new TransactionConfirmation(driver);
await confirmation.checkPageIsLoaded();
assert.equal(
await confirmation.checkIsSenderAccountDisplayed('Account 2'),
true,
);
await confirmation.checkNetworkIsDisplayed('Localhost 8546');
await confirmation.clickFooterConfirmButtonAndAndWaitForWindowToClose();
await confirmation.checkNetworkIsNotDisplayed(currentNetwork);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in each iteration, we check that the network is different from the previous confirmation screen to ensure that we’ve switched to a new confirmation screen

currentAccount = await confirmation.getSenderAccountName();
currentNetwork = await confirmation.getNetworkName();
resultConfirmations.push({
account: currentAccount,
network: currentNetwork,
});

// Confirm the transaction except for the last one
if (i < GANACHE_SCOPES.length - 2) {
await confirmation.clickFooterConfirmButton();
} else {
await confirmation.clickFooterConfirmButtonAndAndWaitForWindowToClose();
}
}

// Verify all expected confirmations were found
const hasAllExpectedConfirmations = expectedConfirmations.every(
(expectedConf) =>
resultConfirmations.find(
(resultConf) =>
resultConf.account === expectedConf.account &&
resultConf.network === expectedConf.network,
),
);
assert.ok(
hasAllExpectedConfirmations,
'Not all expected confirmation screens were found',
);
},
);
});
Expand Down Expand Up @@ -260,24 +283,64 @@ describe('Multichain API', function () {

await testDapp.clickInvokeAllMethodsButton();
const totalNumberOfScopes = GANACHE_SCOPES.length;
for (let i = 0; i < totalNumberOfScopes; i++) {
const expectedNetworks = [
'Localhost 8545',
'Localhost 8546',
'Localhost 7777',
];
const currentNetworks = new Set<string>();

// Get the network name from the first confirmation screen
await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
const firstConfirmation = new TransactionConfirmation(driver);
await firstConfirmation.checkPageIsLoaded();
let currentNetworkName = await firstConfirmation.getNetworkName();
await firstConfirmation.checkPageNumbers(1, totalNumberOfScopes);
await firstConfirmation.clickFooterConfirmButton();
currentNetworks.add(currentNetworkName);

for (let i = 0; i < totalNumberOfScopes - 1; i++) {
await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
const confirmation = new TransactionConfirmation(driver);
await confirmation.checkPageIsLoaded();
if (i < totalNumberOfScopes - 1) {
// if pending tx's, verify navigation and confirm
await confirmation.checkPageNumbers(1, totalNumberOfScopes - i);
await confirmation.checkNetworkIsDisplayed(
`Localhost ${8545 + i}`,

// Check that the network is different from the previous confirmation screen to ensure that we’ve switched to a new confirmation screen
await confirmation.checkNetworkIsNotDisplayed(currentNetworkName);

// Get the network name from the current confirmation screen
currentNetworkName = await confirmation.getNetworkName();

// Verify this network hasn't been seen before and is expected
assert(
!currentNetworks.has(currentNetworkName),
`Network ${currentNetworkName} appeared more than once`,
);
assert(
expectedNetworks.includes(currentNetworkName),
`Unexpected network: ${currentNetworkName}`,
);
currentNetworks.add(currentNetworkName);

if (i < totalNumberOfScopes - 2) {
// First 2 confirmations: verify navigation and confirm
await confirmation.checkPageNumbers(
1,
totalNumberOfScopes - i - 1,
);
await confirmation.clickFooterConfirmButton();
} else {
await confirmation.checkNetworkIsDisplayed('Localhost 7777');
// if no pending tx's, confirm and wait for window to close
// Last confirmation: confirm and wait for window to close
await confirmation.clickFooterConfirmButtonAndAndWaitForWindowToClose();
}
}

// Verify all expected networks were seen
assert.equal(
currentNetworks.size,
expectedNetworks.length,
'Not all networks were confirmed',
);

await driver.switchToWindowWithTitle(
WINDOW_TITLES.ExtensionInFullScreenView,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,16 @@ class TransactionConfirmation extends Confirmation {
private readonly gasLimitInput: RawLocator =
'[data-testid="gas-limit-input"]';

private readonly headerAccountName: RawLocator =
'[data-testid="header-account-name"]';

private readonly networkName: RawLocator =
'[data-testid="confirmation__details-network-name"]';

private readonly saveButton: RawLocator = { tag: 'button', text: 'Save' };

private readonly senderAccount: RawLocator = '[data-testid="sender-address"]';

private readonly transactionDetails: RawLocator =
'[data-testid="confirmation__token-details-section"]';

private readonly walletInitiatedHeadingTitle: RawLocator = {
css: 'h4',
text: tEn('review') as string,
Expand Down Expand Up @@ -215,6 +218,16 @@ class TransactionConfirmation extends Confirmation {
});
}

async checkHeaderAccountNameIsDisplayed(account: string): Promise<void> {
console.log(
`Checking header account name ${account} on transaction confirmation page.`,
);
await this.driver.waitForSelector({
css: this.headerAccountName,
text: account,
});
}

async checkPaidByMetaMask() {
await this.driver.findElement({
css: this.paidByMetaMaskNotice,
Expand All @@ -223,26 +236,18 @@ class TransactionConfirmation extends Confirmation {
}

/**
* Checks if the sender account is displayed in the transaction confirmation page.
* Checks that the sender account is displayed on the transaction confirmation page.
*
* @param account - The sender account to check.
*/
async checkIsSenderAccountDisplayed(account: string): Promise<boolean> {
async checkSenderAccountIsDisplayed(account: string): Promise<void> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the original method was called without asserting the return value in code base, making it effectively do nothing. I updated the implementation to prevent false positives.

console.log(
`Checking sender account ${account} on transaction confirmation page.`,
);
try {
await this.driver.waitForSelector({
css: this.senderAccount,
text: account,
});
return true;
} catch (err) {
console.log(
`Sender account ${account} is not displayed on transaction confirmation page.`,
);
return false;
}
await this.driver.waitForSelector({
css: this.senderAccount,
text: account,
});
}

/**
Expand All @@ -259,11 +264,23 @@ class TransactionConfirmation extends Confirmation {
`Checking network ${network} is displayed on transaction confirmation page.`,
);
await this.driver.waitForSelector({
css: this.transactionDetails,
css: this.networkName,
text: network,
});
}

async checkNetworkIsNotDisplayed(network: string): Promise<void> {
console.log(
`Checking network ${network} is not displayed on transaction confirmation page.`,
);
await this.driver.assertElementNotPresent(
{ css: this.networkName, text: network },
{
waitAtLeastGuard: 1000,
},
);
}

async checkNoAlertMessageIsDisplayed() {
console.log(
`Checking no alert message is displayed on transaction confirmation page.`,
Expand Down Expand Up @@ -355,6 +372,45 @@ class TransactionConfirmation extends Confirmation {
await this.driver.fill(this.customNonceInput, nonce);
}

/**
* Gets the network name displayed on the transaction confirmation page.
*
* IMPORTANT: Make sure the transaction confirmation screen is fully loaded
* before calling this method to avoid race conditions, as the network name element
* might not be present or updated correctly immediately after navigation.
*
* @returns The network name.
*/
async getNetworkName(): Promise<string> {
const networkNameElement = await this.driver.findElement(this.networkName);
const networkName = await networkNameElement.getText();
console.log(
'Current network name displayed on transaction confirmation page: ',
networkName,
);
return networkName;
}

/**
* Gets the sender account name displayed on the transaction confirmation page.
*
* IMPORTANT: Make sure the transaction confirmation screen is fully loaded
* before calling this method to avoid race conditions.
*
* @returns The sender account name.
*/
async getSenderAccountName(): Promise<string> {
const senderAccountElement = await this.driver.findElement(
this.senderAccount,
);
const senderAccountName = await senderAccountElement.getText();
console.log(
'Current sender account name displayed on transaction confirmation page: ',
senderAccountName,
);
return senderAccountName;
}

async setCustomNonce(nonce: string) {
await this.clickCustomNonceButton();
await this.fillCustomNonce(nonce);
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/tests/confirmations/transactions/metrics.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe('Metrics', function () {
const transactionConfirmation = new TransactionConfirmation(driver);
// verify UI before clicking advanced details to give time for the Transaction Added event to be emitted without Advanced Details being displayed
await transactionConfirmation.checkPageIsLoaded();
await transactionConfirmation.checkIsSenderAccountDisplayed(
await transactionConfirmation.checkHeaderAccountNameIsDisplayed(
'Account 1',
);
await transactionConfirmation.checkGasFeeSymbol('ETH');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1883,6 +1883,7 @@ exports[`Info renders info section for typed sign request with permission 1`] =
</div>
<p
class="mm-box mm-text mm-text--body-md mm-box--color-text-default"
data-testid="confirmation__details-network-name"
>
Goerli
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ exports[`NativeTransferInfo renders correctly 1`] = `
</div>
<p
class="mm-box mm-text mm-text--body-md mm-box--color-text-default"
data-testid="confirmation__details-network-name"
>
Goerli
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ exports[`NFTTokenTransferInfo renders correctly 1`] = `
</div>
<p
class="mm-box mm-text mm-text--body-md mm-box--color-text-default"
data-testid="confirmation__details-network-name"
>
Goerli
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ export const NetworkRow = ({
name={networkName}
style={{ borderWidth: 0 }}
/>
<Text variant={TextVariant.bodyMd} color={TextColor.textDefault}>
<Text
variant={TextVariant.bodyMd}
color={TextColor.textDefault}
data-testid="confirmation__details-network-name"
>
{networkName}
</Text>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ exports[`TokenDetailsSection renders correctly 1`] = `
</div>
<p
class="mm-box mm-text mm-text--body-md mm-box--color-text-default"
data-testid="confirmation__details-network-name"
>
Goerli
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ exports[`TokenTransferInfo renders correctly 1`] = `
</div>
<p
class="mm-box mm-text mm-text--body-md mm-box--color-text-default"
data-testid="confirmation__details-network-name"
>
Goerli
</p>
Expand Down
Loading