Skip to content

Commit

Permalink
✨ feat: Test cases for network management and new tokens deployment (#…
Browse files Browse the repository at this point in the history
…1193)

* feat: Test cases for network management and new tokens deployment

* fix: cypress tests befores and afters

* fix: Network type imports
  • Loading branch information
matstyler authored Aug 6, 2024
1 parent ae7c111 commit b715a00
Show file tree
Hide file tree
Showing 13 changed files with 263 additions and 28 deletions.
97 changes: 96 additions & 1 deletion wallets/metamask/src/cypress/configureSynpress.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import type { BrowserContext, Page } from '@playwright/test'
import { expect } from '@playwright/test'
import { ensureRdpPort } from '@synthetixio/synpress-core'
import { type CreateAnvilOptions, createPool } from '@viem/anvil'
import { waitFor } from '../playwright/utils/waitFor'
import HomePageSelectors from '../selectors/pages/HomePage'
import Selectors from '../selectors/pages/HomePage'
import type { Network } from '../type/Network'
import getPlaywrightMetamask from './getPlaywrightMetamask'
import importMetaMaskWallet from './support/importMetaMaskWallet'
import { initMetaMask } from './support/initMetaMask'
Expand Down Expand Up @@ -118,7 +122,7 @@ export default function configureSynpress(on: Cypress.PluginEvents, config: Cypr

await metamask.renameAccount(currentAccountName, newAccountName)

await metamaskExtensionPage.locator(Selectors.threeDotsMenu.accountDetailsCloseButton).click()
await metamaskExtensionPage.locator(HomePageSelectors.threeDotsMenu.accountDetailsCloseButton).click()

await expect(metamaskExtensionPage.locator(metamask.homePage.selectors.accountMenu.accountButton)).toHaveText(
newAccountName
Expand Down Expand Up @@ -146,6 +150,84 @@ export default function configureSynpress(on: Cypress.PluginEvents, config: Cypr
})
},

async createAnvilNode(options?: CreateAnvilOptions) {
const pool = createPool()

const nodeId = Array.from(pool.instances()).length
const anvil = await pool.start(nodeId, options)

const rpcUrl = `http://${anvil.host}:${anvil.port}`

const DEFAULT_ANVIL_CHAIN_ID = 31337
const chainId = options?.chainId ?? DEFAULT_ANVIL_CHAIN_ID

return { anvil, rpcUrl, chainId }
},

async connectToAnvil({
rpcUrl,
chainId
}: {
rpcUrl: string
chainId: number
}) {
const metamask = getPlaywrightMetamask(context, metamaskExtensionPage, metamaskExtensionId)

try {
await metamask.addNetwork({
name: 'Anvil',
rpcUrl,
chainId,
symbol: 'ETH',
blockExplorerUrl: 'https://etherscan.io/'
})

await metamask.switchNetwork('Anvil')
return true
} catch (e) {
console.error('Error connecting to Anvil network', e)
return false
}
},

async addNetwork(network: Network) {
const metamask = getPlaywrightMetamask(context, metamaskExtensionPage, metamaskExtensionId)

await metamask.addNetwork(network)

await waitFor(
() => metamaskExtensionPage.locator(HomePageSelectors.networkAddedPopover.switchToNetworkButton).isVisible(),
3_000,
false
)

await metamaskExtensionPage.locator(HomePageSelectors.networkAddedPopover.switchToNetworkButton).click()

return true
},

// Token

async deployToken() {
const metamask = getPlaywrightMetamask(context, metamaskExtensionPage, metamaskExtensionId)

await metamask.confirmTransaction()

return true
},

async addNewToken() {
const metamask = getPlaywrightMetamask(context, metamaskExtensionPage, metamaskExtensionId)

await metamask.addNewToken()

await expect(metamaskExtensionPage.locator(Selectors.portfolio.singleToken).nth(1)).toContainText('TST')

return true
},

// Others

async providePublicEncryptionKey() {
const metamask = getPlaywrightMetamask(context, metamaskExtensionPage, metamaskExtensionId)

Expand Down Expand Up @@ -183,6 +265,19 @@ export default function configureSynpress(on: Cypress.PluginEvents, config: Cypr
.catch(() => {
return false
})
},

async confirmTransaction() {
const metamask = getPlaywrightMetamask(context, metamaskExtensionPage, metamaskExtensionId)

return await metamask
.confirmTransaction()
.then(() => {
return true
})
.catch(() => {
return false
})
}
})

