chainwright 0.8.10 → 0.8.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- import { W as WalletProfileFixtureArgs, c as WorkerScopeFixtureArgs } from '../../types-B56pinWs.js';
2
- import { W as WorkerScopeFixture } from '../../worker-scope-context-DiN3_Sig.js';
3
- export { w as workerScopeContext } from '../../worker-scope-context-DiN3_Sig.js';
1
+ import { W as WalletProfileFixtureArgs } from '../../types-DK8rutb5.js';
2
+ import { W as WorkerScopeFixture } from '../../worker-scope-context-CNAfiliw.js';
3
+ export { w as workerScopeContext } from '../../worker-scope-context-CNAfiliw.js';
4
4
  import * as _playwright_test from '@playwright/test';
5
5
  import { Page, BrowserContext } from '@playwright/test';
6
6
  import z from 'zod';
@@ -433,6 +433,6 @@ declare class Metamask extends MetamaskProfile {
433
433
 
434
434
  declare const metamaskFixture: ({ slowMo, profileName }?: WalletProfileFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & MetamaskFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
435
435
 
436
- declare const metamaskWorkerScopeFixture: ({ profileName, dappUrl, slowMo }?: WorkerScopeFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & MetamaskFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerScopeFixture<Metamask>>;
436
+ declare const metamaskWorkerScopeFixture: ({ profileName, slowMo }?: WalletProfileFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & MetamaskFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerScopeFixture<Metamask>>;
437
437
 
438
- export { type AddAccountArgs, type AddCustomNetwork, type AnvilNodeInstance, type AnvilNodeOptions, type CreateAnvilNodeResult, type GasFeeSettings, type GetAccountAddressChains, Metamask, type MetamaskFixture, type OnboardingArgs, type SwitchNetwork, WalletProfileFixtureArgs, WorkerScopeFixture, WorkerScopeFixtureArgs, addCustomNetworkSchema, metamaskFixture, metamaskWorkerScopeFixture };
438
+ export { type AddAccountArgs, type AddCustomNetwork, type AnvilNodeInstance, type AnvilNodeOptions, type CreateAnvilNodeResult, type GasFeeSettings, type GetAccountAddressChains, Metamask, type MetamaskFixture, type OnboardingArgs, type SwitchNetwork, WalletProfileFixtureArgs, WorkerScopeFixture, addCustomNetworkSchema, metamaskFixture, metamaskWorkerScopeFixture };
@@ -1,3 +1,3 @@
1
- import dt from"fs";import Vt from"path";import{chromium as Ut}from"@playwright/test";import Wt from"path";var st=".wallet-cache",ct=".wallet-context";var it="13.22.0",U="https://github.com/amaify/chainwright/releases/download/v0.1.0/",we=`https://github.com/MetaMask/metamask-extension/releases/download/v${it}/metamask-chrome-${it}.zip`,fe=`${U}solflare-wallet-extension-v2.19.1.zip`,ge=`${U}petra-wallet-extension-v2.4.8.zip`,ye=`${U}phantom-wallet-extension-v26.10.0.zip`,he=`${U}meteor-wallet-extension-v0.7.0.zip`,xe=`${U}keplr-wallet-extension-v0.13.3.zip`;async function R(t){return Wt.resolve(process.cwd(),ct,t)}import Lt from"path";function h(t){return Lt.resolve(process.cwd(),st,t)}import lt from"fs";import Dt from"path";async function _(t){try{let e=h(t),o=Dt.resolve(e,"extension-path.txt");if(!lt.existsSync(o))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let n=lt.readFileSync(o,"utf-8").trim();if(!n)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return n}catch(e){throw new Error(`\u274C Failed to get ${t} extension path: ${e.message}`)}}async function Oe({wallet:t,workerInfo:e,profileName:o,slowMo:n}){let a=await R(e.workerIndex.toString()),r=h(t.name),i=Vt.resolve(r,o??"wallet-data");if(!dt.existsSync(i))throw new Error(`Cache for ${t.name} does not exist. Create it first!`);dt.cpSync(i,a,{recursive:!0,force:!0});let c=await _(t.name),s=await Ut.launchPersistentContext(a,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:n}),u=await t.indexUrl(),l=s.pages()[0];return l||(l=await s.newPage()),await l.goto(u),{context:s,walletPage:l,contextPath:a}}import{expect as x}from"@playwright/test";import ut from"zod";import{test as Ot}from"@playwright/test";function mt(t,e){t&&(console.warn(`
2
- \u26A0\uFE0F Skipping test: ${e}`),Ot.skip())}var w={buyButton:"eth-overview-buy",swapButton:"eth-overview-swap",sendButton:"eth-overview-send",receiveButton:"eth-overview-receive",openSettingsButton:"account-options-menu-button",accountMenuButton:"account-menu-icon",accountCell:"multichain-account-cell-entropy",openNetworkSelectorButton:"sort-by-networks",accountAddressesButton:"networks-subtitle-test-id",accountAddressesElements:"multichain-address-row",accountAddressQRCode:"multichain-address-row-qr-button"},M={lockButton:"global-menu-lock",networksButton:"global-menu-networks"},O={passwordInput:"unlock-password",unlockButton:"unlock-submit"},P={accountOptionsMenuButton:"multichain-account-cell-end-accessory",accountDetailsLabel:"Account details",renameAccountLabel:"Rename",addressesLabel:"Addresses",pinToTopLabel:"Pin to top",hideAccountLabel:"Hide account",backButton:"back",addMultichainAccountButton:"add-multichain-account-button",addWalletButton:"account-list-add-wallet-button",importWalletButton:"add-wallet-modal-import-wallet",importAccountButton:"add-wallet-modal-import-account"};var g={createWalletButton:"onboarding-create-wallet",importWalletButton:"onboarding-import-wallet",useSecretRecoveryPhraseButton:"onboarding-create-with-srp-button",createNewPasswordInput:"create-password-new-input",confirmNewPasswordInput:"create-password-confirm-input",confirmPasswordCheckbox:"create-password-terms",createPasswordButton:"create-password-submit",revealSecretRecoveryPhraseButton:"recovery-phrase-reveal",recoveryPhraseRemindMeLaterButton:"recovery-phrase-remind-later",metamaskMetricsIAgreeButton:"metametrics-i-agree",onboardingDoneButton:"onboarding-complete-done",importUsingSecretRecoveryPhraseButton:"onboarding-import-with-srp-button",secretRecoveryPhraseTextAreaInput:"srp-input-import__srp-note",importWalletConfirmButton:"import-srp-confirm",importAccountConfirmButton:"import-account-confirm-button",importSRPError:"bannerAlert"};async function pt({page:t,privateKey:e,accountName:o}){let n=ut.string().min(1,"Account name cannot be an empty string").trim().parse(o),a=ut.string().min(1,"Private key cannot be an empty string").trim().parse(e),r=t.getByTestId(w.accountMenuButton);await x(r).toBeVisible({timeout:3e4}),await r.click(),await x(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let i=t.getByTestId(P.addWalletButton),c=await i.textContent();c?.includes("Syncing")&&await x.poll(async()=>(await i.textContent())?.trim()??"",{timeout:12e4}).not.toBe(c),await x(i).toBeEnabled({timeout:6e4}),await i.click();let s=t.getByRole("dialog");await x(s).toContainText(/add wallet/i),await t.getByTestId(P.importAccountButton).click(),await t.locator("input[id='private-key-box']").fill(a);let p=t.getByTestId(g.importAccountConfirmButton);await x(p).toBeEnabled(),await p.click();let f=t.getByTestId(g.importSRPError),B=await f.isVisible().catch(()=>!1);B&&mt(B,`${(await f.textContent())?.split(".")[0]}`);let S=t.locator("div:has(> div[data-testid^='multichain-account-cell-keyring'][class*='mm-box--background-color-background-muted'])"),A=(await S.textContent())?.split("$")[0];A&&await $t({page:t,accountName:n,activeAccountLocator:S,activeAccountName:A}),await t.locator("button[aria-label='Back']").first().click()}async function $t({page:t,accountName:e,activeAccountLocator:o,activeAccountName:n}){let a=o.locator(`div[aria-label='${n} options']`);await x(a).toBeVisible(),await a.click(),await x(t.getByRole("tooltip")).toBeVisible();let r=t.locator(`div[aria-label='${P.renameAccountLabel}']`);await x(r).toBeVisible(),await r.click();let i=t.getByRole("dialog"),c=i.getByRole("heading",{name:/rename/i});await x(c).toBeVisible();let s=i.getByRole("textbox");await x(s).toBeVisible(),await s.fill(e);let u=i.getByRole("button",{name:/confirm/i});await x(u).toBeEnabled(),await u.click(),await i.waitFor({state:"detached",timeout:2e4});let l=t.locator("div:has(> div[data-testid^='multichain-account-cell-keyring'][class*='mm-box--background-color-background-muted'])");await x(l).toContainText(e)}import{expect as $}from"@playwright/test";import W from"zod";var wt=W.object({networkName:W.string().min(1,"Network name cannot be an empty string"),rpcUrl:W.url(),chainId:W.number().or(W.string().includes("0x")),currencySymbol:W.string().toUpperCase().min(1,"Currency symbol cannot be an empty string")});import{expect as Ht}from"@playwright/test";async function j(t){let e=t.locator("div:has(> p[data-testid='notifications-tag-counter__unread-dot'])"),o=t.getByTestId(w.openSettingsButton);await e.isVisible().catch(()=>!1)?await e.click():(await Ht(o).toBeVisible(),await o.click())}async function ft({page:t,...e}){let{chainId:o,currencySymbol:n,networkName:a,rpcUrl:r}=wt.parse({...e},{reportInput:!0});await j(t),await t.getByTestId(M.networksButton).click();let c=t.locator("section[role='dialog']");await $(c).toContainText(/manage networks/i),await t.getByRole("button",{name:/add a custom network/i}).click(),await $(c).toContainText(/Add a custom network/i);let u=t.getByTestId("network-form-network-name"),l=t.getByTestId("test-add-rpc-drop-down"),p=t.getByTestId("network-form-chain-id"),f=t.getByTestId("network-form-ticker-input");await u.fill(a),await l.click(),await t.getByRole("tooltip").locator("div:has(> button:has-text('Add RPC URL'))").click(),await $(c).toContainText(/Add RPC URL/i);let A=t.getByTestId("rpc-url-input-test"),k=t.getByRole("button",{name:/Add URL/i});await A.fill(r),await k.click(),await $(c).toContainText(/Add a custom network/i);let y=t.getByTestId("network-form-chain-id-error");if(await y.isVisible().catch(()=>!1)){let T=await y.textContent();throw Error(`RPC error: ${T}`)}await p.fill(`${o}`),await f.fill(n);let I=t.getByRole("button",{name:/save/i});await $(I).toBeEnabled(),await I.click()}import{expect as gt}from"@playwright/test";function v(t){return new Promise(e=>setTimeout(e,t))}var q={confirmButton:"confirm-footer-button",cancelButton:"confirm-footer-cancel-button"};async function yt(t,e){let o=t.getByTestId(q.confirmButton);await v(2e3);let a=(await o.textContent())?.includes("Review alert"),r=await o.isDisabled().catch(()=>!1);if(a&&r){await t.getByTestId("edit-gas-fees-row").locator("> div").first().click();let l=t.getByRole("dialog");await gt(l).toBeVisible();let p=l.locator("h4",{hasText:"Insufficient funds"}),f=await l.getByTestId("alert-modal__selected-alert").textContent();if(await p.isVisible().catch(()=>!1))throw Error(`${f}`)}if(e){let s=t.getByTestId("edit-gas-fee-icon");if(await s.scrollIntoViewIfNeeded(),await s.click(),e.feeType!=="advanced"&&await t.getByTestId(`gas-option-${e.feeType}`).click(),e.feeType==="advanced"){await t.getByTestId("gas-option-advanced").click();let l=t.getByRole("textbox",{name:"Max base fee"}),p=t.getByRole("textbox",{name:"Priority fee"}),f=t.getByRole("button",{name:"Save",exact:!0});await l.fill(e.maxBaseFee),await p.fill(e.priorityFee),await f.click()}}await gt(o).toBeEnabled(),await o.click();let i=t.getByRole("dialog");await i.isVisible().catch(()=>!1)&&await i.locator("h4",{hasText:"Your assets may be at risk"}).isVisible().catch(()=>!1)&&(await i.getByTestId("alert-modal-acknowledge-checkbox").click(),await i.getByTestId("confirm-alert-modal-submit-button").click()),await t.waitForEvent("close",{timeout:15e3})}import{expect as Gt}from"@playwright/test";import{expect as Y}from"@playwright/test";async function L({page:t,accountName:e}){let o=t.getByTestId(w.accountMenuButton);if(await o.textContent()===e){console.info(`Can't switch account to "${e}", it is already selected.`);return}await Y(o).toBeVisible({timeout:15e3}),await o.click(),await Y(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let a=t.getByTestId(P.addMultichainAccountButton),r=await a.textContent();r?.includes("Syncing")&&await Y.poll(async()=>(await a.textContent())?.trim()??"",{timeout:6e4}).not.toBe(r);let i=await t.getByTestId(/^multichain-account-cell-(?:entropy|keyring):/).all(),c=null;for(let s of i)if(await s.scrollIntoViewIfNeeded(),(await s.textContent())?.includes(e)){c=s;break}if(!c)throw Error(`Account with name "${e}" not found.`);await c?.click()}async function ht(t,e){e&&await L({page:t,accountName:e});let o=t.getByRole("button",{name:"Connect",exact:!0});await o.waitFor({state:"visible",timeout:25e3}),await o.click(),await t.getByRole("heading",{name:"Connecting",exact:!0}).waitFor({state:"detached",timeout:3e4});let a;await Gt.poll(async()=>(a=await t.locator("div[class='permissions-connect']").isVisible().catch(()=>!1),a),{timeout:25e3}).toBe(!0).catch(()=>console.error("Notice dialog did not appear within the timeout period."));let r=t.getByTestId("page-container-footer-next");await r.waitFor({state:"visible",timeout:25e3}),await r.click(),await t.waitForEvent("close",{predicate:()=>!0,timeout:25e3}).catch(()=>console.error("Extension popup did not close within the timeout period when connecting to the DApp."))}async function xt(t,e){return await t.getByTestId(w.accountAddressesButton).hover(),await t.getByTestId("multichain-address-rows-list").getByRole("button",{name:/view all/i}).click(),await t.getByRole("searchbox",{name:/search networks/i}).fill(e),await t.locator(`div[data-testid='${w.accountAddressesElements}']:has-text('${e}')`).getByTestId(w.accountAddressQRCode).click(),await t.getByRole("dialog").locator("div > p[data-testid='account-address']").textContent()}import{expect as qt}from"@playwright/test";import{errors as zt}from"@playwright/test";async function E(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}var Bt={loadingOverlay:"loading-overlay",loadingSpinner:"spinner loading-overlay__spinner"};var Kt=6e4,jt=async(t,e,o)=>{await E(e);try{await e.locator(`div[class="${t}"]`).waitFor({state:"detached",timeout:o})}catch(n){if(n instanceof zt.TimeoutError)console.info(`Loading indicator '${t}' not found - continuing.`);else throw console.error(`Error while waiting for loading indicator '${t}' to disappear`),n}},X=async t=>{try{await jt(Bt.loadingSpinner,t,Kt)}catch(e){console.warn("Warning during MetaMask load:",e)}return await v(300),t};async function kt(t){if(await t.getByTestId(O.unlockButton).isVisible().catch(()=>!1)){console.info("\u{1F4A1} Wallet is already locked");return}await j(t);let n=t.getByTestId(M.lockButton);await qt(n).toBeVisible(),await n.click(),await X(t)}import{styleText as Pt}from"util";import{expect as V}from"@playwright/test";import bt from"fs";import Xt from"path";async function Q(t){let e=h(t),o=Xt.resolve(e,"password.txt");try{if(!bt.existsSync(o))throw new Error("\u274C password.txt not found. Run setup script first.");return bt.readFileSync(o,"utf-8")}catch(n){throw new Error(`\u274C Failed to get ${t} password from cache: ${n.message}`)}}import{expect as Qt}from"@playwright/test";async function At({context:t,path:e,locator:o}){let n;try{await Qt.poll(async()=>(n=t.pages().filter(a=>a.url().startsWith("chrome-extension://")).find(a=>a.url().match(e)),!!n),{timeout:3e4}).toBe(!0)}catch{let a=t.pages().filter(r=>r.url().startsWith("chrome-extension://")).map(r=>r.url());throw new Error(`Popup page with path "${e}" not found in context after 30s. Pages in context: ${JSON.stringify(a)}`)}if(!n)throw new Error(`Popup page with path ${e} not found in context.`);return await Jt(n,o),await n.setViewportSize({width:360,height:592}),n}async function Jt(t,e){await t.waitForLoadState("load",{timeout:4e4}),await t.waitForLoadState("domcontentloaded",{timeout:4e4}),await t.locator(e).first().waitFor({state:"attached",timeout:4e4})}import Ct from"fs";import Yt from"path";async function Tt(t){let e=h(t),o=Yt.resolve(e,"extension-id.txt");try{if(!Ct.existsSync(o))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return Ct.readFileSync(o,"utf-8")}catch(n){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${n.message}`)}}var C=class{name="metamask";onboardingPath="/home.html#onboarding";async indexUrl(){return`chrome-extension://${await this.extensionId()}/home.html`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/notification.html`}async extensionId(){return await Tt(this.name)}async promptPage(e){let o=await this.promptUrl();return await At({context:e,path:o,locator:"div[data-testid='multichain-page']"})}};import{expect as Z}from"@playwright/test";async function D({page:t}){await t.locator(`div:has(> button[data-testid='${w.openSettingsButton}'])`).click(),await t.getByTestId(M.networksButton).click();let n=t.locator("section[role='dialog']");await Z(n).toBeVisible(),await Z(n).toContainText(/manage networks/i);let a="div:has(> p:has-text('Show test networks'))";await n.locator(a).scrollIntoViewIfNeeded();let r=n.locator(a);if(!await r.locator("label[class='toggle-button toggle-button--off']").isVisible().catch(()=>!1)){await n.getByRole("button",{name:/close/i}).click(),console.info("Testnet networks are already visible.");return}await r.locator("label[class='toggle-button toggle-button--off']").click(),await t.getByTestId("Sepolia").scrollIntoViewIfNeeded(),await Z(t.getByTestId("Sepolia")).toBeVisible(),await n.getByRole("button",{name:/close/i}).click()}async function tt({page:t,mainAccountName:e,...o}){console.info(Pt("yellowBright",`
3
- \u{1F98A} MetaMask onboarding started...`,{validateStream:!1}));let n=await Q("metamask"),a=new C,r=t.locator("img[class='loading-spinner']"),i=t.getByTestId(g.createWalletButton),c=t.getByTestId(g.importWalletButton),s=t.getByTestId(g.createNewPasswordInput),u=t.getByTestId(g.confirmNewPasswordInput),l=t.getByTestId(g.confirmPasswordCheckbox),p=t.getByTestId(g.createPasswordButton),f=t.getByTestId(g.metamaskMetricsIAgreeButton),B=t.getByTestId(g.onboardingDoneButton);if(await r.waitFor({state:"detached",timeout:3e4}),o.mode==="create"){let I=t.getByTestId(g.useSecretRecoveryPhraseButton);await i.click(),await I.click(),await s.fill(n),await u.fill(n),await l.click(),await p.click(),await t.getByTestId(g.revealSecretRecoveryPhraseButton).click(),await t.getByTestId(g.recoveryPhraseRemindMeLaterButton).click(),await f.click()}if(o.mode==="import"){let{secretRecoveryPhrase:I}=o,T=I.split(" "),z=t.getByTestId(g.importUsingSecretRecoveryPhraseButton);await c.click(),await z.click();let at=t.getByTestId(g.secretRecoveryPhraseTextAreaInput);await at.fill(T[0]),await at.press("Space");for(let K=1;K<T.length;K++){let rt=t.getByTestId(`import-srp__srp-word-${K}`);await rt.fill(T[K]),await rt.press("Space")}await t.getByTestId(g.importWalletConfirmButton).click(),await s.fill(n),await u.fill(n),await l.click(),await p.click(),await f.click();let Mt=t.getByTestId("wallet-ready");await V(Mt).toContainText(/your wallet is ready/i)}await B.click();let A=`chrome-extension://${await a.extensionId()}/sidepanel.html`,y=await t.context().browser()?.newBrowserCDPSession(),F;await V.poll(async()=>{if(y){let{targetInfos:I}=await y.send("Target.getTargets"),T=I.find(z=>z.url===A);return F=T,!!T}},{timeout:15e3}).toBe(!0),F&&await y?.send("Target.closeTarget",{targetId:F.targetId}),await t.goto(await a.indexUrl()),await r.waitFor({state:"detached",timeout:3e4}),await V(t.getByTestId(w.buyButton)).toBeVisible(),await V(t.getByTestId(w.swapButton)).toBeVisible(),await V(t.getByTestId(w.sendButton)).toBeVisible(),await V(t.getByTestId(w.receiveButton)).toBeVisible(),await D({page:t}),e&&await L({page:t,accountName:e}),await v(5e3),console.info(Pt("greenBright","\u2728 MetaMask onboarding completed successfully",{validateStream:!1}))}import{expect as Zt}from"@playwright/test";async function St(t){let e=t.getByTestId(q.cancelButton);await v(1e3),await Zt(e).toBeEnabled(),await e.click()}import{expect as b}from"@playwright/test";async function It({page:t,currentAccountName:e,newAccountName:o}){let n=t.getByTestId(w.accountMenuButton);if(await n.textContent()===o)throw Error(`The account to be renamed "${o}" already exists.`);await b(n).toBeVisible({timeout:15e3}),await n.click(),await b(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let r=t.getByTestId(P.addMultichainAccountButton),i=await r.textContent();i?.includes("Syncing")&&await b.poll(async()=>(await r.textContent())?.trim()??"",{timeout:6e4}).not.toBe(i);let c=await t.getByTestId(/^multichain-account-cell/).all(),s=null;for(let y of c)if((await y.textContent())?.includes(e)){s=y;break}if(!s)throw Error(`Account with name "${e}" not found.`);if((await s.textContent())?.split("$")[0]===o)throw Error(`The new account name "${o}" is the same as the old account name "${e}".`);let l=t.locator(`div[aria-label='${e} options']`);await b(l).toBeVisible(),await l.click(),await b(t.getByRole("tooltip")).toBeVisible();let p=t.locator(`div[aria-label='${P.renameAccountLabel}']`);await b(p).toBeVisible(),await p.click();let f=t.getByRole("dialog"),B=f.getByRole("heading",{name:/rename/i});await b(B).toBeVisible();let S=f.getByRole("textbox");await b(S).toBeVisible(),await S.fill(o);let A=f.getByRole("button",{name:/confirm/i});await b(A).toBeEnabled(),await A.click();for(let y of c)if((await y.textContent())?.includes(o)){await b(y).toBeVisible(),await b(y).toContainText(o);break}await t.locator("button[aria-label='Back']").first().click()}import{expect as et}from"@playwright/test";async function vt({page:t,networkType:e,chainName:o}){let n=t.getByTestId(w.openNetworkSelectorButton);await n.click();let a=t.getByTestId("modal-header-close-button");if(e==="testnet"||e==="custom"){let s=t.getByRole("tab",{name:"Custom"});await s.click(),await t.locator("p:has-text('Testnets')").isVisible().catch(()=>!1)||(await a.click(),await D({page:t}),await n.click(),await s.click());let p=t.locator(`div div[data-testid='${o}']`),f=await p.textContent();et(f).toBe(o),await p.click();return}await t.getByRole("tab",{name:"Popular"}).click();let i=t.locator(`div div[data-testid='${o}']`),c=await i.textContent();et(c).toBe(o),await i.click(),await et(n).toContainText(o,{timeout:3e4})}import{expect as Rt}from"@playwright/test";async function H(t){let e=await Q("metamask"),o=t.getByTestId(O.passwordInput);if(await t.getByTestId(w.openNetworkSelectorButton).isVisible().catch(()=>!1)){console.info("\u{1F4A1} Wallet is already unlocked");return}await o.fill(e);let r=t.getByTestId(O.unlockButton);await Rt(r).toBeVisible(),await r.click(),await X(t),await Rt(t.getByTestId(w.buyButton)).toBeVisible({timeout:3e4})}var N=class extends C{page;constructor(e){super(),this.page=e}async onboard(e){await tt({page:this.page,...e})}async unlock(){await H(this.page)}async lock(){await kt(this.page)}async renameAccount({newAccountName:e,currentAccountName:o}){await It({page:this.page,newAccountName:e,currentAccountName:o})}async addAccount({privateKey:e,accountName:o}){await pt({page:this.page,privateKey:e,accountName:o})}async switchAccount({accountName:e}){await L({page:this.page,accountName:e})}async switchNetwork({...e}){await vt({page:this.page,...e})}async getAccountAddress(e){return await xt(this.page,e)}async toggleShowTestnetNetwork(){await D({page:this.page})}async addCustomNetwork({chainId:e,currencySymbol:o,networkName:n,rpcUrl:a}){await ft({page:this.page,chainId:e,currencySymbol:o,networkName:n,rpcUrl:a})}async connectToApp(e){await ht(await this.promptPage(this.page.context()),e)}async confirmTransaction(e){await yt(await this.promptPage(this.page.context()),e)}async rejectTransaction(){await St(await this.promptPage(this.page.context()))}};import Nt from"fs";import ne from"path";import{test as ae,chromium as re}from"@playwright/test";import{Instance as ie,Pool as se}from"prool";import{expect as te}from"@playwright/test";async function ot(t,e){let o=await t.newPage();return await te(async()=>{await o.goto(e),await E(o)}).toPass(),o}async function nt(t,e){let o=await e.newPage();for(let{origin:n,localStorage:a}of t){let r=o.mainFrame();await r.goto(n),await r.evaluate(i=>{i.forEach(({name:c,value:s})=>{window.localStorage.setItem(c,s)})},a)}await o.close()}import ee from"fs/promises";async function Et(t){await ee.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var oe=35e3;async function J(t,e){try{await Promise.race([t.close(),new Promise((o,n)=>setTimeout(()=>n(new Error("Context close timed out")),oe))])}catch(o){console.warn(`Browser context close did not complete cleanly: ${o.message}`)}try{await Et(e)}catch(o){console.error(`Failed to remove temporary context directory at ${e}. Error:`,o)}}var G,Ua=({slowMo:t=0,profileName:e}={})=>ae.extend({contextPath:async({browserName:o},n,a)=>{let r=await R(`${o}-${a.testId}`);await n(r)},context:async({context:o,contextPath:n},a)=>{let r=new C,i=h(r.name),c=await _(r.name),s=ne.resolve(i,e??"wallet-data");if(!Nt.existsSync(s))throw new Error("\u274C Cache for MetaMask wallet data not found. Create it first");Nt.cpSync(s,n,{recursive:!0,force:!0});let u=[`--disable-extensions-except=${c}`,`--load-extension=${c}`];process.env.HEADLESS&&(u.push("--headless=new"),t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!"));let l=await re.launchPersistentContext(n,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:t}),{cookies:p,origins:f}=await o.storageState();p&&await l.addCookies(p),f&&f.length>0&&nt(f,l);let B=await r.indexUrl();await l.waitForEvent("page",{predicate:k=>k.url().startsWith(B),timeout:3e4}),G=l.pages().find(k=>k.url().startsWith(B))??await ot(l,B);for(let k of l.pages())k.url().includes("about:blank")&&await k.close();await G.locator("img[class='loading-spinner']").waitFor({state:"detached"}),await H(G),await a(l),await J(l,n)},metamaskPage:async({context:o},n)=>{await n(G)},metamask:async({context:o},n)=>{let a=new N(G);await n(a)},createAnvilNode:async({context:o},n,a)=>{let r=a.workerIndex,i;await n(async c=>{i=se.define({instance:ie.anvil(c)});let s=await i.start(r),u=`http://${s.host}:${s.port}`,p=c?.chainId??31337;return{rpcUrl:u,anvil:s,chainId:p}}),i&&await i.stop(r)},connectToAnvil:async({context:o,metamask:n,createAnvilNode:a},r)=>{await r(async()=>{let{chainId:i,rpcUrl:c}=await a({chainId:2251});await n.addCustomNetwork({chainId:i,currencySymbol:"ETH",networkName:"Anvil Localnet",rpcUrl:c})})}});import{test as de}from"@playwright/test";import{Instance as me,Pool as ue}from"prool";import Ft from"fs";import ce from"path";import{chromium as le}from"@playwright/test";async function _t({workerInfo:t,profileName:e,slowMo:o}){let n=new C,a=await R(t.workerIndex.toString()),r=h(n.name),i=ce.resolve(r,e??"wallet-data");if(!Ft.existsSync(i))throw new Error(`Cache for ${n.name} does not exist. Create it first!`);Ft.cpSync(i,a,{recursive:!0,force:!0});let c=await _(n.name),s=await le.launchPersistentContext(a,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:o}),u=await n.indexUrl();await s.waitForEvent("page",{predicate:p=>p.url().startsWith(u),timeout:4e4});let l=s.pages().find(p=>p.url().startsWith(u));l||(l=await s.newPage(),await l.goto(u),await E(l));for(let p of s.pages())p.url().includes("about:blank")&&await p.close();return{context:s,walletPage:l,contextPath:a}}var ar=({profileName:t,dappUrl:e,slowMo:o}={})=>de.extend({workerScopeContents:[async({browser:n},a,r)=>{let{context:i,contextPath:c,walletPage:s}=await _t({workerInfo:r,profileName:t,slowMo:o});await i.grantPermissions(["clipboard-read"]);let u=new N(s);await u.unlock(),await a({wallet:u,walletPage:s,context:i}),await J(i,c)},{scope:"worker"}],dappPage:[async({workerScopeContents:n},a)=>{let{context:r}=n,i=await r.newPage();e&&await i.goto(e),await a(i)},{scope:"worker"}],metamaskPage:async({workerScopeContents:n},a)=>{await a(n.walletPage)},metamask:async({workerScopeContents:n},a)=>{let r=new N(n.walletPage);await a(r)},createAnvilNode:async({context:n},a,r)=>{let i=r.workerIndex,c;await a(async s=>{c=ue.define({instance:me.anvil(s)});let u=await c.start(i),l=`http://${u.host}:${u.port}`,f=s?.chainId??31337;return{rpcUrl:l,anvil:u,chainId:f}}),c&&await c.stop(i)},connectToAnvil:async({context:n,metamask:a,createAnvilNode:r},i)=>{await i(async()=>{let{chainId:c,rpcUrl:s}=await r({chainId:2251});await a.addCustomNetwork({chainId:c,currencySymbol:"ETH",networkName:"Anvil Localnet",rpcUrl:s})})}});export{N as Metamask,Ua as metamaskFixture,ar as metamaskWorkerScopeFixture,Oe as workerScopeContext};
1
+ import dt from"fs";import Vt from"path";import{chromium as Ut}from"@playwright/test";import Wt from"path";var st=".wallet-cache",ct=".wallet-context";var it="13.22.0",U="https://github.com/amaify/chainwright/releases/download/v0.1.0/",we=`https://github.com/MetaMask/metamask-extension/releases/download/v${it}/metamask-chrome-${it}.zip`,fe=`${U}solflare-wallet-extension-v2.19.1.zip`,ge=`${U}petra-wallet-extension-v2.4.8.zip`,ye=`${U}phantom-wallet-extension-v26.10.0.zip`,he=`${U}meteor-wallet-extension-v0.7.0.zip`,xe=`${U}keplr-wallet-extension-v0.13.3.zip`;async function R(t){return Wt.resolve(process.cwd(),ct,t)}import Lt from"path";function h(t){return Lt.resolve(process.cwd(),st,t)}import lt from"fs";import Dt from"path";async function F(t){try{let e=h(t),o=Dt.resolve(e,"extension-path.txt");if(!lt.existsSync(o))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let n=lt.readFileSync(o,"utf-8").trim();if(!n)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return n}catch(e){throw new Error(`\u274C Failed to get ${t} extension path: ${e.message}`)}}async function Oe({wallet:t,workerInfo:e,profileName:o,slowMo:n}){let r=await R(e.workerIndex.toString()),a=h(t.name),i=Vt.resolve(a,o??"wallet-data");if(!dt.existsSync(i))throw new Error(`Cache for ${t.name} does not exist. Create it first!`);dt.cpSync(i,r,{recursive:!0,force:!0});let c=await F(t.name),s=await Ut.launchPersistentContext(r,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:n}),p=await t.indexUrl(),l=s.pages()[0];return l||(l=await s.newPage()),await l.goto(p),{context:s,walletPage:l,contextPath:r}}import{expect as x}from"@playwright/test";import ut from"zod";import{test as Ot}from"@playwright/test";function mt(t,e){t&&(console.warn(`
2
+ \u26A0\uFE0F Skipping test: ${e}`),Ot.skip())}var w={buyButton:"eth-overview-buy",swapButton:"eth-overview-swap",sendButton:"eth-overview-send",receiveButton:"eth-overview-receive",openSettingsButton:"account-options-menu-button",accountMenuButton:"account-menu-icon",accountCell:"multichain-account-cell-entropy",openNetworkSelectorButton:"sort-by-networks",accountAddressesButton:"networks-subtitle-test-id",accountAddressesElements:"multichain-address-row",accountAddressQRCode:"multichain-address-row-qr-button"},_={lockButton:"global-menu-lock",networksButton:"global-menu-networks"},O={passwordInput:"unlock-password",unlockButton:"unlock-submit"},P={accountOptionsMenuButton:"multichain-account-cell-end-accessory",accountDetailsLabel:"Account details",renameAccountLabel:"Rename",addressesLabel:"Addresses",pinToTopLabel:"Pin to top",hideAccountLabel:"Hide account",backButton:"back",addMultichainAccountButton:"add-multichain-account-button",addWalletButton:"account-list-add-wallet-button",importWalletButton:"add-wallet-modal-import-wallet",importAccountButton:"add-wallet-modal-import-account"};var g={createWalletButton:"onboarding-create-wallet",importWalletButton:"onboarding-import-wallet",useSecretRecoveryPhraseButton:"onboarding-create-with-srp-button",createNewPasswordInput:"create-password-new-input",confirmNewPasswordInput:"create-password-confirm-input",confirmPasswordCheckbox:"create-password-terms",createPasswordButton:"create-password-submit",revealSecretRecoveryPhraseButton:"recovery-phrase-reveal",recoveryPhraseRemindMeLaterButton:"recovery-phrase-remind-later",metamaskMetricsIAgreeButton:"metametrics-i-agree",onboardingDoneButton:"onboarding-complete-done",importUsingSecretRecoveryPhraseButton:"onboarding-import-with-srp-button",secretRecoveryPhraseTextAreaInput:"srp-input-import__srp-note",importWalletConfirmButton:"import-srp-confirm",importAccountConfirmButton:"import-account-confirm-button",importSRPError:"bannerAlert"};async function pt({page:t,privateKey:e,accountName:o}){let n=ut.string().min(1,"Account name cannot be an empty string").trim().parse(o),r=ut.string().min(1,"Private key cannot be an empty string").trim().parse(e),a=t.getByTestId(w.accountMenuButton);await x(a).toBeVisible({timeout:3e4}),await a.click(),await x(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let i=t.getByTestId(P.addWalletButton),c=await i.textContent();c?.includes("Syncing")&&await x.poll(async()=>(await i.textContent())?.trim()??"",{timeout:12e4}).not.toBe(c),await x(i).toBeEnabled({timeout:6e4}),await i.click();let s=t.getByRole("dialog");await x(s).toContainText(/add wallet/i),await t.getByTestId(P.importAccountButton).click(),await t.locator("input[id='private-key-box']").fill(r);let u=t.getByTestId(g.importAccountConfirmButton);await x(u).toBeEnabled(),await u.click();let f=t.getByTestId(g.importSRPError),B=await f.isVisible().catch(()=>!1);B&&mt(B,`${(await f.textContent())?.split(".")[0]}`);let S=t.locator("div:has(> div[data-testid^='multichain-account-cell-keyring'][class*='mm-box--background-color-background-muted'])"),A=(await S.textContent())?.split("$")[0];A&&await $t({page:t,accountName:n,activeAccountLocator:S,activeAccountName:A}),await t.locator("button[aria-label='Back']").first().click()}async function $t({page:t,accountName:e,activeAccountLocator:o,activeAccountName:n}){let r=o.locator(`div[aria-label='${n} options']`);await x(r).toBeVisible(),await r.click(),await x(t.getByRole("tooltip")).toBeVisible();let a=t.locator(`div[aria-label='${P.renameAccountLabel}']`);await x(a).toBeVisible(),await a.click();let i=t.getByRole("dialog"),c=i.getByRole("heading",{name:/rename/i});await x(c).toBeVisible();let s=i.getByRole("textbox");await x(s).toBeVisible(),await s.fill(e);let p=i.getByRole("button",{name:/confirm/i});await x(p).toBeEnabled(),await p.click(),await i.waitFor({state:"detached",timeout:2e4});let l=t.locator("div:has(> div[data-testid^='multichain-account-cell-keyring'][class*='mm-box--background-color-background-muted'])");await x(l).toContainText(e)}import{expect as $}from"@playwright/test";import M from"zod";var wt=M.object({networkName:M.string().min(1,"Network name cannot be an empty string"),rpcUrl:M.url(),chainId:M.number().or(M.string().includes("0x")),currencySymbol:M.string().toUpperCase().min(1,"Currency symbol cannot be an empty string")});import{expect as Ht}from"@playwright/test";async function j(t){let e=t.locator("div:has(> p[data-testid='notifications-tag-counter__unread-dot'])"),o=t.getByTestId(w.openSettingsButton);await e.isVisible().catch(()=>!1)?await e.click():(await Ht(o).toBeVisible(),await o.click())}async function ft({page:t,...e}){let{chainId:o,currencySymbol:n,networkName:r,rpcUrl:a}=wt.parse({...e},{reportInput:!0});await j(t),await t.getByTestId(_.networksButton).click();let c=t.locator("section[role='dialog']");await $(c).toContainText(/manage networks/i),await t.getByRole("button",{name:/add a custom network/i}).click(),await $(c).toContainText(/Add a custom network/i);let p=t.getByTestId("network-form-network-name"),l=t.getByTestId("test-add-rpc-drop-down"),u=t.getByTestId("network-form-chain-id"),f=t.getByTestId("network-form-ticker-input");await p.fill(r),await l.click(),await t.getByRole("tooltip").locator("div:has(> button:has-text('Add RPC URL'))").click(),await $(c).toContainText(/Add RPC URL/i);let A=t.getByTestId("rpc-url-input-test"),k=t.getByRole("button",{name:/Add URL/i});await A.fill(a),await k.click(),await $(c).toContainText(/Add a custom network/i);let y=t.getByTestId("network-form-chain-id-error");if(await y.isVisible().catch(()=>!1)){let T=await y.textContent();throw Error(`RPC error: ${T}`)}await u.fill(`${o}`),await f.fill(n);let I=t.getByRole("button",{name:/save/i});await $(I).toBeEnabled(),await I.click()}import{expect as gt}from"@playwright/test";function v(t){return new Promise(e=>setTimeout(e,t))}var q={confirmButton:"confirm-footer-button",cancelButton:"confirm-footer-cancel-button"};async function yt(t,e){let o=t.getByTestId(q.confirmButton);await v(2e3);let r=(await o.textContent())?.includes("Review alert"),a=await o.isDisabled().catch(()=>!1);if(r&&a){await t.getByTestId("edit-gas-fees-row").locator("> div").first().click();let l=t.getByRole("dialog");await gt(l).toBeVisible();let u=l.locator("h4",{hasText:"Insufficient funds"}),f=await l.getByTestId("alert-modal__selected-alert").textContent();if(await u.isVisible().catch(()=>!1))throw Error(`${f}`)}if(e){let s=t.getByTestId("edit-gas-fee-icon");if(await s.scrollIntoViewIfNeeded(),await s.click(),e.feeType!=="advanced"&&await t.getByTestId(`gas-option-${e.feeType}`).click(),e.feeType==="advanced"){await t.getByTestId("gas-option-advanced").click();let l=t.getByRole("textbox",{name:"Max base fee"}),u=t.getByRole("textbox",{name:"Priority fee"}),f=t.getByRole("button",{name:"Save",exact:!0});await l.fill(e.maxBaseFee),await u.fill(e.priorityFee),await f.click()}}await gt(o).toBeEnabled(),await o.click();let i=t.getByRole("dialog");await i.isVisible().catch(()=>!1)&&await i.locator("h4",{hasText:"Your assets may be at risk"}).isVisible().catch(()=>!1)&&(await i.getByTestId("alert-modal-acknowledge-checkbox").click(),await i.getByTestId("confirm-alert-modal-submit-button").click()),await t.waitForEvent("close",{timeout:15e3})}import{expect as Gt}from"@playwright/test";import{expect as Y}from"@playwright/test";async function W({page:t,accountName:e}){let o=t.getByTestId(w.accountMenuButton);if(await o.textContent()===e){console.info(`Can't switch account to "${e}", it is already selected.`);return}await Y(o).toBeVisible({timeout:15e3}),await o.click(),await Y(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let r=t.getByTestId(P.addMultichainAccountButton),a=await r.textContent();a?.includes("Syncing")&&await Y.poll(async()=>(await r.textContent())?.trim()??"",{timeout:6e4}).not.toBe(a);let i=await t.getByTestId(/^multichain-account-cell-(?:entropy|keyring):/).all(),c=null;for(let s of i)if(await s.scrollIntoViewIfNeeded(),(await s.textContent())?.includes(e)){c=s;break}if(!c)throw Error(`Account with name "${e}" not found.`);await c?.click()}async function ht(t,e){e&&await W({page:t,accountName:e});let o=t.getByRole("button",{name:"Connect",exact:!0});await o.waitFor({state:"visible",timeout:25e3}),await o.click(),await t.getByRole("heading",{name:"Connecting",exact:!0}).waitFor({state:"detached",timeout:3e4});let r;await Gt.poll(async()=>(r=await t.locator("div[class='permissions-connect']").isVisible().catch(()=>!1),r),{timeout:25e3}).toBe(!0).catch(()=>console.error("Notice dialog did not appear within the timeout period."));let a=t.getByTestId("page-container-footer-next");await a.waitFor({state:"visible",timeout:25e3}),await a.click(),await t.waitForEvent("close",{predicate:()=>!0,timeout:25e3}).catch(()=>console.error("Extension popup did not close within the timeout period when connecting to the DApp."))}async function xt(t,e){return await t.getByTestId(w.accountAddressesButton).hover(),await t.getByTestId("multichain-address-rows-list").getByRole("button",{name:/view all/i}).click(),await t.getByRole("searchbox",{name:/search networks/i}).fill(e),await t.locator(`div[data-testid='${w.accountAddressesElements}']:has-text('${e}')`).getByTestId(w.accountAddressQRCode).click(),await t.getByRole("dialog").locator("div > p[data-testid='account-address']").textContent()}import{expect as qt}from"@playwright/test";import{errors as zt}from"@playwright/test";async function E(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}var Bt={loadingOverlay:"loading-overlay",loadingSpinner:"spinner loading-overlay__spinner"};var Kt=6e4,jt=async(t,e,o)=>{await E(e);try{await e.locator(`div[class="${t}"]`).waitFor({state:"detached",timeout:o})}catch(n){if(n instanceof zt.TimeoutError)console.info(`Loading indicator '${t}' not found - continuing.`);else throw console.error(`Error while waiting for loading indicator '${t}' to disappear`),n}},X=async t=>{try{await jt(Bt.loadingSpinner,t,Kt)}catch(e){console.warn("Warning during MetaMask load:",e)}return await v(300),t};async function kt(t){if(await t.getByTestId(O.unlockButton).isVisible().catch(()=>!1)){console.info("\u{1F4A1} Wallet is already locked");return}await j(t);let n=t.getByTestId(_.lockButton);await qt(n).toBeVisible(),await n.click(),await X(t)}import{styleText as Pt}from"util";import{expect as D}from"@playwright/test";import bt from"fs";import Xt from"path";async function Q(t){let e=h(t),o=Xt.resolve(e,"password.txt");try{if(!bt.existsSync(o))throw new Error("\u274C password.txt not found. Run setup script first.");return bt.readFileSync(o,"utf-8")}catch(n){throw new Error(`\u274C Failed to get ${t} password from cache: ${n.message}`)}}import{expect as Qt}from"@playwright/test";async function At({context:t,path:e,locator:o}){let n;try{await Qt.poll(async()=>(n=t.pages().filter(r=>r.url().startsWith("chrome-extension://")).find(r=>r.url().match(e)),!!n),{timeout:3e4}).toBe(!0)}catch{let r=t.pages().filter(a=>a.url().startsWith("chrome-extension://")).map(a=>a.url());throw new Error(`Popup page with path "${e}" not found in context after 30s. Pages in context: ${JSON.stringify(r)}`)}if(!n)throw new Error(`Popup page with path ${e} not found in context.`);return await Jt(n,o),await n.setViewportSize({width:360,height:592}),n}async function Jt(t,e){await t.waitForLoadState("load",{timeout:4e4}),await t.waitForLoadState("domcontentloaded",{timeout:4e4}),await t.locator(e).first().waitFor({state:"attached",timeout:4e4})}import Ct from"fs";import Yt from"path";async function Tt(t){let e=h(t),o=Yt.resolve(e,"extension-id.txt");try{if(!Ct.existsSync(o))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return Ct.readFileSync(o,"utf-8")}catch(n){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${n.message}`)}}var C=class{name="metamask";onboardingPath="/home.html#onboarding";async indexUrl(){return`chrome-extension://${await this.extensionId()}/home.html`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/notification.html`}async extensionId(){return await Tt(this.name)}async promptPage(e){let o=await this.promptUrl();return await At({context:e,path:o,locator:"div[data-testid='multichain-page']"})}};import{expect as Z}from"@playwright/test";async function L({page:t}){await t.locator(`div:has(> button[data-testid='${w.openSettingsButton}'])`).click(),await t.getByTestId(_.networksButton).click();let n=t.locator("section[role='dialog']");await Z(n).toBeVisible(),await Z(n).toContainText(/manage networks/i);let r="div:has(> p:has-text('Show test networks'))";await n.locator(r).scrollIntoViewIfNeeded();let a=n.locator(r);if(!await a.locator("label[class='toggle-button toggle-button--off']").isVisible().catch(()=>!1)){await n.getByRole("button",{name:/close/i}).click(),console.info("Testnet networks are already visible.");return}await a.locator("label[class='toggle-button toggle-button--off']").click(),await t.getByTestId("Sepolia").scrollIntoViewIfNeeded(),await Z(t.getByTestId("Sepolia")).toBeVisible(),await n.getByRole("button",{name:/close/i}).click()}async function tt({page:t,mainAccountName:e,...o}){console.info(Pt("yellowBright",`
3
+ \u{1F98A} MetaMask onboarding started...`,{validateStream:!1}));let n=await Q("metamask"),r=new C,a=t.locator("img[class='loading-spinner']"),i=t.getByTestId(g.createWalletButton),c=t.getByTestId(g.importWalletButton),s=t.getByTestId(g.createNewPasswordInput),p=t.getByTestId(g.confirmNewPasswordInput),l=t.getByTestId(g.confirmPasswordCheckbox),u=t.getByTestId(g.createPasswordButton),f=t.getByTestId(g.metamaskMetricsIAgreeButton),B=t.getByTestId(g.onboardingDoneButton);if(await a.waitFor({state:"detached",timeout:3e4}),o.mode==="create"){let I=t.getByTestId(g.useSecretRecoveryPhraseButton);await i.click(),await I.click(),await s.fill(n),await p.fill(n),await l.click(),await u.click(),await t.getByTestId(g.revealSecretRecoveryPhraseButton).click(),await t.getByTestId(g.recoveryPhraseRemindMeLaterButton).click(),await f.click()}if(o.mode==="import"){let{secretRecoveryPhrase:I}=o,T=I.split(" "),z=t.getByTestId(g.importUsingSecretRecoveryPhraseButton);await c.click(),await z.click();let at=t.getByTestId(g.secretRecoveryPhraseTextAreaInput);await at.fill(T[0]),await at.press("Space");for(let K=1;K<T.length;K++){let rt=t.getByTestId(`import-srp__srp-word-${K}`);await rt.fill(T[K]),await rt.press("Space")}await t.getByTestId(g.importWalletConfirmButton).click(),await s.fill(n),await p.fill(n),await l.click(),await u.click(),await f.click();let Mt=t.getByTestId("wallet-ready");await D(Mt).toContainText(/your wallet is ready/i)}await B.click();let A=`chrome-extension://${await r.extensionId()}/sidepanel.html`,y=await t.context().browser()?.newBrowserCDPSession(),N;await D.poll(async()=>{if(y){let{targetInfos:I}=await y.send("Target.getTargets"),T=I.find(z=>z.url===A);return N=T,!!T}},{timeout:15e3}).toBe(!0),N&&await y?.send("Target.closeTarget",{targetId:N.targetId}),await t.goto(await r.indexUrl()),await a.waitFor({state:"detached",timeout:3e4}),await D(t.getByTestId(w.buyButton)).toBeVisible(),await D(t.getByTestId(w.swapButton)).toBeVisible(),await D(t.getByTestId(w.sendButton)).toBeVisible(),await D(t.getByTestId(w.receiveButton)).toBeVisible(),await L({page:t}),e&&await W({page:t,accountName:e}),await v(5e3),console.info(Pt("greenBright","\u2728 MetaMask onboarding completed successfully",{validateStream:!1}))}import{expect as Zt}from"@playwright/test";async function St(t){let e=t.getByTestId(q.cancelButton);await v(1e3),await Zt(e).toBeEnabled(),await e.click()}import{expect as b}from"@playwright/test";async function It({page:t,currentAccountName:e,newAccountName:o}){let n=t.getByTestId(w.accountMenuButton);if(await n.textContent()===o)throw Error(`The account to be renamed "${o}" already exists.`);await b(n).toBeVisible({timeout:15e3}),await n.click(),await b(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let a=t.getByTestId(P.addMultichainAccountButton),i=await a.textContent();i?.includes("Syncing")&&await b.poll(async()=>(await a.textContent())?.trim()??"",{timeout:6e4}).not.toBe(i);let c=await t.getByTestId(/^multichain-account-cell/).all(),s=null;for(let y of c)if((await y.textContent())?.includes(e)){s=y;break}if(!s)throw Error(`Account with name "${e}" not found.`);if((await s.textContent())?.split("$")[0]===o)throw Error(`The new account name "${o}" is the same as the old account name "${e}".`);let l=t.locator(`div[aria-label='${e} options']`);await b(l).toBeVisible(),await l.click(),await b(t.getByRole("tooltip")).toBeVisible();let u=t.locator(`div[aria-label='${P.renameAccountLabel}']`);await b(u).toBeVisible(),await u.click();let f=t.getByRole("dialog"),B=f.getByRole("heading",{name:/rename/i});await b(B).toBeVisible();let S=f.getByRole("textbox");await b(S).toBeVisible(),await S.fill(o);let A=f.getByRole("button",{name:/confirm/i});await b(A).toBeEnabled(),await A.click();for(let y of c)if((await y.textContent())?.includes(o)){await b(y).toBeVisible(),await b(y).toContainText(o);break}await t.locator("button[aria-label='Back']").first().click()}import{expect as et}from"@playwright/test";async function vt({page:t,networkType:e,chainName:o}){let n=t.getByTestId(w.openNetworkSelectorButton);await n.click();let r=t.getByTestId("modal-header-close-button");if(e==="testnet"||e==="custom"){let s=t.getByRole("tab",{name:"Custom"});await s.click(),await t.locator("p:has-text('Testnets')").isVisible().catch(()=>!1)||(await r.click(),await L({page:t}),await n.click(),await s.click());let u=t.locator(`div div[data-testid='${o}']`),f=await u.textContent();et(f).toBe(o),await u.click();return}await t.getByRole("tab",{name:"Popular"}).click();let i=t.locator(`div div[data-testid='${o}']`),c=await i.textContent();et(c).toBe(o),await i.click(),await et(n).toContainText(o,{timeout:3e4})}import{expect as Rt}from"@playwright/test";async function H(t){let e=await Q("metamask"),o=t.getByTestId(O.passwordInput);if(await t.getByTestId(w.openNetworkSelectorButton).isVisible().catch(()=>!1)){console.info("\u{1F4A1} Wallet is already unlocked");return}await o.fill(e);let a=t.getByTestId(O.unlockButton);await Rt(a).toBeVisible(),await a.click(),await X(t),await Rt(t.getByTestId(w.buyButton)).toBeVisible({timeout:3e4})}var V=class extends C{page;constructor(e){super(),this.page=e}async onboard(e){await tt({page:this.page,...e})}async unlock(){await H(this.page)}async lock(){await kt(this.page)}async renameAccount({newAccountName:e,currentAccountName:o}){await It({page:this.page,newAccountName:e,currentAccountName:o})}async addAccount({privateKey:e,accountName:o}){await pt({page:this.page,privateKey:e,accountName:o})}async switchAccount({accountName:e}){await W({page:this.page,accountName:e})}async switchNetwork({...e}){await vt({page:this.page,...e})}async getAccountAddress(e){return await xt(this.page,e)}async toggleShowTestnetNetwork(){await L({page:this.page})}async addCustomNetwork({chainId:e,currencySymbol:o,networkName:n,rpcUrl:r}){await ft({page:this.page,chainId:e,currencySymbol:o,networkName:n,rpcUrl:r})}async connectToApp(e){await ht(await this.promptPage(this.page.context()),e)}async confirmTransaction(e){await yt(await this.promptPage(this.page.context()),e)}async rejectTransaction(){await St(await this.promptPage(this.page.context()))}};import Nt from"fs";import ne from"path";import{test as ae,chromium as re}from"@playwright/test";import{Instance as ie,Pool as se}from"prool";import{expect as te}from"@playwright/test";async function ot(t,e){let o=await t.newPage();return await te(async()=>{await o.goto(e),await E(o)}).toPass(),o}async function nt(t,e){let o=await e.newPage();for(let{origin:n,localStorage:r}of t){let a=o.mainFrame();await a.goto(n),await a.evaluate(i=>{i.forEach(({name:c,value:s})=>{window.localStorage.setItem(c,s)})},r)}await o.close()}import ee from"fs/promises";async function Et(t){await ee.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var oe=35e3;async function J(t,e){try{await Promise.race([t.close(),new Promise((o,n)=>setTimeout(()=>n(new Error("Context close timed out")),oe))])}catch(o){console.warn(`Browser context close did not complete cleanly: ${o.message}`)}try{await Et(e)}catch(o){console.error(`Failed to remove temporary context directory at ${e}. Error:`,o)}}var G,Ua=({slowMo:t=0,profileName:e}={})=>ae.extend({contextPath:async({browserName:o},n,r)=>{let a=await R(`${o}-${r.testId}`);await n(a)},context:async({context:o,contextPath:n},r)=>{let a=new C,i=h(a.name),c=await F(a.name),s=ne.resolve(i,e??"wallet-data");if(!Nt.existsSync(s))throw new Error("\u274C Cache for MetaMask wallet data not found. Create it first");Nt.cpSync(s,n,{recursive:!0,force:!0});let p=[`--disable-extensions-except=${c}`,`--load-extension=${c}`];process.env.HEADLESS&&(p.push("--headless=new"),t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!"));let l=await re.launchPersistentContext(n,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:t}),{cookies:u,origins:f}=await o.storageState();u&&await l.addCookies(u),f&&f.length>0&&nt(f,l);let B=await a.indexUrl();await l.waitForEvent("page",{predicate:k=>k.url().startsWith(B),timeout:3e4}),G=l.pages().find(k=>k.url().startsWith(B))??await ot(l,B);for(let k of l.pages())k.url().includes("about:blank")&&await k.close();await G.locator("img[class='loading-spinner']").waitFor({state:"detached"}),await H(G),await r(l),await J(l,n)},metamaskPage:async({context:o},n)=>{await n(G)},metamask:async({context:o},n)=>{let r=new V(G);await n(r)},createAnvilNode:async({context:o},n,r)=>{let a=r.workerIndex,i;await n(async c=>{i=se.define({instance:ie.anvil(c)});let s=await i.start(a),p=`http://${s.host}:${s.port}`,u=c?.chainId??31337;return{rpcUrl:p,anvil:s,chainId:u}}),i&&await i.stop(a)},connectToAnvil:async({context:o,metamask:n,createAnvilNode:r},a)=>{await a(async()=>{let{chainId:i,rpcUrl:c}=await r({chainId:2251});await n.addCustomNetwork({chainId:i,currencySymbol:"ETH",networkName:"Anvil Localnet",rpcUrl:c})})}});import{test as de}from"@playwright/test";import{Instance as me,Pool as ue}from"prool";import Ft from"fs";import ce from"path";import{chromium as le}from"@playwright/test";async function _t({workerInfo:t,profileName:e,slowMo:o}){let n=new C,r=await R(t.workerIndex.toString()),a=h(n.name),i=ce.resolve(a,e??"wallet-data");if(!Ft.existsSync(i))throw new Error(`Cache for ${n.name} does not exist. Create it first!`);Ft.cpSync(i,r,{recursive:!0,force:!0});let c=await F(n.name),s=await le.launchPersistentContext(r,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:o}),p=await n.indexUrl();await s.waitForEvent("page",{predicate:u=>u.url().startsWith(p),timeout:4e4});let l=s.pages().find(u=>u.url().startsWith(p));l||(l=await s.newPage(),await l.goto(p),await E(l));for(let u of s.pages())u.url().includes("about:blank")&&await u.close();return{context:s,walletPage:l,contextPath:r}}var ar=({profileName:t,slowMo:e}={})=>de.extend({workerScopeContents:[async({browser:o},n,r)=>{let{context:a,contextPath:i,walletPage:c}=await _t({workerInfo:r,profileName:t,slowMo:e});await a.grantPermissions(["clipboard-read"]);let s=new V(c);await s.unlock(),await n({wallet:s,walletPage:c,context:a}),await J(a,i)},{scope:"worker"}],createAnvilNode:async({context:o},n,r)=>{let a=r.workerIndex,i;await n(async c=>{i=ue.define({instance:me.anvil(c)});let s=await i.start(a),p=`http://${s.host}:${s.port}`,u=c?.chainId??31337;return{rpcUrl:p,anvil:s,chainId:u}}),i&&await i.stop(a)},connectToAnvil:async({context:o,createAnvilNode:n,workerScopeContents:r},a)=>{await a(async()=>{let{wallet:i}=r,{chainId:c,rpcUrl:s}=await n({chainId:2251});await i.addCustomNetwork({chainId:c,currencySymbol:"ETH",networkName:"Anvil Localnet",rpcUrl:s})})}});export{V as Metamask,Ua as metamaskFixture,ar as metamaskWorkerScopeFixture,Oe as workerScopeContext};
@@ -1,6 +1,6 @@
1
- import { W as WalletProfileFixtureArgs, c as WorkerScopeFixtureArgs } from '../../types-B56pinWs.js';
2
- import { W as WorkerScopeFixture } from '../../worker-scope-context-DiN3_Sig.js';
3
- export { w as workerScopeContext } from '../../worker-scope-context-DiN3_Sig.js';
1
+ import { W as WalletProfileFixtureArgs } from '../../types-DK8rutb5.js';
2
+ import { W as WorkerScopeFixture } from '../../worker-scope-context-CNAfiliw.js';
3
+ export { w as workerScopeContext } from '../../worker-scope-context-CNAfiliw.js';
4
4
  import * as _playwright_test from '@playwright/test';
5
5
  import { BrowserContext, Page } from '@playwright/test';
6
6
 
@@ -146,6 +146,6 @@ declare class Meteor extends MeteorProfile {
146
146
 
147
147
  declare const meteorFixture: ({ slowMo, profileName }?: WalletProfileFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & MeteorFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
148
148
 
149
- declare const meteorWorkerScopeFixture: ({ slowMo, profileName, dappUrl }?: WorkerScopeFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & MeteorFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerScopeFixture<Meteor>>;
149
+ declare const meteorWorkerScopeFixture: ({ slowMo, profileName }?: WalletProfileFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & MeteorFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerScopeFixture<Meteor>>;
150
150
 
151
- export { Meteor, WalletProfileFixtureArgs, WorkerScopeFixture, WorkerScopeFixtureArgs, meteorFixture, meteorWorkerScopeFixture };
151
+ export { Meteor, WalletProfileFixtureArgs, WorkerScopeFixture, meteorFixture, meteorWorkerScopeFixture };
@@ -1,7 +1,7 @@
1
- import tt from"fs";import gt from"path";import{chromium as yt}from"@playwright/test";import ft from"path";var Y=".wallet-cache",Q=".wallet-context";var J="13.22.0",v="https://github.com/amaify/chainwright/releases/download/v0.1.0/",Rt=`https://github.com/MetaMask/metamask-extension/releases/download/v${J}/metamask-chrome-${J}.zip`,Ut=`${v}solflare-wallet-extension-v2.19.1.zip`,$t=`${v}petra-wallet-extension-v2.4.8.zip`,Vt=`${v}phantom-wallet-extension-v26.10.0.zip`,Kt=`${v}meteor-wallet-extension-v0.7.0.zip`,Ht=`${v}keplr-wallet-extension-v0.13.3.zip`;async function E(t){return ft.resolve(process.cwd(),Q,t)}import ht from"path";function f(t){return ht.resolve(process.cwd(),Y,t)}import Z from"fs";import xt from"path";async function N(t){try{let o=f(t),e=xt.resolve(o,"extension-path.txt");if(!Z.existsSync(e))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let r=Z.readFileSync(e,"utf-8").trim();if(!r)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return r}catch(o){throw new Error(`\u274C Failed to get ${t} extension path: ${o.message}`)}}async function ot({wallet:t,workerInfo:o,profileName:e,slowMo:r}){let a=await E(o.workerIndex.toString()),c=f(t.name),p=gt.resolve(c,e??"wallet-data");if(!tt.existsSync(p))throw new Error(`Cache for ${t.name} does not exist. Create it first!`);tt.cpSync(p,a,{recursive:!0,force:!0});let u=await N(t.name),l=await yt.launchPersistentContext(a,{headless:!1,args:[`--disable-extensions-except=${u}`],slowMo:process.env.HEADLESS?0:r}),s=await t.indexUrl(),m=l.pages()[0];return m||(m=await l.newPage()),await m.goto(s),{context:l,walletPage:m,contextPath:a}}var w={openSidebarMenuButton:"button[aria-label='open sidebar']",addWalletButton:"button:has-text('Add Wallet')",settingsButton:"button:has-text('Settings')",settingsMenuBackButton:"button[aria-label='Back']"};var d={importExistingWalletButton:'button:has-text("Import an existing wallet")',switchNetworkButton:"button[id^='menu-button']",privateKeyButton:"button:has-text('Private Key')",findMyAccountButton:"button:has-text('Find my account')"};async function _(t,o,e){let r=t.locator(d.switchNetworkButton).last();await r.scrollIntoViewIfNeeded();let a=await r.textContent(),c=o.split("net")[0]?.toLowerCase()??"";if(a?.toLowerCase()===c)return console.info(`
2
- Already on ${o}, no need to switch network.`),"Exit";await r.click();let u=t.locator(e).last().locator(`> button:has-text('${o}')`);await u.click(),await t.locator("div > h2:has-text('Meteor Community')").isVisible().catch(()=>!1)&&await u.click()}async function A({page:t,newAccountName:o}){await t.locator(w.openSidebarMenuButton).click(),await t.locator("div:has(> h2):has(> svg)").click();let a=t.locator("input[placeholder='Ex. My Meteor Wallet']"),c=t.locator("button[type='submit']:has-text('Update')");await a.fill(o),await c.click(),await t.locator("div[id='root'] button[aria-label='Close']").click()}async function F({page:t,privateKey:o,accountName:e,network:r}){await t.locator(w.openSidebarMenuButton).click(),await t.locator(w.addWalletButton).click(),await _(t,r,"section[role='dialog'] div[role='menu']"),await t.locator(d.importExistingWalletButton).click(),await t.locator(d.privateKeyButton).click();let l=t.locator('button:has-text("Continue")');await l.scrollIntoViewIfNeeded(),await l.click(),await t.locator("textarea:not([disabled])").fill(o),await t.locator(d.findMyAccountButton).click(),await t.locator("button[type='submit'][data-loading]").waitFor({state:"detached",timeout:25e3}),await t.locator("button:not([aria-label='Back'],[id^='menu-button']):has-text('Account')").click(),await A({page:t,newAccountName:e})}var k={approveButton:"button:has-text('Approve')",connectButton:"button:has-text('Connect')",cancelButton:"button:has-text('Cancel')"};import et from"fs";import Pt from"path";async function I(t){let o=f(t),e=Pt.resolve(o,"password.txt");try{if(!et.existsSync(e))throw new Error("\u274C password.txt not found. Run setup script first.");return et.readFileSync(e,"utf-8")}catch(r){throw new Error(`\u274C Failed to get ${t} password from cache: ${r.message}`)}}async function h(t){let o=await I("meteor"),e=t.locator("input[placeholder='Enter Password']"),r=t.locator('button:has-text("Unlock")');await e.fill(o),await r.click()}async function rt(t){await h(t),await t.locator(k.approveButton).click(),await t.locator("h2:has-text('Executing Transaction')").waitFor({state:"attached"}),await t.waitForEvent("close",{timeout:15e3})}async function B(t,o){if((await t.locator("div:has(button[type='button'][aria-label='open sidebar'])").nth(-2).locator("div:has(div > h2)").locator("div > h2").textContent())?.toLowerCase()===o.toLowerCase()){console.info(`
3
- Switching to the ${o} account aborted. Account is already selected.`);return}await t.locator(w.openSidebarMenuButton).click();let l=await t.locator("div:has(div > button[type='button'][aria-label='Close'])").nth(-2).locator("div").nth(2).locator("> div").nth(1).locator("div").nth(1).locator("div > h2").all(),s=null;for(let m of l)if((await m.textContent())?.toLowerCase()===o.toLowerCase()){s=m;break}if(!s)throw new Error(`Account with name "${o}" not found.`);await s.click()}async function at(t,o){await h(t),o&&await B(t,o);let e=t.getByRole("heading",{name:"Connect Request",exact:!0});await Promise.all([t.locator(k.connectButton).click(),e.waitFor({state:"detached",timeout:3e4})])}async function nt(t){return await t.locator("div:has(button[type='button'][aria-label='open sidebar'])").nth(-2).locator("div:has(div > h2)").locator("div > svg").click(),await t.evaluate(async()=>await navigator.clipboard.readText())}async function it(t){await t.locator(w.openSidebarMenuButton).click(),await t.locator("button:has-text('Lock Wallet')").click()}import{styleText as O}from"util";function T(t){return new Promise(o=>setTimeout(o,t))}import{expect as bt}from"@playwright/test";async function ct({context:t,path:o,locator:e}){let r;try{await bt.poll(async()=>(r=t.pages().filter(a=>a.url().startsWith("chrome-extension://")).find(a=>a.url().match(o)),!!r),{timeout:3e4}).toBe(!0)}catch{let a=t.pages().filter(c=>c.url().startsWith("chrome-extension://")).map(c=>c.url());throw new Error(`Popup page with path "${o}" not found in context after 30s. Pages in context: ${JSON.stringify(a)}`)}if(!r)throw new Error(`Popup page with path ${o} not found in context.`);return await At(r,e),await r.setViewportSize({width:360,height:592}),r}async function At(t,o){await t.waitForLoadState("load",{timeout:4e4}),await t.waitForLoadState("domcontentloaded",{timeout:4e4}),await t.locator(o).first().waitFor({state:"attached",timeout:4e4})}import st from"fs";import kt from"path";async function lt(t){let o=f(t),e=kt.resolve(o,"extension-id.txt");try{if(!st.existsSync(e))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return st.readFileSync(e,"utf-8")}catch(r){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${r.message}`)}}var x=class{name="meteor";onboardingPath="ext_index_popup.html";async indexUrl(){return`chrome-extension://${await this.extensionId()}/ext_index_popup.html`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/ext_index.html`}async extensionId(){return await lt(this.name)}async promptPage(o){let e=await this.promptUrl();return await ct({context:o,path:e,locator:"div[id='root']"})}};async function C(t){await t.locator(w.openSidebarMenuButton).click(),await t.locator(w.settingsButton).click()}async function L(t,o){if(await C(t),await _(t,o,"div[role='menu']")==="Exit"){let c=t.locator(w.settingsMenuBackButton);await c.scrollIntoViewIfNeeded(),await c.click();return}let r=t.locator("p:has-text('Available Balance')");if(await T(1e3),!await r.isVisible().catch(()=>!1))throw new Error([`There is no associated account for the ${o} network in your wallet.`,`Please add an account to the ${o} network in your wallet using the "addAccount" method.`,"NOTE: For the account to be persisted across tests, do this when onboarding the wallet."].join(`
4
- `))}async function R({page:t,privateKey:o,network:e,accountName:r,additionalAccounts:a}){console.info(O("yellowBright",`
5
- Meteor onboarding started...`,{validateStream:!1}));let c=await I("meteor"),u=await new x().indexUrl();await t.goto(u);let l=t.locator(d.switchNetworkButton),s=await l.textContent(),m=e.split("net")[0]?.toLowerCase()??"";s?.toLowerCase().includes(m)||(await l.click(),await t.locator("div[role='menu']").locator(`> button:has-text('${e}')`).click());let y=t.locator("input[placeholder='Enter Password']"),S=t.locator("input[placeholder='Confirm Password']"),K=t.locator("label.chakra-checkbox .chakra-checkbox__control"),g=t.locator('button:has-text("Continue")');await y.fill(c),await S.fill(c),await K.click(),await g.click(),await t.locator(d.importExistingWalletButton).click(),await t.locator(d.privateKeyButton).click(),await g.scrollIntoViewIfNeeded(),await g.click(),await t.locator("textarea:not([disabled])").fill(o);let H=t.locator(d.findMyAccountButton);await H.click();let z=t.locator("button[type='submit'][data-loading]");if(await z.waitFor({state:"detached",timeout:25e3}),await t.getByRole("status").locator("div[id='toast-1-title']:has-text('No Account Found')").isVisible().catch(()=>!1)){let P=5,M=!1;for(;P>0;){if(console.info(`
6
- Retrying search for account. ${P} attempts left`),await T(15e3),await H.click(),await z.waitFor({state:"detached",timeout:2e4}),await t.locator("div:has-text('Import Your Account')").nth(-2).locator("button").isVisible().catch(()=>!1)){M=!0;break}P-=1}if(!M)throw Error(O("redBright",["No Account Found","Account associated with the private key not found. Please make sure you are trying to import an account on the correct network(Mainnet/Testnet)."].join(`
7
- `),{validateStream:!1}))}await t.locator("button:not([aria-label='Back'],[id^='menu-button']):has-text('Account')").click();let j=t.locator("section[role='dialog']").locator("button:has-text('Close')").first();if(await j.isVisible().then(()=>!0).catch(()=>!1)&&await j.click(),await A({page:t,newAccountName:r}),a&&a.length>0){for(let{privateKey:q,accountName:G,network:dt}of a)await F({page:t,privateKey:q,accountName:G,network:dt});await C(t);let P=t.locator(d.switchNetworkButton).last();await P.scrollIntoViewIfNeeded();let M=await P.textContent(),X=e.split("net")[0]?.toLowerCase()??"";M?.toLowerCase()!==X&&await L(t,e),await B(t,r)}await T(3e3),console.info(O("greenBright","\u2728 Meteor onboarding completed successfully"))}async function pt(t){await h(t),await t.locator(k.cancelButton).click()}var b=class extends x{page;constructor(o){super(),this.page=o}async onboard({network:o,privateKey:e,accountName:r,additionalAccounts:a}){await R({page:this.page,network:o,privateKey:e,accountName:r,additionalAccounts:a})}async unlock(){await h(this.page)}async lock(){await it(this.page)}async renameAccount({newAccountName:o}){await A({page:this.page,newAccountName:o})}async switchNetwork(o){await L(this.page,o)}async switchAccount(o){await B(this.page,o)}async getAccountAddress(){return await nt(this.page)}async addAccount({accountName:o,network:e,privateKey:r}){await F({page:this.page,accountName:o,network:e,privateKey:r})}async openSettings(){await C(this.page)}async connectToApp(o){await at(await this.promptPage(this.page.context()),o)}async confirmTransaction(){await rt(await this.promptPage(this.page.context()))}async rejectTransaction(){await pt(await this.promptPage(this.page.context()))}};import ut from"fs";import Mt from"path";import{test as vt,chromium as Et}from"@playwright/test";import{expect as Bt}from"@playwright/test";async function U(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}async function $(t,o){let e=await t.newPage();return await Bt(async()=>{await e.goto(o),await U(e)}).toPass(),e}async function V(t,o){let e=await o.newPage();for(let{origin:r,localStorage:a}of t){let c=e.mainFrame();await c.goto(r),await c.evaluate(p=>{p.forEach(({name:u,value:l})=>{window.localStorage.setItem(u,l)})},a)}await e.close()}import Ct from"fs/promises";async function mt(t){await Ct.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var St=35e3;async function D(t,o){try{await Promise.race([t.close(),new Promise((e,r)=>setTimeout(()=>r(new Error("Context close timed out")),St))])}catch(e){console.warn(`Browser context close did not complete cleanly: ${e.message}`)}try{await mt(o)}catch(e){console.error(`Failed to remove temporary context directory at ${o}. Error:`,e)}}var W,Tr=({slowMo:t=0,profileName:o}={})=>vt.extend({contextPath:async({browserName:e},r,a)=>{let c=await E(`${e}-${a.testId}`);await r(c)},context:async({context:e,contextPath:r},a)=>{let c=new x,p=f(c.name),u=await N(c.name),l=Mt.resolve(p,o??"wallet-data");if(!ut.existsSync(l))throw new Error("\u274C Cache for Meteor wallet data not found. Create it first");ut.cpSync(l,r,{recursive:!0,force:!0}),process.env.HEADLESS&&t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!");let s=await Et.launchPersistentContext(r,{headless:!1,args:[`--disable-extensions-except=${u}`,`--load-extension=${u}`],slowMo:process.env.HEADLESS?0:t});await s.grantPermissions(["clipboard-read"]);let{cookies:m,origins:y}=await e.storageState();m&&await s.addCookies(m),y&&y.length>0&&V(y,s);let S=await c.indexUrl();W=s.pages().find(g=>g.url().startsWith(S))||await $(s,S);for(let g of s.pages())g.url().includes("about:blank")&&await g.close();await W.bringToFront(),await h(W),await a(s),await D(s,r)},meteorPage:async({context:e},r)=>{await r(W)},meteor:async({context:e},r)=>{let a=new b(W);await r(a)}});import{test as Tt}from"@playwright/test";var Or=({slowMo:t,profileName:o,dappUrl:e}={})=>Tt.extend({workerScopeContents:[async({browser:r},a,c)=>{let{context:p,contextPath:u,walletPage:l}=await ot({workerInfo:c,profileName:o,slowMo:t,wallet:new x});await p.grantPermissions(["clipboard-read"]);for(let m of p.pages())m.url().includes("about:blank")&&await m.close();let s=new b(l);await s.unlock(),await a({wallet:s,walletPage:l,context:p}),await D(p,u)},{scope:"worker"}],dappPage:[async({workerScopeContents:r},a)=>{let{context:c}=r,p=await c.newPage();e&&await p.goto(e),await a(p)},{scope:"worker"}],meteorPage:async({workerScopeContents:r},a)=>{await a(r.walletPage)},meteor:async({workerScopeContents:r},a)=>{let c=new b(r.walletPage);await a(c)}});export{b as Meteor,Tr as meteorFixture,Or as meteorWorkerScopeFixture,ot as workerScopeContext};
1
+ import tt from"fs";import gt from"path";import{chromium as yt}from"@playwright/test";import ft from"path";var Y=".wallet-cache",Q=".wallet-context";var J="13.22.0",v="https://github.com/amaify/chainwright/releases/download/v0.1.0/",Rt=`https://github.com/MetaMask/metamask-extension/releases/download/v${J}/metamask-chrome-${J}.zip`,Ut=`${v}solflare-wallet-extension-v2.19.1.zip`,$t=`${v}petra-wallet-extension-v2.4.8.zip`,Vt=`${v}phantom-wallet-extension-v26.10.0.zip`,Kt=`${v}meteor-wallet-extension-v0.7.0.zip`,Ht=`${v}keplr-wallet-extension-v0.13.3.zip`;async function E(t){return ft.resolve(process.cwd(),Q,t)}import ht from"path";function f(t){return ht.resolve(process.cwd(),Y,t)}import Z from"fs";import xt from"path";async function N(t){try{let o=f(t),e=xt.resolve(o,"extension-path.txt");if(!Z.existsSync(e))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let r=Z.readFileSync(e,"utf-8").trim();if(!r)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return r}catch(o){throw new Error(`\u274C Failed to get ${t} extension path: ${o.message}`)}}async function ot({wallet:t,workerInfo:o,profileName:e,slowMo:r}){let i=await E(o.workerIndex.toString()),c=f(t.name),u=gt.resolve(c,e??"wallet-data");if(!tt.existsSync(u))throw new Error(`Cache for ${t.name} does not exist. Create it first!`);tt.cpSync(u,i,{recursive:!0,force:!0});let p=await N(t.name),l=await yt.launchPersistentContext(i,{headless:!1,args:[`--disable-extensions-except=${p}`],slowMo:process.env.HEADLESS?0:r}),s=await t.indexUrl(),w=l.pages()[0];return w||(w=await l.newPage()),await w.goto(s),{context:l,walletPage:w,contextPath:i}}var m={openSidebarMenuButton:"button[aria-label='open sidebar']",addWalletButton:"button:has-text('Add Wallet')",settingsButton:"button:has-text('Settings')",settingsMenuBackButton:"button[aria-label='Back']"};var d={importExistingWalletButton:'button:has-text("Import an existing wallet")',switchNetworkButton:"button[id^='menu-button']",privateKeyButton:"button:has-text('Private Key')",findMyAccountButton:"button:has-text('Find my account')"};async function _(t,o,e){let r=t.locator(d.switchNetworkButton).last();await r.scrollIntoViewIfNeeded();let i=await r.textContent(),c=o.split("net")[0]?.toLowerCase()??"";if(i?.toLowerCase()===c)return console.info(`
2
+ Already on ${o}, no need to switch network.`),"Exit";await r.click();let p=t.locator(e).last().locator(`> button:has-text('${o}')`);await p.click(),await t.locator("div > h2:has-text('Meteor Community')").isVisible().catch(()=>!1)&&await p.click()}async function P({page:t,newAccountName:o}){await t.locator(m.openSidebarMenuButton).click(),await t.locator("div:has(> h2):has(> svg)").click();let i=t.locator("input[placeholder='Ex. My Meteor Wallet']"),c=t.locator("button[type='submit']:has-text('Update')");await i.fill(o),await c.click(),await t.locator("div[id='root'] button[aria-label='Close']").click()}async function F({page:t,privateKey:o,accountName:e,network:r}){await t.locator(m.openSidebarMenuButton).click(),await t.locator(m.addWalletButton).click(),await _(t,r,"section[role='dialog'] div[role='menu']"),await t.locator(d.importExistingWalletButton).click(),await t.locator(d.privateKeyButton).click();let l=t.locator('button:has-text("Continue")');await l.scrollIntoViewIfNeeded(),await l.click(),await t.locator("textarea:not([disabled])").fill(o),await t.locator(d.findMyAccountButton).click(),await t.locator("button[type='submit'][data-loading]").waitFor({state:"detached",timeout:25e3}),await t.locator("button:not([aria-label='Back'],[id^='menu-button']):has-text('Account')").click(),await P({page:t,newAccountName:e})}var A={approveButton:"button:has-text('Approve')",connectButton:"button:has-text('Connect')",cancelButton:"button:has-text('Cancel')"};import et from"fs";import bt from"path";async function I(t){let o=f(t),e=bt.resolve(o,"password.txt");try{if(!et.existsSync(e))throw new Error("\u274C password.txt not found. Run setup script first.");return et.readFileSync(e,"utf-8")}catch(r){throw new Error(`\u274C Failed to get ${t} password from cache: ${r.message}`)}}async function h(t){let o=await I("meteor"),e=t.locator("input[placeholder='Enter Password']"),r=t.locator('button:has-text("Unlock")');await e.fill(o),await r.click()}async function rt(t){await h(t),await t.locator(A.approveButton).click(),await t.locator("h2:has-text('Executing Transaction')").waitFor({state:"attached"}),await t.waitForEvent("close",{timeout:15e3})}async function k(t,o){if((await t.locator("div:has(button[type='button'][aria-label='open sidebar'])").nth(-2).locator("div:has(div > h2)").locator("div > h2").textContent())?.toLowerCase()===o.toLowerCase()){console.info(`
3
+ Switching to the ${o} account aborted. Account is already selected.`);return}await t.locator(m.openSidebarMenuButton).click();let l=await t.locator("div:has(div > button[type='button'][aria-label='Close'])").nth(-2).locator("div").nth(2).locator("> div").nth(1).locator("div").nth(1).locator("div > h2").all(),s=null;for(let w of l)if((await w.textContent())?.toLowerCase()===o.toLowerCase()){s=w;break}if(!s)throw new Error(`Account with name "${o}" not found.`);await s.click()}async function at(t,o){await h(t),o&&await k(t,o);let e=t.getByRole("heading",{name:"Connect Request",exact:!0});await Promise.all([t.locator(A.connectButton).click(),e.waitFor({state:"detached",timeout:3e4})])}async function nt(t){return await t.locator("div:has(button[type='button'][aria-label='open sidebar'])").nth(-2).locator("div:has(div > h2)").locator("div > svg").click(),await t.evaluate(async()=>await navigator.clipboard.readText())}async function it(t){await t.locator(m.openSidebarMenuButton).click(),await t.locator("button:has-text('Lock Wallet')").click()}import{styleText as O}from"util";function T(t){return new Promise(o=>setTimeout(o,t))}import{expect as Pt}from"@playwright/test";async function ct({context:t,path:o,locator:e}){let r;try{await Pt.poll(async()=>(r=t.pages().filter(i=>i.url().startsWith("chrome-extension://")).find(i=>i.url().match(o)),!!r),{timeout:3e4}).toBe(!0)}catch{let i=t.pages().filter(c=>c.url().startsWith("chrome-extension://")).map(c=>c.url());throw new Error(`Popup page with path "${o}" not found in context after 30s. Pages in context: ${JSON.stringify(i)}`)}if(!r)throw new Error(`Popup page with path ${o} not found in context.`);return await At(r,e),await r.setViewportSize({width:360,height:592}),r}async function At(t,o){await t.waitForLoadState("load",{timeout:4e4}),await t.waitForLoadState("domcontentloaded",{timeout:4e4}),await t.locator(o).first().waitFor({state:"attached",timeout:4e4})}import st from"fs";import kt from"path";async function lt(t){let o=f(t),e=kt.resolve(o,"extension-id.txt");try{if(!st.existsSync(e))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return st.readFileSync(e,"utf-8")}catch(r){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${r.message}`)}}var x=class{name="meteor";onboardingPath="ext_index_popup.html";async indexUrl(){return`chrome-extension://${await this.extensionId()}/ext_index_popup.html`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/ext_index.html`}async extensionId(){return await lt(this.name)}async promptPage(o){let e=await this.promptUrl();return await ct({context:o,path:e,locator:"div[id='root']"})}};async function B(t){await t.locator(m.openSidebarMenuButton).click(),await t.locator(m.settingsButton).click()}async function L(t,o){if(await B(t),await _(t,o,"div[role='menu']")==="Exit"){let c=t.locator(m.settingsMenuBackButton);await c.scrollIntoViewIfNeeded(),await c.click();return}let r=t.locator("p:has-text('Available Balance')");if(await T(1e3),!await r.isVisible().catch(()=>!1))throw new Error([`There is no associated account for the ${o} network in your wallet.`,`Please add an account to the ${o} network in your wallet using the "addAccount" method.`,"NOTE: For the account to be persisted across tests, do this when onboarding the wallet."].join(`
4
+ `))}async function R({page:t,privateKey:o,network:e,accountName:r,additionalAccounts:i}){console.info(O("yellowBright",`
5
+ Meteor onboarding started...`,{validateStream:!1}));let c=await I("meteor"),p=await new x().indexUrl();await t.goto(p);let l=t.locator(d.switchNetworkButton),s=await l.textContent(),w=e.split("net")[0]?.toLowerCase()??"";s?.toLowerCase().includes(w)||(await l.click(),await t.locator("div[role='menu']").locator(`> button:has-text('${e}')`).click());let y=t.locator("input[placeholder='Enter Password']"),S=t.locator("input[placeholder='Confirm Password']"),K=t.locator("label.chakra-checkbox .chakra-checkbox__control"),g=t.locator('button:has-text("Continue")');await y.fill(c),await S.fill(c),await K.click(),await g.click(),await t.locator(d.importExistingWalletButton).click(),await t.locator(d.privateKeyButton).click(),await g.scrollIntoViewIfNeeded(),await g.click(),await t.locator("textarea:not([disabled])").fill(o);let H=t.locator(d.findMyAccountButton);await H.click();let z=t.locator("button[type='submit'][data-loading]");if(await z.waitFor({state:"detached",timeout:25e3}),await t.getByRole("status").locator("div[id='toast-1-title']:has-text('No Account Found')").isVisible().catch(()=>!1)){let b=5,M=!1;for(;b>0;){if(console.info(`
6
+ Retrying search for account. ${b} attempts left`),await T(15e3),await H.click(),await z.waitFor({state:"detached",timeout:2e4}),await t.locator("div:has-text('Import Your Account')").nth(-2).locator("button").isVisible().catch(()=>!1)){M=!0;break}b-=1}if(!M)throw Error(O("redBright",["No Account Found","Account associated with the private key not found. Please make sure you are trying to import an account on the correct network(Mainnet/Testnet)."].join(`
7
+ `),{validateStream:!1}))}await t.locator("button:not([aria-label='Back'],[id^='menu-button']):has-text('Account')").click();let j=t.locator("section[role='dialog']").locator("button:has-text('Close')").first();if(await j.isVisible().then(()=>!0).catch(()=>!1)&&await j.click(),await P({page:t,newAccountName:r}),i&&i.length>0){for(let{privateKey:q,accountName:G,network:dt}of i)await F({page:t,privateKey:q,accountName:G,network:dt});await B(t);let b=t.locator(d.switchNetworkButton).last();await b.scrollIntoViewIfNeeded();let M=await b.textContent(),X=e.split("net")[0]?.toLowerCase()??"";M?.toLowerCase()!==X&&await L(t,e),await k(t,r)}await T(3e3),console.info(O("greenBright","\u2728 Meteor onboarding completed successfully"))}async function pt(t){await h(t),await t.locator(A.cancelButton).click()}var C=class extends x{page;constructor(o){super(),this.page=o}async onboard({network:o,privateKey:e,accountName:r,additionalAccounts:i}){await R({page:this.page,network:o,privateKey:e,accountName:r,additionalAccounts:i})}async unlock(){await h(this.page)}async lock(){await it(this.page)}async renameAccount({newAccountName:o}){await P({page:this.page,newAccountName:o})}async switchNetwork(o){await L(this.page,o)}async switchAccount(o){await k(this.page,o)}async getAccountAddress(){return await nt(this.page)}async addAccount({accountName:o,network:e,privateKey:r}){await F({page:this.page,accountName:o,network:e,privateKey:r})}async openSettings(){await B(this.page)}async connectToApp(o){await at(await this.promptPage(this.page.context()),o)}async confirmTransaction(){await rt(await this.promptPage(this.page.context()))}async rejectTransaction(){await pt(await this.promptPage(this.page.context()))}};import ut from"fs";import Mt from"path";import{test as vt,chromium as Et}from"@playwright/test";import{expect as Bt}from"@playwright/test";async function U(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}async function $(t,o){let e=await t.newPage();return await Bt(async()=>{await e.goto(o),await U(e)}).toPass(),e}async function V(t,o){let e=await o.newPage();for(let{origin:r,localStorage:i}of t){let c=e.mainFrame();await c.goto(r),await c.evaluate(u=>{u.forEach(({name:p,value:l})=>{window.localStorage.setItem(p,l)})},i)}await e.close()}import Ct from"fs/promises";async function mt(t){await Ct.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var St=35e3;async function D(t,o){try{await Promise.race([t.close(),new Promise((e,r)=>setTimeout(()=>r(new Error("Context close timed out")),St))])}catch(e){console.warn(`Browser context close did not complete cleanly: ${e.message}`)}try{await mt(o)}catch(e){console.error(`Failed to remove temporary context directory at ${o}. Error:`,e)}}var W,Tr=({slowMo:t=0,profileName:o}={})=>vt.extend({contextPath:async({browserName:e},r,i)=>{let c=await E(`${e}-${i.testId}`);await r(c)},context:async({context:e,contextPath:r},i)=>{let c=new x,u=f(c.name),p=await N(c.name),l=Mt.resolve(u,o??"wallet-data");if(!ut.existsSync(l))throw new Error("\u274C Cache for Meteor wallet data not found. Create it first");ut.cpSync(l,r,{recursive:!0,force:!0}),process.env.HEADLESS&&t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!");let s=await Et.launchPersistentContext(r,{headless:!1,args:[`--disable-extensions-except=${p}`,`--load-extension=${p}`],slowMo:process.env.HEADLESS?0:t});await s.grantPermissions(["clipboard-read"]);let{cookies:w,origins:y}=await e.storageState();w&&await s.addCookies(w),y&&y.length>0&&V(y,s);let S=await c.indexUrl();W=s.pages().find(g=>g.url().startsWith(S))||await $(s,S);for(let g of s.pages())g.url().includes("about:blank")&&await g.close();await W.bringToFront(),await h(W),await i(s),await D(s,r)},meteorPage:async({context:e},r)=>{await r(W)},meteor:async({context:e},r)=>{let i=new C(W);await r(i)}});import{test as Tt}from"@playwright/test";var Or=({slowMo:t,profileName:o}={})=>Tt.extend({workerScopeContents:[async({browser:e},r,i)=>{let{context:c,contextPath:u,walletPage:p}=await ot({workerInfo:i,profileName:o,slowMo:t,wallet:new x});await c.grantPermissions(["clipboard-read"]);for(let s of c.pages())s.url().includes("about:blank")&&await s.close();let l=new C(p);await l.unlock(),await r({wallet:l,walletPage:p,context:c}),await D(c,u)},{scope:"worker"}]});export{C as Meteor,Tr as meteorFixture,Or as meteorWorkerScopeFixture,ot as workerScopeContext};
@@ -1,6 +1,6 @@
1
- import { W as WalletProfileFixtureArgs, c as WorkerScopeFixtureArgs } from '../../types-B56pinWs.js';
2
- import { W as WorkerScopeFixture } from '../../worker-scope-context-DiN3_Sig.js';
3
- export { w as workerScopeContext } from '../../worker-scope-context-DiN3_Sig.js';
1
+ import { W as WalletProfileFixtureArgs } from '../../types-DK8rutb5.js';
2
+ import { W as WorkerScopeFixture } from '../../worker-scope-context-CNAfiliw.js';
3
+ export { w as workerScopeContext } from '../../worker-scope-context-CNAfiliw.js';
4
4
  import * as _playwright_test from '@playwright/test';
5
5
  import { Page, BrowserContext } from '@playwright/test';
6
6
 
@@ -153,6 +153,6 @@ declare class Petra extends PetraProfile {
153
153
 
154
154
  declare const petraFixture: ({ slowMo, profileName }?: WalletProfileFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & PetraFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
155
155
 
156
- declare const petraWorkerScopeFixture: ({ slowMo, profileName, dappUrl }?: WorkerScopeFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & PetraFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerScopeFixture<Petra>>;
156
+ declare const petraWorkerScopeFixture: ({ slowMo, profileName }?: WalletProfileFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & PetraFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerScopeFixture<Petra>>;
157
157
 
158
- export { Petra, WalletProfileFixtureArgs, WorkerScopeFixture, WorkerScopeFixtureArgs, petraFixture, petraWorkerScopeFixture };
158
+ export { Petra, WalletProfileFixtureArgs, WorkerScopeFixture, petraFixture, petraWorkerScopeFixture };
@@ -1,3 +1,3 @@
1
- import J from"fs";import yt from"path";import{chromium as gt}from"@playwright/test";import ft from"path";var G=".wallet-cache",X=".wallet-context";var j="13.22.0",W="https://github.com/amaify/chainwright/releases/download/v0.1.0/",Nt=`https://github.com/MetaMask/metamask-extension/releases/download/v${j}/metamask-chrome-${j}.zip`,Rt=`${W}solflare-wallet-extension-v2.19.1.zip`,Ut=`${W}petra-wallet-extension-v2.4.8.zip`,$t=`${W}phantom-wallet-extension-v26.10.0.zip`,Vt=`${W}meteor-wallet-extension-v0.7.0.zip`,Kt=`${W}keplr-wallet-extension-v0.13.3.zip`;async function I(t){return ft.resolve(process.cwd(),X,t)}import xt from"path";function h(t){return xt.resolve(process.cwd(),G,t)}import Z from"fs";import ht from"path";async function O(t){try{let o=h(t),e=ht.resolve(o,"extension-path.txt");if(!Z.existsSync(e))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let r=Z.readFileSync(e,"utf-8").trim();if(!r)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return r}catch(o){throw new Error(`\u274C Failed to get ${t} extension path: ${o.message}`)}}async function Y({wallet:t,workerInfo:o,profileName:e,slowMo:r}){let a=await I(o.workerIndex.toString()),n=h(t.name),s=yt.resolve(n,e??"wallet-data");if(!J.existsSync(s))throw new Error(`Cache for ${t.name} does not exist. Create it first!`);J.cpSync(s,a,{recursive:!0,force:!0});let l=await O(t.name),u=await gt.launchPersistentContext(a,{headless:!1,args:[`--disable-extensions-except=${l}`],slowMo:process.env.HEADLESS?0:r}),d=await t.indexUrl(),p=u.pages()[0];return p||(p=await u.newPage()),await p.goto(d),{context:u,walletPage:p,contextPath:a}}import Bt from"zod";var m={depositButton:"button:has-text('Deposit')",sendButton:"button:has-text('Send')",receiveButton:"button:has-text('Receive')",settingsMenu:"button[aria-label='Settings']",lockButton:"global-menu-lock",accountMenuButton:"button[data-part='trigger']",accountDialog:"div[role='dialog']",backButton:"button[id='back-button']"},$={networkSection:"a[href='/settings/network']",backButton:"button[id='back-button']"},V={passwordInput:"input[name='password']",unlockButton:"button:has-text('Unlock')"},y={accountOptionsMenuButton:"button[data-scope='popover']",editAccountButton:"button[aria-label='Edit account name']",renameAccountInput:"input[name='name']",saveButton:"button:has-text('Save')",cancelButton:"button:has-text('Cancel')",addAccountButton:"button:has-text('Add accounts')",addAccountWithPrivateKeyButton:"button:has-text('Import private key')",addAccountWithMnemonicButton:"button:has-text('Import mnemonic')"};var w={createWalletButton:"button:has-text('Create an account')",createSeedPhraseButton:"button:has-text('Create a seed phrase wallet')",createNewPasswordInput:"input[name='password']",confirmNewPasswordInput:"input[name='confirmPassword']",confirmPasswordCheckbox:"label>div[data-scope='checkbox']",continueButton:"button:has-text('Continue')",skipCopyRecoveryPhraseButton:"button:has-text('Skip')",getStartedButton:"button:has-text('Get started')",onboardingCompleteText:"h1:has-text('Your wallet is ready, you may close this window')",importWalletButton:"button:has-text('Import an account')",importUsingPrivateKeyButton:"button:has-text('Import private key')",importUsingMnemonicButton:"button:has-text('Import mnemonic')",importButton:"button:has-text('Import')",privateKeyInput:"input[name='privateKey']"};import{expect as F}from"@playwright/test";import Pt from"zod";async function k({page:t,newAccountName:o}){let e=Pt.string().min(1,"Account name cannot be an empty string").parse(o);await t.locator(m.settingsMenu).click(),await F(t.getByText("Settings").first()).toBeVisible();let a=t.locator(y.editAccountButton);await F(a).toBeVisible(),await a.click(),await F(t.getByText("Account name").first()).toBeVisible();let n=t.locator(y.renameAccountInput);if(await n.getAttribute("value")===e)throw Error(`The account to be renamed "${e}" already exists.`);await n.fill(e);let l=t.locator(y.saveButton);await F(l).toBeEnabled(),await l.click(),await F(t.getByText(e).first()).toBeVisible(),await t.locator(m.backButton).click(),await Promise.allSettled([t.locator(m.depositButton).waitFor({state:"visible",timeout:2e4}),t.locator(m.sendButton).waitFor({state:"visible",timeout:2e4})])}async function L({page:t,accountName:o,mode:e,...r}){let a=Bt.string().max(14,"For switching accounts reason, account name should not be longer than 14 characters. The reason for this is because the name will be truncated. Hence, it will be difficult to select the account.").parse(o);if(await t.locator(y.accountOptionsMenuButton).first().click(),await t.getByRole("dialog").locator(y.addAccountButton).click(),e==="privateKey"){let u="privateKey"in r?r.privateKey:"";if(await t.locator(y.addAccountWithPrivateKeyButton).click(),await t.locator(w.privateKeyInput).fill(u),await t.locator(w.importButton).click(),(await t.getByRole("status").locator("div[data-part='description']",{hasText:"Account already exists in wallet"}).textContent({timeout:3e3}).catch(()=>null))?.includes("Account already exists in wallet"))throw Error(`Account ${a} already exists in wallet`);await k({page:t,newAccountName:a})}if(e==="mnemonic"){let d=("mnemonicPhrase"in r?r.mnemonicPhrase:"").split(" ");await t.locator(y.addAccountWithMnemonicButton).click();for(let[g,v]of d.entries())await t.locator(`input[name="mnemonic-${String.fromCharCode(97+g)}"]`).fill(v);if(await t.locator(w.continueButton).click(),(await t.getByRole("status").locator("div[data-part='description']",{hasText:"Account already exists in wallet"}).textContent({timeout:3e3}).catch(()=>null))?.includes("Account already exists in wallet"))throw Error(`Account ${a} already exists in wallet`);await k({page:t,newAccountName:a})}}function N(t){return new Promise(o=>setTimeout(o,t))}var C={approveButton:'button:has-text("Approve")',cancelButton:'button:has-text("Cancel")'};var bt=/^[A-Z0-9]+(?:_[A-Z0-9]+)+$/;function q(t){return bt.test(t)?t.toLowerCase().replace(/_/g," ").replace(/\b[a-z]/g,o=>o.toUpperCase()):t}async function kt(t,o){for(;;){let r=o();if(r||t.isClosed())break;try{let a=t.locator("div:has(> h2:has-text('Simulation error'))");if(await a.isVisible().catch(()=>!1)){let s=await a.locator("p").textContent();throw new Error(`[Confirm Transaction Error]: ${q(s||"Unexpected error!")}`)}}catch(a){if(t.isClosed())break;throw a instanceof Error?a:new Error(`[Confirm Transaction Error]: ${a}`)}if(r||t.isClosed())break;await N(300)}}async function Q(t){let o=!1;kt(t,()=>o).catch(async a=>{t.isClosed()||console.error(a.message)}),await t.locator(C.approveButton).click(),o=!0}import{expect as At}from"@playwright/test";async function E(t,o){let e=t.locator(y.accountOptionsMenuButton).first();if((await e.textContent())?.split("Switch wallet")[1]?.split("0x")[0]?.toLowerCase().trim().includes(o.toLowerCase().trim())){console.info(`
2
- Switching to ${o} account aborted because the account is already selected.`);return}await e.click();let n=await t.getByRole("dialog").locator("> div > div > button[type='button']").all(),s=null;for(let l of n)if((await l.textContent())?.toLowerCase()?.trim().includes(o.toLowerCase().trim())){s=l;break}if(!s)throw new Error(`Account with name "${o}" not found.`);await s.click()}async function tt(t,o){o&&await E(t,o);let e=t.locator(C.approveButton);await At(e).toBeEnabled({timeout:2e4}),await e.click()}async function ot(t){return await t.getByRole("button",{name:"Copy Address",exact:!0}).click(),await t.evaluate(async()=>await navigator.clipboard.readText())}import{expect as et}from"@playwright/test";async function rt(t){let o=t.locator(m.settingsMenu);await et(o).toBeVisible(),await o.click(),await et(t.getByText("Settings").first()).toBeVisible()}async function at(t){await rt(t),await t.getByRole("button",{name:/lock wallet/i}).click(),await t.getByRole("heading",{name:/welcome/i}).waitFor({state:"visible",timeout:2e4})}import{styleText as lt}from"util";import{expect as b}from"@playwright/test";async function _(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}import nt from"fs";import St from"path";async function R(t){let o=h(t),e=St.resolve(o,"password.txt");try{if(!nt.existsSync(e))throw new Error("\u274C password.txt not found. Run setup script first.");return nt.readFileSync(e,"utf-8")}catch(r){throw new Error(`\u274C Failed to get ${t} password from cache: ${r.message}`)}}import{expect as Ct}from"@playwright/test";async function it({context:t,path:o,locator:e}){let r;try{await Ct.poll(async()=>(r=t.pages().filter(a=>a.url().startsWith("chrome-extension://")).find(a=>a.url().match(o)),!!r),{timeout:3e4}).toBe(!0)}catch{let a=t.pages().filter(n=>n.url().startsWith("chrome-extension://")).map(n=>n.url());throw new Error(`Popup page with path "${o}" not found in context after 30s. Pages in context: ${JSON.stringify(a)}`)}if(!r)throw new Error(`Popup page with path ${o} not found in context.`);return await Et(r,e),await r.setViewportSize({width:360,height:592}),r}async function Et(t,o){await t.waitForLoadState("load",{timeout:4e4}),await t.waitForLoadState("domcontentloaded",{timeout:4e4}),await t.locator(o).first().waitFor({state:"attached",timeout:4e4})}import ct from"fs";import Tt from"path";async function st(t){let o=h(t),e=Tt.resolve(o,"extension-id.txt");try{if(!ct.existsSync(e))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return ct.readFileSync(e,"utf-8")}catch(r){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${r.message}`)}}var P=class{name="petra";onboardingPath="/onboarding.html";async indexUrl(){return`chrome-extension://${await this.extensionId()}/index.html`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/prompt.html`}async extensionId(){return await st(this.name)}async promptPage(o){let e=await this.promptUrl();return await it({context:o,path:e,locator:"div[id='prompt']"})}};var T=3e4;async function K({page:t,...o}){console.info(lt("yellowBright",`
3
- Petra onboarding started...`,{validateStream:!1}));let e=new P,r=await R("petra"),a=t.locator(w.createWalletButton),n=t.locator(w.importWalletButton),s=t.locator(w.createNewPasswordInput),l=t.locator(w.confirmNewPasswordInput),u=t.locator(w.confirmPasswordCheckbox),d=t.locator(w.continueButton),p=t.locator(w.getStartedButton),x=t.locator(w.onboardingCompleteText);if(o.mode==="create"){let f=t.locator(w.createSeedPhraseButton);await a.click(),await f.click(),await s.fill(r),await l.fill(r),await u.click(),await d.click(),await t.locator(w.skipCopyRecoveryPhraseButton).click(),await p.click(),await b(x).toBeVisible({timeout:25e3}),await t.goto(await e.indexUrl()),await b(t.locator(m.depositButton)).toBeVisible({timeout:T}),await b(t.locator(m.sendButton)).toBeVisible({timeout:T})}if(o.mode==="importPrivateKey"){let{privateKey:f}=o,B=t.locator(w.importUsingPrivateKeyButton),S=t.locator(w.privateKeyInput),g=t.locator(w.importButton);await n.click(),await B.click(),await S.fill(f),await g.click(),await s.fill(r),await l.fill(r),await u.click(),await d.click(),await p.click(),await b(x).toBeVisible({timeout:25e3}),await t.goto(await e.indexUrl()),await _(t),await b(t.locator(m.depositButton)).toBeVisible({timeout:T}),await b(t.locator(m.sendButton)).toBeVisible({timeout:T})}if(o.mode==="importMnemonic"){let{secretRecoveryPhrase:f}=o,B=t.locator(w.importUsingMnemonicButton);await n.click(),await B.click();for(let[S,g]of f.split(" ").entries())await t.locator(`input[name="mnemonic-${String.fromCharCode(97+S)}"]`).fill(g);await d.click(),await s.fill(r),await l.fill(r),await u.click(),await d.click(),await p.click(),await b(x).toBeVisible({timeout:25e3}),await t.goto(await e.indexUrl()),await b(t.locator(m.depositButton)).toBeVisible({timeout:T}),await b(t.locator(m.sendButton)).toBeVisible({timeout:T})}if(await k({page:t,newAccountName:o.accountName}),o.additionalAccounts&&o.additionalAccounts.length>0){for(let{...f}of o.additionalAccounts)await L({page:t,...f});await E(t,o.accountName)}await N(1500),console.info(lt("greenBright","\u2728 Petra onboarding completed successfully",{validateStream:!1}))}import{expect as vt}from"@playwright/test";async function pt(t){let o=t.locator(C.cancelButton);await vt(o).toBeEnabled(),await o.click()}async function ut(t,o){await t.locator(m.settingsMenu).click(),await t.locator($.networkSection).click(),await t.locator(`div:has(> span:has-text("${o}"))`).first().click();let n=t.locator($.backButton);await n.click(),await n.click()}import{expect as mt}from"@playwright/test";async function M(t){let o=await R("petra"),e=t.locator(V.passwordInput);if(!await e.isVisible().then(()=>!0).catch(()=>!1)){console.info("\u{1F4A1} Wallet is already unlocked");return}await mt(e).toBeVisible({timeout:15e3}),await e.fill(o);let a=t.locator(V.unlockButton);await mt(a).toBeEnabled(),await a.click(),await Promise.allSettled([t.locator(m.sendButton).waitFor({state:"visible",timeout:2e4}),t.locator(m.receiveButton).waitFor({state:"visible",timeout:2e4})])}var A=class extends P{page;constructor(o){super(),this.page=o}async onboard(o){await K({page:this.page,...o})}async unlock(){await M(this.page)}async lock(){await at(this.page)}async renameAccount({newAccountName:o}){await k({page:this.page,newAccountName:o})}async switchNetwork(o){await ut(this.page,o)}async switchAccount(o){await E(this.page,o)}async getAccountAddress(){return await ot(this.page)}async addAccount({accountName:o,...e}){await L({page:this.page,accountName:o,...e})}async connectToApp(o){await tt(await this.promptPage(this.page.context()),o)}async confirmTransaction(){await Q(await this.promptPage(this.page.context()))}async rejectTransaction(){await pt(await this.promptPage(this.page.context()))}};import dt from"fs";import _t from"path";import{test as Mt,chromium as Dt}from"@playwright/test";import{expect as Wt}from"@playwright/test";async function z(t,o){let e=await t.newPage();return await Wt(async()=>{await e.goto(o),await _(e)}).toPass(),e}async function H(t,o){let e=await o.newPage();for(let{origin:r,localStorage:a}of t){let n=e.mainFrame();await n.goto(r),await n.evaluate(s=>{s.forEach(({name:l,value:u})=>{window.localStorage.setItem(l,u)})},a)}await e.close()}import It from"fs/promises";async function wt(t){await It.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var Ft=35e3;async function U(t,o){try{await Promise.race([t.close(),new Promise((e,r)=>setTimeout(()=>r(new Error("Context close timed out")),Ft))])}catch(e){console.warn(`Browser context close did not complete cleanly: ${e.message}`)}try{await wt(o)}catch(e){console.error(`Failed to remove temporary context directory at ${o}. Error:`,e)}}var D,Ir=({slowMo:t=0,profileName:o}={})=>Mt.extend({contextPath:async({browserName:e},r,a)=>{let n=await I(`${e}-${a.testId}`);await r(n)},context:async({context:e,contextPath:r},a)=>{let n=new P,s=h(n.name),l=await O(n.name),u=_t.resolve(s,o??"wallet-data");if(!dt.existsSync(u))throw new Error("\u274C Cache for Petra wallet data not found. Create it first");dt.cpSync(u,r,{recursive:!0,force:!0});let d=[`--disable-extensions-except=${l}`,`--load-extension=${l}`];process.env.HEADLESS&&(d.push("--headless=new"),t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!"));let p=await Dt.launchPersistentContext(r,{headless:!1,args:[`--disable-extensions-except=${l}`],slowMo:process.env.HEADLESS?0:t});await p.grantPermissions(["clipboard-read"]);let{cookies:x,origins:f}=await e.storageState();x&&await p.addCookies(x),f&&f.length>0&&H(f,p);let B=await n.indexUrl();D=p.pages().find(g=>g.url().startsWith(B))||await z(p,B);for(let g of p.pages()){let v=g.url();(v.includes("about:blank")||v.includes(n.onboardingPath))&&await g.close()}await D.bringToFront(),await M(D),await a(p),await U(p,r)},petraPage:async({context:e},r)=>{await r(D)},petra:async({context:e},r)=>{let a=new A(D);await r(a)}});import{test as Ot}from"@playwright/test";var Rr=({slowMo:t,profileName:o,dappUrl:e}={})=>Ot.extend({workerScopeContents:[async({browser:r},a,n)=>{let s=new P,{context:l,contextPath:u,walletPage:d}=await Y({wallet:s,workerInfo:n,profileName:o,slowMo:t});await l.grantPermissions(["clipboard-read"]);for(let x of l.pages())x.url().includes(s.onboardingPath)&&await x.close();let p=new A(d);await p.unlock(),await a({wallet:p,walletPage:d,context:l}),await U(l,u)},{scope:"worker"}],dappPage:[async({workerScopeContents:r},a)=>{let{context:n}=r,s=await n.newPage();e&&await s.goto(e),await a(s)},{scope:"worker"}],petraPage:async({workerScopeContents:r},a)=>{await a(r.walletPage)},petra:async({workerScopeContents:r},a)=>{let n=new A(r.walletPage);await a(n)}});export{A as Petra,Ir as petraFixture,Rr as petraWorkerScopeFixture,Y as workerScopeContext};
1
+ import J from"fs";import yt from"path";import{chromium as gt}from"@playwright/test";import ft from"path";var G=".wallet-cache",X=".wallet-context";var j="13.22.0",W="https://github.com/amaify/chainwright/releases/download/v0.1.0/",Nt=`https://github.com/MetaMask/metamask-extension/releases/download/v${j}/metamask-chrome-${j}.zip`,Rt=`${W}solflare-wallet-extension-v2.19.1.zip`,Ut=`${W}petra-wallet-extension-v2.4.8.zip`,$t=`${W}phantom-wallet-extension-v26.10.0.zip`,Vt=`${W}meteor-wallet-extension-v0.7.0.zip`,Kt=`${W}keplr-wallet-extension-v0.13.3.zip`;async function I(t){return ft.resolve(process.cwd(),X,t)}import xt from"path";function x(t){return xt.resolve(process.cwd(),G,t)}import Z from"fs";import ht from"path";async function O(t){try{let o=x(t),e=ht.resolve(o,"extension-path.txt");if(!Z.existsSync(e))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let r=Z.readFileSync(e,"utf-8").trim();if(!r)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return r}catch(o){throw new Error(`\u274C Failed to get ${t} extension path: ${o.message}`)}}async function Y({wallet:t,workerInfo:o,profileName:e,slowMo:r}){let a=await I(o.workerIndex.toString()),c=x(t.name),s=yt.resolve(c,e??"wallet-data");if(!J.existsSync(s))throw new Error(`Cache for ${t.name} does not exist. Create it first!`);J.cpSync(s,a,{recursive:!0,force:!0});let p=await O(t.name),u=await gt.launchPersistentContext(a,{headless:!1,args:[`--disable-extensions-except=${p}`],slowMo:process.env.HEADLESS?0:r}),d=await t.indexUrl(),l=u.pages()[0];return l||(l=await u.newPage()),await l.goto(d),{context:u,walletPage:l,contextPath:a}}import Bt from"zod";var m={depositButton:"button:has-text('Deposit')",sendButton:"button:has-text('Send')",receiveButton:"button:has-text('Receive')",settingsMenu:"button[aria-label='Settings']",lockButton:"global-menu-lock",accountMenuButton:"button[data-part='trigger']",accountDialog:"div[role='dialog']",backButton:"button[id='back-button']"},$={networkSection:"a[href='/settings/network']",backButton:"button[id='back-button']"},V={passwordInput:"input[name='password']",unlockButton:"button:has-text('Unlock')"},h={accountOptionsMenuButton:"button[data-scope='popover']",editAccountButton:"button[aria-label='Edit account name']",renameAccountInput:"input[name='name']",saveButton:"button:has-text('Save')",cancelButton:"button:has-text('Cancel')",addAccountButton:"button:has-text('Add accounts')",addAccountWithPrivateKeyButton:"button:has-text('Import private key')",addAccountWithMnemonicButton:"button:has-text('Import mnemonic')"};var w={createWalletButton:"button:has-text('Create an account')",createSeedPhraseButton:"button:has-text('Create a seed phrase wallet')",createNewPasswordInput:"input[name='password']",confirmNewPasswordInput:"input[name='confirmPassword']",confirmPasswordCheckbox:"label>div[data-scope='checkbox']",continueButton:"button:has-text('Continue')",skipCopyRecoveryPhraseButton:"button:has-text('Skip')",getStartedButton:"button:has-text('Get started')",onboardingCompleteText:"h1:has-text('Your wallet is ready, you may close this window')",importWalletButton:"button:has-text('Import an account')",importUsingPrivateKeyButton:"button:has-text('Import private key')",importUsingMnemonicButton:"button:has-text('Import mnemonic')",importButton:"button:has-text('Import')",privateKeyInput:"input[name='privateKey']"};import{expect as _}from"@playwright/test";import Pt from"zod";async function A({page:t,newAccountName:o}){let e=Pt.string().min(1,"Account name cannot be an empty string").parse(o);await t.locator(m.settingsMenu).click(),await _(t.getByText("Settings").first()).toBeVisible();let a=t.locator(h.editAccountButton);await _(a).toBeVisible(),await a.click(),await _(t.getByText("Account name").first()).toBeVisible();let c=t.locator(h.renameAccountInput);if(await c.getAttribute("value")===e)throw Error(`The account to be renamed "${e}" already exists.`);await c.fill(e);let p=t.locator(h.saveButton);await _(p).toBeEnabled(),await p.click(),await _(t.getByText(e).first()).toBeVisible(),await t.locator(m.backButton).click(),await Promise.allSettled([t.locator(m.depositButton).waitFor({state:"visible",timeout:2e4}),t.locator(m.sendButton).waitFor({state:"visible",timeout:2e4})])}async function L({page:t,accountName:o,mode:e,...r}){let a=Bt.string().max(14,"For switching accounts reason, account name should not be longer than 14 characters. The reason for this is because the name will be truncated. Hence, it will be difficult to select the account.").parse(o);if(await t.locator(h.accountOptionsMenuButton).first().click(),await t.getByRole("dialog").locator(h.addAccountButton).click(),e==="privateKey"){let u="privateKey"in r?r.privateKey:"";if(await t.locator(h.addAccountWithPrivateKeyButton).click(),await t.locator(w.privateKeyInput).fill(u),await t.locator(w.importButton).click(),(await t.getByRole("status").locator("div[data-part='description']",{hasText:"Account already exists in wallet"}).textContent({timeout:3e3}).catch(()=>null))?.includes("Account already exists in wallet"))throw Error(`Account ${a} already exists in wallet`);await A({page:t,newAccountName:a})}if(e==="mnemonic"){let d=("mnemonicPhrase"in r?r.mnemonicPhrase:"").split(" ");await t.locator(h.addAccountWithMnemonicButton).click();for(let[y,v]of d.entries())await t.locator(`input[name="mnemonic-${String.fromCharCode(97+y)}"]`).fill(v);if(await t.locator(w.continueButton).click(),(await t.getByRole("status").locator("div[data-part='description']",{hasText:"Account already exists in wallet"}).textContent({timeout:3e3}).catch(()=>null))?.includes("Account already exists in wallet"))throw Error(`Account ${a} already exists in wallet`);await A({page:t,newAccountName:a})}}function N(t){return new Promise(o=>setTimeout(o,t))}var S={approveButton:'button:has-text("Approve")',cancelButton:'button:has-text("Cancel")'};var bt=/^[A-Z0-9]+(?:_[A-Z0-9]+)+$/;function q(t){return bt.test(t)?t.toLowerCase().replace(/_/g," ").replace(/\b[a-z]/g,o=>o.toUpperCase()):t}async function At(t,o){for(;;){let r=o();if(r||t.isClosed())break;try{let a=t.locator("div:has(> h2:has-text('Simulation error'))");if(await a.isVisible().catch(()=>!1)){let s=await a.locator("p").textContent();throw new Error(`[Confirm Transaction Error]: ${q(s||"Unexpected error!")}`)}}catch(a){if(t.isClosed())break;throw a instanceof Error?a:new Error(`[Confirm Transaction Error]: ${a}`)}if(r||t.isClosed())break;await N(300)}}async function Q(t){let o=!1;At(t,()=>o).catch(async a=>{t.isClosed()||console.error(a.message)}),await t.locator(S.approveButton).click(),o=!0}import{expect as kt}from"@playwright/test";async function C(t,o){let e=t.locator(h.accountOptionsMenuButton).first();if((await e.textContent())?.split("Switch wallet")[1]?.split("0x")[0]?.toLowerCase().trim().includes(o.toLowerCase().trim())){console.info(`
2
+ Switching to ${o} account aborted because the account is already selected.`);return}await e.click();let c=await t.getByRole("dialog").locator("> div > div > button[type='button']").all(),s=null;for(let p of c)if((await p.textContent())?.toLowerCase()?.trim().includes(o.toLowerCase().trim())){s=p;break}if(!s)throw new Error(`Account with name "${o}" not found.`);await s.click()}async function tt(t,o){o&&await C(t,o);let e=t.locator(S.approveButton);await kt(e).toBeEnabled({timeout:2e4}),await e.click()}async function ot(t){return await t.getByRole("button",{name:"Copy Address",exact:!0}).click(),await t.evaluate(async()=>await navigator.clipboard.readText())}import{expect as et}from"@playwright/test";async function rt(t){let o=t.locator(m.settingsMenu);await et(o).toBeVisible(),await o.click(),await et(t.getByText("Settings").first()).toBeVisible()}async function at(t){await rt(t),await t.getByRole("button",{name:/lock wallet/i}).click(),await t.getByRole("heading",{name:/welcome/i}).waitFor({state:"visible",timeout:2e4})}import{styleText as lt}from"util";import{expect as B}from"@playwright/test";async function F(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}import nt from"fs";import St from"path";async function R(t){let o=x(t),e=St.resolve(o,"password.txt");try{if(!nt.existsSync(e))throw new Error("\u274C password.txt not found. Run setup script first.");return nt.readFileSync(e,"utf-8")}catch(r){throw new Error(`\u274C Failed to get ${t} password from cache: ${r.message}`)}}import{expect as Ct}from"@playwright/test";async function it({context:t,path:o,locator:e}){let r;try{await Ct.poll(async()=>(r=t.pages().filter(a=>a.url().startsWith("chrome-extension://")).find(a=>a.url().match(o)),!!r),{timeout:3e4}).toBe(!0)}catch{let a=t.pages().filter(c=>c.url().startsWith("chrome-extension://")).map(c=>c.url());throw new Error(`Popup page with path "${o}" not found in context after 30s. Pages in context: ${JSON.stringify(a)}`)}if(!r)throw new Error(`Popup page with path ${o} not found in context.`);return await Et(r,e),await r.setViewportSize({width:360,height:592}),r}async function Et(t,o){await t.waitForLoadState("load",{timeout:4e4}),await t.waitForLoadState("domcontentloaded",{timeout:4e4}),await t.locator(o).first().waitFor({state:"attached",timeout:4e4})}import ct from"fs";import Tt from"path";async function st(t){let o=x(t),e=Tt.resolve(o,"extension-id.txt");try{if(!ct.existsSync(e))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return ct.readFileSync(e,"utf-8")}catch(r){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${r.message}`)}}var g=class{name="petra";onboardingPath="/onboarding.html";async indexUrl(){return`chrome-extension://${await this.extensionId()}/index.html`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/prompt.html`}async extensionId(){return await st(this.name)}async promptPage(o){let e=await this.promptUrl();return await it({context:o,path:e,locator:"div[id='prompt']"})}};var E=3e4;async function K({page:t,...o}){console.info(lt("yellowBright",`
3
+ Petra onboarding started...`,{validateStream:!1}));let e=new g,r=await R("petra"),a=t.locator(w.createWalletButton),c=t.locator(w.importWalletButton),s=t.locator(w.createNewPasswordInput),p=t.locator(w.confirmNewPasswordInput),u=t.locator(w.confirmPasswordCheckbox),d=t.locator(w.continueButton),l=t.locator(w.getStartedButton),b=t.locator(w.onboardingCompleteText);if(o.mode==="create"){let f=t.locator(w.createSeedPhraseButton);await a.click(),await f.click(),await s.fill(r),await p.fill(r),await u.click(),await d.click(),await t.locator(w.skipCopyRecoveryPhraseButton).click(),await l.click(),await B(b).toBeVisible({timeout:25e3}),await t.goto(await e.indexUrl()),await B(t.locator(m.depositButton)).toBeVisible({timeout:E}),await B(t.locator(m.sendButton)).toBeVisible({timeout:E})}if(o.mode==="importPrivateKey"){let{privateKey:f}=o,P=t.locator(w.importUsingPrivateKeyButton),k=t.locator(w.privateKeyInput),y=t.locator(w.importButton);await c.click(),await P.click(),await k.fill(f),await y.click(),await s.fill(r),await p.fill(r),await u.click(),await d.click(),await l.click(),await B(b).toBeVisible({timeout:25e3}),await t.goto(await e.indexUrl()),await F(t),await B(t.locator(m.depositButton)).toBeVisible({timeout:E}),await B(t.locator(m.sendButton)).toBeVisible({timeout:E})}if(o.mode==="importMnemonic"){let{secretRecoveryPhrase:f}=o,P=t.locator(w.importUsingMnemonicButton);await c.click(),await P.click();for(let[k,y]of f.split(" ").entries())await t.locator(`input[name="mnemonic-${String.fromCharCode(97+k)}"]`).fill(y);await d.click(),await s.fill(r),await p.fill(r),await u.click(),await d.click(),await l.click(),await B(b).toBeVisible({timeout:25e3}),await t.goto(await e.indexUrl()),await B(t.locator(m.depositButton)).toBeVisible({timeout:E}),await B(t.locator(m.sendButton)).toBeVisible({timeout:E})}if(await A({page:t,newAccountName:o.accountName}),o.additionalAccounts&&o.additionalAccounts.length>0){for(let{...f}of o.additionalAccounts)await L({page:t,...f});await C(t,o.accountName)}await N(1500),console.info(lt("greenBright","\u2728 Petra onboarding completed successfully",{validateStream:!1}))}import{expect as vt}from"@playwright/test";async function pt(t){let o=t.locator(S.cancelButton);await vt(o).toBeEnabled(),await o.click()}async function ut(t,o){await t.locator(m.settingsMenu).click(),await t.locator($.networkSection).click(),await t.locator(`div:has(> span:has-text("${o}"))`).first().click();let c=t.locator($.backButton);await c.click(),await c.click()}import{expect as mt}from"@playwright/test";async function M(t){let o=await R("petra"),e=t.locator(V.passwordInput);if(!await e.isVisible().then(()=>!0).catch(()=>!1)){console.info("\u{1F4A1} Wallet is already unlocked");return}await mt(e).toBeVisible({timeout:15e3}),await e.fill(o);let a=t.locator(V.unlockButton);await mt(a).toBeEnabled(),await a.click(),await Promise.allSettled([t.locator(m.sendButton).waitFor({state:"visible",timeout:2e4}),t.locator(m.receiveButton).waitFor({state:"visible",timeout:2e4})])}var T=class extends g{page;constructor(o){super(),this.page=o}async onboard(o){await K({page:this.page,...o})}async unlock(){await M(this.page)}async lock(){await at(this.page)}async renameAccount({newAccountName:o}){await A({page:this.page,newAccountName:o})}async switchNetwork(o){await ut(this.page,o)}async switchAccount(o){await C(this.page,o)}async getAccountAddress(){return await ot(this.page)}async addAccount({accountName:o,...e}){await L({page:this.page,accountName:o,...e})}async connectToApp(o){await tt(await this.promptPage(this.page.context()),o)}async confirmTransaction(){await Q(await this.promptPage(this.page.context()))}async rejectTransaction(){await pt(await this.promptPage(this.page.context()))}};import dt from"fs";import Ft from"path";import{test as Mt,chromium as Dt}from"@playwright/test";import{expect as Wt}from"@playwright/test";async function z(t,o){let e=await t.newPage();return await Wt(async()=>{await e.goto(o),await F(e)}).toPass(),e}async function H(t,o){let e=await o.newPage();for(let{origin:r,localStorage:a}of t){let c=e.mainFrame();await c.goto(r),await c.evaluate(s=>{s.forEach(({name:p,value:u})=>{window.localStorage.setItem(p,u)})},a)}await e.close()}import It from"fs/promises";async function wt(t){await It.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var _t=35e3;async function U(t,o){try{await Promise.race([t.close(),new Promise((e,r)=>setTimeout(()=>r(new Error("Context close timed out")),_t))])}catch(e){console.warn(`Browser context close did not complete cleanly: ${e.message}`)}try{await wt(o)}catch(e){console.error(`Failed to remove temporary context directory at ${o}. Error:`,e)}}var D,Ir=({slowMo:t=0,profileName:o}={})=>Mt.extend({contextPath:async({browserName:e},r,a)=>{let c=await I(`${e}-${a.testId}`);await r(c)},context:async({context:e,contextPath:r},a)=>{let c=new g,s=x(c.name),p=await O(c.name),u=Ft.resolve(s,o??"wallet-data");if(!dt.existsSync(u))throw new Error("\u274C Cache for Petra wallet data not found. Create it first");dt.cpSync(u,r,{recursive:!0,force:!0});let d=[`--disable-extensions-except=${p}`,`--load-extension=${p}`];process.env.HEADLESS&&(d.push("--headless=new"),t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!"));let l=await Dt.launchPersistentContext(r,{headless:!1,args:[`--disable-extensions-except=${p}`],slowMo:process.env.HEADLESS?0:t});await l.grantPermissions(["clipboard-read"]);let{cookies:b,origins:f}=await e.storageState();b&&await l.addCookies(b),f&&f.length>0&&H(f,l);let P=await c.indexUrl();D=l.pages().find(y=>y.url().startsWith(P))||await z(l,P);for(let y of l.pages()){let v=y.url();(v.includes("about:blank")||v.includes(c.onboardingPath))&&await y.close()}await D.bringToFront(),await M(D),await a(l),await U(l,r)},petraPage:async({context:e},r)=>{await r(D)},petra:async({context:e},r)=>{let a=new T(D);await r(a)}});import{test as Ot}from"@playwright/test";var Rr=({slowMo:t,profileName:o}={})=>Ot.extend({workerScopeContents:[async({browser:e},r,a)=>{let c=new g,{context:s,contextPath:p,walletPage:u}=await Y({wallet:c,workerInfo:a,profileName:o,slowMo:t});await s.grantPermissions(["clipboard-read"]);for(let l of s.pages())l.url().includes(c.onboardingPath)&&await l.close();let d=new T(u);await d.unlock(),await r({wallet:d,walletPage:u,context:s}),await U(s,p)},{scope:"worker"}]});export{T as Petra,Ir as petraFixture,Rr as petraWorkerScopeFixture,Y as workerScopeContext};
@@ -1,6 +1,6 @@
1
- import { W as WalletProfileFixtureArgs, c as WorkerScopeFixtureArgs } from '../../types-B56pinWs.js';
2
- import { W as WorkerScopeFixture } from '../../worker-scope-context-DiN3_Sig.js';
3
- export { w as workerScopeContext } from '../../worker-scope-context-DiN3_Sig.js';
1
+ import { W as WalletProfileFixtureArgs } from '../../types-DK8rutb5.js';
2
+ import { W as WorkerScopeFixture } from '../../worker-scope-context-CNAfiliw.js';
3
+ export { w as workerScopeContext } from '../../worker-scope-context-CNAfiliw.js';
4
4
  import * as _playwright_test from '@playwright/test';
5
5
  import { BrowserContext, Page } from '@playwright/test';
6
6
 
@@ -191,6 +191,6 @@ declare class Phantom extends PhantomProfile {
191
191
 
192
192
  declare const phantomFixture: ({ slowMo, profileName }?: WalletProfileFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & PhantomFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
193
193
 
194
- declare const phantomWorkerScopeFixture: ({ slowMo, profileName, dappUrl }?: WorkerScopeFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & PhantomFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerScopeFixture<Phantom>>;
194
+ declare const phantomWorkerScopeFixture: ({ slowMo, profileName }?: WalletProfileFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & PhantomFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerScopeFixture<Phantom>>;
195
195
 
196
- export { Phantom, WalletProfileFixtureArgs, WorkerScopeFixture, WorkerScopeFixtureArgs, phantomFixture, phantomWorkerScopeFixture };
196
+ export { Phantom, WalletProfileFixtureArgs, WorkerScopeFixture, phantomFixture, phantomWorkerScopeFixture };
@@ -1,3 +1,3 @@
1
- import ot from"fs";import Ct from"path";import{chromium as At}from"@playwright/test";import Bt from"path";var Z=".wallet-cache",tt=".wallet-context";var Y="13.22.0",N="https://github.com/amaify/chainwright/releases/download/v0.1.0/",zt=`https://github.com/MetaMask/metamask-extension/releases/download/v${Y}/metamask-chrome-${Y}.zip`,jt=`${N}solflare-wallet-extension-v2.19.1.zip`,Xt=`${N}petra-wallet-extension-v2.4.8.zip`,Jt=`${N}phantom-wallet-extension-v26.10.0.zip`,qt=`${N}meteor-wallet-extension-v0.7.0.zip`,Qt=`${N}keplr-wallet-extension-v0.13.3.zip`;async function T(t){return Bt.resolve(process.cwd(),tt,t)}import Pt from"path";function x(t){return Pt.resolve(process.cwd(),Z,t)}import et from"fs";import kt from"path";async function S(t){try{let e=x(t),o=kt.resolve(e,"extension-path.txt");if(!et.existsSync(o))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let a=et.readFileSync(o,"utf-8").trim();if(!a)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return a}catch(e){throw new Error(`\u274C Failed to get ${t} extension path: ${e.message}`)}}async function xe({wallet:t,workerInfo:e,profileName:o,slowMo:a}){let n=await T(e.workerIndex.toString()),r=x(t.name),l=Ct.resolve(r,o??"wallet-data");if(!ot.existsSync(l))throw new Error(`Cache for ${t.name} does not exist. Create it first!`);ot.cpSync(l,n,{recursive:!0,force:!0});let i=await S(t.name),m=await At.launchPersistentContext(n,{headless:!1,args:[`--disable-extensions-except=${i}`],slowMo:process.env.HEADLESS?0:a}),u=await t.indexUrl(),f=m.pages()[0];return f||(f=await m.newPage()),await f.goto(u),{context:m,walletPage:f,contextPath:n}}var h={openMenuButton:"settings-menu-open-button",settingsButton:"sidebar_menu-button-settings",addAccountButton:"sidebar_menu-button-add_account",unlockWalletButton:"unlock-form-submit-button",manageAccountsButton:"sidebar_menu-button-manage_accounts",homeHeaderAccountName:"home-header-account-name"},B={lockWalletButton:"lock-menu-item",closeMenuButton:"settings-menu-close-button",developerSettingsButton:"settings-item-developer-settings",activeNetworksButton:"settings-item-active-networks"},at={accountProfileContainer:"sortable-account-container"};var p={createNewWalletButton:"button:has-text('Create a new wallet')",IAlreadyHaveAWalletButton:"button:has-text('I already have a wallet')",importRecoveryPhraseButton:"button:has-text('Import Recovery Phrase')",importPrivateKeyButton:"button:has-text('Import Private Key')",createSeedPhraseWalletButton:"create-manual-seed-phrase",passwordInput:"onboarding-form-password-input",passwordConfirmInput:"onboarding-form-confirm-password-input",termsCheckBox:"onboarding-form-terms-of-service-checkbox",continueButton:"button:has-text('Continue')",importWalletButton:"button:has-text('Import Wallet')",getStartedButton:"button:has-text('Get Started')",recoveryPhraseSavedCheckbox:"onboarding-form-saved-secret-recovery-phrase-checkbox",recoveryPhraseInput:"secret-recovery-phrase-word-input"};async function D({page:t,privateKey:e,accountName:o,chain:a}){await t.getByTestId(h.openMenuButton).click(),await t.getByTestId(h.addAccountButton).click(),await t.locator(p.importPrivateKeyButton).click();let i=t.locator("span[id^='button--listbox-input--']"),m=await i.textContent(),u=t.locator("input[name='name']"),f=t.locator("textarea[name='privateKey']");m!==a&&(await i.click(),await t.locator("ul[id^='listbox--listbox-input--']").locator(`li[data-label='${a}']`).click()),await u.fill(o),await f.fill(e),await t.locator("button:has-text('Import')").click()}var v={confirmButton:"primary-button",cancelButton:"secondary-button"};async function nt(t){let e=t.getByTestId(v.confirmButton);await t.getByTestId("approve-transaction").waitFor({state:"attached"});let a=t.getByRole("button",{name:"Confirm anyway",exact:!0});if(await a.isVisible().catch(()=>!1)){await a.click();return}await e.click()}import{expect as Tt}from"@playwright/test";import bt from"zod";async function E(t,e){let o=bt.string().min(1,"Account name cannot be an empty string").parse(e);await t.getByTestId(h.openMenuButton).click();let n=null,r=await t.locator("div[data-testid='account-menu'] div[data-testid='tooltip_interactive-wrapper']").all();for(let l of r)if((await l.textContent())?.includes(o)){n=l;break}if(!n)throw new Error(`Account with name "${o}" not found in the account list.`);await n.click()}async function rt(t,e){e&&await E(t,e);let o=t.getByTestId(v.confirmButton);await Tt(o).toBeEnabled({timeout:15e3}),await o.click()}import It from"zod";var St=t=>t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");async function it({page:t,accountName:e,chain:o}){let a=It.string().min(1,"Account name cannot be an empty string").parse(e);await t.getByTestId(h.openMenuButton).click(),await t.getByTestId(h.manageAccountsButton).click(),await t.getByTestId(`manage-accounts-sortable-${a}`).click();let i=t.getByRole("button",{name:/Account Address(?:es)?/i});await i.waitFor({state:"visible",timeout:2e4});let u=await i.locator("div[data-name='row.pair'] > div").last().textContent();if(u&&Number(u)===1){await i.locator("> div > div").last().click(),await t.getByTestId("header--back").click();let y=t.getByTestId(B.closeMenuButton);await y.waitFor({state:"visible",timeout:15e3}),await y.click()}else{await i.click();let d=new RegExp(`${St(o.network)}`,"i");await t.getByRole("button",{name:d}).locator("> div").last().locator("> div").last().locator("div > button").last().click(),await t.getByRole("button",{name:"Close",exact:!0}).last().click();let C=t.getByTestId("header--back");await C.waitFor({state:"visible",timeout:15e3}),await C.click();let b=t.getByTestId(B.closeMenuButton);await b.waitFor({state:"visible",timeout:15e3}),await b.click()}return await t.evaluate(async()=>await navigator.clipboard.readText())}async function ct(t){await t.getByTestId(h.openMenuButton).click(),await t.getByTestId(h.settingsButton).click(),await t.getByTestId(B.lockWalletButton).click()}import{styleText as pt}from"util";import{expect as Nt}from"@playwright/test";function _(t){return new Promise(e=>setTimeout(e,t))}import st from"fs";import vt from"path";async function R(t){let e=x(t),o=vt.resolve(e,"password.txt");try{if(!st.existsSync(o))throw new Error("\u274C password.txt not found. Run setup script first.");return st.readFileSync(o,"utf-8")}catch(a){throw new Error(`\u274C Failed to get ${t} password from cache: ${a.message}`)}}import{expect as Et}from"@playwright/test";async function lt({context:t,path:e,locator:o}){let a;try{await Et.poll(async()=>(a=t.pages().filter(n=>n.url().startsWith("chrome-extension://")).find(n=>n.url().match(e)),!!a),{timeout:3e4}).toBe(!0)}catch{let n=t.pages().filter(r=>r.url().startsWith("chrome-extension://")).map(r=>r.url());throw new Error(`Popup page with path "${e}" not found in context after 30s. Pages in context: ${JSON.stringify(n)}`)}if(!a)throw new Error(`Popup page with path ${e} not found in context.`);return await Wt(a,o),await a.setViewportSize({width:360,height:592}),a}async function Wt(t,e){await t.waitForLoadState("load",{timeout:4e4}),await t.waitForLoadState("domcontentloaded",{timeout:4e4}),await t.locator(e).first().waitFor({state:"attached",timeout:4e4})}import ut from"fs";import Ft from"path";async function mt(t){let e=x(t),o=Ft.resolve(e,"extension-id.txt");try{if(!ut.existsSync(o))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return ut.readFileSync(o,"utf-8")}catch(a){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${a.message}`)}}var k=class{name="phantom";onboardingPath="/onboarding.html";async indexUrl(){return`chrome-extension://${await this.extensionId()}/popup.html`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/notification.html`}async extensionId(){return await mt(this.name)}async promptPage(e){let o=await this.promptUrl();return await lt({context:e,path:o,locator:"div[id='root']"})}};async function W(t,e){let a=!1;for(;!e();){let n=e();if(n||a||t.isClosed())break;try{let r=t.locator("div[id='modal']").locator("div > svg").first();await r.isVisible().catch(()=>!1)&&(await r.click(),a=!0)}catch(r){if(t.isClosed())break;console.error("[autoClosePhantomNotification]: ",r)}if(n||a||t.isClosed())break;await _(300)}}async function $({page:t,currentAccountName:e,newAccountName:o}){await t.getByTestId(h.openMenuButton).click(),await t.getByTestId(h.manageAccountsButton).click();let l=await t.getByTestId(at.accountProfileContainer).locator("div[data-testid^='manage-accounts-sortable'] div > p").all(),i=null;for(let g of l)if((await g.textContent())?.toLowerCase()===e.toLowerCase()){i=g;break}if(!i)throw new Error(`Account with name "${e}" not found`);await i.click(),await t.locator("button:has-text('Account Name')").click();let u=t.locator("input[name='name']");await u.clear(),await u.fill(o),await t.getByTestId("primary-button").click(),await t.getByTestId("header--back").click(),await t.getByTestId(B.closeMenuButton).click()}async function U(t){await t.getByTestId(h.openMenuButton).click(),await t.getByTestId(h.settingsButton).click()}async function H({page:t,...e}){await U(t);let o=t.locator(`button[id='${B.developerSettingsButton}']`);await o.scrollIntoViewIfNeeded(),await o.click();let a=t.getByTestId("toggleTestNetwork"),r=await a.locator("label[data-testid='toggleTestNetwork-switch'] > input[aria-label='Toggle']").isChecked().catch(()=>!1);if(!r&&e.mode==="on"&&await a.click(),r&&e.mode==="off"){await a.click(),await t.getByTestId("header--back").click(),await t.getByTestId(B.closeMenuButton).click();return}if(e.mode==="on"&&e.chain==="Solana"){let{network:m}=e;await t.locator(`button:has-text("${m}")`).click()}if(e.mode==="on"&&e.chain==="Ethereum"){let{network:m}=e;if(!await t.getByText("EVM",{exact:!0}).isVisible().catch(()=>!1))throw new Error(["EVM testnet options are not available. Please ensure Ethereum is enabled in optional chains.","To enable Ethereum, call the 'toggleOptionalChain' action before switching the network.","toggleOptionalChain({ page: page, toggleMode: 'on', supportedChains: ['Ethereum'] })","Tip: For persistence, enable Ethereum in your setup file after the onboarding step completes."].join(`
1
+ import ot from"fs";import Ct from"path";import{chromium as At}from"@playwright/test";import Bt from"path";var Z=".wallet-cache",tt=".wallet-context";var Y="13.22.0",N="https://github.com/amaify/chainwright/releases/download/v0.1.0/",zt=`https://github.com/MetaMask/metamask-extension/releases/download/v${Y}/metamask-chrome-${Y}.zip`,jt=`${N}solflare-wallet-extension-v2.19.1.zip`,Xt=`${N}petra-wallet-extension-v2.4.8.zip`,Jt=`${N}phantom-wallet-extension-v26.10.0.zip`,qt=`${N}meteor-wallet-extension-v0.7.0.zip`,Qt=`${N}keplr-wallet-extension-v0.13.3.zip`;async function T(t){return Bt.resolve(process.cwd(),tt,t)}import Pt from"path";function x(t){return Pt.resolve(process.cwd(),Z,t)}import et from"fs";import kt from"path";async function I(t){try{let e=x(t),o=kt.resolve(e,"extension-path.txt");if(!et.existsSync(o))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let a=et.readFileSync(o,"utf-8").trim();if(!a)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return a}catch(e){throw new Error(`\u274C Failed to get ${t} extension path: ${e.message}`)}}async function xe({wallet:t,workerInfo:e,profileName:o,slowMo:a}){let n=await T(e.workerIndex.toString()),r=x(t.name),u=Ct.resolve(r,o??"wallet-data");if(!ot.existsSync(u))throw new Error(`Cache for ${t.name} does not exist. Create it first!`);ot.cpSync(u,n,{recursive:!0,force:!0});let i=await I(t.name),m=await At.launchPersistentContext(n,{headless:!1,args:[`--disable-extensions-except=${i}`],slowMo:process.env.HEADLESS?0:a}),l=await t.indexUrl(),h=m.pages()[0];return h||(h=await m.newPage()),await h.goto(l),{context:m,walletPage:h,contextPath:n}}var g={openMenuButton:"settings-menu-open-button",settingsButton:"sidebar_menu-button-settings",addAccountButton:"sidebar_menu-button-add_account",unlockWalletButton:"unlock-form-submit-button",manageAccountsButton:"sidebar_menu-button-manage_accounts",homeHeaderAccountName:"home-header-account-name"},B={lockWalletButton:"lock-menu-item",closeMenuButton:"settings-menu-close-button",developerSettingsButton:"settings-item-developer-settings",activeNetworksButton:"settings-item-active-networks"},at={accountProfileContainer:"sortable-account-container"};var p={createNewWalletButton:"button:has-text('Create a new wallet')",IAlreadyHaveAWalletButton:"button:has-text('I already have a wallet')",importRecoveryPhraseButton:"button:has-text('Import Recovery Phrase')",importPrivateKeyButton:"button:has-text('Import Private Key')",createSeedPhraseWalletButton:"create-manual-seed-phrase",passwordInput:"onboarding-form-password-input",passwordConfirmInput:"onboarding-form-confirm-password-input",termsCheckBox:"onboarding-form-terms-of-service-checkbox",continueButton:"button:has-text('Continue')",importWalletButton:"button:has-text('Import Wallet')",getStartedButton:"button:has-text('Get Started')",recoveryPhraseSavedCheckbox:"onboarding-form-saved-secret-recovery-phrase-checkbox",recoveryPhraseInput:"secret-recovery-phrase-word-input"};async function D({page:t,privateKey:e,accountName:o,chain:a}){await t.getByTestId(g.openMenuButton).click(),await t.getByTestId(g.addAccountButton).click(),await t.locator(p.importPrivateKeyButton).click();let i=t.locator("span[id^='button--listbox-input--']"),m=await i.textContent(),l=t.locator("input[name='name']"),h=t.locator("textarea[name='privateKey']");m!==a&&(await i.click(),await t.locator("ul[id^='listbox--listbox-input--']").locator(`li[data-label='${a}']`).click()),await l.fill(o),await h.fill(e),await t.locator("button:has-text('Import')").click()}var S={confirmButton:"primary-button",cancelButton:"secondary-button"};async function nt(t){let e=t.getByTestId(S.confirmButton);await t.getByTestId("approve-transaction").waitFor({state:"attached"});let a=t.getByRole("button",{name:"Confirm anyway",exact:!0});if(await a.isVisible().catch(()=>!1)){await a.click();return}await e.click()}import{expect as Tt}from"@playwright/test";import bt from"zod";async function v(t,e){let o=bt.string().min(1,"Account name cannot be an empty string").parse(e);await t.getByTestId(g.openMenuButton).click();let n=null,r=await t.locator("div[data-testid='account-menu'] div[data-testid='tooltip_interactive-wrapper']").all();for(let u of r)if((await u.textContent())?.includes(o)){n=u;break}if(!n)throw new Error(`Account with name "${o}" not found in the account list.`);await n.click()}async function rt(t,e){e&&await v(t,e);let o=t.getByTestId(S.confirmButton);await Tt(o).toBeEnabled({timeout:15e3}),await o.click()}import It from"zod";var St=t=>t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");async function it({page:t,accountName:e,chain:o}){let a=It.string().min(1,"Account name cannot be an empty string").parse(e);await t.getByTestId(g.openMenuButton).click(),await t.getByTestId(g.manageAccountsButton).click(),await t.getByTestId(`manage-accounts-sortable-${a}`).click();let i=t.getByRole("button",{name:/Account Address(?:es)?/i});await i.waitFor({state:"visible",timeout:2e4});let l=await i.locator("div[data-name='row.pair'] > div").last().textContent();if(l&&Number(l)===1){await i.locator("> div > div").last().click(),await t.getByTestId("header--back").click();let y=t.getByTestId(B.closeMenuButton);await y.waitFor({state:"visible",timeout:15e3}),await y.click()}else{await i.click();let w=new RegExp(`${St(o.network)}`,"i");await t.getByRole("button",{name:w}).locator("> div").last().locator("> div").last().locator("div > button").last().click(),await t.getByRole("button",{name:"Close",exact:!0}).last().click();let C=t.getByTestId("header--back");await C.waitFor({state:"visible",timeout:15e3}),await C.click();let b=t.getByTestId(B.closeMenuButton);await b.waitFor({state:"visible",timeout:15e3}),await b.click()}return await t.evaluate(async()=>await navigator.clipboard.readText())}async function ct(t){await t.getByTestId(g.openMenuButton).click(),await t.getByTestId(g.settingsButton).click(),await t.getByTestId(B.lockWalletButton).click()}import{styleText as pt}from"util";import{expect as Nt}from"@playwright/test";function _(t){return new Promise(e=>setTimeout(e,t))}import st from"fs";import vt from"path";async function R(t){let e=x(t),o=vt.resolve(e,"password.txt");try{if(!st.existsSync(o))throw new Error("\u274C password.txt not found. Run setup script first.");return st.readFileSync(o,"utf-8")}catch(a){throw new Error(`\u274C Failed to get ${t} password from cache: ${a.message}`)}}import{expect as Et}from"@playwright/test";async function lt({context:t,path:e,locator:o}){let a;try{await Et.poll(async()=>(a=t.pages().filter(n=>n.url().startsWith("chrome-extension://")).find(n=>n.url().match(e)),!!a),{timeout:3e4}).toBe(!0)}catch{let n=t.pages().filter(r=>r.url().startsWith("chrome-extension://")).map(r=>r.url());throw new Error(`Popup page with path "${e}" not found in context after 30s. Pages in context: ${JSON.stringify(n)}`)}if(!a)throw new Error(`Popup page with path ${e} not found in context.`);return await Wt(a,o),await a.setViewportSize({width:360,height:592}),a}async function Wt(t,e){await t.waitForLoadState("load",{timeout:4e4}),await t.waitForLoadState("domcontentloaded",{timeout:4e4}),await t.locator(e).first().waitFor({state:"attached",timeout:4e4})}import ut from"fs";import Ft from"path";async function mt(t){let e=x(t),o=Ft.resolve(e,"extension-id.txt");try{if(!ut.existsSync(o))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return ut.readFileSync(o,"utf-8")}catch(a){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${a.message}`)}}var k=class{name="phantom";onboardingPath="/onboarding.html";async indexUrl(){return`chrome-extension://${await this.extensionId()}/popup.html`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/notification.html`}async extensionId(){return await mt(this.name)}async promptPage(e){let o=await this.promptUrl();return await lt({context:e,path:o,locator:"div[id='root']"})}};async function E(t,e){let a=!1;for(;!e();){let n=e();if(n||a||t.isClosed())break;try{let r=t.locator("div[id='modal']").locator("div > svg").first();await r.isVisible().catch(()=>!1)&&(await r.click(),a=!0)}catch(r){if(t.isClosed())break;console.error("[autoClosePhantomNotification]: ",r)}if(n||a||t.isClosed())break;await _(300)}}async function $({page:t,currentAccountName:e,newAccountName:o}){await t.getByTestId(g.openMenuButton).click(),await t.getByTestId(g.manageAccountsButton).click();let u=await t.getByTestId(at.accountProfileContainer).locator("div[data-testid^='manage-accounts-sortable'] div > p").all(),i=null;for(let f of u)if((await f.textContent())?.toLowerCase()===e.toLowerCase()){i=f;break}if(!i)throw new Error(`Account with name "${e}" not found`);await i.click(),await t.locator("button:has-text('Account Name')").click();let l=t.locator("input[name='name']");await l.clear(),await l.fill(o),await t.getByTestId("primary-button").click(),await t.getByTestId("header--back").click(),await t.getByTestId(B.closeMenuButton).click()}async function U(t){await t.getByTestId(g.openMenuButton).click(),await t.getByTestId(g.settingsButton).click()}async function H({page:t,...e}){await U(t);let o=t.locator(`button[id='${B.developerSettingsButton}']`);await o.scrollIntoViewIfNeeded(),await o.click();let a=t.getByTestId("toggleTestNetwork"),r=await a.locator("label[data-testid='toggleTestNetwork-switch'] > input[aria-label='Toggle']").isChecked().catch(()=>!1);if(!r&&e.mode==="on"&&await a.click(),r&&e.mode==="off"){await a.click(),await t.getByTestId("header--back").click(),await t.getByTestId(B.closeMenuButton).click();return}if(e.mode==="on"&&e.chain==="Solana"){let{network:m}=e;await t.locator(`button:has-text("${m}")`).click()}if(e.mode==="on"&&e.chain==="Ethereum"){let{network:m}=e;if(!await t.getByText("EVM",{exact:!0}).isVisible().catch(()=>!1))throw new Error(["EVM testnet options are not available. Please ensure Ethereum is enabled in optional chains.","To enable Ethereum, call the 'toggleOptionalChain' action before switching the network.","toggleOptionalChain({ page: page, toggleMode: 'on', supportedChains: ['Ethereum'] })","Tip: For persistence, enable Ethereum in your setup file after the onboarding step completes."].join(`
2
2
  `));await t.locator(`button:has-text("${m}")`).click()}await t.getByTestId("header--back").click(),await t.getByTestId(B.closeMenuButton).click()}async function z({page:t,additionalAccounts:e,...o}){console.info(pt("yellowBright",`
3
- Phantom onboarding started...`,{validateStream:!1}));let a=await R("phantom");if(o.mode==="create"){await t.locator(p.createNewWalletButton).click(),await t.getByTestId(p.createSeedPhraseWalletButton).click();let g=t.getByTestId(p.passwordInput),w=t.getByTestId(p.passwordConfirmInput),A=t.getByTestId(p.termsCheckBox),P=t.locator(p.continueButton);await g.fill(a),await w.fill(a),await A.click(),await P.click(),await P.locator("> div > svg").waitFor({state:"detached",timeout:3e4}),await t.getByTestId(p.recoveryPhraseSavedCheckbox).click(),await P.click(),await _(1e3),await P.click(),await t.locator(p.getStartedButton).last().click()}if(o.mode==="recovery phrase"){let y=o.secretRecoveryPhrase.split(" ");await t.locator(p.IAlreadyHaveAWalletButton).click(),await t.locator(p.importRecoveryPhraseButton).click();for(let[G,O]of Object.entries(y))await t.getByTestId(`${p.recoveryPhraseInput}-${G}`).fill(O);await t.locator(p.importWalletButton).click(),await t.locator("p:has-text('Finding accounts with activity')").waitFor({state:"detached",timeout:6e4});let C=t.locator(p.continueButton);await C.click();let b=t.getByTestId(p.passwordInput),L=t.getByTestId(p.passwordConfirmInput),J=t.getByTestId(p.termsCheckBox);await b.fill(a),await L.fill(a),await J.click(),await C.click(),await C.locator("> div > svg").waitFor({state:"detached",timeout:3e4}),await t.locator(p.getStartedButton).last().click()}if(o.mode==="private key"){await t.locator(p.IAlreadyHaveAWalletButton).click();let{privateKey:y,chain:g,accountName:w}=o;await t.locator(p.importPrivateKeyButton).click();let P=t.locator("span[id='button--listbox-input--1']"),C=await P.textContent(),b=t.locator("input[name='name']"),L=t.locator("textarea[name='privateKey']");C!==g&&(await P.click(),await t.locator("ul[id='listbox--listbox-input--1']").locator(`li[data-label='${g}']`).click()),await b.fill(w),await L.fill(y),await t.locator("button:has-text('Import')").click();let q=t.getByTestId(p.passwordInput),Q=t.getByTestId(p.passwordConfirmInput),G=t.getByTestId(p.termsCheckBox);await q.fill(a),await Q.fill(a),await G.click();let O=t.locator(p.continueButton);await O.click(),await O.locator("> div > svg").waitFor({state:"detached",timeout:3e4}),await t.locator(p.getStartedButton).last().click()}let n=await t.context().newPage(),r=await new k().indexUrl();await n.goto(r);let i=await t.context().browser()?.newBrowserCDPSession(),m;await Nt.poll(async()=>{if(i){let{targetInfos:d}=await i.send("Target.getTargets"),g=d.filter(w=>w.title==="Phantom Wallet").find(w=>!w.attached&&w.url===r);return m=g,!!g}},{timeout:2e4}).toBe(!0),m&&await i?.send("Target.closeTarget",{targetId:m.targetId});let u=await n.getByTestId("home-header-account-name").textContent();if(o.mode==="create"){let{accountName:d}=o;await $({page:n,newAccountName:d,currentAccountName:"Account 1"})}if(e&&e.length>0){let d=!1;W(n,()=>d).catch(w=>console.error({error:w}));for(let{accountName:w,chain:A,privateKey:P}of e)await D({page:n,privateKey:P,accountName:w,chain:A}),d=!0;let g=o.mode==="create"?o.accountName:u;g&&await E(n,g)}o.toggleNetworkMode&&await H({page:n,...o.toggleNetworkMode}),await _(3e3),console.info(pt("greenBright","\u2728 Phantom onboarding completed successfully",{validateStream:!1}))}async function wt(t){let e=t.getByTestId(v.cancelButton);await t.getByTestId("approve-transaction").waitFor({state:"attached"}),await e.click()}async function dt({page:t,supportedChains:e,toggleMode:o="off"}){if(await U(t),await t.locator("button[id='settings-item-active-networks']").click(),e.length===0)throw Error("Supported chains array cannot be empty for toggle mode other than 'onboard'");for(let l of e){let i=t.locator(`button[id='toggle-${l.toLowerCase()}']`),u=await i.locator(`label[data-testid='toggle-${l.toLowerCase()}-switch'] > input[aria-label='Toggle']`).isChecked().catch(()=>!1);o==="off"&&u&&await i.click(),o==="on"&&!u&&await i.click()}await t.getByTestId("header--back").click(),await t.getByTestId(B.closeMenuButton).click()}async function V(t){let e=await R("phantom"),o=t.locator("input[name='password']"),a=t.getByTestId("unlock-form-submit-button");await o.fill(e),await a.click(),await a.waitFor({state:"detached"})}var I=class extends k{page;constructor(e){super(),this.page=e}async onboard({...e}){await z({page:this.page,...e})}async unlock(){await V(this.page)}async lock(){await ct(this.page)}async renameAccount({...e}){await $({page:this.page,...e})}async switchAccount(e){await E(this.page,e)}async getAccountAddress({accountName:e,chain:o}){return await it({page:this.page,accountName:e,chain:o})}async addAccount({...e}){await D({page:this.page,...e})}async toggleOptionalChains({toggleMode:e,supportedChains:o}){await dt({page:this.page,supportedChains:o,toggleMode:e})}async switchNetwork({...e}){await H({page:this.page,...e})}async connectToApp(e){await rt(await this.promptPage(this.page.context()),e)}async confirmTransaction(){await nt(await this.promptPage(this.page.context()))}async rejectTransaction(){await wt(await this.promptPage(this.page.context()))}};import gt from"fs";import Ot from"path";import{test as Dt,chromium as Rt}from"@playwright/test";import{expect as _t}from"@playwright/test";async function j(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}async function M(t,e){let o=await t.newPage();return await _t(async()=>{await o.goto(e),await j(o)}).toPass(),o}async function X(t,e){let o=await e.newPage();for(let{origin:a,localStorage:n}of t){let r=o.mainFrame();await r.goto(a),await r.evaluate(l=>{l.forEach(({name:i,value:m})=>{window.localStorage.setItem(i,m)})},n)}await o.close()}import Mt from"fs/promises";async function ft(t){await Mt.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var Lt=35e3;async function K(t,e){try{await Promise.race([t.close(),new Promise((o,a)=>setTimeout(()=>a(new Error("Context close timed out")),Lt))])}catch(o){console.warn(`Browser context close did not complete cleanly: ${o.message}`)}try{await ft(e)}catch(o){console.error(`Failed to remove temporary context directory at ${e}. Error:`,o)}}var F,Ua=({slowMo:t=0,profileName:e}={})=>Dt.extend({contextPath:async({browserName:o},a,n)=>{let r=await T(`${o}-${n.testId}`);await a(r)},context:async({context:o,contextPath:a},n)=>{let r=new k,l=x(r.name),i=await S(r.name),m=Ot.resolve(l,e??"wallet-data");if(!gt.existsSync(m))throw new Error("\u274C Cache for Phantom wallet data not found. Create it first");gt.cpSync(m,a,{recursive:!0,force:!0}),process.env.HEADLESS&&t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!");let u=await Rt.launchPersistentContext(a,{headless:!1,args:[`--disable-extensions-except=${i}`,`--load-extension=${i}`],slowMo:process.env.HEADLESS?0:t});await u.grantPermissions(["clipboard-read"]);let{cookies:f,origins:d}=await o.storageState();f&&await u.addCookies(f),d&&d.length>0&&await X(d,u);let y=await r.indexUrl();F=u.pages().find(w=>w.url().startsWith(y))||await M(u,y);for(let w of u.pages())w.url().includes("about:blank")&&await w.close();await F.bringToFront(),await V(F),await n(u),await K(u,a)},phantomPage:async({context:o},a)=>{await a(F)},phantom:async({context:o},a)=>{let n=new I(F);await a(n)},autoCloseNotification:[async({context:o},a)=>{let n=!1,l=W(F,()=>n);await a(void 0),n=!0,await l.catch(i=>{console.error(`Auto close notification error: ${i.message}`)})},{auto:!0}]});import{test as Ht}from"@playwright/test";import ht from"fs";import $t from"path";import{chromium as Ut}from"@playwright/test";async function yt({workerInfo:t,profileName:e,slowMo:o}){let a=new k,n=await T(t.workerIndex.toString()),r=x(a.name),l=$t.resolve(r,e??"wallet-data");if(!ht.existsSync(l))throw new Error(`Cache for ${a.name} does not exist. Create it first!`);ht.cpSync(l,n,{recursive:!0,force:!0});let i=await S(a.name),m=await Ut.launchPersistentContext(n,{headless:!1,args:[`--disable-extensions-except=${i}`],slowMo:process.env.HEADLESS?0:o}),u=await a.indexUrl(),f=await M(m,u);return{context:m,walletPage:f,contextPath:n}}var rn=({slowMo:t,profileName:e,dappUrl:o}={})=>Ht.extend({workerScopeContents:[async({browser:a},n,r)=>{let{context:l,contextPath:i,walletPage:m}=await yt({workerInfo:r,profileName:e,slowMo:t});await l.grantPermissions(["clipboard-read"]);for(let f of l.pages())f.url().includes("about:blank")&&await f.close();let u=new I(m);await u.unlock(),await n({wallet:u,walletPage:m,context:l}),await K(l,i)},{scope:"worker"}],dappPage:[async({workerScopeContents:a},n)=>{let{context:r}=a,l=await r.newPage();o&&await l.goto(o),await n(l)},{scope:"worker"}],phantomPage:async({workerScopeContents:a},n)=>{await n(a.walletPage)},phantom:async({workerScopeContents:a},n)=>{let r=new I(a.walletPage);await n(r)},autoCloseNotification:[async({workerScopeContents:a},n)=>{let r=!1,l=()=>r,i=W(a.walletPage,l);await n(void 0),r=!0,await i.catch(m=>{console.error(`Auto close notification error: ${m.message}`)})},{auto:!0}]});export{I as Phantom,Ua as phantomFixture,rn as phantomWorkerScopeFixture,xe as workerScopeContext};
3
+ Phantom onboarding started...`,{validateStream:!1}));let a=await R("phantom");if(o.mode==="create"){await t.locator(p.createNewWalletButton).click(),await t.getByTestId(p.createSeedPhraseWalletButton).click();let f=t.getByTestId(p.passwordInput),d=t.getByTestId(p.passwordConfirmInput),A=t.getByTestId(p.termsCheckBox),P=t.locator(p.continueButton);await f.fill(a),await d.fill(a),await A.click(),await P.click(),await P.locator("> div > svg").waitFor({state:"detached",timeout:3e4}),await t.getByTestId(p.recoveryPhraseSavedCheckbox).click(),await P.click(),await _(1e3),await P.click(),await t.locator(p.getStartedButton).last().click()}if(o.mode==="recovery phrase"){let y=o.secretRecoveryPhrase.split(" ");await t.locator(p.IAlreadyHaveAWalletButton).click(),await t.locator(p.importRecoveryPhraseButton).click();for(let[G,O]of Object.entries(y))await t.getByTestId(`${p.recoveryPhraseInput}-${G}`).fill(O);await t.locator(p.importWalletButton).click(),await t.locator("p:has-text('Finding accounts with activity')").waitFor({state:"detached",timeout:6e4});let C=t.locator(p.continueButton);await C.click();let b=t.getByTestId(p.passwordInput),L=t.getByTestId(p.passwordConfirmInput),J=t.getByTestId(p.termsCheckBox);await b.fill(a),await L.fill(a),await J.click(),await C.click(),await C.locator("> div > svg").waitFor({state:"detached",timeout:3e4}),await t.locator(p.getStartedButton).last().click()}if(o.mode==="private key"){await t.locator(p.IAlreadyHaveAWalletButton).click();let{privateKey:y,chain:f,accountName:d}=o;await t.locator(p.importPrivateKeyButton).click();let P=t.locator("span[id='button--listbox-input--1']"),C=await P.textContent(),b=t.locator("input[name='name']"),L=t.locator("textarea[name='privateKey']");C!==f&&(await P.click(),await t.locator("ul[id='listbox--listbox-input--1']").locator(`li[data-label='${f}']`).click()),await b.fill(d),await L.fill(y),await t.locator("button:has-text('Import')").click();let q=t.getByTestId(p.passwordInput),Q=t.getByTestId(p.passwordConfirmInput),G=t.getByTestId(p.termsCheckBox);await q.fill(a),await Q.fill(a),await G.click();let O=t.locator(p.continueButton);await O.click(),await O.locator("> div > svg").waitFor({state:"detached",timeout:3e4}),await t.locator(p.getStartedButton).last().click()}let n=await t.context().newPage(),r=await new k().indexUrl();await n.goto(r);let i=await t.context().browser()?.newBrowserCDPSession(),m;await Nt.poll(async()=>{if(i){let{targetInfos:w}=await i.send("Target.getTargets"),f=w.filter(d=>d.title==="Phantom Wallet").find(d=>!d.attached&&d.url===r);return m=f,!!f}},{timeout:2e4}).toBe(!0),m&&await i?.send("Target.closeTarget",{targetId:m.targetId});let l=await n.getByTestId("home-header-account-name").textContent();if(o.mode==="create"){let{accountName:w}=o;await $({page:n,newAccountName:w,currentAccountName:"Account 1"})}if(e&&e.length>0){let w=!1;E(n,()=>w).catch(d=>console.error({error:d}));for(let{accountName:d,chain:A,privateKey:P}of e)await D({page:n,privateKey:P,accountName:d,chain:A}),w=!0;let f=o.mode==="create"?o.accountName:l;f&&await v(n,f)}o.toggleNetworkMode&&await H({page:n,...o.toggleNetworkMode}),await _(3e3),console.info(pt("greenBright","\u2728 Phantom onboarding completed successfully",{validateStream:!1}))}async function dt(t){let e=t.getByTestId(S.cancelButton);await t.getByTestId("approve-transaction").waitFor({state:"attached"}),await e.click()}async function wt({page:t,supportedChains:e,toggleMode:o="off"}){if(await U(t),await t.locator("button[id='settings-item-active-networks']").click(),e.length===0)throw Error("Supported chains array cannot be empty for toggle mode other than 'onboard'");for(let u of e){let i=t.locator(`button[id='toggle-${u.toLowerCase()}']`),l=await i.locator(`label[data-testid='toggle-${u.toLowerCase()}-switch'] > input[aria-label='Toggle']`).isChecked().catch(()=>!1);o==="off"&&l&&await i.click(),o==="on"&&!l&&await i.click()}await t.getByTestId("header--back").click(),await t.getByTestId(B.closeMenuButton).click()}async function V(t){let e=await R("phantom"),o=t.locator("input[name='password']"),a=t.getByTestId("unlock-form-submit-button");await o.fill(e),await a.click(),await a.waitFor({state:"detached"})}var W=class extends k{page;constructor(e){super(),this.page=e}async onboard({...e}){await z({page:this.page,...e})}async unlock(){await V(this.page)}async lock(){await ct(this.page)}async renameAccount({...e}){await $({page:this.page,...e})}async switchAccount(e){await v(this.page,e)}async getAccountAddress({accountName:e,chain:o}){return await it({page:this.page,accountName:e,chain:o})}async addAccount({...e}){await D({page:this.page,...e})}async toggleOptionalChains({toggleMode:e,supportedChains:o}){await wt({page:this.page,supportedChains:o,toggleMode:e})}async switchNetwork({...e}){await H({page:this.page,...e})}async connectToApp(e){await rt(await this.promptPage(this.page.context()),e)}async confirmTransaction(){await nt(await this.promptPage(this.page.context()))}async rejectTransaction(){await dt(await this.promptPage(this.page.context()))}};import gt from"fs";import Ot from"path";import{test as Dt,chromium as Rt}from"@playwright/test";import{expect as _t}from"@playwright/test";async function j(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}async function M(t,e){let o=await t.newPage();return await _t(async()=>{await o.goto(e),await j(o)}).toPass(),o}async function X(t,e){let o=await e.newPage();for(let{origin:a,localStorage:n}of t){let r=o.mainFrame();await r.goto(a),await r.evaluate(u=>{u.forEach(({name:i,value:m})=>{window.localStorage.setItem(i,m)})},n)}await o.close()}import Mt from"fs/promises";async function ft(t){await Mt.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var Lt=35e3;async function K(t,e){try{await Promise.race([t.close(),new Promise((o,a)=>setTimeout(()=>a(new Error("Context close timed out")),Lt))])}catch(o){console.warn(`Browser context close did not complete cleanly: ${o.message}`)}try{await ft(e)}catch(o){console.error(`Failed to remove temporary context directory at ${e}. Error:`,o)}}var F,Ua=({slowMo:t=0,profileName:e}={})=>Dt.extend({contextPath:async({browserName:o},a,n)=>{let r=await T(`${o}-${n.testId}`);await a(r)},context:async({context:o,contextPath:a},n)=>{let r=new k,u=x(r.name),i=await I(r.name),m=Ot.resolve(u,e??"wallet-data");if(!gt.existsSync(m))throw new Error("\u274C Cache for Phantom wallet data not found. Create it first");gt.cpSync(m,a,{recursive:!0,force:!0}),process.env.HEADLESS&&t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!");let l=await Rt.launchPersistentContext(a,{headless:!1,args:[`--disable-extensions-except=${i}`,`--load-extension=${i}`],slowMo:process.env.HEADLESS?0:t});await l.grantPermissions(["clipboard-read"]);let{cookies:h,origins:w}=await o.storageState();h&&await l.addCookies(h),w&&w.length>0&&await X(w,l);let y=await r.indexUrl();F=l.pages().find(d=>d.url().startsWith(y))||await M(l,y);for(let d of l.pages())d.url().includes("about:blank")&&await d.close();await F.bringToFront(),await V(F),await n(l),await K(l,a)},phantomPage:async({context:o},a)=>{await a(F)},phantom:async({context:o},a)=>{let n=new W(F);await a(n)},autoCloseNotification:[async({context:o},a)=>{let n=!1,u=E(F,()=>n);await a(void 0),n=!0,await u.catch(i=>{console.error(`Auto close notification error: ${i.message}`)})},{auto:!0}]});import{test as Ht}from"@playwright/test";import ht from"fs";import $t from"path";import{chromium as Ut}from"@playwright/test";async function yt({workerInfo:t,profileName:e,slowMo:o}){let a=new k,n=await T(t.workerIndex.toString()),r=x(a.name),u=$t.resolve(r,e??"wallet-data");if(!ht.existsSync(u))throw new Error(`Cache for ${a.name} does not exist. Create it first!`);ht.cpSync(u,n,{recursive:!0,force:!0});let i=await I(a.name),m=await Ut.launchPersistentContext(n,{headless:!1,args:[`--disable-extensions-except=${i}`],slowMo:process.env.HEADLESS?0:o}),l=await a.indexUrl(),h=await M(m,l);return{context:m,walletPage:h,contextPath:n}}var rn=({slowMo:t,profileName:e}={})=>Ht.extend({workerScopeContents:[async({browser:o},a,n)=>{let{context:r,contextPath:u,walletPage:i}=await yt({workerInfo:n,profileName:e,slowMo:t});await r.grantPermissions(["clipboard-read"]);for(let l of r.pages())l.url().includes("about:blank")&&await l.close();let m=new W(i);await m.unlock(),await a({wallet:m,walletPage:i,context:r}),await K(r,u)},{scope:"worker"}],autoCloseNotification:[async({workerScopeContents:o},a)=>{let n=!1,r=()=>n,u=E(o.walletPage,r);await a(void 0),n=!0,await u.catch(i=>{console.error(`Auto close notification error: ${i.message}`)})},{auto:!0}]});export{W as Phantom,Ua as phantomFixture,rn as phantomWorkerScopeFixture,xe as workerScopeContext};
@@ -1,6 +1,6 @@
1
- import { W as WalletProfileFixtureArgs, c as WorkerScopeFixtureArgs } from '../../types-B56pinWs.js';
2
- import { W as WorkerScopeFixture } from '../../worker-scope-context-DiN3_Sig.js';
3
- export { w as workerScopeContext } from '../../worker-scope-context-DiN3_Sig.js';
1
+ import { W as WalletProfileFixtureArgs } from '../../types-DK8rutb5.js';
2
+ import { W as WorkerScopeFixture } from '../../worker-scope-context-CNAfiliw.js';
3
+ export { w as workerScopeContext } from '../../worker-scope-context-CNAfiliw.js';
4
4
  import * as _playwright_test from '@playwright/test';
5
5
  import { BrowserContext, Page } from '@playwright/test';
6
6
  import z from 'zod';
@@ -138,6 +138,6 @@ declare class Solflare extends SolflareProfile {
138
138
 
139
139
  declare const solflareFixture: ({ slowMo, profileName }?: WalletProfileFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & SolflareFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
140
140
 
141
- declare const solflareWorkerScopeFixture: ({ slowMo, profileName, dappUrl }?: WorkerScopeFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & SolflareFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerScopeFixture<Solflare>>;
141
+ declare const solflareWorkerScopeFixture: ({ slowMo, profileName }?: WalletProfileFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & SolflareFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerScopeFixture<Solflare>>;
142
142
 
143
- export { Solflare, WalletProfileFixtureArgs, WorkerScopeFixture, WorkerScopeFixtureArgs, solflareFixture, solflareWorkerScopeFixture };
143
+ export { Solflare, WalletProfileFixtureArgs, WorkerScopeFixture, solflareFixture, solflareWorkerScopeFixture };