Skip to content

Commit fe28e0d

Browse files
authored
Cleanup beforeunload handler after transaction is resolved (#7333)
* Cleanup beforeunload handler after transaction is resolved The notification window was updated to reject transactions upon close in #6340. A handler that rejects the transaction was added to `window.onbeforeunload`, and it was cleared in `actions.js` if it was confirmed or rejected. However, the `onbeforeunload` handler remained uncleared if the transaction was resolved in another window. This results in the transaction being rejected when the notification window closes, even long after the transaction is submitted and confirmed. This has been the cause of many problems with the Firefox e2e tests. Instead the `onbeforeunload` handler is cleared in the `componentWillUnmount` lifecycle function, alongside where it's set in the first place. This ensures that it's correctly unset regardless of how the transaction was resolved, and it better matches user expectations. * Fix indentation and remove redundant export The `run-all.sh` Bash script now uses consistent indentation, and is consistent about only re-exporting the Ganache arguments when they change. * Ensure transactions are completed before checking balance Various intermittent e2e test failures appear to be caused by React re-rendering the transaction list during the test, as the transaction goes from pending to confirmed. To avoid this race condition, the transaction is now explicitly looked for in the confirmed transaction list in each of the tests using this pattern. * Enable all e2e tests on Firefox The remaining tests that were disabled on Firefox now work correctly. Only a few timing adjustments were needed. * Update Firefox used in CI Firefox v70 is now used on CI instead of v68. This necessitated rewriting the function where the extension ID was obtained because the Firefox extensions page was redesigned.
1 parent 1996598 commit fe28e0d

12 files changed

Lines changed: 96 additions & 123 deletions

File tree

.circleci/scripts/firefox-install

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set -e
44
set -u
55
set -o pipefail
66

7-
FIREFOX_VERSION='68.0'
7+
FIREFOX_VERSION='70.0'
88
FIREFOX_BINARY="firefox-${FIREFOX_VERSION}.tar.bz2"
99
FIREFOX_BINARY_URL="https://ftp.mozilla.org/pub/firefox/releases/${FIREFOX_VERSION}/linux-x86_64/en-US/${FIREFOX_BINARY}"
1010
FIREFOX_PATH='/opt/firefox'

test/e2e/address-book.spec.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -210,13 +210,13 @@ describe('MetaMask', function () {
210210
})
211211

212212
it('finds the transaction in the transactions list', async function () {
213-
const transactions = await findElements(driver, By.css('.transaction-list-item'))
214-
assert.equal(transactions.length, 1)
213+
await driver.wait(async () => {
214+
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
215+
return confirmedTxes.length === 1
216+
}, 10000)
215217

216-
if (process.env.SELENIUM_BROWSER !== 'firefox') {
217-
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
218-
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
219-
}
218+
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
219+
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
220220
})
221221
})
222222

@@ -251,13 +251,13 @@ describe('MetaMask', function () {
251251
})
252252

253253
it('finds the transaction in the transactions list', async function () {
254-
const transactions = await findElements(driver, By.css('.transaction-list-item'))
255-
assert.equal(transactions.length, 2)
254+
await driver.wait(async () => {
255+
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
256+
return confirmedTxes.length === 2
257+
}, 10000)
256258

257-
if (process.env.SELENIUM_BROWSER !== 'firefox') {
258-
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
259-
await driver.wait(until.elementTextMatches(txValues, /-2\s*ETH/), 10000)
260-
}
259+
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
260+
await driver.wait(until.elementTextMatches(txValues, /-2\s*ETH/), 10000)
261261
})
262262
})
263263
})

test/e2e/from-import-ui.spec.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,10 @@ describe('Using MetaMask with an existing account', function () {
226226
})
227227

