From 1c2c6c0a745795f78cff49403d1ef64ba072a96d Mon Sep 17 00:00:00 2001 From: No-Cash-7970 Date: Mon, 7 Oct 2024 05:03:34 -0700 Subject: [PATCH] test(e2e): reorganize the page models and a few of the tests --- src/e2e/compose_txn.spec.ts | 3 +- src/e2e/compose_txn_settings.spec.ts | 3 +- src/e2e/flow_single_txn.spec.ts | 137 ++++++++++----------------- src/e2e/home.spec.ts | 6 +- src/e2e/pageModels/index.ts | 7 ++ src/e2e/shared/NodeTestResponses.ts | 40 ++++++++ src/e2e/sign_txn.spec.ts | 3 +- src/e2e/txn_presets.spec.ts | 3 +- 8 files changed, 103 insertions(+), 99 deletions(-) create mode 100644 src/e2e/pageModels/index.ts diff --git a/src/e2e/compose_txn.spec.ts b/src/e2e/compose_txn.spec.ts index 12284916..1b32c806 100644 --- a/src/e2e/compose_txn.spec.ts +++ b/src/e2e/compose_txn.spec.ts @@ -1,7 +1,6 @@ import { test as base, expect } from '@playwright/test'; import { LanguageSupport, NavBarComponent as NavBar } from './shared'; -import { ComposeTxnPage } from './pageModels/ComposeTxnPage'; -import { TxnPresetsPage } from './pageModels/TxnPresetsPage'; +import { ComposeTxnPage, TxnPresetsPage } from './pageModels'; import { usdcAsset } from './shared/NodeTestResponses'; // Extend basic test by providing a "composeTxnPage" fixture. diff --git a/src/e2e/compose_txn_settings.spec.ts b/src/e2e/compose_txn_settings.spec.ts index 89278213..26449d17 100644 --- a/src/e2e/compose_txn_settings.spec.ts +++ b/src/e2e/compose_txn_settings.spec.ts @@ -1,6 +1,5 @@ import { test as base, expect } from '@playwright/test'; -import { ComposeTxnPage } from './pageModels/ComposeTxnPage'; -import { HomePage } from './pageModels/HomePage'; +import { ComposeTxnPage, HomePage } from './pageModels'; // Extend basic test by providing a "composeTxnPage" fixture. // Code adapted from https://playwright.dev/docs/pom diff --git a/src/e2e/flow_single_txn.spec.ts b/src/e2e/flow_single_txn.spec.ts index fe08e77d..fd82de72 100644 --- a/src/e2e/flow_single_txn.spec.ts +++ b/src/e2e/flow_single_txn.spec.ts @@ -1,6 +1,6 @@ import { test as base, expect, type Page } from '@playwright/test'; -import { HomePage } from './pageModels/HomePage'; -import { NodeTestResp } from './shared'; +import { HomePage } from './pageModels'; +import { mockNodeResponses } from './shared/NodeTestResponses'; // Extend basic test by providing a "homePage" fixture. // Code adapted from https://playwright.dev/docs/pom @@ -17,108 +17,73 @@ const test = base.extend<{ homePage: HomePage }>({ test.slow(); // Run through the entire flow of creating and sending a single transaction. -test.describe('Flow from Start to Finish: Single Transaction', () => { - test.skip('is successful', async ({ homePage, page }) => { - await mockNodeResponses(page); +test('Flow from start to finish — Single transaction', async ({ homePage, page }) => { + await mockNodeResponses(page); - /*===== Home page =====*/ + /*===== Home page =====*/ - // Switch node network: MainNet -> TestNet - await page.getByRole('button', { name: 'MainNet' }).click(); - await page.getByText('TestNet', { exact: true }).click(); - await expect(page.getByRole('button', { name: 'TestNet' })).toBeVisible(); + // Switch node network: MainNet -> TestNet + await page.getByRole('button', { name: 'MainNet' }).click(); + await page.getByText('TestNet', { exact: true }).click(); + await expect(page.getByRole('button', { name: 'TestNet' })).toBeVisible(); - // Click start button to go to the transaction-presets page - await homePage.startBtn.click(); + // Click start button to go to the transaction-presets page + await homePage.startBtn.click(); - /*===== Transaction Presets page =====*/ + /*===== Transaction Presets page =====*/ - // Click "Transfer Algos" button to go to the compose-transaction page - await page.getByRole('link', { name: 'Transfer Algos' }).click(); + // Click "Transfer Algos" button to go to the compose-transaction page + await page.getByRole('link', { name: 'Transfer Algos' }).click(); - /*===== Compose Transaction page =====*/ + /*===== Compose Transaction page =====*/ - // Fill out form - await page.getByLabel('Sender*').click(); - await page.getByLabel('Sender*') - .fill('3F3FPW6ZQQYD6JDC7FKKQHNGVVUIBIZOUI5WPSJEHBRABZDRN6LOTBMFEY'); - await page.getByLabel('Receiver*').click(); - await page.getByLabel('Receiver*') - .fill('3F3FPW6ZQQYD6JDC7FKKQHNGVVUIBIZOUI5WPSJEHBRABZDRN6LOTBMFEY'); - await page.getByLabel('Amount*').click(); - await page.getByLabel('Amount*').fill('0'); - // Submit form to got to sign-transaction page - await page.getByRole('button', { name: 'Review & sign' }).click(); + // Fill out form + await page.getByLabel('Sender*').click(); + await page.getByLabel('Sender*') + .fill('3F3FPW6ZQQYD6JDC7FKKQHNGVVUIBIZOUI5WPSJEHBRABZDRN6LOTBMFEY'); + await page.getByLabel('Receiver*').click(); + await page.getByLabel('Receiver*') + .fill('3F3FPW6ZQQYD6JDC7FKKQHNGVVUIBIZOUI5WPSJEHBRABZDRN6LOTBMFEY'); + await page.getByLabel('Amount*').click(); + await page.getByLabel('Amount*').fill('0'); + // Submit form to got to sign-transaction page + await page.getByRole('button', { name: 'Review & sign' }).click(); - /*===== Sign Transaction page =====*/ + /*===== Sign Transaction page =====*/ - // Check if the right data is in table - await checkSignTxnDataTable(page); + // Check if the right data is in table + await checkSignTxnDataTable(page); - // Trigger dialog for connecting wallet - await page.getByRole('button', { name: 'Connect wallet' }).click(); + // Trigger dialog for connecting wallet + await page.getByRole('button', { name: 'Connect wallet' }).click(); - // Choose mnemonic wallet and enter mnemonic - page.on('dialog', dialog => dialog.accept( - // eslint-disable-next-line max-len - 'sugar bronze century excuse animal jacket what rail biology symbol want craft annual soul increase question army win execute slim girl chief exhaust abstract wink' - )); - await page.getByRole('button', { name: 'Use mnemonic' }).click(); + // Choose mnemonic wallet and enter the mnemonic when the prompt appears + page.on('dialog', dialog => dialog.accept( + // eslint-disable-next-line max-len + 'sugar bronze century excuse animal jacket what rail biology symbol want craft annual soul increase question army win execute slim girl chief exhaust abstract wink' + )); + await page.getByRole('button', { name: 'Use mnemonic' }).click(); - // Reload page to check if data and sign button are still there - page.reload(); - await checkSignTxnDataTable(page); - await expect(page.getByRole('button', { name: 'Sign this transaction' })).toBeVisible(); + // Reload page to check if data and sign button are still there + page.reload(); + await checkSignTxnDataTable(page); + await expect(page.getByRole('button', { name: 'Sign this transaction' })).toBeVisible(); - // Sign transaction and go to send page - await page.getByRole('button', { name: 'Sign this transaction' }).click(); + // Sign transaction and go to send page + await page.getByRole('button', { name: 'Sign this transaction' }).click(); - /*===== Sign Transaction page =====*/ + /*===== Sign Transaction page =====*/ - // See if transaction succeeded - await expect(page.getByText('Transaction confirmed!')).toBeVisible(); - await expect(page.getByText('NC63ESPZOQI6P6DSVZWG5K2FJFFKI3VAZITE5KRW5SV5GXQDIXMA')) - .toBeVisible(); + // See if transaction succeeded + await expect(page.getByText('Transaction confirmed!')).toBeVisible(); + await expect(page.getByText('NC63ESPZOQI6P6DSVZWG5K2FJFFKI3VAZITE5KRW5SV5GXQDIXMA')) + .toBeVisible(); - // Click "Done" to go back to home page - await page.getByRole('link', { name: 'Done!' }).click(); - await expect(page).toHaveURL(HomePage.getFullUrl()); - }); + // Click "Done" to go back to home page + await page.getByRole('link', { name: 'Done!' }).click(); + await expect(page).toHaveURL(HomePage.getFullUrl()); }); -/** Mock responses to the Algorand node requests */ -async function mockNodeResponses(page: Page) { - await page.route('*/**/v2/transactions/params', async route => { - await route.fulfill({ body: NodeTestResp.suggParams, contentType: 'application/json' }); - }); - - await page.route('*/**/v2/transactions', async (route, request) => { - if (request.method() === 'OPTIONS') { - await route.fulfill(); - } else { - await route.fulfill({ body: NodeTestResp.sendTxn, contentType: 'application/json' }); - } - }); - - await page.route('*/**/v2/status', async route => { - await route.fulfill({ body: NodeTestResp.nodeStatus, contentType: 'application/json' }); - }); - - let pendingTxnCount = 0; - await page.route('*/**/v2/transactions/pending/*', async route => { - if (pendingTxnCount === 0) { // First time - await route.fulfill({ body: NodeTestResp.pendingTxn1, contentType: 'application/msgpack' }); - pendingTxnCount++; - } else { // Second time - await route.fulfill({ body: NodeTestResp.pendingTxn2, contentType: 'application/msgpack' }); - } - }); - - await page.route('*/**/v2/status/wait-for-block-after/*', async route => { - await route.fulfill({ body: NodeTestResp.waitForBlock, contentType: 'application/json' }); - }); -} - async function checkSignTxnDataTable(page: Page) { await expect(page.getByRole('row', { name: 'Node network' }).getByRole('cell')) .toHaveText('TestNet'); diff --git a/src/e2e/home.spec.ts b/src/e2e/home.spec.ts index 7adad5ed..ea339e42 100644 --- a/src/e2e/home.spec.ts +++ b/src/e2e/home.spec.ts @@ -1,10 +1,6 @@ import { test as base, expect } from '@playwright/test'; import { LanguageSupport, NavBarComponent as NavBar } from './shared'; -import { HomePage } from './pageModels/HomePage'; -import { ComposeTxnPage } from './pageModels/ComposeTxnPage'; -import { TxnPresetsPage } from './pageModels/TxnPresetsPage'; -import { SignTxnPage } from './pageModels/SignTxnPage'; -import { SendTxnPage } from './pageModels/SendTxnPage'; +import { ComposeTxnPage, HomePage, SendTxnPage, SignTxnPage, TxnPresetsPage } from './pageModels'; // Extend basic test by providing a "homePage" fixture. // Code adapted from https://playwright.dev/docs/pom diff --git a/src/e2e/pageModels/index.ts b/src/e2e/pageModels/index.ts new file mode 100644 index 00000000..0b39874e --- /dev/null +++ b/src/e2e/pageModels/index.ts @@ -0,0 +1,7 @@ +export * from './ComposeTxnPage'; +export * from './HomePage'; +export * from './NotFoundPage'; +export * from './PrivacyPolicyPage'; +export * from './SendTxnPage'; +export * from './SignTxnPage'; +export * from './TxnPresetsPage'; diff --git a/src/e2e/shared/NodeTestResponses.ts b/src/e2e/shared/NodeTestResponses.ts index cc8106ca..3f39f23a 100644 --- a/src/e2e/shared/NodeTestResponses.ts +++ b/src/e2e/shared/NodeTestResponses.ts @@ -1,5 +1,6 @@ /** @file Test Algod node responses used to mock responses to requests */ +import { type Page } from "@playwright/test"; import { base64ToBytes, stringifyJSON } from "algosdkv3"; /* NOTE: @@ -106,3 +107,42 @@ export const waitForBlock = stringifyJSON({ "stopped-at-unsupported-round": false, "time-since-last-round": 567756 }); + +/** Mock responses to a series of Algorand node requests for a simple transaction. The mocked + * responses are we actual responses from an Algod node. + * + * Mocking the responses of an Algod node makes the tests more consistent, puts less strain on an + * actual Algod node, and removes the requirement of a real Algod node to be available before + * running the testing. + */ +export async function mockNodeResponses(page: Page) { + await page.route('*/**/v2/transactions/params', async route => { + await route.fulfill({ body: suggParams, contentType: 'application/json' }); + }); + + await page.route('*/**/v2/transactions', async (route, request) => { + if (request.method() === 'OPTIONS') { + await route.fulfill(); + } else { + await route.fulfill({ body: sendTxn, contentType: 'application/json' }); + } + }); + + await page.route('*/**/v2/status', async route => { + await route.fulfill({ body: nodeStatus, contentType: 'application/json' }); + }); + + let pendingTxnCount = 0; + await page.route('*/**/v2/transactions/pending/*', async route => { + if (pendingTxnCount === 0) { // First time + await route.fulfill({ body: pendingTxn1, contentType: 'application/msgpack' }); + pendingTxnCount++; + } else { // Second time + await route.fulfill({ body: pendingTxn2, contentType: 'application/msgpack' }); + } + }); + + await page.route('*/**/v2/status/wait-for-block-after/*', async route => { + await route.fulfill({ body: waitForBlock, contentType: 'application/json' }); + }); +} diff --git a/src/e2e/sign_txn.spec.ts b/src/e2e/sign_txn.spec.ts index f20aec9c..bca7cf97 100644 --- a/src/e2e/sign_txn.spec.ts +++ b/src/e2e/sign_txn.spec.ts @@ -1,7 +1,6 @@ import { test as base, expect } from '@playwright/test'; import { LanguageSupport, NavBarComponent as NavBar } from './shared'; -import { SignTxnPage } from './pageModels/SignTxnPage'; -import { ComposeTxnPage } from './pageModels/ComposeTxnPage'; +import { ComposeTxnPage, SignTxnPage } from './pageModels'; // Extend basic test by providing a "signTxnPage" fixture. // Code adapted from https://playwright.dev/docs/pom diff --git a/src/e2e/txn_presets.spec.ts b/src/e2e/txn_presets.spec.ts index 33813486..96a50127 100644 --- a/src/e2e/txn_presets.spec.ts +++ b/src/e2e/txn_presets.spec.ts @@ -1,6 +1,5 @@ import { test as base, expect } from '@playwright/test'; -import { NavBarComponent as NavBar } from './shared/NavBarComponent'; -import { LanguageSupport } from './shared/LanguageSupport'; +import { LanguageSupport, NavBarComponent as NavBar } from './shared'; import { TxnPresetsPage } from './pageModels/TxnPresetsPage'; // Extend basic test by providing a "txnPresetsPage" fixture.