Skip to content

Commit

Permalink
Cypress tests refactoring: PO model, safe app tests (#2522)
Browse files Browse the repository at this point in the history
* Cypress tests refactoring: PO model, safe app tests

* Cypress tests refactoring: PO model, safe app tests

# Conflicts:
#	cypress/e2e/pages/safeapps.pages.js
#	cypress/support/constants.js

* Fix tests

* Add missing constants

* Remove unused import

* Fix tests, fix naming

* Update Ubuntu image

* Update Cypress version

* Update yarn .lock file to reflect requied changes due to cypress v update

* Fix tests: manage local storage, set test isolation setting

* Disable pendingactions tests, need to clarify logic

* Remove unused import

* Update cypress/e2e/pages/create_tx.pages.js

Co-authored-by: Aaron Cook <[email protected]>

* Update cypress/e2e/pages/create_tx.pages.js

Co-authored-by: Aaron Cook <[email protected]>

* Address comments in PR

* Update constants

* Disabling beamer test as it is not reliable

---------

Co-authored-by: Aaron Cook <[email protected]>
  • Loading branch information
mike10ca and iamacook authored Sep 25, 2023
1 parent 500c06a commit ec9408c
Show file tree
Hide file tree
Showing 33 changed files with 598 additions and 334 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ concurrency:

jobs:
e2e:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
name: Smoke E2E tests
steps:
- uses: actions/checkout@v3
Expand Down
1 change: 1 addition & 0 deletions cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default defineConfig({

e2e: {
baseUrl: 'http://localhost:3000',
testIsolation: false,
},

chromeWebSecurity: false,
Expand Down
21 changes: 21 additions & 0 deletions cypress/e2e/pages/address_book.page.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ export const acceptSelection = 'Accept selection'
export const addressBook = 'Address book'
const createEntryBtn = 'Create entry'

const beameriFrameContainer = '#beamerOverlay .iframeCointaner'
const beamerInput = 'input[id="beamer"]'
const nameInput = 'input[name="name"]'
const addressInput = 'input[name="address"]'
const saveBtn = 'Save'
Expand All @@ -13,6 +15,8 @@ const exportFileModalBtnSection = '.MuiDialogActions-root'
const exportFileModalExportBtn = 'Export'
const importBtn = 'Import'
const exportBtn = 'Export'
const whatsNewBtnStr = "What's new"
const beamrCookiesStr = 'accept the "Beamer" cookies'

export function clickOnImportFileBtn() {
cy.contains(importBtn).click()
Expand Down Expand Up @@ -91,3 +95,20 @@ export function clickDeleteEntryModalDeleteButton() {
export function verifyEditedNameNotExists(name) {
cy.get(name).should('not.exist')
}

export function clickOnWhatsNewBtn(force = false) {
cy.contains(whatsNewBtnStr).click({ force: force })
}

export function acceptBeamerCookies() {
cy.contains(beamrCookiesStr)
}

export function verifyBeamerIsChecked() {
cy.get(beamerInput).should('be.checked')
}

export function verifyBeameriFrameExists() {
cy.wait(1000)
cy.get(beameriFrameContainer).should('exist')
}
1 change: 1 addition & 0 deletions cypress/e2e/pages/balances.pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const hideAssetBtn = 'button[aria-label="Hide asset"]'
const hiddeTokensBtn = '[data-testid="toggle-hidden-assets"]'
const hiddenTokenCheckbox = 'input[type="checkbox"]'
const paginationPageList = 'ul[role="listbox"]'
const currencyDropDown = 'div[id="currency"]'
const hiddenTokenSaveBtn = 'Save'
const hideTokenDefaultString = 'Hide tokens'

Expand Down
9 changes: 7 additions & 2 deletions cypress/e2e/pages/batches.pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const tokenAddressInput = 'input[name="tokenAddress"]'
const listBox = 'ul[role="listbox"]'
const amountInput = '[name="amount"]'
const nonceInput = 'input[name="nonce"]'
const executeOptionsContainer = 'div[role="radiogroup"]'

export function addToBatch(EOA, currentNonce, amount, verify = false) {
fillTransactionData(EOA, amount)
Expand All @@ -49,8 +50,12 @@ function setNonceAndProceed(currentNonce) {
}

function executeTransaction() {
cy.contains(yesExecuteString, { timeout: 4000 }).click()
cy.contains(addToBatchBtn).should('not.exist')
cy.waitForSelector(() => {
return cy.get(executeOptionsContainer).then(() => {
cy.contains(yesExecuteString, { timeout: 4000 }).click()
cy.contains(addToBatchBtn).should('not.exist')
})
})
}

function addToBatchButton() {
Expand Down
44 changes: 42 additions & 2 deletions cypress/e2e/pages/create_tx.pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const amountInput = 'input[name="amount"]'
const nonceInput = 'input[name="nonce"]'
const gasLimitInput = '[name="gasLimit"]'
const rotateLeftIcon = '[data-testid="RotateLeftIcon"]'
const transactionItemExpandable = 'div[id^="transfer"]'

const viewTransactionBtn = 'View transaction'
const transactionDetailsTitle = 'Transaction details'
Expand All @@ -26,6 +27,8 @@ const editBtnStr = 'Edit'
const executionParamsStr = 'Execution parameters'
const noLaterStr = 'No, later'
const signBtnStr = 'Sign'
const expandAllBtnStr = 'Expand all'
const collapseAllBtnStr = 'Collapse all'

export function clickOnNewtransactionBtn() {
// Assert that "New transaction" button is visible
Expand Down Expand Up @@ -90,7 +93,7 @@ export function changeNonce(value) {
}

export function verifyConfirmTransactionData() {
cy.contains(yesStr).should('exist')
cy.contains(yesStr).should('exist').click()
cy.contains(estimatedFeeStr).should('exist')

// Asserting the sponsored info is present
Expand Down Expand Up @@ -130,7 +133,7 @@ export function clickOnSignTransactionBtn() {
}

export function waitForProposeRequest() {
cy.intercept('POST', constants.proposeEndPoint).as('ProposeTx')
cy.intercept('POST', constants.proposeEndpoint).as('ProposeTx')
cy.wait('@ProposeTx')
}

Expand All @@ -149,3 +152,40 @@ export function verifyQueueLabel() {
export function verifyTransactionSummary(sendValue) {
cy.contains(TransactionSummary + `${sendValue} ${constants.tokenAbbreviation.gor}`).should('exist')
}

export function verifyDateExists(date) {
cy.contains('div', date).should('exist')
}

export function verifyImageAltTxt(index, text) {
cy.get('img').eq(index).should('have.attr', 'alt', text).should('be.visible')
}

export function verifyStatus(status) {
cy.contains('div', status).should('exist')
}

export function verifyTransactionStrExists(str) {
cy.contains(str).should('exist')
}

export function verifyTransactionStrNotVible(str) {
cy.contains(str).should('not.be.visible')
}

export function clickOnTransactionExpandableItem(name, actions) {
cy.contains('div', name)
.next()
.click()
.within(() => {
actions()
})
}

export function clickOnExpandAllBtn() {
cy.contains(expandAllBtnStr).click()
}

export function clickOnCollapseAllBtn() {
cy.contains(collapseAllBtnStr).click()
}
5 changes: 5 additions & 0 deletions cypress/e2e/pages/load_safe.pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export function selectGoerli() {
cy.contains('span', constants.networks.goerli)
}

export function selectPolygon() {
cy.get('ul li').contains(constants.networks.polygon).click()
cy.contains('span', constants.networks.polygon)
}

export function verifyNameInputHasPlceholder() {
cy.get(nameInput).should('have.attr', 'placeholder').should('match', constants.goerlySafeName)
}
Expand Down
10 changes: 10 additions & 0 deletions cypress/e2e/pages/main.page.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,13 @@ export function verifyGoerliWalletHeader() {
export function verifyHomeSafeUrl(safe) {
cy.location('href', { timeout: 10000 }).should('include', constants.homeUrl + safe)
}

export function checkTextsExistWithinElement(element, texts) {
texts.forEach((text) => {
cy.wrap(element).findByText(text).should('exist')
})
}

export function verifyCheckboxeState(element, index, state) {
cy.get(element).eq(index).should(state)
}
193 changes: 193 additions & 0 deletions cypress/e2e/pages/safeapps.pages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
import * as constants from '../../support/constants'

const searchAppInput = 'input[id="search-by-name"]'
const appUrlInput = 'input[name="appUrl"]'
const closePreviewWindowBtn = 'button[aria-label*="Close"][aria-label*="preview"]'

const addBtnStr = /add/i
const noAppsStr = /no Safe Apps found/i
const bookmarkedAppsStr = /bookmarked Apps/i
const customAppsStr = /my custom Apps/i
const addCustomAppBtnStr = /add custom Safe App/i
const openSafeAppBtnStr = /open Safe App/i
const disclaimerTtle = /disclaimer/i
const continueBtnStr = /continue/i
const cameraCheckBoxStr = /camera/i
const microfoneCheckBoxStr = /microphone/i
const permissionRequestStr = /permissions request/i
const accessToAddressBookStr = /access to your address book/i
const acceptBtnStr = /accept/i
const clearAllBtnStr = /clear all/i
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 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 localStorageItem =
'{"https://safe-test-app.com":[{"feature":"camera","status":"granted"},{"feature":"microphone","status":"denied"}]}'
export const gridItem = 'main .MuiPaper-root > .MuiGrid-item'
export const linkNames = {
logo: /logo/i,
}

export const permissionCheckboxes = {
camera: 'input[name="camera"]',
addressbook: 'input[name="requestAddressBook"]',
microphone: 'input[name="microphone"]',
geolocation: 'input[name="geolocation"]',
fullscreen: 'input[name="fullscreen"]',
}

export const permissionCheckboxNames = {
camera: 'Camera',
addressbook: 'Address Book',
microphone: 'Microphone',
geolocation: 'Geolocation',
fullscreen: 'Fullscreen',
}
export function typeAppName(name) {
cy.get(searchAppInput).clear().type(name)
}

export function clearSearchAppInput() {
cy.get(searchAppInput).clear()
}

export function verifyLinkName(name) {
cy.findAllByRole('link', { name: name }).should('have.length', 1)
}

export function clickOnApp(app) {
cy.findByRole('link', { name: app }).click()
}

export function verifyNoAppsTextPresent() {
cy.contains(noAppsStr).should('exist')
}

export function pinApp(app, pin = true) {
let str = 'Unpin'
if (!pin) str = 'Pin'
cy.findByLabelText(app)
.click()
.should(($el) => {
const ariaLabel = $el.attr('aria-label')
expect(ariaLabel).to.include(str)
})
}

export function clickOnBookmarkedAppsTab() {
cy.findByText(bookmarkedAppsStr).click()
}

export function verifyAppCount(count) {
cy.findByText(`ALL (${count})`).should('be.visible')
}

export function clickOnCustomAppsTab() {
cy.findByText(customAppsStr).click()
}

export function clickOnAddCustomApp() {
cy.findByText(addCustomAppBtnStr).click()
}

export function typeCustomAppUrl(url) {
cy.get(appUrlInput).clear().type(url)
}

export function verifyAppNotSupportedMsg() {
cy.contains(appNotSupportedMsg).should('be.visible')
}

export function verifyAppTitle(title) {
cy.findByRole('heading', { name: title }).should('exist')
}

export function acceptTC() {
cy.findByRole('checkbox').click()
}

export function clickOnAddBtn() {
cy.findByRole('button', { name: addBtnStr }).click()
}

export function verifyAppDescription(descr) {
cy.findByText(descr).should('exist')
}

export function clickOnOpenSafeAppBtn() {
cy.findByRole('link', { name: openSafeAppBtnStr }).click()
cy.wait(500)
verifyDisclaimerIsVisible()
cy.wait(500)
}

function verifyDisclaimerIsVisible() {
cy.findByRole('heading', { name: disclaimerTtle }).should('be.visible')
}

export function clickOnContinueBtn() {
return cy.findByRole('button', { name: continueBtnStr }).click()
}

export function verifyCameraCheckBoxExists() {
cy.findByRole('checkbox', { name: cameraCheckBoxStr }).should('exist')
}

export function verifyMicrofoneCheckBoxExists() {
return cy.findByRole('checkbox', { name: microfoneCheckBoxStr }).should('exist')
}

export function storeAndVerifyPermissions() {
cy.waitForSelector(() => {
return cy
.findByRole('button', { name: continueBtnStr })
.click()
.wait(500)
.should(() => {
const storedBrowserPermissions = JSON.parse(localStorage.getItem(constants.BROWSER_PERMISSIONS_KEY))
const browserPermissions = Object.values(storedBrowserPermissions)[0][0]
const storedInfoModal = JSON.parse(localStorage.getItem(constants.INFO_MODAL_KEY))

expect(browserPermissions.feature).to.eq('camera')
expect(browserPermissions.status).to.eq('granted')
expect(storedInfoModal['5'].consentsAccepted).to.eq(true)
})
})
}

export function verifyPreviewWindow(str1, str2, str3) {
cy.findByRole('heading', { name: str1 }).should('exist')
cy.findByText(str2).should('exist')
cy.findByText(str3).should('exist')
}

export function closePreviewWindow() {
cy.get(closePreviewWindowBtn).click()
}

export function verifyPermissionsRequestExists() {
cy.findByRole('heading', { name: permissionRequestStr }).should('exist')
}

export function verifyAccessToAddressBookExists() {
cy.findByText(accessToAddressBookStr).should('exist')
}

export function clickOnAcceptBtn() {
cy.findByRole('button', { name: acceptBtnStr }).click()
}

export function uncheckAllPermissions(element) {
cy.wrap(element).findByText(clearAllBtnStr).click()
}

export function checkAllPermissions(element) {
cy.wrap(element).findByText(allowAllPermissions).click()
}
Loading

0 comments on commit ec9408c

Please sign in to comment.