chainwright 0.9.11 → 0.9.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import Y from"fs";import
|
|
2
|
-
Switching to ${o} account aborted because the account is already selected.`);return}await e.click();let c=await t.getByRole("dialog").locator("> div > div > button[type='button']").all(),s=null;for(let p of c)
|
|
3
|
-
Petra onboarding started...`,{validateStream:!1}));let r=new g,a=await
|
|
1
|
+
import Y from"fs";import yt from"path";import{chromium as gt}from"@playwright/test";import ft from"path";var X=".wallet-cache",Z=".wallet-context";var G="13.33.0",W="https://github.com/amaify/chainwright/releases/download/v0.1.0/",Lt=`https://github.com/MetaMask/metamask-extension/releases/download/v${G}/metamask-chrome-${G}.zip`,Rt=`${W}solflare-wallet-extension-v2.19.1.zip`,Ut=`${W}petra-wallet-extension-v2.4.8.zip`,Nt=`${W}phantom-wallet-extension-v26.10.0.zip`,$t=`${W}meteor-wallet-extension-v0.7.0.zip`,Vt=`${W}keplr-wallet-extension-v0.13.3.zip`;async function I(t){return ft.resolve(process.cwd(),Z,t)}import xt from"path";function x(t){return xt.resolve(process.cwd(),X,t)}import J from"fs";import ht from"path";async function O(t){try{let o=x(t),e=ht.resolve(o,"extension-path.txt");if(!J.existsSync(e))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let r=J.readFileSync(e,"utf-8").trim();if(!r)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return r}catch(o){throw new Error(`\u274C Failed to get ${t} extension path: ${o.message}`)}}async function q({wallet:t,workerInfo:o,profileName:e,slowMo:r}){let a=await I(o.workerIndex.toString()),c=x(t.name),s=yt.resolve(c,e??"wallet-data");if(!Y.existsSync(s))throw new Error(`Cache for ${t.name} does not exist. Create it first!`);Y.cpSync(s,a,{recursive:!0,force:!0});let p=await O(t.name),u=await gt.launchPersistentContext(a,{headless:!1,args:[`--disable-extensions-except=${p}`],slowMo:process.env.HEADLESS?0:r}),d=await t.indexUrl(),l=u.pages()[0];return l||(l=await u.newPage()),await l.goto(d),{context:u,walletPage:l,contextPath:a}}var m={depositButton:"button:has-text('Deposit')",sendButton:"button:has-text('Send')",receiveButton:"button:has-text('Receive')",settingsMenu:"button[aria-label='Settings']",lockButton:"global-menu-lock",accountMenuButton:"button[data-part='trigger']",accountDialog:"div[role='dialog']",backButton:"button[id='back-button']"},V={networkSection:"a[href='/settings/network']",backButton:"button[id='back-button']"},K={passwordInput:"input[name='password']",unlockButton:"button:has-text('Unlock')"},h={accountOptionsMenuButton:"button[data-scope='popover']",editAccountButton:"button[aria-label='Edit account name']",renameAccountInput:"input[name='name']",saveButton:"button:has-text('Save')",cancelButton:"button:has-text('Cancel')",addAccountButton:"button:has-text('Add accounts')",addAccountWithPrivateKeyButton:"button:has-text('Import private key')",addAccountWithMnemonicButton:"button:has-text('Import mnemonic')"};var w={createWalletButton:"button:has-text('Create an account')",createSeedPhraseButton:"button:has-text('Create a seed phrase wallet')",createNewPasswordInput:"input[name='password']",confirmNewPasswordInput:"input[name='confirmPassword']",confirmPasswordCheckbox:"label>div[data-scope='checkbox']",continueButton:"button:has-text('Continue')",skipCopyRecoveryPhraseButton:"button:has-text('Skip')",getStartedButton:"button:has-text('Get started')",onboardingCompleteText:"h1:has-text('Your wallet is ready, you may close this window')",importWalletButton:"button:has-text('Import an account')",importUsingPrivateKeyButton:"button:has-text('Import private key')",importUsingMnemonicButton:"button:has-text('Import mnemonic')",importButton:"button:has-text('Import')",privateKeyInput:"input[name='privateKey']"};import{expect as _}from"@playwright/test";import Pt from"zod";async function S({page:t,newAccountName:o}){let e=Pt.string().min(1,"Account name cannot be an empty string").parse(o);await t.locator(m.settingsMenu).click(),await _(t.getByText("Settings").first()).toBeVisible();let a=t.locator(h.editAccountButton);await _(a).toBeVisible(),await a.click(),await _(t.getByText("Account name").first()).toBeVisible();let c=t.locator(h.renameAccountInput);if(await c.getAttribute("value")===e)throw Error(`The account to be renamed "${e}" already exists.`);await c.fill(e);let p=t.locator(h.saveButton);await _(p).toBeEnabled(),await p.click(),await _(t.getByText(e).first()).toBeVisible(),await t.locator(m.backButton).click(),await Promise.allSettled([t.locator(m.depositButton).waitFor({state:"visible",timeout:2e4}),t.locator(m.sendButton).waitFor({state:"visible",timeout:2e4})])}async function L({page:t,accountName:o,mode:e,...r}){if(await t.locator(h.accountOptionsMenuButton).first().click(),await t.getByRole("dialog").locator(h.addAccountButton).click(),e==="privateKey"){let p="privateKey"in r?r.privateKey:"";if(await t.locator(h.addAccountWithPrivateKeyButton).click(),await t.locator(w.privateKeyInput).fill(p),await t.locator(w.importButton).click(),(await t.getByRole("status").locator("div[data-part='description']",{hasText:"Account already exists in wallet"}).textContent({timeout:3e3}).catch(()=>null))?.includes("Account already exists in wallet"))throw Error(`Account ${o} already exists in wallet`);await S({page:t,newAccountName:o})}if(e==="mnemonic"){let u=("mnemonicPhrase"in r?r.mnemonicPhrase:"").split(" ");await t.locator(h.addAccountWithMnemonicButton).click();for(let[k,y]of u.entries())await t.locator(`input[name="mnemonic-${String.fromCharCode(97+k)}"]`).fill(y);if(await t.locator(w.continueButton).click(),(await t.getByRole("status").locator("div[data-part='description']",{hasText:"Account already exists in wallet"}).textContent({timeout:3e3}).catch(()=>null))?.includes("Account already exists in wallet"))throw Error(`Account ${o} already exists in wallet`);await S({page:t,newAccountName:o})}}function R(t){return new Promise(o=>setTimeout(o,t))}var C={approveButton:'button:has-text("Approve")',cancelButton:'button:has-text("Cancel")'};var Bt=/^[A-Z0-9]+(?:_[A-Z0-9]+)+$/;function Q(t){return Bt.test(t)?t.toLowerCase().replace(/_/g," ").replace(/\b[a-z]/g,o=>o.toUpperCase()):t}async function bt(t,o){for(;;){let r=o();if(r||t.isClosed())break;try{let a=t.locator("div:has(> h2:has-text('Simulation error'))");if(await a.isVisible().catch(()=>!1)){let s=await a.locator("p").textContent();throw new Error(`[Confirm Transaction Error]: ${Q(s||"Unexpected error!")}`)}}catch(a){if(t.isClosed())break;throw a instanceof Error?a:new Error(`[Confirm Transaction Error]: ${a}`)}if(r||t.isClosed())break;await R(300)}}async function tt(t){let o=!1;bt(t,()=>o).catch(async a=>{t.isClosed()||console.error(a.message)}),await t.locator(C.approveButton).click(),o=!0}import{expect as kt}from"@playwright/test";async function E(t,o){let e=t.locator(h.accountOptionsMenuButton).first();if((await e.textContent())?.split("Switch wallet")[1]?.split("0x")[0]?.toLowerCase().trim().includes(o.toLowerCase().trim())){console.info(`
|
|
2
|
+
Switching to ${o} account aborted because the account is already selected.`);return}await e.click();let c=await t.getByRole("dialog").locator("> div > div > button[type='button']").all(),s=null;for(let p of c){let d=(await p.textContent())?.split("0x")[0]?.split("...")[0];if(o.toLowerCase().includes(d?.toLowerCase()??"")){s=p;break}}if(!s)throw new Error(`Account with name "${o}" not found.`);await s.click()}async function ot(t,o){o&&await E(t,o);let e=t.locator(C.approveButton);await kt(e).toBeEnabled({timeout:2e4}),await e.click()}async function et(t){return await t.getByRole("button",{name:"Copy Address",exact:!0}).click(),await t.evaluate(async()=>await navigator.clipboard.readText())}import{expect as rt}from"@playwright/test";async function at(t){let o=t.locator(m.settingsMenu);await rt(o).toBeVisible(),await o.click(),await rt(t.getByText("Settings").first()).toBeVisible()}async function nt(t){await at(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 pt}from"util";import{expect as B}from"@playwright/test";async function M(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}import it from"fs";import At from"path";async function U(t){let o=x(t),e=At.resolve(o,"password.txt");try{if(!it.existsSync(e))throw new Error("\u274C password.txt not found. Run setup script first.");return it.readFileSync(e,"utf-8")}catch(r){throw new Error(`\u274C Failed to get ${t} password from cache: ${r.message}`)}}import{expect as St}from"@playwright/test";async function ct({context:t,path:o,locator:e}){let r;try{await St.poll(async()=>(r=t.pages().filter(a=>a.url().startsWith("chrome-extension://")).find(a=>a.url().match(o)),!!r),{timeout:3e4}).toBe(!0)}catch{let a=t.pages().filter(c=>c.url().startsWith("chrome-extension://")).map(c=>c.url());throw new Error(`Popup page with path "${o}" not found in context after 30s. Pages in context: ${JSON.stringify(a)}`)}if(!r)throw new Error(`Popup page with path ${o} not found in context.`);return await Ct(r,e),await r.setViewportSize({width:360,height:592}),r}async function Ct(t,o){await t.waitForLoadState("load",{timeout:4e4}),await t.waitForLoadState("domcontentloaded",{timeout:4e4}),await t.locator(o).first().waitFor({state:"attached",timeout:4e4})}import st from"fs";import Et from"path";async function lt(t){let o=x(t),e=Et.resolve(o,"extension-id.txt");try{if(!st.existsSync(e))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return st.readFileSync(e,"utf-8")}catch(r){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${r.message}`)}}var g=class{name="petra";onboardingPath="/onboarding.html";async indexUrl(){return`chrome-extension://${await this.extensionId()}/index.html`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/prompt.html`}async extensionId(){return await lt(this.name)}async promptPage(o){let e=await this.promptUrl();return await ct({context:o,path:e,locator:"div[id='prompt']"})}};async function N(t,o){await t.locator(m.settingsMenu).click(),await t.locator(V.networkSection).click(),await t.locator(`div:has(> span:has-text("${o}"))`).first().click();let c=t.locator(V.backButton);await c.click(),await c.click()}var T=3e4;async function z({page:t,network:o,...e}){console.info(pt("yellowBright",`
|
|
3
|
+
Petra onboarding started...`,{validateStream:!1}));let r=new g,a=await U("petra"),c=t.locator(w.createWalletButton),s=t.locator(w.importWalletButton),p=t.locator(w.createNewPasswordInput),u=t.locator(w.confirmNewPasswordInput),d=t.locator(w.confirmPasswordCheckbox),l=t.locator(w.continueButton),b=t.locator(w.getStartedButton),P=t.locator(w.onboardingCompleteText);if(e.mode==="create"){let f=t.locator(w.createSeedPhraseButton);await c.click(),await f.click(),await p.fill(a),await u.fill(a),await d.click(),await l.click(),await t.locator(w.skipCopyRecoveryPhraseButton).click(),await b.click(),await B(P).toBeVisible({timeout:25e3}),await t.goto(await r.indexUrl()),await B(t.locator(m.depositButton)).toBeVisible({timeout:T}),await B(t.locator(m.sendButton)).toBeVisible({timeout:T})}if(e.mode==="importPrivateKey"){let{privateKey:f}=e,k=t.locator(w.importUsingPrivateKeyButton),y=t.locator(w.privateKeyInput),A=t.locator(w.importButton);await s.click(),await k.click(),await y.fill(f),await A.click(),await p.fill(a),await u.fill(a),await d.click(),await l.click(),await b.click(),await B(P).toBeVisible({timeout:25e3}),await t.goto(await r.indexUrl()),await M(t),await B(t.locator(m.depositButton)).toBeVisible({timeout:T}),await B(t.locator(m.sendButton)).toBeVisible({timeout:T})}if(e.mode==="importMnemonic"){let{secretRecoveryPhrase:f}=e,k=t.locator(w.importUsingMnemonicButton);await s.click(),await k.click();for(let[y,A]of f.split(" ").entries())await t.locator(`input[name="mnemonic-${String.fromCharCode(97+y)}"]`).fill(A);await l.click(),await p.fill(a),await u.fill(a),await d.click(),await l.click(),await b.click(),await B(P).toBeVisible({timeout:25e3}),await t.goto(await r.indexUrl()),await B(t.locator(m.depositButton)).toBeVisible({timeout:T}),await B(t.locator(m.sendButton)).toBeVisible({timeout:T})}if(await S({page:t,newAccountName:e.accountName}),e.additionalAccounts&&e.additionalAccounts.length>0){for(let{...f}of e.additionalAccounts)await L({page:t,...f});await E(t,e.accountName)}await N(t,o),await R(1500),console.info(pt("greenBright","\u2728 Petra onboarding completed successfully",{validateStream:!1}))}import{expect as Tt}from"@playwright/test";async function ut(t){let o=t.locator(C.cancelButton);await Tt(o).toBeEnabled(),await o.click()}import{expect as mt}from"@playwright/test";async function F(t){let o=await U("petra"),e=t.locator(K.passwordInput);if(!await e.isVisible().then(()=>!0).catch(()=>!1)){console.info("\u{1F4A1} Wallet is already unlocked");return}await mt(e).toBeVisible({timeout:15e3}),await e.fill(o);let a=t.locator(K.unlockButton);await mt(a).toBeEnabled(),await a.click(),await Promise.allSettled([t.locator(m.sendButton).waitFor({state:"visible",timeout:2e4}),t.locator(m.receiveButton).waitFor({state:"visible",timeout:2e4})])}var v=class extends g{page;constructor(o){super(),this.page=o}async onboard(o){await z({page:this.page,...o})}async unlock(){await F(this.page)}async lock(){await nt(this.page)}async renameAccount({newAccountName:o}){await S({page:this.page,newAccountName:o})}async switchNetwork(o){await N(this.page,o)}async switchAccount(o){await E(this.page,o)}async getAccountAddress(){return await et(this.page)}async addAccount({accountName:o,...e}){await L({page:this.page,accountName:o,...e})}async connectToApp(o){await ot(await this.promptPage(this.page.context()),o)}async confirmTransaction(){await tt(await this.promptPage(this.page.context()))}async rejectTransaction(){await ut(await this.promptPage(this.page.context()))}};import dt from"fs";import _t from"path";import{test as Mt,chromium as Ft}from"@playwright/test";import{expect as vt}from"@playwright/test";async function H(t,o){let e=await t.newPage();return await vt(async()=>{await e.goto(o),await M(e)}).toPass(),e}async function j(t,o){let e=await o.newPage();for(let{origin:r,localStorage:a}of t){let c=e.mainFrame();await c.goto(r),await c.evaluate(s=>{s.forEach(({name:p,value:u})=>{window.localStorage.setItem(p,u)})},a)}await e.close()}import Wt from"fs/promises";async function wt(t){await Wt.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var It=35e3;async function $(t,o){try{await Promise.race([t.close(),new Promise((e,r)=>setTimeout(()=>r(new Error("Context close timed out")),It))])}catch(e){console.warn(`Browser context close did not complete cleanly: ${e.message}`)}try{await wt(o)}catch(e){console.error(`Failed to remove temporary context directory at ${o}. Error:`,e)}}var D,Wr=({slowMo:t=0,profileName:o}={})=>Mt.extend({contextPath:async({browserName:e},r,a)=>{let c=await I(`${e}-${a.testId}`);await r(c)},context:async({context:e,contextPath:r},a)=>{let c=new g,s=x(c.name),p=await O(c.name),u=_t.resolve(s,o??"wallet-data");if(!dt.existsSync(u))throw new Error("\u274C Cache for Petra wallet data not found. Create it first");dt.cpSync(u,r,{recursive:!0,force:!0});let d=[`--disable-extensions-except=${p}`,`--load-extension=${p}`];process.env.HEADLESS&&(d.push("--headless=new"),t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!"));let l=await Ft.launchPersistentContext(r,{headless:!1,args:[`--disable-extensions-except=${p}`],slowMo:process.env.HEADLESS?0:t});await l.grantPermissions(["clipboard-read"]);let{cookies:b,origins:P}=await e.storageState();b&&await l.addCookies(b),P&&P.length>0&&j(P,l);let f=await c.indexUrl();D=l.pages().find(y=>y.url().startsWith(f))||await H(l,f);for(let y of l.pages()){let A=y.url();(A.includes("about:blank")||A.includes(c.onboardingPath))&&await y.close()}await D.bringToFront(),await F(D),await a(l),await $(l,r)},petraPage:async({context:e},r)=>{await r(D)},petra:async({context:e},r)=>{let a=new v(D);await r(a)}});import{test as Dt}from"@playwright/test";var Rr=({slowMo:t,profileName:o}={})=>Dt.extend({workerScopeContents:[async({browser:e},r,a)=>{let c=new g,{context:s,contextPath:p,walletPage:u}=await q({wallet:c,workerInfo:a,profileName:o,slowMo:t});await s.grantPermissions(["clipboard-read"]);for(let l of s.pages())l.url().includes(c.onboardingPath)&&await l.close();let d=new v(u);await d.unlock(),await r({wallet:d,walletPage:u,context:s}),await $(s,p)},{scope:"worker"}]});export{v as Petra,Wr as petraFixture,Rr as petraWorkerScopeFixture,q as workerScopeContext};
|
package/package.json
CHANGED