Skip to content

Commit

Permalink
Add confirmMetamaskTransactionAndWaitForMining
Browse files Browse the repository at this point in the history
  • Loading branch information
duckception committed Sep 7, 2023
1 parent 96db944 commit a3f8fcc
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 0 deletions.
65 changes: 65 additions & 0 deletions commands/metamask.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const log = require('debug')('synpress:metamask');
const playwright = require('./playwright');
const sleep = require('util').promisify(setTimeout);

const {
onboardingWelcomePageElements,
Expand Down Expand Up @@ -1180,6 +1181,70 @@ const metamask = {
log('[confirmTransaction] Transaction confirmed!');
return txData;
},
async confirmTransactionAndWaitForMining(gasConfig) {
// Before we switch to MetaMask tab we have to make sure the notification window has opened.
//
// Chaining `confirmTransactionAndWaitForMining` results in quick tabs switching
// which breaks MetaMask and the notification window does not open
// until we switch back to the "Cypress" tab.
await playwright.switchToMetamaskNotification();

await switchToMetamaskIfNotActive();
await playwright
.metamaskWindow()
.locator(mainPageElements.tabs.activityButton)
.click();

let retries = 0;
const retiresLimit = 600;

// 120 seconds
while (retries < retiresLimit) {
const unapprovedTxs = await playwright
.metamaskWindow()
.getByText('Unapproved')
.count();
if (unapprovedTxs === 1) {
break;
}
await sleep(200);
retries++;
}

if (retries === retiresLimit) {
throw new Error(
'New unapproved transaction was not detected in 120 seconds.',
);
}

const txData = await module.exports.confirmTransaction(gasConfig);

// 120 seconds
while (retries < retiresLimit) {
const pendingTxs = await playwright // TODO rename
.metamaskWindow()
.getByText('Pending')
.count();
const queuedTxs = await playwright // TODO rename
.metamaskWindow()
.getByText('Queued')
.count();
if (pendingTxs === 0 && queuedTxs === 0) {
break;
}
await sleep(200);
retries++;
}

if (retries === retiresLimit) {
throw new Error('Transaction was not mined in 120 seconds.');
}

await switchToCypressIfNotActive();

log('[confirmTransactionAndWaitForMining] Transaction confirmed!');
return txData;
},
async rejectTransaction() {
const notificationPage = await playwright.switchToMetamaskNotification();
await playwright.waitAndClick(
Expand Down
8 changes: 8 additions & 0 deletions docs/synpress-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,14 @@ Confirm metamask transaction (auto-detects eip-1559 and legacy transactions).
confirmMetamaskTransaction(gasConfig?: object | string): Chainable<Subject>;
```

#### `cy.confirmMetamaskTransactionAndWaitForMining()`

Confirm metamask transaction (auto-detects eip-1559 and legacy transactions) and wait for ALL pending transactions to be mined.

```ts
confirmMetamaskTransactionAndWaitForMining(gasConfig?: object | string): Chainable<Subject>;
```

#### `cy.rejectMetamaskTransaction()`

Reject metamask transaction.
Expand Down
2 changes: 2 additions & 0 deletions plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ module.exports = (on, config) => {
acceptMetamaskAccess: metamask.acceptAccess,
rejectMetamaskAccess: metamask.rejectAccess,
confirmMetamaskTransaction: metamask.confirmTransaction,
confirmMetamaskTransactionAndWaitForMining:
metamask.confirmTransactionAndWaitForMining,
rejectMetamaskTransaction: metamask.rejectTransaction,
allowMetamaskToAddNetwork: async ({ waitForEvent }) =>
await metamask.allowToAddNetwork({ waitForEvent }),
Expand Down
7 changes: 7 additions & 0 deletions support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,13 @@ Cypress.Commands.add('confirmMetamaskTransaction', gasConfig => {
return cy.task('confirmMetamaskTransaction', gasConfig);
});

Cypress.Commands.add(
'confirmMetamaskTransactionAndWaitForMining',
gasConfig => {
return cy.task('confirmMetamaskTransactionAndWaitForMining', gasConfig);
},
);

Cypress.Commands.add('rejectMetamaskTransaction', () => {
return cy.task('rejectMetamaskTransaction');
});
Expand Down
24 changes: 24 additions & 0 deletions support/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,30 @@ declare namespace Cypress {
| 'aggressive'
| 'site',
): Chainable<Subject>;
/**
* Confirm metamask transaction (auto-detects eip-1559 and legacy transactions) and wait for ALL pending transactions to be mined
* @example
* cy.confirmMetamaskTransactionAndWaitForMining()
* cy.confirmMetamaskTransactionAndWaitForMining({ gasLimit: 1000000, baseFee: 20, priorityFee: 20 }) // eip-1559
* cy.confirmMetamaskTransactionAndWaitForMining({ gasLimit: 1000000, gasPrice: 20 }) // legacy
* cy.confirmMetamaskTransactionAndWaitForMining('aggressive') // eip-1559 only! => available options: 'low', 'market', 'aggressive', 'site' (site is usually by default)
*/
confirmMetamaskTransactionAndWaitForMining(
gasConfig?:
| {
gasLimit?: number;
baseFee?: number;
priorityFee?: number;
}
| {
gasLimit?: number;
gasPrice?: number;
}
| 'low'
| 'market'
| 'aggressive'
| 'site',
): Chainable<Subject>;
/**
* Reject metamask transaction
* @example
Expand Down
36 changes: 36 additions & 0 deletions tests/e2e/specs/metamask-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,42 @@ describe('Metamask', () => {
expect(txData.confirmed).to.be.true;
});
});
it(`confirmMetamaskTransactionAndWaitForMining should confirm legacy transaction and wait for it to be mined`, () => {
cy.get('#sendButton').click();
cy.confirmMetamaskTransactionAndWaitForMining().then(txData => {
expect(txData.recipientPublicAddress).to.be.not.empty;
expect(txData.networkName).to.be.not.empty;
expect(txData.customNonce).to.be.not.empty;
expect(txData.confirmed).to.be.true;
});
});
it(`confirmMetamaskTransactionAndWaitForMining should confirm eip-1559 transaction and wait for it to be mined`, () => {
cy.get('#sendEIP1559Button').click();
cy.confirmMetamaskTransactionAndWaitForMining().then(txData => {
expect(txData.recipientPublicAddress).to.be.not.empty;
expect(txData.networkName).to.be.not.empty;
expect(txData.customNonce).to.be.not.empty;
expect(txData.confirmed).to.be.true;
});
});
it(`chaining confirmMetamaskTransactionAndWaitForMining should work as expected`, () => {
cy.get('#sendEIP1559Button').click();
cy.confirmMetamaskTransactionAndWaitForMining().then(txData => {
expect(txData.confirmed).to.be.true;
});
cy.get('#sendEIP1559Button').click();
cy.confirmMetamaskTransactionAndWaitForMining().then(txData => {
expect(txData.confirmed).to.be.true;
});
cy.get('#sendEIP1559Button').click();
cy.confirmMetamaskTransactionAndWaitForMining().then(txData => {
expect(txData.confirmed).to.be.true;
});
cy.get('#sendEIP1559Button').click();
cy.confirmMetamaskTransactionAndWaitForMining().then(txData => {
expect(txData.confirmed).to.be.true;
});
});
it(`confirmMetamaskTransaction should confirm transaction for token creation (contract deployment) and check tx data`, () => {
cy.get('#createToken').click();
cy.confirmMetamaskTransaction().then(txData => {
Expand Down

0 comments on commit a3f8fcc

Please sign in to comment.