Expand Down
59 changes: 59 additions & 0 deletions wallets/metamask/src/cypress/support/synpressCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
// https://on.cypress.io/custom-commands
// ***********************************************

import type { Anvil, CreateAnvilOptions } from '@viem/anvil'
import type { Network } from '../../type/Network'

declare global {
namespace Cypress {
interface Chainable {
Expand All @@ -22,9 +25,21 @@ declare global {
renameAccount(currentAccountName: string, newAccountName: string): Chainable<void>

switchNetwork(networkName: string, isTestnet?: boolean): Chainable<void>
createAnvilNode(options?: CreateAnvilOptions): Chainable<{
anvil: Anvil
rpcUrl: string
chainId: number
}>
connectToAnvil(): Chainable<void>
addNetwork(network: Network): Chainable<void>

deployToken(): Chainable<void>
addNewToken(): Chainable<void>

providePublicEncryptionKey(): Chainable<void>
decrypt(): Chainable<void>
confirmSignature(): Chainable<void>
confirmTransaction(): Chainable<void>
}
}
}
Expand All @@ -41,6 +56,8 @@ export default function synpressCommands() {
return cy.task('connectToDapp')
})

// Account

Cypress.Commands.add('addNewAccount', (accountName: string) => {
return cy.task('addNewAccount', accountName)
})
Expand All @@ -51,9 +68,48 @@ export default function synpressCommands() {
return cy.task('renameAccount', { currentAccountName, newAccountName })
})

// Network

Cypress.Commands.add('switchNetwork', (networkName: string, isTestnet = false) => {
return cy.task('switchNetwork', { networkName, isTestnet })
})
Cypress.Commands.add('createAnvilNode', (options?: CreateAnvilOptions) => {
return cy.task('createAnvilNode', options)
})
Cypress.Commands.add('connectToAnvil', () => {
return cy.task('createAnvilNode').then((anvilNetwork) => {
const anvilNetworkDetails = anvilNetwork as {
anvil: Anvil
rpcUrl: string
chainId: number
}

const network = {
name: 'Anvil',
rpcUrl: anvilNetworkDetails.rpcUrl,
chainId: anvilNetworkDetails.chainId,
symbol: 'ETH',
blockExplorerUrl: 'https://etherscan.io/'
}

return cy.task('addNetwork', network)
})
})
Cypress.Commands.add('addNetwork', (network: Network) => {
return cy.task('addNetwork', network)
})

// Token

Cypress.Commands.add('deployToken', () => {
return cy.task('deployToken')
})
Cypress.Commands.add('addNewToken', () => {
return cy.task('addNewToken')
})

// Others

Cypress.Commands.add('providePublicEncryptionKey', () => {
return cy.task('providePublicEncryptionKey')
})
Expand All @@ -63,4 +119,7 @@ export default function synpressCommands() {
Cypress.Commands.add('confirmSignature', () => {
return cy.task('confirmSignature')
})
Cypress.Commands.add('confirmTransaction', () => {
return cy.task('confirmTransaction')
})
}
2 changes: 1 addition & 1 deletion wallets/metamask/src/playwright/MetaMask.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { BrowserContext, Page } from '@playwright/test'
import { SettingsSidebarMenus } from '../selectors/pages/HomePage/settings'
import { MetaMaskAbstract } from '../type/MetaMaskAbstract'
import type { Network } from '../type/Network'
import { CrashPage, HomePage, LockPage, NotificationPage, OnboardingPage } from './pages'
import type { Network } from './pages/HomePage/actions'
import type { GasSetting } from './pages/NotificationPage/actions'
import { SettingsPage } from './pages/SettingsPage/page'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
import type { Page } from '@playwright/test'
import { z } from 'zod'
import Selectors from '../../../../selectors/pages/HomePage'
import { type Network, NetworkValidation } from '../../../../type/Network'
import { waitFor } from '../../../utils/waitFor'
import { closeNetworkAddedPopover, closeNewNetworkInfoPopover } from './popups'

const Network = z.object({
name: z.string(),
rpcUrl: z.string(),
chainId: z.number(),
symbol: z.string(),
blockExplorerUrl: z.string().optional()
})

export type Network = z.infer<typeof Network>

