From 5cf536923611a185d9965844b54a0c7927286e53 Mon Sep 17 00:00:00 2001 From: amaify2 Date: Wed, 24 Jun 2026 10:42:58 +0100 Subject: [PATCH 1/5] [MetaMask] - Fix issues with MetaMask --- src/wallets/metamask/actions/switch-account.metamask.ts | 4 +++- src/wallets/metamask/metamask-worker-scope-fixture.ts | 1 - src/wallets/metamask/worker-scope-context.metamask.ts | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/wallets/metamask/actions/switch-account.metamask.ts b/src/wallets/metamask/actions/switch-account.metamask.ts index 545856b..fc88f7c 100644 --- a/src/wallets/metamask/actions/switch-account.metamask.ts +++ b/src/wallets/metamask/actions/switch-account.metamask.ts @@ -40,5 +40,7 @@ export async function switchAccount(page: Page, accountName: string) { throw Error(`Account with name "${accountName}" not found.`); } - await currentAccount?.click(); + await currentAccount.click(); + const loadingSpinner = page.locator("div[class='spinner loading-overlay__spinner']"); + await loadingSpinner.waitFor({ state: "detached" }); } diff --git a/src/wallets/metamask/metamask-worker-scope-fixture.ts b/src/wallets/metamask/metamask-worker-scope-fixture.ts index bb415bd..c098ac2 100644 --- a/src/wallets/metamask/metamask-worker-scope-fixture.ts +++ b/src/wallets/metamask/metamask-worker-scope-fixture.ts @@ -20,7 +20,6 @@ export const metamaskWorkerScopeFixture = ({ profileName, slowMo }: WalletProfil profileName, slowMo, }); - await context.grantPermissions(["clipboard-read"]); const metamask = new Metamask(walletPageFromContext); await metamask.unlock(); diff --git a/src/wallets/metamask/worker-scope-context.metamask.ts b/src/wallets/metamask/worker-scope-context.metamask.ts index ca04053..5e08321 100644 --- a/src/wallets/metamask/worker-scope-context.metamask.ts +++ b/src/wallets/metamask/worker-scope-context.metamask.ts @@ -52,5 +52,8 @@ export async function workerScopeContextMetamask({ workerInfo, profileName, slow } } + const loadingSpinner = page.locator("img[class='loading-spinner']"); + await loadingSpinner.waitFor({ state: "detached" }); + return { context, walletPage: page, contextPath }; } From ad6fc4a3e0a6f44c619fd4985e2b00b68de005d4 Mon Sep 17 00:00:00 2001 From: amaify2 Date: Wed, 24 Jun 2026 11:42:14 +0100 Subject: [PATCH 2/5] [Wallets] - Code improvement and update playwright config for CI tests. --- src/utils/wallets/get-popup-page-from-context.ts | 2 +- src/wallets/keplr/keplr-fixture.ts | 11 ++--------- src/wallets/metamask/metamask-fixture.ts | 15 ++++----------- .../metamask/worker-scope-context.metamask.ts | 4 +++- src/wallets/meteor/meteor-fixture.ts | 9 +++------ src/wallets/petra/petra-fixture.ts | 13 +++---------- src/wallets/phantom/phantom-fixture.ts | 10 +++------- .../phantom/worker-scope-context.phantom.ts | 4 +++- src/wallets/solflare/solflare-fixture.ts | 13 +++---------- .../solflare/worker-scope-context.solflare.ts | 4 +++- src/wallets/utils/get-browser-args.ts | 12 ++++++++++++ src/wallets/utils/worker-scope-context.ts | 4 +++- tests/playwright.config.ts | 2 +- 13 files changed, 44 insertions(+), 59 deletions(-) create mode 100644 src/wallets/utils/get-browser-args.ts diff --git a/src/utils/wallets/get-popup-page-from-context.ts b/src/utils/wallets/get-popup-page-from-context.ts index b68a0cf..059733f 100644 --- a/src/utils/wallets/get-popup-page-from-context.ts +++ b/src/utils/wallets/get-popup-page-from-context.ts @@ -19,7 +19,7 @@ export async function getPopupPageFromContext({ context, path, locator }: GetPop return !!popupPage; }, { - timeout: 30_000, + timeout: 60_000, }, ) .toBe(true); diff --git a/src/wallets/keplr/keplr-fixture.ts b/src/wallets/keplr/keplr-fixture.ts index a120b42..4437f43 100644 --- a/src/wallets/keplr/keplr-fixture.ts +++ b/src/wallets/keplr/keplr-fixture.ts @@ -9,6 +9,7 @@ import persistLocalStorage from "@/utils/persist-local-storage"; import { teardownContext } from "@/utils/teardown-context"; import waitForStablePage from "@/utils/wait-for-stable-page"; import { getWalletExtensionPathFromCache } from "@/utils/wallets/get-wallet-extension-path-from-cache"; +import { getBrowserArgs } from "../utils/get-browser-args"; import { unlock } from "./actions/unlock.keplr"; import { Keplr } from "./keplr"; import { KeplrProfile } from "./keplr-profile"; @@ -36,15 +37,7 @@ export const keplrFixture = ({ slowMo = 0, profileName }: WalletProfileFixtureAr fs.cpSync(walletDataDir, tempWalletDataDir, { recursive: true, force: true }); - const browserArgs = [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`]; - if (process.env.HEADLESS) { - browserArgs.push("--headless=new"); - - if (slowMo > 0) { - console.warn("⚠️ Slow motion makes no sense in headless mode. It will be ignored!"); - } - } - + const browserArgs = getBrowserArgs(extensionPath, slowMo); const walletPageContext = await chromium.launchPersistentContext(tempWalletDataDir, { headless: false, args: browserArgs, diff --git a/src/wallets/metamask/metamask-fixture.ts b/src/wallets/metamask/metamask-fixture.ts index f8616f4..ee932f1 100644 --- a/src/wallets/metamask/metamask-fixture.ts +++ b/src/wallets/metamask/metamask-fixture.ts @@ -9,6 +9,7 @@ import getPageFromContext from "@/utils/get-page-from-context"; import persistLocalStorage from "@/utils/persist-local-storage"; import { teardownContext } from "@/utils/teardown-context"; import { getWalletExtensionPathFromCache } from "@/utils/wallets/get-wallet-extension-path-from-cache"; +import { getBrowserArgs } from "../utils/get-browser-args"; import unlock from "./actions/unlock.metamask"; import { Metamask } from "./metamask"; import { MetamaskProfile } from "./metamask-profile"; @@ -35,18 +36,10 @@ export const metamaskFixture = ({ slowMo = 0, profileName }: WalletProfileFixtur fs.cpSync(walletDataDir, tempWalletDataDir, { recursive: true, force: true }); - const browserArgs = [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`]; - if (process.env.HEADLESS) { - browserArgs.push("--headless=new"); - - if (slowMo > 0) { - console.warn("⚠️ Slow motion makes no sense in headless mode. It will be ignored!"); - } - } - + const browserArgs = getBrowserArgs(extensionPath, slowMo); const walletPageContext = await chromium.launchPersistentContext(tempWalletDataDir, { headless: false, - args: [`--disable-extensions-except=${extensionPath}`], + args: browserArgs, slowMo: process.env.HEADLESS ? 0 : slowMo, }); @@ -68,7 +61,7 @@ export const metamaskFixture = ({ slowMo = 0, profileName }: WalletProfileFixtur } const loadingSpinner = _metamaskPage.locator("img[class='loading-spinner']"); - await loadingSpinner.waitFor({ state: "detached" }); + await loadingSpinner.waitFor({ state: "detached", timeout: 45_000 }); await unlock(_metamaskPage); await use(walletPageContext); diff --git a/src/wallets/metamask/worker-scope-context.metamask.ts b/src/wallets/metamask/worker-scope-context.metamask.ts index 5e08321..a67a317 100644 --- a/src/wallets/metamask/worker-scope-context.metamask.ts +++ b/src/wallets/metamask/worker-scope-context.metamask.ts @@ -5,6 +5,7 @@ import createTempContextDirectory from "@/utils/create-temp-context-directory"; import getCacheDirectory from "@/utils/get-cache-directory"; import waitForStablePage from "@/utils/wait-for-stable-page"; import { getWalletExtensionPathFromCache } from "@/utils/wallets/get-wallet-extension-path-from-cache"; +import { getBrowserArgs } from "../utils/get-browser-args"; import { MetamaskProfile } from "./metamask-profile"; type WorkerScopeContext = { @@ -27,9 +28,10 @@ export async function workerScopeContextMetamask({ workerInfo, profileName, slow fs.cpSync(walletDataDir, contextPath, { recursive: true, force: true }); const walletPath = await getWalletExtensionPathFromCache(wallet.name); + const browserArgs = getBrowserArgs(walletPath, slowMo ?? 0); const context = await chromium.launchPersistentContext(contextPath, { headless: false, - args: [`--disable-extensions-except=${walletPath}`], + args: browserArgs, slowMo: process.env.HEADLESS ? 0 : slowMo, }); diff --git a/src/wallets/meteor/meteor-fixture.ts b/src/wallets/meteor/meteor-fixture.ts index 694bbcb..49b81df 100644 --- a/src/wallets/meteor/meteor-fixture.ts +++ b/src/wallets/meteor/meteor-fixture.ts @@ -8,6 +8,7 @@ import getPageFromContext from "@/utils/get-page-from-context"; import persistLocalStorage from "@/utils/persist-local-storage"; import { teardownContext } from "@/utils/teardown-context"; import { getWalletExtensionPathFromCache } from "@/utils/wallets/get-wallet-extension-path-from-cache"; +import { getBrowserArgs } from "../utils/get-browser-args"; import { unlock } from "./actions/unlock.meteor"; import { Meteor } from "./meteor"; import { MeteorProfile } from "./meteor-profile"; @@ -34,15 +35,11 @@ export const meteorFixture = ({ slowMo = 0, profileName }: WalletProfileFixtureA fs.cpSync(walletDataDir, tempWalletDataDir, { recursive: true, force: true }); - if (process.env.HEADLESS) { - if (slowMo > 0) { - console.warn("⚠️ Slow motion makes no sense in headless mode. It will be ignored!"); - } - } + const browserArgs = getBrowserArgs(extensionPath, slowMo); const walletPageContext = await chromium.launchPersistentContext(tempWalletDataDir, { headless: false, - args: [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`], + args: browserArgs, slowMo: process.env.HEADLESS ? 0 : slowMo, }); diff --git a/src/wallets/petra/petra-fixture.ts b/src/wallets/petra/petra-fixture.ts index 0a3352d..2a8e5fb 100644 --- a/src/wallets/petra/petra-fixture.ts +++ b/src/wallets/petra/petra-fixture.ts @@ -8,6 +8,7 @@ import getPageFromContext from "@/utils/get-page-from-context"; import persistLocalStorage from "@/utils/persist-local-storage"; import { teardownContext } from "@/utils/teardown-context"; import { getWalletExtensionPathFromCache } from "@/utils/wallets/get-wallet-extension-path-from-cache"; +import { getBrowserArgs } from "../utils/get-browser-args"; import unlock from "./actions/unlock.petra"; import { Petra } from "./petra"; import { PetraProfile } from "./petra-profile"; @@ -34,18 +35,10 @@ export const petraFixture = ({ slowMo = 0, profileName }: WalletProfileFixtureAr fs.cpSync(walletDataDir, tempWalletDataDir, { recursive: true, force: true }); - const browserArgs = [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`]; - if (process.env.HEADLESS) { - browserArgs.push("--headless=new"); - - if (slowMo > 0) { - console.warn("⚠️ Slow motion makes no sense in headless mode. It will be ignored!"); - } - } - + const browserArgs = getBrowserArgs(extensionPath, slowMo); const walletPageContext = await chromium.launchPersistentContext(tempWalletDataDir, { headless: false, - args: [`--disable-extensions-except=${extensionPath}`], + args: browserArgs, slowMo: process.env.HEADLESS ? 0 : slowMo, }); diff --git a/src/wallets/phantom/phantom-fixture.ts b/src/wallets/phantom/phantom-fixture.ts index f8fc32d..13096da 100644 --- a/src/wallets/phantom/phantom-fixture.ts +++ b/src/wallets/phantom/phantom-fixture.ts @@ -8,6 +8,7 @@ import getPageFromContext from "@/utils/get-page-from-context"; import persistLocalStorage from "@/utils/persist-local-storage"; import { teardownContext } from "@/utils/teardown-context"; import { getWalletExtensionPathFromCache } from "@/utils/wallets/get-wallet-extension-path-from-cache"; +import { getBrowserArgs } from "../utils/get-browser-args"; import { unlock } from "./actions/unlock.phantom"; import { Phantom } from "./phantom"; import { PhantomProfile } from "./phantom-profile"; @@ -36,15 +37,10 @@ export const phantomFixture = ({ slowMo = 0, profileName }: WalletProfileFixture fs.cpSync(walletDataDir, tempWalletDataDir, { recursive: true, force: true }); - if (process.env.HEADLESS) { - if (slowMo > 0) { - console.warn("⚠️ Slow motion makes no sense in headless mode. It will be ignored!"); - } - } - + const browserArgs = getBrowserArgs(extensionPath, slowMo); const walletPageContext = await chromium.launchPersistentContext(tempWalletDataDir, { headless: false, - args: [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`], + args: browserArgs, slowMo: process.env.HEADLESS ? 0 : slowMo, }); diff --git a/src/wallets/phantom/worker-scope-context.phantom.ts b/src/wallets/phantom/worker-scope-context.phantom.ts index 8d51123..9e0c0d2 100644 --- a/src/wallets/phantom/worker-scope-context.phantom.ts +++ b/src/wallets/phantom/worker-scope-context.phantom.ts @@ -5,6 +5,7 @@ import createTempContextDirectory from "@/utils/create-temp-context-directory"; import getCacheDirectory from "@/utils/get-cache-directory"; import getPageFromContext from "@/utils/get-page-from-context"; import { getWalletExtensionPathFromCache } from "@/utils/wallets/get-wallet-extension-path-from-cache"; +import { getBrowserArgs } from "../utils/get-browser-args"; import { PhantomProfile } from "./phantom-profile"; type WorkerScopeContext = { @@ -27,9 +28,10 @@ export async function workerScopeContextPhantom({ workerInfo, profileName, slowM fs.cpSync(walletDataDir, contextPath, { recursive: true, force: true }); const walletPath = await getWalletExtensionPathFromCache(wallet.name); + const browserArgs = getBrowserArgs(walletPath, slowMo ?? 0); const context = await chromium.launchPersistentContext(contextPath, { headless: false, - args: [`--disable-extensions-except=${walletPath}`], + args: browserArgs, slowMo: process.env.HEADLESS ? 0 : slowMo, }); diff --git a/src/wallets/solflare/solflare-fixture.ts b/src/wallets/solflare/solflare-fixture.ts index 0935347..df65257 100644 --- a/src/wallets/solflare/solflare-fixture.ts +++ b/src/wallets/solflare/solflare-fixture.ts @@ -8,6 +8,7 @@ import getPageFromContext from "@/utils/get-page-from-context"; import persistLocalStorage from "@/utils/persist-local-storage"; import { teardownContext } from "@/utils/teardown-context"; import { getWalletExtensionPathFromCache } from "@/utils/wallets/get-wallet-extension-path-from-cache"; +import { getBrowserArgs } from "../utils/get-browser-args"; import { unlock } from "./actions/unlock.solflare"; import { Solflare } from "./solflare"; import { SolflareProfile } from "./solflare-profile"; @@ -35,18 +36,10 @@ export const solflareFixture = ({ slowMo = 0, profileName }: WalletProfileFixtur await fs.promises.cp(walletDataDir, tempWalletDataDir, { recursive: true, force: true }); - const browserArgs = [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`]; - if (process.env.HEADLESS) { - browserArgs.push("--headless=new"); - - if (slowMo > 0) { - console.warn("⚠️ Slow motion makes no sense in headless mode. It will be ignored!"); - } - } - + const browserArgs = getBrowserArgs(extensionPath, slowMo); const walletPageContext = await chromium.launchPersistentContext(tempWalletDataDir, { headless: false, - args: [`--disable-extensions-except=${extensionPath}`], + args: browserArgs, slowMo: process.env.HEADLESS ? 0 : slowMo, }); diff --git a/src/wallets/solflare/worker-scope-context.solflare.ts b/src/wallets/solflare/worker-scope-context.solflare.ts index 2dda7b3..b69d1ab 100644 --- a/src/wallets/solflare/worker-scope-context.solflare.ts +++ b/src/wallets/solflare/worker-scope-context.solflare.ts @@ -5,6 +5,7 @@ import createTempContextDirectory from "@/utils/create-temp-context-directory"; import getCacheDirectory from "@/utils/get-cache-directory"; import waitForStablePage from "@/utils/wait-for-stable-page"; import { getWalletExtensionPathFromCache } from "@/utils/wallets/get-wallet-extension-path-from-cache"; +import { getBrowserArgs } from "../utils/get-browser-args"; import { SolflareProfile } from "./solflare-profile"; type WorkerScopeContext = { @@ -27,9 +28,10 @@ export async function workerScopeContextSolana({ workerInfo, profileName, slowMo fs.cpSync(walletDataDir, contextPath, { recursive: true, force: true }); const walletPath = await getWalletExtensionPathFromCache(wallet.name); + const browserArgs = getBrowserArgs(walletPath, slowMo ?? 0); const context = await chromium.launchPersistentContext(contextPath, { headless: false, - args: [`--disable-extensions-except=${walletPath}`], + args: browserArgs, slowMo: process.env.HEADLESS ? 0 : slowMo, }); diff --git a/src/wallets/utils/get-browser-args.ts b/src/wallets/utils/get-browser-args.ts new file mode 100644 index 0000000..2fcd067 --- /dev/null +++ b/src/wallets/utils/get-browser-args.ts @@ -0,0 +1,12 @@ +export function getBrowserArgs(extensionPath: string, slowMo: number) { + const browserArgs = [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`]; + if (process.env.HEADLESS) { + browserArgs.push("--headless=new"); + + if (slowMo > 0) { + console.warn("⚠️ Slow motion makes no sense in headless mode. It will be ignored!"); + } + } + + return browserArgs; +} diff --git a/src/wallets/utils/worker-scope-context.ts b/src/wallets/utils/worker-scope-context.ts index ad66774..81e990d 100644 --- a/src/wallets/utils/worker-scope-context.ts +++ b/src/wallets/utils/worker-scope-context.ts @@ -5,6 +5,7 @@ import createTempContextDirectory from "@/utils/create-temp-context-directory"; import getCacheDirectory from "@/utils/get-cache-directory"; import { getWalletExtensionPathFromCache } from "@/utils/wallets/get-wallet-extension-path-from-cache"; import type { BaseWallet } from "./base-wallet"; +import { getBrowserArgs } from "./get-browser-args"; type WorkerScopeContext = { workerInfo: WorkerInfo; @@ -40,9 +41,10 @@ export async function workerScopeContext({ fs.cpSync(walletDataDir, contextPath, { recursive: true, force: true }); const walletPath = await getWalletExtensionPathFromCache(wallet.name); + const browserArgs = getBrowserArgs(walletPath, slowMo ?? 0); const context = await chromium.launchPersistentContext(contextPath, { headless: false, - args: [`--disable-extensions-except=${walletPath}`], + args: browserArgs, slowMo: process.env.HEADLESS ? 0 : slowMo, }); diff --git a/tests/playwright.config.ts b/tests/playwright.config.ts index c35a2de..23a2c4c 100644 --- a/tests/playwright.config.ts +++ b/tests/playwright.config.ts @@ -13,7 +13,7 @@ export default defineConfig({ reporter: [["list"]], /* Global timeout for each test */ - timeout: process.env.CI ? 60_000 : 30_000, + timeout: process.env.CI ? 120_000 : 60_000, use: { // We are using locally deployed Metamask Test Dapp for somePhantom tests. From 324e8aa210a57634b3b2943d5f1c18e32cc12cfa Mon Sep 17 00:00:00 2001 From: amaify2 Date: Wed, 24 Jun 2026 11:53:56 +0100 Subject: [PATCH 3/5] [CI] - Upload the artifacts. --- .github/workflows/chainwright.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/chainwright.yaml b/.github/workflows/chainwright.yaml index 99186ba..0cb288b 100644 --- a/.github/workflows/chainwright.yaml +++ b/.github/workflows/chainwright.yaml @@ -97,3 +97,12 @@ jobs: - name: Skip e2e tests (no relevant file changes) if: github.event_name != 'workflow_dispatch' && steps.changed-tests.outputs.test_files == '' run: echo "No relevant test files changed - skipping tests" + + - name: Upload Playwright artifacts + if: ${{ !failure() }} + uses: actions/upload-artifact@v4 + with: + name: playwright-test-results + path: tests/test-results/ + retention-days: 4 + if-no-files-found: ignore From aa65408fdbed8ebd82466367bfcd7bdb730e90b0 Mon Sep 17 00:00:00 2001 From: amaify2 Date: Wed, 24 Jun 2026 12:03:59 +0100 Subject: [PATCH 4/5] [CI] - Upload Playwright artifacts. --- .github/workflows/chainwright.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/chainwright.yaml b/.github/workflows/chainwright.yaml index 0cb288b..80844d5 100644 --- a/.github/workflows/chainwright.yaml +++ b/.github/workflows/chainwright.yaml @@ -99,10 +99,12 @@ jobs: run: echo "No relevant test files changed - skipping tests" - name: Upload Playwright artifacts - if: ${{ !failure() }} + if: ${{ !cancelled() }} uses: actions/upload-artifact@v4 with: name: playwright-test-results - path: tests/test-results/ + path: | + test-results/ + tests/test-results/ retention-days: 4 if-no-files-found: ignore From 491f5044a944f00d8345a36713e6165c2bf0eda3 Mon Sep 17 00:00:00 2001 From: amaify2 Date: Wed, 24 Jun 2026 14:13:05 +0100 Subject: [PATCH 5/5] chore: fix Metamask's onboarding flow. --- src/wallets/keplr/actions/onboard.keplr.ts | 2 - .../metamask/actions/onboard.metamask.ts | 4 +- src/wallets/metamask/utils.ts | 52 ++++++++++++++++++- src/wallets/meteor/actions/onboard.meteor.ts | 1 - src/wallets/petra/actions/onboard.petra.ts | 2 - .../phantom/actions/onboard.phantom.ts | 1 - tests/playwright.config.ts | 4 +- 7 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/wallets/keplr/actions/onboard.keplr.ts b/src/wallets/keplr/actions/onboard.keplr.ts index ad3eca9..c9fc263 100644 --- a/src/wallets/keplr/actions/onboard.keplr.ts +++ b/src/wallets/keplr/actions/onboard.keplr.ts @@ -1,6 +1,5 @@ import { styleText } from "node:util"; import { expect, type Page } from "@playwright/test"; -import { sleep } from "@/utils/sleep"; import { homepageSelectors } from "../selectors/homepage-selectors.keplr"; import type { OnboardingArgs } from "../types"; import { addWalletViaPrivateKey, addWalletViaSeedPhrase, goToOnboardingPage } from "../utils"; @@ -115,6 +114,5 @@ export default async function onboard({ page, onboard }: Onboard) { } } - await sleep(3_000); console.info(styleText("greenBright", "✨ Keplr onboarding completed successfully", { validateStream: false })); } diff --git a/src/wallets/metamask/actions/onboard.metamask.ts b/src/wallets/metamask/actions/onboard.metamask.ts index 5648424..bbcd29e 100644 --- a/src/wallets/metamask/actions/onboard.metamask.ts +++ b/src/wallets/metamask/actions/onboard.metamask.ts @@ -1,11 +1,11 @@ import { styleText } from "node:util"; import { expect, type Page } from "@playwright/test"; -import { sleep } from "@/utils/sleep"; import { getWalletPasswordFromCache } from "@/utils/wallets/get-wallet-password-from-cache"; import { MetamaskProfile } from "../metamask-profile"; import { homepageSelectors } from "../selectors/homepage-selectors.metamask"; import { onboardSelectors } from "../selectors/onboard-selectors.metamask"; import type { OnboardingArgs } from "../types"; +import { ensureMetaMaskOnboardingCompleted } from "../utils"; import { switchAccount } from "./switch-account.metamask"; import { toggleShowTestnetNetwork } from "./toggle-show-testnet-network.metamask"; @@ -142,6 +142,6 @@ export default async function onboard({ page, mainAccountName, ...args }: Onboar await switchAccount(page, mainAccountName); } - await sleep(5_000); + await ensureMetaMaskOnboardingCompleted(page); console.info(styleText("greenBright", "✨ MetaMask onboarding completed successfully", { validateStream: false })); } diff --git a/src/wallets/metamask/utils.ts b/src/wallets/metamask/utils.ts index feb6fff..01099b8 100644 --- a/src/wallets/metamask/utils.ts +++ b/src/wallets/metamask/utils.ts @@ -1,4 +1,4 @@ -import { errors, type Page } from "@playwright/test"; +import { errors, expect, type Page } from "@playwright/test"; import { sleep } from "@/utils/sleep"; import waitForStablePage from "@/utils/wait-for-stable-page"; import { loadingSelectors } from "./selectors/loading-selectors.metamask"; @@ -35,3 +35,53 @@ export const waitForMetaMaskLoad = async (page: Page) => { return page; }; + +export async function ensureMetaMaskOnboardingCompleted(page: Page) { + const extensionUrl = new URL(page.url()); + const extensionOrigin = `${extensionUrl.protocol}//${extensionUrl.host}`; + const context = page.context(); + + const serviceWorker = + context.serviceWorkers().find((worker) => worker.url().startsWith(extensionOrigin)) ?? + (await context.waitForEvent("serviceworker", { + predicate: (worker) => worker.url().startsWith(extensionOrigin), + timeout: 60_000, + })); + + await expect + .poll( + async () => { + try { + return await serviceWorker.evaluate( + `(async () => { + const state = await chrome.storage.local.get([ + "OnboardingController", + "KeyringController", + "PreferencesController", + ]); + const record = (value) => value && typeof value === "object" ? value : {}; + + const onboarding = record(state.OnboardingController); + const keyring = record(state.KeyringController); + const preferencesController = record(state.PreferencesController); + const preferences = record(preferencesController.preferences); + + return ( + onboarding.completedOnboarding === true && + typeof keyring.vault === "string" && + keyring.vault.length > 0 && + preferences.showTestNetworks === true + ); + })()`, + ); + } catch { + return false; + } + }, + { + message: "MetaMask onboarding state was not persisted to extension storage", + timeout: 60_000, + }, + ) + .toBe(true); +} diff --git a/src/wallets/meteor/actions/onboard.meteor.ts b/src/wallets/meteor/actions/onboard.meteor.ts index 2912806..42cd266 100644 --- a/src/wallets/meteor/actions/onboard.meteor.ts +++ b/src/wallets/meteor/actions/onboard.meteor.ts @@ -148,6 +148,5 @@ export default async function onboard({ page, network, accountName, additionalAc await switchAccount(page, accountName); } - await sleep(3_000); console.info(styleText("greenBright", "✨ Meteor onboarding completed successfully")); } diff --git a/src/wallets/petra/actions/onboard.petra.ts b/src/wallets/petra/actions/onboard.petra.ts index 89013d1..10dc037 100644 --- a/src/wallets/petra/actions/onboard.petra.ts +++ b/src/wallets/petra/actions/onboard.petra.ts @@ -1,6 +1,5 @@ import { styleText } from "node:util"; import { expect, type Page } from "@playwright/test"; -import { sleep } from "@/utils/sleep"; import waitForStablePage from "@/utils/wait-for-stable-page"; import { getWalletPasswordFromCache } from "@/utils/wallets/get-wallet-password-from-cache"; import { PetraProfile } from "../petra-profile"; @@ -121,6 +120,5 @@ export default async function onboard({ page, network, ...args }: Onboard) { await switchNetwork(page, network); - await sleep(1_500); console.info(styleText("greenBright", "✨ Petra onboarding completed successfully", { validateStream: false })); } diff --git a/src/wallets/phantom/actions/onboard.phantom.ts b/src/wallets/phantom/actions/onboard.phantom.ts index 72d35b8..98d0e69 100644 --- a/src/wallets/phantom/actions/onboard.phantom.ts +++ b/src/wallets/phantom/actions/onboard.phantom.ts @@ -216,6 +216,5 @@ export default async function onboard({ page, additionalAccounts, ...args }: Onb await switchNetwork({ page: newPage, ...args.toggleNetworkMode }); } - await sleep(3_000); console.info(styleText("greenBright", "✨ Phantom onboarding completed successfully", { validateStream: false })); } diff --git a/tests/playwright.config.ts b/tests/playwright.config.ts index 23a2c4c..c7c2f11 100644 --- a/tests/playwright.config.ts +++ b/tests/playwright.config.ts @@ -13,11 +13,11 @@ export default defineConfig({ reporter: [["list"]], /* Global timeout for each test */ - timeout: process.env.CI ? 120_000 : 60_000, + timeout: process.env.CI ? 60_000 : 45_000, use: { // We are using locally deployed Metamask Test Dapp for somePhantom tests. - baseURL: process.env.CI ? "https://chainwright-dapp.vercel.app/" : "https://chainwright-dapp.vercel.app/", + baseURL: "https://chainwright-dapp.vercel.app/", // Collect all traces on CI, and only traces for failed tests when running locally. // See https://playwright.dev/docs/trace-viewer.