Skip to content

Commit

Permalink
fix: Update and fix e2e tests to handle the presence of the offscreen…
Browse files Browse the repository at this point in the history
… document under MV3 (#24675)

## **Description**

Our MV3 builds add a "Offscreen Document" to our extension. This means
that when our e2e tests call `driver.getAllWindowHandles()`, a new
window is included in the list (the window for the offscreen document).
This PR updates the e2e tests to handle this change. Comments are left
on each file to explain why the change was needed.

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

## **Related issues**

Fixes: #21496

## **Manual testing steps**

Any of the test files modified in this PR should pass when run locally
with MV3 builds

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] 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
- [ ] 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**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] 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.
  • Loading branch information
danjm committed May 31, 2024
1 parent f8969ed commit 4b6cde9
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 64 deletions.
16 changes: 15 additions & 1 deletion test/e2e/accounts/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
validateContractDetails,
multipleGanacheOptions,
regularDelayMs,
openDapp,
} from '../helpers';
import { Driver } from '../webdriver/driver';
import { TEST_SNAPS_SIMPLE_KEYRING_WEBSITE_URL } from '../constants';
Expand Down Expand Up @@ -182,7 +183,20 @@ async function switchToAccount2(driver: Driver) {
}

export async function connectAccountToTestDapp(driver: Driver) {
await switchToOrOpenDapp(driver);
try {
// Do an unusually fast switchToWindowWithTitle, just 1 second
await driver.switchToWindowWithTitle(
WINDOW_TITLES.TestDApp,
null,
1000,
1000,
);
} catch {
await driver.switchToWindowWithTitle(
WINDOW_TITLES.ExtensionInFullScreenView,
);
await openDapp(driver);
}
await driver.clickElement('#connectButton');

await driver.delay(regularDelayMs);
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ const DAPP_URL = 'http://127.0.0.1:8080';
const DAPP_ONE_URL = 'http://127.0.0.1:8081';

const openDapp = async (driver, contract = null, dappURL = DAPP_URL) => {
contract
return contract
? await driver.openNewPage(`${dappURL}/?contract=${contract}`)
: await driver.openNewPage(dappURL);
};
Expand Down
35 changes: 10 additions & 25 deletions test/e2e/json-rpc/switchEthereumChain.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,8 @@ describe('Switch Ethereum Chain for two dapps', function () {
await unlockWallet(driver);

// open two dapps
await openDapp(driver, undefined, DAPP_URL);
await openDapp(driver, undefined, DAPP_ONE_URL);

// Window Handling
const windowHandles = await driver.getAllWindowHandles();
const dappOne = windowHandles[1];
const dappTwo = windowHandles[2];
const dappOne = await openDapp(driver, undefined, DAPP_URL);
const dappTwo = await openDapp(driver, undefined, DAPP_ONE_URL);

// switchEthereumChain request
const switchEthereumChainRequest = JSON.stringify({
Expand Down Expand Up @@ -100,13 +95,9 @@ describe('Switch Ethereum Chain for two dapps', function () {
await unlockWallet(driver);

// open two dapps
await openDapp(driver, undefined, DAPP_URL);
const dappOne = await openDapp(driver, undefined, DAPP_URL);
await openDapp(driver, undefined, DAPP_ONE_URL);

// Window Handling
const windowHandles = await driver.getAllWindowHandles();
const dappOne = windowHandles[1];

// Initiate send transaction on Dapp two
await driver.clickElement('#sendButton');
await driver.delay(2000);
Expand Down Expand Up @@ -172,13 +163,9 @@ describe('Switch Ethereum Chain for two dapps', function () {
await unlockWallet(driver);

// open two dapps
await openDapp(driver, undefined, DAPP_URL);
const dappOne = await openDapp(driver, undefined, DAPP_URL);
await openDapp(driver, undefined, DAPP_ONE_URL);

// Window Handling
let windowHandles = await driver.getAllWindowHandles();
const dappOne = windowHandles[1];

// switchEthereumChain request
const switchEthereumChainRequest = JSON.stringify({
jsonrpc: '2.0',
Expand Down Expand Up @@ -217,10 +204,12 @@ describe('Switch Ethereum Chain for two dapps', function () {
// Confirm switchEthereumChain with queued pending tx
await driver.clickElement({ text: 'Switch network', tag: 'button' });

// Window handles should only be expanded mm, dapp one, dapp 2 (3 total)
// Window handles should only be expanded mm, dapp one, dapp 2, and the offscreen document
// if this is an MV3 build(3 or 4 total)
await driver.wait(async () => {
windowHandles = await driver.getAllWindowHandles();
return windowHandles.length === 3;
const windowHandles = await driver.getAllWindowHandles();
const numberOfWindowHandlesToExpect = process.env.ENABLE_MV3 ? 4 : 3;
return windowHandles.length === numberOfWindowHandlesToExpect;
});
},
);
Expand All @@ -245,13 +234,9 @@ describe('Switch Ethereum Chain for two dapps', function () {
await unlockWallet(driver);

// open two dapps
await openDapp(driver, undefined, DAPP_URL);
const dappOne = await openDapp(driver, undefined, DAPP_URL);
await openDapp(driver, undefined, DAPP_ONE_URL);

// Window Handling
const windowHandles = await driver.getAllWindowHandles();
const dappOne = windowHandles[1];

// switchEthereumChain request
const switchEthereumChainRequest = JSON.stringify({
jsonrpc: '2.0',
Expand Down
16 changes: 15 additions & 1 deletion test/e2e/tests/request-queuing/ui.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,22 @@ async function openDappAndSwitchChain(driver, dappUrl, chainId) {

async function selectDappClickSendGetNetwork(driver, dappUrl) {
await driver.switchToWindowWithUrl(dappUrl);
const currentWindowHandles = await driver.getAllWindowHandles();
await driver.clickElement('#sendButton');
await switchToNotificationWindow(driver, 4);

// Under mv3, we don't need to add to the current number of window handles
// because the offscreen document returned by getAllWindowHandles provides
// an extra window handle
const newWindowHandles = await driver.waitUntilXWindowHandles(
process.env.ENABLE_MV3
? currentWindowHandles.length
: currentWindowHandles.length + 1,
);
const [newNotificationWindowHandle] = newWindowHandles.filter(
(h) => !currentWindowHandles.includes(h),
);
await driver.switchToWindow(newNotificationWindowHandle);

const networkPill = await driver.findElement(
'[data-testid="network-display"]',
);
Expand Down
25 changes: 11 additions & 14 deletions test/e2e/tests/settings/full-size-view-settings.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,25 @@ describe('Full-size View Setting @no-mmi', function () {
await unlockWallet(driver);
await toggleFullSizeViewSetting(driver);
await openDapp(driver);
const windowHandlesPreClick = await driver.waitUntilXWindowHandles(
2,
1000,
10000,
);
await driver.clickElement('#maliciousPermit'); // Opens the extension in popup view.
const windowHandles = await driver.waitUntilXWindowHandles(
const windowHandlesPostClick = await driver.waitUntilXWindowHandles(
3,
1000,
10000,
);
const fullScreenWindowTitle = await driver.getWindowTitleByHandlerId(
windowHandles[0],
const [newWindowHandle] = windowHandlesPostClick.filter(
(handleId) => !windowHandlesPreClick.includes(handleId),
);
const dappWindowTitle = await driver.getWindowTitleByHandlerId(
windowHandles[1],
);
const popUpWindowTitle = await driver.getWindowTitleByHandlerId(
windowHandles[2],
const newWindowTitle = await driver.getWindowTitleByHandlerId(
newWindowHandle,
);

assert.equal(
fullScreenWindowTitle,
WINDOW_TITLES.ExtensionInFullScreenView,
);
assert.equal(dappWindowTitle, WINDOW_TITLES.TestDApp);
assert.equal(popUpWindowTitle, WINDOW_TITLES.Dialog);
assert.equal(newWindowTitle, WINDOW_TITLES.Dialog);
},
);
});
Expand Down
9 changes: 5 additions & 4 deletions test/e2e/tests/transaction/edit-gas-fee.spec.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const { strict: assert } = require('assert');
const {
getWindowHandles,
withFixtures,
openDapp,
unlockWallet,
generateGanacheOptions,
WINDOW_TITLES,
} = require('../../helpers');
const FixtureBuilder = require('../../fixture-builder');

Expand Down Expand Up @@ -176,8 +176,7 @@ describe('Editing Confirm Transaction', function () {
});

// check transaction in extension popup
const windowHandles = await getWindowHandles(driver, 3);
await driver.switchToWindow(windowHandles.popup);
await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
await driver.waitForSelector({
text: 'Site suggested',
});
Expand Down Expand Up @@ -207,7 +206,9 @@ describe('Editing Confirm Transaction', function () {
await driver.clickElement({ text: 'Confirm', tag: 'button' });

// transaction should correct values in activity tab
await driver.switchToWindow(windowHandles.extension);
await driver.switchToWindowWithTitle(
WINDOW_TITLES.ExtensionInFullScreenView,
);
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
Expand Down
27 changes: 13 additions & 14 deletions test/e2e/tests/transaction/multiple-transactions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const {
regularDelayMs,
unlockWallet,
generateGanacheOptions,
WINDOW_TITLES,
} = require('../../helpers');
const FixtureBuilder = require('../../fixture-builder');

Expand All @@ -30,27 +31,23 @@ describe('Multiple transactions', function () {
tag: 'button',
});
await driver.waitUntilXWindowHandles(3);
const windowHandles = await driver.getAllWindowHandles();
const extensionTab = windowHandles[0];
const dApp = windowHandles[1];
const confirmation = windowHandles[2];

await driver.switchToWindow(dApp);
await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp);

// creates second transaction
await driver.clickElement({
text: 'Send EIP 1559 Transaction',
tag: 'button',
});
await driver.switchToWindow(confirmation);
await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);

// confirms second transaction
await driver.waitForSelector({
text: 'Reject 2 transactions',
tag: 'a',
});
await driver.clickElement({ text: 'Confirm', tag: 'button' });
await driver.switchToWindow(confirmation);
await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);

// wait for the "Reject 2 transactions" to disappear
await driver.assertElementNotPresent(
Expand All @@ -61,7 +58,9 @@ describe('Multiple transactions', function () {
await driver.clickElement({ text: 'Confirm', tag: 'button' });

await driver.waitUntilXWindowHandles(2);
await driver.switchToWindow(extensionTab);
await driver.switchToWindowWithTitle(
WINDOW_TITLES.ExtensionInFullScreenView,
);
await driver.delay(regularDelayMs);
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.waitForSelector(
Expand Down Expand Up @@ -98,17 +97,15 @@ describe('Multiple transactions', function () {
tag: 'button',
});
await driver.waitUntilXWindowHandles(3);
const windowHandles = await driver.getAllWindowHandles();
const extension = windowHandles[0];
const confirmation = windowHandles[2];
await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles);

await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp);

// creates second transaction
await driver.clickElement({
text: 'Send EIP 1559 Transaction',
tag: 'button',
});
await driver.switchToWindow(confirmation);
await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);

// rejects second transaction
await driver.waitForSelector({
Expand All @@ -121,7 +118,9 @@ describe('Multiple transactions', function () {
await driver.clickElement({ text: 'Reject', tag: 'button' });

await driver.waitUntilXWindowHandles(2);
await driver.switchToWindow(extension);
await driver.switchToWindowWithTitle(
WINDOW_TITLES.ExtensionInFullScreenView,
);
await driver.delay(regularDelayMs);
await driver.clickElement('[data-testid="home__activity-tab"]');

Expand Down
9 changes: 5 additions & 4 deletions test/e2e/webdriver/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -533,8 +533,9 @@ class Driver {
}

async openNewPage(url) {
const newHandle = await this.driver.switchTo().newWindow();
await this.driver.switchTo().newWindow();
await this.openNewURL(url);
const newHandle = await this.driver.getWindowHandle();
return newHandle;
}

Expand All @@ -558,12 +559,12 @@ class Driver {
return await this.driver.getAllWindowHandles();
}

async waitUntilXWindowHandles(x, delayStep = 1000, timeout = this.timeout) {
async waitUntilXWindowHandles(_x, delayStep = 1000, timeout = this.timeout) {
const x = process.env.ENABLE_MV3 ? _x + 1 : _x;
let timeElapsed = 0;
let windowHandles = [];
while (timeElapsed <= timeout) {
windowHandles = await this.driver.getAllWindowHandles();

windowHandles = await this.getAllWindowHandles();
if (windowHandles.length === x) {
return windowHandles;
}
Expand Down

0 comments on commit 4b6cde9

Please sign in to comment.