1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

use waitForSelector instead of until (#10852)

* complete abstraction of until method

* response to feedback
This commit is contained in:
Brad Decker 2021-04-13 16:36:02 -05:00 committed by GitHub
parent 7fb4e09e6f
commit 57be0e49d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 112 additions and 100 deletions

View File

@ -1,6 +1,4 @@
const assert = require('assert'); const assert = require('assert');
const { until } = require('selenium-webdriver');
const enLocaleMessages = require('../../app/_locales/en/messages.json'); const enLocaleMessages = require('../../app/_locales/en/messages.json');
const { regularDelayMs, largeDelayMs } = require('./helpers'); const { regularDelayMs, largeDelayMs } = require('./helpers');
const { buildWebDriver } = require('./webdriver'); const { buildWebDriver } = require('./webdriver');
@ -126,11 +124,13 @@ describe('Using MetaMask with an existing account', function () {
'[data-testid="account-options-menu__account-details"]', '[data-testid="account-options-menu__account-details"]',
); );
await driver.findVisibleElement('.qr-code__wrapper'); await driver.findVisibleElement('.qr-code__wrapper');
const detailModal = await driver.findElement('span .modal'); // wait for details modal to be visible
const detailsModal = await driver.findVisibleElement('span .modal');
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
await driver.clickElement('.account-modal__close'); await driver.clickElement('.account-modal__close');
await driver.wait(until.stalenessOf(detailModal)); // wait for details modal to be removed from DOM
await detailsModal.waitForElementState('hidden');
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
}); });
}); });
@ -213,10 +213,11 @@ describe('Using MetaMask with an existing account', function () {
await driver.clickElement('.advanced-gas-options-btn'); await driver.clickElement('.advanced-gas-options-btn');
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
const gasModal = await driver.findElement('span .modal'); // wait for gas modal to be visible
const gasModal = await driver.findVisibleElement('span .modal');
await driver.clickElement({ text: 'Save', tag: 'button' }); await driver.clickElement({ text: 'Save', tag: 'button' });
await driver.wait(until.stalenessOf(gasModal)); // wait for gas modal to be removed from DOM
await driver.delay(regularDelayMs); await gasModal.waitForElementState('hidden');
// Continue to next screen // Continue to next screen
await driver.clickElement({ text: 'Next', tag: 'button' }); await driver.clickElement({ text: 'Next', tag: 'button' });

View File

@ -1,5 +1,4 @@
const assert = require('assert'); const assert = require('assert');
const { until } = require('selenium-webdriver');
const enLocaleMessages = require('../../app/_locales/en/messages.json'); const enLocaleMessages = require('../../app/_locales/en/messages.json');
const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers'); const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers');
@ -109,11 +108,13 @@ describe('MetaMask', function () {
const addressInput = await driver.findElement('.readonly-input__input'); const addressInput = await driver.findElement('.readonly-input__input');
publicAddress = await addressInput.getAttribute('value'); publicAddress = await addressInput.getAttribute('value');
const accountModal = await driver.findElement('span .modal'); // wait for account modal to be visible
const accountModal = await driver.findVisibleElement('span .modal');
await driver.clickElement('.account-modal__close'); await driver.clickElement('.account-modal__close');
await driver.wait(until.stalenessOf(accountModal)); // wait for account modal to be removed from DOM
await accountModal.waitForElementState('hidden');
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
}); });
}); });
@ -134,8 +135,10 @@ describe('MetaMask', function () {
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
await driver.clickElement('#send'); await driver.clickElement('#send');
const txStatus = await driver.findElement('#success'); await driver.waitForSelector(
await driver.wait(until.elementTextMatches(txStatus, /Success/u), 15000); { css: '#success', text: 'Success' },
{ timeout: 15000 },
);
}); });
it('switches back to MetaMask', async function () { it('switches back to MetaMask', async function () {
@ -143,13 +146,13 @@ describe('MetaMask', function () {
}); });
it('should have the correct amount of eth', async function () { it('should have the correct amount of eth', async function () {
const balances = await driver.findElements( const currencyDisplay = await driver.waitForSelector({
'.currency-display-component__text', css: '.currency-display-component__text',
); text: '1',
await driver.wait(until.elementTextMatches(balances[0], /1/u), 15000); });
const balance = await balances[0].getText(); const balance = await currencyDisplay.getText();
assert.equal(balance, '1'); assert.strictEqual(balance, '1');
}); });
}); });
@ -213,13 +216,13 @@ describe('MetaMask', function () {
}); });
it('should have the correct amount of eth', async function () { it('should have the correct amount of eth', async function () {
const balances = await driver.findElements( const currencyDisplay = await driver.waitForSelector({
'.currency-display-component__text', css: '.currency-display-component__text',
); text: '1',
await driver.wait(until.elementTextMatches(balances[0], /1/u), 15000); });
const balance = await balances[0].getText(); const balance = await currencyDisplay.getText();
assert.equal(balance, '1'); assert.strictEqual(balance, '1');
}); });
it('should not show a backup reminder', async function () { it('should not show a backup reminder', async function () {

View File

@ -1,5 +1,4 @@
const assert = require('assert'); const assert = require('assert');
const { until } = require('selenium-webdriver');
const enLocaleMessages = require('../../app/_locales/en/messages.json'); const enLocaleMessages = require('../../app/_locales/en/messages.json');
const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers'); const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers');
@ -194,10 +193,10 @@ describe('MetaMask', function () {
}); });
it('balance renders', async function () { it('balance renders', async function () {
const balance = await driver.findElement( await driver.waitForSelector({
'[data-testid="eth-overview__primary-currency"]', css: '[data-testid="eth-overview__primary-currency"]',
); text: '100 ETH',
await driver.wait(until.elementTextMatches(balance, /100\s*ETH/u)); });
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
}); });
}); });
@ -224,10 +223,11 @@ describe('MetaMask', function () {
await driver.clickElement('.advanced-gas-options-btn'); await driver.clickElement('.advanced-gas-options-btn');
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
const gasModal = await driver.findElement('span .modal'); // wait for gas modal to be visible
const gasModal = await driver.findVisibleElement('span .modal');
await driver.clickElement('.page-container__header-close-text'); await driver.clickElement('.page-container__header-close-text');
await driver.wait(until.stalenessOf(gasModal), 10000); // wait for gas modal to be removed from dom
await gasModal.waitForElementState('hidden');
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
}); });
@ -250,10 +250,13 @@ describe('MetaMask', function () {
return confirmedTxes.length === 1; return confirmedTxes.length === 1;
}, 10000); }, 10000);
const txValues = await driver.findElement( await driver.waitForSelector(
'.transaction-list-item__primary-currency', {
css: '.transaction-list-item__primary-currency',
text: '-1 ETH',
},
{ timeout: 10000 },
); );
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000);
}); });
}); });
}); });

