Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ feat: Add wait for methods #1154

Merged
merged 4 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions wallets/metamask/src/pages/NotificationPage/page.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { Page } from '@playwright/test'
import { getNotificationPageAndWaitForLoad } from '../../utils/getNotificationPageAndWaitForLoad'
import { waitFor } from '../../utils/waitFor'
import {
type GasSetting,
approvePermission,
Expand Down Expand Up @@ -35,13 +34,14 @@ export class NotificationPage {
private async beforeMessageSignature(extensionId: string) {
const notificationPage = await getNotificationPageAndWaitForLoad(this.page.context(), extensionId)

// TODO: Make this configurable.
// Most of the time, this function will be used to sign structured messages, so we check for the scroll button first.
const isScrollButtonVisible = await waitFor(
() => notificationPage.locator(Selectors.SignaturePage.structuredMessage.scrollDownButton).isVisible(),
1_500,
false
)
const scrollButton = notificationPage.locator(Selectors.SignaturePage.structuredMessage.scrollDownButton)
const isScrollButtonPresent = (await scrollButton.count()) > 0

let isScrollButtonVisible = false
if (isScrollButtonPresent) {
await scrollButton.waitFor({ state: 'visible' })
isScrollButtonVisible = true
}

return {
notificationPage,
Expand Down
15 changes: 14 additions & 1 deletion wallets/metamask/src/selectors/loading/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
export const LoadingSelectors = {
spinner: '.spinner'
spinner: '.spinner',
loadingIndicators: [
'.loading-logo',
'.loading-spinner',
'.loading-overlay',
'.loading-overlay__spinner',
'.loading-span',
'.loading-indicator',
'#loading__logo',
'#loading__spinner',
'.mm-button-base__icon-loading',
'.loading-swaps-quotes',
'.loading-heartbeat'
]
}
17 changes: 16 additions & 1 deletion wallets/metamask/src/utils/getNotificationPageAndWaitForLoad.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type { BrowserContext, Page } from '@playwright/test'
import { LoadingSelectors } from '../selectors'
import { waitUntilStable } from './waitFor'
import { waitForSelector } from './waitFor'

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

await waitUntilStable(notificationPage as Page)

// Set pop-up window viewport size to resemble the actual MetaMask pop-up window.
await notificationPage.setViewportSize({
width: 360,
height: 592
})

await notificationPage.waitForLoadState('load')
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
}
23 changes: 23 additions & 0 deletions wallets/metamask/src/utils/waitFor.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
import type { Page } from '@playwright/test'
import { errors } from '@playwright/test'

export const waitUntilStable = async (page: Page) => {
await page.waitForLoadState('domcontentloaded')
await page.waitForLoadState('networkidle')
}

export const waitForSelector = async (selector: string, page: Page, timeout: number) => {
await waitUntilStable(page)

try {
await page.waitForSelector(selector, { state: 'hidden', timeout })
} catch (error) {
if (error instanceof errors.TimeoutError) {
console.log(`Loading indicator '${selector}' not found - continuing.`)
} else {
console.log(`Error while waiting for loading indicator '${selector}' to disappear`)
throw error
}
}
}

// 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
Loading