228228
it('finds the transaction in the transactions list', async function () {
229-
const transactions = await findElements(driver, By.css('.transaction-list-item'))
230-
assert.equal(transactions.length, 1)
229+
await driver.wait(async () => {
230+
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
231+
return confirmedTxes.length === 1
232+
}, 10000)
231233

232234
const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
233235
assert.equal(txValues.length, 1)

test/e2e/func.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ async function getExtensionIdChrome (driver) {
9191

9292
async function getExtensionIdFirefox (driver) {
9393
await driver.get('about:debugging#addons')
94-
const extensionId = await driver.findElement(By.css('dd.addon-target-info-content:nth-child(6) > span:nth-child(1)')).getText()
94+
const extensionId = await driver.wait(webdriver.until.elementLocated(By.xpath('//dl/div[contains(., \'Internal UUID\')]/dd')), 1000).getText()
9595
return extensionId
9696
}
9797

test/e2e/metamask-responsive-ui.spec.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,13 @@ describe('MetaMask', function () {
231231
})
232232

233233
it('finds the transaction in the transactions list', async function () {
234-
const transactions = await findElements(driver, By.css('.transaction-list-item'))
235-
assert.equal(transactions.length, 1)
234+
await driver.wait(async () => {
235+
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
236+
return confirmedTxes.length === 1
237+
}, 10000)
236238

237-
if (process.env.SELENIUM_BROWSER !== 'firefox') {
238-
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
239-
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
240-
}
239+
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
240+
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
241241
})
242242
})
243243
})

test/e2e/metamask-ui.spec.js

Lines changed: 31 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -289,13 +289,13 @@ describe('MetaMask', function () {
289289
})
290290

291291
it('finds the transaction in the transactions list', async function () {
292-
const transactions = await findElements(driver, By.css('.transaction-list-item'))
293-
assert.equal(transactions.length, 1)
292+
await driver.wait(async () => {
293+
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
294+
return confirmedTxes.length === 1
295+
}, 10000)
294296

295-
if (process.env.SELENIUM_BROWSER !== 'firefox') {
296-
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
297-
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
298-
}
297+
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
298+
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
299299
})
300300
})
301301

@@ -332,13 +332,13 @@ describe('MetaMask', function () {
332332
})
333333

334334
it('finds the transaction in the transactions list', async function () {
335-
const transactions = await findElements(driver, By.css('.transaction-list-item'))
336-
assert.equal(transactions.length, 2)
335+
await driver.wait(async () => {
336+
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
337+
return confirmedTxes.length === 2
338+
}, 10000)
337339

338-
if (process.env.SELENIUM_BROWSER !== 'firefox') {
339-
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
340-
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
341-
}
340+
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
341+
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
342342
})
343343
})
344344

@@ -385,13 +385,13 @@ describe('MetaMask', function () {
385385
})
386386

387387
it('finds the transaction in the transactions list', async function () {
388-
const transactions = await findElements(driver, By.css('.transaction-list-item'))
389-
assert.equal(transactions.length, 3)
388+
await driver.wait(async () => {
389+
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
390+
return confirmedTxes.length === 3
391+
}, 10000)
390392

391-
if (process.env.SELENIUM_BROWSER !== 'firefox') {
392-
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
393-
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
394-
}
393+
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
394+
await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
395395
})
396396
})
397397

@@ -838,12 +838,10 @@ describe('MetaMask', function () {
838838
it('renders the correct ETH balance', async () => {
839839
const balance = await findElement(driver, By.css('.transaction-view-balance__primary-balance'))
840840
await delay(regularDelayMs)
841-
if (process.env.SELENIUM_BROWSER !== 'firefox') {
842-
await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/), 10000)
843-
const tokenAmount = await balance.getText()
844-
assert.ok(/^87.*\s*ETH.*$/.test(tokenAmount))
845-
await delay(regularDelayMs)
846-
}
841+
await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/), 10000)
842+
const tokenAmount = await balance.getText()
843+
assert.ok(/^87.*\s*ETH.*$/.test(tokenAmount))
844+
await delay(regularDelayMs)
847845
})
848846
})
849847

@@ -1002,22 +1000,15 @@ describe('MetaMask', function () {
10021000
})
10031001

10041002
it('finds the transaction in the transactions list', async function () {
1005-
const transactions = await findElements(driver, By.css('.transaction-list-item'))
1006-
assert.equal(transactions.length, 1)
1007-
1008-
const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
1009-
assert.equal(txValues.length, 1)
1010-
1011-
// test cancelled on firefox until https://github.com/mozilla/geckodriver/issues/906 is resolved,
1012-
// or possibly until we use latest version of firefox in the tests
1013-
if (process.env.SELENIUM_BROWSER !== 'firefox') {
1014-
await driver.wait(until.elementTextMatches(txValues[0], /-1\s*TST/), 10000)
1015-
}
1016-
10171003
await driver.wait(async () => {
10181004
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
10191005
return confirmedTxes.length === 1
10201006
}, 10000)
1007+
1008+
const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
1009+
assert.equal(txValues.length, 1)
1010+
await driver.wait(until.elementTextMatches(txValues[0], /-1\s*TST/), 10000)
1011+
10211012
const txStatuses = await findElements(driver, By.css('.transaction-list-item__action'))
10221013
await driver.wait(until.elementTextMatches(txStatuses[0], /Sent\sToken/i), 10000)
10231014
})
@@ -1104,7 +1095,6 @@ describe('MetaMask', function () {
11041095
return confirmedTxes.length === 2
11051096
}, 10000)
11061097