View File

@ -142,11 +142,11 @@ describe('MetaMask', function () {
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
// wait for permission modal to be visible. // wait for permission modal to be visible.
await driver.waitForSelector('span .modal'); const permissionModal = await driver.findVisibleElement('span .modal');
await driver.clickElement('.account-modal__close'); await driver.clickElement('.account-modal__close');
// wait for account modal to be removed from DOM. // wait for permission modal to be removed from DOM.
await driver.waitForSelector('span .modal', { state: 'detached' }); await permissionModal.waitForElementState('hidden');
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
}); });
}); });
@ -377,12 +377,13 @@ describe('MetaMask', function () {
await driver.clickElement('.advanced-gas-options-btn'); await driver.clickElement('.advanced-gas-options-btn');
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
// wait for gas modal to be visible
const gasModal = await driver.findVisibleElement('span .modal');
await driver.clickElement({ text: 'Save', tag: 'button' }); await driver.clickElement({ text: 'Save', tag: 'button' });
// Wait for gas modal to be removed from DOM // Wait for gas modal to be removed from DOM
await driver.waitForSelector('span .modal', { await gasModal.waitForElementState('hidden');
state: 'detached',
});
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
// Continue to next screen // Continue to next screen
@ -854,8 +855,8 @@ describe('MetaMask', function () {
// Set the gas limit // Set the gas limit
await driver.clickElement('.confirm-detail-row__header-text--edit'); await driver.clickElement('.confirm-detail-row__header-text--edit');
// wait for gas modal to be detached from DOM // wait for gas modal to be visible.
await driver.waitForSelector('span .modal'); const gasModal = await driver.findVisibleElement('span .modal');
await driver.clickElement('.page-container__tab:nth-of-type(2)'); await driver.clickElement('.page-container__tab:nth-of-type(2)');
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
@ -875,7 +876,7 @@ describe('MetaMask', function () {
await driver.clickElement({ text: 'Save', tag: 'button' }); await driver.clickElement({ text: 'Save', tag: 'button' });
// wait for gas modal to be detached from DOM // wait for gas modal to be detached from DOM
await driver.waitForSelector('span .modal', { state: 'detached' }); await gasModal.waitForElementState('hidden');
await driver.clickElement({ text: 'Confirm', tag: 'button' }); await driver.clickElement({ text: 'Confirm', tag: 'button' });
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
@ -1044,12 +1045,12 @@ describe('MetaMask', function () {
it('opens customize gas modal and saves options to continue', async function () { it('opens customize gas modal and saves options to continue', async function () {
await driver.clickElement('.advanced-gas-options-btn'); await driver.clickElement('.advanced-gas-options-btn');
// Wait for gas modal to be visible // wait for gas modal to be visible
await driver.waitForSelector('span .modal'); const gasModal = await driver.findVisibleElement('span .modal');
await driver.findElement('.page-container__title'); await driver.findElement('.page-container__title');
await driver.clickElement({ text: 'Save', tag: 'button' }); await driver.clickElement({ text: 'Save', tag: 'button' });
// wait for gas modal to be removed from DOM. // wait for gas modal to be removed from DOM.
await driver.waitForSelector('span .modal', { state: 'detached' }); await gasModal.waitForElementState('hidden');
}); });
it('transitions to the confirm screen', async function () { it('transitions to the confirm screen', async function () {
@ -1152,16 +1153,14 @@ describe('MetaMask', function () {
); );
const transactionAmount = transactionAmounts[0]; const transactionAmount = transactionAmounts[0];
assert(await transactionAmount.getText(), '1.5 TST'); assert(await transactionAmount.getText(), '1.5 TST');
// Set the gas limit
await driver.clickElement('.confirm-detail-row__header-text--edit');
await driver.delay(regularDelayMs);
// wait for gas modal to be visible
await driver.waitForSelector('span .modal');
}); });
it('customizes gas', async function () { it('customizes gas', async function () {
// Set the gas limit
await driver.clickElement('.confirm-detail-row__header-text--edit');
await driver.delay(regularDelayMs);
// wait for gas modal to be visible
const gasModal = await driver.findVisibleElement('span .modal');
await driver.clickElement('.page-container__tab:nth-of-type(2)'); await driver.clickElement('.page-container__tab:nth-of-type(2)');
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
@ -1178,10 +1177,8 @@ describe('MetaMask', function () {
await driver.clickElement('.page-container__footer-button'); await driver.clickElement('.page-container__footer-button');
// Wait for gas modal to be removed from DOM. // wait for gas modal to be removed from DOM.
await driver.waitForSelector('span .modal', { await gasModal.waitForElementState('hidden');
state: 'detached',
});
const gasFeeInputs = await driver.findElements( const gasFeeInputs = await driver.findElements(
'.confirm-detail-row__primary', '.confirm-detail-row__primary',
@ -1286,17 +1283,14 @@ describe('MetaMask', function () {
); );
}); });
it('opens the gas edit modal', async function () { it('customizes gas', async function () {
await driver.clickElement( await driver.clickElement(
'.confirm-approve-content__small-blue-text.cursor-pointer', '.confirm-approve-content__small-blue-text.cursor-pointer',
); );
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
// Wait for the gas modal to be visible // wait for gas modal to be visible
await driver.waitForSelector('span .modal'); const gasModal = await driver.findVisibleElement('span .modal');
});
it('customizes gas', async function () {
await driver.clickElement('.page-container__tab:nth-of-type(2)'); await driver.clickElement('.page-container__tab:nth-of-type(2)');
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
@ -1313,10 +1307,8 @@ describe('MetaMask', function () {
await driver.clickElement('.page-container__footer-button'); await driver.clickElement('.page-container__footer-button');
// wait for the gas modal to be removed from DOM. // wait for gas modal to be removed from DOM.
await driver.waitForSelector('span .modal', { await gasModal.waitForElementState('hidden');
state: 'detached',
});
const gasFeeInEth = await driver.findElement( const gasFeeInEth = await driver.findElement(
'.confirm-approve-content__transaction-details-content__secondary-fee', '.confirm-approve-content__transaction-details-content__secondary-fee',
@ -1331,7 +1323,7 @@ describe('MetaMask', function () {
await editButtons[1].click(); await editButtons[1].click();
// wait for permission modal to be visible // wait for permission modal to be visible
await driver.waitForSelector('span .modal'); const permissionModal = await driver.findVisibleElement('span .modal');
const radioButtons = await driver.findClickableElements( const radioButtons = await driver.findClickableElements(
'.edit-approval-permission__edit-section__radio-button', '.edit-approval-permission__edit-section__radio-button',
); );
@ -1343,7 +1335,7 @@ describe('MetaMask', function () {
await driver.clickElement({ text: 'Save', tag: 'button' }); await driver.clickElement({ text: 'Save', tag: 'button' });
// wait for permission modal to be removed from DOM. // wait for permission modal to be removed from DOM.
await driver.waitForSelector('span .modal', { state: 'detached' }); await permissionModal.waitForElementState('hidden');
const permissionInfo = await driver.findElements( const permissionInfo = await driver.findElements(
'.confirm-approve-content__medium-text', '.confirm-approve-content__medium-text',
@ -1521,14 +1513,14 @@ describe('MetaMask', function () {
await driver.clickElement('[data-testid="token-options__hide"]'); await driver.clickElement('[data-testid="token-options__hide"]');
// wait for confirm hide modal to be visible // wait for confirm hide modal to be visible
await driver.waitForSelector('span .modal'); const confirmHideModal = await driver.findVisibleElement('span .modal');
await driver.clickElement( await driver.clickElement(
'[data-testid="hide-token-confirmation__hide"]', '[data-testid="hide-token-confirmation__hide"]',
); );
// wait for confirm hide modal to be removed from DOM. // wait for confirm hide modal to be removed from DOM.
await driver.waitForSelector('span .modal', { state: 'detached' }); await confirmHideModal.waitForElementState('hidden');
}); });
}); });
@ -1649,15 +1641,15 @@ describe('MetaMask', function () {
await driver.clickElement('.btn-danger'); await driver.clickElement('.btn-danger');
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
// wait for confirm delete modal to be visible. // wait for confirm delete modal to be visible
await driver.waitForSelector('span .modal'); const confirmDeleteModal = await driver.findVisibleElement('span .modal');
await driver.clickElement( await driver.clickElement(
'.button.btn-danger.modal-container__footer-button', '.button.btn-danger.modal-container__footer-button',
); );
// wait for confirm delete modal to be removed from DOM. // wait for confirm delete modal to be removed from DOM.
await driver.waitForSelector('span .modal', { state: 'detached' }); await confirmDeleteModal.waitForElementState('hidden');
const newNetworkListItems = await driver.findElements( const newNetworkListItems = await driver.findElements(
'.networks-tab__networks-list-name', '.networks-tab__networks-list-name',

View File

@ -1,5 +1,4 @@
const { strict: assert } = require('assert'); const { strict: assert } = require('assert');
const { until } = require('selenium-webdriver');
const { withFixtures } = require('../helpers'); const { withFixtures } = require('../helpers');
describe('Address Book', function () { describe('Address Book', function () {
@ -34,13 +33,16 @@ describe('Address Book', function () {
await driver.clickElement('.dialog.send__dialog.dialog--message'); await driver.clickElement('.dialog.send__dialog.dialog--message');
const addressBookAddModal = await driver.findElement('span .modal'); // wait for address book modal to be visible
const addressModal = await driver.findElement('span .modal');
await driver.findElement('.add-to-address-book-modal'); await driver.findElement('.add-to-address-book-modal');
await driver.fill('.add-to-address-book-modal__input', 'Test Name 1'); await driver.fill('.add-to-address-book-modal__input', 'Test Name 1');
await driver.clickElement( await driver.clickElement(
'.add-to-address-book-modal__footer .btn-primary', '.add-to-address-book-modal__footer .btn-primary',
); );
await driver.wait(until.stalenessOf(addressBookAddModal)); // wait for address book modal to be removed from DOM
await addressModal.waitForElementState('hidden');
const inputAmount = await driver.findElement('.unit-input__input'); const inputAmount = await driver.findElement('.unit-input__input');
await inputAmount.fill('1'); await inputAmount.fill('1');
@ -60,12 +62,12 @@ describe('Address Book', function () {
return confirmedTxes.length === 1; return confirmedTxes.length === 1;
}, 10000); }, 10000);
const txValues = await driver.findElement( await driver.waitForSelector(
'.transaction-list-item__primary-currency', {
); css: '.transaction-list-item__primary-currency',
await driver.wait( text: '-1 ETH',
until.elementTextMatches(txValues, /-1\s*ETH/u), },
10000, { timeout: 10000 },
); );
}, },
); );
@ -106,12 +108,12 @@ describe('Address Book', function () {
return confirmedTxes.length === 1; return confirmedTxes.length === 1;
}, 10000); }, 10000);
const txValues = await driver.findElement( await driver.waitForSelector(
'.transaction-list-item__primary-currency', {
); css: '.transaction-list-item__primary-currency',
await driver.wait( text: '-2 ETH',
until.elementTextMatches(txValues, /-2\s*ETH/u), },
10000, { timeout: 10000 },
); );
}, },
); );

View File

@ -1,5 +1,4 @@
const { strict: assert } = require('assert'); const { strict: assert } = require('assert');
const { until } = require('selenium-webdriver');
const { const {
withFixtures, withFixtures,
tinyDelayMs, tinyDelayMs,
@ -46,7 +45,8 @@ describe('Editing Confirm Transaction', function () {
await driver.clickElement('.advanced-gas-options-btn'); await driver.clickElement('.advanced-gas-options-btn');
await driver.delay(regularDelayMs); await driver.delay(regularDelayMs);
const gasModal = await driver.findElement('span .modal'); // wait for gas modal to be visible
const gasModal = await driver.findVisibleElement('span .modal');
const [gasPriceInput, gasLimitInput] = await driver.findElements( const [gasPriceInput, gasLimitInput] = await driver.findElements(
'.advanced-gas-inputs__gas-edit-row__input', '.advanced-gas-inputs__gas-edit-row__input',
@ -59,7 +59,8 @@ describe('Editing Confirm Transaction', function () {
await driver.delay(largeDelayMs); await driver.delay(largeDelayMs);
await driver.clickElement({ text: 'Save', tag: 'button' }); await driver.clickElement({ text: 'Save', tag: 'button' });
await driver.wait(until.stalenessOf(gasModal)); // Wait for gas modal to be removed from DOM
await gasModal.waitForElementState('hidden');
await driver.clickElement({ text: 'Next', tag: 'button' }); await driver.clickElement({ text: 'Next', tag: 'button' });
// has correct updated value on the confirm screen the transaction // has correct updated value on the confirm screen the transaction

View File

@ -9,13 +9,23 @@ const cssToXPath = require('css-to-xpath');
* @param {Object} element - Selenium Element * @param {Object} element - Selenium Element
* @returns {Object} modified Selenium Element * @returns {Object} modified Selenium Element
*/ */
function wrapElementWithAPI(element) { function wrapElementWithAPI(element, driver) {
element.press = (key) => element.sendKeys(key); element.press = (key) => element.sendKeys(key);
element.fill = async (input) => { element.fill = async (input) => {
// The 'fill' method in playwright replaces existing input // The 'fill' method in playwright replaces existing input
await element.clear(); await element.clear();
await element.sendKeys(input); await element.sendKeys(input);
}; };
element.waitForElementState = async (state, timeout) => {
switch (state) {
case 'hidden':
return await driver.wait(until.stalenessOf(element), timeout);
case 'visible':
return await driver.wait(until.elementIsVisible(element), timeout);
default:
throw new Error(`Provided state: '${state}' is not supported`);
}
};
return element; return element;
} }
@ -127,7 +137,7 @@ class Driver {
timeout, timeout,
); );
} }
return wrapElementWithAPI(element); return wrapElementWithAPI(element, this);
} }
async quit() { async quit() {
@ -142,14 +152,14 @@ class Driver {
until.elementLocated(locator), until.elementLocated(locator),
this.timeout, this.timeout,
); );
return wrapElementWithAPI(element); return wrapElementWithAPI(element, this);
} }
async findVisibleElement(rawLocator) { async findVisibleElement(rawLocator) {
const locator = this.buildLocator(rawLocator); const locator = this.buildLocator(rawLocator);
const element = await this.findElement(locator); const element = await this.findElement(locator);
await this.driver.wait(until.elementIsVisible(element), this.timeout); await this.driver.wait(until.elementIsVisible(element), this.timeout);
return wrapElementWithAPI(element); return wrapElementWithAPI(element, this);
} }
async findClickableElement(rawLocator) { async findClickableElement(rawLocator) {
@ -159,7 +169,7 @@ class Driver {
this.driver.wait(until.elementIsVisible(element), this.timeout), this.driver.wait(until.elementIsVisible(element), this.timeout),
this.driver.wait(until.elementIsEnabled(element), this.timeout), this.driver.wait(until.elementIsEnabled(element), this.timeout),
]); ]);
return wrapElementWithAPI(element); return wrapElementWithAPI(element, this);
} }
async findElements(rawLocator) { async findElements(rawLocator) {
@ -168,7 +178,7 @@ class Driver {
until.elementsLocated(locator), until.elementsLocated(locator),
this.timeout, this.timeout,
); );
return elements.map(wrapElementWithAPI); return elements.map((element) => wrapElementWithAPI(element, this));
} }
async findClickableElements(rawLocator) { async findClickableElements(rawLocator) {
@ -183,7 +193,7 @@ class Driver {
return acc; return acc;
}, []), }, []),
); );
return elements.map(wrapElementWithAPI); return elements.map((element) => wrapElementWithAPI(element, this));
} }
async clickElement(rawLocator) { async clickElement(rawLocator) {