From 9405799ff7214f6387a93f111c27f2f7f7ccedc0 Mon Sep 17 00:00:00 2001 From: Jorge Luis <28708889+hyphenized@users.noreply.github.com> Date: Fri, 7 Feb 2025 23:49:36 -0500 Subject: [PATCH] Add wallet popup helpers Added a utility class for connection popup interactions and a helper function to strictly watch for extension popups. --- e2e-tests/regular/dapp-connect.spec.ts | 51 +++++++------------- e2e-tests/regular/signing.spec.ts | 21 ++++----- e2e-tests/utils.ts | 8 +++- e2e-tests/utils/connect-popup.ts | 65 ++++++++++++++++++++++++++ e2e-tests/utils/walletPageHelper.ts | 42 ++--------------- 5 files changed, 104 insertions(+), 83 deletions(-) create mode 100644 e2e-tests/utils/connect-popup.ts diff --git a/e2e-tests/regular/dapp-connect.spec.ts b/e2e-tests/regular/dapp-connect.spec.ts index c522f520b..4f9df711b 100644 --- a/e2e-tests/regular/dapp-connect.spec.ts +++ b/e2e-tests/regular/dapp-connect.spec.ts @@ -14,30 +14,15 @@ test.describe("dApp Connections", () => { .first() .click() + const popupPage = walletPageHelper.getConnectPopup() // Get page after a specific action (e.g. clicking a link) - const [popupPage] = await Promise.all([ - context.waitForEvent("page"), - await dappPage.locator("text=Injected").click(), // Opens a new tab - ]) - await popupPage.waitForLoadState() - - // Clear the one-time informational popup, if present. - const connectingPopupTitle = popupPage.locator("h3", { - hasText: "Connecting with Taho", - }) + await dappPage.locator("text=Injected").click() // Opens a new tab - expect(await connectingPopupTitle.count()).toBe(1) - await expect(connectingPopupTitle).toBeVisible() - - // Clear the popover. - const popupCloseLocator = popupPage.getByRole("button", { - name: "Background close", - }) + await popupPage.ready() - await popupCloseLocator.click() - await popupCloseLocator.waitFor({ state: "detached", timeout: 1000 }) + await popupPage.hideDappConnectPopup() - await popupPage.locator("button", { hasText: "Reject" }).click() + await popupPage.closeWindow() await dappPage.close() @@ -48,15 +33,15 @@ test.describe("dApp Connections", () => { .first() .click() + const popup2 = walletPageHelper.getConnectPopup() + + await dappPage2.locator("text=Injected").click() // Opens a new tab // Get page after a specific action (e.g. clicking a link) - const [popupPage2] = await Promise.all([ - context.waitForEvent("page"), - await dappPage2.locator("text=Injected").click(), // Opens a new tab - ]) - await popupPage2.waitForLoadState() + + await popup2.ready() // Check that the popup is no longer displayed. - const connectingPopupTitle2 = popupPage2.locator("h3", { + const connectingPopupTitle2 = popup2.page.locator("h3", { hasText: "Connecting with Taho", }) expect(await connectingPopupTitle2.count()).toBe(0) @@ -68,23 +53,23 @@ test.describe("dApp Connections", () => { walletPageHelper, }) => { await walletPageHelper.onboarding.addReadOnlyAccount("testertesting.eth") - await walletPageHelper.hideDappConnectPopup() const dappPage = await context.newPage() await dappPage.goto("https://swap.cow.fi/") + + const popup = walletPageHelper.getConnectPopup() + await dappPage .getByRole("button", { name: "Connect Wallet" }) .first() .click() // Get page after a specific action (e.g. clicking a link) - const [popupPage] = await Promise.all([ - context.waitForEvent("page"), - await dappPage.locator("text=Injected").click(), // Opens a new tab - ]) - await popupPage.waitForLoadState() + await dappPage.locator("text=Injected").click() // Opens a new tab - await popupPage.locator("button", { hasText: "Connect" }).click() + await popup.ready() + await popup.hideDappConnectPopup() + await popup.acceptConnection() await walletPageHelper.goToStartPage() diff --git a/e2e-tests/regular/signing.spec.ts b/e2e-tests/regular/signing.spec.ts index caa3e7ac1..4b7b7fa78 100644 --- a/e2e-tests/regular/signing.spec.ts +++ b/e2e-tests/regular/signing.spec.ts @@ -4,33 +4,30 @@ test.describe("Signing", () => { test("User can sign in with Ethereum", async ({ context, walletPageHelper, + waitForExtensionPage, }) => { await walletPageHelper.onboarding.addNewWallet() - await walletPageHelper.hideDappConnectPopup() const siwe = await context.newPage() await siwe.goto("https://login.xyz") await siwe.getByRole("button", { name: "SIGN-IN WITH ETHEREUM" }).click() - const connectPopupOpens = context.waitForEvent("page") + const connectPopup = walletPageHelper.getConnectPopup() await siwe.getByTestId("component-wallet-button-taho").click() - await connectPopupOpens.then(async (popup) => { - await popup.waitForLoadState() - await popup.getByRole("button", { name: "Connect", exact: true }).click() - }) + await connectPopup.ready() + await connectPopup.hideDappConnectPopup() + + await connectPopup.acceptConnection() - const signDataPromptOpens = context.waitForEvent("page") + const signDataPromptOpens = waitForExtensionPage() await signDataPromptOpens.then(async (prompt) => { + await prompt.waitForLoadState() await prompt.getByRole("button", { name: "Sign" }).click() }) - // There's a bug on login.xyz that makes the test fail - // (https://discord.com/channels/862419652286218251/886997073650655232/1173226370776694794). - // We're adding the expectation of failure. Playwright will throw `Expected - // to fail, but passed.` when bug is fixed. - test.fail() + await expect(siwe.getByText("Vote for your favorite emoji")).toBeVisible() }) diff --git a/e2e-tests/utils.ts b/e2e-tests/utils.ts index 6d59b6b9a..afa6b1fd9 100644 --- a/e2e-tests/utils.ts +++ b/e2e-tests/utils.ts @@ -1,5 +1,5 @@ /* eslint-disable no-empty-pattern */ -import { test as base, chromium, Request, Worker } from "@playwright/test" +import { test as base, chromium, Page, Request, Worker } from "@playwright/test" import path from "path" import WalletPageHelper from "./utils/walletPageHelper" import AssetsHelper from "./utils/assets" @@ -15,6 +15,7 @@ type WalletTestFixtures = { transactionsHelper: TransactionsHelper backgroundPage: Worker isExtensionRequest: (request: Request) => boolean + waitForExtensionPage: () => Promise } /** @@ -52,6 +53,11 @@ export const test = base.extend({ const extensionId = backgroundPage.url().split("/")[2] await use(extensionId) }, + waitForExtensionPage: async ({ context, extensionId }, use) => { + await use(async () => + context.waitForEvent("page", (page) => page.url().includes(extensionId)), + ) + }, isExtensionRequest: async ({}, use) => { const hasExtensionOrigin = (url: string) => /^chrome-extension:\/\//.test(url) diff --git a/e2e-tests/utils/connect-popup.ts b/e2e-tests/utils/connect-popup.ts new file mode 100644 index 000000000..6115f223d --- /dev/null +++ b/e2e-tests/utils/connect-popup.ts @@ -0,0 +1,65 @@ +import { BrowserContext, Page, expect } from "@playwright/test" + +export default class SiteConnectionHelper { + get page() { + if (this.#targetPage === null) { + throw new Error("Connection popup hasn't loaded yet") + } + return this.#targetPage + } + + #targetPage: Page | null = null + + #pagePromise: Promise + + constructor( + private readonly context: BrowserContext, + extensionId: string, + ) { + this.#pagePromise = this.context.waitForEvent("page", (page) => + page.url().includes(extensionId), + ) + } + + async ready() { + const popup = await this.#pagePromise + await popup.waitForLoadState() + this.#targetPage = popup + } + + /** + * Hides the dApp Connection "use Taho as default" informational popup so + * tests can proceed assuming dApp connection will be available without + * additional interactions. + */ + async hideDappConnectPopup(): Promise { + // Clear the one-time informational popup, if present. + const connectingPopupTitle = this.page.locator("h3", { + hasText: "Connecting with Taho", + }) + + expect(await connectingPopupTitle.count()).toBe(1) + + await expect(connectingPopupTitle).toBeVisible() + + // Clear the popover. + const bgLocator = this.page + .locator(".bg") + .getByRole("button", { name: "Close" }) + + await bgLocator.click() + await bgLocator.waitFor({ state: "detached", timeout: 1000 }) + } + + async rejectConnection() { + await this.page.locator("button", { hasText: "Reject" }).click() + } + + async acceptConnection() { + await this.page.getByRole("button", { name: "Connect" }).click() + } + + async closeWindow() { + await this.page.close() + } +} diff --git a/e2e-tests/utils/walletPageHelper.ts b/e2e-tests/utils/walletPageHelper.ts index db5c68963..7e2f37c5e 100644 --- a/e2e-tests/utils/walletPageHelper.ts +++ b/e2e-tests/utils/walletPageHelper.ts @@ -1,6 +1,7 @@ import fs from "fs" import { Page, BrowserContext, expect } from "@playwright/test" import OnboardingHelper, { Account, getOnboardingPage } from "./onboarding" +import ConnectPopupHelper from "./connect-popup" export default class WalletPageHelper { readonly url: string @@ -11,6 +12,10 @@ export default class WalletPageHelper { return this.#onboardingHelper } + getConnectPopup(): ConnectPopupHelper { + return new ConnectPopupHelper(this.context, this.extensionId) + } + constructor( public readonly popup: Page, public readonly context: BrowserContext, @@ -300,41 +305,4 @@ export default class WalletPageHelper { this.popup.getByTestId("top_menu_profile_button").last(), ).toHaveText(accountName) } - - /** - * Hides the dApp Connection "use Taho as default" informational popup so - * tests can proceed assuming dApp connection will be available without - * additional interactions. - */ - async hideDappConnectPopup(): Promise { - const dappPage = await this.context.newPage() - await dappPage.goto("https://swap.cow.fi/") - await dappPage - .getByRole("button", { name: "Connect Wallet" }) - .first() - .click() - - const [popupPage] = await Promise.all([ - this.context.waitForEvent("page"), - await dappPage.locator("text=Injected").click(), // Opens a new tab - ]) - await popupPage.waitForLoadState() - - // Clear the one-time informational popup, if present. - const connectingPopupTitle = popupPage.locator("h3", { - hasText: "Connecting with Taho", - }) - if ((await connectingPopupTitle.count()) > 0) { - await expect(connectingPopupTitle).toBeVisible() - const bgLocator = popupPage - .locator(".bg") - .getByRole("button", { name: "Close" }) - - await bgLocator.click() - await bgLocator.waitFor({ state: "detached", timeout: 1000 }) - } - - await popupPage.close() - await dappPage.close() - } }