@tobelabs/chainwright 0.3.3 → 0.5.0
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.
- package/dist/cli/index.js +8 -8
- package/dist/wallets/index.js +16 -16
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
${a}`,{encoding:"utf-8"})}catch(l){console.error("Error appending new profile name type: ",l)}}else try{L.writeFileSync($,a)}catch(r){console.error("Error writing new profile name type: ",r)}}import ne from"path";import{pathToFileURL as se}from"url";import{styleText as ie}from"util";import{glob as le}from"glob";import ae from"path";function O(e){let
|
|
4
|
-
`));return await Promise.all(s.map(async({filePath:i,walletName:p})=>{let f=await
|
|
5
|
-
`));return await
|
|
2
|
+
import B from"path";import{styleText as g}from"util";import Fe from"@inquirer/checkbox";import{Command as Te}from"commander";import L from"fs";import j from"path";import{fileURLToPath as ee}from"url";var te=ee(import.meta.url),oe=j.dirname(te),$=j.resolve(oe,"..","..","generated-profile-name.types.ts"),re=e=>e.replace(/(^\w)/g,t=>t.toUpperCase());async function z({walletName:e,profileName:t}){let o=re(e),a=`export type ${o}Profiles = "${t}";`;if(L.existsSync($)){let r=L.readFileSync($,"utf-8"),n=r.match(new RegExp(`export type ${o}Profiles = ("[^"]+"(?:\\s*\\|\\s*"[^"]+")*)`));if(n){let l=n[0];if(!l.includes(`"${t}"`)){let s=l.concat(` | "${t}"`),c=r.replace(l,s);try{L.writeFileSync($,c)}catch(i){console.error("Error updating existing profile name type: ",i)}}}else try{L.appendFileSync($,`
|
|
3
|
+
${a}`,{encoding:"utf-8"})}catch(l){console.error("Error appending new profile name type: ",l)}}else try{L.writeFileSync($,a)}catch(r){console.error("Error writing new profile name type: ",r)}}import ne from"path";import{pathToFileURL as se}from"url";import{styleText as ie}from"util";import{glob as le}from"glob";import{tsImport as pe}from"tsx/esm/api";import ae from"path";function O(e){let t=ae.basename(e),o=t.match(/^([a-z0-9_]+)(?:-[a-z0-9_]+)*\.setup\.(?:ts|js|mjs)$/i);if(!o)throw new Error(`Invalid wallet setup filename: ${t} (expected "<name>[ -variant].setup.{ts,js,mjs}")`);return o[1]}var ce=e=>e.replace(/\\/g,"/"),me=e=>`${ce(ne.resolve(e))}/**/*.setup.{ts,js,}`,fe=e=>{let t=new URL(se(e)).href;return e.endsWith(".ts")?pe(t,import.meta.url):import(t)};async function R({walletSetupDir:e,selectedWallets:t}){let o=me(e),a=(await le(o,{dot:!0,absolute:!0,nodir:!0,windowsPathsNoEscape:!0})).sort(),r=t.length===1?t[0]:t,n=["metamask","solflare","petra","meteor","keplr","phantom"];Array.isArray(r)&&r.forEach(i=>{n.includes(i)||console.warn(ie("magenta",`Unsupported wallet: "${i}". Supported wallets are: ${n.join(", ")}`,{validateStream:!1}))});let s=(r==="all"?a:Array.isArray(r)?a.filter(i=>r.some(p=>i.includes(p))):a.filter(i=>i.includes(r))).map(i=>({filePath:i,walletName:O(i)}));if(!s.length||s.length===0)throw new Error([`No wallet setup file found at ${e} for wallet: "${t}".`,'Setup files must use a ".setup.{ts,js,mjs}" extension and include a valid wallet name.','Examples: "metamask.setup.ts", "solflare.setup.ts", "phantom.setup.ts", "metamask-connected.setup.ts"'].join(`
|
|
4
|
+
`));return await Promise.all(s.map(async({filePath:i,walletName:p})=>{let f=await(await fe(i)).default,{fn:E,config:h,password:w}=f;return{walletName:p,fileList:s,config:h,walletPassword:w,setupFunction:E}}))}import x from"fs";import I from"path";import{styleText as S}from"util";import{chromium as be}from"@playwright/test";import xe from"path";var G=".wallet-cache";var K="wallet-setup",H="13.22.0",C="https://github.com/amaify/chainwright/releases/download/v0.1.0/",ue=`https://github.com/MetaMask/metamask-extension/releases/download/v${H}/metamask-chrome-${H}.zip`,de=`${C}solflare-wallet-extension-v2.19.1.zip`,we=`${C}petra-wallet-extension-v2.4.8.zip`,ge=`${C}phantom-wallet-extension-v26.10.0.zip`,he=`${C}meteor-wallet-extension-v0.7.0.zip`,ye=`${C}keplr-wallet-extension-v0.13.3.zip`,F={metamask:{downloadUrl:ue,extensionName:"MetaMask"},solflare:{downloadUrl:de,extensionName:"Solflare Wallet"},petra:{downloadUrl:we,extensionName:"Petra Aptos Wallet"},phantom:{downloadUrl:ge,extensionName:"Phantom"},meteor:{downloadUrl:he,extensionName:"Meteor Wallet"},keplr:{downloadUrl:ye,extensionName:"Keplr"}};function P(e){return xe.resolve(process.cwd(),G,e)}import{z as T}from"zod";var Se=T.object({id:T.string(),name:T.string()}),Ee=T.array(Se);async function V(e,t){let o=await e.newPage();await o.goto("chrome://extensions");let a=await o.evaluate("chrome.management.getAll()"),r=Ee.parse(a),n=r.find(l=>l.name.toLowerCase()===t.toLowerCase());if(!n)throw new Error([`[GetExtensionId] Extension with name ${t} not found.`,`Available extensions: ${r.map(l=>l.name).join(", ")}`].join(`
|
|
5
|
+
`));return await o.close(),n.id}import v from"fs";import k from"path";import{styleText as W}from"util";import Ce from"adm-zip";import{createWriteStream as Ae}from"fs";import{Readable as ve}from"stream";import{styleText as N}from"util";import Le from"cli-progress";var $e=12e4;async function X({url:e,destination:t}){let o=new AbortController,a=setTimeout(()=>o.abort(),$e),r=await fetch(e,{redirect:"follow",signal:o.signal});r.ok||(console.error(N("redBright",`\u274C Download failed: HTTP ${r.status}`,{validateStream:!1})),o.abort(),process.exit(1));let n=parseInt(r.headers.get("content-length")||"0",10),l=0,s=ve.fromWeb(r.body);try{let c=new Le.SingleBar({format:`Downloading ${N("cyan","{bar}",{validateStream:!1})} {percentage}%`,clearOnComplete:!0,barCompleteChar:"\u2588",barIncompleteChar:"\u2591",hideCursor:!0});c.start(n,0,{speed:"N/A"}),await new Promise((i,p)=>{let m=Ae(t);s.pipe(m),s.on("data",f=>{l+=f.length,c.update(l)}),m.on("error",p),m.on("finish",()=>{c.stop(),i(void 0)})})}catch(c){console.error(N("redBright",`\u274C Download failed: ${c}`,{validateStream:!1})),process.exit(1)}finally{clearTimeout(a)}}var Y=!1;async function q({downloadUrl:e,name:t,force:o}){let a=P(t),n=F[t].extensionName,l=k.join(a,`${t}-extension.zip`),s=k.join(a,`${t}-extension`);if(o&&v.existsSync(a)&&(v.rmSync(a,{recursive:!0}),console.info(W("magenta",`\u{1F9F9} Removed ${n} because of the force flag`,{validateStream:!1}))),v.existsSync(a)||v.mkdir(a,{recursive:!0},i=>{if(i)throw Error("Failed to create cache directory");console.info(`\u2705 ${n} Cache directory created successfully.`)}),v.existsSync(s)?console.info(`\u2705 ${n} Version is downloaded already.`):(console.info(W("cyanBright",`\u{1F4E5} Downloading ${n} extension...`,{validateStream:!1})),await X({url:e,destination:l}),console.info(W("green",`\u2705 ${t.toUpperCase()} Extension downloaded successfully.`,{validateStream:!1}))),!v.existsSync(s))console.info("\u{1F4E6} Extracting extension..."),new Ce(l).extractAllTo(s,!0),console.info(`\u2705 ${n} Extension extracted successfully.`);else{if(Y)return console.info(W("magentaBright",`Using the cached ${n} extension for profile creation.`,{validateStream:!1})),s;console.info(W("yellow",`\u26A0\uFE0F Skipping ${n} cache creation: Cache already exists at ${s}. Use --force to overwrite.`,{validateStream:!1}))}let c=k.join(s,"manifest.json");if(!v.existsSync(c))throw new Error(`\u274C (${n}) Invalid extension: manifest.json not found`);return Y=!0,s}import{styleText as Pe}from"util";function U(e){return new Promise(t=>setTimeout(t,e))}var D=20,We=6e3,Z=4e3;async function _e(e){return e.pages().find(a=>{try{return a.url().startsWith("chrome-extension://")}catch(r){return console.error("[WaitForExtensionOnLoadPage] Error checking page URL:",r),!1}})}async function J(e,t){let o=0,a=null;if(t==="meteor")return await e.newPage();for(console.info(`Waiting ${Z}ms for browser to initialize...`),await U(Z);o<=D;)try{if(console.info(`Looking for extension page (attempt ${o+1}/${D})...`),o===D)throw new Error("Extension page not found after maximum retries");let r=await _e(e);if(r){console.info(`Found extension page after ${o+1} polling attempts`),a=r;break}r||(o++,console.info(`Extension page not found, retrying (${o}/${D})...`),await U(We))}catch(r){throw console.error("Error waiting for extension page:",r instanceof Error?r.message:"Unknown error"),new Error(`Extension failed to load properly after ${o} attempts!`)}return console.info(Pe("greenBright","\u2705 Extension page is properly loaded and ready",{validateStream:!1})),a}async function M({walletName:e,force:t,config:o,fileList:a,walletPassword:r,setupFunction:n}){let{downloadUrl:l,extensionName:s}=F[e],c=P(e),i=o?.profileName,p=i?`${i}`:"wallet-data",m=I.resolve(c,"extension-id.txt"),f=I.resolve(c,"extension-path.txt"),E=I.resolve(c,"password.txt"),h=I.resolve(c,p),w=await q({downloadUrl:l,name:e,force:t}),y=[`--disable-extensions-except=${w}`,`--load-extension=${w}`];if(x.existsSync(h)&&a.length>1)throw Error([S("yellowBright",[`\u274C ${p} directory already exists for ${s}.`,`
|
|
6
6
|
To setup another wallet profile, add a profile name to the wallet setup function.`,S(["blueBright","italic"],'Example: defineWalletSetup(async ({ context, walletPage }) => { ... }, { profileName: "profile-name" });'),S("italic","You can also use the --force flag to overwrite the existing cache.")].join(`
|
|
7
7
|
`),{validateStream:!1})].join(`
|
|
8
|
-
`));if(x.existsSync(
|
|
9
|
-
Setting up cache for ${p}...`,{validateStream:!1})),await M({walletName:p,config:m,setupFunction:E,fileList:
|
|
10
|
-
\u274C Failed to setup cache for ${p}: ${
|
|
11
|
-
\u274C Attempt ${
|
|
8
|
+
`));if(x.existsSync(h))return;let A=await be.launchPersistentContext(h,{headless:!1,args:y,slowMo:o?.slowMo??0});console.info(S("magentaBright",`\u{1F9E9}\u{1F680} Starting Chrome extension for ${e.toUpperCase()}`,{validateStream:!1}));let Q=await J(A,e);if(!x.existsSync(m)&&!x.existsSync(f)){let b=await V(A,s);console.info(S("magentaBright",`\u{1F194} ${s} extension ID: ${b}`,{validateStream:!1})),x.writeFileSync(m,b,"utf-8"),console.info(S("cyanBright",`\u{1F4BE} Saved extension ID to: ${m}`,{validateStream:!1})),x.writeFileSync(f,w,"utf-8"),console.info(S("blueBright",`\u{1F4C1} Saved extension Path to: ${f}`,{validateStream:!1})),x.writeFileSync(E,r,"utf-8"),console.info(S("yellowBright",`\u{1F511} Saved ${e} password to: ${E}`,{validateStream:!1}))}try{await n({context:A,walletPage:Q})}catch(b){await A.close(),x.rmSync(c,{force:!0,recursive:!0}),console.error("Error setting up wallet: ",b.message)}await A.close()}var De=B.resolve(process.cwd(),"tests",K),_=2;async function Ie(){let e=new Te;e.name(g("yellow","Chainwright")).description(g("green","A CLI tool for setting up wallet cache for E2E testing of web3 applications")).version(g("blue","0.0.0")),e.argument("[dir]","Directory containing the wallet setup functions",B.resolve(De)).option("--headless","Build cache in the headless browser mode. Alternatively, set the `HEADLESS` env variable to `true`",!1).option("-f, --force","Force the creation of cache even if it already exists",!1).option("-a, --all","Setup all wallets","all").option("--kp, --keplr","Setup Keplr","keplr").option("-m, --metamask","Setup MetaMask","metamask").option("--mt, --meteor","Setup Meteor","meteor").option("--pt, --petra","Setup Petra","petra").option("--ph, --phantom","Setup Phantom","phantom").option("-s, --solflare","Setup Solflare","solflare").option("--wls, --wallets <wallets...>","Specify wallets to setup (e.g., --wallets keplr metamask)").action(async(t,o)=>{let a=["all","metamask","solflare","petra","meteor","keplr","phantom"],r=Object.keys(o).filter(p=>a.includes(p)?o[p]===!0:!1),n=r.length>0,l=o.wallets,s=l||(n?r:await Fe({message:"Select the wallet you want to setup",choices:[{name:"All",value:"all"},{name:"Keplr",value:"keplr"},{name:"MetaMask",value:"metamask"},{name:"Meteor",value:"meteor"},{name:"Petra",value:"petra"},{name:"Phantom",value:"phantom"},{name:"Solflare",value:"solflare"}],validate:p=>{let m=p.map(f=>f.value);return m.includes("all")&&m.length>1?'Select either "All" or specific wallets, not both.':!0},pageSize:10})),c=B.resolve(process.cwd(),t);o.headless&&(process.env.HEADLESS=!0);let i=await R({walletSetupDir:c,selectedWallets:s});for(let{walletName:p,config:m,walletPassword:f,setupFunction:E,fileList:h}of i)try{console.info(g("cyanBright",`
|
|
9
|
+
Setting up cache for ${p}...`,{validateStream:!1})),await M({walletName:p,config:m,setupFunction:E,fileList:h,force:o.force,walletPassword:f}),m.profileName&&await z({walletName:p,profileName:m.profileName})}catch(w){if(w.message.includes("directory already exists")&&console.warn(w.message),!w.message.includes("directory already exists")){console.error(g("redBright",`
|
|
10
|
+
\u274C Failed to setup cache for ${p}: ${w.message}`,{validateStream:!1}));let y=0;for(;_>y;){console.info(`${g("yellow",`Retry Attempt ${y+1} of ${_} for ${p}...`,{validateStream:!1})}`),console.info(g("yellow","Retrying wallet setup...",{validateStream:!1}));try{await M({walletName:p,config:m,setupFunction:E,fileList:h,force:o.force,walletPassword:f});break}catch(A){y+1<_&&console.error(g("redBright",`
|
|
11
|
+
\u274C Attempt ${y+1} failed! Retrying...`,{validateStream:!1})),y++,y===_&&console.error(g("redBright",`\u274C Failed to setup cache after ${_} attempts for ${p}: ${A.message}`,{validateStream:!1}))}}}}}),await e.parseAsync(process.argv)}Ie().catch(e=>console.error(g("redBright",`Failed to run the CLI: ${e.message})`,{validateStream:!1})));export{Ie as clientEntry};
|
package/dist/wallets/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import{expect as
|
|
2
|
-
Already on ${e} account. No need to switch.`);return}await a.click();let n=t.locator("div[class='simplebar-content'] > div").locator("> div",{hasText:e});if(!await n.isVisible().catch(()=>!1))throw new Error(`Account "${e}" not found. Make sure the account is onboarded or verify the account name.`);let i=t.locator("div:has-text('Select Wallet')").last();await n.click(),await i.waitFor({state:"detached",timeout:3e4})}async function
|
|
3
|
-
Keplr onboarding started...`,{validateStream:!1})),e.length===1)for(let{privateKey:a,walletName:o,chains:n}of e)await xt({page:t,privateKey:a,walletName:o,chains:n,mode:"onboard"});if(e.length>1){let a=e[0];if(a){let{privateKey:
|
|
4
|
-
\u26A0\uFE0F Skipping test: ${e}`),Ea.skip())}var C={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"},bt={lockButton:"global-menu-lock",networksButton:"global-menu-networks"},Ot={passwordInput:"unlock-password",unlockButton:"unlock-submit"},nt={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 M={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 ao({page:t,privateKey:e,accountName:a}){let o=oo.string().min(1,"Account name cannot be an empty string").trim().parse(a),n=oo.string().min(1,"Private key cannot be an empty string").trim().parse(e),r=t.getByTestId(C.accountMenuButton);await D(r).toBeVisible({timeout:3e4}),await r.click(),await D(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let i=t.getByTestId(nt.addWalletButton),c=await i.textContent();c?.includes("Syncing")&&await D.poll(async()=>(await i.textContent())?.trim()??"",{timeout:12e4}).not.toBe(c),await D(i).toBeEnabled({timeout:6e4}),await i.click();let u=t.getByRole("dialog");await D(u).toContainText(/add wallet/i),await t.getByTestId(nt.importAccountButton).click(),await t.locator("input[id='private-key-box']").fill(n);let d=t.getByTestId(M.importAccountConfirmButton);await D(d).toBeEnabled(),await d.click();let w=t.getByTestId(M.importSRPError),g=await w.isVisible().catch(()=>!1);g&&eo(g,`${(await w.textContent())?.split(".")[0]}`);let f=t.locator("div:has(> div[data-testid^='multichain-account-cell-keyring'][class*='mm-box--background-color-background-muted'])"),y=(await f.textContent())?.split("$")[0];y&&await Ra({page:t,accountName:o,activeAccountLocator:f,activeAccountName:y}),await t.locator("button[aria-label='Back']").first().click()}async function Ra({page:t,accountName:e,activeAccountLocator:a,activeAccountName:o}){let n=a.locator(`div[aria-label='${o} options']`);await D(n).toBeVisible(),await n.click(),await D(t.getByRole("tooltip")).toBeVisible();let r=t.locator(`div[aria-label='${nt.renameAccountLabel}']`);await D(r).toBeVisible(),await r.click();let i=t.getByRole("dialog"),c=i.getByRole("heading",{name:/rename/i});await D(c).toBeVisible();let u=i.getByRole("textbox");await D(u).toBeVisible(),await u.fill(e);let m=i.getByRole("button",{name:/confirm/i});await D(m).toBeEnabled(),await m.click(),await i.waitFor({state:"detached",timeout:2e4});let p=t.locator("div:has(> div[data-testid^='multichain-account-cell-keyring'][class*='mm-box--background-color-background-muted'])");await D(p).toContainText(e)}import{expect as Dt}from"@playwright/test";import Pt from"zod";var no=Pt.object({networkName:Pt.string().min(1,"Network name cannot be an empty string"),rpcUrl:Pt.url(),chainId:Pt.number().or(Pt.string().includes("0x")),currencySymbol:Pt.string().toUpperCase().min(1,"Currency symbol cannot be an empty string")});import{expect as _a}from"@playwright/test";async function te(t){let e=t.locator("div:has(> p[data-testid='notifications-tag-counter__unread-dot'])"),a=t.getByTestId(C.openSettingsButton);await e.isVisible().catch(()=>!1)?await e.click():(await _a(a).toBeVisible(),await a.click())}async function ro({page:t,...e}){let{chainId:a,currencySymbol:o,networkName:n,rpcUrl:r}=no.parse({...e},{reportInput:!0});await te(t),await t.getByTestId(bt.networksButton).click();let c=t.locator("section[role='dialog']");await Dt(c).toContainText(/manage networks/i),await t.getByRole("button",{name:/add a custom network/i}).click(),await Dt(c).toContainText(/Add a custom network/i);let m=t.getByTestId("network-form-network-name"),p=t.getByTestId("test-add-rpc-drop-down"),d=t.getByTestId("network-form-chain-id"),w=t.getByTestId("network-form-ticker-input");await m.fill(n),await p.click(),await t.getByRole("tooltip").locator("div:has(> button:has-text('Add RPC URL'))").click(),await Dt(c).toContainText(/Add RPC URL/i);let y=t.getByTestId("rpc-url-input-test"),h=t.getByRole("button",{name:/Add URL/i});await y.fill(r),await h.click(),await Dt(c).toContainText(/Add a custom network/i);let x=t.getByTestId("network-form-chain-id-error");if(await x.isVisible().catch(()=>!1)){let v=await x.textContent();throw Error(`RPC error: ${v}`)}await d.fill(`${a}`),await w.fill(o);let S=t.getByRole("button",{name:/save/i});await Dt(S).toBeEnabled(),await S.click()}import{expect as io}from"@playwright/test";var ee={confirmButton:"confirm-footer-button",cancelButton:"confirm-footer-cancel-button"};async function co(t,e){let a=t.getByTestId(ee.confirmButton);await B(2e3);let n=(await a.textContent())?.includes("Review alert"),r=await a.isDisabled().catch(()=>!1);if(n&&r){await t.getByTestId("edit-gas-fees-row").locator("> div").first().click();let p=t.getByRole("dialog");await io(p).toBeVisible();let d=p.locator("h4",{hasText:"Insufficient funds"}),w=await p.getByTestId("alert-modal__selected-alert").textContent();if(await d.isVisible().catch(()=>!1))throw Error(`${w}`)}if(e){let u=t.getByTestId("edit-gas-fee-icon");if(await u.scrollIntoViewIfNeeded(),await u.click(),e.feeType!=="advanced"&&await t.getByTestId(`gas-option-${e.feeType}`).click(),e.feeType==="advanced"){await t.getByTestId("gas-option-advanced").click();let p=t.getByRole("textbox",{name:"Max base fee"}),d=t.getByRole("textbox",{name:"Priority fee"}),w=t.getByRole("button",{name:"Save",exact:!0});await p.fill(e.maxBaseFee),await d.fill(e.priorityFee),await w.click()}}await io(a).toBeEnabled(),await a.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 Va}from"@playwright/test";import{expect as Ce}from"@playwright/test";async function At({page:t,accountName:e}){let a=t.getByTestId(C.accountMenuButton);if(await a.textContent()===e){console.info(`Can't switch account to "${e}", it is already selected.`);return}await Ce(a).toBeVisible({timeout:15e3}),await a.click(),await Ce(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let n=t.getByTestId(nt.addMultichainAccountButton),r=await n.textContent();r?.includes("Syncing")&&await Ce.poll(async()=>(await n.textContent())?.trim()??"",{timeout:6e4}).not.toBe(r);let i=await t.getByTestId(/^multichain-account-cell-(?:entropy|keyring):/).all(),c=null;for(let u of i)if(await u.scrollIntoViewIfNeeded(),(await u.textContent())?.includes(e)){c=u;break}if(!c)throw Error(`Account with name "${e}" not found.`);await c?.click()}async function so(t,e){e&&await At({page:t,accountName:e});let a=t.getByRole("button",{name:"Connect",exact:!0});await a.waitFor({state:"visible",timeout:25e3}),await a.click(),await t.getByRole("heading",{name:"Connecting",exact:!0}).waitFor({state:"detached",timeout:3e4});let n;await Va.poll(async()=>(n=await t.locator("div[class='permissions-connect']").isVisible().catch(()=>!1),n),{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 lo(t,e){return await t.getByTestId(C.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='${C.accountAddressesElements}']:has-text('${e}')`).getByTestId(C.accountAddressQRCode).click(),await t.getByRole("dialog").locator("div > p[data-testid='account-address']").textContent()}import{expect as Da}from"@playwright/test";import{errors as $a}from"@playwright/test";var uo={loadingOverlay:"loading-overlay",loadingSpinner:"spinner loading-overlay__spinner"};var La=6e4,Oa=async(t,e,a)=>{await R(e);try{await e.locator(`div[class="${t}"]`).waitFor({state:"detached",timeout:a})}catch(o){if(o instanceof $a.TimeoutError)console.info(`Loading indicator '${t}' not found - continuing.`);else throw console.error(`Error while waiting for loading indicator '${t}' to disappear`),o}},oe=async t=>{try{await Oa(uo.loadingSpinner,t,La)}catch(e){console.warn("Warning during MetaMask load:",e)}return await B(300),t};async function mo(t){if(await t.getByTestId(Ot.unlockButton).isVisible().catch(()=>!1)){console.info("\u{1F4A1} Wallet is already locked");return}await te(t);let o=t.getByTestId(bt.lockButton);await Da(o).toBeVisible(),await o.click(),await oe(t)}import{styleText as po}from"util";import{expect as St}from"@playwright/test";var Z=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 H(this.name)}async promptPage(e){let a=await this.promptUrl();return await K({context:e,path:a,locator:"div[data-testid='multichain-page']"})}};import{expect as Se}from"@playwright/test";async function Ct({page:t}){await t.locator(`div:has(> button[data-testid='${C.openSettingsButton}'])`).click(),await t.getByTestId(bt.networksButton).click();let o=t.locator("section[role='dialog']");await Se(o).toBeVisible(),await Se(o).toContainText(/manage networks/i);let n="div:has(> p:has-text('Show test networks'))";await o.locator(n).scrollIntoViewIfNeeded();let r=o.locator(n);if(!await r.locator("label[class='toggle-button toggle-button--off']").isVisible().catch(()=>!1)){await o.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 Se(t.getByTestId("Sepolia")).toBeVisible(),await o.getByRole("button",{name:/close/i}).click()}async function ve({page:t,mainAccountName:e,...a}){console.info(po("yellowBright",`
|
|
5
|
-
\u{1F98A} MetaMask onboarding started...`,{validateStream:!1}));let o=await P("metamask"),n=new Z,r=t.locator("img[class='loading-spinner']"),i=t.getByTestId(M.createWalletButton),c=t.getByTestId(M.importWalletButton),u=t.getByTestId(M.createNewPasswordInput),m=t.getByTestId(M.confirmNewPasswordInput),p=t.getByTestId(M.confirmPasswordCheckbox),d=t.getByTestId(M.createPasswordButton),w=t.getByTestId(M.metamaskMetricsIAgreeButton),g=t.getByTestId(M.onboardingDoneButton);if(await r.waitFor({state:"detached",timeout:3e4}),a.mode==="create"){let S=t.getByTestId(M.useSecretRecoveryPhraseButton);await i.click(),await S.click(),await u.fill(o),await m.fill(o),await p.click(),await d.click(),await t.getByTestId(M.revealSecretRecoveryPhraseButton).click(),await t.getByTestId(M.recoveryPhraseRemindMeLaterButton).click(),await w.click()}if(a.mode==="import"){let{secretRecoveryPhrase:S}=a,v=S.split(" "),V=t.getByTestId(M.importUsingSecretRecoveryPhraseButton);await c.click(),await V.click();let L=t.getByTestId(M.secretRecoveryPhraseTextAreaInput);await L.fill(v[0]),await L.press("Space");for(let X=1;X<v.length;X++){let Yt=t.getByTestId(`import-srp__srp-word-${X}`);await Yt.fill(v[X]),await Yt.press("Space")}await t.getByTestId(M.importWalletConfirmButton).click(),await u.fill(o),await m.fill(o),await p.click(),await d.click(),await w.click();let at=t.getByTestId("wallet-ready");await St(at).toContainText(/your wallet is ready/i)}await g.click();let y=`chrome-extension://${await n.extensionId()}/sidepanel.html`,x=await t.context().browser()?.newBrowserCDPSession(),I;await St.poll(async()=>{if(x){let{targetInfos:S}=await x.send("Target.getTargets"),v=S.find(V=>V.url===y);return I=v,!!v}},{timeout:15e3}).toBe(!0),I&&await x?.send("Target.closeTarget",{targetId:I.targetId}),await t.goto(await n.indexUrl()),await r.waitFor({state:"detached",timeout:3e4}),await St(t.getByTestId(C.buyButton)).toBeVisible(),await St(t.getByTestId(C.swapButton)).toBeVisible(),await St(t.getByTestId(C.sendButton)).toBeVisible(),await St(t.getByTestId(C.receiveButton)).toBeVisible(),await Ct({page:t}),e&&await At({page:t,accountName:e}),await B(5e3),console.info(po("greenBright","\u2728 MetaMask onboarding completed successfully",{validateStream:!1}))}import{expect as Ua}from"@playwright/test";async function wo(t){let e=t.getByTestId(ee.cancelButton);await B(1e3),await Ua(e).toBeEnabled(),await e.click()}import{expect as Y}from"@playwright/test";async function fo({page:t,currentAccountName:e,newAccountName:a}){let o=t.getByTestId(C.accountMenuButton);if(await o.textContent()===a)throw Error(`The account to be renamed "${a}" already exists.`);await Y(o).toBeVisible({timeout:15e3}),await o.click(),await Y(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let r=t.getByTestId(nt.addMultichainAccountButton),i=await r.textContent();i?.includes("Syncing")&&await Y.poll(async()=>(await r.textContent())?.trim()??"",{timeout:6e4}).not.toBe(i);let c=await t.getByTestId(/^multichain-account-cell/).all(),u=null;for(let x of c)if((await x.textContent())?.includes(e)){u=x;break}if(!u)throw Error(`Account with name "${e}" not found.`);if((await u.textContent())?.split("$")[0]===a)throw Error(`The new account name "${a}" is the same as the old account name "${e}".`);let p=t.locator(`div[aria-label='${e} options']`);await Y(p).toBeVisible(),await p.click(),await Y(t.getByRole("tooltip")).toBeVisible();let d=t.locator(`div[aria-label='${nt.renameAccountLabel}']`);await Y(d).toBeVisible(),await d.click();let w=t.getByRole("dialog"),g=w.getByRole("heading",{name:/rename/i});await Y(g).toBeVisible();let f=w.getByRole("textbox");await Y(f).toBeVisible(),await f.fill(a);let y=w.getByRole("button",{name:/confirm/i});await Y(y).toBeEnabled(),await y.click();for(let x of c)if((await x.textContent())?.includes(a)){await Y(x).toBeVisible(),await Y(x).toContainText(a);break}await t.locator("button[aria-label='Back']").first().click()}import{expect as Ie}from"@playwright/test";async function go({page:t,networkType:e,chainName:a}){let o=t.getByTestId(C.openNetworkSelectorButton);await o.click();let n=t.getByTestId("modal-header-close-button");if(e==="testnet"||e==="custom"){let u=t.getByRole("tab",{name:"Custom"});await u.click(),await t.locator("p:has-text('Testnets')").isVisible().catch(()=>!1)||(await n.click(),await Ct({page:t}),await o.click(),await u.click());let d=t.locator(`div div[data-testid='${a}']`),w=await d.textContent();Ie(w).toBe(a),await d.click();return}await t.getByRole("tab",{name:"Popular"}).click();let i=t.locator(`div div[data-testid='${a}']`),c=await i.textContent();Ie(c).toBe(a),await i.click(),await Ie(o).toContainText(a,{timeout:3e4})}import{expect as ho}from"@playwright/test";async function Ut(t){let e=await P("metamask"),a=t.getByTestId(Ot.passwordInput);if(await t.getByTestId(C.openNetworkSelectorButton).isVisible().catch(()=>!1)){console.info("\u{1F4A1} Wallet is already unlocked");return}await a.fill(e);let r=t.getByTestId(Ot.unlockButton);await ho(r).toBeVisible(),await r.click(),await oe(t),await ho(t.getByTestId(C.buyButton)).toBeVisible({timeout:3e4})}var mt=class extends Z{page;constructor(e){super(),this.page=e}async onboard(e){await ve({page:this.page,...e})}async unlock(){await Ut(this.page)}async lock(){await mo(this.page)}async renameAccount({newAccountName:e,currentAccountName:a}){await fo({page:this.page,newAccountName:e,currentAccountName:a})}async addAccount({privateKey:e,accountName:a}){await ao({page:this.page,privateKey:e,accountName:a})}async switchAccount({accountName:e}){await At({page:this.page,accountName:e})}async switchNetwork({...e}){await go({page:this.page,...e})}async getAccountAddress(e){return await lo(this.page,e)}async toggleShowTestnetNetwork(){await Ct({page:this.page})}async addCustomNetwork({chainId:e,currencySymbol:a,networkName:o,rpcUrl:n}){await ro({page:this.page,chainId:e,currencySymbol:a,networkName:o,rpcUrl:n})}async connectToApp(e){await so(await this.promptPage(this.page.context()),e)}async confirmTransaction(e){await co(await this.promptPage(this.page.context()),e)}async rejectTransaction(){await wo(await this.promptPage(this.page.context()))}};import yo from"fs";import Ka from"path";import{test as Ha,chromium as ja}from"@playwright/test";import{Instance as Ga,Pool as za}from"prool";var Kt,Ll=({slowMo:t=0,profileName:e}={})=>Ha.extend({contextPath:async({browserName:a},o,n)=>{let r=await T(`${a}-${n.testId}`);await o(r)},context:async({context:a,contextPath:o},n)=>{let r=new Z,i=k(r.name),c=await W(r.name),u=Ka.resolve(i,e??"wallet-data");if(!yo.existsSync(u))throw new Error("\u274C Cache for MetaMask wallet data not found. Create it first");yo.cpSync(u,o,{recursive:!0,force:!0});let m=[`--disable-extensions-except=${c}`,`--load-extension=${c}`];process.env.HEADLESS&&(m.push("--headless=new"),t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!"));let p=await ja.launchPersistentContext(o,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:t}),{cookies:d,origins:w}=await a.storageState();d&&await p.addCookies(d),w&&w.length>0&&O(w,p);let g=await r.indexUrl();await p.waitForEvent("page",{predicate:h=>h.url().startsWith(g),timeout:3e4}),Kt=p.pages().find(h=>h.url().startsWith(g))??await _(p,g);for(let h of p.pages())h.url().includes("about:blank")&&await h.close();await Kt.locator("img[class='loading-spinner']").waitFor({state:"detached"}),await Ut(Kt),await n(p),await A(p,o)},metamaskPage:async({context:a},o)=>{await o(Kt)},metamask:async({context:a},o)=>{let n=new mt(Kt);await o(n)},createAnvilNode:async({context:a},o,n)=>{let r=n.workerIndex,i;await o(async c=>{i=za.define({instance:Ga.anvil(c)});let u=await i.start(r),m=`http://${u.host}:${u.port}`,d=c?.chainId??31337;return{rpcUrl:m,anvil:u,chainId:d}}),i&&await i.stop(r)},connectToAnvil:async({context:a,metamask:o,createAnvilNode:n},r)=>{await r(async()=>{let{chainId:i,rpcUrl:c}=await n({chainId:2251});await o.addCustomNetwork({chainId:i,currencySymbol:"ETH",networkName:"Anvil Localnet",rpcUrl:c})})}});import{test as Qa}from"@playwright/test";import{Instance as Xa,Pool as Za}from"prool";import xo from"fs";import qa from"path";import{chromium as Ya}from"@playwright/test";async function Bo({workerInfo:t,profileName:e,slowMo:a}){let o=new Z,n=await T(t.workerIndex.toString()),r=k(o.name),i=qa.resolve(r,e??"wallet-data");if(!xo.existsSync(i))throw new Error(`Cache for ${o.name} does not exist. Create it first!`);xo.cpSync(i,n,{recursive:!0,force:!0});let c=await W(o.name),u=await Ya.launchPersistentContext(n,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:a}),m=await o.indexUrl();await u.waitForEvent("page",{predicate:d=>d.url().startsWith(m),timeout:4e4});let p=u.pages().find(d=>d.url().startsWith(m));p||(p=await u.newPage(),await p.goto(m),await R(p));for(let d of u.pages())d.url().includes("about:blank")&&await d.close();return{context:u,walletPage:p,contextPath:n}}var au=({profileName:t,dappUrl:e,slowMo:a}={})=>Qa.extend({workerScopeContents:[async({browser:o},n,r)=>{let{context:i,contextPath:c,walletPage:u}=await Bo({workerInfo:r,profileName:t,slowMo:a});await i.grantPermissions(["clipboard-read"]);let m=new mt(u);await m.unlock(),await n({wallet:m,walletPage:u,context:i}),await A(i,c)},{scope:"worker"}],dappPage:[async({workerScopeContents:o},n)=>{let{context:r}=o,i=await r.newPage();e&&await i.goto(e),await n(i)},{scope:"worker"}],metamaskPage:async({workerScopeContents:o},n)=>{await n(o.walletPage)},metamask:async({workerScopeContents:o},n)=>{let r=new mt(o.walletPage);await n(r)},createAnvilNode:async({context:o},n,r)=>{let i=r.workerIndex,c;await n(async u=>{c=Za.define({instance:Xa.anvil(u)});let m=await c.start(i),p=`http://${m.host}:${m.port}`,w=u?.chainId??31337;return{rpcUrl:p,anvil:m,chainId:w}}),c&&await c.stop(i)},connectToAnvil:async({context:o,metamask:n,createAnvilNode:r},i)=>{await i(async()=>{let{chainId:c,rpcUrl:u}=await r({chainId:2251});await n.addCustomNetwork({chainId:c,currencySymbol:"ETH",networkName:"Anvil Localnet",rpcUrl:u})})}});var $={openSidebarMenuButton:"button[aria-label='open sidebar']",addWalletButton:"button:has-text('Add Wallet')",settingsButton:"button:has-text('Settings')",settingsMenuBackButton:"button[aria-label='Back']"};var j={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 ae(t,e,a){let o=t.locator(j.switchNetworkButton).last();await o.scrollIntoViewIfNeeded();let n=await o.textContent(),r=e.split("net")[0]?.toLowerCase()??"";if(n?.toLowerCase()===r)return console.info(`
|
|
6
|
-
Already on ${e}, no need to switch network.`),"Exit";await o.click();let c=t.locator(a).last().locator(`> button:has-text('${e}')`);await c.click(),await t.locator("div > h2:has-text('Meteor Community')").isVisible().catch(()=>!1)&&await c.click()}async function vt({page:t,newAccountName:e}){await t.locator(
|
|
7
|
-
Switching to the ${e} account aborted. Account is already selected.`);return}await t.locator(
|
|
8
|
-
`))}async function
|
|
9
|
-
Meteor onboarding started...`,{validateStream:!1}));let r=await
|
|
10
|
-
Retrying search for account. ${ct} attempts left`),await B(15e3),await
|
|
11
|
-
`),{validateStream:!1}))}await t.locator("button:not([aria-label='Back'],[id^='menu-button']):has-text('Account')").click();let
|
|
12
|
-
Switching to ${e} account aborted because the account is already selected.`);return}await a.click();let r=await t.getByRole("dialog").locator("> div > div > button[type='button']").all(),i=null;for(let c of r)if((await c.textContent())?.toLowerCase()?.trim().includes(e.toLowerCase().trim())){i=c;break}if(!i)throw new Error(`Account with name "${e}" not found.`);await i.click()}async function
|
|
13
|
-
Petra onboarding started...`,{validateStream:!1}));let a=new et,o=await P("petra"),n=t.locator(N.createWalletButton),r=t.locator(N.importWalletButton),i=t.locator(N.createNewPasswordInput),c=t.locator(N.confirmNewPasswordInput),u=t.locator(N.confirmPasswordCheckbox),m=t.locator(N.continueButton),p=t.locator(N.getStartedButton),d=t.locator(N.onboardingCompleteText);if(e.mode==="create"){let w=t.locator(N.createSeedPhraseButton);await n.click(),await w.click(),await i.fill(o),await c.fill(o),await u.click(),await m.click(),await t.locator(N.skipCopyRecoveryPhraseButton).click(),await p.click(),await rt(d).toBeVisible({timeout:25e3}),await t.goto(await a.indexUrl()),await rt(t.locator(F.depositButton)).toBeVisible({timeout:Mt}),await rt(t.locator(F.sendButton)).toBeVisible({timeout:Mt})}if(e.mode==="importPrivateKey"){let{privateKey:w}=e,g=t.locator(N.importUsingPrivateKeyButton),f=t.locator(N.privateKeyInput),y=t.locator(N.importButton);await r.click(),await g.click(),await f.fill(w),await y.click(),await i.fill(o),await c.fill(o),await u.click(),await m.click(),await p.click(),await rt(d).toBeVisible({timeout:25e3}),await t.goto(await a.indexUrl()),await R(t),await rt(t.locator(F.depositButton)).toBeVisible({timeout:Mt}),await rt(t.locator(F.sendButton)).toBeVisible({timeout:Mt})}if(e.mode==="importMnemonic"){let{secretRecoveryPhrase:w}=e,g=t.locator(N.importUsingMnemonicButton);await r.click(),await g.click();for(let[f,y]of w.split(" ").entries())await t.locator(`input[name="mnemonic-${String.fromCharCode(97+f)}"]`).fill(y);await m.click(),await i.fill(o),await c.fill(o),await u.click(),await m.click(),await p.click(),await rt(d).toBeVisible({timeout:25e3}),await t.goto(await a.indexUrl()),await rt(t.locator(F.depositButton)).toBeVisible({timeout:Mt}),await rt(t.locator(F.sendButton)).toBeVisible({timeout:Mt})}if(await dt({page:t,newAccountName:e.accountName}),e.addWallet&&e.addWallet.length>0){for(let{...w}of e.addWallet)await ie({page:t,...w});await Nt(t,e.accountName)}await B(1500),console.info(Eo("greenBright","\u2728 Petra onboarding completed successfully",{validateStream:!1}))}import{expect as ln}from"@playwright/test";async function Ro(t){let e=t.locator(Ft.cancelButton);await ln(e).toBeEnabled(),await e.click()}async function _o(t,e){await t.locator(F.settingsMenu).click(),await t.locator(Fe.networkSection).click(),await t.locator(`div:has(> span:has-text("${e}"))`).first().click();let r=t.locator(Fe.backButton);await r.click(),await r.click()}import{expect as Vo}from"@playwright/test";async function Gt(t){let e=await P("petra"),a=t.locator(Ne.passwordInput);if(!await a.isVisible().then(()=>!0).catch(()=>!1)){console.info("\u{1F4A1} Wallet is already unlocked");return}await Vo(a).toBeVisible({timeout:15e3}),await a.fill(e);let n=t.locator(Ne.unlockButton);await Vo(n).toBeEnabled(),await n.click(),await Promise.allSettled([t.locator(F.sendButton).waitFor({state:"visible",timeout:2e4}),t.locator(F.receiveButton).waitFor({state:"visible",timeout:2e4})])}var wt=class extends et{page;constructor(e){super(),this.page=e}async onboard(e){await Me({page:this.page,...e})}async unlock(){await Gt(this.page)}async lock(){await Mo(this.page)}async renameAccount({newAccountName:e}){await dt({page:this.page,newAccountName:e})}async switchNetwork(e){await _o(this.page,e)}async switchAccount(e){await Nt(this.page,e)}async getAccountAddress(){return await Wo(this.page)}async addAccount({accountName:e,...a}){await ie({page:this.page,accountName:e,...a})}async connectToApp(e){await To(await this.promptPage(this.page.context()),e)}async confirmTransaction(){await Io(await this.promptPage(this.page.context()))}async rejectTransaction(){await Ro(await this.promptPage(this.page.context()))}};import $o from"fs";import un from"path";import{test as mn,chromium as pn}from"@playwright/test";var zt,ew=({slowMo:t=0,profileName:e}={})=>mn.extend({contextPath:async({browserName:a},o,n)=>{let r=await T(`${a}-${n.testId}`);await o(r)},context:async({context:a,contextPath:o},n)=>{let r=new et,i=k(r.name),c=await W(r.name),u=un.resolve(i,e??"wallet-data");if(!$o.existsSync(u))throw new Error("\u274C Cache for Petra wallet data not found. Create it first");$o.cpSync(u,o,{recursive:!0,force:!0});let m=[`--disable-extensions-except=${c}`,`--load-extension=${c}`];process.env.HEADLESS&&(m.push("--headless=new"),t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!"));let p=await pn.launchPersistentContext(o,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:t});await p.grantPermissions(["clipboard-read"]);let{cookies:d,origins:w}=await a.storageState();d&&await p.addCookies(d),w&&w.length>0&&O(w,p);let g=await r.indexUrl();zt=p.pages().find(y=>y.url().startsWith(g))||await _(p,g);for(let y of p.pages()){let h=y.url();(h.includes("about:blank")||h.includes(r.onboardingPath))&&await y.close()}await zt.bringToFront(),await Gt(zt),await n(p),await A(p,o)},petraPage:async({context:a},o)=>{await o(zt)},petra:async({context:a},o)=>{let n=new wt(zt);await o(n)}});import{test as dn}from"@playwright/test";var lw=({slowMo:t,profileName:e,dappUrl:a}={})=>dn.extend({workerScopeContents:[async({browser:o},n,r)=>{let i=new et,{context:c,contextPath:u,walletPage:m}=await kt({wallet:i,workerInfo:r,profileName:e,slowMo:t});await c.grantPermissions(["clipboard-read"]);for(let d of c.pages())d.url().includes(i.onboardingPath)&&await d.close();let p=new wt(m);await p.unlock(),await n({wallet:p,walletPage:m,context:c}),await A(c,u)},{scope:"worker"}],dappPage:[async({workerScopeContents:o},n)=>{let{context:r}=o,i=await r.newPage();a&&await i.goto(a),await n(i)},{scope:"worker"}],petraPage:async({workerScopeContents:o},n)=>{await n(o.walletPage)},petra:async({workerScopeContents:o},n)=>{let r=new wt(o.walletPage);await n(r)}});var E={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"},U={lockWalletButton:"lock-menu-item",closeMenuButton:"settings-menu-close-button",developerSettingsButton:"settings-item-developer-settings",activeNetworksButton:"settings-item-active-networks"},Lo={accountProfileContainer:"sortable-account-container"};var b={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 ce({page:t,privateKey:e,accountName:a,chain:o}){await t.getByTestId(E.openMenuButton).click(),await t.getByTestId(E.addAccountButton).click(),await t.locator(b.importPrivateKeyButton).click();let c=t.locator("span[id^='button--listbox-input--']"),u=await c.textContent(),m=t.locator("input[name='name']"),p=t.locator("textarea[name='privateKey']");u!==o&&(await c.click(),await t.locator("ul[id^='listbox--listbox-input--']").locator(`li[data-label='${o}']`).click()),await m.fill(a),await p.fill(e),await t.locator("button:has-text('Import')").click()}var Et={confirmButton:"primary-button",cancelButton:"secondary-button"};async function Oo(t){let e=t.getByTestId(Et.confirmButton);await t.getByTestId("approve-transaction").waitFor({state:"attached"});let o=t.getByRole("button",{name:"Confirm anyway",exact:!0});if(await o.isVisible().catch(()=>!1)){await o.click();return}await e.click()}import{expect as fn}from"@playwright/test";import wn from"zod";async function Rt(t,e){let a=wn.string().min(1,"Account name cannot be an empty string").parse(e);await t.getByTestId(E.openMenuButton).click();let n=null,r=await t.locator("div[data-testid='account-menu'] div[data-testid='tooltip_interactive-wrapper']").all();for(let i of r)if((await i.textContent())?.includes(a)){n=i;break}if(!n)throw new Error(`Account with name "${a}" not found in the account list.`);await n.click()}async function Do(t,e){e&&await Rt(t,e);let a=t.getByTestId(Et.confirmButton);await fn(a).toBeEnabled({timeout:15e3}),await a.click()}import gn from"zod";var hn=t=>t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");async function Uo({page:t,accountName:e,chain:a}){let o=gn.string().min(1,"Account name cannot be an empty string").parse(e);await t.getByTestId(E.openMenuButton).click(),await t.getByTestId(E.manageAccountsButton).click(),await t.getByTestId(`manage-accounts-sortable-${o}`).click();let c=t.getByRole("button",{name:/Account Address(?:es)?/i});await c.waitFor({state:"visible",timeout:2e4});let m=await c.locator("div[data-name='row.pair'] > div").last().textContent();if(m&&Number(m)===1){await c.locator("> div > div").last().click(),await t.getByTestId("header--back").click();let w=t.getByTestId(U.closeMenuButton);await w.waitFor({state:"visible",timeout:15e3}),await w.click()}else{await c.click();let d=new RegExp(`${hn(a.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 x=t.getByTestId("header--back");await x.waitFor({state:"visible",timeout:15e3}),await x.click();let I=t.getByTestId(U.closeMenuButton);await I.waitFor({state:"visible",timeout:15e3}),await I.click()}return await t.evaluate(async()=>await navigator.clipboard.readText())}async function Ko(t){await t.getByTestId(E.openMenuButton).click(),await t.getByTestId(E.settingsButton).click(),await t.getByTestId(U.lockWalletButton).click()}import{styleText as Ho}from"util";import{expect as yn}from"@playwright/test";var ot=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 H(this.name)}async promptPage(e){let a=await this.promptUrl();return await K({context:e,path:a,locator:"div[id='root']"})}};async function _t(t,e){let o=!1;for(;!e();){let n=e();if(n||o||t.isClosed())break;try{let r=t.locator("div[id='modal']").locator("div > svg").first();await r.isVisible().catch(()=>!1)&&(await r.click(),o=!0)}catch(r){if(t.isClosed())break;console.error("[autoClosePhantomNotification]: ",r)}if(n||o||t.isClosed())break;await B(300)}}async function se({page:t,currentAccountName:e,newAccountName:a}){await t.getByTestId(E.openMenuButton).click(),await t.getByTestId(E.manageAccountsButton).click();let i=await t.getByTestId(Lo.accountProfileContainer).locator("div[data-testid^='manage-accounts-sortable'] div > p").all(),c=null;for(let g of i)if((await g.textContent())?.toLowerCase()===e.toLowerCase()){c=g;break}if(!c)throw new Error(`Account with name "${e}" not found`);await c.click(),await t.locator("button:has-text('Account Name')").click();let m=t.locator("input[name='name']");await m.clear(),await m.fill(a),await t.getByTestId("primary-button").click(),await t.getByTestId("header--back").click(),await t.getByTestId(U.closeMenuButton).click()}async function le(t){await t.getByTestId(E.openMenuButton).click(),await t.getByTestId(E.settingsButton).click()}async function ue({page:t,...e}){await le(t);let a=t.locator(`button[id='${U.developerSettingsButton}']`);await a.scrollIntoViewIfNeeded(),await a.click();let o=t.getByTestId("toggleTestNetwork"),r=await o.locator("label[data-testid='toggleTestNetwork-switch'] > input[aria-label='Toggle']").isChecked().catch(()=>!1);if(!r&&e.mode==="on"&&await o.click(),r&&e.mode==="off"){await o.click(),await t.getByTestId("header--back").click(),await t.getByTestId(U.closeMenuButton).click();return}if(e.mode==="on"&&e.chain==="Solana"){let{network:u}=e;await t.locator(`button:has-text("${u}")`).click()}if(e.mode==="on"&&e.chain==="Ethereum"){let{network:u}=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(`
|
|
14
|
-
`));await t.locator(`button:has-text("${u}")`).click()}await t.getByTestId("header--back").click(),await t.getByTestId(U.closeMenuButton).click()}async function Ee({page:t,addWallet:e,...a}){console.info(
|
|
15
|
-
Phantom onboarding started...`,{validateStream:!1}));let o=await P("phantom");if(a.mode==="create"){await t.locator(b.createNewWalletButton).click(),await t.getByTestId(b.createSeedPhraseWalletButton).click();let g=t.getByTestId(b.passwordInput),f=t.getByTestId(b.passwordConfirmInput),y=t.getByTestId(b.termsCheckBox),h=t.locator(b.continueButton);await g.fill(o),await f.fill(o),await y.click(),await h.click(),await h.locator("> div > svg").waitFor({state:"detached",timeout:3e4}),await t.getByTestId(b.recoveryPhraseSavedCheckbox).click(),await h.click(),await B(1e3),await h.click(),await t.locator(b.getStartedButton).last().click()}if(a.mode==="recovery phrase"){let w=a.secretRecoveryPhrase.split(" ");await t.locator(b.IAlreadyHaveAWalletButton).click(),await t.locator(b.importRecoveryPhraseButton).click();for(let[it,at]of Object.entries(w))await t.getByTestId(`${b.recoveryPhraseInput}-${it}`).fill(at);await t.locator(b.importWalletButton).click(),await t.locator("p:has-text('Finding accounts with activity')").waitFor({state:"detached",timeout:6e4});let x=t.locator(b.continueButton);await x.click();let I=t.getByTestId(b.passwordInput),S=t.getByTestId(b.passwordConfirmInput),v=t.getByTestId(b.termsCheckBox);await I.fill(o),await S.fill(o),await v.click(),await x.click(),await x.locator("> div > svg").waitFor({state:"detached",timeout:3e4}),await t.locator(b.getStartedButton).last().click()}if(a.mode==="private key"){await t.locator(b.IAlreadyHaveAWalletButton).click();let{privateKey:w,chain:g,accountName:f}=a;await t.locator(b.importPrivateKeyButton).click();let h=t.locator("span[id='button--listbox-input--1']"),x=await h.textContent(),I=t.locator("input[name='name']"),S=t.locator("textarea[name='privateKey']");x!==g&&(await h.click(),await t.locator("ul[id='listbox--listbox-input--1']").locator(`li[data-label='${g}']`).click()),await I.fill(f),await S.fill(w),await t.locator("button:has-text('Import')").click();let V=t.getByTestId(b.passwordInput),L=t.getByTestId(b.passwordConfirmInput),it=t.getByTestId(b.termsCheckBox);await V.fill(o),await L.fill(o),await it.click();let at=t.locator(b.continueButton);await at.click(),await at.locator("> div > svg").waitFor({state:"detached",timeout:3e4}),await t.locator(b.getStartedButton).last().click()}let n=await t.context().newPage(),r=await new ot().indexUrl();await n.goto(r);let c=await t.context().browser()?.newBrowserCDPSession(),u;await yn.poll(async()=>{if(c){let{targetInfos:d}=await c.send("Target.getTargets"),g=d.filter(f=>f.title==="Phantom Wallet").find(f=>!f.attached&&f.url===r);return u=g,!!g}},{timeout:2e4}).toBe(!0),u&&await c?.send("Target.closeTarget",{targetId:u.targetId});let m=await n.getByTestId("home-header-account-name").textContent();if(a.mode==="create"){let{accountName:d}=a;await se({page:n,newAccountName:d,currentAccountName:"Account 1"})}if(e&&e.length>0){let d=!1;_t(n,()=>d).catch(f=>console.error({error:f}));for(let{accountName:f,chain:y,privateKey:h}of e)await ce({page:n,privateKey:h,accountName:f,chain:y}),d=!0;let g=a.mode==="create"?a.accountName:m;g&&await Rt(n,g)}a.toggleNetworkMode&&await ue({page:n,...a.toggleNetworkMode}),await B(3e3),console.info(Ho("greenBright","\u2728 Phantom onboarding completed successfully",{validateStream:!1}))}async function jo(t){let e=t.getByTestId(Et.cancelButton);await t.getByTestId("approve-transaction").waitFor({state:"attached"}),await e.click()}async function Go({page:t,supportedChains:e,toggleMode:a="off"}){if(await le(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 i of e){let c=t.locator(`button[id='toggle-${i.toLowerCase()}']`),m=await c.locator(`label[data-testid='toggle-${i.toLowerCase()}-switch'] > input[aria-label='Toggle']`).isChecked().catch(()=>!1);a==="off"&&m&&await c.click(),a==="on"&&!m&&await c.click()}await t.getByTestId("header--back").click(),await t.getByTestId(U.closeMenuButton).click()}async function me(t){let e=await P("phantom"),a=t.locator("input[name='password']"),o=t.getByTestId("unlock-form-submit-button");await a.fill(e),await o.click(),await o.waitFor({state:"detached"})}var ft=class extends ot{page;constructor(e){super(),this.page=e}async onboard({...e}){await Ee({page:this.page,...e})}async unlock(){await me(this.page)}async lock(){await Ko(this.page)}async renameAccount({...e}){await se({page:this.page,...e})}async switchAccount(e){await Rt(this.page,e)}async getAccountAddress({accountName:e,chain:a}){return await Uo({page:this.page,accountName:e,chain:a})}async addAccount({...e}){await ce({page:this.page,...e})}async toggleOptionalChains({toggleMode:e,supportedChains:a}){await Go({page:this.page,supportedChains:a,toggleMode:e})}async switchNetwork({...e}){await ue({page:this.page,...e})}async connectToApp(e){await Do(await this.promptPage(this.page.context()),e)}async confirmTransaction(){await Oo(await this.promptPage(this.page.context()))}async rejectTransaction(){await jo(await this.promptPage(this.page.context()))}};import zo from"fs";import xn from"path";import{test as Bn,chromium as kn}from"@playwright/test";var Vt,cg=({slowMo:t=0,profileName:e}={})=>Bn.extend({contextPath:async({browserName:a},o,n)=>{let r=await T(`${a}-${n.testId}`);await o(r)},context:async({context:a,contextPath:o},n)=>{let r=new ot,i=k(r.name),c=await W(r.name),u=xn.resolve(i,e??"wallet-data");if(!zo.existsSync(u))throw new Error("\u274C Cache for Phantom wallet data not found. Create it first");zo.cpSync(u,o,{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 m=await kn.launchPersistentContext(o,{headless:!1,args:[`--disable-extensions-except=${c}`,`--load-extension=${c}`],slowMo:process.env.HEADLESS?0:t});await m.grantPermissions(["clipboard-read"]);let{cookies:p,origins:d}=await a.storageState();p&&await m.addCookies(p),d&&d.length>0&&await O(d,m);let w=await r.indexUrl();Vt=m.pages().find(f=>f.url().startsWith(w))||await _(m,w);for(let f of m.pages())f.url().includes("about:blank")&&await f.close();await Vt.bringToFront(),await me(Vt),await n(m),await A(m,o)},phantomPage:async({context:a},o)=>{await o(Vt)},phantom:async({context:a},o)=>{let n=new ft(Vt);await o(n)},autoCloseNotification:[async({context:a},o)=>{let n=!1,i=_t(Vt,()=>n);await o(void 0),n=!0,await i.catch(c=>{console.error(`Auto close notification error: ${c.message}`)})},{auto:!0}]});import{test as An}from"@playwright/test";import qo from"fs";import bn from"path";import{chromium as Pn}from"@playwright/test";async function Yo({workerInfo:t,profileName:e,slowMo:a}){let o=new ot,n=await T(t.workerIndex.toString()),r=k(o.name),i=bn.resolve(r,e??"wallet-data");if(!qo.existsSync(i))throw new Error(`Cache for ${o.name} does not exist. Create it first!`);qo.cpSync(i,n,{recursive:!0,force:!0});let c=await W(o.name),u=await Pn.launchPersistentContext(n,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:a}),m=await o.indexUrl(),p=await _(u,m);return{context:u,walletPage:p,contextPath:n}}var Cg=({slowMo:t,profileName:e,dappUrl:a}={})=>An.extend({workerScopeContents:[async({browser:o},n,r)=>{let{context:i,contextPath:c,walletPage:u}=await Yo({workerInfo:r,profileName:e,slowMo:t});await i.grantPermissions(["clipboard-read"]);for(let p of i.pages())p.url().includes("about:blank")&&await p.close();let m=new ft(u);await m.unlock(),await n({wallet:m,walletPage:u,context:i}),await A(i,c)},{scope:"worker"}],dappPage:[async({workerScopeContents:o},n)=>{let{context:r}=o,i=await r.newPage();a&&await i.goto(a),await n(i)},{scope:"worker"}],phantomPage:async({workerScopeContents:o},n)=>{await n(o.walletPage)},phantom:async({workerScopeContents:o},n)=>{let r=new ft(o.walletPage);await n(r)},autoCloseNotification:[async({workerScopeContents:o},n)=>{let r=!1,i=()=>r,c=_t(o.walletPage,i);await n(void 0),r=!0,await c.catch(u=>{console.error(`Auto close notification error: ${u.message}`)})},{auto:!0}]});var gt={networkSettings:"li-settings-network",selectNetwork:"select-network",confirmModal:"modal-confirm",confifmButton:"btn-confirm",securityAndPrivacyButton:"nav-item-security-and-privacy",lockButton:"btn-lock"},$t={portfolioButton:"nav-item-portfolio",walletSelectorButton:"icon-section-wallet-picker-arrow-right"};import pe from"zod";var Qo=pe.object({walletName:pe.string().min(1,"Wallet name cannot be an empty string"),privateKey:pe.array(pe.number()).length(64)});async function de({page:t,privateKey:e,walletName:a}){let o=Qo.parse({privateKey:e,walletName:a});await t.getByTestId($t.walletSelectorButton).click(),await t.getByTestId("icon-btn-add").click(),await t.getByTestId("li-add-wallet-privateKey-add").click();let c=t.getByTestId("input-name"),u=t.getByTestId("input-private-key");await c.fill(o.walletName),await u.fill(`${o.privateKey}`),await t.getByTestId("btn-import").click(),await t.locator("span:has-text('My wallets')").waitFor({state:"attached"}),await t.getByRole("dialog").getByTestId("icon-btn-close").click()}import{expect as Cn}from"@playwright/test";var we={approveButton:"btn-approve",rejectButton:"btn-reject"};async function Xo(t){let e=t.getByTestId(we.approveButton);await t.getByTestId("section-network-fee").waitFor({state:"attached",timeout:3e4}).catch(async()=>{console.error("Network fee section did not appear within the timeout period, which may indicate that the transaction confirmation popup did not load correctly."),await t.getByText("Network mismatch",{exact:!0}).isVisible().catch(()=>!1)&&(await t.getByRole("button",{name:"Close",exact:!0}).click(),console.error("A 'Network mismatch' error was detected in the popup. Closing the popup and aborting the transaction confirmation process."))});let o=t.locator("div[data-id='control-label']");await o.isVisible().catch(()=>!1)&&await o.click(),await Cn(e).toBeEnabled(),await e.click()}async function fe(t,e){await t.getByTestId("icon-section-wallet-picker-arrow-right").click();let o=t.getByTestId("list-item-m-title").filter({hasText:e}).locator("xpath=../..");if(!await o.isVisible().catch(()=>!1))throw new Error(`Account "${e}" not found. Make sure the account is onboarded or verify the account name.`);await o.click()}async function Zo(t,e){e&&await fe(t,e),await t.getByRole("button",{name:"Connect",exact:!0}).click()}async function Jo(t){return await t.getByTestId("icon-section-wallet-picker-copy").click(),await t.evaluate(async()=>await navigator.clipboard.readText())}async function ge(t){let e=t.getByRole("button",{name:"settings",exact:!0});await e.waitFor({state:"attached",timeout:3e4}),await e.click()}async function ta(t){await ge(t),await t.getByTestId(gt.securityAndPrivacyButton).click(),await t.getByTestId("li-settings-lock").getByTestId(gt.lockButton).click()}import{styleText as ea}from"util";var st={alreadyHaveAWalletButton:"btn-already-have-wallet",recoveryPhraseInput:"input-recovery-phrase",continueButton:"btn-continue",passwordInput:"input-new-password",repeatPasswordInput:"input-repeat-password",quickSetupButton:"btn-quick-setup",IAgreeButton:"btn-explore"};async function he({page:t,currentAccountName:e,newAccountName:a}){await t.getByTestId($t.walletSelectorButton).click();let n=t.locator(`button[data-testid^='li-wallets']:has-text('${e}')`);if(!await n.isVisible().catch(()=>!1))throw new Error(`Account "${e}" not found. Make sure the account is available.`);await n.hover({timeout:2e4}),await n.getByTestId("icon-btn-three-dots").click({timeout:2e4});let c=t.getByTestId("li-manage-wallet-rename-wallet");await c.click();let u=t.getByTestId("input-name");await u.clear(),await u.fill(a),await t.getByTestId("btn-save").click(),await c.waitFor({state:"attached",timeout:15e3}),await t.getByTestId("icon-btn-close").click()}async function ye(t,e){await ge(t);let o=t.getByTestId("li-settings-network").getByRole("combobox");await o.locator(" > p").textContent()!==e?(await o.click(),await t.getByTestId(gt.selectNetwork).getByRole("option",{name:e,exact:!0}).click(),(e==="Devnet"||e==="Testnet")&&await t.getByTestId(gt.confirmModal).getByTestId(gt.confifmButton).click()):console.info(`Network is already set to ${e}`),await t.getByTestId($t.portfolioButton).click()}async function oa({page:t,recoveryPhrase:e,network:a,walletName:o,addWallet:n}){console.info(ea("yellowBright",`
|
|
16
|
-
Solflare onboarding started...`,{validateStream:!1}));let r=await
|
|
1
|
+
import{expect as Ue}from"@playwright/test";function B(t){return new Promise(e=>setTimeout(e,t))}async function _(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}import Oe from"fs";import pa from"path";import ua from"path";var Le=".wallet-cache",$e=".wallet-context";var Ve="13.22.0",$t="https://github.com/amaify/chainwright/releases/download/v0.1.0/",Fn=`https://github.com/MetaMask/metamask-extension/releases/download/v${Ve}/metamask-chrome-${Ve}.zip`,En=`${$t}solflare-wallet-extension-v2.19.1.zip`,Mn=`${$t}petra-wallet-extension-v2.4.8.zip`,_n=`${$t}phantom-wallet-extension-v26.10.0.zip`,Rn=`${$t}meteor-wallet-extension-v0.7.0.zip`,Vn=`${$t}keplr-wallet-extension-v0.13.3.zip`;function k(t){return ua.resolve(process.cwd(),Le,t)}async function A(t){let e=k(t),a=pa.resolve(e,"password.txt");try{if(!Oe.existsSync(a))throw new Error("\u274C password.txt not found. Run setup script first.");return Oe.readFileSync(a,"utf-8")}catch(o){throw new Error(`\u274C Failed to get ${t} password from cache: ${o.message}`)}}import{expect as ma}from"@playwright/test";async function K({context:t,path:e,locator:a}){let o;try{await ma.poll(async()=>(o=t.pages().filter(n=>n.url().startsWith("chrome-extension://")).find(n=>n.url().match(e)),!!o),{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(!o)throw new Error(`Popup page with path ${e} not found in context.`);return await da(o,a),await o.setViewportSize({width:360,height:592}),o}async function da(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 De from"fs";import wa from"path";async function H(t){let e=k(t),a=wa.resolve(e,"extension-id.txt");try{if(!De.existsSync(a))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return De.readFileSync(a,"utf-8")}catch(o){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${o.message}`)}}var G=class{name="keplr";onboardingPath="register.html";async indexUrl(){return`chrome-extension://${await this.extensionId()}/sidePanel.html`}async onboardingUrl(){return`chrome-extension://${await this.extensionId()}/${this.onboardingPath}`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/popup.html`}async extensionId(){return await H(this.name)}async promptPage(e){let a=await this.promptUrl();return await K({context:e,path:a,locator:"div[data-simplebar='init']"})}};var z={importExistingWalletButton:"button:has-text('Import an existing wallet')",usePrivateKeyButton:"button:has-text('Use recovery phrase or private key')",privateKeyTabButton:"button:has-text('Private key')",privateKeyInput:"input[type='password']",importButton:"button:has-text('Import')",walletNameInput:"input[name='name']",walletPasswordInput:"input[name='password']",confirmWalletPasswordInput:"input[name='confirmPassword']",nextButton:"button:has-text('Next')",searchNetworkInput:"input[placeholder='Search networks']",saveButton:"button:has-text('Save')",finishButton:"button:has-text('Finish')"};function fa(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}async function xt({page:t,privateKey:e,walletName:a,chains:o,mode:n="onboard"}){let r=await A("keplr"),i=new G;if(await t.locator(z.importExistingWalletButton).click(),await t.locator(z.usePrivateKeyButton).click(),await t.getByRole("button",{name:"Private key",exact:!0}).click(),await t.locator(z.privateKeyInput).fill(e),await t.getByRole("button",{name:"Import",exact:!0}).click(),await t.locator(z.walletNameInput).fill(a),n==="onboard"){let v=t.locator(z.walletPasswordInput),V=t.locator(z.confirmWalletPasswordInput);await v.fill(r),await V.fill(r)}await t.locator(z.nextButton).click();let f=t.locator("div:has-text('All Native Chains')").nth(-4),y=t.locator("div[cursor='pointer']:has-text('Cosmos Hub')"),h=await f.locator("input[type='checkbox']").getAttribute("checked"),x=await y.locator("input[type='checkbox']").getAttribute("checked");h!==null&&await f.click(),x!==null&&await y.click();let T=t.locator(z.searchNetworkInput);for(let v of o){await T.fill(v);let $=t.locator("div[class='simplebar-content']").locator("div[cursor] > div").first().locator("div").filter({hasText:new RegExp(`^${fa(v)}$`,"i")}).nth(2).locator("../../../../..");await $.waitFor({state:"visible",timeout:2e4}),await $.locator("input[type='checkbox']").getAttribute("checked")===null&&await $.click()}let S=t.locator(z.saveButton);if(await S.scrollIntoViewIfNeeded(),await S.click(),await B(2e3),n==="onboard"){await t.goto(await i.indexUrl());return}if(n==="add-account-single"){let v=t.locator(z.finishButton);await v.waitFor({state:"visible",timeout:2e4}),await Ue(v).toBeEnabled({timeout:2e4}),await v.click()}}async function Qt(t){let a=await new G().onboardingUrl();await t.getByRole("link",{name:"Settings",exact:!0}).click(),await t.locator("div[cursor='pointer']").first().click(),await t.getByRole("button",{name:"Add Wallet",exact:!0}).click();let i;if(await Ue.poll(async()=>(i=t.context().pages().find(c=>c.url().match(a)),!!i),{timeout:3e4}).toBe(!0).catch(c=>{console.error(`Failed to find onboarding page with URL matching ${a}. Original error: ${c}`)}),!i)throw new Error(`Onboarding page not found. Expected URL: ${a}`);return await _(i),await i.bringToFront(),i}async function Ke({page:t,privateKey:e,chains:a,walletName:o,mode:n}){let r=await Qt(t);await xt({page:r,privateKey:e,walletName:o,chains:a,mode:n}),await t.locator("div:has(div:has-text('Select Wallet'))").nth(-4).locator("div:has(> div > svg)").first().click(),await t.getByRole("link",{name:"Home",exact:!0}).click()}import{expect as ga}from"@playwright/test";var Zt={approveButton:"button:has-text('Approve')",rejectButton:"button[color='secondary']"};async function He(t){let e=t.locator(Zt.approveButton);await ga(e).toBeEnabled({timeout:2e4}),await e.click()}async function je(t){t.getByRole("button",{name:"Approve",exact:!0}).click(),await B(1e3)}import{expect as ha}from"@playwright/test";import q from"zod";var Ge=q.discriminatedUnion("chain",[q.object({chain:q.literal(["Injective","Injective (Testnet)","Polygon"]),walletName:q.string().min(1,"Wallet name cannot be an empty string")}),q.object({chain:q.literal(["Bitcoin","Bitcoin Signet","Bitcoin Testnet"]),chainTag:q.literal(["Taproot","Native Segwit"]),walletName:q.string().min(1,"Wallet name cannot be an empty string")})]),ze=q.object({currentAccountName:q.string().min(1,"Current account name cannot be an empty string"),newAccountName:q.string().min(1,"New account name cannot be an empty string")});async function qe({page:t,...e}){let a=Ge.parse({...e});await t.getByRole("textbox",{name:"Search for asset or chain (i.e. ATOM, Cosmos)",exact:!0}).fill(a.chain);let n=t.locator(`div:has-text("${a.chain}")`).nth(-2).filter({hasNot:t.locator("span")});if(await n.waitFor({state:"attached",timeout:2e4}),!await n.isVisible().catch(()=>!1))throw Error(`Make sure "${a.chain}" is activated.`);let i=await n.locator("div").all();ha(i.length).toBeGreaterThan(0),await t.locator(`div:has(div:has-text('${a.walletName}'))`).nth(-3).locator("div:has(> div > svg)").click();let p=t.locator("div:has(> div[data-simplebar='init'])").last(),d=p.locator("div:has(> div > input)").locator("input");await d.fill(a.chain);let g=await p.locator("div[cursor='pointer']",{hasText:a.chain}).all(),f;for(let h of g){let x;"chainTag"in e&&(x=e.chainTag);let T=h.locator("div",{hasText:a.chain}).last(),S=x?h.locator("div",{hasText:x}).last():null,V=(S?await S?.isVisible().catch(()=>!1):!1)?await S?.textContent():null,$=await T.textContent(),it=V?`${$} ${V}`:$,at=x?`${a.chain} ${x}`:a.chain;if(it===at){f=T.locator("xpath=../../../.."),await d.clear();break}}if(!f)throw Error(`Address for ${a.walletName} account on "${a.chain}" chain not found.`);return await f.hover(),await f.scrollIntoViewIfNeeded(),await f.click(),await t.evaluate(async()=>await navigator.clipboard.readText())}var Ot={openSidebarMenuButton:"div[cursor='pointer']:has(> div[cursor='pointer'])",menuPopupContent:"div[id='modal-root-3']",lockWalletButton:"div:has(> div:has-text('Lock Wallet'))",settingsButton:"div:has(a[href='#/settings'])"},be={unlockButton:"button[type='submit']:has-text('Unlock')",passwordInput:"input[placeholder='Type Your Password']"};async function Ye(t){await t.locator(Ot.openSidebarMenuButton).click(),await t.locator(Ot.lockWalletButton).nth(-1).click(),await t.getByText("Welcome Back").waitFor({state:"visible",timeout:3e4})}import{styleText as Xe}from"util";import{expect as ya}from"@playwright/test";async function Jt(t,e){let a=t.locator("div[color]").nth(1);if(await a.textContent()===e){console.info(`
|
|
2
|
+
Already on ${e} account. No need to switch.`);return}await a.click();let n=t.locator("div[class='simplebar-content'] > div").locator("> div",{hasText:e});if(!await n.isVisible().catch(()=>!1))throw new Error(`Account "${e}" not found. Make sure the account is onboarded or verify the account name.`);let i=t.locator("div:has-text('Select Wallet')").last();await n.click(),await i.waitFor({state:"detached",timeout:3e4})}async function Ae({page:t,onboard:e}){if(console.info(Xe("yellowBright",`
|
|
3
|
+
Keplr onboarding started...`,{validateStream:!1})),e.length===1)for(let{privateKey:a,walletName:o,chains:n}of e)await xt({page:t,privateKey:a,walletName:o,chains:n,mode:"onboard"});if(e.length>1){let a=e[0];if(a){let{privateKey:m,walletName:d,chains:w}=a;await xt({page:t,privateKey:m,walletName:d,chains:w,mode:"onboard"})}let o=e.slice(1);for(let{privateKey:m,walletName:d,chains:w}of o){let g=await Qt(t);await xt({page:g,privateKey:m,walletName:d,chains:w,mode:"add-account-single"})}await t.locator("div",{hasText:"Select Wallet"}).last().locator("../../..").locator("div > svg").click(),await t.getByRole("link",{name:"Home",exact:!0}).click();let c=t.locator(Ot.openSidebarMenuButton);await ya(c).toBeVisible({timeout:3e4});let u=e.at(-1)?.walletName,p=e[0]?.walletName;u&&p&&await Jt(t,p)}await B(3e3),console.info(Xe("greenBright","\u2728 Keplr onboarding completed successfully",{validateStream:!1}))}async function Qe(t){let e=t.locator(Zt.rejectButton);await e.waitFor({state:"visible",timeout:2e4}),await e.click()}async function Ze({page:t,currentAccountName:e,newAccountName:a}){let o=ze.parse({currentAccountName:e,newAccountName:a});await t.getByRole("link",{name:"Settings",exact:!0}).click(),await t.locator("div[cursor='pointer']").first().click();let i=t.locator("div",{hasText:o.currentAccountName}).nth(-4);if(!await i.isVisible().catch(()=>!1))throw Error(`Account with name "${o.currentAccountName}" not found`);await i.locator("div[cursor='pointer'] svg").click(),await t.locator("div > div[cursor='pointer'] > div:has-text('Change Wallet Name')").last().click(),await t.locator("input[name='name']").fill(o.newAccountName),await t.locator("button:has-text('Save')").click()}async function te(t){let e=await A("keplr");await t.locator(be.passwordInput).fill(e),await t.locator(be.unlockButton).click(),await t.locator("div:has-text('Deposit')").last().waitFor({state:"visible",timeout:3e4})}var ut=class extends G{page;constructor(e){super(),this.page=e}async onboard(e){await Ae({page:this.page,onboard:e})}async unlock(){await te(this.page)}async lock(){await Ye(this.page)}async renameAccount({currentAccountName:e,newAccountName:a}){await Ze({page:this.page,currentAccountName:e,newAccountName:a})}async switchAccount(e){await Jt(this.page,e)}async getAccountAddress({...e}){return await qe({page:this.page,...e})}async addAccount({chains:e,privateKey:a,walletName:o,mode:n="add-account-multiple"}){await Ke({page:this.page,privateKey:a,walletName:o,chains:e,mode:n})}async connectToApp(){await je(await this.promptPage(this.page.context()))}async confirmTransaction(){await He(await this.promptPage(this.page.context()))}async rejectTransaction(){await Qe(await this.promptPage(this.page.context()))}};import eo from"fs";import Pa from"path";import{test as Ca,chromium as Sa}from"@playwright/test";import xa from"path";async function I(t){return xa.resolve(process.cwd(),$e,t)}import{expect as Ba}from"@playwright/test";async function R(t,e){let a=await t.newPage();return await Ba(async()=>{await a.goto(e),await _(a)}).toPass(),a}async function O(t,e){let a=await e.newPage();for(let{origin:o,localStorage:n}of t){let r=a.mainFrame();await r.goto(o),await r.evaluate(i=>{i.forEach(({name:c,value:u})=>{window.localStorage.setItem(c,u)})},n)}await a.close()}import ka from"fs/promises";async function Je(t){await ka.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var ba=35e3;async function P(t,e){try{await Promise.race([t.close(),new Promise((a,o)=>setTimeout(()=>o(new Error("Context close timed out")),ba))])}catch(a){console.warn(`Browser context close did not complete cleanly: ${a.message}`)}try{await Je(e)}catch(a){console.error(`Failed to remove temporary context directory at ${e}. Error:`,a)}}import to from"fs";import Aa from"path";async function W(t){try{let e=k(t),a=Aa.resolve(e,"extension-path.txt");if(!to.existsSync(a))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let o=to.readFileSync(a,"utf-8").trim();if(!o)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return o}catch(e){throw new Error(`\u274C Failed to get ${t} extension path: ${e.message}`)}}var Bt,tc=({slowMo:t=0,profileName:e}={})=>Ca.extend({contextPath:async({browserName:a},o,n)=>{let r=await I(`${a}-${n.testId}`);await o(r)},context:async({context:a,contextPath:o},n)=>{let r=new G,i=k(r.name),c=await W(r.name),u=Pa.resolve(i,e??"wallet-data");if(!eo.existsSync(u))throw new Error("\u274C Cache for Keplr wallet data not found. Create it first");eo.cpSync(u,o,{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 m=await Sa.launchPersistentContext(o,{headless:!1,args:p,slowMo:process.env.HEADLESS?0:t});await m.grantPermissions(["clipboard-read"]);let{cookies:d,origins:w}=await a.storageState();d&&await m.addCookies(d),w&&w.length>0&&O(w,m);let g=await r.indexUrl();Bt=m.pages().find(y=>y.url().startsWith(g))||await R(m,g),await _(Bt);for(let y of m.pages()){let h=y.url();(h.includes("about:blank")||h.includes(r.onboardingPath))&&await y.close()}await Bt.bringToFront(),await te(Bt),await n(m),await P(m,o)},keplrPage:async({context:a},o)=>{await o(Bt)},keplr:async({context:a},o)=>{let n=new ut(Bt);await o(n)}});import{test as Ia}from"@playwright/test";import oo from"fs";import va from"path";import{chromium as Ta}from"@playwright/test";async function kt({wallet:t,workerInfo:e,profileName:a,slowMo:o}){let n=await I(e.workerIndex.toString()),r=k(t.name),i=va.resolve(r,a??"wallet-data");if(!oo.existsSync(i))throw new Error(`Cache for ${t.name} does not exist. Create it first!`);oo.cpSync(i,n,{recursive:!0,force:!0});let c=await W(t.name),u=await Ta.launchPersistentContext(n,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:o}),p=await t.indexUrl(),m=u.pages()[0];return m||(m=await u.newPage()),await m.goto(p),{context:u,walletPage:m,contextPath:n}}var gc=({slowMo:t,profileName:e,dappUrl:a}={})=>Ia.extend({workerScopeContents:[async({browser:o},n,r)=>{let i=new G,{context:c,contextPath:u,walletPage:p}=await kt({wallet:i,workerInfo:r,profileName:e,slowMo:t});await c.grantPermissions(["clipboard-read"]);for(let d of c.pages())d.url().includes("about:blank")&&await d.close();let m=new ut(p);await m.unlock(),await n({wallet:m,walletPage:p,context:c}),await P(c,u)},{scope:"worker"}],dappPage:[async({workerScopeContents:o},n)=>{let{context:r}=o,i=await r.newPage();a&&await i.goto(a),await n(i)},{scope:"worker"}],keplrPage:async({workerScopeContents:o},n)=>{await n(o.walletPage)},keplr:async({workerScopeContents:o},n)=>{let r=new ut(o.walletPage);await n(r)}});import{expect as D}from"@playwright/test";import no from"zod";import{test as Wa}from"@playwright/test";function ao(t,e){t&&(console.warn(`
|
|
4
|
+
\u26A0\uFE0F Skipping test: ${e}`),Wa.skip())}var C={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"},bt={lockButton:"global-menu-lock",networksButton:"global-menu-networks"},Dt={passwordInput:"unlock-password",unlockButton:"unlock-submit"},nt={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 E={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 ro({page:t,privateKey:e,accountName:a}){let o=no.string().min(1,"Account name cannot be an empty string").trim().parse(a),n=no.string().min(1,"Private key cannot be an empty string").trim().parse(e),r=t.getByTestId(C.accountMenuButton);await D(r).toBeVisible({timeout:3e4}),await r.click(),await D(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let i=t.getByTestId(nt.addWalletButton),c=await i.textContent();c?.includes("Syncing")&&await D.poll(async()=>(await i.textContent())?.trim()??"",{timeout:12e4}).not.toBe(c),await D(i).toBeEnabled({timeout:6e4}),await i.click();let u=t.getByRole("dialog");await D(u).toContainText(/add wallet/i),await t.getByTestId(nt.importAccountButton).click(),await t.locator("input[id='private-key-box']").fill(n);let d=t.getByTestId(E.importAccountConfirmButton);await D(d).toBeEnabled(),await d.click();let w=t.getByTestId(E.importSRPError),g=await w.isVisible().catch(()=>!1);g&&ao(g,`${(await w.textContent())?.split(".")[0]}`);let f=t.locator("div:has(> div[data-testid^='multichain-account-cell-keyring'][class*='mm-box--background-color-background-muted'])"),y=(await f.textContent())?.split("$")[0];y&&await Na({page:t,accountName:o,activeAccountLocator:f,activeAccountName:y}),await t.locator("button[aria-label='Back']").first().click()}async function Na({page:t,accountName:e,activeAccountLocator:a,activeAccountName:o}){let n=a.locator(`div[aria-label='${o} options']`);await D(n).toBeVisible(),await n.click(),await D(t.getByRole("tooltip")).toBeVisible();let r=t.locator(`div[aria-label='${nt.renameAccountLabel}']`);await D(r).toBeVisible(),await r.click();let i=t.getByRole("dialog"),c=i.getByRole("heading",{name:/rename/i});await D(c).toBeVisible();let u=i.getByRole("textbox");await D(u).toBeVisible(),await u.fill(e);let p=i.getByRole("button",{name:/confirm/i});await D(p).toBeEnabled(),await p.click(),await i.waitFor({state:"detached",timeout:2e4});let m=t.locator("div:has(> div[data-testid^='multichain-account-cell-keyring'][class*='mm-box--background-color-background-muted'])");await D(m).toContainText(e)}import{expect as Ut}from"@playwright/test";import At from"zod";var io=At.object({networkName:At.string().min(1,"Network name cannot be an empty string"),rpcUrl:At.url(),chainId:At.number().or(At.string().includes("0x")),currencySymbol:At.string().toUpperCase().min(1,"Currency symbol cannot be an empty string")});import{expect as Fa}from"@playwright/test";async function ee(t){let e=t.locator("div:has(> p[data-testid='notifications-tag-counter__unread-dot'])"),a=t.getByTestId(C.openSettingsButton);await e.isVisible().catch(()=>!1)?await e.click():(await Fa(a).toBeVisible(),await a.click())}async function co({page:t,...e}){let{chainId:a,currencySymbol:o,networkName:n,rpcUrl:r}=io.parse({...e},{reportInput:!0});await ee(t),await t.getByTestId(bt.networksButton).click();let c=t.locator("section[role='dialog']");await Ut(c).toContainText(/manage networks/i),await t.getByRole("button",{name:/add a custom network/i}).click(),await Ut(c).toContainText(/Add a custom network/i);let p=t.getByTestId("network-form-network-name"),m=t.getByTestId("test-add-rpc-drop-down"),d=t.getByTestId("network-form-chain-id"),w=t.getByTestId("network-form-ticker-input");await p.fill(n),await m.click(),await t.getByRole("tooltip").locator("div:has(> button:has-text('Add RPC URL'))").click(),await Ut(c).toContainText(/Add RPC URL/i);let y=t.getByTestId("rpc-url-input-test"),h=t.getByRole("button",{name:/Add URL/i});await y.fill(r),await h.click(),await Ut(c).toContainText(/Add a custom network/i);let x=t.getByTestId("network-form-chain-id-error");if(await x.isVisible().catch(()=>!1)){let v=await x.textContent();throw Error(`RPC error: ${v}`)}await d.fill(`${a}`),await w.fill(o);let S=t.getByRole("button",{name:/save/i});await Ut(S).toBeEnabled(),await S.click()}import{expect as so}from"@playwright/test";var oe={confirmButton:"confirm-footer-button",cancelButton:"confirm-footer-cancel-button"};async function lo(t,e){let a=t.getByTestId(oe.confirmButton);await B(2e3);let n=(await a.textContent())?.includes("Review alert"),r=await a.isDisabled().catch(()=>!1);if(n&&r){await t.getByTestId("edit-gas-fees-row").locator("> div").first().click();let m=t.getByRole("dialog");await so(m).toBeVisible();let d=m.locator("h4",{hasText:"Insufficient funds"}),w=await m.getByTestId("alert-modal__selected-alert").textContent();if(await d.isVisible().catch(()=>!1))throw Error(`${w}`)}if(e){let u=t.getByTestId("edit-gas-fee-icon");if(await u.scrollIntoViewIfNeeded(),await u.click(),e.feeType!=="advanced"&&await t.getByTestId(`gas-option-${e.feeType}`).click(),e.feeType==="advanced"){await t.getByTestId("gas-option-advanced").click();let m=t.getByRole("textbox",{name:"Max base fee"}),d=t.getByRole("textbox",{name:"Priority fee"}),w=t.getByRole("button",{name:"Save",exact:!0});await m.fill(e.maxBaseFee),await d.fill(e.priorityFee),await w.click()}}await so(a).toBeEnabled(),await a.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 Ea}from"@playwright/test";import{expect as Pe}from"@playwright/test";async function Pt({page:t,accountName:e}){let a=t.getByTestId(C.accountMenuButton);if(await a.textContent()===e){console.info(`Can't switch account to "${e}", it is already selected.`);return}await Pe(a).toBeVisible({timeout:15e3}),await a.click(),await Pe(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let n=t.getByTestId(nt.addMultichainAccountButton),r=await n.textContent();r?.includes("Syncing")&&await Pe.poll(async()=>(await n.textContent())?.trim()??"",{timeout:6e4}).not.toBe(r);let i=await t.getByTestId(/^multichain-account-cell-(?:entropy|keyring):/).all(),c=null;for(let u of i)if(await u.scrollIntoViewIfNeeded(),(await u.textContent())?.includes(e)){c=u;break}if(!c)throw Error(`Account with name "${e}" not found.`);await c?.click()}async function uo(t,e){e&&await Pt({page:t,accountName:e});let a=t.getByRole("button",{name:"Connect",exact:!0});await a.waitFor({state:"visible",timeout:25e3}),await a.click(),await t.getByRole("heading",{name:"Connecting",exact:!0}).waitFor({state:"detached",timeout:3e4});let n;await Ea.poll(async()=>(n=await t.locator("div[class='permissions-connect']").isVisible().catch(()=>!1),n),{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 po(t,e){return await t.getByTestId(C.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='${C.accountAddressesElements}']:has-text('${e}')`).getByTestId(C.accountAddressQRCode).click(),await t.getByRole("dialog").locator("div > p[data-testid='account-address']").textContent()}import{expect as Va}from"@playwright/test";import{errors as Ma}from"@playwright/test";var mo={loadingOverlay:"loading-overlay",loadingSpinner:"spinner loading-overlay__spinner"};var _a=6e4,Ra=async(t,e,a)=>{await _(e);try{await e.locator(`div[class="${t}"]`).waitFor({state:"detached",timeout:a})}catch(o){if(o instanceof Ma.TimeoutError)console.info(`Loading indicator '${t}' not found - continuing.`);else throw console.error(`Error while waiting for loading indicator '${t}' to disappear`),o}},ae=async t=>{try{await Ra(mo.loadingSpinner,t,_a)}catch(e){console.warn("Warning during MetaMask load:",e)}return await B(300),t};async function wo(t){if(await t.getByTestId(Dt.unlockButton).isVisible().catch(()=>!1)){console.info("\u{1F4A1} Wallet is already locked");return}await ee(t);let o=t.getByTestId(bt.lockButton);await Va(o).toBeVisible(),await o.click(),await ae(t)}import{styleText as fo}from"util";import{expect as St}from"@playwright/test";var Z=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 H(this.name)}async promptPage(e){let a=await this.promptUrl();return await K({context:e,path:a,locator:"div[data-testid='multichain-page']"})}};import{expect as Ce}from"@playwright/test";async function Ct({page:t}){await t.locator(`div:has(> button[data-testid='${C.openSettingsButton}'])`).click(),await t.getByTestId(bt.networksButton).click();let o=t.locator("section[role='dialog']");await Ce(o).toBeVisible(),await Ce(o).toContainText(/manage networks/i);let n="div:has(> p:has-text('Show test networks'))";await o.locator(n).scrollIntoViewIfNeeded();let r=o.locator(n);if(!await r.locator("label[class='toggle-button toggle-button--off']").isVisible().catch(()=>!1)){await o.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 Ce(t.getByTestId("Sepolia")).toBeVisible(),await o.getByRole("button",{name:/close/i}).click()}async function Se({page:t,mainAccountName:e,...a}){console.info(fo("yellowBright",`
|
|
5
|
+
\u{1F98A} MetaMask onboarding started...`,{validateStream:!1}));let o=await A("metamask"),n=new Z,r=t.locator("img[class='loading-spinner']"),i=t.getByTestId(E.createWalletButton),c=t.getByTestId(E.importWalletButton),u=t.getByTestId(E.createNewPasswordInput),p=t.getByTestId(E.confirmNewPasswordInput),m=t.getByTestId(E.confirmPasswordCheckbox),d=t.getByTestId(E.createPasswordButton),w=t.getByTestId(E.metamaskMetricsIAgreeButton),g=t.getByTestId(E.onboardingDoneButton);if(await r.waitFor({state:"detached",timeout:3e4}),a.mode==="create"){let S=t.getByTestId(E.useSecretRecoveryPhraseButton);await i.click(),await S.click(),await u.fill(o),await p.fill(o),await m.click(),await d.click(),await t.getByTestId(E.revealSecretRecoveryPhraseButton).click(),await t.getByTestId(E.recoveryPhraseRemindMeLaterButton).click(),await w.click()}if(a.mode==="import"){let{secretRecoveryPhrase:S}=a,v=S.split(" "),V=t.getByTestId(E.importUsingSecretRecoveryPhraseButton);await c.click(),await V.click();let $=t.getByTestId(E.secretRecoveryPhraseTextAreaInput);await $.fill(v[0]),await $.press("Space");for(let Q=1;Q<v.length;Q++){let Xt=t.getByTestId(`import-srp__srp-word-${Q}`);await Xt.fill(v[Q]),await Xt.press("Space")}await t.getByTestId(E.importWalletConfirmButton).click(),await u.fill(o),await p.fill(o),await m.click(),await d.click(),await w.click();let at=t.getByTestId("wallet-ready");await St(at).toContainText(/your wallet is ready/i)}await g.click();let y=`chrome-extension://${await n.extensionId()}/sidepanel.html`,x=await t.context().browser()?.newBrowserCDPSession(),T;await St.poll(async()=>{if(x){let{targetInfos:S}=await x.send("Target.getTargets"),v=S.find(V=>V.url===y);return T=v,!!v}},{timeout:15e3}).toBe(!0),T&&await x?.send("Target.closeTarget",{targetId:T.targetId}),await t.goto(await n.indexUrl()),await r.waitFor({state:"detached",timeout:3e4}),await St(t.getByTestId(C.buyButton)).toBeVisible(),await St(t.getByTestId(C.swapButton)).toBeVisible(),await St(t.getByTestId(C.sendButton)).toBeVisible(),await St(t.getByTestId(C.receiveButton)).toBeVisible(),await Ct({page:t}),e&&await Pt({page:t,accountName:e}),await B(5e3),console.info(fo("greenBright","\u2728 MetaMask onboarding completed successfully",{validateStream:!1}))}import{expect as La}from"@playwright/test";async function go(t){let e=t.getByTestId(oe.cancelButton);await B(1e3),await La(e).toBeEnabled(),await e.click()}import{expect as Y}from"@playwright/test";async function ho({page:t,currentAccountName:e,newAccountName:a}){let o=t.getByTestId(C.accountMenuButton);if(await o.textContent()===a)throw Error(`The account to be renamed "${a}" already exists.`);await Y(o).toBeVisible({timeout:15e3}),await o.click(),await Y(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let r=t.getByTestId(nt.addMultichainAccountButton),i=await r.textContent();i?.includes("Syncing")&&await Y.poll(async()=>(await r.textContent())?.trim()??"",{timeout:6e4}).not.toBe(i);let c=await t.getByTestId(/^multichain-account-cell/).all(),u=null;for(let x of c)if((await x.textContent())?.includes(e)){u=x;break}if(!u)throw Error(`Account with name "${e}" not found.`);if((await u.textContent())?.split("$")[0]===a)throw Error(`The new account name "${a}" is the same as the old account name "${e}".`);let m=t.locator(`div[aria-label='${e} options']`);await Y(m).toBeVisible(),await m.click(),await Y(t.getByRole("tooltip")).toBeVisible();let d=t.locator(`div[aria-label='${nt.renameAccountLabel}']`);await Y(d).toBeVisible(),await d.click();let w=t.getByRole("dialog"),g=w.getByRole("heading",{name:/rename/i});await Y(g).toBeVisible();let f=w.getByRole("textbox");await Y(f).toBeVisible(),await f.fill(a);let y=w.getByRole("button",{name:/confirm/i});await Y(y).toBeEnabled(),await y.click();for(let x of c)if((await x.textContent())?.includes(a)){await Y(x).toBeVisible(),await Y(x).toContainText(a);break}await t.locator("button[aria-label='Back']").first().click()}import{expect as ve}from"@playwright/test";async function yo({page:t,networkType:e,chainName:a}){let o=t.getByTestId(C.openNetworkSelectorButton);await o.click();let n=t.getByTestId("modal-header-close-button");if(e==="testnet"||e==="custom"){let u=t.getByRole("tab",{name:"Custom"});await u.click(),await t.locator("p:has-text('Testnets')").isVisible().catch(()=>!1)||(await n.click(),await Ct({page:t}),await o.click(),await u.click());let d=t.locator(`div div[data-testid='${a}']`),w=await d.textContent();ve(w).toBe(a),await d.click();return}await t.getByRole("tab",{name:"Popular"}).click();let i=t.locator(`div div[data-testid='${a}']`),c=await i.textContent();ve(c).toBe(a),await i.click(),await ve(o).toContainText(a,{timeout:3e4})}import{expect as xo}from"@playwright/test";async function Kt(t){let e=await A("metamask"),a=t.getByTestId(Dt.passwordInput);if(await t.getByTestId(C.openNetworkSelectorButton).isVisible().catch(()=>!1)){console.info("\u{1F4A1} Wallet is already unlocked");return}await a.fill(e);let r=t.getByTestId(Dt.unlockButton);await xo(r).toBeVisible(),await r.click(),await ae(t),await xo(t.getByTestId(C.buyButton)).toBeVisible({timeout:3e4})}var pt=class extends Z{page;constructor(e){super(),this.page=e}async onboard(e){await Se({page:this.page,...e})}async unlock(){await Kt(this.page)}async lock(){await wo(this.page)}async renameAccount({newAccountName:e,currentAccountName:a}){await ho({page:this.page,newAccountName:e,currentAccountName:a})}async addAccount({privateKey:e,accountName:a}){await ro({page:this.page,privateKey:e,accountName:a})}async switchAccount({accountName:e}){await Pt({page:this.page,accountName:e})}async switchNetwork({...e}){await yo({page:this.page,...e})}async getAccountAddress(e){return await po(this.page,e)}async toggleShowTestnetNetwork(){await Ct({page:this.page})}async addCustomNetwork({chainId:e,currencySymbol:a,networkName:o,rpcUrl:n}){await co({page:this.page,chainId:e,currencySymbol:a,networkName:o,rpcUrl:n})}async connectToApp(e){await uo(await this.promptPage(this.page.context()),e)}async confirmTransaction(e){await lo(await this.promptPage(this.page.context()),e)}async rejectTransaction(){await go(await this.promptPage(this.page.context()))}};import Bo from"fs";import $a from"path";import{test as Oa,chromium as Da}from"@playwright/test";import{Instance as Ua,Pool as Ka}from"prool";var Ht,Kl=({slowMo:t=0,profileName:e}={})=>Oa.extend({contextPath:async({browserName:a},o,n)=>{let r=await I(`${a}-${n.testId}`);await o(r)},context:async({context:a,contextPath:o},n)=>{let r=new Z,i=k(r.name),c=await W(r.name),u=$a.resolve(i,e??"wallet-data");if(!Bo.existsSync(u))throw new Error("\u274C Cache for MetaMask wallet data not found. Create it first");Bo.cpSync(u,o,{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 m=await Da.launchPersistentContext(o,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:t}),{cookies:d,origins:w}=await a.storageState();d&&await m.addCookies(d),w&&w.length>0&&O(w,m);let g=await r.indexUrl();await m.waitForEvent("page",{predicate:h=>h.url().startsWith(g),timeout:3e4}),Ht=m.pages().find(h=>h.url().startsWith(g))??await R(m,g);for(let h of m.pages())h.url().includes("about:blank")&&await h.close();await Ht.locator("img[class='loading-spinner']").waitFor({state:"detached"}),await Kt(Ht),await n(m),await P(m,o)},metamaskPage:async({context:a},o)=>{await o(Ht)},metamask:async({context:a},o)=>{let n=new pt(Ht);await o(n)},createAnvilNode:async({context:a},o,n)=>{let r=n.workerIndex,i;await o(async c=>{i=Ka.define({instance:Ua.anvil(c)});let u=await i.start(r),p=`http://${u.host}:${u.port}`,d=c?.chainId??31337;return{rpcUrl:p,anvil:u,chainId:d}}),i&&await i.stop(r)},connectToAnvil:async({context:a,metamask:o,createAnvilNode:n},r)=>{await r(async()=>{let{chainId:i,rpcUrl:c}=await n({chainId:2251});await o.addCustomNetwork({chainId:i,currencySymbol:"ETH",networkName:"Anvil Localnet",rpcUrl:c})})}});import{test as Ga}from"@playwright/test";import{Instance as za,Pool as qa}from"prool";import ko from"fs";import Ha from"path";import{chromium as ja}from"@playwright/test";async function bo({workerInfo:t,profileName:e,slowMo:a}){let o=new Z,n=await I(t.workerIndex.toString()),r=k(o.name),i=Ha.resolve(r,e??"wallet-data");if(!ko.existsSync(i))throw new Error(`Cache for ${o.name} does not exist. Create it first!`);ko.cpSync(i,n,{recursive:!0,force:!0});let c=await W(o.name),u=await ja.launchPersistentContext(n,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:a}),p=await o.indexUrl();await u.waitForEvent("page",{predicate:d=>d.url().startsWith(p),timeout:4e4});let m=u.pages().find(d=>d.url().startsWith(p));m||(m=await u.newPage(),await m.goto(p),await _(m));for(let d of u.pages())d.url().includes("about:blank")&&await d.close();return{context:u,walletPage:m,contextPath:n}}var cu=({profileName:t,dappUrl:e,slowMo:a}={})=>Ga.extend({workerScopeContents:[async({browser:o},n,r)=>{let{context:i,contextPath:c,walletPage:u}=await bo({workerInfo:r,profileName:t,slowMo:a});await i.grantPermissions(["clipboard-read"]);let p=new pt(u);await p.unlock(),await n({wallet:p,walletPage:u,context:i}),await P(i,c)},{scope:"worker"}],dappPage:[async({workerScopeContents:o},n)=>{let{context:r}=o,i=await r.newPage();e&&await i.goto(e),await n(i)},{scope:"worker"}],metamaskPage:async({workerScopeContents:o},n)=>{await n(o.walletPage)},metamask:async({workerScopeContents:o},n)=>{let r=new pt(o.walletPage);await n(r)},createAnvilNode:async({context:o},n,r)=>{let i=r.workerIndex,c;await n(async u=>{c=qa.define({instance:za.anvil(u)});let p=await c.start(i),m=`http://${p.host}:${p.port}`,w=u?.chainId??31337;return{rpcUrl:m,anvil:p,chainId:w}}),c&&await c.stop(i)},connectToAnvil:async({context:o,metamask:n,createAnvilNode:r},i)=>{await i(async()=>{let{chainId:c,rpcUrl:u}=await r({chainId:2251});await n.addCustomNetwork({chainId:c,currencySymbol:"ETH",networkName:"Anvil Localnet",rpcUrl:u})})}});var L={openSidebarMenuButton:"button[aria-label='open sidebar']",addWalletButton:"button:has-text('Add Wallet')",settingsButton:"button:has-text('Settings')",settingsMenuBackButton:"button[aria-label='Back']"};var j={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 ne(t,e,a){let o=t.locator(j.switchNetworkButton).last();await o.scrollIntoViewIfNeeded();let n=await o.textContent(),r=e.split("net")[0]?.toLowerCase()??"";if(n?.toLowerCase()===r)return console.info(`
|
|
6
|
+
Already on ${e}, no need to switch network.`),"Exit";await o.click();let c=t.locator(a).last().locator(`> button:has-text('${e}')`);await c.click(),await t.locator("div > h2:has-text('Meteor Community')").isVisible().catch(()=>!1)&&await c.click()}async function vt({page:t,newAccountName:e}){await t.locator(L.openSidebarMenuButton).click(),await t.locator("div:has(> h2):has(> svg)").click();let n=t.locator("input[placeholder='Ex. My Meteor Wallet']"),r=t.locator("button[type='submit']:has-text('Update')");await n.fill(e),await r.click(),await t.locator("div[id='root'] button[aria-label='Close']").click()}async function re({page:t,privateKey:e,accountName:a,network:o}){await t.locator(L.openSidebarMenuButton).click(),await t.locator(L.addWalletButton).click(),await ne(t,o,"section[role='dialog'] div[role='menu']"),await t.locator(j.importExistingWalletButton).click(),await t.locator(j.privateKeyButton).click();let u=t.locator('button:has-text("Continue")');await u.scrollIntoViewIfNeeded(),await u.click(),await t.locator("textarea:not([disabled])").fill(e),await t.locator(j.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 vt({page:t,newAccountName:a})}var Tt={approveButton:"button:has-text('Approve')",connectButton:"button:has-text('Connect')",cancelButton:"button:has-text('Cancel')"};async function J(t){let e=await A("meteor"),a=t.locator("input[placeholder='Enter Password']"),o=t.locator('button:has-text("Unlock")');await a.fill(e),await o.click()}async function Ao(t){await J(t),await t.locator(Tt.approveButton).click(),await t.locator("h2:has-text('Executing Transaction')").waitFor({state:"attached"}),await t.waitForEvent("close",{timeout:15e3})}async function It(t,e){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()===e.toLowerCase()){console.info(`
|
|
7
|
+
Switching to the ${e} account aborted. Account is already selected.`);return}await t.locator(L.openSidebarMenuButton).click();let u=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(),p=null;for(let m of u)if((await m.textContent())?.toLowerCase()===e.toLowerCase()){p=m;break}if(!p)throw new Error(`Account with name "${e}" not found.`);await p.click()}async function Po(t,e){await J(t),e&&await It(t,e);let a=t.getByRole("heading",{name:"Connect Request",exact:!0});await Promise.all([t.locator(Tt.connectButton).click(),a.waitFor({state:"detached",timeout:3e4})])}async function Co(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 So(t){await t.locator(L.openSidebarMenuButton).click(),await t.locator("button:has-text('Lock Wallet')").click()}import{styleText as Te}from"util";var tt=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 H(this.name)}async promptPage(e){let a=await this.promptUrl();return await K({context:e,path:a,locator:"div[id='root']"})}};async function Wt(t){await t.locator(L.openSidebarMenuButton).click(),await t.locator(L.settingsButton).click()}async function ie(t,e){if(await Wt(t),await ne(t,e,"div[role='menu']")==="Exit"){let r=t.locator(L.settingsMenuBackButton);await r.scrollIntoViewIfNeeded(),await r.click();return}let o=t.locator("p:has-text('Available Balance')");if(await B(1e3),!await o.isVisible().catch(()=>!1))throw new Error([`There is no associated account for the ${e} network in your wallet.`,`Please add an account to the ${e} network in your wallet using the "addAccount" method.`,"NOTE: For the account to be persisted across tests, do this when onboarding the wallet."].join(`
|
|
8
|
+
`))}async function Ie({page:t,privateKey:e,network:a,accountName:o,addWallet:n}){console.info(Te("yellowBright",`
|
|
9
|
+
Meteor onboarding started...`,{validateStream:!1}));let r=await A("meteor"),c=await new tt().indexUrl();await t.goto(c);let u=t.locator(j.switchNetworkButton),p=await u.textContent(),m=a.split("net")[0]?.toLowerCase()??"";p?.toLowerCase().includes(m)||(await u.click(),await t.locator("div[role='menu']").locator(`> button:has-text('${a}')`).click());let d=t.locator("input[placeholder='Enter Password']"),w=t.locator("input[placeholder='Confirm Password']"),g=t.locator("label.chakra-checkbox .chakra-checkbox__control"),f=t.locator('button:has-text("Continue")');await d.fill(r),await w.fill(r),await g.click(),await f.click(),await t.locator(j.importExistingWalletButton).click(),await t.locator(j.privateKeyButton).click(),await f.scrollIntoViewIfNeeded(),await f.click(),await t.locator("textarea:not([disabled])").fill(e);let T=t.locator(j.findMyAccountButton);await T.click();let S=t.locator("button[type='submit'][data-loading]");if(await S.waitFor({state:"detached",timeout:25e3}),await t.getByRole("status").locator("div[id='toast-1-title']:has-text('No Account Found')").isVisible().catch(()=>!1)){let ct=5,yt=!1;for(;ct>0;){if(console.info(`
|
|
10
|
+
Retrying search for account. ${ct} attempts left`),await B(15e3),await T.click(),await S.waitFor({state:"detached",timeout:2e4}),await t.locator("div:has-text('Import Your Account')").nth(-2).locator("button").isVisible().catch(()=>!1)){yt=!0;break}ct-=1}if(!yt)throw Error(Te("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(`
|
|
11
|
+
`),{validateStream:!1}))}await t.locator("button:not([aria-label='Back'],[id^='menu-button']):has-text('Account')").click();let Q=t.locator("section[role='dialog']").locator("button:has-text('Close')").first();if(await Q.isVisible().then(()=>!0).catch(()=>!1)&&await Q.click(),await vt({page:t,newAccountName:o}),n&&n.length>0){for(let{privateKey:_e,accountName:Re,network:la}of n)await re({page:t,privateKey:_e,accountName:Re,network:la});await Wt(t);let ct=t.locator(j.switchNetworkButton).last();await ct.scrollIntoViewIfNeeded();let yt=await ct.textContent(),Me=a.split("net")[0]?.toLowerCase()??"";yt?.toLowerCase()!==Me&&await ie(t,a),await It(t,o)}await B(3e3),console.info(Te("greenBright","\u2728 Meteor onboarding completed successfully"))}async function vo(t){await J(t),await t.locator(Tt.cancelButton).click()}var mt=class extends tt{page;constructor(e){super(),this.page=e}async onboard({network:e,privateKey:a,accountName:o,addWallet:n}){await Ie({page:this.page,network:e,privateKey:a,accountName:o,addWallet:n})}async unlock(){await J(this.page)}async lock(){await So(this.page)}async renameAccount({newAccountName:e}){await vt({page:this.page,newAccountName:e})}async switchNetwork(e){await ie(this.page,e)}async switchAccount(e){await It(this.page,e)}async getAccountAddress(){return await Co(this.page)}async addAccount({accountName:e,network:a,privateKey:o}){await re({page:this.page,accountName:e,network:a,privateKey:o})}async openSettings(){await Wt(this.page)}async connectToApp(e){await Po(await this.promptPage(this.page.context()),e)}async confirmTransaction(){await Ao(await this.promptPage(this.page.context()))}async rejectTransaction(){await vo(await this.promptPage(this.page.context()))}};import To from"fs";import Ya from"path";import{test as Xa,chromium as Qa}from"@playwright/test";var jt,em=({slowMo:t=0,profileName:e}={})=>Xa.extend({contextPath:async({browserName:a},o,n)=>{let r=await I(`${a}-${n.testId}`);await o(r)},context:async({context:a,contextPath:o},n)=>{let r=new tt,i=k(r.name),c=await W(r.name),u=Ya.resolve(i,e??"wallet-data");if(!To.existsSync(u))throw new Error("\u274C Cache for Meteor wallet data not found. Create it first");To.cpSync(u,o,{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 p=await Qa.launchPersistentContext(o,{headless:!1,args:[`--disable-extensions-except=${c}`,`--load-extension=${c}`],slowMo:process.env.HEADLESS?0:t});await p.grantPermissions(["clipboard-read"]);let{cookies:m,origins:d}=await a.storageState();m&&await p.addCookies(m),d&&d.length>0&&O(d,p);let w=await r.indexUrl();jt=p.pages().find(f=>f.url().startsWith(w))||await R(p,w);for(let f of p.pages())f.url().includes("about:blank")&&await f.close();await jt.bringToFront(),await J(jt),await n(p),await P(p,o)},meteorPage:async({context:a},o)=>{await o(jt)},meteor:async({context:a},o)=>{let n=new mt(jt);await o(n)}});import{test as Za}from"@playwright/test";var lm=({slowMo:t,profileName:e,dappUrl:a}={})=>Za.extend({workerScopeContents:[async({browser:o},n,r)=>{let{context:i,contextPath:c,walletPage:u}=await kt({workerInfo:r,profileName:e,slowMo:t,wallet:new tt});await i.grantPermissions(["clipboard-read"]);for(let m of i.pages())m.url().includes("about:blank")&&await m.close();let p=new mt(u);await p.unlock(),await n({wallet:p,walletPage:u,context:i}),await P(i,c)},{scope:"worker"}],dappPage:[async({workerScopeContents:o},n)=>{let{context:r}=o,i=await r.newPage();a&&await i.goto(a),await n(i)},{scope:"worker"}],meteorPage:async({workerScopeContents:o},n)=>{await n(o.walletPage)},meteor:async({workerScopeContents:o},n)=>{let r=new mt(o.walletPage);await n(r)}});import tn from"zod";var N={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']"},We={networkSection:"a[href='/settings/network']",backButton:"button[id='back-button']"},Ne={passwordInput:"input[name='password']",unlockButton:"button:has-text('Unlock')"},X={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 F={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 Gt}from"@playwright/test";import Ja from"zod";async function dt({page:t,newAccountName:e}){let a=Ja.string().min(1,"Account name cannot be an empty string").parse(e);await t.locator(N.settingsMenu).click(),await Gt(t.getByText("Settings").first()).toBeVisible();let n=t.locator(X.editAccountButton);await Gt(n).toBeVisible(),await n.click(),await Gt(t.getByText("Account name").first()).toBeVisible();let r=t.locator(X.renameAccountInput);if(await r.getAttribute("value")===a)throw Error(`The account to be renamed "${a}" already exists.`);await r.fill(a);let c=t.locator(X.saveButton);await Gt(c).toBeEnabled(),await c.click(),await Gt(t.getByText(a).first()).toBeVisible(),await t.locator(N.backButton).click(),await Promise.allSettled([t.locator(N.depositButton).waitFor({state:"visible",timeout:2e4}),t.locator(N.sendButton).waitFor({state:"visible",timeout:2e4})])}async function ce({page:t,accountName:e,mode:a,...o}){let n=tn.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(e);if(await t.locator(X.accountOptionsMenuButton).first().click(),await t.getByRole("dialog").locator(X.addAccountButton).click(),a==="privateKey"){let u="privateKey"in o?o.privateKey:"";if(await t.locator(X.addAccountWithPrivateKeyButton).click(),await t.locator(F.privateKeyInput).fill(u),await t.locator(F.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 ${n} already exists in wallet`);await dt({page:t,newAccountName:n})}if(a==="mnemonic"){let p=("mnemonicPhrase"in o?o.mnemonicPhrase:"").split(" ");await t.locator(X.addAccountWithMnemonicButton).click();for(let[y,h]of p.entries())await t.locator(`input[name="mnemonic-${String.fromCharCode(97+y)}"]`).fill(h);if(await t.locator(F.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 ${n} already exists in wallet`);await dt({page:t,newAccountName:n})}}var Nt={approveButton:'button:has-text("Approve")',cancelButton:'button:has-text("Cancel")'};var en=/^[A-Z0-9]+(?:_[A-Z0-9]+)+$/;function Io(t){return en.test(t)?t.toLowerCase().replace(/_/g," ").replace(/\b[a-z]/g,e=>e.toUpperCase()):t}async function on(t,e){for(;;){let o=e();if(o||t.isClosed())break;try{let n=t.locator("div:has(> h2:has-text('Simulation error'))");if(await n.isVisible().catch(()=>!1)){let i=await n.locator("p").textContent();throw new Error(`[Confirm Transaction Error]: ${Io(i||"Unexpected error!")}`)}}catch(n){if(t.isClosed())break;throw n instanceof Error?n:new Error(`[Confirm Transaction Error]: ${n}`)}if(o||t.isClosed())break;await B(300)}}async function Wo(t){let e=!1;on(t,()=>e).catch(async n=>{t.isClosed()||console.error(n.message)}),await t.locator(Nt.approveButton).click(),e=!0}import{expect as an}from"@playwright/test";async function Ft(t,e){let a=t.locator(X.accountOptionsMenuButton).first();if((await a.textContent())?.split("Switch wallet")[1]?.split("0x")[0]?.toLowerCase().trim().includes(e.toLowerCase().trim())){console.info(`
|
|
12
|
+
Switching to ${e} account aborted because the account is already selected.`);return}await a.click();let r=await t.getByRole("dialog").locator("> div > div > button[type='button']").all(),i=null;for(let c of r)if((await c.textContent())?.toLowerCase()?.trim().includes(e.toLowerCase().trim())){i=c;break}if(!i)throw new Error(`Account with name "${e}" not found.`);await i.click()}async function No(t,e){e&&await Ft(t,e);let a=t.locator(Nt.approveButton);await an(a).toBeEnabled({timeout:2e4}),await a.click()}async function Fo(t){return await t.getByRole("button",{name:"Copy Address",exact:!0}).click(),await t.evaluate(async()=>await navigator.clipboard.readText())}import{expect as Eo}from"@playwright/test";async function Mo(t){let e=t.locator(N.settingsMenu);await Eo(e).toBeVisible(),await e.click(),await Eo(t.getByText("Settings").first()).toBeVisible()}async function _o(t){await Mo(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 Ro}from"util";import{expect as rt}from"@playwright/test";var et=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 H(this.name)}async promptPage(e){let a=await this.promptUrl();return await K({context:e,path:a,locator:"div[id='prompt']"})}};var Et=3e4;async function Fe({page:t,...e}){console.info(Ro("yellowBright",`
|
|
13
|
+
Petra onboarding started...`,{validateStream:!1}));let a=new et,o=await A("petra"),n=t.locator(F.createWalletButton),r=t.locator(F.importWalletButton),i=t.locator(F.createNewPasswordInput),c=t.locator(F.confirmNewPasswordInput),u=t.locator(F.confirmPasswordCheckbox),p=t.locator(F.continueButton),m=t.locator(F.getStartedButton),d=t.locator(F.onboardingCompleteText);if(e.mode==="create"){let w=t.locator(F.createSeedPhraseButton);await n.click(),await w.click(),await i.fill(o),await c.fill(o),await u.click(),await p.click(),await t.locator(F.skipCopyRecoveryPhraseButton).click(),await m.click(),await rt(d).toBeVisible({timeout:25e3}),await t.goto(await a.indexUrl()),await rt(t.locator(N.depositButton)).toBeVisible({timeout:Et}),await rt(t.locator(N.sendButton)).toBeVisible({timeout:Et})}if(e.mode==="importPrivateKey"){let{privateKey:w}=e,g=t.locator(F.importUsingPrivateKeyButton),f=t.locator(F.privateKeyInput),y=t.locator(F.importButton);await r.click(),await g.click(),await f.fill(w),await y.click(),await i.fill(o),await c.fill(o),await u.click(),await p.click(),await m.click(),await rt(d).toBeVisible({timeout:25e3}),await t.goto(await a.indexUrl()),await _(t),await rt(t.locator(N.depositButton)).toBeVisible({timeout:Et}),await rt(t.locator(N.sendButton)).toBeVisible({timeout:Et})}if(e.mode==="importMnemonic"){let{secretRecoveryPhrase:w}=e,g=t.locator(F.importUsingMnemonicButton);await r.click(),await g.click();for(let[f,y]of w.split(" ").entries())await t.locator(`input[name="mnemonic-${String.fromCharCode(97+f)}"]`).fill(y);await p.click(),await i.fill(o),await c.fill(o),await u.click(),await p.click(),await m.click(),await rt(d).toBeVisible({timeout:25e3}),await t.goto(await a.indexUrl()),await rt(t.locator(N.depositButton)).toBeVisible({timeout:Et}),await rt(t.locator(N.sendButton)).toBeVisible({timeout:Et})}if(await dt({page:t,newAccountName:e.accountName}),e.addWallet&&e.addWallet.length>0){for(let{...w}of e.addWallet)await ce({page:t,...w});await Ft(t,e.accountName)}await B(1500),console.info(Ro("greenBright","\u2728 Petra onboarding completed successfully",{validateStream:!1}))}import{expect as nn}from"@playwright/test";async function Vo(t){let e=t.locator(Nt.cancelButton);await nn(e).toBeEnabled(),await e.click()}async function Lo(t,e){await t.locator(N.settingsMenu).click(),await t.locator(We.networkSection).click(),await t.locator(`div:has(> span:has-text("${e}"))`).first().click();let r=t.locator(We.backButton);await r.click(),await r.click()}import{expect as $o}from"@playwright/test";async function zt(t){let e=await A("petra"),a=t.locator(Ne.passwordInput);if(!await a.isVisible().then(()=>!0).catch(()=>!1)){console.info("\u{1F4A1} Wallet is already unlocked");return}await $o(a).toBeVisible({timeout:15e3}),await a.fill(e);let n=t.locator(Ne.unlockButton);await $o(n).toBeEnabled(),await n.click(),await Promise.allSettled([t.locator(N.sendButton).waitFor({state:"visible",timeout:2e4}),t.locator(N.receiveButton).waitFor({state:"visible",timeout:2e4})])}var wt=class extends et{page;constructor(e){super(),this.page=e}async onboard(e){await Fe({page:this.page,...e})}async unlock(){await zt(this.page)}async lock(){await _o(this.page)}async renameAccount({newAccountName:e}){await dt({page:this.page,newAccountName:e})}async switchNetwork(e){await Lo(this.page,e)}async switchAccount(e){await Ft(this.page,e)}async getAccountAddress(){return await Fo(this.page)}async addAccount({accountName:e,...a}){await ce({page:this.page,accountName:e,...a})}async connectToApp(e){await No(await this.promptPage(this.page.context()),e)}async confirmTransaction(){await Wo(await this.promptPage(this.page.context()))}async rejectTransaction(){await Vo(await this.promptPage(this.page.context()))}};import Oo from"fs";import rn from"path";import{test as cn,chromium as sn}from"@playwright/test";var qt,rw=({slowMo:t=0,profileName:e}={})=>cn.extend({contextPath:async({browserName:a},o,n)=>{let r=await I(`${a}-${n.testId}`);await o(r)},context:async({context:a,contextPath:o},n)=>{let r=new et,i=k(r.name),c=await W(r.name),u=rn.resolve(i,e??"wallet-data");if(!Oo.existsSync(u))throw new Error("\u274C Cache for Petra wallet data not found. Create it first");Oo.cpSync(u,o,{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 m=await sn.launchPersistentContext(o,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:t});await m.grantPermissions(["clipboard-read"]);let{cookies:d,origins:w}=await a.storageState();d&&await m.addCookies(d),w&&w.length>0&&O(w,m);let g=await r.indexUrl();qt=m.pages().find(y=>y.url().startsWith(g))||await R(m,g);for(let y of m.pages()){let h=y.url();(h.includes("about:blank")||h.includes(r.onboardingPath))&&await y.close()}await qt.bringToFront(),await zt(qt),await n(m),await P(m,o)},petraPage:async({context:a},o)=>{await o(qt)},petra:async({context:a},o)=>{let n=new wt(qt);await o(n)}});import{test as ln}from"@playwright/test";var dw=({slowMo:t,profileName:e,dappUrl:a}={})=>ln.extend({workerScopeContents:[async({browser:o},n,r)=>{let i=new et,{context:c,contextPath:u,walletPage:p}=await kt({wallet:i,workerInfo:r,profileName:e,slowMo:t});await c.grantPermissions(["clipboard-read"]);for(let d of c.pages())d.url().includes(i.onboardingPath)&&await d.close();let m=new wt(p);await m.unlock(),await n({wallet:m,walletPage:p,context:c}),await P(c,u)},{scope:"worker"}],dappPage:[async({workerScopeContents:o},n)=>{let{context:r}=o,i=await r.newPage();a&&await i.goto(a),await n(i)},{scope:"worker"}],petraPage:async({workerScopeContents:o},n)=>{await n(o.walletPage)},petra:async({workerScopeContents:o},n)=>{let r=new wt(o.walletPage);await n(r)}});var M={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"},U={lockWalletButton:"lock-menu-item",closeMenuButton:"settings-menu-close-button",developerSettingsButton:"settings-item-developer-settings",activeNetworksButton:"settings-item-active-networks"},Do={accountProfileContainer:"sortable-account-container"};var b={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 se({page:t,privateKey:e,accountName:a,chain:o}){await t.getByTestId(M.openMenuButton).click(),await t.getByTestId(M.addAccountButton).click(),await t.locator(b.importPrivateKeyButton).click();let c=t.locator("span[id^='button--listbox-input--']"),u=await c.textContent(),p=t.locator("input[name='name']"),m=t.locator("textarea[name='privateKey']");u!==o&&(await c.click(),await t.locator("ul[id^='listbox--listbox-input--']").locator(`li[data-label='${o}']`).click()),await p.fill(a),await m.fill(e),await t.locator("button:has-text('Import')").click()}var Mt={confirmButton:"primary-button",cancelButton:"secondary-button"};async function Uo(t){let e=t.getByTestId(Mt.confirmButton);await t.getByTestId("approve-transaction").waitFor({state:"attached"});let o=t.getByRole("button",{name:"Confirm anyway",exact:!0});if(await o.isVisible().catch(()=>!1)){await o.click();return}await e.click()}import{expect as pn}from"@playwright/test";import un from"zod";async function _t(t,e){let a=un.string().min(1,"Account name cannot be an empty string").parse(e);await t.getByTestId(M.openMenuButton).click();let n=null,r=await t.locator("div[data-testid='account-menu'] div[data-testid='tooltip_interactive-wrapper']").all();for(let i of r)if((await i.textContent())?.includes(a)){n=i;break}if(!n)throw new Error(`Account with name "${a}" not found in the account list.`);await n.click()}async function Ko(t,e){e&&await _t(t,e);let a=t.getByTestId(Mt.confirmButton);await pn(a).toBeEnabled({timeout:15e3}),await a.click()}import mn from"zod";var dn=t=>t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");async function Ho({page:t,accountName:e,chain:a}){let o=mn.string().min(1,"Account name cannot be an empty string").parse(e);await t.getByTestId(M.openMenuButton).click(),await t.getByTestId(M.manageAccountsButton).click(),await t.getByTestId(`manage-accounts-sortable-${o}`).click();let c=t.getByRole("button",{name:/Account Address(?:es)?/i});await c.waitFor({state:"visible",timeout:2e4});let p=await c.locator("div[data-name='row.pair'] > div").last().textContent();if(p&&Number(p)===1){await c.locator("> div > div").last().click(),await t.getByTestId("header--back").click();let w=t.getByTestId(U.closeMenuButton);await w.waitFor({state:"visible",timeout:15e3}),await w.click()}else{await c.click();let d=new RegExp(`${dn(a.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 x=t.getByTestId("header--back");await x.waitFor({state:"visible",timeout:15e3}),await x.click();let T=t.getByTestId(U.closeMenuButton);await T.waitFor({state:"visible",timeout:15e3}),await T.click()}return await t.evaluate(async()=>await navigator.clipboard.readText())}async function jo(t){await t.getByTestId(M.openMenuButton).click(),await t.getByTestId(M.settingsButton).click(),await t.getByTestId(U.lockWalletButton).click()}import{styleText as Go}from"util";import{expect as wn}from"@playwright/test";var ot=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 H(this.name)}async promptPage(e){let a=await this.promptUrl();return await K({context:e,path:a,locator:"div[id='root']"})}};async function Rt(t,e){let o=!1;for(;!e();){let n=e();if(n||o||t.isClosed())break;try{let r=t.locator("div[id='modal']").locator("div > svg").first();await r.isVisible().catch(()=>!1)&&(await r.click(),o=!0)}catch(r){if(t.isClosed())break;console.error("[autoClosePhantomNotification]: ",r)}if(n||o||t.isClosed())break;await B(300)}}async function le({page:t,currentAccountName:e,newAccountName:a}){await t.getByTestId(M.openMenuButton).click(),await t.getByTestId(M.manageAccountsButton).click();let i=await t.getByTestId(Do.accountProfileContainer).locator("div[data-testid^='manage-accounts-sortable'] div > p").all(),c=null;for(let g of i)if((await g.textContent())?.toLowerCase()===e.toLowerCase()){c=g;break}if(!c)throw new Error(`Account with name "${e}" not found`);await c.click(),await t.locator("button:has-text('Account Name')").click();let p=t.locator("input[name='name']");await p.clear(),await p.fill(a),await t.getByTestId("primary-button").click(),await t.getByTestId("header--back").click(),await t.getByTestId(U.closeMenuButton).click()}async function ue(t){await t.getByTestId(M.openMenuButton).click(),await t.getByTestId(M.settingsButton).click()}async function pe({page:t,...e}){await ue(t);let a=t.locator(`button[id='${U.developerSettingsButton}']`);await a.scrollIntoViewIfNeeded(),await a.click();let o=t.getByTestId("toggleTestNetwork"),r=await o.locator("label[data-testid='toggleTestNetwork-switch'] > input[aria-label='Toggle']").isChecked().catch(()=>!1);if(!r&&e.mode==="on"&&await o.click(),r&&e.mode==="off"){await o.click(),await t.getByTestId("header--back").click(),await t.getByTestId(U.closeMenuButton).click();return}if(e.mode==="on"&&e.chain==="Solana"){let{network:u}=e;await t.locator(`button:has-text("${u}")`).click()}if(e.mode==="on"&&e.chain==="Ethereum"){let{network:u}=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(`
|
|
14
|
+
`));await t.locator(`button:has-text("${u}")`).click()}await t.getByTestId("header--back").click(),await t.getByTestId(U.closeMenuButton).click()}async function Ee({page:t,addWallet:e,...a}){console.info(Go("yellowBright",`
|
|
15
|
+
Phantom onboarding started...`,{validateStream:!1}));let o=await A("phantom");if(a.mode==="create"){await t.locator(b.createNewWalletButton).click(),await t.getByTestId(b.createSeedPhraseWalletButton).click();let g=t.getByTestId(b.passwordInput),f=t.getByTestId(b.passwordConfirmInput),y=t.getByTestId(b.termsCheckBox),h=t.locator(b.continueButton);await g.fill(o),await f.fill(o),await y.click(),await h.click(),await h.locator("> div > svg").waitFor({state:"detached",timeout:3e4}),await t.getByTestId(b.recoveryPhraseSavedCheckbox).click(),await h.click(),await B(1e3),await h.click(),await t.locator(b.getStartedButton).last().click()}if(a.mode==="recovery phrase"){let w=a.secretRecoveryPhrase.split(" ");await t.locator(b.IAlreadyHaveAWalletButton).click(),await t.locator(b.importRecoveryPhraseButton).click();for(let[it,at]of Object.entries(w))await t.getByTestId(`${b.recoveryPhraseInput}-${it}`).fill(at);await t.locator(b.importWalletButton).click(),await t.locator("p:has-text('Finding accounts with activity')").waitFor({state:"detached",timeout:6e4});let x=t.locator(b.continueButton);await x.click();let T=t.getByTestId(b.passwordInput),S=t.getByTestId(b.passwordConfirmInput),v=t.getByTestId(b.termsCheckBox);await T.fill(o),await S.fill(o),await v.click(),await x.click(),await x.locator("> div > svg").waitFor({state:"detached",timeout:3e4}),await t.locator(b.getStartedButton).last().click()}if(a.mode==="private key"){await t.locator(b.IAlreadyHaveAWalletButton).click();let{privateKey:w,chain:g,accountName:f}=a;await t.locator(b.importPrivateKeyButton).click();let h=t.locator("span[id='button--listbox-input--1']"),x=await h.textContent(),T=t.locator("input[name='name']"),S=t.locator("textarea[name='privateKey']");x!==g&&(await h.click(),await t.locator("ul[id='listbox--listbox-input--1']").locator(`li[data-label='${g}']`).click()),await T.fill(f),await S.fill(w),await t.locator("button:has-text('Import')").click();let V=t.getByTestId(b.passwordInput),$=t.getByTestId(b.passwordConfirmInput),it=t.getByTestId(b.termsCheckBox);await V.fill(o),await $.fill(o),await it.click();let at=t.locator(b.continueButton);await at.click(),await at.locator("> div > svg").waitFor({state:"detached",timeout:3e4}),await t.locator(b.getStartedButton).last().click()}let n=await t.context().newPage(),r=await new ot().indexUrl();await n.goto(r);let c=await t.context().browser()?.newBrowserCDPSession(),u;await wn.poll(async()=>{if(c){let{targetInfos:d}=await c.send("Target.getTargets"),g=d.filter(f=>f.title==="Phantom Wallet").find(f=>!f.attached&&f.url===r);return u=g,!!g}},{timeout:2e4}).toBe(!0),u&&await c?.send("Target.closeTarget",{targetId:u.targetId});let p=await n.getByTestId("home-header-account-name").textContent();if(a.mode==="create"){let{accountName:d}=a;await le({page:n,newAccountName:d,currentAccountName:"Account 1"})}if(e&&e.length>0){let d=!1;Rt(n,()=>d).catch(f=>console.error({error:f}));for(let{accountName:f,chain:y,privateKey:h}of e)await se({page:n,privateKey:h,accountName:f,chain:y}),d=!0;let g=a.mode==="create"?a.accountName:p;g&&await _t(n,g)}a.toggleNetworkMode&&await pe({page:n,...a.toggleNetworkMode}),await B(3e3),console.info(Go("greenBright","\u2728 Phantom onboarding completed successfully",{validateStream:!1}))}async function zo(t){let e=t.getByTestId(Mt.cancelButton);await t.getByTestId("approve-transaction").waitFor({state:"attached"}),await e.click()}async function qo({page:t,supportedChains:e,toggleMode:a="off"}){if(await ue(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 i of e){let c=t.locator(`button[id='toggle-${i.toLowerCase()}']`),p=await c.locator(`label[data-testid='toggle-${i.toLowerCase()}-switch'] > input[aria-label='Toggle']`).isChecked().catch(()=>!1);a==="off"&&p&&await c.click(),a==="on"&&!p&&await c.click()}await t.getByTestId("header--back").click(),await t.getByTestId(U.closeMenuButton).click()}async function me(t){let e=await A("phantom"),a=t.locator("input[name='password']"),o=t.getByTestId("unlock-form-submit-button");await a.fill(e),await o.click(),await o.waitFor({state:"detached"})}var ft=class extends ot{page;constructor(e){super(),this.page=e}async onboard({...e}){await Ee({page:this.page,...e})}async unlock(){await me(this.page)}async lock(){await jo(this.page)}async renameAccount({...e}){await le({page:this.page,...e})}async switchAccount(e){await _t(this.page,e)}async getAccountAddress({accountName:e,chain:a}){return await Ho({page:this.page,accountName:e,chain:a})}async addAccount({...e}){await se({page:this.page,...e})}async toggleOptionalChains({toggleMode:e,supportedChains:a}){await qo({page:this.page,supportedChains:a,toggleMode:e})}async switchNetwork({...e}){await pe({page:this.page,...e})}async connectToApp(e){await Ko(await this.promptPage(this.page.context()),e)}async confirmTransaction(){await Uo(await this.promptPage(this.page.context()))}async rejectTransaction(){await zo(await this.promptPage(this.page.context()))}};import Yo from"fs";import fn from"path";import{test as gn,chromium as hn}from"@playwright/test";var Vt,pg=({slowMo:t=0,profileName:e}={})=>gn.extend({contextPath:async({browserName:a},o,n)=>{let r=await I(`${a}-${n.testId}`);await o(r)},context:async({context:a,contextPath:o},n)=>{let r=new ot,i=k(r.name),c=await W(r.name),u=fn.resolve(i,e??"wallet-data");if(!Yo.existsSync(u))throw new Error("\u274C Cache for Phantom wallet data not found. Create it first");Yo.cpSync(u,o,{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 p=await hn.launchPersistentContext(o,{headless:!1,args:[`--disable-extensions-except=${c}`,`--load-extension=${c}`],slowMo:process.env.HEADLESS?0:t});await p.grantPermissions(["clipboard-read"]);let{cookies:m,origins:d}=await a.storageState();m&&await p.addCookies(m),d&&d.length>0&&await O(d,p);let w=await r.indexUrl();Vt=p.pages().find(f=>f.url().startsWith(w))||await R(p,w);for(let f of p.pages())f.url().includes("about:blank")&&await f.close();await Vt.bringToFront(),await me(Vt),await n(p),await P(p,o)},phantomPage:async({context:a},o)=>{await o(Vt)},phantom:async({context:a},o)=>{let n=new ft(Vt);await o(n)},autoCloseNotification:[async({context:a},o)=>{let n=!1,i=Rt(Vt,()=>n);await o(void 0),n=!0,await i.catch(c=>{console.error(`Auto close notification error: ${c.message}`)})},{auto:!0}]});import{test as Bn}from"@playwright/test";import Xo from"fs";import yn from"path";import{chromium as xn}from"@playwright/test";async function Qo({workerInfo:t,profileName:e,slowMo:a}){let o=new ot,n=await I(t.workerIndex.toString()),r=k(o.name),i=yn.resolve(r,e??"wallet-data");if(!Xo.existsSync(i))throw new Error(`Cache for ${o.name} does not exist. Create it first!`);Xo.cpSync(i,n,{recursive:!0,force:!0});let c=await W(o.name),u=await xn.launchPersistentContext(n,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:a}),p=await o.indexUrl(),m=await R(u,p);return{context:u,walletPage:m,contextPath:n}}var Ig=({slowMo:t,profileName:e,dappUrl:a}={})=>Bn.extend({workerScopeContents:[async({browser:o},n,r)=>{let{context:i,contextPath:c,walletPage:u}=await Qo({workerInfo:r,profileName:e,slowMo:t});await i.grantPermissions(["clipboard-read"]);for(let m of i.pages())m.url().includes("about:blank")&&await m.close();let p=new ft(u);await p.unlock(),await n({wallet:p,walletPage:u,context:i}),await P(i,c)},{scope:"worker"}],dappPage:[async({workerScopeContents:o},n)=>{let{context:r}=o,i=await r.newPage();a&&await i.goto(a),await n(i)},{scope:"worker"}],phantomPage:async({workerScopeContents:o},n)=>{await n(o.walletPage)},phantom:async({workerScopeContents:o},n)=>{let r=new ft(o.walletPage);await n(r)},autoCloseNotification:[async({workerScopeContents:o},n)=>{let r=!1,i=()=>r,c=Rt(o.walletPage,i);await n(void 0),r=!0,await c.catch(u=>{console.error(`Auto close notification error: ${u.message}`)})},{auto:!0}]});var gt={networkSettings:"li-settings-network",selectNetwork:"select-network",confirmModal:"modal-confirm",confifmButton:"btn-confirm",securityAndPrivacyButton:"nav-item-security-and-privacy",lockButton:"btn-lock"},Lt={portfolioButton:"nav-item-portfolio",walletSelectorButton:"icon-section-wallet-picker-arrow-right"};import de from"zod";var Zo=de.object({walletName:de.string().min(1,"Wallet name cannot be an empty string"),privateKey:de.array(de.number()).length(64)});async function we({page:t,privateKey:e,walletName:a}){let o=Zo.parse({privateKey:e,walletName:a});await t.getByTestId(Lt.walletSelectorButton).click(),await t.getByTestId("icon-btn-add").click(),await t.getByTestId("li-add-wallet-privateKey-add").click();let c=t.getByTestId("input-name"),u=t.getByTestId("input-private-key");await c.fill(o.walletName),await u.fill(`${o.privateKey}`),await t.getByTestId("btn-import").click(),await t.locator("span:has-text('My wallets')").waitFor({state:"attached"}),await t.getByRole("dialog").getByTestId("icon-btn-close").click()}import{expect as kn}from"@playwright/test";var fe={approveButton:"btn-approve",rejectButton:"btn-reject"};async function Jo(t){let e=t.getByTestId(fe.approveButton);await t.getByTestId("section-network-fee").waitFor({state:"attached",timeout:3e4}).catch(async()=>{console.error("Network fee section did not appear within the timeout period, which may indicate that the transaction confirmation popup did not load correctly."),await t.getByText("Network mismatch",{exact:!0}).isVisible().catch(()=>!1)&&(await t.getByRole("button",{name:"Close",exact:!0}).click(),console.error("A 'Network mismatch' error was detected in the popup. Closing the popup and aborting the transaction confirmation process."))});let o=t.locator("div[data-id='control-label']");await o.isVisible().catch(()=>!1)&&await o.click(),await kn(e).toBeEnabled(),await e.click()}async function ge(t,e){await t.getByTestId("icon-section-wallet-picker-arrow-right").click();let o=t.getByTestId("list-item-m-title").filter({hasText:e}).locator("xpath=../..");if(!await o.isVisible().catch(()=>!1))throw new Error(`Account "${e}" not found. Make sure the account is onboarded or verify the account name.`);await o.click()}async function ta(t,e){e&&await ge(t,e),await t.getByRole("button",{name:"Connect",exact:!0}).click()}async function ea(t){return await t.getByTestId("icon-section-wallet-picker-copy").click(),await t.evaluate(async()=>await navigator.clipboard.readText())}async function he(t){let e=t.getByRole("button",{name:"settings",exact:!0});await e.waitFor({state:"attached",timeout:3e4}),await e.click()}async function oa(t){await he(t),await t.getByTestId(gt.securityAndPrivacyButton).click(),await t.getByTestId("li-settings-lock").getByTestId(gt.lockButton).click()}import{styleText as aa}from"util";var st={alreadyHaveAWalletButton:"btn-already-have-wallet",recoveryPhraseInput:"input-recovery-phrase",continueButton:"btn-continue",passwordInput:"input-new-password",repeatPasswordInput:"input-repeat-password",quickSetupButton:"btn-quick-setup",IAgreeButton:"btn-explore"};async function ye({page:t,currentAccountName:e,newAccountName:a}){await t.getByTestId(Lt.walletSelectorButton).click();let n=t.locator(`button[data-testid^='li-wallets']:has-text('${e}')`);if(!await n.isVisible().catch(()=>!1))throw new Error(`Account "${e}" not found. Make sure the account is available.`);await n.hover({timeout:2e4}),await n.getByTestId("icon-btn-three-dots").click({timeout:2e4});let c=t.getByTestId("li-manage-wallet-rename-wallet");await c.click();let u=t.getByTestId("input-name");await u.clear(),await u.fill(a),await t.getByTestId("btn-save").click(),await c.waitFor({state:"attached",timeout:15e3}),await t.getByTestId("icon-btn-close").click()}async function xe(t,e){await he(t);let o=t.getByTestId("li-settings-network").getByRole("combobox");await o.locator(" > p").textContent()!==e?(await o.click(),await t.getByTestId(gt.selectNetwork).getByRole("option",{name:e,exact:!0}).click(),(e==="Devnet"||e==="Testnet")&&await t.getByTestId(gt.confirmModal).getByTestId(gt.confifmButton).click()):console.info(`Network is already set to ${e}`),await t.getByTestId(Lt.portfolioButton).click()}async function na({page:t,recoveryPhrase:e,network:a,walletName:o,addWallet:n}){console.info(aa("yellowBright",`
|
|
16
|
+
Solflare onboarding started...`,{validateStream:!1}));let r=await A("solflare");await t.getByTestId(st.alreadyHaveAWalletButton).click();let c=e.split(" ");for(let[y,h]of Object.entries(c))await t.getByTestId(`${st.recoveryPhraseInput}-${Number(y)+1}`).fill(h);let u=t.getByTestId(st.continueButton);await u.click();let p=t.getByTestId(st.passwordInput),m=t.getByTestId(st.repeatPasswordInput);if(await p.fill(r),await m.fill(r),await u.click(),await t.locator("div",{hasText:"Detecting your existing accounts. This process can take up to a minute."}).waitFor({state:"detached"}),await t.getByTestId(st.quickSetupButton).click(),await t.getByTestId(st.IAgreeButton).click(),await ye({page:t,currentAccountName:"Main Wallet",newAccountName:o}),a&&await xe(t,a),n&&n?.length>0)for(let{privateKey:y,walletName:h}of n)await we({page:t,privateKey:y,walletName:h});console.info(aa("greenBright","\u2728 Solflare onboarding completed successfully",{validateStream:!1}))}async function ra(t){await t.getByTestId(fe.rejectButton).click()}async function Be(t){let e=await A("solflare");await t.getByTestId("input-password").fill(e),await t.getByTestId("btn-unlock").click(),await t.getByTestId("nav-main").waitFor({state:"attached",timeout:3e4})}var lt=class{name="solflare";onboardingPath="wallet.html#/onboard";async indexUrl(){return`chrome-extension://${await this.extensionId()}/wallet.html#/portfolio`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/confirm_popup.html`}async extensionId(){return await H(this.name)}async promptPage(e){let a=await this.promptUrl();return await K({context:e,path:a,locator:"div[data-testid='page-dapp-connect'], div[data-testid='page-tx-sign']"})}};var ht=class extends lt{page;constructor(e){super(),this.page=e}async onboard({recoveryPhrase:e,network:a,addWallet:o,walletName:n}){await na({page:this.page,recoveryPhrase:e,network:a,addWallet:o,walletName:n})}async unlock(){await Be(this.page)}async lock(){await oa(this.page)}async renameAccount({currentAccountName:e,newAccountName:a}){await ye({page:this.page,currentAccountName:e,newAccountName:a})}async switchNetwork(e){await xe(this.page,e)}async switchAccount(e){await ge(this.page,e)}async getAccountAddress(){return await ea(this.page)}async addAccount({privateKey:e,walletName:a}){await we({page:this.page,privateKey:e,walletName:a})}async connectToApp(e){await ta(await this.promptPage(this.page.context()),e)}async confirmTransaction(){await Jo(await this.promptPage(this.page.context()))}async rejectTransaction(){await ra(await this.promptPage(this.page.context()))}};import ia from"fs";import bn from"path";import{test as An,chromium as Pn}from"@playwright/test";async function ke(t,e){let o=!1;for(;!e();){let n=e();if(n||o||t.isClosed())break;try{let r=t.locator("div[role='dialog']").locator("button[data-testid='icon-btn-whats-new-modal-close']");await r.isVisible().catch(()=>!1)&&(await r.click(),o=!0)}catch(r){console.error("[autoCloseSolflareNotification]: ",r)}if(n||o||t.isClosed())break;await B(150)}}var Yt,wy=({slowMo:t=0,profileName:e}={})=>An.extend({contextPath:async({browserName:a},o,n)=>{let r=await I(`${a}-${n.testId}`);await o(r)},context:async({context:a,contextPath:o},n)=>{let r=new lt,i=k(r.name),c=await W(r.name),u=bn.resolve(i,e??"wallet-data");if(!ia.existsSync(u))throw new Error("\u274C Cache for Solflare wallet data not found. Create it first");await ia.promises.cp(u,o,{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 m=await Pn.launchPersistentContext(o,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:t});await m.grantPermissions(["clipboard-read"]);let{cookies:d,origins:w}=await a.storageState();d&&await m.addCookies(d),w&&w.length>0&&O(w,m);let g=await r.indexUrl(),f=g.split("#")[0]??"";await m.waitForEvent("page",{predicate:h=>h.url().includes(f),timeout:15e3}),Yt=m.pages().find(h=>h.url().startsWith(f))||await R(m,g);for(let h of m.pages())h.url().includes("about:blank")&&await h.close();await Be(Yt),await n(m),await P(m,o)},solflarePage:async({context:a},o)=>{await o(Yt)},solflare:async({context:a},o)=>{let n=new ht(Yt);await o(n)},autoCloseNotification:[async({context:a},o)=>{let n=!1,i=ke(Yt,()=>n);await o(void 0),n=!0,await i.catch(c=>{console.error(`Auto close notification error: ${c.message}`)})},{auto:!0}]});import{test as vn}from"@playwright/test";import ca from"fs";import Cn from"path";import{chromium as Sn}from"@playwright/test";async function sa({workerInfo:t,profileName:e,slowMo:a}){let o=new lt,n=await I(t.workerIndex.toString()),r=k(o.name),i=Cn.resolve(r,e??"wallet-data");if(!ca.existsSync(i))throw new Error(`Cache for ${o.name} does not exist. Create it first!`);ca.cpSync(i,n,{recursive:!0,force:!0});let c=await W(o.name),u=await Sn.launchPersistentContext(n,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:a}),p=await o.indexUrl(),m=p.split("#")[0]??"";await u.waitForEvent("page",{predicate:w=>w.url().includes(m),timeout:15e3});let d=u.pages().find(w=>w.url().startsWith(m));d||(d=await u.newPage(),await d.goto(p),await _(d));for(let w of u.pages())w.url().includes("about:blank")&&await w.close();return{context:u,walletPage:d,contextPath:n}}var Fy=({slowMo:t,profileName:e,dappUrl:a}={})=>vn.extend({workerScopeContents:[async({browser:o},n,r)=>{let{context:i,contextPath:c,walletPage:u}=await sa({workerInfo:r,profileName:e,slowMo:t});await i.grantPermissions(["clipboard-read"]);let p=new ht(u);await p.unlock(),await n({wallet:p,walletPage:u,context:i}),await P(i,c)},{scope:"worker"}],dappPage:[async({workerScopeContents:o},n)=>{let{context:r}=o,i=await r.newPage();a&&await i.goto(a),await n(i)},{scope:"worker"}],solflarePage:async({workerScopeContents:o},n)=>{await n(o.walletPage)},solflare:async({workerScopeContents:o},n)=>{let r=new ht(o.walletPage);await n(r)},autoCloseNotification:[async({workerScopeContents:o},n)=>{let r=!1,i=()=>r,c=ke(o.walletPage,i);await n(void 0),r=!0,await c.catch(u=>{console.error(`Auto close notification error: ${u.message}`)})},{auto:!0}]});export{ut as Keplr,pt as Metamask,mt as Meteor,wt as Petra,ft as Phantom,ht as Solflare,tc as keplrFixture,gc as keplrWorkerScopeFixture,Kl as metamaskFixture,cu as metamaskWorkerScopeFixture,em as meteorFixture,lm as meteorWorkerScopeFixture,rw as petraFixture,dw as petraWorkerScopeFixture,pg as phantomFixture,Ig as phantomWorkerScopeFixture,wy as solflareFixture,Fy as solflareWorkerScopeFixture};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tobelabs/chainwright",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "An end-to-end testing framework built on top of Playwright for Web3 wallet interactions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,7 +57,6 @@
|
|
|
57
57
|
"@types/cli-progress": "^3.11.6",
|
|
58
58
|
"@types/node": "^25.8.0",
|
|
59
59
|
"tsup": "^8.5.1",
|
|
60
|
-
"tsx": "^4.22.0",
|
|
61
60
|
"typescript": "^6.0.3",
|
|
62
61
|
"vitest": "^4.1.6"
|
|
63
62
|
},
|
|
@@ -68,6 +67,7 @@
|
|
|
68
67
|
"commander": "^14.0.3",
|
|
69
68
|
"glob": "^13.0.6",
|
|
70
69
|
"prool": "^0.2.4",
|
|
70
|
+
"tsx": "^4.22.0",
|
|
71
71
|
"zod": "^4.4.3"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|