From b29c3a6eee05301a4c1461f8f7d20dd18fd03fe9 Mon Sep 17 00:00:00 2001 From: amaify2 Date: Tue, 23 Jun 2026 15:15:33 +0100 Subject: [PATCH 01/14] [Core] - Update Keplr wallet version --- src/utils/constants.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/constants.ts b/src/utils/constants.ts index c1491e9..365774f 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -5,7 +5,7 @@ export const WALLET_CONTEXT_DIR_NAME = ".wallet-context"; export const WALLET_SETUP_DIR_NAME = "wallet-setup"; const METAMASK_VERSION = "13.33.0"; -const KEPLR_VERSION = "0.13.3"; +const KEPLR_VERSION = "0.13.39"; const ARCHIVED_WALLET_BASE_URL = `https://github.com/amaify/chainwright/releases/download/v0.1.0/`; const KEPLR_WALLET_BASE_URL = `https://github.com/chainapsis/keplr-wallet/releases/download/v${KEPLR_VERSION}/`; @@ -47,6 +47,6 @@ export const SUPPORTED_WALLETS: SupportedWalletsMap = { keplr: { downloadUrl: KEPLR_DOWNLOAD_URL, extensionName: "Keplr", - sha256: "df601d806aea6b345ab0fc53504c58ecae1aa0c108d8b3f02dd743e0fcbb0751", + sha256: "15811192edf86074e351c4e4e569ec1282054f316f6d958fa6c5485e23aa47b6", }, }; From 2d326c1d3a2395a06d7caac1218665ea0b87cfe1 Mon Sep 17 00:00:00 2001 From: amaify2 Date: Tue, 23 Jun 2026 16:16:06 +0100 Subject: [PATCH 02/14] [Core] - Pin Playwright version to v1.61.0 --- package.json | 4 ++-- pnpm-lock.yaml | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 9a141a9..a35f610 100644 --- a/package.json +++ b/package.json @@ -89,12 +89,12 @@ "add:wallet": "tsx scripts/add-wallet.ts" }, "peerDependencies": { - "@playwright/test": "1.60.0" + "@playwright/test": "1.61.0" }, "devDependencies": { "@biomejs/biome": "2.4.15", "@changesets/cli": "^2.31.0", - "@playwright/test": "^1.60.0", + "@playwright/test": "1.61.0", "@types/adm-zip": "^0.5.8", "@types/cli-progress": "^3.11.6", "@types/node": "^25.8.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4c64c6e..cd50bb7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,8 +43,8 @@ importers: specifier: ^2.31.0 version: 2.31.0(@types/node@25.9.0) '@playwright/test': - specifier: ^1.60.0 - version: 1.60.0 + specifier: 1.61.0 + version: 1.61.0 '@types/adm-zip': specifier: ^0.5.8 version: 0.5.8 @@ -587,8 +587,8 @@ packages: '@oxc-project/types@0.130.0': resolution: {integrity: sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==} - '@playwright/test@1.60.0': - resolution: {integrity: sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==} + '@playwright/test@1.61.0': + resolution: {integrity: sha512-cKA5B6lpFEMyMGjxF54QihfYpB4FkEGH+qZhtArDEG+wezQAJY8Pq6C7T1SjWz+FFzt3TbyoXBQYk/0292TdJA==} engines: {node: '>=18'} hasBin: true @@ -1436,13 +1436,13 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - playwright-core@1.60.0: - resolution: {integrity: sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==} + playwright-core@1.61.0: + resolution: {integrity: sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA==} engines: {node: '>=18'} hasBin: true - playwright@1.60.0: - resolution: {integrity: sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==} + playwright@1.61.0: + resolution: {integrity: sha512-Z+7BeeqQPRRzklHsVFP4KTGIyMxKUmfeRA4WisM6G3/XW6nwGeX6fX9qYaDa+CiUqpOkb2f6X3nar05R3kSuJQ==} engines: {node: '>=18'} hasBin: true @@ -2235,9 +2235,9 @@ snapshots: '@oxc-project/types@0.130.0': {} - '@playwright/test@1.60.0': + '@playwright/test@1.61.0': dependencies: - playwright: 1.60.0 + playwright: 1.61.0 '@rolldown/binding-android-arm64@1.0.1': optional: true @@ -2944,11 +2944,11 @@ snapshots: mlly: 1.8.2 pathe: 2.0.3 - playwright-core@1.60.0: {} + playwright-core@1.61.0: {} - playwright@1.60.0: + playwright@1.61.0: dependencies: - playwright-core: 1.60.0 + playwright-core: 1.61.0 optionalDependencies: fsevents: 2.3.2 From b3dab22127222cf07f87b5d96666c3fbc493fa65 Mon Sep 17 00:00:00 2001 From: amaify2 Date: Wed, 24 Jun 2026 09:30:14 +0100 Subject: [PATCH 03/14] [All] - Fix failing tests, update actions and downgrade Playwright - Downgrade Playwright to `1.60.0` because of a bug in the latest version `1.61.0`. - Fix race conditions in all fixtures. - Fix failing tests across Metamask, Solflare, and Petra --- package.json | 6 ++--- pnpm-lock.yaml | 26 +++++++++---------- src/wallets/keplr/keplr-fixture.ts | 2 +- src/wallets/metamask/metamask-fixture.ts | 2 +- src/wallets/meteor/meteor-fixture.ts | 2 +- .../petra/actions/switch-network.petra.ts | 2 +- src/wallets/petra/petra-fixture.ts | 2 +- src/wallets/solflare/solflare-fixture.ts | 2 +- .../dapp/confirm-transaction.metamask.spec.ts | 4 +-- .../petra/wallet/switch-network.petra.spec.ts | 10 ++++--- .../wallet/add-account.solflare.spec.ts | 2 +- 11 files changed, 31 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index a35f610..27e23eb 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "version-package": "changeset version", "release": "pnpm run build && changeset publish", "dev": "tsx src/cli/index.ts ./tests/wallet-setup", - "setup-wallets": "tsx src/cli/index.ts ./tests/wallet-setup --all", + "setup-wallets": "tsx src/cli/index.ts ./tests/wallet-setup --all -f", "tests": "vitest --exclude '**/*.spec.ts'", "lint": "biome check ./src", "format": "biome format --write ./src", @@ -89,12 +89,12 @@ "add:wallet": "tsx scripts/add-wallet.ts" }, "peerDependencies": { - "@playwright/test": "1.61.0" + "@playwright/test": "1.60.0" }, "devDependencies": { "@biomejs/biome": "2.4.15", "@changesets/cli": "^2.31.0", - "@playwright/test": "1.61.0", + "@playwright/test": "1.60.0", "@types/adm-zip": "^0.5.8", "@types/cli-progress": "^3.11.6", "@types/node": "^25.8.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cd50bb7..30f0d6e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,8 +43,8 @@ importers: specifier: ^2.31.0 version: 2.31.0(@types/node@25.9.0) '@playwright/test': - specifier: 1.61.0 - version: 1.61.0 + specifier: 1.60.0 + version: 1.60.0 '@types/adm-zip': specifier: ^0.5.8 version: 0.5.8 @@ -587,8 +587,8 @@ packages: '@oxc-project/types@0.130.0': resolution: {integrity: sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==} - '@playwright/test@1.61.0': - resolution: {integrity: sha512-cKA5B6lpFEMyMGjxF54QihfYpB4FkEGH+qZhtArDEG+wezQAJY8Pq6C7T1SjWz+FFzt3TbyoXBQYk/0292TdJA==} + '@playwright/test@1.60.0': + resolution: {integrity: sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==} engines: {node: '>=18'} hasBin: true @@ -1436,13 +1436,13 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - playwright-core@1.61.0: - resolution: {integrity: sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA==} + playwright-core@1.60.0: + resolution: {integrity: sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==} engines: {node: '>=18'} hasBin: true - playwright@1.61.0: - resolution: {integrity: sha512-Z+7BeeqQPRRzklHsVFP4KTGIyMxKUmfeRA4WisM6G3/XW6nwGeX6fX9qYaDa+CiUqpOkb2f6X3nar05R3kSuJQ==} + playwright@1.60.0: + resolution: {integrity: sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==} engines: {node: '>=18'} hasBin: true @@ -2235,9 +2235,9 @@ snapshots: '@oxc-project/types@0.130.0': {} - '@playwright/test@1.61.0': + '@playwright/test@1.60.0': dependencies: - playwright: 1.61.0 + playwright: 1.60.0 '@rolldown/binding-android-arm64@1.0.1': optional: true @@ -2944,11 +2944,11 @@ snapshots: mlly: 1.8.2 pathe: 2.0.3 - playwright-core@1.61.0: {} + playwright-core@1.60.0: {} - playwright@1.61.0: + playwright@1.60.0: dependencies: - playwright-core: 1.61.0 + playwright-core: 1.60.0 optionalDependencies: fsevents: 2.3.2 diff --git a/src/wallets/keplr/keplr-fixture.ts b/src/wallets/keplr/keplr-fixture.ts index 9981452..a120b42 100644 --- a/src/wallets/keplr/keplr-fixture.ts +++ b/src/wallets/keplr/keplr-fixture.ts @@ -55,7 +55,7 @@ export const keplrFixture = ({ slowMo = 0, profileName }: WalletProfileFixtureAr const { cookies, origins } = await currentContext.storageState(); if (cookies) await walletPageContext.addCookies(cookies); - if (origins && origins.length > 0) persistLocalStorage(origins, walletPageContext); + if (origins && origins.length > 0) await persistLocalStorage(origins, walletPageContext); const indexUrl = await wallet.indexUrl(); const homePage = walletPageContext.pages().find((page) => page.url().startsWith(indexUrl)); diff --git a/src/wallets/metamask/metamask-fixture.ts b/src/wallets/metamask/metamask-fixture.ts index 62a4110..f8616f4 100644 --- a/src/wallets/metamask/metamask-fixture.ts +++ b/src/wallets/metamask/metamask-fixture.ts @@ -52,7 +52,7 @@ export const metamaskFixture = ({ slowMo = 0, profileName }: WalletProfileFixtur const { cookies, origins } = await currentContext.storageState(); if (cookies) await walletPageContext.addCookies(cookies); - if (origins && origins.length > 0) persistLocalStorage(origins, walletPageContext); + if (origins && origins.length > 0) await persistLocalStorage(origins, walletPageContext); const indexUrl = await wallet.indexUrl(); await walletPageContext.waitForEvent("page", { diff --git a/src/wallets/meteor/meteor-fixture.ts b/src/wallets/meteor/meteor-fixture.ts index b2a7972..694bbcb 100644 --- a/src/wallets/meteor/meteor-fixture.ts +++ b/src/wallets/meteor/meteor-fixture.ts @@ -50,7 +50,7 @@ export const meteorFixture = ({ slowMo = 0, profileName }: WalletProfileFixtureA const { cookies, origins } = await currentContext.storageState(); if (cookies) await walletPageContext.addCookies(cookies); - if (origins && origins.length > 0) persistLocalStorage(origins, walletPageContext); + if (origins && origins.length > 0) await persistLocalStorage(origins, walletPageContext); const indexUrl = await wallet.indexUrl(); const homePage = walletPageContext.pages().find((page) => page.url().startsWith(indexUrl)); diff --git a/src/wallets/petra/actions/switch-network.petra.ts b/src/wallets/petra/actions/switch-network.petra.ts index 2ae1de3..c629967 100644 --- a/src/wallets/petra/actions/switch-network.petra.ts +++ b/src/wallets/petra/actions/switch-network.petra.ts @@ -9,7 +9,7 @@ export async function switchNetwork(page: Page, networkName: SwitchNetwork) { const networkOptionButton = page.locator(settingsMenuSelectors.networkSection); await networkOptionButton.click(); - const networkOption = page.locator(`div:has(> span:has-text("${networkName}"))`).first(); + const networkOption = page.locator(`div:has(> span:has-text("${networkName}"))`).last(); await networkOption.click(); const backButton = page.locator(settingsMenuSelectors.backButton); diff --git a/src/wallets/petra/petra-fixture.ts b/src/wallets/petra/petra-fixture.ts index 20ddd9e..0a3352d 100644 --- a/src/wallets/petra/petra-fixture.ts +++ b/src/wallets/petra/petra-fixture.ts @@ -53,7 +53,7 @@ export const petraFixture = ({ slowMo = 0, profileName }: WalletProfileFixtureAr const { cookies, origins } = await currentContext.storageState(); if (cookies) await walletPageContext.addCookies(cookies); - if (origins && origins.length > 0) persistLocalStorage(origins, walletPageContext); + if (origins && origins.length > 0) await persistLocalStorage(origins, walletPageContext); const indexUrl = await wallet.indexUrl(); const homePage = walletPageContext.pages().find((page) => page.url().startsWith(indexUrl)); diff --git a/src/wallets/solflare/solflare-fixture.ts b/src/wallets/solflare/solflare-fixture.ts index 71e5f3b..0935347 100644 --- a/src/wallets/solflare/solflare-fixture.ts +++ b/src/wallets/solflare/solflare-fixture.ts @@ -54,7 +54,7 @@ export const solflareFixture = ({ slowMo = 0, profileName }: WalletProfileFixtur const { cookies, origins } = await currentContext.storageState(); if (cookies) await walletPageContext.addCookies(cookies); - if (origins && origins.length > 0) persistLocalStorage(origins, walletPageContext); + if (origins && origins.length > 0) await persistLocalStorage(origins, walletPageContext); const indexUrl = await wallet.indexUrl(); const formatedIndexUrl = indexUrl.split("#")[0] ?? ""; diff --git a/tests/e2e/metamask/dapp/confirm-transaction.metamask.spec.ts b/tests/e2e/metamask/dapp/confirm-transaction.metamask.spec.ts index b0399e2..5ab69f8 100644 --- a/tests/e2e/metamask/dapp/confirm-transaction.metamask.spec.ts +++ b/tests/e2e/metamask/dapp/confirm-transaction.metamask.spec.ts @@ -6,7 +6,7 @@ import type { Metamask } from "@/wallets/metamask/metamask"; const test = testWorkerScopeDappFixture; async function _confirmTransaction(metamask: Metamask, dappPage: Page) { - await metamask.switchAccount({ accountName: "Dapp" }); + await metamask.switchAccount("Dapp"); const connectWalletButton = dappPage.getByTestId("connect-wallet-button"); const isConnectWalletButtonVisible = await connectWalletButton.isVisible().catch(() => false); @@ -38,7 +38,7 @@ test.describe("E2E For Confirming transaction in Metamask wallet", () => { test("Should confirm transaction with warning successfully", async ({ dappPage, workerScopeContents }) => { const { wallet: metamask } = workerScopeContents; - await metamask.switchAccount({ accountName: "Dapp" }); + await metamask.switchAccount("Dapp"); const connectWalletButton = dappPage.getByTestId("connect-wallet-button"); const isConnectWalletButtonVisible = await connectWalletButton.isVisible().catch(() => false); diff --git a/tests/e2e/petra/wallet/switch-network.petra.spec.ts b/tests/e2e/petra/wallet/switch-network.petra.spec.ts index 0d014e4..aa0c18f 100644 --- a/tests/e2e/petra/wallet/switch-network.petra.spec.ts +++ b/tests/e2e/petra/wallet/switch-network.petra.spec.ts @@ -1,10 +1,11 @@ import { expect } from "@playwright/test"; -import { testWithPetraFixture } from "@/tests/fixture/test-with-petra-fixture"; +import { testWithPetraWorkerScope } from "@/tests/fixture/test-with-petra-fixture"; -const test = testWithPetraFixture; +const test = testWithPetraWorkerScope; test.describe("Switch network E2E tests", () => { - test("Should switch to Testnet network successfully", async ({ petra, petraPage }) => { + test("Should switch to Testnet network successfully", async ({ workerScopeContents }) => { + const { wallet: petra, walletPage: petraPage } = workerScopeContents; await petra.switchNetwork("Devnet"); const devnetPulse = petraPage.locator("div>span:has-text('Devnet')"); @@ -16,7 +17,8 @@ test.describe("Switch network E2E tests", () => { await expect(devnetPulse).toBeVisible(); await expect(devnetPulse).toHaveText("Devnet"); }); - test("Should switch to Mainnet network successfully", async ({ petra, petraPage }) => { + test("Should switch to Mainnet network successfully", async ({ workerScopeContents }) => { + const { wallet: petra, walletPage: petraPage } = workerScopeContents; const tokenTabButton = petraPage.locator("button[role='tab']:has-text('Tokens')"); await petra.switchNetwork("Mainnet"); diff --git a/tests/e2e/solflare/wallet/add-account.solflare.spec.ts b/tests/e2e/solflare/wallet/add-account.solflare.spec.ts index 4e455cf..43c8560 100644 --- a/tests/e2e/solflare/wallet/add-account.solflare.spec.ts +++ b/tests/e2e/solflare/wallet/add-account.solflare.spec.ts @@ -11,7 +11,7 @@ const test = testWithsolflareFixture; test("Should add account successfully", async ({ solflare, solflarePage }) => { const WALLET_NAME = "Alpha"; - await solflare.addAccount({ privateKey: PRIVATE_KEY, walletName: WALLET_NAME }); + await solflare.addAccount({ privateKey: `${PRIVATE_KEY}`, walletName: WALLET_NAME }); const openWalletSelectorMenu = solflarePage.getByTestId("icon-section-wallet-picker-arrow-right"); await openWalletSelectorMenu.click(); From a4017c9df30f6f32a91b0e85b0bd789621476cd3 Mon Sep 17 00:00:00 2001 From: amaify2 Date: Wed, 24 Jun 2026 09:32:30 +0100 Subject: [PATCH 04/14] [CI] - Fix failing CI --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 27e23eb..cc28ba1 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "version-package": "changeset version", "release": "pnpm run build && changeset publish", "dev": "tsx src/cli/index.ts ./tests/wallet-setup", - "setup-wallets": "tsx src/cli/index.ts ./tests/wallet-setup --all -f", + "setup-wallets": "tsx src/cli/index.ts ./tests/wallet-setup --all", "tests": "vitest --exclude '**/*.spec.ts'", "lint": "biome check ./src", "format": "biome format --write ./src", From 61543888b3e2048e01f8637dc8ffe7ee1a84b0bb Mon Sep 17 00:00:00 2001 From: amaify2 Date: Wed, 24 Jun 2026 09:38:16 +0100 Subject: [PATCH 05/14] [CI] - fix Playwright browser installation command --- .github/workflows/chainwright.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/chainwright.yaml b/.github/workflows/chainwright.yaml index 5dd1277..99186ba 100644 --- a/.github/workflows/chainwright.yaml +++ b/.github/workflows/chainwright.yaml @@ -73,7 +73,7 @@ jobs: run: sudo apt-get install -y xvfb - name: Install Playwright browsers - run: pnpx playwright install chromium + run: pnpm exec playwright install chromium - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 From 5cf536923611a185d9965844b54a0c7927286e53 Mon Sep 17 00:00:00 2001 From: amaify2 Date: Wed, 24 Jun 2026 10:42:58 +0100 Subject: [PATCH 06/14] [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 07/14] [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 08/14] [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 09/14] [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 10/14] 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. From 9393d358b955967236cef73ee930193b5a18daf9 Mon Sep 17 00:00:00 2001 From: Ugwuanyi TobeChukwu <39131739+amaify@users.noreply.github.com> Date: Wed, 24 Jun 2026 14:29:30 +0100 Subject: [PATCH 11/14] [README] - Update the README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 840a8ff..fb9a21b 100644 --- a/README.md +++ b/README.md @@ -192,7 +192,7 @@ These are Chainwright's wallet extensions and their versions: - **Phantom**: v26.10.0 - **Solflare**: v2.19.1 - **Meteor**: v0.7.0 - - **Keplr**: v0.13.3 + - **Keplr**: v0.13.39 Example: From 86c77fefc22d59ab7f427e6cdc30a1d65737aa79 Mon Sep 17 00:00:00 2001 From: Ugwuanyi TobeChukwu <39131739+amaify@users.noreply.github.com> Date: Wed, 24 Jun 2026 14:56:41 +0100 Subject: [PATCH 12/14] [Core] - Verify file integrity for local files --- src/utils/prepare-wallet-extension.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/utils/prepare-wallet-extension.ts b/src/utils/prepare-wallet-extension.ts index 33a56cd..537e145 100644 --- a/src/utils/prepare-wallet-extension.ts +++ b/src/utils/prepare-wallet-extension.ts @@ -63,11 +63,6 @@ export async function prepareWalletExtension({ downloadUrl, name, force, extensi styleText("cyanBright", `📥 Downloading ${walletName} extension...`, { validateStream: false }), ); await downloadFile({ url: urlSource, destination: zipFilePath }); - await verifyFileIntegrity({ - filePath: zipFilePath, - expectedSha256, - label: `${walletName} extension`, - }); console.info( styleText("green", `✅ ${name.toUpperCase()} Extension downloaded successfully.`, { validateStream: false, @@ -84,8 +79,15 @@ export async function prepareWalletExtension({ downloadUrl, name, force, extensi // Unzip the archive if not already extracted if (!fs.existsSync(outputPath)) { + const _filePath = !localPath ? zipFilePath : localPath; + console.info(`🚨 Verifying file integrity...`); + await verifyFileIntegrity({ + filePath: _filePath, + expectedSha256, + label: `${walletName} extension`, + }); console.info(`📦 Extracting extension...`); - const zip = new AdmZip(!localPath ? zipFilePath : localPath); + const zip = new AdmZip(_filePath); zip.extractAllTo(outputPath, true); console.info(`✅ ${walletName} Extension extracted successfully.`); } else { From ae8f1e0c453645af14f868545f82aa8877b6589f Mon Sep 17 00:00:00 2001 From: Ugwuanyi TobeChukwu <39131739+amaify@users.noreply.github.com> Date: Wed, 24 Jun 2026 15:31:40 +0100 Subject: [PATCH 13/14] [CI] - Use the latest "actions/upload-artifact" version. --- .github/workflows/chainwright.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/chainwright.yaml b/.github/workflows/chainwright.yaml index 80844d5..80d274c 100644 --- a/.github/workflows/chainwright.yaml +++ b/.github/workflows/chainwright.yaml @@ -100,7 +100,7 @@ jobs: - name: Upload Playwright artifacts if: ${{ !cancelled() }} - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: playwright-test-results path: | From 15b57c68eec11b09497f54e7d3091b3e6b75e7fb Mon Sep 17 00:00:00 2001 From: Ugwuanyi TobeChukwu <39131739+amaify@users.noreply.github.com> Date: Wed, 24 Jun 2026 15:47:28 +0100 Subject: [PATCH 14/14] [Release] - Release v0.10.1 --- .github/workflows/changeset-report.yaml | 32 +++++++++++++++++++++++++ CHANGELOG.md | 6 +++++ package.json | 2 +- 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/changeset-report.yaml diff --git a/.github/workflows/changeset-report.yaml b/.github/workflows/changeset-report.yaml new file mode 100644 index 0000000..02f8feb --- /dev/null +++ b/.github/workflows/changeset-report.yaml @@ -0,0 +1,32 @@ +name: Changeset report + +on: + push: + branches: [dev] + +jobs: + changeset-status: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - uses: pnpm/action-setup@v5 + with: + version: 10 + + - uses: actions/setup-node@v6 + with: + node-version: 24.x + cache: pnpm + + - run: pnpm install --frozen-lockfile + + - name: Report pending release changes + run: pnpm changeset status --output changeset-status.json + + - uses: actions/upload-artifact@v7 + with: + name: changeset-status + path: changeset-status.json \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 202e2e6..23a25c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # @tobelabs/chainwright +## 0.10.1 + +### Patch Changes + +- Update READEME.md and fix flakiness in Metamask when onboarding a user + ## 0.10.0 ### Minor Changes diff --git a/package.json b/package.json index cc28ba1..be39735 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chainwright", - "version": "0.10.0", + "version": "0.10.1", "description": "Playwright Web3 wallet testing framework for end-to-end dApp automation with MetaMask, Phantom, Solflare, Petra, Meteor, and Keplr", "type": "module", "license": "MIT",