From a6250403f08b277b1ef177d17c6f035e25405bec Mon Sep 17 00:00:00 2001 From: wafflesvsfrankie <92288602+burtonemily@users.noreply.github.com> Date: Thu, 8 May 2025 15:20:29 +1000 Subject: [PATCH 1/3] Creates tests for new network page feature --- playwright.config.ts | 3 +- tests/automation/input_validations.spec.ts | 1 - tests/automation/landing_page.spec.ts | 1 + tests/automation/network_page.spec.ts | 144 ++++++++++++++++++ tests/automation/setup/new_user.ts | 1 + tests/automation/setup/open.ts | 2 + tests/automation/setup/recovery_using_seed.ts | 15 +- tests/automation/setup/sessionTest.ts | 24 +++ tests/automation/types/testing.ts | 9 +- tests/automation/utilities/utils.ts | 2 +- 10 files changed, 195 insertions(+), 7 deletions(-) create mode 100644 tests/automation/network_page.spec.ts diff --git a/playwright.config.ts b/playwright.config.ts index 915bfae..a89cc29 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -23,5 +23,6 @@ export default defineConfig({ reportSlowTests: null, fullyParallel: true, // otherwise, tests in the same file are not run in parallel globalSetup: './global.setup', // clean leftovers of previous test runs on start, runs only once - snapshotPathTemplate: screenshotFolder + '/{testName}/{arg}-{platform}{ext}', + // eslint-disable-next-line prefer-template + snapshotPathTemplate: screenshotFolder + '/{testName}/{arg}-{platform}{text}', }); diff --git a/tests/automation/input_validations.spec.ts b/tests/automation/input_validations.spec.ts index 80569f0..d33c584 100644 --- a/tests/automation/input_validations.spec.ts +++ b/tests/automation/input_validations.spec.ts @@ -55,7 +55,6 @@ import { [ { testName: 'No name', - // This currently fails - displays wrong error message displayName: ' ', expectedError: englishStrippedStr('displayNameErrorDescription').toString(), }, diff --git a/tests/automation/landing_page.spec.ts b/tests/automation/landing_page.spec.ts index b1ac53e..5083534 100644 --- a/tests/automation/landing_page.spec.ts +++ b/tests/automation/landing_page.spec.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line import/no-cycle import { test_Alice_2W } from './setup/sessionTest'; import { compareScreenshot, waitForElement } from './utilities/utils'; diff --git a/tests/automation/network_page.spec.ts b/tests/automation/network_page.spec.ts new file mode 100644 index 0000000..ee575ce --- /dev/null +++ b/tests/automation/network_page.spec.ts @@ -0,0 +1,144 @@ +import { englishStrippedStr } from '../locale/localizedString'; +import { sleepFor } from '../promise_utils'; +import { recoverFromSeed } from './setup/recovery_using_seed'; +import { sessionTestOneWindow, test_Alice_1W } from './setup/sessionTest'; +import { User } from './types/testing'; +import { + checkModalStrings, + clickOnTestIdWithText, + doesElementExist, + grabTextFromElement, + typeIntoInput, + waitForElement, + waitForLoadingAnimationToFinish, + waitForTestIdWithText, +} from './utilities/utils'; + +/* Waiting for test id to be fixed +// Links to test are: +- Learn more Network link +- Learn more staking link +- How to create wallet link +*/ + +test_Alice_1W('Learn more network link', async ({ aliceWindow1 }) => { + await clickOnTestIdWithText(aliceWindow1, 'settings-section'); + await clickOnTestIdWithText( + aliceWindow1, + 'session-network-settings-menu-item', + ); + await waitForLoadingAnimationToFinish(aliceWindow1, 'loading-spinner'); + await clickOnTestIdWithText(aliceWindow1, 'learn-more-network-link'); + await checkModalStrings( + aliceWindow1, + englishStrippedStr('urlOpen').toString(), + englishStrippedStr('urlOpenDescription').toString(), + ); + const el = await waitForElement( + aliceWindow1, + 'data-testid', + 'open-url-confirm-button', + ); + const href = await el.getAttribute('href'); + console.log('href', href); +}); + +sessionTestOneWindow('No token bonus', async ([window]) => { + const userA: User = { + userName: 'Alice', + accountid: + '666016369d70fa182d981e257d49fbdad6b71070a31114c8db8f13f4e110db7c', + recoveryPassword: + 'initiate doorway obliged pancakes huddle omega vexed regular antics impel sonic gorilla initiate', + }; + await recoverFromSeed(window, userA.recoveryPassword, true); + await clickOnTestIdWithText(window, 'settings-section'); + await clickOnTestIdWithText(window, 'session-network-settings-menu-item'); + await waitForLoadingAnimationToFinish(window, 'loading-spinner'); + // Need to wait for page to load + await sleepFor(1000); + await doesElementExist(window, 'data-testid', 'token-bonus-amount'); +}); + +sessionTestOneWindow('Token bonus matches', async ([window]) => { + const userA: User = { + userName: 'Alice', + accountid: + 'cafe7498de7c43aa528551392a9b573ac4154ec9db455652d01cddd48e345a22', + recoveryPassword: + 'pirate pancakes lunar jabbed serving cake greater textbook icon items roles ouch pirate', + }; + const expectedTokenAmount = '125'; + await recoverFromSeed(window, userA.recoveryPassword, true); + await clickOnTestIdWithText(window, 'settings-section'); + await clickOnTestIdWithText(window, 'session-network-settings-menu-item'); + await waitForLoadingAnimationToFinish(window, 'loading-spinner'); + const actualTokenAmount = await grabTextFromElement( + window, + 'data-testid', + 'token-bonus-amount', + ); + if (actualTokenAmount !== expectedTokenAmount) { + throw new Error( + `Expected token amount: ${expectedTokenAmount}, but got: ${actualTokenAmount}`, + ); + } +}); + +sessionTestOneWindow('Invalid checksum', async ([window]) => { + const userA: User = { + userName: 'Alice', + accountid: + 'cafe7498de7c43aa528551392a9b573ac4154ec9db455652d01cddd48e345a22', + recoveryPassword: + 'pirate pancakes lunar jabbed serving cake greater textbook icon items roles ouch pirate', + }; + const invalidAddress = '0x8282A0293DB7487C09Ca145Ace9bb23c345EaeD6'; + // TODO Add string in once crowdin has been updated + // const expectedError = englishStrippedStr('sessionNetworkWalletAddressError').toString(); + const expectedError = + 'You have submitted an invalid Ethereum wallet address. Please check and try again.'; + await recoverFromSeed(window, userA.recoveryPassword, true); + await clickOnTestIdWithText(window, 'settings-section'); + await clickOnTestIdWithText(window, 'session-network-settings-menu-item'); + await waitForLoadingAnimationToFinish(window, 'loading-spinner'); + await clickOnTestIdWithText(window, 'token-claim-button'); + await typeIntoInput(window, 'wallet-address-input', invalidAddress); + await clickOnTestIdWithText(window, 'submit-button'); + await waitForTestIdWithText(window, 'session-error-message'); + const returnedError = await grabTextFromElement( + window, + 'data-testid', + 'session-error-message', + ); + if (returnedError !== expectedError) { + throw new Error( + `Expected error message: ${expectedError}, but got: ${returnedError}`, + ); + } +}); + +test_Alice_1W('Refreshing page works', async ({ aliceWindow1 }) => { + // TODO Add string in once crowdin has been updated + // const expectedText = englishStrippedStr('updated') + // .withArgs({ relative_time: '0m' }) + // .toString(); + const expectedText = 'Last updated 0m ago'; + await clickOnTestIdWithText(aliceWindow1, 'settings-section'); + await clickOnTestIdWithText( + aliceWindow1, + 'session-network-settings-menu-item', + ); + await waitForLoadingAnimationToFinish(aliceWindow1, 'loading-spinner'); + await clickOnTestIdWithText(aliceWindow1, 'refresh-button'); + await waitForLoadingAnimationToFinish(aliceWindow1, 'loading-spinner'); + await waitForTestIdWithText(aliceWindow1, 'last-updated-timestamp'); + const returnedText = await grabTextFromElement( + aliceWindow1, + 'data-testid', + 'last-updated-timestamp', + ); + if (returnedText !== expectedText) { + throw new Error(`Expected text: ${expectedText}, but got: ${returnedText}`); + } +}); diff --git a/tests/automation/setup/new_user.ts b/tests/automation/setup/new_user.ts index 3ebaa8d..5670a5b 100644 --- a/tests/automation/setup/new_user.ts +++ b/tests/automation/setup/new_user.ts @@ -1,6 +1,7 @@ import { Page } from '@playwright/test'; import chalk from 'chalk'; import { User } from '../types/testing'; +// eslint-disable-next-line import/no-cycle import { checkPathLight, clickOnTestIdWithText, diff --git a/tests/automation/setup/open.ts b/tests/automation/setup/open.ts index 7431a2f..5a00d2d 100644 --- a/tests/automation/setup/open.ts +++ b/tests/automation/setup/open.ts @@ -4,7 +4,9 @@ import chalk from 'chalk'; import { isEmpty } from 'lodash'; import { join } from 'path'; import { v4 } from 'uuid'; +import dotenv from 'dotenv'; +dotenv.config(); export const NODE_ENV = 'production'; export const MULTI_PREFIX = 'test-integration-'; const multisAvailable = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; diff --git a/tests/automation/setup/recovery_using_seed.ts b/tests/automation/setup/recovery_using_seed.ts index 50b95b9..3f66750 100644 --- a/tests/automation/setup/recovery_using_seed.ts +++ b/tests/automation/setup/recovery_using_seed.ts @@ -1,4 +1,5 @@ import { Page } from '@playwright/test'; +// eslint-disable-next-line import/no-cycle import { clickOnTestIdWithText, doesElementExist, @@ -6,7 +7,11 @@ import { waitForLoadingAnimationToFinish, } from '../utilities/utils'; -export async function recoverFromSeed(window: Page, recoveryPhrase: string) { +export async function recoverFromSeed( + window: Page, + recoveryPhrase: string, + createDisplayName?: boolean, +) { await clickOnTestIdWithText(window, 'existing-account-button'); await typeIntoInput(window, 'recovery-phrase-input', recoveryPhrase); await clickOnTestIdWithText(window, 'continue-button'); @@ -17,8 +22,12 @@ export async function recoverFromSeed(window: Page, recoveryPhrase: string) { 'display-name-input', ); if (displayName) { - throw new Error(`Display name was not found when restoring from seed`); + if (createDisplayName) { + await typeIntoInput(window, 'display-name-input', 'Alice'); + await clickOnTestIdWithText(window, 'continue-button'); + } else { + throw new Error(`Display name was not found when restoring from seed`); + } } - return { window }; } diff --git a/tests/automation/setup/sessionTest.ts b/tests/automation/setup/sessionTest.ts index ab701e2..a7517de 100644 --- a/tests/automation/setup/sessionTest.ts +++ b/tests/automation/setup/sessionTest.ts @@ -4,6 +4,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { Page, TestInfo, test } from '@playwright/test'; import { Group, User } from '../types/testing'; +// eslint-disable-next-line import/no-cycle import { linkedDevice } from '../utilities/linked_device'; import { forceCloseAllWindows } from './closeWindows'; import { createGroup } from './create_group'; @@ -222,6 +223,29 @@ export function test_Alice_1W_no_network( }, ); } +// Need a test for one window with network, mainly for Network Page +export function test_Alice_1W( + testname: string, + testCallback: ( + details: WithAlice & WithAliceWindow1, + testInfo: TestInfo, + ) => Promise, +) { + return sessionTestGeneric( + testname, + 1, + { waitForNetwork: true }, + ({ mainWindows, users }, testInfo) => { + return testCallback( + { + alice: users[0], + aliceWindow1: mainWindows[0], + }, + testInfo, + ); + }, + ); +} /** * Setup the test with 1 user and 2 windows total: diff --git a/tests/automation/types/testing.ts b/tests/automation/types/testing.ts index 86ecd47..b4238d7 100644 --- a/tests/automation/types/testing.ts +++ b/tests/automation/types/testing.ts @@ -191,4 +191,11 @@ export type DataTestId = | 'error-message' | 'group-members' | 'session-confirm-cancel-button' - | 'session-recovery-password'; + | 'session-recovery-password' + | 'session-network-settings-menu-item' + | 'learn-more-network-link' + | 'token-claim-button' + | 'wallet-address-input' + | 'submit-button' + | 'refresh-button' + | 'last-updated-timestamp'; diff --git a/tests/automation/utilities/utils.ts b/tests/automation/utilities/utils.ts index 4658f88..d7dd51d 100644 --- a/tests/automation/utilities/utils.ts +++ b/tests/automation/utilities/utils.ts @@ -43,7 +43,7 @@ export async function waitForTestIdWithText( const found = await window.waitForSelector(builtSelector, { timeout: maxWait, }); - // console.info('found selector', builtSelector); + console.info('found selector', builtSelector); return found; } From 5a217c049eb253c5e5a37a07626f2b383ece7626 Mon Sep 17 00:00:00 2001 From: wafflesvsfrankie <92288602+burtonemily@users.noreply.github.com> Date: Mon, 12 May 2025 16:34:40 +1000 Subject: [PATCH 2/3] Fixing linting issues --- eslint.config.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/eslint.config.mjs b/eslint.config.mjs index a0e2340..91a73e0 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,4 +1,5 @@ import eslint from '@eslint/js'; +// eslint-disable-next-line import/no-unresolved import tseslint from 'typescript-eslint'; import globals from 'globals'; From f7399c7fe587fe246a128cec40942fca8ae27d22 Mon Sep 17 00:00:00 2001 From: wafflesvsfrankie <92288602+burtonemily@users.noreply.github.com> Date: Thu, 15 May 2025 13:28:12 +1000 Subject: [PATCH 3/3] Network page tests --- tests/automation/network_page.spec.ts | 82 +-------------------------- tests/automation/types/testing.ts | 3 - 2 files changed, 1 insertion(+), 84 deletions(-) diff --git a/tests/automation/network_page.spec.ts b/tests/automation/network_page.spec.ts index ee575ce..90b3bcb 100644 --- a/tests/automation/network_page.spec.ts +++ b/tests/automation/network_page.spec.ts @@ -1,14 +1,9 @@ import { englishStrippedStr } from '../locale/localizedString'; -import { sleepFor } from '../promise_utils'; -import { recoverFromSeed } from './setup/recovery_using_seed'; -import { sessionTestOneWindow, test_Alice_1W } from './setup/sessionTest'; -import { User } from './types/testing'; +import { test_Alice_1W } from './setup/sessionTest'; import { checkModalStrings, clickOnTestIdWithText, - doesElementExist, grabTextFromElement, - typeIntoInput, waitForElement, waitForLoadingAnimationToFinish, waitForTestIdWithText, @@ -43,81 +38,6 @@ test_Alice_1W('Learn more network link', async ({ aliceWindow1 }) => { console.log('href', href); }); -sessionTestOneWindow('No token bonus', async ([window]) => { - const userA: User = { - userName: 'Alice', - accountid: - '666016369d70fa182d981e257d49fbdad6b71070a31114c8db8f13f4e110db7c', - recoveryPassword: - 'initiate doorway obliged pancakes huddle omega vexed regular antics impel sonic gorilla initiate', - }; - await recoverFromSeed(window, userA.recoveryPassword, true); - await clickOnTestIdWithText(window, 'settings-section'); - await clickOnTestIdWithText(window, 'session-network-settings-menu-item'); - await waitForLoadingAnimationToFinish(window, 'loading-spinner'); - // Need to wait for page to load - await sleepFor(1000); - await doesElementExist(window, 'data-testid', 'token-bonus-amount'); -}); - -sessionTestOneWindow('Token bonus matches', async ([window]) => { - const userA: User = { - userName: 'Alice', - accountid: - 'cafe7498de7c43aa528551392a9b573ac4154ec9db455652d01cddd48e345a22', - recoveryPassword: - 'pirate pancakes lunar jabbed serving cake greater textbook icon items roles ouch pirate', - }; - const expectedTokenAmount = '125'; - await recoverFromSeed(window, userA.recoveryPassword, true); - await clickOnTestIdWithText(window, 'settings-section'); - await clickOnTestIdWithText(window, 'session-network-settings-menu-item'); - await waitForLoadingAnimationToFinish(window, 'loading-spinner'); - const actualTokenAmount = await grabTextFromElement( - window, - 'data-testid', - 'token-bonus-amount', - ); - if (actualTokenAmount !== expectedTokenAmount) { - throw new Error( - `Expected token amount: ${expectedTokenAmount}, but got: ${actualTokenAmount}`, - ); - } -}); - -sessionTestOneWindow('Invalid checksum', async ([window]) => { - const userA: User = { - userName: 'Alice', - accountid: - 'cafe7498de7c43aa528551392a9b573ac4154ec9db455652d01cddd48e345a22', - recoveryPassword: - 'pirate pancakes lunar jabbed serving cake greater textbook icon items roles ouch pirate', - }; - const invalidAddress = '0x8282A0293DB7487C09Ca145Ace9bb23c345EaeD6'; - // TODO Add string in once crowdin has been updated - // const expectedError = englishStrippedStr('sessionNetworkWalletAddressError').toString(); - const expectedError = - 'You have submitted an invalid Ethereum wallet address. Please check and try again.'; - await recoverFromSeed(window, userA.recoveryPassword, true); - await clickOnTestIdWithText(window, 'settings-section'); - await clickOnTestIdWithText(window, 'session-network-settings-menu-item'); - await waitForLoadingAnimationToFinish(window, 'loading-spinner'); - await clickOnTestIdWithText(window, 'token-claim-button'); - await typeIntoInput(window, 'wallet-address-input', invalidAddress); - await clickOnTestIdWithText(window, 'submit-button'); - await waitForTestIdWithText(window, 'session-error-message'); - const returnedError = await grabTextFromElement( - window, - 'data-testid', - 'session-error-message', - ); - if (returnedError !== expectedError) { - throw new Error( - `Expected error message: ${expectedError}, but got: ${returnedError}`, - ); - } -}); - test_Alice_1W('Refreshing page works', async ({ aliceWindow1 }) => { // TODO Add string in once crowdin has been updated // const expectedText = englishStrippedStr('updated') diff --git a/tests/automation/types/testing.ts b/tests/automation/types/testing.ts index b4238d7..f67be16 100644 --- a/tests/automation/types/testing.ts +++ b/tests/automation/types/testing.ts @@ -194,8 +194,5 @@ export type DataTestId = | 'session-recovery-password' | 'session-network-settings-menu-item' | 'learn-more-network-link' - | 'token-claim-button' - | 'wallet-address-input' - | 'submit-button' | 'refresh-button' | 'last-updated-timestamp';