export async function addNetwork(page: Page, network: Network) {
const { name, rpcUrl, chainId, symbol, blockExplorerUrl } = Network.parse(network)
const { name, rpcUrl, chainId, symbol, blockExplorerUrl } = NetworkValidation.parse(network)

await page.locator(Selectors.networkDropdown.dropdownButton).click()
await page.locator(Selectors.networkDropdown.addNetworkButton).click()
Expand Down
2 changes: 1 addition & 1 deletion wallets/metamask/src/playwright/pages/HomePage/page.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Page } from '@playwright/test'
import Selectors from '../../../selectors/pages/HomePage'
import type { SettingsSidebarMenus } from '../../../selectors/pages/HomePage/settings'
import type { Network } from '../../../type/Network'
import {
addNetwork,
addNewAccount,
Expand All @@ -14,7 +15,6 @@ import {
toggleShowTestNetworks,
transactionDetails
} from './actions'
import type { Network } from './actions'

export class HomePage {
static readonly selectors = Selectors
Expand Down
2 changes: 1 addition & 1 deletion wallets/metamask/src/selectors/pages/HomePage/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const popover = {
}

const networkAddedPopover = {
switchToNetworkButton: '.home__new-network-added button.btn-primary',
switchToNetworkButton: '.home__new-network-added__switch-to-button',
dismissButton: '.home__new-network-added button.btn-secondary'
}

Expand Down
2 changes: 1 addition & 1 deletion wallets/metamask/src/type/MetaMaskAbstract.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Network } from '../playwright/pages/HomePage/actions'
import type { GasSetting } from '../playwright/pages/NotificationPage/actions'
import { SettingsSidebarMenus } from '../selectors/pages/HomePage/settings'
import type { Network } from './Network'

export abstract class MetaMaskAbstract {
/**
Expand Down
11 changes: 11 additions & 0 deletions wallets/metamask/src/type/Network.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { z } from 'zod'

export const NetworkValidation = z.object({
name: z.string(),
rpcUrl: z.string(),
chainId: z.number(),
symbol: z.string(),
blockExplorerUrl: z.string().optional()
})

export type Network = z.infer<typeof NetworkValidation>
31 changes: 31 additions & 0 deletions wallets/metamask/test/cypress/addNetwork.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
it('should add network and close network added popup', () => {
cy.createAnvilNode().then(({ rpcUrl, chainId }) => {
const network = {
name: 'Anvil',
rpcUrl,
chainId,
symbol: 'ETH',
blockExplorerUrl: 'https://etherscan.io/'
}

cy.addNetwork(network).then(() => cy.getNetwork().should('eq', 'Anvil'))
})
})

it('should add network without block explorer', () => {
cy.createAnvilNode().then(({ rpcUrl, chainId }) => {
const network = {
name: 'Anvil2',
rpcUrl,
chainId,
symbol: 'ETH',
blockExplorerUrl: undefined
}

cy.addNetwork(network).then(() => cy.getNetwork().should('eq', 'Anvil2'))
})
})

after(() => {
cy.switchNetwork('Anvil', true)
})
42 changes: 42 additions & 0 deletions wallets/metamask/test/cypress/addNewToken.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
before(() => {
cy.getNetwork().then((network) => {
console.log(network)
if (network !== 'Anvil') {
cy.switchNetwork('Anvil')
}
})

cy.get('#connectButton').click()

cy.connectToDapp()
})

it('should add new token to MetaMask', () => {
cy.get('#createToken').click()

// wait for the blockchain - todo: replace with an event handler
cy.wait(5000)

cy.deployToken().then(() => {
// wait for the blockchain - todo: replace with an event handler
cy.wait(5000)

cy.get('#tokenAddresses').should('have.text', '0x7ef8E99980Da5bcEDcF7C10f41E55f759F6A174B')

cy.get('#watchAssets').click()

cy.addNewToken()
})
})

it('should add new token using EIP747', () => {
cy.get('#eip747ContractAddress').type('0x5FbDB2315678afecb367f032d93F642f64180aa3')
cy.get('#eip747Symbol').type('TST')
cy.get('#eip747Decimals').type('4')

cy.get('#eip747WatchButton').click()

cy.addNewToken().then(() => {
cy.get('#eip747Status').should('have.text', 'NFT added successfully')
})
})
Loading

0 comments on commit b715a00

Please sign in to comment.