From 03732af6f4696ee13dc8b98d8c9e8b8f344f96b9 Mon Sep 17 00:00:00 2001 From: Davide Brocchetto Date: Tue, 7 Mar 2023 16:51:15 +0100 Subject: [PATCH] Added e2e swap test and fixed mocked API (#17934) * Added test for submitting second swap without waiting for first one to finish * Added more test code * Removed look around Review Swap button * Added test verification for the transaction details * Changed mocked API for token import * Added assert error messages * Fixed lint errors * Removed empty lines and improved coding consistency * Removed empty lines --- test/e2e/mock-e2e.js | 4 +- test/e2e/swaps/shared.js | 131 ++++++++++++++++++--- test/e2e/swaps/swap-eth.spec.js | 113 +++++++++++------- test/e2e/swaps/swaps-notifications.spec.js | 8 +- 4 files changed, 191 insertions(+), 65 deletions(-) diff --git a/test/e2e/mock-e2e.js b/test/e2e/mock-e2e.js index e6da0333d..9213a6e5b 100644 --- a/test/e2e/mock-e2e.js +++ b/test/e2e/mock-e2e.js @@ -332,10 +332,10 @@ async function setupMocking(server, testSpecificMock) { }; }); - // It disables loading of token icons, e.g. this URL: https://static.metaswap.codefi.network/api/v1/tokenIcons/1337/0x0000000000000000000000000000000000000000.png + // It disables loading of token icons, e.g. this URL: https://static.metafi.codefi.network/api/v1/tokenIcons/1337/0x0000000000000000000000000000000000000000.png await server .forGet( - /^https:\/\/static\.metaswap\.codefi\.network\/api\/v1\/tokenIcons\/1337\/.*\.png/u, + /^https:\/\/static\.metafi\.codefi\.network\/api\/v1\/tokenIcons\/1337\/.*\.png/u, ) .thenCallback(() => { return { diff --git a/test/e2e/swaps/shared.js b/test/e2e/swaps/shared.js index 4a2d4d124..f6cb920a5 100644 --- a/test/e2e/swaps/shared.js +++ b/test/e2e/swaps/shared.js @@ -1,5 +1,6 @@ +const { strict: assert } = require('assert'); const FixtureBuilder = require('../fixture-builder'); -const { veryLargeDelayMs } = require('../helpers'); +const { regularDelayMs, veryLargeDelayMs } = require('../helpers'); const ganacheOptions = { accounts: [ @@ -16,32 +17,27 @@ const withFixturesOptions = { ganacheOptions, }; -const loadSwaps = async (driver) => { +const loadExtension = async (driver) => { await driver.navigate(); await driver.fill('#password', 'correct horse battery staple'); await driver.press('#password', driver.Key.ENTER); - await driver.clickElement( - '.wallet-overview__buttons .icon-button:nth-child(3)', - ); }; const buildQuote = async (driver, options) => { + await driver.clickElement( + '.wallet-overview__buttons .icon-button:nth-child(3)', + ); await driver.fill('input[placeholder*="0"]', options.amount); await driver.delay(veryLargeDelayMs); // Need an extra delay after typing an amount. - await driver.clickElement( - '[class="dropdown-search-list__closed-primary-label dropdown-search-list__select-default"]', + await driver.waitForSelector( + '[class="dropdown-input-pair dropdown-input-pair__to"]', ); - await driver.wait(async () => { - const tokens = await driver.findElements('.searchable-item-list__item'); - return tokens.length > 1; - }); - await driver.clickElement('.searchable-item-list__labels'); await driver.clickElement('.dropdown-input-pair__to'); - await driver.clickElement('input[data-testid="search-list-items"]'); await driver.fill( 'input[data-testid="search-list-items"]', options.swapTo || options.swapToContractAddress, ); + await driver.delay(veryLargeDelayMs); // Need an extra delay after typing an amount. if (options.swapTo) { await driver.wait(async () => { const tokenNames = await driver.findElements( @@ -63,8 +59,115 @@ const buildQuote = async (driver, options) => { await driver.clickElement('.searchable-item-list__primary-label'); }; +const reviewQuote = async (driver, options) => { + await driver.clickElement({ text: 'Review swap', tag: 'button' }); + await driver.waitForSelector({ text: 'Swap', tag: 'button' }); + await driver.waitForSelector({ + css: '[class*="box--align-items-center"]', + text: 'Estimated gas fee', + }); + const sourceValue = await driver.waitForSelector( + '.main-quote-summary__source-row-value', + ); + assert.equal( + await sourceValue.getText(), + options.amount, + 'Error: Quote has wrong amount', + ); + const sourceSymbol = await driver.waitForSelector( + '.main-quote-summary__source-row-symbol', + ); + assert.equal( + await sourceSymbol.getText(), + options.swapFrom, + 'Error: SwapFrom has wrong symbol', + ); + const swapToSymbol = await driver.waitForSelector( + '.main-quote-summary__destination-row', + ); + assert.equal( + await swapToSymbol.getText(), + options.swapTo, + 'Error: SwapTo has wrong symbol', + ); + await driver.waitForSelector( + '[class="exchange-rate-display main-quote-summary__exchange-rate-display"]', + ); + await driver.waitForSelector('[class="fee-card__info-tooltip-container"]'); + await driver.waitForSelector({ + css: '[class="countdown-timer__time"]', + text: '0:23', + }); +}; + +const waitForTransactionToComplete = async (driver, tokenName) => { + const sucessfulTransactionMessage = await driver.waitForSelector( + { + css: '[class="awaiting-swap__header"]', + text: 'Transaction complete', + }, + { timeout: 30000 }, + ); + assert.equal( + await sucessfulTransactionMessage.getText(), + 'Transaction complete', + 'Incorrect transaction message', + ); + const sucessfulTransactionToken = await driver.waitForSelector({ + css: '[class="awaiting-swap__amount-and-symbol"]', + text: tokenName, + }); + assert.equal( + await sucessfulTransactionToken.getText(), + tokenName, + 'Incorrect token name', + ); + await driver.clickElement({ text: 'Close', tag: 'button' }); + await driver.waitForSelector('[data-testid="home__asset-tab"]'); +}; + +const checkActivityTransaction = async (driver, options) => { + await driver.clickElement('[data-testid="home__activity-tab"]'); + const itemsText = await driver.findElements('.list-item__title'); + assert.equal( + await itemsText[options.index].getText(), + `Swap ${options.swapFrom} to ${options.swapTo}`, + 'Title is incorrect', + ); + const amountValues = await driver.findElements( + '.transaction-list-item__primary-currency', + ); + assert.equal( + await amountValues[options.index].getText(), + `-${options.amount} ${options.swapFrom}`, + 'Transaction amount is incorrect', + ); + await itemsText[options.index].click(); + await driver.delay(regularDelayMs); + const txStatus = await driver.findElement( + '.transaction-list-item-details__tx-status >div > div:last-child', + ); + assert.equal( + await txStatus.getText(), + `Confirmed`, + `Transaction status is not 'Confirmed'`, + ); + const txAmount = await driver.findElement( + '.transaction-breakdown__value--amount', + ); + assert.equal( + await txAmount.getText(), + `-${options.amount} ${options.swapFrom}`, + 'Transaction breakdown is incorrect', + ); + await driver.clickElement('[data-testid="popover-close"]'); +}; + module.exports = { withFixturesOptions, - loadSwaps, + loadExtension, buildQuote, + reviewQuote, + waitForTransactionToComplete, + checkActivityTransaction, }; diff --git a/test/e2e/swaps/swap-eth.spec.js b/test/e2e/swaps/swap-eth.spec.js index d67c258d8..6506fa262 100644 --- a/test/e2e/swaps/swap-eth.spec.js +++ b/test/e2e/swaps/swap-eth.spec.js @@ -1,64 +1,87 @@ -const { strict: assert } = require('assert'); - const { withFixtures } = require('../helpers'); -const { withFixturesOptions, loadSwaps, buildQuote } = require('./shared'); +const { + withFixturesOptions, + loadExtension, + buildQuote, + reviewQuote, + waitForTransactionToComplete, + checkActivityTransaction, +} = require('./shared'); describe('Swap Eth for another Token', function () { - it('Completes a Swap between Eth and Matic', async function () { + it('Completes second Swaps while first swap is processing', async function () { + withFixturesOptions.ganacheOptions.blockTime = 10; + + await withFixtures( + { + ...withFixturesOptions, + failOnConsoleError: false, + title: this.test.title, + }, + async ({ driver }) => { + await loadExtension(driver); + await buildQuote(driver, { + amount: 0.001, + swapTo: 'USDC', + }); + await reviewQuote(driver, { + amount: '0.001', + swapFrom: 'TESTETH', + swapTo: 'USDC', + }); + await driver.clickElement({ text: 'Swap', tag: 'button' }); + await driver.clickElement({ text: 'View in activity', tag: 'button' }); + await buildQuote(driver, { + amount: 0.003, + swapTo: 'DAI', + }); + await reviewQuote(driver, { + amount: '0.003', + swapFrom: 'TESTETH', + swapTo: 'DAI', + }); + await driver.clickElement({ text: 'Swap', tag: 'button' }); + await waitForTransactionToComplete(driver, 'DAI'); + await checkActivityTransaction(driver, { + index: 0, + amount: '0.003', + swapFrom: 'TESTETH', + swapTo: 'DAI', + }); + await checkActivityTransaction(driver, { + index: 1, + amount: '0.001', + swapFrom: 'TESTETH', + swapTo: 'USDC', + }); + }, + ); + }); + it('Completes a Swap between Eth and Dai', async function () { await withFixtures( { ...withFixturesOptions, title: this.test.title, }, async ({ driver }) => { - await loadSwaps(driver); + await loadExtension(driver); await buildQuote(driver, { amount: 2, swapTo: 'DAI', }); - await driver.clickElement({ text: 'Review swap', tag: 'button' }); - await driver.waitForSelector('[class*="box--align-items-center"]'); - const estimatedEth = await driver.waitForSelector({ - css: '[class*="box--align-items-center"]', - text: 'Estimated gas fee', - }); - assert.equal(await estimatedEth.getText(), 'Estimated gas fee'); - await driver.waitForSelector( - '[class="exchange-rate-display main-quote-summary__exchange-rate-display"]', - ); - await driver.waitForSelector( - '[class="fee-card__info-tooltip-container"]', - ); - await driver.waitForSelector({ - css: '[class="countdown-timer__time"]', - text: '0:24', + await reviewQuote(driver, { + amount: '2', + swapFrom: 'TESTETH', + swapTo: 'DAI', }); await driver.clickElement({ text: 'Swap', tag: 'button' }); - const sucessfulTransactionMessage = await driver.waitForSelector({ - css: '[class="awaiting-swap__header"]', - text: 'Transaction complete', + await waitForTransactionToComplete(driver, 'DAI'); + await checkActivityTransaction(driver, { + index: 0, + amount: '2', + swapFrom: 'TESTETH', + swapTo: 'DAI', }); - assert.equal( - await sucessfulTransactionMessage.getText(), - 'Transaction complete', - ); - const sucessfulTransactionToken = await driver.waitForSelector({ - css: '[class="awaiting-swap__amount-and-symbol"]', - text: 'DAI', - }); - assert.equal(await sucessfulTransactionToken.getText(), 'DAI'); - await driver.clickElement({ text: 'Close', tag: 'button' }); - await driver.clickElement('[data-testid="home__activity-tab"]'); - const swaptotal = await driver.waitForSelector({ - css: '[class="transaction-list-item__primary-currency"]', - text: '-2 TESTETH', - }); - assert.equal(await swaptotal.getText(), '-2 TESTETH'); - const swaptotaltext = await driver.waitForSelector({ - css: '[class="list-item__title"]', - text: 'Swap TESTETH to DAI', - }); - assert.equal(await swaptotaltext.getText(), 'Swap TESTETH to DAI'); }, ); }); diff --git a/test/e2e/swaps/swaps-notifications.spec.js b/test/e2e/swaps/swaps-notifications.spec.js index 0158b599b..02bfe43dd 100644 --- a/test/e2e/swaps/swaps-notifications.spec.js +++ b/test/e2e/swaps/swaps-notifications.spec.js @@ -2,7 +2,7 @@ const { strict: assert } = require('assert'); const { withFixtures } = require('../helpers'); -const { withFixturesOptions, loadSwaps, buildQuote } = require('./shared'); +const { withFixturesOptions, loadExtension, buildQuote } = require('./shared'); describe('Swaps - notifications', function () { async function mockTradesApiPriceSlippageError(mockServer) { @@ -60,7 +60,7 @@ describe('Swaps - notifications', function () { title: this.test.title, }, async ({ driver }) => { - await loadSwaps(driver); + await loadExtension(driver); await buildQuote(driver, { amount: 2, swapTo: 'INUINU', @@ -99,7 +99,7 @@ describe('Swaps - notifications', function () { title: this.test.title, }, async ({ driver }) => { - await loadSwaps(driver); + await loadExtension(driver); await buildQuote(driver, { amount: 50, swapTo: 'USDC', @@ -134,7 +134,7 @@ describe('Swaps - notifications', function () { title: this.test.title, }, async ({ driver }) => { - await loadSwaps(driver); + await loadExtension(driver); await buildQuote(driver, { amount: 2, swapToContractAddress: '0x72c9Fb7ED19D3ce51cea5C56B3e023cd918baaDf',