Skip to content

Commit

Permalink
✨ feat: Wait for metamask functions (#1160)
Browse files Browse the repository at this point in the history
  • Loading branch information
Seroxdesign authored Jul 4, 2024
1 parent c0348f5 commit c13f03b
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 17 deletions.
3 changes: 2 additions & 1 deletion wallets/metamask/src/fixtures/metaMaskFixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { type Anvil, type CreateAnvilOptions, createPool } from '@viem/anvil'
import fs from 'fs-extra'
import { persistLocalStorage } from '../fixture-actions/persistLocalStorage'
import { waitForMetaMaskWindowToBeStable } from '../utils/waitFor'

type MetaMaskFixtures = {
_contextPath: string
Expand Down Expand Up @@ -84,7 +85,7 @@ export const metaMaskFixtures = (walletSetup: ReturnType<typeof defineWalletSetu
_metamaskPage = context.pages()[0] as Page

await _metamaskPage.goto(`chrome-extension://${extensionId}/home.html`)

await waitForMetaMaskWindowToBeStable(_metamaskPage)
await unlockForFixture(_metamaskPage, walletSetup.walletPassword)

await use(context)
Expand Down
7 changes: 7 additions & 0 deletions wallets/metamask/src/selectors/error/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const ErrorSelectors = {
loadingOverlayErrorButtons: '.loading-overlay__error-buttons',
loadingOverlayErrorButtonsRetryButton: '.loading-overlay__error-buttons .btn-primary',
criticalError: '.critical-error',
criticalErrorRestartButton: '#critical-error-button',
errorPage: '.error-page'
}
1 change: 1 addition & 0 deletions wallets/metamask/src/selectors/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './loading'
export * from './error'
1 change: 1 addition & 0 deletions wallets/metamask/src/selectors/loading/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const LoadingSelectors = {
spinner: '.spinner',
loadingOverlay: '.loading-overlay',
loadingIndicators: [
'.loading-logo',
'.loading-spinner',
Expand Down
18 changes: 2 additions & 16 deletions wallets/metamask/src/utils/getNotificationPageAndWaitForLoad.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import type { BrowserContext, Page } from '@playwright/test'
import { LoadingSelectors } from '../selectors'
import { waitUntilStable } from './waitFor'
import { waitForSelector } from './waitFor'
import { waitForMetaMaskLoad, waitUntilStable } from './waitFor'

export async function getNotificationPageAndWaitForLoad(context: BrowserContext, extensionId: string) {
const notificationPageUrl = `chrome-extension://${extensionId}/notification.html`
Expand All @@ -25,17 +23,5 @@ export async function getNotificationPageAndWaitForLoad(context: BrowserContext,
height: 592
})

await Promise.all(
LoadingSelectors.loadingIndicators.map(async (selector) => {
await waitForSelector(selector, notificationPage as Page, 5000)
})
)
.then(() => {
console.log('All loading indicators are hidden')
})
.catch((error) => {
console.error('Error: ', error)
})

return notificationPage
return await waitForMetaMaskLoad(notificationPage)
}
57 changes: 57 additions & 0 deletions wallets/metamask/src/utils/waitFor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import type { Page } from '@playwright/test'
import { errors } from '@playwright/test'
import { ErrorSelectors, LoadingSelectors } from '../selectors'

const DEFAULT_TIMEOUT = 2000

export const waitUntilStable = async (page: Page) => {
await page.waitForLoadState('domcontentloaded')
Expand All @@ -21,6 +24,60 @@ export const waitForSelector = async (selector: string, page: Page, timeout: num
}
}

export const waitForMetaMaskLoad = async (page: Page) => {
await Promise.all(
LoadingSelectors.loadingIndicators.map(async (selector) => {
await waitForSelector(selector, page, DEFAULT_TIMEOUT)
})
)
.then(() => {
console.log('All loading indicators are hidden')
})
.catch((error) => {
console.error('Error: ', error)
})

return page
}

export const waitForMetaMaskWindowToBeStable = async (page: Page) => {
await waitForMetaMaskLoad(page)
if ((await page.locator(ErrorSelectors.loadingOverlayErrorButtons).count()) > 0) {
const retryButton = await page.locator(ErrorSelectors.loadingOverlayErrorButtonsRetryButton)
await retryButton.click()
await waitForSelector(LoadingSelectors.loadingOverlay, page, DEFAULT_TIMEOUT)
}
await fixCriticalError(page)
}

export const fixCriticalError = async (page: Page) => {
for (let times = 0; times < 5; times++) {
if ((await page.locator(ErrorSelectors.criticalError).count()) > 0) {
console.log('[fixCriticalError] Metamask crashed with critical error, refreshing..')
if (times <= 3) {
await page.reload()
await waitForMetaMaskWindowToBeStable(page)
} else if (times === 4) {
const restartButton = await page.locator(ErrorSelectors.criticalErrorRestartButton)
await restartButton.click()
await waitForMetaMaskWindowToBeStable(page)
} else {
throw new Error('[fixCriticalError] Max amount of retries to fix critical metamask error has been reached.')
}
} else if ((await page.locator(ErrorSelectors.errorPage).count()) > 0) {
console.log('[fixCriticalError] Metamask crashed with error, refreshing..')
if (times <= 4) {
await page.reload()
await waitForMetaMaskWindowToBeStable(page)
} else {
throw new Error('[fixCriticalError] Max amount of retries to fix critical metamask error has been reached.')
}
} else {
break
}
}
}

// Inlining the sleep function here cause this is one of the few places in the entire codebase where sleep should be used!
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))

Expand Down

0 comments on commit c13f03b

Please sign in to comment.