Skip to content

Commit

Permalink
✨ feat(metamask): Add network switching on demand (#1005)
Browse files Browse the repository at this point in the history
  • Loading branch information
duckception authored Nov 21, 2023
1 parent 04ef607 commit 64297af
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 3 deletions.
4 changes: 4 additions & 0 deletions wallets/metamask/src/metamask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ export class MetaMask {
await this.homePage.switchAccount(accountName)
}

async switchNetwork(networkName: string) {
await this.homePage.switchNetwork(networkName)
}

async connectToDapp() {
if (!this.extensionId) {
throw NO_EXTENSION_ID_ERROR
Expand Down
1 change: 1 addition & 0 deletions wallets/metamask/src/pages/HomePage/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './lock'
export * from './importWalletFromPrivateKey'
export * from './switchAccount'
export * from './settings'
export * from './switchNetwork'
31 changes: 30 additions & 1 deletion wallets/metamask/src/pages/HomePage/actions/settings.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Page } from '@playwright/test'
import { waitFor } from '../../../utils/waitFor'
import Selectors from '../selectors'
import type { SettingsSidebarMenus } from '../selectors/settings'

Expand All @@ -14,7 +15,35 @@ async function openSidebarMenu(page: Page, menu: SettingsSidebarMenus) {
async function toggleShowTestNetworks(page: Page) {
// .nth(0) -> Show conversion on test networks
// .nth(1) -> Show test networks
await page.locator(Selectors.settings.advanced.showTestNetworksToggle).nth(1).click()
const toggleLocator = page.locator(Selectors.settings.advanced.showTestNetworksToggle).nth(1)

// TODO: Extract timeout
const classes = await toggleLocator.getAttribute('class', { timeout: 3_000 })

if (!classes) {
throw new Error('[ToggleShowTestNetworks] Toggle class returned null')
}

const isOn = classes.includes('toggle-button--on')

await toggleLocator.click()

const waitForAction = async () => {
const classes = await toggleLocator.getAttribute('class')

if (!classes) {
throw new Error('[ToggleShowTestNetworks] Toggle class returned null inside waitFor')
}

if (isOn) {
return classes.includes('toggle-button--off')
}

return classes.includes('toggle-button--on')
}

// TODO: Extract timeout
await waitFor(waitForAction, 3_000, true)
}

const advanced = {
Expand Down
24 changes: 24 additions & 0 deletions wallets/metamask/src/pages/HomePage/actions/switchNetwork.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { Page } from '@playwright/test'
import Selectors from '../selectors'

export async function switchNetwork(page: Page, networkName: string) {
await page.locator(Selectors.networkDropdown.dropdownButton).click()

const networkLocators = await page.locator(Selectors.networkDropdown.networks).all()

const networkNames = await page.locator(Selectors.networkDropdown.networks).allTextContents()

console.log({ networkNames })

const seekedNetworkNames = networkNames.filter((name) => name.toLocaleLowerCase() === networkName.toLocaleLowerCase())

if (seekedNetworkNames.length === 0) {
throw new Error(`[SwitchNetwork] Network with name ${networkName} not found`)
}

// biome-ignore lint/style/noNonNullAssertion: this non-null assertion is intentional
const accountIndex = networkNames.indexOf(seekedNetworkNames[0]!) // TODO: handle the undefined here better

// biome-ignore lint/style/noNonNullAssertion: this non-null assertion is intentional
await networkLocators[accountIndex]!.click() // TODO: handle the undefined here better
}
6 changes: 5 additions & 1 deletion wallets/metamask/src/pages/HomePage/page.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Page } from '@playwright/test'
import { importWalletFromPrivateKey, lock, settings, switchAccount } from './actions'
import { importWalletFromPrivateKey, lock, settings, switchAccount, switchNetwork } from './actions'
import Selectors from './selectors'
import type { SettingsSidebarMenus } from './selectors/settings'

Expand Down Expand Up @@ -40,4 +40,8 @@ export class HomePage {
async toggleShowTestNetworks() {
await settings.advanced.toggleShowTestNetworks(this.page)
}

async switchNetwork(networkName: string) {
await switchNetwork(this.page, networkName)
}
}
3 changes: 2 additions & 1 deletion wallets/metamask/src/pages/HomePage/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ const recoveryPhraseReminder = {

const networkDropdown = {
dropdownButton: createDataTestSelector('network-display'),
networks: `${createDataTestSelector('network-droppo')} .network-dropdown-list li`
networks: `${createDataTestSelector('network-droppo')} .network-dropdown-list li > span`
}

export default {
logo: createDataTestSelector('app-header-logo'),
account: createDataTestSelector('selected-account-click'),
currentNetwork: createDataTestSelector('network-display'),
settings,
networkDropdown,
accountMenu,
Expand Down
42 changes: 42 additions & 0 deletions wallets/metamask/test/e2e/metamask/switchNetwork.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { testWithSynpress } from 'fixtures'
import { MetaMask, unlockForFixture } from '../../../src'

import basicSetup from '../wallet-setup/basic.setup'

const test = testWithSynpress(basicSetup, unlockForFixture)

const { expect } = test

test.use({
permissions: ['clipboard-read']
})

test('should switch network', async ({ context, metamaskPage }) => {
const metamask = new MetaMask(context, metamaskPage, basicSetup.walletPassword)

await metamask.openSettings()

const SidebarMenus = metamask.homePage.selectors.settings.SettingsSidebarMenus
await metamask.openSidebarMenu(SidebarMenus.Advanced)

await metamask.toggleShowTestNetworks()

const networkBefore = await metamaskPage.locator(metamask.homePage.selectors.currentNetwork).textContent()

expect(networkBefore).toEqual('Ethereum Mainnet')

const targetNetwork = 'Sepolia test network'
await metamask.switchNetwork(targetNetwork)

const networkAfter = await metamaskPage.locator(metamask.homePage.selectors.currentNetwork).textContent()
expect(networkAfter).toEqual(targetNetwork)
})

test('should throw an error if there is no account with target name', async ({ context, metamaskPage }) => {
const metamask = new MetaMask(context, metamaskPage, basicSetup.walletPassword)

const accountName = 'Account 420'
const switchAccountPromise = metamask.switchAccount(accountName)

await expect(switchAccountPromise).rejects.toThrowError(`[SwitchAccount] Account with name ${accountName} not found`)
})

0 comments on commit 64297af

Please sign in to comment.