From 78ad80660486b84340d9496ff0800ba027437fa4 Mon Sep 17 00:00:00 2001 From: Daniel Izdebski Date: Mon, 9 Oct 2023 21:21:17 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(metamask):=20Add=20basic=20`co?= =?UTF-8?q?nnectToDapp`=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wallets/metamask/src/actions/connectToDapp.ts | 20 +++++++++++++ .../metamask/src/utils/getNotificationPage.ts | 29 +++++++++++++++++++ wallets/metamask/test/e2e/metamask.spec.ts | 25 ++++++++++++---- wallets/metamask/tsconfig.build.json | 3 +- 4 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 wallets/metamask/src/actions/connectToDapp.ts create mode 100644 wallets/metamask/src/utils/getNotificationPage.ts diff --git a/wallets/metamask/src/actions/connectToDapp.ts b/wallets/metamask/src/actions/connectToDapp.ts new file mode 100644 index 000000000..844dbf28d --- /dev/null +++ b/wallets/metamask/src/actions/connectToDapp.ts @@ -0,0 +1,20 @@ +import type { BrowserContext } from '@playwright/test' +import { getNotificationPage } from '../utils/getNotificationPage' + +export async function connectToDapp(context: BrowserContext, extensionId: string) { + const notificationPage = await getNotificationPage(context, extensionId) + + if (!process.env.HEADLESS) { + // Set pop-up window viewport size to resemble the actual MetaMask pop-up window. + await notificationPage.setViewportSize({ + width: 360, + height: 592 + }) + } + + // Next + await notificationPage.getByRole('button').nth(1).click() + + // Connect + await notificationPage.getByRole('button').nth(1).click() +} diff --git a/wallets/metamask/src/utils/getNotificationPage.ts b/wallets/metamask/src/utils/getNotificationPage.ts new file mode 100644 index 000000000..cb11452a6 --- /dev/null +++ b/wallets/metamask/src/utils/getNotificationPage.ts @@ -0,0 +1,29 @@ +import type { BrowserContext, Page } from '@playwright/test' + +export async function getNotificationPage(context: BrowserContext, extensionId: string) { + const notificationPageUrl = `chrome-extension://${extensionId}/notification.html` + + /** + * If running in headless mode, create a new notification page manually. + * + * This is a workaround due to a bug in Chromium/MetaMask where pop-up windows + * are not created in the new headless mode. + */ + if (process.env.HEADLESS) { + const notificationPage = await context.newPage() + await notificationPage.goto(notificationPageUrl) + + return notificationPage + } + + const isNotificationPage = (page: Page) => page.url().includes(notificationPageUrl) + + // Check if notification page is already open. + const notificationPage = context.pages().find(isNotificationPage) + + if (notificationPage) { + return notificationPage + } + + return await context.waitForEvent('page', { predicate: isNotificationPage }) +} diff --git a/wallets/metamask/test/e2e/metamask.spec.ts b/wallets/metamask/test/e2e/metamask.spec.ts index f2bb1c25c..f2fe5f4e3 100644 --- a/wallets/metamask/test/e2e/metamask.spec.ts +++ b/wallets/metamask/test/e2e/metamask.spec.ts @@ -1,4 +1,5 @@ import { type BrowserContext, type Page, chromium, test as base } from '@playwright/test' +import { connectToDapp } from '../../src/actions/connectToDapp' import { OnboardingPage } from '../../src/pages' import { prepareExtension } from '../../src/prepareExtension' import { getExtensionId } from '../../src/utils/getExtensionId' @@ -43,7 +44,7 @@ const test = base.extend({ sharedContext = context await use(context) }, - page: async ({ context }, use) => { + metamaskPage: async ({ context }, use) => { const metamaskOnboardingPage = context.pages()[1] as Page await use(metamaskOnboardingPage) } @@ -54,13 +55,13 @@ const { describe, expect } = test // Currently testing only happy paths until we have proper setup for parallel tests. describe('MetaMask', () => { describe('importWallet', () => { - test('should go through the onboarding flow and import wallet from seed phrase', async ({ page }) => { - const onboardingPage = new OnboardingPage(page) + test('should go through the onboarding flow and import wallet from seed phrase', async ({ metamaskPage }) => { + const onboardingPage = new OnboardingPage(metamaskPage) await onboardingPage.importWallet(DEFAULT_SEED_PHRASE, DEFAULT_PASSWORD) - await expect(page.getByText('Account 1')).toBeVisible() - await expect(page.getByText('0xf39...2266')).toBeVisible() + await expect(metamaskPage.getByText('Account 1')).toBeVisible() + await expect(metamaskPage.getByText('0xf39...2266')).toBeVisible() }) }) @@ -70,4 +71,18 @@ describe('MetaMask', () => { expect(extensionId).toMatch(/^[a-z]{32}$/) }) }) + + describe('connectToDapp', () => { + test('should connect wallet to dapp', async ({ context, page }) => { + const extensionId = await getExtensionId(context, 'MetaMask') + + await page.goto('https://metamask.github.io/test-dapp/') + + await page.locator('#connectButton').click() + + await connectToDapp(context, extensionId) + + await expect(page.locator('#accounts')).toHaveText('0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266') + }) + }) }) diff --git a/wallets/metamask/tsconfig.build.json b/wallets/metamask/tsconfig.build.json index 177eb2938..97afa3ef9 100644 --- a/wallets/metamask/tsconfig.build.json +++ b/wallets/metamask/tsconfig.build.json @@ -7,5 +7,6 @@ "sourceMap": true, "declarationMap": true }, - "include": ["src"] + "include": ["src"], + "files": ["environment.d.ts"] }