From fd3ba32582ac0e45f1e710b45ec856a89db77988 Mon Sep 17 00:00:00 2001 From: Michael <30682308+mike10ca@users.noreply.github.com> Date: Wed, 1 Nov 2023 08:01:04 +0100 Subject: [PATCH 1/3] Tests: Fix Cypress tests (#2706) * Fix Cypress tests * Update tests logic --- cypress/e2e/pages/balances.pages.js | 2 +- cypress/e2e/pages/batches.pages.js | 8 ++++-- cypress/e2e/pages/create_wallet.pages.js | 10 ++------ cypress/e2e/pages/main.page.js | 4 +-- cypress/e2e/pages/owners.pages.js | 14 ++++++++++- cypress/e2e/pages/safeapps.pages.js | 17 ++++++------- cypress/e2e/safe-apps/apps_list.cy.js | 7 ++---- cypress/e2e/safe-apps/info_modal.cy.js | 8 +++--- cypress/e2e/safe-apps/preview_drawer.cy.js | 6 ++--- cypress/e2e/safe-apps/safe_permissions.cy.js | 2 +- cypress/e2e/smoke/add_owner.cy.js | 8 +++--- cypress/e2e/smoke/assets.cy.js | 2 +- cypress/e2e/smoke/balances.cy.js | 2 +- cypress/e2e/smoke/balances_pagination.cy.js | 5 ++-- cypress/e2e/smoke/batch_tx.cy.js | 26 ++++++++++++++------ cypress/e2e/smoke/create_tx.cy.js | 4 +-- cypress/e2e/smoke/import_export_data.cy.js | 2 +- cypress/e2e/smoke/remove_owner.cy.js | 6 ++--- cypress/e2e/smoke/replace_owner.cy.js | 6 ++--- cypress/e2e/smoke/tx_history.cy.js | 4 +-- 20 files changed, 76 insertions(+), 67 deletions(-) diff --git a/cypress/e2e/pages/balances.pages.js b/cypress/e2e/pages/balances.pages.js index 1dcaf46e5c..0cb82caeb1 100644 --- a/cypress/e2e/pages/balances.pages.js +++ b/cypress/e2e/pages/balances.pages.js @@ -44,7 +44,7 @@ export const tokenListOptions = { export const currencyEUR = 'EUR' export const currencyUSD = 'USD' -export const currentcySepoliaFormat = '0.1 ETH' +export const currentcySepoliaFormat = '0.09996 ETH' export const currencyAave = 'AAVE' export const currencyAaveAlttext = 'AAVE' diff --git a/cypress/e2e/pages/batches.pages.js b/cypress/e2e/pages/batches.pages.js index dfbb34d7ef..d1c5628475 100644 --- a/cypress/e2e/pages/batches.pages.js +++ b/cypress/e2e/pages/batches.pages.js @@ -67,15 +67,19 @@ function addToBatchButton() { export function openBatchtransactionsModal() { cy.get(batchTxTopBar).should('be.visible').click() cy.contains(batchedTransactionsStr).should('be.visible') - cy.contains(addInitialTransactionStr) } export function openNewTransactionModal() { cy.get(addNewTxBatch).click() - cy.contains('h1', newTransactionTitle).should('be.visible') cy.contains(sendTokensButn).click() } +export function addNewTransactionToBatch(EOA, currentNonce, funds_first_tx) { + openBatchtransactionsModal() + openNewTransactionModal() + addToBatch(EOA, currentNonce, funds_first_tx) +} + export function verifyAmountTransactionsInBatch(count) { cy.contains(batchedTransactionsStr, { timeout: 7000 }) .should('be.visible') diff --git a/cypress/e2e/pages/create_wallet.pages.js b/cypress/e2e/pages/create_wallet.pages.js index 65ca64c824..706f7e4da1 100644 --- a/cypress/e2e/pages/create_wallet.pages.js +++ b/cypress/e2e/pages/create_wallet.pages.js @@ -55,15 +55,9 @@ export function typeWalletName(name) { export function selectNetwork(network, regex = false) { cy.wait(1000) - cy.get(selectNetworkBtn).should('exist').click() + cy.get(selectNetworkBtn).should('be.visible').click() + cy.wait(1000) cy.get('li').contains(network).click() - - if (regex) { - regex = constants.networks.goerli - cy.get(selectNetworkBtn).click().invoke('text').should('match', regex) - } else { - cy.get(selectNetworkBtn).click().should('have.text', network) - } cy.get('body').click() } diff --git a/cypress/e2e/pages/main.page.js b/cypress/e2e/pages/main.page.js index 1f38e0ded6..438797b93c 100644 --- a/cypress/e2e/pages/main.page.js +++ b/cypress/e2e/pages/main.page.js @@ -6,11 +6,11 @@ export function clickOnSideMenuItem(item) { cy.get('p').contains(item).click() } -export function acceptCookies() { +export function acceptCookies(index = 0) { cy.wait(1000) cy.findAllByText('Got it!') - .should('have.length.at.least', 0) + .should('have.length.at.least', index) .each(($el) => $el.click()) cy.get('button') diff --git a/cypress/e2e/pages/owners.pages.js b/cypress/e2e/pages/owners.pages.js index 7799f73854..51d0c658f6 100644 --- a/cypress/e2e/pages/owners.pages.js +++ b/cypress/e2e/pages/owners.pages.js @@ -5,7 +5,7 @@ const copyToClipboardBtn = 'button[aria-label="Copy to clipboard"]' const tooltipLabel = (label) => `span[aria-label="${label}"]` const removeOwnerBtn = 'span[data-track="settings: Remove owner"] > span > button' const replaceOwnerBtn = 'span[data-track="settings: Replace owner"] > span > button' -const addOwnerBtn = 'span[data-track="settings: Add owner"]' +const addOwnerBtn = 'span[data-track="settings: Add owner"] > button' const tooltip = 'div[role="tooltip"]' const expandMoreIcon = 'svg[data-testid="ExpandMoreIcon"]' const sentinelStart = 'div[data-testid="sentinelStart"]' @@ -87,6 +87,10 @@ export function verifyRemoveBtnIsEnabled() { return cy.get(removeOwnerBtn).should('exist') } +export function verifyRemoveBtnIsDisabled() { + return cy.get(removeOwnerBtn).should('exist').and('be.disabled') +} + export function hoverOverDeleteOwnerBtn(index) { cy.get(removeOwnerBtn).eq(index).trigger('mouseover', { force: true }) } @@ -110,6 +114,10 @@ export function verifyReplaceBtnIsEnabled() { cy.get(replaceOwnerBtn).should('exist').and('not.be.disabled') } +export function verifyReplaceBtnIsDisabled() { + cy.get(replaceOwnerBtn).should('exist').and('be.disabled') +} + export function hoverOverReplaceOwnerBtn() { cy.get(replaceOwnerBtn).trigger('mouseover', { force: true }) } @@ -118,6 +126,10 @@ export function verifyAddOwnerBtnIsEnabled() { cy.get(addOwnerBtn).should('exist').and('not.be.disabled') } +export function verifyAddOwnerBtnIsDisabled() { + cy.get(addOwnerBtn).should('exist').and('be.disabled') +} + export function hoverOverAddOwnerBtn() { cy.get(addOwnerBtn).trigger('mouseover') } diff --git a/cypress/e2e/pages/safeapps.pages.js b/cypress/e2e/pages/safeapps.pages.js index d4626dafc0..6c2dce7dcb 100644 --- a/cypress/e2e/pages/safeapps.pages.js +++ b/cypress/e2e/pages/safeapps.pages.js @@ -23,11 +23,12 @@ const allowAllPermissions = /allow all/i const appNotSupportedMsg = "The app doesn't support Safe App functionality" export const pinWalletConnectStr = /pin walletconnect/i -export const transactionBuilderStr = /pin transaction builder/i +export const transactionBuilderStr = 'Transaction Builder' export const logoWalletConnect = /logo.*walletconnect/i export const walletConnectHeadlinePreview = /walletconnect/i -export const availableNetworksPreview = /available networks/i -export const connecttextPreview = 'Connect your Safe to any dApp that supports WalletConnect' +export const transactiobUilderHeadlinePreview = 'Transaction Builder' +export const availableNetworksPreview = 'Available networks' +export const connecttextPreview = 'Compose custom contract interactions and batch them into a single transaction' const warningDefaultAppStr = 'The application you are trying to access is not in the default Safe Apps list' export const localStorageItem = '{"https://safe-test-app.com":[{"feature":"camera","status":"granted"},{"feature":"microphone","status":"denied"}]}' @@ -70,7 +71,7 @@ export function verifyLinkName(name) { } export function clickOnApp(app) { - cy.findByRole('link', { name: app }).click() + cy.contains(app).click() } export function verifyNoAppsTextPresent() { @@ -78,12 +79,8 @@ export function verifyNoAppsTextPresent() { } export function pinApp(app, pin = true) { - cy.findByLabelText(app).click() - cy.wait(200) - cy.findByLabelText(app).should(($el) => { - const ariaLabel = $el.attr('aria-label') - expect(ariaLabel).to.include(pin ? 'Unpin' : 'Pin') - }) + const option = pin ? 'Pin' : 'Unpin' + cy.get(`[aria-label="${option} ${app}"]`).click() } export function clickOnBookmarkedAppsTab() { diff --git a/cypress/e2e/safe-apps/apps_list.cy.js b/cypress/e2e/safe-apps/apps_list.cy.js index c14f41bb38..4081b813cf 100644 --- a/cypress/e2e/safe-apps/apps_list.cy.js +++ b/cypress/e2e/safe-apps/apps_list.cy.js @@ -9,7 +9,7 @@ describe('Safe Apps tests', () => { beforeEach(() => { cy.clearLocalStorage() cy.visit(constants.SEPOLIA_TEST_SAFE_4 + constants.appsUrl, { failOnStatusCode: false }) - main.acceptCookies() + main.acceptCookies(1) }) it('Verify app list can be filtered by app name [C56130]', () => { @@ -32,15 +32,12 @@ describe('Safe Apps tests', () => { it('Verify apps can be pinned [C56133]', () => { safeapps.clearSearchAppInput() - safeapps.pinApp(safeapps.pinWalletConnectStr) safeapps.pinApp(safeapps.transactionBuilderStr) - safeapps.verifyPinnedAppCount(2) + safeapps.verifyPinnedAppCount(1) }) it('Verify apps can be unpinned [C56134]', () => { - safeapps.pinApp(safeapps.pinWalletConnectStr) safeapps.pinApp(safeapps.transactionBuilderStr) - safeapps.pinApp(safeapps.pinWalletConnectStr, false) safeapps.pinApp(safeapps.transactionBuilderStr, false) safeapps.verifyPinnedAppCount(0) }) diff --git a/cypress/e2e/safe-apps/info_modal.cy.js b/cypress/e2e/safe-apps/info_modal.cy.js index d4b93b3aad..63e45f1b0e 100644 --- a/cypress/e2e/safe-apps/info_modal.cy.js +++ b/cypress/e2e/safe-apps/info_modal.cy.js @@ -10,17 +10,19 @@ describe('Safe Apps info modal tests', () => { }) it('Verify the disclaimer is displayed when a Safe App is opened [C56139]', () => { - safeapps.clickOnApp(safeapps.logoWalletConnect) + safeapps.clickOnApp(safeapps.transactionBuilderStr) safeapps.clickOnOpenSafeAppBtn() }) - it('Verify the permissions slide is shown if the app require permissions [C56140]', () => { + // Skip tests due to changed logic + // TODO: Discuss furthers + it.skip('Verify the permissions slide is shown if the app require permissions [C56140]', () => { safeapps.clickOnContinueBtn() cy.wait(500) // wait for the animation to finish safeapps.verifyCameraCheckBoxExists() }) - it('Verify the permissions and consents decision are stored when accepted [C56141]', () => { + it.skip('Verify the permissions and consents decision are stored when accepted [C56141]', () => { safeapps.storeAndVerifyPermissions() }) }) diff --git a/cypress/e2e/safe-apps/preview_drawer.cy.js b/cypress/e2e/safe-apps/preview_drawer.cy.js index 0f0b10abef..bae5b9ca94 100644 --- a/cypress/e2e/safe-apps/preview_drawer.cy.js +++ b/cypress/e2e/safe-apps/preview_drawer.cy.js @@ -10,16 +10,14 @@ describe('Safe Apps info modal tests', () => { }) it('Verify the preview drawer is displayed when opening a Safe App from the app list [C56149]', () => { - safeapps.clickOnApp(safeapps.logoWalletConnect) + safeapps.clickOnApp(safeapps.transactionBuilderStr) cy.findByRole('presentation').within(() => { safeapps.verifyPreviewWindow( - safeapps.walletConnectHeadlinePreview, + safeapps.transactiobUilderHeadlinePreview, safeapps.connecttextPreview, safeapps.availableNetworksPreview, ) - safeapps.pinApp(safeapps.pinWalletConnectStr) - safeapps.pinApp(safeapps.pinWalletConnectStr, false) safeapps.closePreviewWindow() }) cy.findByRole('presentation').should('not.exist') diff --git a/cypress/e2e/safe-apps/safe_permissions.cy.js b/cypress/e2e/safe-apps/safe_permissions.cy.js index af06401a08..b93a135b90 100644 --- a/cypress/e2e/safe-apps/safe_permissions.cy.js +++ b/cypress/e2e/safe-apps/safe_permissions.cy.js @@ -19,7 +19,7 @@ describe('Safe permissions system tests', () => { it('Verify that requesting permissions with wallet_requestPermissions shows the permissions prompt and return the permissions on accept [C56150]', () => { cy.visitSafeApp(constants.testAppUrl + constants.requestPermissionsUrl) - main.acceptCookies() + main.acceptCookies(1) safeapps.clickOnContinueBtn() safeapps.verifyWarningDefaultAppMsgIsDisplayed() safeapps.clickOnContinueBtn() diff --git a/cypress/e2e/smoke/add_owner.cy.js b/cypress/e2e/smoke/add_owner.cy.js index af9ec0f9c8..a36635750c 100644 --- a/cypress/e2e/smoke/add_owner.cy.js +++ b/cypress/e2e/smoke/add_owner.cy.js @@ -7,7 +7,7 @@ describe('Add Owners tests', () => { beforeEach(() => { cy.visit(constants.setupUrl + constants.SEPOLIA_TEST_SAFE_1) cy.clearLocalStorage() - main.acceptCookies() + main.acceptCookies(1) cy.contains(owner.safeAccountNonceStr, { timeout: 10000 }) }) @@ -17,16 +17,14 @@ describe('Add Owners tests', () => { it('Verify “Add new owner” button tooltip displays correct message for Non-Owner [C56018]', () => { cy.visit(constants.setupUrl + constants.SEPOLIA_TEST_SAFE_2) - owner.hoverOverAddOwnerBtn() - owner.verifyTooltiptext(owner.nonOwnerErrorMsg) + owner.verifyAddOwnerBtnIsDisabled() }) it('Verify Tooltip displays correct message for disconnected user [C56019]', () => { owner.waitForConnectionStatus() owner.clickOnWalletExpandMoreIcon() owner.clickOnDisconnectBtn() - owner.hoverOverAddOwnerBtn() - owner.verifyTooltiptext(owner.disconnectedUserErrorMsg) + owner.verifyAddOwnerBtnIsDisabled() }) it('Verify the Add New Owner Form can be opened [C56020]', () => { diff --git a/cypress/e2e/smoke/assets.cy.js b/cypress/e2e/smoke/assets.cy.js index e8067221a9..578fc639ee 100644 --- a/cypress/e2e/smoke/assets.cy.js +++ b/cypress/e2e/smoke/assets.cy.js @@ -13,7 +13,7 @@ describe('Assets tests', () => { beforeEach(() => { cy.visit(constants.BALANCE_URL + constants.SEPOLIA_TEST_SAFE_5) cy.clearLocalStorage() - main.acceptCookies() + main.acceptCookies(2) }) it('Verify that the token tab is selected by default and the table is visible [C56039]', () => { diff --git a/cypress/e2e/smoke/balances.cy.js b/cypress/e2e/smoke/balances.cy.js index 98f32cad67..47142aa9f5 100644 --- a/cypress/e2e/smoke/balances.cy.js +++ b/cypress/e2e/smoke/balances.cy.js @@ -14,7 +14,7 @@ describe('Balance tests', () => { before(() => { cy.clearLocalStorage() cy.visit(constants.BALANCE_URL + constants.SEPOLIA_TEST_SAFE_5) - main.acceptCookies() + main.acceptCookies(2) cy.contains('Assets') cy.get(balances.balanceSingleRow).should('have.length.lessThan', ASSETS_LENGTH) balances.selectTokenList(balances.tokenListOptions.allTokens) diff --git a/cypress/e2e/smoke/balances_pagination.cy.js b/cypress/e2e/smoke/balances_pagination.cy.js index 695dfda308..92539761cd 100644 --- a/cypress/e2e/smoke/balances_pagination.cy.js +++ b/cypress/e2e/smoke/balances_pagination.cy.js @@ -1,5 +1,6 @@ import * as constants from '../../support/constants' import * as balances from '../pages/balances.pages' +import * as main from '../../e2e/pages/main.page' const ASSETS_LENGTH = 8 @@ -8,9 +9,7 @@ describe('Balance tests', () => { cy.clearLocalStorage() // Open the Safe used for testing cy.visit(constants.BALANCE_URL + constants.PAGINATION_TEST_SAFE) - cy.contains('button', 'Accept selection').click() - // Table is loaded - cy.contains('Görli Ether') + main.acceptCookies(2) cy.contains('div', 'Default tokens').click() cy.wait(100) diff --git a/cypress/e2e/smoke/batch_tx.cy.js b/cypress/e2e/smoke/batch_tx.cy.js index 777621dc43..507b2b3ecd 100644 --- a/cypress/e2e/smoke/batch_tx.cy.js +++ b/cypress/e2e/smoke/batch_tx.cy.js @@ -7,10 +7,10 @@ const funds_first_tx = '0.001' const funds_second_tx = '0.002' describe('Batch transaction tests', () => { - before(() => { + beforeEach(() => { cy.clearLocalStorage() cy.visit(constants.BALANCE_URL + constants.SEPOLIA_TEST_SAFE_5) - main.acceptCookies() + main.acceptCookies(2) }) it('Verify empty batch list can be opened [C56082]', () => { @@ -20,10 +20,11 @@ describe('Batch transaction tests', () => { it('Verify the Add batch button is present in a transaction form [C56084]', () => { //The "true" is to validate that the add to batch button is not visible if "Yes, execute" is selected - batch.addToBatch(constants.EOA, currentNonce, funds_first_tx) + batch.addNewTransactionToBatch(constants.EOA, currentNonce, funds_first_tx) }) it('Verify a transaction can be added to the batch [C56085]', () => { + batch.addNewTransactionToBatch(constants.EOA, currentNonce, funds_first_tx) cy.contains(batch.transactionAddedToBatchStr).should('be.visible') //The batch button in the header shows the transaction count batch.verifyBatchIconCount(1) @@ -32,26 +33,37 @@ describe('Batch transaction tests', () => { }) it('Verify a second transaction can be added to the batch [C56086]', () => { - batch.openNewTransactionModal() - batch.addToBatch(constants.EOA, currentNonce, funds_second_tx) + batch.addNewTransactionToBatch(constants.EOA, currentNonce, funds_first_tx) + cy.wait(1000) + batch.addNewTransactionToBatch(constants.EOA, currentNonce, funds_first_tx) batch.verifyBatchIconCount(2) batch.clickOnBatchCounter() batch.verifyAmountTransactionsInBatch(2) }) it('Verify the batch can be confirmed and related transactions exist in the form [C56088]', () => { + batch.addNewTransactionToBatch(constants.EOA, currentNonce, funds_first_tx) + cy.wait(1000) + batch.addNewTransactionToBatch(constants.EOA, currentNonce, funds_first_tx) + batch.clickOnBatchCounter() + batch.clickOnConfirmBatchBtn() + batch.clickOnBatchCounter() batch.clickOnConfirmBatchBtn() batch.verifyBatchTransactionsCount(2) + batch.clickOnBatchCounter() cy.contains(funds_first_tx).parents('ul').as('TransactionList') cy.get('@TransactionList').find('li').eq(0).find('span').eq(0).contains(funds_first_tx) - cy.get('@TransactionList').find('li').eq(1).find('span').eq(0).contains(funds_second_tx) + cy.get('@TransactionList').find('li').eq(1).find('span').eq(0).contains(funds_first_tx) }) it('Verify a transaction can be removed from the batch [C56089]', () => { + batch.addNewTransactionToBatch(constants.EOA, currentNonce, funds_first_tx) + cy.wait(1000) + batch.addNewTransactionToBatch(constants.EOA, currentNonce, funds_first_tx) batch.clickOnBatchCounter() cy.contains(batch.batchedTransactionsStr).should('be.visible').parents('aside').find('ul > li').as('BatchList') cy.get('@BatchList').find(batch.deleteTransactionbtn).eq(0).click() cy.get('@BatchList').should('have.length', 1) - cy.get('@BatchList').contains(funds_first_tx).should('not.exist') + cy.get('@BatchList').contains(funds_second_tx).should('not.exist') }) }) diff --git a/cypress/e2e/smoke/create_tx.cy.js b/cypress/e2e/smoke/create_tx.cy.js index 055adac173..b1a5e1ac1a 100644 --- a/cypress/e2e/smoke/create_tx.cy.js +++ b/cypress/e2e/smoke/create_tx.cy.js @@ -3,13 +3,13 @@ import * as main from '../../e2e/pages/main.page' import * as createtx from '../../e2e/pages/create_tx.pages' const sendValue = 0.00002 -const currentNonce = 1 +const currentNonce = 11 describe('Create transactions tests', () => { before(() => { cy.clearLocalStorage() cy.visit(constants.BALANCE_URL + constants.SEPOLIA_TEST_SAFE_5) - main.acceptCookies() + main.acceptCookies(2) }) it('Verify a new send token transaction can be created [C56104]', () => { diff --git a/cypress/e2e/smoke/import_export_data.cy.js b/cypress/e2e/smoke/import_export_data.cy.js index 1c41ff5ab8..de7e8f3881 100644 --- a/cypress/e2e/smoke/import_export_data.cy.js +++ b/cypress/e2e/smoke/import_export_data.cy.js @@ -24,6 +24,7 @@ describe('Import Export Data tests', () => { }) it('Verify address book imported data [C56112]', () => { + main.acceptCookies(1) file.clickOnAddressBookBtn() file.verifyImportedAddressBookData() }) @@ -32,7 +33,6 @@ describe('Import Export Data tests', () => { const appNames = ['Transaction Builder'] file.clickOnAppsBtn() - file.clickOnBookmarkedAppsBtn() file.verifyAppsAreVisible(appNames) }) diff --git a/cypress/e2e/smoke/remove_owner.cy.js b/cypress/e2e/smoke/remove_owner.cy.js index bb00c61d9d..b22848c26e 100644 --- a/cypress/e2e/smoke/remove_owner.cy.js +++ b/cypress/e2e/smoke/remove_owner.cy.js @@ -18,8 +18,7 @@ describe('Remove Owners tests', () => { it('Verify Tooltip displays correct message for Non-Owner [C56037]', () => { cy.visit(constants.setupUrl + constants.SEPOLIA_TEST_SAFE_4) owner.waitForConnectionStatus() - owner.hoverOverDeleteOwnerBtn(0) - owner.verifyTooltipLabel(owner.nonOwnerErrorMsg) + owner.verifyRemoveBtnIsDisabled() }) it('Verify Tooltip displays correct message for disconnected user [C56031]', () => { @@ -27,8 +26,7 @@ describe('Remove Owners tests', () => { owner.waitForConnectionStatus() owner.clickOnWalletExpandMoreIcon() owner.clickOnDisconnectBtn() - owner.hoverOverDeleteOwnerBtn(0) - owner.verifyTooltipLabel(owner.disconnectedUserErrorMsg) + owner.verifyRemoveBtnIsDisabled() }) it('Verify owner removal form can be opened [C56032]', () => { diff --git a/cypress/e2e/smoke/replace_owner.cy.js b/cypress/e2e/smoke/replace_owner.cy.js index d16935dc93..b43ec2a8ce 100644 --- a/cypress/e2e/smoke/replace_owner.cy.js +++ b/cypress/e2e/smoke/replace_owner.cy.js @@ -18,16 +18,14 @@ describe('Replace Owners tests', () => { it('Verify Tooltip displays correct message for Non-Owner [C56016]', () => { cy.visit(constants.setupUrl + constants.SEPOLIA_TEST_SAFE_2) owner.waitForConnectionStatus() - owner.hoverOverReplaceOwnerBtn() - owner.verifyTooltipLabel(owner.nonOwnerErrorMsg) + owner.verifyReplaceBtnIsDisabled() }) it('Verify Tooltip displays correct message for disconnected user [C56006]', () => { owner.waitForConnectionStatus() owner.clickOnWalletExpandMoreIcon() owner.clickOnDisconnectBtn() - owner.hoverOverReplaceOwnerBtn() - owner.verifyTooltipLabel(owner.disconnectedUserErrorMsg) + owner.verifyReplaceBtnIsDisabled() }) it('Verify that the owner replacement form is opened [C56007]', () => { diff --git a/cypress/e2e/smoke/tx_history.cy.js b/cypress/e2e/smoke/tx_history.cy.js index b0b7c18c54..dc2fd67b26 100644 --- a/cypress/e2e/smoke/tx_history.cy.js +++ b/cypress/e2e/smoke/tx_history.cy.js @@ -19,7 +19,7 @@ describe('Transaction history tests', () => { // So that tests that rely on this feature don't randomly fail cy.window().then((win) => win.localStorage.setItem('SAFE_v2__AB_human-readable', true)) - main.acceptCookies() + main.acceptCookies(1) }) //Skipping this due to test data creation @@ -129,7 +129,7 @@ describe('Transaction history tests', () => { }) it('Verify transaction can be expanded/collapsed [C56129]', () => { - createTx.clickOnTransactionExpandableItem('Oct 9, 2023', () => { + createTx.clickOnTransactionExpandableItem('Oct 20, 2023', () => { createTx.verifyTransactionStrExists(str1) createTx.verifyTransactionStrExists(str2) createTx.verifyTransactionStrExists(str3) From 481e6a37927dd5b5f0c641e2e2752896dfbb5aac Mon Sep 17 00:00:00 2001 From: Michael <30682308+mike10ca@users.noreply.github.com> Date: Wed, 1 Nov 2023 13:14:19 +0100 Subject: [PATCH 2/3] Tests: Update skipped tests (#2723) * Update skipped tests * Fix permissions tests * Fix NFTS tests --- cypress/e2e/pages/dashboard.pages.js | 6 +- cypress/e2e/pages/nfts.pages.js | 6 +- cypress/e2e/pages/safeapps.pages.js | 2 +- .../e2e/safe-apps/browser_permissions.cy.js | 5 +- cypress/e2e/safe-apps/safe_permissions.cy.js | 6 +- cypress/e2e/smoke/dashboard.cy.js | 12 +- cypress/e2e/smoke/nfts.cy.js | 16 +-- cypress/e2e/smoke/tx_history.cy.js | 115 +++--------------- 8 files changed, 42 insertions(+), 126 deletions(-) diff --git a/cypress/e2e/pages/dashboard.pages.js b/cypress/e2e/pages/dashboard.pages.js index 43ad81fa8a..44b0bb4743 100644 --- a/cypress/e2e/pages/dashboard.pages.js +++ b/cypress/e2e/pages/dashboard.pages.js @@ -66,12 +66,8 @@ export function verifyFeaturedAppsSection() { cy.contains(transactionBuilderStr) cy.get(txBuilder).should('exist') - // WalletConnect app - cy.contains(walletConnectStr) - cy.get(walletConnect).should('exist') - // Featured apps have a Safe-specific link - cy.get(safeSpecificLink).should('have.length', 2) + cy.get(safeSpecificLink).should('have.length', 1) }) } diff --git a/cypress/e2e/pages/nfts.pages.js b/cypress/e2e/pages/nfts.pages.js index 0800d2bb9f..85775098cb 100644 --- a/cypress/e2e/pages/nfts.pages.js +++ b/cypress/e2e/pages/nfts.pages.js @@ -32,8 +32,10 @@ export function verifyDataInTable(name, address, tokenID) { cy.get('tbody tr:first-child').contains('td:nth-child(2)', tokenID) } -export function openFirstNFT() { - cy.get('tbody tr:first-child td:nth-child(2)').click() +export function openNFT(index) { + cy.get('tbody').within(() => { + cy.get('tr').eq(index).click() + }) } export function verifyNameInNFTModal(name) { diff --git a/cypress/e2e/pages/safeapps.pages.js b/cypress/e2e/pages/safeapps.pages.js index 6c2dce7dcb..1385761e8b 100644 --- a/cypress/e2e/pages/safeapps.pages.js +++ b/cypress/e2e/pages/safeapps.pages.js @@ -143,7 +143,7 @@ function verifyDisclaimerIsVisible() { } export function clickOnContinueBtn() { - return cy.findByRole('button', { name: continueBtnStr }).click() + return cy.findByRole('button', { name: continueBtnStr }).click().wait(1000) } export function verifyCameraCheckBoxExists() { diff --git a/cypress/e2e/safe-apps/browser_permissions.cy.js b/cypress/e2e/safe-apps/browser_permissions.cy.js index cfd4f8ae41..da34de03ab 100644 --- a/cypress/e2e/safe-apps/browser_permissions.cy.js +++ b/cypress/e2e/safe-apps/browser_permissions.cy.js @@ -14,11 +14,11 @@ describe('Browser permissions tests', () => { safe_apps_permissions: ['camera', 'microphone'], }) }) + cy.visitSafeApp(`${constants.testAppUrl}/app`) + main.acceptCookies(1) }) it('Verify a permissions slide to the user is displayed [C56137]', () => { - cy.visitSafeApp(`${constants.testAppUrl}/app`) - main.acceptCookies() safeapps.clickOnContinueBtn() safeapps.verifyCameraCheckBoxExists() safeapps.verifyMicrofoneCheckBoxExists() @@ -29,6 +29,7 @@ describe('Browser permissions tests', () => { safeapps.clickOnContinueBtn() safeapps.verifyWarningDefaultAppMsgIsDisplayed() safeapps.verifyCameraCheckBoxExists() + safeapps.clickOnContinueBtn() safeapps.clickOnContinueBtn().should(() => { expect(window.localStorage.getItem(constants.BROWSER_PERMISSIONS_KEY)).to.eq(safeapps.localStorageItem) }) diff --git a/cypress/e2e/safe-apps/safe_permissions.cy.js b/cypress/e2e/safe-apps/safe_permissions.cy.js index b93a135b90..771beee30d 100644 --- a/cypress/e2e/safe-apps/safe_permissions.cy.js +++ b/cypress/e2e/safe-apps/safe_permissions.cy.js @@ -3,10 +3,8 @@ import * as safeapps from '../pages/safeapps.pages' import * as main from '../pages/main.page' describe('Safe permissions system tests', () => { - before(() => { - cy.clearLocalStorage() - }) beforeEach(() => { + cy.clearLocalStorage() cy.fixture('safe-app').then((html) => { cy.intercept('GET', `${constants.testAppUrl}/*`, html) cy.intercept('GET', `*/manifest.json`, { @@ -58,7 +56,7 @@ describe('Safe permissions system tests', () => { }) cy.visitSafeApp(constants.testAppUrl + constants.getPermissionsUrl) - main.acceptCookies() + main.acceptCookies(1) safeapps.clickOnContinueBtn() safeapps.verifyWarningDefaultAppMsgIsDisplayed() safeapps.clickOnContinueBtn() diff --git a/cypress/e2e/smoke/dashboard.cy.js b/cypress/e2e/smoke/dashboard.cy.js index fac9d8a91f..ad0ca6d0ee 100644 --- a/cypress/e2e/smoke/dashboard.cy.js +++ b/cypress/e2e/smoke/dashboard.cy.js @@ -3,27 +3,27 @@ import * as dashboard from '../pages/dashboard.pages' import * as main from '../pages/main.page' describe('Dashboard tests', () => { - before(() => { + beforeEach(() => { cy.clearLocalStorage() cy.visit(constants.BALANCE_URL + constants.SEPOLIA_TEST_SAFE_5) - main.acceptCookies() + main.acceptCookies(2) main.clickOnSideMenuItem(constants.mainSideMenuOptions.home) dashboard.verifyConnectTransactStrIsVisible() }) - it.skip('Verify the overview widget is displayed [C56107]', () => { + it('Verify the overview widget is displayed [C56107]', () => { dashboard.verifyOverviewWidgetData() }) - it.skip('Verify the transaction queue widget is displayed [C56108]', () => { + it('Verify the transaction queue widget is displayed [C56108]', () => { dashboard.verifyTxQueueWidget() }) - it.skip('Verify the featured Safe Apps are displayed [C56109]', () => { + it('Verify the featured Safe Apps are displayed [C56109]', () => { dashboard.verifyFeaturedAppsSection() }) - it.skip('Verify the Safe Apps Section is displayed [C56110]', () => { + it('Verify the Safe Apps Section is displayed [C56110]', () => { dashboard.verifySafeAppsSection() }) }) diff --git a/cypress/e2e/smoke/nfts.cy.js b/cypress/e2e/smoke/nfts.cy.js index d6cb124519..e86f1d671a 100644 --- a/cypress/e2e/smoke/nfts.cy.js +++ b/cypress/e2e/smoke/nfts.cy.js @@ -7,34 +7,34 @@ const nftsAddress = '0x373B...866c' const nftsTokenID = 'CF' describe('NFTs tests', () => { - before(() => { + beforeEach(() => { cy.clearLocalStorage() cy.visit(constants.BALANCE_URL + constants.SEPOLIA_TEST_SAFE_5) - main.acceptCookies() + main.acceptCookies(2) nfts.clickOnNftsTab() }) - it.skip('Verify that NFTs exist in the table [C56123]', () => { + it('Verify that NFTs exist in the table [C56123]', () => { nfts.verifyNFTNumber(20) }) - it.skip('Verify NFT row contains data [C56124]', () => { + it('Verify NFT row contains data [C56124]', () => { nfts.verifyDataInTable(nftsName, nftsAddress, nftsTokenID) }) - it.skip('Verify NFT preview window can be opened [C56125]', () => { - nfts.openFirstNFT() + it('Verify NFT preview window can be opened [C56125]', () => { + nfts.openNFT(1) nfts.verifyNameInNFTModal(nftsTokenID) nfts.verifySelectedNetwrokSepolia() nfts.closeNFTModal() }) - it.skip('Verify NFT open does not open if no NFT exits [C56126]', () => { + it('Verify NFT open does not open if no NFT exits [C56126]', () => { nfts.clickOn6thNFT() nfts.verifyNFTModalDoesNotExist() }) - it.skip('Verify multipls NFTs can be selected and reviewed [C56127]', () => { + it('Verify multipls NFTs can be selected and reviewed [C56127]', () => { nfts.verifyInitialNFTData() nfts.selectNFTs(3) nfts.deselectNFTs([2], 3) diff --git a/cypress/e2e/smoke/tx_history.cy.js b/cypress/e2e/smoke/tx_history.cy.js index dc2fd67b26..cbc49612ed 100644 --- a/cypress/e2e/smoke/tx_history.cy.js +++ b/cypress/e2e/smoke/tx_history.cy.js @@ -2,16 +2,14 @@ import * as constants from '../../support/constants' import * as main from '../pages/main.page' import * as createTx from '../pages/create_tx.pages' -const INCOMING = 'Received' const OUTGOING = 'Sent' -const CONTRACT_INTERACTION = 'Contract interaction' const str1 = 'Received' const str2 = 'Executed' const str3 = 'Transaction hash' describe('Transaction history tests', () => { - before(() => { + beforeEach(() => { cy.clearLocalStorage() // Go to the test Safe transaction history cy.visit(constants.transactionsHistoryUrl + constants.SEPOLIA_TEST_SAFE_5) @@ -22,110 +20,31 @@ describe('Transaction history tests', () => { main.acceptCookies(1) }) - //Skipping this due to test data creation - it.skip('Verify October 9th transactions are displayed [C56128]', () => { - const DATE = 'Oct 9, 2023' - const NEXT_DATE_LABEL = 'Oct 11, 2023' - const amount = '0.1 ETH' - const amount2 = '15 TT_A' - const amount3 = '21 TT_B' - const amount4 = '82 DAI' - const amount5 = '73 USDC' - const amount6 = '27 AAVE' - const amount7 = '35.94 LINK' - const amount8 = '< 0.00001 ETH' - const time = '2:56 AM' - const time2 = '12:59 AM' - const time3 = '1:00 AM' - const time4 = '1:01 AM' + it('Verify October 9th transactions are displayed [C56128]', () => { + const DATE = 'Oct 29, 2023' + const NEXT_DATE_LABEL = 'Oct 20, 2023' + const amount = '0.00001 ETH' + const time = '10:39 PM' const success = 'Success' createTx.verifyDateExists(DATE) createTx.verifyDateExists(NEXT_DATE_LABEL) - main.scrollToBottomAndWaitForPageLoad() - // Transaction summaries from October 9th const rows = cy.contains('div', DATE).nextUntil(`div:contains(${NEXT_DATE_LABEL})`) - rows.should('have.length', 3) + rows.should('have.length', 10) - rows - .last() - .prev() - .within(() => { - // Type - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) + rows.eq(0).within(() => { + // Type + createTx.verifyImageAltTxt(0, OUTGOING) + createTx.verifyStatus(constants.transactionStatus.sent) - // Info - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.sep) - createTx.verifyTransactionStrExists(amount) - createTx.verifyTransactionStrExists(time) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.tta) - createTx.verifyTransactionStrExists(amount2) - createTx.verifyTransactionStrExists(time2) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.ttb) - createTx.verifyTransactionStrExists(amount3) - createTx.verifyTransactionStrExists(time2) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.dai) - createTx.verifyTransactionStrExists(amount4) - createTx.verifyTransactionStrExists(time2) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.usds) - createTx.verifyTransactionStrExists(amount5) - createTx.verifyTransactionStrExists(time3) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.aave) - createTx.verifyTransactionStrExists(amount6) - createTx.verifyTransactionStrExists(time3) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.link) - createTx.verifyTransactionStrExists(amount7) - createTx.verifyTransactionStrExists(time3) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.sep) - createTx.verifyTransactionStrExists(amount8) - createTx.verifyTransactionStrExists(time4) - createTx.verifyTransactionStrExists(success) - }) + // Info + createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.sep) + createTx.verifyTransactionStrExists(amount) + createTx.verifyTransactionStrExists(time) + createTx.verifyTransactionStrExists(success) + }) }) it('Verify transaction can be expanded/collapsed [C56129]', () => { From 391bc56a477881137d549e25a69e5dc31c813aa8 Mon Sep 17 00:00:00 2001 From: katspaugh <381895+katspaugh@users.noreply.github.com> Date: Wed, 1 Nov 2023 14:11:41 +0100 Subject: [PATCH 3/3] Fix: render mobile pairing correctly (#2718) --- src/pages/_app.tsx | 3 + src/services/pairing/QRModal.tsx | 106 ++++++++----------------- src/services/pairing/module.ts | 5 +- src/services/pairing/styles.module.css | 3 - 4 files changed, 38 insertions(+), 79 deletions(-) delete mode 100644 src/services/pairing/styles.module.css diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 6e8cea4cbd..ae4df5aeba 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -41,6 +41,7 @@ import { WalletConnectProvider } from '@/services/walletconnect/WalletConnectCon import useABTesting from '@/services/tracking/useAbTesting' import { AbTest } from '@/services/tracking/abTesting' import { useNotificationTracking } from '@/components/settings/PushNotifications/hooks/useNotificationTracking' +import MobilePairingModal from '@/services/pairing/QRModal' const GATEWAY_URL = IS_PRODUCTION || cgwDebugStorage.get() ? GATEWAY_URL_PRODUCTION : GATEWAY_URL_STAGING @@ -121,6 +122,8 @@ const WebCoreApp = ({ + + diff --git a/src/services/pairing/QRModal.tsx b/src/services/pairing/QRModal.tsx index b363838046..47b2e18b14 100644 --- a/src/services/pairing/QRModal.tsx +++ b/src/services/pairing/QRModal.tsx @@ -1,95 +1,55 @@ -import { useState } from 'react' import { Dialog, DialogContent, DialogTitle, IconButton } from '@mui/material' -import { createRoot } from 'react-dom/client' import CloseIcon from '@mui/icons-material/Close' import PairingQRCode from '@/components/common/PairingDetails/PairingQRCode' import PairingDescription from '@/components/common/PairingDetails/PairingDescription' -import { StoreHydrator } from '@/store' -import { AppProviders } from '@/pages/_app' import { PAIRING_MODULE_LABEL } from '@/services/pairing/module' -import css from './styles.module.css' import PairingDeprecationWarning from '@/components/common/PairingDetails/PairingDeprecationWarning' +import ExternalStore from '@/services/ExternalStore' -const WRAPPER_ID = 'safe-mobile-qr-modal' -const QR_CODE_SIZE = 200 +const { useStore: useCloseCallback, setStore: setCloseCallback } = new ExternalStore<() => void>() -const renderWrapper = () => { - if (typeof document === 'undefined') { - return - } - - const wrapper = document.createElement('div') - wrapper.setAttribute('id', WRAPPER_ID) - - document.body.appendChild(wrapper) - - return wrapper -} - -const open = (uri: string, cb: () => void) => { - const wrapper = renderWrapper() - - if (!wrapper) { - return - } - - const root = createRoot(wrapper) - - root.render() +export const open = (cb: () => void) => { + setCloseCallback(() => cb) } -const close = () => { - if (typeof document === 'undefined') { - return - } - - const wrapper = document.getElementById(WRAPPER_ID) - if (wrapper) { - document.body.removeChild(wrapper) - document.body.style.overflow = '' - } +export const close = () => { + setCloseCallback(undefined) } -const Modal = ({ uri, cb }: { uri: string; cb: () => void }) => { - const [open, setOpen] = useState(true) +const QRModal = () => { + const closeCallback = useCloseCallback() + const open = !!closeCallback const handleClose = () => { - cb() - setOpen(false) + closeCallback?.() + setCloseCallback(undefined) close() } + if (!open) return null + return ( - - - - - {PAIRING_MODULE_LABEL} - - - - - - - -
- -
-
-
-
+ + + {PAIRING_MODULE_LABEL} + + + + + + + +
+ +
+
) } -const QRModal = { - open, - close, -} - export default QRModal diff --git a/src/services/pairing/module.ts b/src/services/pairing/module.ts index fe5eba715c..add033b65c 100644 --- a/src/services/pairing/module.ts +++ b/src/services/pairing/module.ts @@ -5,6 +5,7 @@ import type { ITxData } from '@walletconnect/types' import { getPairingConnector, PAIRING_MODULE_STORAGE_ID } from '@/services/pairing/connector' import local from '@/services/local-storage/local' import { killPairingSession } from '@/services/pairing/utils' +import * as QRModal from '@/services/pairing/QRModal' enum ProviderEvents { ACCOUNTS_CHANGED = 'accountsChanged', @@ -44,8 +45,6 @@ const pairingModule = (): WalletInit => { const { default: WalletConnect } = await import('@walletconnect/client') - const { default: QRModal } = await import('@/services/pairing/QRModal') - const { Subject, fromEvent } = await import('rxjs') const { takeUntil, take } = await import('rxjs/operators') @@ -131,7 +130,7 @@ const pairingModule = (): WalletInit => { return new Promise((resolve, reject) => { if (!this.connector.connected) { this.connector.createSession().then(() => { - QRModal.open(this.connector.uri, () => + QRModal.open(() => reject( new ProviderRpcError({ code: 4001, diff --git a/src/services/pairing/styles.module.css b/src/services/pairing/styles.module.css deleted file mode 100644 index d1e8523d06..0000000000 --- a/src/services/pairing/styles.module.css +++ /dev/null @@ -1,3 +0,0 @@ -.modal { - z-index: var(--onboard-modal-z-index) !important; -}