diff --git a/README.md b/README.md index 5466959f..17efecfe 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,23 @@ it directly. Check [usage examples](https://github.com/Synthetixio/synpress/#usage-examples) for more details. -## Install +# Table of content + +- [๐Ÿ–ฅ๏ธ Install](#%EF%B8%8F-install) +- [โš™๏ธ Supported frameworks](#%EF%B8%8F-supported-frameworks) +- [๐Ÿ‘ Supported wallets](#-supported-wallets) +- [โœ๏ธ Usage examples](#%EF%B8%8F-usage-examples) +- [๐ŸŒŸ Features](#-features) +- [๐Ÿ‘ท Example setup for eslint and tsconfig](#-example-setup-for-eslint-and-tsconfig) +- [โšก Important notes](#-important-notes) +- [๐Ÿณ Synpress + Docker](#-using-with-docker) +- [๐Ÿ’โ€โ™‚๏ธ CI tips & tricks](#%EF%B8%8F-ci-tips--tricks) +- [๐Ÿงช CLI](#-usage--commands) +- [๐Ÿ“ƒ Environmental variables](#-environmental-variables) +- [๐Ÿšข Release process](#-release-process) +- [๐Ÿ“ More resources](#-more-resources) + +## ๐Ÿ–ฅ๏ธ Install ```bash # with pnpm @@ -72,20 +88,20 @@ npm install --save-dev @synthetixio/synpress yarn add -D @synthetixio/synpress ``` -## Supported frameworks +## โš™๏ธ Supported frameworks - [Synpress](https://github.com/Synthetixio/synpress) - [Playwright](https://playwright.dev/) (as a plugin) - [Cypress](https://github.com/cypress-io/cypress) (as a plugin) -## Supported wallets +## ๐Ÿ‘ Supported wallets - [MetaMask](https://metamask.io/) -## Usage examples: +## โœ๏ธ Usage examples: -- โญ [synpress-examples](https://github.com/drptbl/synpress-examples/) -- [synpress](https://github.com/Synthetixio/synpress/tree/dev/tests/e2e) +- [โญ Synpress examples](https://github.com/drptbl/synpress-examples/) +- [Synpress e2e tests](https://github.com/Synthetixio/synpress/tree/dev/tests/e2e) --- @@ -95,7 +111,7 @@ For full Synpress commands and their examples, To see in which direction Synpress is headed to, take a look at [planning board](https://github.com/orgs/Synthetixio/projects/14). -## Features +## ๐ŸŒŸ Features - Added support for metamask ๐ŸฆŠ - Supports headless mode ๐Ÿค– (`synpress run --headless`) @@ -103,7 +119,7 @@ To see in which direction Synpress is headed to, take a look at [not for CI yet](https://developer.chrome.com/articles/new-headless/) as it's new and experimental) - Integrated with - [docker ๐Ÿณ](https://github.com/Synthetixio/synpress#-using-with-docker) + [Docker ๐Ÿณ](https://github.com/Synthetixio/synpress#-using-with-docker) - Recommended for [CI](https://github.com/Synthetixio/synpress#ci-tips--tricks) - Includes VNC and [noVNC](https://novnc.com/info.html) @@ -118,7 +134,7 @@ To see in which direction Synpress is headed to, take a look at - Blazingly-fast โšก - Extensible โš™๏ธ (add own custom commands and plugins) - Can be used in existing - [cypress setup](https://github.com/Synthetixio/synpress/issues/346#issuecomment-1060506096) + [Cypress setup](https://github.com/Synthetixio/synpress/issues/346#issuecomment-1060506096) - Supports dotenv - Loads all env vars from your `.env` file automatically (from project root folder) @@ -213,7 +229,7 @@ and then modify it for your needs. Then you can direct synpress to use it with For example: `synpress run --configFile __tests__/e2e/customConfig.config.js` -## โšก Important +## โšก Important notes Synpress doesn't seem to communicate with metamask properly if `"chromeWebSecurity": false` flag is set. More about it @@ -230,7 +246,7 @@ In the past, tests worked only in non-headless mode because extensions were not supported in headless mode by [playwright](https://playwright.dev/docs/chrome-extensions) and [Cypress](https://docs.cypress.io/api/plugins/browser-launch-api.html#Add-browser-extensions). -As a workaround, we've provided docker ๐Ÿณ containers. They solved this issue and +As a workaround, we've provided Docker ๐Ÿณ containers. They solved this issue and it's an alternative. You have to setup `xvfb` and window manager (like `fluxbox` or `xfce4`) to run @@ -306,8 +322,8 @@ introduce delay between every action, 50ms by default) / `SLOW_MODE=`. following features: - improved logging -- [cypress debugger](https://docs.cypress.io/guides/guides/debugging) -- [playwright debugger](https://playwright.dev/docs/debug) +- [Cypress debugger](https://docs.cypress.io/guides/guides/debugging) +- [Playwright debugger](https://playwright.dev/docs/debug) - slow down tests You may encounter 403 errors (on shared IPs & CI) related to rate limiting while @@ -335,7 +351,7 @@ Docker is awesome for CI. Give it a try. - remote: https://.ngrok.io/vnc.html?autoconnect=true (check logs for url) -### How to use +### How to run e2e tests for Synpress using Docker 1. `git clone git@github.com:Synthetixio/synpress.git` 2. `cd synpress` @@ -350,7 +366,7 @@ Docker is awesome for CI. Give it a try. All examples of setup are present in this repository. Just take a look around. -## CI tips & tricks +## ๐Ÿ’โ€โ™‚๏ธ CI tips & tricks - check out many different [examples in this repository](https://github.com/Synthetixio/synpress/tree/dev/.github/workflows): @@ -367,7 +383,7 @@ All examples of setup are present in this repository. Just take a look around. - use [docker-e2e](https://github.com/Synthetixio/docker-e2e) - synpress is tested and should work on all resolutions, starting from 800x600 -## ๐Ÿงช Usage +## ๐Ÿงช Usage & commands - `synpress run` to run tests - `synpress open` to open Cypress UI (may be bugged in some cases because it @@ -409,7 +425,7 @@ Options: -h, --help display help for command ``` -## Environmental variables +## ๐Ÿ“ƒ Environmental variables | Variable | Description | | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -455,8 +471,9 @@ Above actions will lead to: - New GitHub packages node module release - New GitHub release (tagged) created with changelog from commit messages -## ๐Ÿ“ƒ More resources +## ๐Ÿ“ More resources +- [End-to-end testing using Synpress](https://klaytn.foundation/synpress-setup-tutorial/) - [Synpress - web3-enabled e2e testing tool](https://gitcoin.co/grants/5699/synpress-web3-enabled-e2e-testing-tool) - [How to set up Synpress for Web3 dApp Frontend Test Automation with MetaMask](https://medium.com/andamp/how-to-setup-synpress-for-wen3-dapp-frontend-test-automation-with-metamask-73396896684a) - [Extending Synpress with additional MetaMask commands](https://medium.com/andamp/extending-synpress-with-additional-metamask-commands-fdc6b35a2ffc) diff --git a/commands/etherscan.js b/commands/etherscan.js index 85e89e0b..7dc2a5ac 100644 --- a/commands/etherscan.js +++ b/commands/etherscan.js @@ -4,8 +4,8 @@ let retries = 0; module.exports = { async getTransactionStatus(txid) { - const { getNetwork } = require('../helpers'); - const currentNetwork = getNetwork().networkName; + const { getCurrentNetwork } = require('../helpers'); + const currentNetwork = getCurrentNetwork().name; const etherscanApi = require('etherscan-api').init( process.env.ETHERSCAN_KEY, currentNetwork, diff --git a/commands/metamask.js b/commands/metamask.js index 3606afc5..333d65ce 100644 --- a/commands/metamask.js +++ b/commands/metamask.js @@ -32,7 +32,13 @@ const { const { confirmationPageElements, } = require('../pages/metamask/confirmation-page'); -const { setNetwork, getNetwork } = require('../helpers'); +const { + setNetwork, + addNetwork, + findNetwork, + checkNetworkAdded, + getCurrentNetwork, +} = require('../helpers'); let extensionInitialUrl; let extensionId; @@ -127,10 +133,10 @@ const metamask = { // otherwise popup may not be detected properly and not closed await playwright.metamaskWindow().waitForTimeout(1000); if ( - await playwright + (await playwright .metamaskWindow() .locator(mainPageElements.popup.container) - .isVisible() + .count()) > 0 ) { const popupBackground = playwright .metamaskWindow() @@ -141,18 +147,18 @@ const metamask = { .mouse.click(popupBackgroundBox.x + 1, popupBackgroundBox.y + 1); } if ( - await playwright + (await playwright .metamaskWindow() .locator(mainPageElements.tippyTooltip.closeButton) - .isVisible() + .count()) > 0 ) { await playwright.waitAndClick(mainPageElements.tippyTooltip.closeButton); } if ( - await playwright + (await playwright .metamaskWindow() .locator(mainPageElements.actionableMessage.closeButton) - .isVisible() + .count()) > 0 ) { await playwright.waitAndClick( mainPageElements.actionableMessage.closeButton, @@ -165,10 +171,10 @@ const metamask = { // otherwise modal may not be detected properly and not closed await playwright.metamaskWindow().waitForTimeout(1000); if ( - await playwright + (await playwright .metamaskWindow() .locator(mainPageElements.connectedSites.modal) - .isVisible() + .count()) > 0 ) { await playwright.waitAndClick( mainPageElements.connectedSites.closeButton, @@ -372,114 +378,137 @@ const metamask = { return true; }, async changeNetwork(network) { - const currentNetwork = getNetwork(); + // check if network is available in presets + if (typeof network === 'string') { + network = await findNetwork(network); + } - if ( - typeof network === 'string' && - (currentNetwork.networkDisplayName === network.toLowerCase() || - currentNetwork.networkName === network.toLowerCase()) - ) + // handle a case if network is already changed + const currentNetwork = getCurrentNetwork(); + if (network === currentNetwork) { return false; + } - if ( - typeof network === 'object' && - (currentNetwork.networkDisplayName === - network.networkName.toLowerCase() || - currentNetwork.networkName === network.networkName.toLowerCase()) - ) - return false; + // uncomment to automatically add network if not added yet + // const networkAdded = await checkNetworkAdded(network); + // if (!networkAdded) { + // await module.exports.addNetwork(network); + // return true; + // } await switchToMetamaskIfNotActive(); await playwright.waitAndClick(mainPageElements.networkSwitcher.button); - if (typeof network === 'string') { - network = network.toLowerCase(); - if (network === 'mainnet') { - await playwright.waitAndClick( - mainPageElements.networkSwitcher.mainnetNetworkItem, - ); - } else if (network === 'goerli') { - await playwright.waitAndClick( - mainPageElements.networkSwitcher.goerliNetworkItem, - ); - } else if (network === 'sepolia') { - await playwright.waitAndClick( - mainPageElements.networkSwitcher.sepoliaNetworkItem, - ); - } else if (network === 'localhost') { - await playwright.waitAndClick( - mainPageElements.networkSwitcher.localhostNetworkItem, - ); - } else { - await playwright.waitAndClickByText( - mainPageElements.networkSwitcher.dropdownMenuItem, - network, - ); - } - await playwright.waitForText( - mainPageElements.networkSwitcher.networkName, - network, - ); - } else if (typeof network === 'object') { - network.networkName = network.networkName.toLowerCase(); - await playwright.waitAndClickByText( - mainPageElements.networkSwitcher.dropdownMenuItem, - network.networkName, - ); - await playwright.waitForText( - mainPageElements.networkSwitcher.networkName, - network.networkName, - ); - } + + await playwright.waitAndClickByText( + mainPageElements.networkSwitcher.dropdownMenuItem, + network.name, + ); + await playwright.waitForText( + mainPageElements.networkSwitcher.networkName, + network.name, + ); + await playwright.waitUntilStable(); await module.exports.closePopupAndTooltips(); + // set network to currently active await setNetwork(network); await switchToCypressIfNotActive(); return true; }, async addNetwork(network) { - await switchToMetamaskIfNotActive(); + // check if available in presets + if (typeof network === 'string') { + network = await findNetwork(network); + } + + // backward compatibility with older synpress versions + if ( + typeof network === 'object' && + (network.name || network.networkName) && + network.rpcUrl && + network.chainId && + network.symbol + ) { + network = { + id: network.chainId, + name: network.name || network.networkName, + nativeCurrency: { + symbol: network.symbol, + }, + rpcUrls: { + public: { http: [network.rpcUrl] }, + default: { http: [network.rpcUrl] }, + }, + testnet: network.isTestnet, + }; + + if (network.blockExplorer) { + network.blockExplorers = { + etherscan: { url: network.blockExplorer }, + default: { url: network.blockExplorer }, + }; + } + } + + // dont add network if already present + const networkAlreadyAdded = await checkNetworkAdded(network); + if (networkAlreadyAdded) { + // uncomment to automatically change network if it was already added + // await module.exports.changeNetwork(network); + return false; + } + + // handle adding network with env vars if ( process.env.NETWORK_NAME && process.env.RPC_URL && - process.env.CHAIN_ID + process.env.CHAIN_ID && + process.env.SYMBOL ) { network = { - networkName: process.env.NETWORK_NAME, - rpcUrl: process.env.RPC_URL, - chainId: process.env.CHAIN_ID, - symbol: process.env.SYMBOL, - blockExplorer: process.env.BLOCK_EXPLORER, - isTestnet: process.env.IS_TESTNET, + id: process.env.CHAIN_ID, + name: process.env.NETWORK_NAME, + nativeCurrency: { + symbol: process.env.SYMBOL, + }, + rpcUrls: { + public: { http: [process.env.RPC_URL] }, + default: { http: [process.env.RPC_URL] }, + }, + blockExplorers: { + etherscan: { url: process.env.BLOCK_EXPLORER }, + default: { url: process.env.BLOCK_EXPLORER }, + }, + testnet: process.env.IS_TESTNET, }; } - if (typeof network === 'string') { - network = network.toLowerCase(); - } else if (typeof network === 'object') { - network.networkName = network.networkName.toLowerCase(); - } + + // add network to presets + await addNetwork(network); + + await switchToMetamaskIfNotActive(); + await module.exports.goToAddNetwork(); await playwright.waitAndType( addNetworkPageElements.networkNameInput, - network.networkName, + network.name, ); await playwright.waitAndType( addNetworkPageElements.rpcUrlInput, - network.rpcUrl, + network.rpcUrls.default.http[0], ); await playwright.waitAndType( addNetworkPageElements.chainIdInput, - network.chainId, + network.id, + ); + await playwright.waitAndType( + addNetworkPageElements.symbolInput, + network.nativeCurrency.symbol, ); - if (network.symbol) { - await playwright.waitAndType( - addNetworkPageElements.symbolInput, - network.symbol, - ); - } if (network.blockExplorer) { await playwright.waitAndType( addNetworkPageElements.blockExplorerInput, - network.blockExplorer, + network.blockExplorers.default.url, ); } await playwright.waitAndClick( @@ -490,11 +519,12 @@ const metamask = { }, ); await module.exports.closePopupAndTooltips(); - await setNetwork(network); await playwright.waitForText( mainPageElements.networkSwitcher.networkName, - network.networkName, + network.name, ); + // set as currently active network + await setNetwork(network); await switchToCypressIfNotActive(); return true; }, @@ -505,10 +535,10 @@ const metamask = { mainPageElements.optionsMenu.connectedSitesButton, ); if ( - await playwright + (await playwright .metamaskWindow() .locator(mainPageElements.connectedSites.disconnectLabel) - .isVisible() + .count()) > 0 ) { console.log( '[disconnectWalletFromDapp] Wallet is connected to a dapp, disconnecting..', @@ -635,10 +665,10 @@ const metamask = { async confirmSignatureRequest() { const notificationPage = await playwright.switchToMetamaskNotification(); if ( - await playwright + (await playwright .metamaskNotificationWindow() .locator(signaturePageElements.signatureRequestScrollDownButton) - .isVisible() + .count()) > 0 ) { await playwright.waitAndClick( signaturePageElements.signatureRequestScrollDownButton, @@ -664,10 +694,10 @@ const metamask = { async confirmDataSignatureRequest() { const notificationPage = await playwright.switchToMetamaskNotification(); if ( - await playwright + (await playwright .metamaskNotificationWindow() .locator(signaturePageElements.signatureRequestScrollDownButton) - .isVisible() + .count()) > 0 ) { await playwright.waitAndClick( signaturePageElements.signatureRequestScrollDownButton, @@ -773,10 +803,10 @@ const metamask = { const notificationPage = await playwright.switchToMetamaskNotification(); // experimental mode on if ( - await playwright + (await playwright .metamaskNotificationWindow() .locator(notificationPageElements.customSpendingLimitInput) - .isVisible() + .count()) > 0 ) { await playwright.waitAndSetValue( spendLimit, @@ -865,10 +895,10 @@ const metamask = { '[confirmTransaction] gasConfig is present, determining transaction type..', ); if ( - await playwright + (await playwright .metamaskNotificationWindow() .locator(confirmPageElements.editGasFeeLegacyButton) - .isVisible() + .count()) > 0 ) { log('[confirmTransaction] Looks like legacy tx'); if (typeof gasConfig === 'object') { @@ -878,10 +908,10 @@ const metamask = { notificationPage, ); if ( - await playwright + (await playwright .metamaskNotificationWindow() .locator(confirmPageElements.editGasFeeLegacyOverrideAckButton) - .isVisible() + .count()) > 0 ) { log( '[confirmTransaction] Override acknowledgement modal is present, closing..', @@ -991,10 +1021,10 @@ const metamask = { } log('[confirmTransaction] Checking if recipient address is present..'); if ( - await playwright + (await playwright .metamaskNotificationWindow() .locator(confirmPageElements.recipientButton) - .isVisible() + .count()) > 0 ) { log('[confirmTransaction] Getting recipient address..'); await playwright.waitAndClick( @@ -1012,10 +1042,10 @@ const metamask = { } log('[confirmTransaction] Checking if network name is present..'); if ( - await playwright + (await playwright .metamaskNotificationWindow() .locator(confirmPageElements.networkLabel) - .isVisible() + .count()) > 0 ) { log('[confirmTransaction] Getting network name..'); txData.networkName = await playwright.waitAndGetValue( @@ -1036,7 +1066,7 @@ const metamask = { // await playwright // .metamaskNotificationWindow() // .locator(confirmPageElements.dataButton) - // .isVisible() + // .count() > 0 // ) { // log('[confirmTransaction] Fetching tx data..'); // await playwright.waitAndClick( @@ -1218,7 +1248,8 @@ const metamask = { const isCustomNetwork = (process.env.NETWORK_NAME && process.env.RPC_URL && - process.env.CHAIN_ID) || + process.env.CHAIN_ID && + process.env.SYMBOL) || typeof network == 'object'; if (playwrightInstance) { await playwright.init(playwrightInstance); @@ -1231,10 +1262,10 @@ const metamask = { await playwright.fixBlankPage(); await playwright.fixCriticalError(); if ( - await playwright + (await playwright .metamaskWindow() .locator(onboardingWelcomePageElements.onboardingWelcomePage) - .isVisible() + .count()) > 0 ) { if (secretWordsOrPrivateKey.includes(' ')) { // secret words @@ -1256,10 +1287,10 @@ const metamask = { await playwright.switchToCypressWindow(); return true; } else if ( - await playwright + (await playwright .metamaskWindow() .locator(unlockPageElements.passwordInput) - .isVisible() + .count()) > 0 ) { await module.exports.unlock(password); walletAddress = await module.exports.getWalletAddress(); @@ -1270,7 +1301,7 @@ const metamask = { (await playwright .metamaskWindow() .locator(mainPageElements.walletOverview) - .isVisible()) && + .count()) > 0 && !process.env.RESET_METAMASK ) { await switchToMetamaskIfNotActive(); @@ -1314,7 +1345,7 @@ async function activateAdvancedSetting( await metamask.goToAdvancedSettings(); } } - if (!(await playwright.metamaskWindow().locator(toggleOn).isVisible())) { + if ((await playwright.metamaskWindow().locator(toggleOn).count()) === 0) { await playwright.waitAndClick(toggleOff); } if (!skipSetup) { @@ -1345,8 +1376,8 @@ async function setupSettings( if (enableAdvancedSettings) { await metamask.activateTestnetConversion(true); } - await metamask.goToExperimentalSettings(); if (enableExperimentalSettings) { + await metamask.goToExperimentalSettings(); await metamask.activateImprovedTokenAllowance(true); } await playwright.waitAndClick( diff --git a/commands/playwright.js b/commands/playwright.js index b152ff4a..b44acde3 100644 --- a/commands/playwright.js +++ b/commands/playwright.js @@ -182,11 +182,14 @@ module.exports = { }, async waitAndClickByText(selector, text, page = metamaskWindow) { await module.exports.waitFor(selector, page); - const element = page.locator(`text=${text}`); - await element.click(); + const element = `:is(:text-is("${text}"), :text("${text}"))`; + await page.click(element); await module.exports.waitUntilStable(); }, async waitAndType(selector, value, page = metamaskWindow) { + if (typeof value === 'number') { + value = value.toString(); + } const element = await module.exports.waitFor(selector, page); await element.type(value); await module.exports.waitUntilStable(page); @@ -253,7 +256,7 @@ module.exports = { // info: waits for 60 seconds const locator = page.locator(selector); for (const element of await locator.all()) { - if ((await element.isVisible()) && retries < 300) { + if ((await element.count()) > 0 && retries < 300) { retries++; await page.waitForTimeout(200); await module.exports.waitToBeHidden(selector, page); @@ -304,7 +307,7 @@ module.exports = { ); // shown on balance load // network error handler if ( - await page.locator(pageElements.loadingOverlayErrorButtons).isVisible() + (await page.locator(pageElements.loadingOverlayErrorButtons).count()) > 0 ) { await module.exports.waitAndClick( pageElements.loadingOverlayErrorButtonsRetryButton, diff --git a/docs/synpress-commands.md b/docs/synpress-commands.md index fc851db8..9fefccda 100644 --- a/docs/synpress-commands.md +++ b/docs/synpress-commands.md @@ -64,12 +64,12 @@ Switch to metamask notification window. switchToMetamaskNotification(): Chainable; ``` -#### `cy.getNetwork()` +#### `cy.getCurrentNetwork()` Get current network. ```ts -getNetwork(): Chainable; +getCurrentNetwork(): Chainable; ``` #### `cy.addMetamaskNetwork()` diff --git a/helpers.js b/helpers.js index ec0e62d7..22b33379 100644 --- a/helpers.js +++ b/helpers.js @@ -5,78 +5,103 @@ const path = require('path'); const { ethers } = require('ethers'); const download = require('download'); const packageJson = require('./package.json'); +const chains = require('viem/chains'); -const PRESET_NETWORKS = Object.freeze({ - mainnet: { - networkName: 'mainnet', - networkDisplayName: 'Ethereum Mainnet', - networkId: 1, - isTestnet: false, - }, - goerli: { - networkName: 'goerli', - networkDisplayName: 'Goerli Test Network', - networkId: 5, - isTestnet: true, - }, - sepolia: { - networkName: 'sepolia', - networkDisplayName: 'Sepolia Test Network', - networkId: 11155111, - isTestnet: true, - }, -}); - -// map(networkName => networkInfo) -const ADDED_NETWORKS = { - 'ethereum mainnet': PRESET_NETWORKS.mainnet, - 'goerli test network': PRESET_NETWORKS.goerli, - 'sepolia test network': PRESET_NETWORKS.sepolia, -}; -let selectedNetwork = PRESET_NETWORKS.mainnet; +let currentNetwork = chains.mainnet; +// list of added networks to metamask +let addedNetworks = [chains.mainnet, chains.goerli, chains.sepolia]; module.exports = { + // set currently active network async setNetwork(network) { log(`Setting network to ${JSON.stringify(network)}`); + currentNetwork = network; + }, + // find network in presets + async findNetwork(network) { + if (typeof network === 'object') { + network = network.name || network.network; + } + + network = network.toLowerCase(); + log( + `[findNetwork] Trying to find following network: ${JSON.stringify( + network, + )}`, + ); - if (Object.keys(PRESET_NETWORKS).includes(network)) { - selectedNetwork = PRESET_NETWORKS[network]; - return; + let chain; + for (const [key, value] of Object.entries(chains)) { + const { name, network: chainNetwork } = value; + const lcName = name ? name.toLowerCase() : undefined; + const lcChainNetwork = chainNetwork + ? chainNetwork.toLowerCase() + : undefined; + if (lcName === network || lcChainNetwork === network) { + chain = chains[key]; + break; + } else if (key.toLowerCase() === network) { + chain = chains[key]; + break; + } } - if (network === 'localhost') { - const provider = new ethers.JsonRpcProvider('http://127.0.0.1:8545'); - const { chainId, name } = await provider.getNetwork(); - selectedNetwork = { - networkName: name.toLowerCase(), - networkDisplayName: name, - networkId: Number(chainId), - isTestnet: true, - }; - ADDED_NETWORKS[name] = selectedNetwork; - return; + if (!chain) { + throw new Error( + `[setNetwork] Provided chain was not found.\nFor list of available chains, check: https://github.com/wagmi-dev/references/tree/main/packages/chains#chains`, + ); } - if (typeof network === 'object') { - selectedNetwork = { - networkName: network.networkName.toLowerCase(), - networkDisplayName: network.networkName, - networkId: Number(network.chainId), - isTestnet: network.isTestnet, - }; - ADDED_NETWORKS[network.networkName] = selectedNetwork; - return; + if ( + chain.network === 'localhost' || + chain.network === 'foundry' || + chain.network === 'hardhat' + ) { + // todo: ip+port rpcUrls + const provider = new ethers.JsonRpcProvider( + chain.rpcUrls.default.http[0], + ); + await provider.getNetwork().then(result => { + chain.id = Number(result.chainId); + chain.forkedFrom = result.name; + }); } - if (typeof network === 'string') { - const addedNetwork = ADDED_NETWORKS[network.toLowerCase()]; - if (!addedNetwork) throw new Error('Network not found'); - selectedNetwork = addedNetwork; + return chain; + }, + // get currently active network + getCurrentNetwork() { + log( + `[getCurrentNetwork] Current network data: ${JSON.stringify( + currentNetwork, + )}`, + ); + return currentNetwork; + }, + // add new network to presets and list of metamask networks + async addNetwork(newNetwork) { + if (!newNetwork.network) { + newNetwork.network = newNetwork.name.toLowerCase().replace(' ', '-'); } + + log(`[addNetwork] Adding new network: ${newNetwork}`); + chains[newNetwork.network] = newNetwork; + addedNetworks.push(newNetwork); }, - getNetwork: () => { - log(`Current network data: ${selectedNetwork}`); - return selectedNetwork; + // check if network is already added to metamask + async checkNetworkAdded(network) { + log( + `[checkNetworkAdded] Checking if network is already added: ${JSON.stringify( + network, + )}`, + ); + if (addedNetworks.includes(network)) { + log(`[checkNetworkAdded] Network is present`); + return true; + } else { + log(`[checkNetworkAdded] Network doesn't exist`); + return false; + } }, getSynpressPath() { if (process.env.SYNPRESS_LOCAL_TEST) { diff --git a/package.json b/package.json index 840cbfbe..de176067 100644 --- a/package.json +++ b/package.json @@ -53,10 +53,12 @@ "@cypress/code-coverage": "^3.10.4", "@cypress/webpack-dev-server": "^3.4.1", "@drptbl/gremlins.js": "^2.2.1", + "@foundry-rs/easy-foundryup": "^0.1.3", "@playwright/test": "^1.33.0", "@testing-library/cypress": "^9.0.0", "@testing-library/react": "^14.0.0", "@types/testing-library__cypress": "^5.0.9", + "@viem/anvil": "^0.0.5", "axios": "^1.4.0", "babel-plugin-istanbul": "^6.1.1", "babel-plugin-react-generate-property": "^1.1.2", @@ -74,7 +76,10 @@ "ethers": "^6.3.0", "etherscan-api": "^10.3.0", "find-config": "^1.0.0", + "get-port": "^6.1.2", "node-fetch": "^2.6.1", + "underscore": "^1.13.6", + "viem": "^0.3.17", "wait-on": "^7.0.1" }, "devDependencies": { diff --git a/plugins/index.js b/plugins/index.js index a9aba263..cc30d6bd 100644 --- a/plugins/index.js +++ b/plugins/index.js @@ -284,8 +284,8 @@ module.exports = (on, config) => { }); return true; }, - getNetwork: () => { - const network = helpers.getNetwork(); + getCurrentNetwork: () => { + const network = helpers.getCurrentNetwork(); return network; }, etherscanGetTransactionStatus: async ({ txid }) => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3ad49e73..e9efc7f2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,6 +16,9 @@ dependencies: '@drptbl/gremlins.js': specifier: ^2.2.1 version: 2.2.1 + '@foundry-rs/easy-foundryup': + specifier: ^0.1.3 + version: 0.1.3 '@playwright/test': specifier: ^1.33.0 version: 1.33.0 @@ -28,6 +31,9 @@ dependencies: '@types/testing-library__cypress': specifier: ^5.0.9 version: 5.0.9 + '@viem/anvil': + specifier: ^0.0.5 + version: 0.0.5(debug@4.3.4) axios: specifier: ^1.4.0 version: 1.4.0(debug@4.3.4) @@ -79,9 +85,18 @@ dependencies: find-config: specifier: ^1.0.0 version: 1.0.0 + get-port: + specifier: ^6.1.2 + version: 6.1.2 node-fetch: specifier: ^2.6.1 version: 2.6.9 + underscore: + specifier: ^1.13.6 + version: 1.13.6 + viem: + specifier: ^0.3.17 + version: 0.3.17(typescript@5.0.4) wait-on: specifier: ^7.0.1 version: 7.0.1(debug@4.3.4) @@ -1461,6 +1476,13 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@foundry-rs/easy-foundryup@0.1.3: + resolution: {integrity: sha512-Funb4hrSBeikKCmccFT/d3Ud5o92tlIZHTJeMCVk5b54/+CHZHr4g7MmtvO5xrGhxrOebQ0L+ojIj+VixgW7ug==} + dependencies: + command-exists: 1.2.9 + ts-interface-checker: 0.1.13 + dev: false + /@gar/promisify@1.1.3: resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} dev: true @@ -1587,10 +1609,26 @@ packages: - supports-color dev: true + /@noble/curves@0.8.3: + resolution: {integrity: sha512-OqaOf4RWDaCRuBKJLDURrgVxjLmneGsiCXGuzYB5y95YithZMA6w4uk34DHSm0rKMrrYiaeZj48/81EvaAScLQ==} + dependencies: + '@noble/hashes': 1.3.0 + dev: false + + /@noble/curves@0.9.0: + resolution: {integrity: sha512-OAdtHMXBp7Chl2lcTn/i7vnFX/q+hhTwDnek5NfYfZsY4LyaUuHCcoq2JlLY3BTFTLT+ZhYZalhF6ejlV7KnJQ==} + dependencies: + '@noble/hashes': 1.3.0 + dev: false + /@noble/hashes@1.1.2: resolution: {integrity: sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==} dev: false + /@noble/hashes@1.3.0: + resolution: {integrity: sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==} + dev: false + /@noble/secp256k1@1.7.1: resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} dev: false @@ -1843,6 +1881,25 @@ packages: config-chain: 1.1.13 dev: true + /@scure/base@1.1.1: + resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==} + dev: false + + /@scure/bip32@1.2.0: + resolution: {integrity: sha512-O+vT/hBVk+ag2i6j2CDemwd1E1MtGt+7O1KzrPNsaNvSsiEK55MyPIxJIMI2PS8Ijj464B2VbQlpRoQXxw1uHg==} + dependencies: + '@noble/curves': 0.8.3 + '@noble/hashes': 1.3.0 + '@scure/base': 1.1.1 + dev: false + + /@scure/bip39@1.2.0: + resolution: {integrity: sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==} + dependencies: + '@noble/hashes': 1.3.0 + '@scure/base': 1.1.1 + dev: false + /@sideway/address@4.1.4: resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==} dependencies: @@ -2183,7 +2240,7 @@ packages: resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} requiresBuild: true dependencies: - '@types/node': 14.18.43 + '@types/node': 18.16.3 dev: false optional: true @@ -2262,6 +2319,30 @@ packages: eslint-visitor-keys: 3.4.0 dev: true + /@viem/anvil@0.0.5(debug@4.3.4): + resolution: {integrity: sha512-aGgbwBNmCcxp08WcYwyL+n01HLLFYuhIczQLy6BPcomQ2CG4ngfTed8K73EOpsBTmvCxAcek0APcVS7UUWNALw==} + dependencies: + execa: 7.1.1 + get-port: 6.1.2 + http-proxy: 1.18.1(debug@4.3.4) + ws: 8.13.0 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + dev: false + + /@wagmi/chains@0.2.16(typescript@5.0.4): + resolution: {integrity: sha512-rkWaI2PxCnbD8G07ZZff5QXftnSkYL0h5f4DkHCG3fGYYr/ZDvmCL4bMae7j7A9sAif1csPPBmbCzHp3R5ogCQ==} + peerDependencies: + typescript: '>=4.9.4' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + typescript: 5.0.4 + dev: false + /@webassemblyjs/ast@1.11.5: resolution: {integrity: sha512-LHY/GSAZZRpsNQH+/oHqhRQ5FT7eoULcBqgfyTB5nQHogFnK3/7QoN7dLnwSE/JkUAF0SrRuclT7ODqMFtWxxQ==} dependencies: @@ -2384,6 +2465,18 @@ packages: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} dev: true + /abitype@0.7.1(typescript@5.0.4): + resolution: {integrity: sha512-VBkRHTDZf9Myaek/dO3yMmOzB/y2s3Zo6nVU7yaw1G+TvCHAjwaJzNGN9yo4K5D8bU/VZXKP1EJpRhFr862PlQ==} + peerDependencies: + typescript: '>=4.9.4' + zod: ^3 >=3.19.1 + peerDependenciesMeta: + zod: + optional: true + dependencies: + typescript: 5.0.4 + dev: false + /accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} @@ -3451,6 +3544,10 @@ packages: dependencies: delayed-stream: 1.0.0 + /command-exists@1.2.9: + resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} + dev: false + /commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} @@ -4787,7 +4884,6 @@ packages: onetime: 6.0.0 signal-exit: 3.0.7 strip-final-newline: 3.0.0 - dev: true /executable@4.1.1: resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==} @@ -5294,6 +5390,11 @@ packages: engines: {node: '>=8.0.0'} dev: false + /get-port@6.1.2: + resolution: {integrity: sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false + /get-stdin@8.0.0: resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==} engines: {node: '>=10'} @@ -5875,7 +5976,6 @@ packages: /human-signals@4.3.1: resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} engines: {node: '>=14.18.0'} - dev: true /humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} @@ -6240,7 +6340,6 @@ packages: /is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true /is-string-and-not-blank@0.0.2: resolution: {integrity: sha512-FyPGAbNVyZpTeDCTXnzuwbu9/WpNXbCfbHXLpCRpN4GANhS00eEIP5Ef+k5HYSNIzIhdN9zRDoBj6unscECvtQ==} @@ -6339,6 +6438,14 @@ packages: engines: {node: '>=0.10.0'} dev: false + /isomorphic-ws@5.0.0(ws@8.12.0): + resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} + peerDependencies: + ws: '*' + dependencies: + ws: 8.12.0 + dev: false + /isstream@0.1.2: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} dev: false @@ -7017,7 +7124,6 @@ packages: /mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - dev: true /mimic-response@1.0.1: resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} @@ -7439,7 +7545,6 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: path-key: 4.0.0 - dev: true /npmlog@6.0.2: resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} @@ -7573,7 +7678,6 @@ packages: engines: {node: '>=12'} dependencies: mimic-fn: 4.0.0 - dev: true /open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} @@ -7911,7 +8015,6 @@ packages: /path-key@4.0.0: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} - dev: true /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -9305,7 +9408,6 @@ packages: /strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} - dev: true /strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} @@ -9529,6 +9631,10 @@ packages: escape-string-regexp: 1.0.5 dev: false + /ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + dev: false + /tsconfig-paths@3.14.2: resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} dependencies: @@ -9712,7 +9818,6 @@ packages: resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} engines: {node: '>=12.20'} hasBin: true - dev: true /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} @@ -9729,6 +9834,10 @@ packages: through: 2.3.8 dev: false + /underscore@1.13.6: + resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} + dev: false + /unicode-canonical-property-names-ecmascript@2.0.0: resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} engines: {node: '>=4'} @@ -9930,6 +10039,25 @@ packages: extsprintf: 1.3.0 dev: false + /viem@0.3.17(typescript@5.0.4): + resolution: {integrity: sha512-WGJQ3rV2gMiHgwxLqeAZQ3HetSfsrkF//WezdJPnwUNXuic/c2jjB3MBk4XfYvuRUMccPfc37ORi03AmQxjscg==} + dependencies: + '@adraffy/ens-normalize': 1.9.0 + '@noble/curves': 0.9.0 + '@noble/hashes': 1.3.0 + '@scure/bip32': 1.2.0 + '@scure/bip39': 1.2.0 + '@wagmi/chains': 0.2.16(typescript@5.0.4) + abitype: 0.7.1(typescript@5.0.4) + isomorphic-ws: 5.0.0(ws@8.12.0) + ws: 8.12.0 + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + - zod + dev: false + /vm2@3.9.17: resolution: {integrity: sha512-AqwtCnZ/ERcX+AVj9vUsphY56YANXxRuqMb7GsDtAr0m0PcQX3u0Aj3KWiXM0YAHy7i6JEeHrwOnwXbGYgRpAw==} engines: {node: '>=6.0'} @@ -10236,6 +10364,19 @@ packages: signal-exit: 3.0.7 typedarray-to-buffer: 3.1.5 + /ws@8.12.0: + resolution: {integrity: sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /ws@8.13.0: resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} engines: {node: '>=10.0.0'} diff --git a/support/commands.js b/support/commands.js index 9ad89749..b02c7f88 100644 --- a/support/commands.js +++ b/support/commands.js @@ -249,8 +249,8 @@ Cypress.Commands.add( }, ); -Cypress.Commands.add('getNetwork', () => { - return cy.task('getNetwork'); +Cypress.Commands.add('getCurrentNetwork', () => { + return cy.task('getCurrentNetwork'); }); // Etherscan commands diff --git a/support/index.d.ts b/support/index.d.ts index 3774d838..9d166480 100644 --- a/support/index.d.ts +++ b/support/index.d.ts @@ -51,21 +51,26 @@ declare namespace Cypress { /** * Get current network * @example - * cy.getNetwork() + * cy.getCurrentNetwork() */ - getNetwork(): Chainable; + getCurrentNetwork(): Chainable; /** * Add network in metamask (and also switch to the newly added network) + * List of available presets for networks: https://github.com/wagmi-dev/references/tree/main/packages/chains#chains + * If preset for your custom chain is not available, you can add custom network by yourself. * @example - * cy.addMetamaskNetwork({networkName: 'name', rpcUrl: 'https://url', chainId: '1', symbol: 'ETH', blockExplorer: 'https://url', isTestnet: true}) + * cy.addMetamaskNetwork('optimism') // works only if chain is available as preset + * cy.addMetamaskNetwork({name: 'optimism', rpcUrl: 'https://mainnet.optimism.io', chainId: 10, symbol: 'oETH', blockExplorer: 'https://https://optimistic.etherscan.io', isTestnet: false}) + * cy.addMetamaskNetwork({id: 10, name: 'optimism', nativeCurrency: { symbol: 'OP' }, rpcUrls: { default: { http: ['https://mainnet.optimism.io'] } }, testnet: false }) */ addMetamaskNetwork(network: object): Chainable; /** - * Change network in metamask + * Change network in metamask (if network is not present, it will be added) + * List of available presets for networks: https://github.com/wagmi-dev/references/tree/main/packages/chains#chains + * If preset for your custom chain is not available, you can add custom network by yourself with `cy.addMetamaskNetwork()`. * @example * cy.changeMetamaskNetwork('goerli') - * cy.changeMetamaskNetwork('custom network') - * cy.changeMetamaskNetwork({networkName: 'name'}) + * cy.changeMetamaskNetwork('custom network name') */ changeMetamaskNetwork(network: string): Chainable; /** @@ -335,12 +340,14 @@ declare namespace Cypress { fetchMetamaskWalletAddress(): Chainable; /** * Run the flow for metamask setup + * List of available presets for networks: https://github.com/wagmi-dev/references/tree/main/packages/chains#chains + * If preset for your custom chain is not available, you can add custom network by yourself. * @example * cy.setupMetamask() // will use defaults - * cy.setupMetamask('secret, words, ...', 'goerli', 'password for metamask') - * cy.setupMetamask('secret, words, ...', {networkName: 'name', rpcUrl: 'https://url', chainId: 1, symbol: 'ETH', blockExplorer: 'https://url', isTestnet: true}, 'password for metamask') + * cy.setupMetamask('secret, words, ...', 'optimism', 'password for metamask') // works only if chain is available as preset + * cy.setupMetamask('secret, words, ...', {name: 'optimism', rpcUrl: 'https://mainnet.optimism.io', chainId: 10, symbol: 'oETH', blockExplorer: 'https://https://optimistic.etherscan.io', isTestnet: false}, 'password for metamask') * cy.setupMetamask('private_key', 'goerli', 'password for metamask') - * cy.setupMetamask('private_key', {networkName: 'name', rpcUrl: 'https://url', chainId: 1, symbol: 'ETH', blockExplorer: 'https://url', isTestnet: true}, 'password for metamask') + * cy.setupMetamask('private_key', {name: 'optimism', rpcUrl: 'https://mainnet.optimism.io', chainId: 10, symbol: 'oETH', blockExplorer: 'https://https://optimistic.etherscan.io', isTestnet: false}, 'password for metamask') */ setupMetamask( secretWordsOrPrivateKey?: string, diff --git a/tests/e2e/specs/metamask-spec.js b/tests/e2e/specs/metamask-spec.js index 6106bf0a..365ba4c0 100644 --- a/tests/e2e/specs/metamask-spec.js +++ b/tests/e2e/specs/metamask-spec.js @@ -41,11 +41,11 @@ describe('Metamask', () => { '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', ); }); - it(`getNetwork should return network by default`, () => { - cy.getNetwork().then(network => { - expect(network.networkName).to.be.equal('sepolia'); - expect(network.networkId).to.be.equal(11155111); - expect(network.isTestnet).to.be.true; + it(`getCurrentNetwork should return network by default`, () => { + cy.getCurrentNetwork().then(network => { + expect(network.name).to.match(/sepolia/i); + expect(network.id).to.be.equal(11155111); + expect(network.testnet).to.be.true; }); }); it(`addMetamaskNetwork should add custom network`, () => { @@ -55,8 +55,8 @@ describe('Metamask', () => { rpcUrl: Cypress.env('DOCKER_RUN') ? 'http://foundry:8545' : 'http://127.0.0.1:8545', - chainId: '11155111', - symbol: 'SETH', + chainId: 11155111, + symbol: 'aETH', isTestnet: true, }); cy.get('#network').contains('11155111'); @@ -65,8 +65,8 @@ describe('Metamask', () => { cy.addMetamaskNetwork({ networkName: 'Optimism Network', rpcUrl: 'https://mainnet.optimism.io', - chainId: '10', - symbol: 'OETH', + chainId: 10, + symbol: 'oETH', blockExplorer: 'https://optimistic.etherscan.io', isTestnet: false, }).then(networkAdded => { @@ -76,35 +76,35 @@ describe('Metamask', () => { cy.get('#chainId').contains('0xa'); } }); - it(`getNetwork should return valid network after adding a new network`, () => { - cy.getNetwork().then(network => { + it(`getCurrentNetwork should return valid network after adding a new network`, () => { + cy.getCurrentNetwork().then(network => { if (Cypress.env('USE_ANVIL')) { - expect(network.networkName).to.be.equal('anvil'); - expect(network.networkId).to.be.equal(11155111); - expect(network.isTestnet).to.be.true; + expect(network.name).to.be.equal('anvil'); + expect(network.id).to.be.equal(11155111); + expect(network.testnet).to.be.true; } else { - expect(network.networkName).to.be.equal('optimism network'); - expect(network.networkId).to.be.equal(10); - expect(network.isTestnet).to.be.false; + expect(network.name).to.match(/optimism network/i); + expect(network.id).to.be.equal(10); + expect(network.testnet).to.be.false; } }); }); it(`changeMetamaskNetwork should change network using pre-defined network`, () => { - cy.changeMetamaskNetwork('mainnet').then(networkChanged => { + cy.changeMetamaskNetwork('ethereum').then(networkChanged => { expect(networkChanged).to.be.true; }); cy.get('#network').contains('0x1'); cy.get('#chainId').contains('0x1'); }); - it(`getNetwork should return valid network after changing a network`, () => { - cy.getNetwork().then(network => { - expect(network.networkName).to.be.equal('mainnet'); - expect(network.networkId).to.be.equal(1); - expect(network.isTestnet).to.be.false; + it(`getCurrentNetwork should return valid network after changing a network`, () => { + cy.getCurrentNetwork().then(network => { + console.log(network); + expect(network.name).to.match(/ethereum/i); + expect(network.id).to.be.equal(1); }); }); it(`changeMetamaskNetwork should discard changing network if it is current one`, () => { - cy.changeMetamaskNetwork('mainnet').then(networkChanged => { + cy.changeMetamaskNetwork('ethereum').then(networkChanged => { expect(networkChanged).to.be.false; }); });