1107-
await delay(regularDelayMs)
11081098
const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
11091099
await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/))
11101100
const txStatuses = await findElements(driver, By.css('.transaction-list-item__action'))
@@ -1115,14 +1105,10 @@ describe('MetaMask', function () {
11151105

11161106
const tokenListItems = await findElements(driver, By.css('.token-list-item'))
11171107
await tokenListItems[0].click()
1118-
await delay(regularDelayMs)
1108+
await delay(1000)
11191109

1120-
// test cancelled on firefox until https://github.com/mozilla/geckodriver/issues/906 is resolved,
1121-
// or possibly until we use latest version of firefox in the tests
1122-
if (process.env.SELENIUM_BROWSER !== 'firefox') {
1123-
const tokenBalanceAmount = await findElements(driver, By.css('.transaction-view-balance__primary-balance'))
1124-
await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /7.500\s*TST/), 10000)
1125-
}
1110+
const tokenBalanceAmount = await findElements(driver, By.css('.transaction-view-balance__primary-balance'))
1111+
await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /7.500\s*TST/), 10000)
11261112
})
11271113
})
11281114

@@ -1141,9 +1127,6 @@ describe('MetaMask', function () {
11411127
const transferTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Approve Tokens')]`))
11421128
await transferTokens.click()
11431129

1144-
if (process.env.SELENIUM_BROWSER !== 'firefox') {
1145-
await closeAllWindowHandlesExcept(driver, [extension, dapp])
1146-
}
11471130
await driver.switchTo().window(extension)
11481131
await delay(regularDelayMs)
11491132

@@ -1232,10 +1215,6 @@ describe('MetaMask', function () {
12321215
})
12331216

12341217
it('finds the transaction in the transactions list', async function () {
1235-
if (process.env.SELENIUM_BROWSER === 'firefox') {
1236-
this.skip()
1237-
}
1238-
12391218
await driver.wait(async () => {
12401219
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
12411220
return confirmedTxes.length === 3
@@ -1249,12 +1228,6 @@ describe('MetaMask', function () {
12491228
})
12501229

12511230
describe('Tranfers a custom token from dapp when no gas value is specified', () => {
1252-
before(function () {
1253-
if (process.env.SELENIUM_BROWSER === 'firefox') {
1254-
this.skip()
1255-
}
1256-
})
1257-
12581231
it('transfers an already created token, without specifying gas', async () => {
12591232
const windowHandles = await driver.getAllWindowHandles()
12601233
const extension = windowHandles[0]
@@ -1267,7 +1240,6 @@ describe('MetaMask', function () {
12671240
const transferTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Transfer Tokens Without Gas')]`))
12681241
await transferTokens.click()
12691242

1270-
await closeAllWindowHandlesExcept(driver, [extension, dapp])
12711243
await driver.switchTo().window(extension)
12721244
await delay(regularDelayMs)
12731245

@@ -1304,12 +1276,6 @@ describe('MetaMask', function () {
13041276
})
13051277

13061278
describe('Approves a custom token from dapp when no gas value is specified', () => {
1307-
before(function () {
1308-
if (process.env.SELENIUM_BROWSER === 'firefox') {
1309-
this.skip()
1310-
}
1311-
})
1312-
13131279
it('approves an already created token', async () => {
13141280
const windowHandles = await driver.getAllWindowHandles()
13151281
const extension = windowHandles[0]
@@ -1323,7 +1289,6 @@ describe('MetaMask', function () {
13231289
const transferTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Approve Tokens Without Gas')]`))
13241290
await transferTokens.click()
13251291

1326-
await closeAllWindowHandlesExcept(driver, extension)
13271292
await driver.switchTo().window(extension)
13281293
await delay(regularDelayMs)
13291294

@@ -1346,7 +1311,7 @@ describe('MetaMask', function () {
13461311
})
13471312

13481313
it('submits the transaction', async function () {
1349-
await delay(regularDelayMs)
1314+
await delay(1000)
13501315
const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`))
13511316
await confirmButton.click()
13521317
await delay(regularDelayMs)

test/e2e/run-all.sh

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,20 @@ concurrently --kill-others \
3737
'yarn ganache:start' \
3838
'sleep 5 && mocha test/e2e/from-import-ui.spec'
3939

40-
export GANACHE_ARGS="${BASE_GANACHE_ARGS} --deterministic --account=0x53CB0AB5226EEBF4D872113D98332C1555DC304443BEE1CF759D15798D3C55A9,25000000000000000000"
4140
concurrently --kill-others \
4241
--names 'ganache,e2e' \
4342
--prefix '[{time}][{name}]' \
4443
--success first \
4544
'npm run ganache:start' \
4645
'sleep 5 && mocha test/e2e/send-edit.spec'
4746

48-
49-
concurrently --kill-others \
50-
--names 'ganache,dapp,e2e' \
51-
--prefix '[{time}][{name}]' \
52-
--success first \
53-
'yarn ganache:start' \
54-
'yarn dapp' \
55-
'sleep 5 && mocha test/e2e/ethereum-on.spec'
47+
concurrently --kill-others \
48+
--names 'ganache,dapp,e2e' \
49+
--prefix '[{time}][{name}]' \
50+
--success first \
51+
'yarn ganache:start' \
52+
'yarn dapp' \
53+
'sleep 5 && mocha test/e2e/ethereum-on.spec'
5654

5755
export GANACHE_ARGS="${BASE_GANACHE_ARGS} --deterministic --account=0x250F458997A364988956409A164BA4E16F0F99F916ACDD73ADCD3A1DE30CF8D1,0 --account=0x53CB0AB5226EEBF4D872113D98332C1555DC304443BEE1CF759D15798D3C55A9,25000000000000000000"
5856
concurrently --kill-others \
@@ -73,12 +71,11 @@ concurrently --kill-others \
7371
'sleep 5 && mocha test/e2e/address-book.spec'
7472

7573
export GANACHE_ARGS="${BASE_GANACHE_ARGS} --deterministic --account=0x53CB0AB5226EEBF4D872113D98332C1555DC304443BEE1CF759D15798D3C55A9,25000000000000000000"
76-
concurrently --kill-others \
77-
--names 'ganache,dapp,e2e' \
78-
--prefix '[{time}][{name}]' \
79-
--success first \
80-
'node test/e2e/mock-3box/server.js' \
81-
'yarn ganache:start' \
82-
'yarn dapp' \
83-
'sleep 5 && mocha test/e2e/threebox.spec'
84-
74+
concurrently --kill-others \
75+
--names 'ganache,dapp,e2e' \
76+
--prefix '[{time}][{name}]' \
77+
--success first \
78+
'node test/e2e/mock-3box/server.js' \
79+
'yarn ganache:start' \
80+
'yarn dapp' \
81+
'sleep 5 && mocha test/e2e/threebox.spec'

test/e2e/send-edit.spec.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,10 @@ describe('Using MetaMask with an existing account', function () {
218218
})
219219

220220
it('finds the transaction in the transactions list', async function () {
221-
const transactions = await findElements(driver, By.css('.transaction-list-item'))
222-
assert.equal(transactions.length, 1)
221+
await driver.wait(async () => {
222+
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
223+
return confirmedTxes.length === 1
224+
}, 10000)
223225

224226
const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
225227
assert.equal(txValues.length, 1)

ui/app/components/app/signature-request.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ SignatureRequest.prototype.componentDidMount = function () {
107107
const { clearConfirmTransaction, cancel } = this.props
108108
const { metricsEvent } = this.context
109109
if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION) {
110-
window.onbeforeunload = event => {
110+
this._onBeforeUnload = event => {
111111
metricsEvent({
112112
eventOpts: {
113113
category: 'Transactions',
@@ -118,6 +118,13 @@ SignatureRequest.prototype.componentDidMount = function () {
118118
clearConfirmTransaction()
119119
cancel(event)
120120
}
121+
window.addEventListener('beforeunload', this._onBeforeUnload)
122+
}
123+
}
124+
125+
SignatureRequest.prototype.componentWillUnmount = function () {
126+
if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION) {
127+
window.removeEventListener('beforeunload', this._onBeforeUnload)
121128
}
122129
}
123130

0 commit comments

Comments
 (0)