chainwright 0.9.8 → 0.9.10

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.
@@ -136,6 +136,13 @@ declare class Meteor extends MeteorProfile {
136
136
  * await meteor.connectToApp("Account 1");
137
137
  */
138
138
  connectToApp(account?: string): Promise<void>;
139
+ /**
140
+ * Confirms the wallet's disconnection from the app.
141
+ * @example
142
+ * const meteor = new Meteor(page);
143
+ * await meteor.confirmDisconnect();
144
+ */
145
+ confirmDisconnect(): Promise<void>;
139
146
  /**
140
147
  * Confirms a transaction in the wallet by clicking on the "Approve" button.
141
148
  * This function confirms a transaction in the wallet by clicking on the "Approve" button.
@@ -1,7 +1,7 @@
1
- import tt from"fs";import gt from"path";import{chromium as yt}from"@playwright/test";import ft from"path";var Y=".wallet-cache",Q=".wallet-context";var J="13.33.0",M="https://github.com/amaify/chainwright/releases/download/v0.1.0/",Dt=`https://github.com/MetaMask/metamask-extension/releases/download/v${J}/metamask-chrome-${J}.zip`,Ot=`${M}solflare-wallet-extension-v2.19.1.zip`,Rt=`${M}petra-wallet-extension-v2.4.8.zip`,Ut=`${M}phantom-wallet-extension-v26.10.0.zip`,$t=`${M}meteor-wallet-extension-v0.7.0.zip`,Vt=`${M}keplr-wallet-extension-v0.13.3.zip`;async function E(t){return ft.resolve(process.cwd(),Q,t)}import ht from"path";function f(t){return ht.resolve(process.cwd(),Y,t)}import Z from"fs";import xt from"path";async function N(t){try{let o=f(t),r=xt.resolve(o,"extension-path.txt");if(!Z.existsSync(r))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let e=Z.readFileSync(r,"utf-8").trim();if(!e)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return e}catch(o){throw new Error(`\u274C Failed to get ${t} extension path: ${o.message}`)}}async function ot({wallet:t,workerInfo:o,profileName:r,slowMo:e}){let a=await E(o.workerIndex.toString()),c=f(t.name),w=gt.resolve(c,r??"wallet-data");if(!tt.existsSync(w))throw new Error(`Cache for ${t.name} does not exist. Create it first!`);tt.cpSync(w,a,{recursive:!0,force:!0});let l=await N(t.name),p=await yt.launchPersistentContext(a,{headless:!1,args:[`--disable-extensions-except=${l}`],slowMo:process.env.HEADLESS?0:e}),s=await t.indexUrl(),d=p.pages()[0];return d||(d=await p.newPage()),await d.goto(s),{context:p,walletPage:d,contextPath:a}}var u={openSidebarMenuButton:"button[aria-label='open sidebar']",addWalletButton:"button:has-text('Add Wallet')",settingsButton:"button:has-text('Settings')",settingsMenuBackButton:"button[aria-label='Back']"};var m={importExistingWalletButton:'button:has-text("Import an existing wallet")',switchNetworkButton:"button[id^='menu-button']",privateKeyButton:"button:has-text('Private Key')",secretPhraseButton:"button:has-text('Secret Phrase')",findMyAccountButton:"button:has-text('Find my account')"};async function I(t,o,r){let e=t.locator(m.switchNetworkButton).last();await e.scrollIntoViewIfNeeded();let a=await e.textContent(),c=o.split("net")[0]?.toLowerCase()??"";if(a?.toLowerCase()===c)return console.info(`
2
- Already on ${o}, no need to switch network.`),"Exit";await e.click();let l=t.locator(r).last().locator(`> button:has-text('${o}')`);await l.click(),await t.locator("div > h2:has-text('Meteor Community')").isVisible().catch(()=>!1)&&await l.click()}async function k({page:t,newAccountName:o}){await t.locator(u.openSidebarMenuButton).click(),await t.locator("div:has(> h2):has(> svg)").click();let a=t.locator("input[placeholder='Ex. My Meteor Wallet']"),c=t.locator("button[type='submit']:has-text('Update')");await a.fill(o),await c.click(),await t.locator("div[id='root'] button[aria-label='Close']").click()}async function _({page:t,accountName:o,network:r,...e}){await t.locator(u.openSidebarMenuButton).click(),await t.locator(u.addWalletButton).click(),await I(t,r,"section[role='dialog'] div[role='menu']"),await t.locator(m.importExistingWalletButton).click();let l=t.locator('button:has-text("Continue")');e.mode==="secretPhrase"&&(await t.locator(m.secretPhraseButton).click(),await l.scrollIntoViewIfNeeded(),await l.click(),await t.locator("textarea:not([disabled])").fill(e.secretPhrase)),e.mode==="privateKey"&&(await t.locator(m.privateKeyButton).click(),await l.scrollIntoViewIfNeeded(),await l.click(),await t.locator("textarea:not([disabled])").fill(e.privateKey)),await t.locator(m.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 k({page:t,newAccountName:o})}var B={approveButton:"button:has-text('Approve')",connectButton:"button:has-text('Connect')",cancelButton:"button:has-text('Cancel')"};import et from"fs";import Pt from"path";async function F(t){let o=f(t),r=Pt.resolve(o,"password.txt");try{if(!et.existsSync(r))throw new Error("\u274C password.txt not found. Run setup script first.");return et.readFileSync(r,"utf-8")}catch(e){throw new Error(`\u274C Failed to get ${t} password from cache: ${e.message}`)}}async function x(t){let o=await F("meteor"),r=t.locator("input[placeholder='Enter Password']"),e=t.locator('button:has-text("Unlock")');await r.fill(o),await e.click()}async function rt(t){await x(t),await t.locator(B.approveButton).click(),await t.locator("h2:has-text('Executing Transaction')").waitFor({state:"attached"}),await t.waitForEvent("close",{timeout:15e3})}async function C(t,o){if((await t.locator("div:has(button[type='button'][aria-label='open sidebar'])").nth(-2).locator("div:has(div > h2)").locator("div > h2").textContent())?.toLowerCase()===o.toLowerCase()){console.info(`
3
- Switching to the ${o} account aborted. Account is already selected.`);return}await t.locator(u.openSidebarMenuButton).click();let p=await t.locator("div:has(div > button[type='button'][aria-label='Close'])").nth(-2).locator("div").nth(2).locator("> div").nth(1).locator("div").nth(1).locator("div > h2").all(),s=null;for(let d of p)if((await d.textContent())?.toLowerCase()===o.toLowerCase()){s=d;break}if(!s)throw new Error(`Account with name "${o}" not found.`);await s.click()}async function at(t,o){await x(t),o&&await C(t,o);let r=t.getByRole("heading",{name:"Connect Request",exact:!0});await Promise.all([t.locator(B.connectButton).click(),r.waitFor({state:"detached",timeout:3e4})])}async function nt(t){return await t.locator("div:has(button[type='button'][aria-label='open sidebar'])").nth(-2).locator("div:has(div > h2)").locator("div > svg").click(),await t.evaluate(async()=>await navigator.clipboard.readText())}async function it(t){await t.locator(u.openSidebarMenuButton).click(),await t.locator("button:has-text('Lock Wallet')").click()}import{styleText as O}from"util";function T(t){return new Promise(o=>setTimeout(o,t))}import{expect as bt}from"@playwright/test";async function ct({context:t,path:o,locator:r}){let e;try{await bt.poll(async()=>(e=t.pages().filter(a=>a.url().startsWith("chrome-extension://")).find(a=>a.url().match(o)),!!e),{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(!e)throw new Error(`Popup page with path ${o} not found in context.`);return await At(e,r),await e.setViewportSize({width:360,height:592}),e}async function At(t,o){await t.waitForLoadState("load",{timeout:4e4}),await t.waitForLoadState("domcontentloaded",{timeout:4e4}),await t.locator(o).first().waitFor({state:"attached",timeout:4e4})}import st from"fs";import kt from"path";async function lt(t){let o=f(t),r=kt.resolve(o,"extension-id.txt");try{if(!st.existsSync(r))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return st.readFileSync(r,"utf-8")}catch(e){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${e.message}`)}}var g=class{name="meteor";onboardingPath="ext_index_popup.html";async indexUrl(){return`chrome-extension://${await this.extensionId()}/ext_index_popup.html`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/ext_index.html`}async extensionId(){return await lt(this.name)}async promptPage(o){let r=await this.promptUrl();return await ct({context:o,path:r,locator:"div[id='root']"})}};async function S(t){await t.locator(u.openSidebarMenuButton).click(),await t.locator(u.settingsButton).click()}async function L(t,o){if(await S(t),await I(t,o,"div[role='menu']")==="Exit"){let c=t.locator(u.settingsMenuBackButton);await c.scrollIntoViewIfNeeded(),await c.click();return}let e=t.locator("p:has-text('Available Balance')");if(await T(1e3),!await e.isVisible().catch(()=>!1))throw new Error([`There is no associated account for the ${o} network in your wallet.`,`Please add an account to the ${o} network in your wallet using the "addAccount" method.`,"NOTE: For the account to be persisted across tests, do this when onboarding the wallet."].join(`
1
+ import tt from"fs";import yt from"path";import{chromium as Pt}from"@playwright/test";import ht from"path";var Y=".wallet-cache",Q=".wallet-context";var J="13.33.0",M="https://github.com/amaify/chainwright/releases/download/v0.1.0/",Ot=`https://github.com/MetaMask/metamask-extension/releases/download/v${J}/metamask-chrome-${J}.zip`,Rt=`${M}solflare-wallet-extension-v2.19.1.zip`,Ut=`${M}petra-wallet-extension-v2.4.8.zip`,$t=`${M}phantom-wallet-extension-v26.10.0.zip`,Vt=`${M}meteor-wallet-extension-v0.7.0.zip`,Kt=`${M}keplr-wallet-extension-v0.13.3.zip`;async function T(t){return ht.resolve(process.cwd(),Q,t)}import xt from"path";function h(t){return xt.resolve(process.cwd(),Y,t)}import Z from"fs";import gt from"path";async function N(t){try{let o=h(t),r=gt.resolve(o,"extension-path.txt");if(!Z.existsSync(r))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let e=Z.readFileSync(r,"utf-8").trim();if(!e)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return e}catch(o){throw new Error(`\u274C Failed to get ${t} extension path: ${o.message}`)}}async function ot({wallet:t,workerInfo:o,profileName:r,slowMo:e}){let a=await T(o.workerIndex.toString()),c=h(t.name),w=yt.resolve(c,r??"wallet-data");if(!tt.existsSync(w))throw new Error(`Cache for ${t.name} does not exist. Create it first!`);tt.cpSync(w,a,{recursive:!0,force:!0});let l=await N(t.name),p=await Pt.launchPersistentContext(a,{headless:!1,args:[`--disable-extensions-except=${l}`],slowMo:process.env.HEADLESS?0:e}),s=await t.indexUrl(),d=p.pages()[0];return d||(d=await p.newPage()),await d.goto(s),{context:p,walletPage:d,contextPath:a}}var u={openSidebarMenuButton:"button[aria-label='open sidebar']",addWalletButton:"button:has-text('Add Wallet')",settingsButton:"button:has-text('Settings')",settingsMenuBackButton:"button[aria-label='Back']"};var m={importExistingWalletButton:'button:has-text("Import an existing wallet")',switchNetworkButton:"button[id^='menu-button']",privateKeyButton:"button:has-text('Private Key')",secretPhraseButton:"button:has-text('Secret Phrase')",findMyAccountButton:"button:has-text('Find my account')"};async function _(t,o,r){let e=t.locator(m.switchNetworkButton).last();await e.scrollIntoViewIfNeeded();let a=await e.textContent(),c=o.split("net")[0]?.toLowerCase()??"";if(a?.toLowerCase()===c)return console.info(`
2
+ Already on ${o}, no need to switch network.`),"Exit";await e.click();let l=t.locator(r).last().locator(`> button:has-text('${o}')`);await l.click(),await t.locator("div > h2:has-text('Meteor Community')").isVisible().catch(()=>!1)&&await l.click()}async function B({page:t,newAccountName:o}){await t.locator(u.openSidebarMenuButton).click(),await t.locator("div:has(> h2):has(> svg)").click();let a=t.locator("input[placeholder='Ex. My Meteor Wallet']"),c=t.locator("button[type='submit']:has-text('Update')");await a.fill(o),await c.click(),await t.locator("div[id='root'] button[aria-label='Close']").click()}async function I({page:t,accountName:o,network:r,...e}){await t.locator(u.openSidebarMenuButton).click(),await t.locator(u.addWalletButton).click(),await _(t,r,"section[role='dialog'] div[role='menu']"),await t.locator(m.importExistingWalletButton).click();let l=t.locator('button:has-text("Continue")');e.mode==="secretPhrase"&&(await t.locator(m.secretPhraseButton).click(),await l.scrollIntoViewIfNeeded(),await l.click(),await t.locator("textarea:not([disabled])").fill(e.secretPhrase)),e.mode==="privateKey"&&(await t.locator(m.privateKeyButton).click(),await l.scrollIntoViewIfNeeded(),await l.click(),await t.locator("textarea:not([disabled])").fill(e.privateKey)),await t.locator(m.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 B({page:t,newAccountName:o})}var b={approveButton:"button:has-text('Approve')",connectButton:"button:has-text('Connect')",cancelButton:"button:has-text('Cancel')",logoutButton:"button:has-text('Logout')"};import et from"fs";import bt from"path";async function F(t){let o=h(t),r=bt.resolve(o,"password.txt");try{if(!et.existsSync(r))throw new Error("\u274C password.txt not found. Run setup script first.");return et.readFileSync(r,"utf-8")}catch(e){throw new Error(`\u274C Failed to get ${t} password from cache: ${e.message}`)}}async function f(t){let o=await F("meteor"),r=t.locator("input[placeholder='Enter Password']"),e=t.locator('button:has-text("Unlock")');if(!await r.waitFor({state:"visible",timeout:5e3}).then(()=>!0).catch(()=>!1)){console.info("\u{1F4A1} Wallet is already unlocked");return}await r.fill(o),await e.click()}async function rt(t){await f(t),await t.locator(b.logoutButton).click()}async function at(t){await f(t),await t.locator(b.approveButton).click(),await t.locator("h2:has-text('Executing Transaction')").waitFor({state:"attached"}),await t.waitForEvent("close",{timeout:15e3})}async function C(t,o){if((await t.locator("div:has(button[type='button'][aria-label='open sidebar'])").nth(-2).locator("div:has(div > h2)").locator("div > h2").textContent())?.toLowerCase()===o.toLowerCase()){console.info(`
3
+ Switching to the ${o} account aborted. Account is already selected.`);return}await t.locator(u.openSidebarMenuButton).click();let p=await t.locator("div:has(div > button[type='button'][aria-label='Close'])").nth(-2).locator("div").nth(2).locator("> div").nth(1).locator("div").nth(1).locator("div > h2").all(),s=null;for(let d of p)if((await d.textContent())?.toLowerCase()===o.toLowerCase()){s=d;break}if(!s)throw new Error(`Account with name "${o}" not found.`);await s.click()}async function nt(t,o){await f(t),o&&await C(t,o);let r=t.getByRole("heading",{name:"Connect Request",exact:!0});await Promise.all([t.locator(b.connectButton).click(),r.waitFor({state:"detached",timeout:3e4})])}async function it(t){let e=t.locator("div:has(button[type='button'][aria-label='open sidebar'])").nth(-2).locator("div:has(div > h2)").locator("div > svg"),a=t.locator(".chakra-toast").last();await e.click(),await a.waitFor({state:"visible",timeout:5e3});let c=await t.evaluate(async()=>await navigator.clipboard.readText());return await a.waitFor({state:"hidden",timeout:5e3}),c}async function ct(t){await t.locator(u.openSidebarMenuButton).click(),await t.locator("button:has-text('Lock Wallet')").click()}import{styleText as O}from"util";function E(t){return new Promise(o=>setTimeout(o,t))}import{expect as kt}from"@playwright/test";async function st({context:t,path:o,locator:r}){let e;try{await kt.poll(async()=>(e=t.pages().filter(a=>a.url().startsWith("chrome-extension://")).find(a=>a.url().match(o)),!!e),{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(!e)throw new Error(`Popup page with path ${o} not found in context.`);return await At(e,r),await e.setViewportSize({width:360,height:592}),e}async function At(t,o){await t.waitForLoadState("load",{timeout:4e4}),await t.waitForLoadState("domcontentloaded",{timeout:4e4}),await t.locator(o).first().waitFor({state:"attached",timeout:4e4})}import lt from"fs";import Bt from"path";async function pt(t){let o=h(t),r=Bt.resolve(o,"extension-id.txt");try{if(!lt.existsSync(r))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return lt.readFileSync(r,"utf-8")}catch(e){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${e.message}`)}}var g=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 pt(this.name)}async promptPage(o){let r=await this.promptUrl();return await st({context:o,path:r,locator:"div[id='root']"})}};async function S(t){await t.locator(u.openSidebarMenuButton).click(),await t.locator(u.settingsButton).click()}async function L(t,o){if(await S(t),await _(t,o,"div[role='menu']")==="Exit"){let c=t.locator(u.settingsMenuBackButton);await c.scrollIntoViewIfNeeded(),await c.click();return}let e=t.locator("p:has-text('Available Balance')");if(await E(1e3),!await e.isVisible().catch(()=>!1))throw new Error([`There is no associated account for the ${o} network in your wallet.`,`Please add an account to the ${o} network in your wallet using the "addAccount" method.`,"NOTE: For the account to be persisted across tests, do this when onboarding the wallet."].join(`
4
4
  `))}async function R({page:t,network:o,accountName:r,additionalAccounts:e,...a}){console.info(O("yellowBright",`
5
- Meteor onboarding started...`,{validateStream:!1}));let c=await F("meteor"),l=await new g().indexUrl();await t.goto(l);let p=t.locator(m.switchNetworkButton),s=await p.textContent(),d=o.split("net")[0]?.toLowerCase()??"";s?.toLowerCase().includes(d)||(await p.click(),await t.locator("div[role='menu']").locator(`> button:has-text('${o}')`).click());let P=t.locator("input[placeholder='Enter Password']"),A=t.locator("input[placeholder='Confirm Password']"),K=t.locator("label.chakra-checkbox .chakra-checkbox__control"),h=t.locator('button:has-text("Continue")');await P.fill(c),await A.fill(c),await K.click(),await h.click(),await t.locator(m.importExistingWalletButton).click(),a.mode==="secretPhrase"&&(await t.locator(m.secretPhraseButton).click(),await h.scrollIntoViewIfNeeded(),await h.click(),await t.locator("textarea:not([disabled])").fill(a.secretPhrase)),a.mode==="privateKey"&&(await t.locator(m.privateKeyButton).click(),await h.scrollIntoViewIfNeeded(),await h.click(),await t.locator("textarea:not([disabled])").fill(a.privateKey));let H=t.locator(m.findMyAccountButton);await H.click();let z=t.locator("button[type='submit'][data-loading]");if(await z.waitFor({state:"detached",timeout:25e3}),await t.getByRole("status").locator("div[id='toast-1-title']:has-text('No Account Found')").isVisible().catch(()=>!1)){let y=5,b=!1;for(;y>0;){if(console.info(`
6
- Retrying search for account. ${y} attempts left`),await T(15e3),await H.click(),await z.waitFor({state:"detached",timeout:2e4}),await t.locator("div:has-text('Import Your Account')").nth(-2).locator("button").isVisible().catch(()=>!1)){b=!0;break}y-=1}if(!b)throw Error(O("redBright",["No Account Found","Account associated with the private key not found. Please make sure you are trying to import an account on the correct network(Mainnet/Testnet)."].join(`
7
- `),{validateStream:!1}))}await t.locator("button:not([aria-label='Back'],[id^='menu-button']):has-text('Account')").click();let j=t.locator("section[role='dialog']").locator("button:has-text('Close')").first();if(await j.isVisible().then(()=>!0).catch(()=>!1)&&await j.click(),await k({page:t,newAccountName:r}),e&&e.length>0){for(let{accountName:q,network:G,...dt}of e)await _({page:t,accountName:q,network:G,...dt});await S(t);let y=t.locator(m.switchNetworkButton).last();await y.scrollIntoViewIfNeeded();let b=await y.textContent(),X=o.split("net")[0]?.toLowerCase()??"";b?.toLowerCase()!==X&&await L(t,o),await C(t,r)}await T(3e3),console.info(O("greenBright","\u2728 Meteor onboarding completed successfully"))}async function pt(t){await x(t),await t.locator(B.cancelButton).click()}var v=class extends g{page;constructor(o){super(),this.page=o}async onboard({network:o,accountName:r,additionalAccounts:e,...a}){await R({page:this.page,network:o,accountName:r,additionalAccounts:e,...a})}async unlock(){await x(this.page)}async lock(){await it(this.page)}async renameAccount({newAccountName:o}){await k({page:this.page,newAccountName:o})}async switchNetwork(o){await L(this.page,o)}async switchAccount(o){await C(this.page,o)}async getAccountAddress(){return await nt(this.page)}async addAccount({accountName:o,network:r,...e}){await _({page:this.page,accountName:o,network:r,...e})}async openSettings(){await S(this.page)}async connectToApp(o){await at(await this.promptPage(this.page.context()),o)}async confirmTransaction(){await rt(await this.promptPage(this.page.context()))}async rejectTransaction(){await pt(await this.promptPage(this.page.context()))}};import mt from"fs";import vt from"path";import{test as Mt,chromium as Et}from"@playwright/test";import{expect as Bt}from"@playwright/test";async function U(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}async function $(t,o){let r=await t.newPage();return await Bt(async()=>{await r.goto(o),await U(r)}).toPass(),r}async function V(t,o){let r=await o.newPage();for(let{origin:e,localStorage:a}of t){let c=r.mainFrame();await c.goto(e),await c.evaluate(w=>{w.forEach(({name:l,value:p})=>{window.localStorage.setItem(l,p)})},a)}await r.close()}import Ct from"fs/promises";async function ut(t){await Ct.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var St=35e3;async function D(t,o){try{await Promise.race([t.close(),new Promise((r,e)=>setTimeout(()=>e(new Error("Context close timed out")),St))])}catch(r){console.warn(`Browser context close did not complete cleanly: ${r.message}`)}try{await ut(o)}catch(r){console.error(`Failed to remove temporary context directory at ${o}. Error:`,r)}}var W,Mr=({slowMo:t=0,profileName:o}={})=>Mt.extend({contextPath:async({browserName:r},e,a)=>{let c=await E(`${r}-${a.testId}`);await e(c)},context:async({context:r,contextPath:e},a)=>{let c=new g,w=f(c.name),l=await N(c.name),p=vt.resolve(w,o??"wallet-data");if(!mt.existsSync(p))throw new Error("\u274C Cache for Meteor wallet data not found. Create it first");mt.cpSync(p,e,{recursive:!0,force:!0}),process.env.HEADLESS&&t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!");let s=await Et.launchPersistentContext(e,{headless:!1,args:[`--disable-extensions-except=${l}`,`--load-extension=${l}`],slowMo:process.env.HEADLESS?0:t});await s.grantPermissions(["clipboard-read"]);let{cookies:d,origins:P}=await r.storageState();d&&await s.addCookies(d),P&&P.length>0&&V(P,s);let A=await c.indexUrl();W=s.pages().find(h=>h.url().startsWith(A))||await $(s,A);for(let h of s.pages())h.url().includes("about:blank")&&await h.close();await W.bringToFront(),await x(W),await a(s),await D(s,e)},meteorPage:async({context:r},e)=>{await e(W)},meteor:async({context:r},e)=>{let a=new v(W);await e(a)}});import{test as Tt}from"@playwright/test";var Lr=({slowMo:t,profileName:o}={})=>Tt.extend({workerScopeContents:[async({browser:r},e,a)=>{let{context:c,contextPath:w,walletPage:l}=await ot({workerInfo:a,profileName:o,slowMo:t,wallet:new g});await c.grantPermissions(["clipboard-read"]);for(let s of c.pages())s.url().includes("about:blank")&&await s.close();let p=new v(l);await p.unlock(),await e({wallet:p,walletPage:l,context:c}),await D(c,w)},{scope:"worker"}]});export{v as Meteor,Mr as meteorFixture,Lr as meteorWorkerScopeFixture,ot as workerScopeContext};
5
+ Meteor onboarding started...`,{validateStream:!1}));let c=await F("meteor"),l=await new g().indexUrl();await t.goto(l);let p=t.locator(m.switchNetworkButton),s=await p.textContent(),d=o.split("net")[0]?.toLowerCase()??"";s?.toLowerCase().includes(d)||(await p.click(),await t.locator("div[role='menu']").locator(`> button:has-text('${o}')`).click());let P=t.locator("input[placeholder='Enter Password']"),A=t.locator("input[placeholder='Confirm Password']"),K=t.locator("label.chakra-checkbox .chakra-checkbox__control"),x=t.locator('button:has-text("Continue")');await P.fill(c),await A.fill(c),await K.click(),await x.click(),await t.locator(m.importExistingWalletButton).click(),a.mode==="secretPhrase"&&(await t.locator(m.secretPhraseButton).click(),await x.scrollIntoViewIfNeeded(),await x.click(),await t.locator("textarea:not([disabled])").fill(a.secretPhrase)),a.mode==="privateKey"&&(await t.locator(m.privateKeyButton).click(),await x.scrollIntoViewIfNeeded(),await x.click(),await t.locator("textarea:not([disabled])").fill(a.privateKey));let H=t.locator(m.findMyAccountButton);await H.click();let z=t.locator("button[type='submit'][data-loading]");if(await z.waitFor({state:"detached",timeout:25e3}),await t.getByRole("status").locator("div[id='toast-1-title']:has-text('No Account Found')").isVisible().catch(()=>!1)){let y=5,k=!1;for(;y>0;){if(console.info(`
6
+ Retrying search for account. ${y} attempts left`),await E(15e3),await H.click(),await z.waitFor({state:"detached",timeout:2e4}),await t.locator("div:has-text('Import Your Account')").nth(-2).locator("button").isVisible().catch(()=>!1)){k=!0;break}y-=1}if(!k)throw Error(O("redBright",["No Account Found","Account associated with the private key not found. Please make sure you are trying to import an account on the correct network(Mainnet/Testnet)."].join(`
7
+ `),{validateStream:!1}))}await t.locator("button:not([aria-label='Back'],[id^='menu-button']):has-text('Account')").click();let j=t.locator("section[role='dialog']").locator("button:has-text('Close')").first();if(await j.isVisible().then(()=>!0).catch(()=>!1)&&await j.click(),await B({page:t,newAccountName:r}),e&&e.length>0){for(let{accountName:q,network:G,...ft}of e)await I({page:t,accountName:q,network:G,...ft});await S(t);let y=t.locator(m.switchNetworkButton).last();await y.scrollIntoViewIfNeeded();let k=await y.textContent(),X=o.split("net")[0]?.toLowerCase()??"";k?.toLowerCase()!==X&&await L(t,o),await C(t,r)}await E(3e3),console.info(O("greenBright","\u2728 Meteor onboarding completed successfully"))}async function ut(t){await f(t),await t.locator(b.cancelButton).click()}var v=class extends g{page;constructor(o){super(),this.page=o}async onboard({network:o,accountName:r,additionalAccounts:e,...a}){await R({page:this.page,network:o,accountName:r,additionalAccounts:e,...a})}async unlock(){await f(this.page)}async lock(){await ct(this.page)}async renameAccount({newAccountName:o}){await B({page:this.page,newAccountName:o})}async switchNetwork(o){await L(this.page,o)}async switchAccount(o){await C(this.page,o)}async getAccountAddress(){return await it(this.page)}async addAccount({accountName:o,network:r,...e}){await I({page:this.page,accountName:o,network:r,...e})}async openSettings(){await S(this.page)}async connectToApp(o){await nt(await this.promptPage(this.page.context()),o)}async confirmDisconnect(){await rt(await this.promptPage(this.page.context()))}async confirmTransaction(){await at(await this.promptPage(this.page.context()))}async rejectTransaction(){await ut(await this.promptPage(this.page.context()))}};import wt from"fs";import Mt from"path";import{test as Tt,chromium as Et}from"@playwright/test";import{expect as Ct}from"@playwright/test";async function U(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}async function $(t,o){let r=await t.newPage();return await Ct(async()=>{await r.goto(o),await U(r)}).toPass(),r}async function V(t,o){let r=await o.newPage();for(let{origin:e,localStorage:a}of t){let c=r.mainFrame();await c.goto(e),await c.evaluate(w=>{w.forEach(({name:l,value:p})=>{window.localStorage.setItem(l,p)})},a)}await r.close()}import St from"fs/promises";async function mt(t){await St.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var vt=35e3;async function D(t,o){try{await Promise.race([t.close(),new Promise((r,e)=>setTimeout(()=>e(new Error("Context close timed out")),vt))])}catch(r){console.warn(`Browser context close did not complete cleanly: ${r.message}`)}try{await mt(o)}catch(r){console.error(`Failed to remove temporary context directory at ${o}. Error:`,r)}}var W,Ir=({slowMo:t=0,profileName:o}={})=>Tt.extend({contextPath:async({browserName:r},e,a)=>{let c=await T(`${r}-${a.testId}`);await e(c)},context:async({context:r,contextPath:e},a)=>{let c=new g,w=h(c.name),l=await N(c.name),p=Mt.resolve(w,o??"wallet-data");if(!wt.existsSync(p))throw new Error("\u274C Cache for Meteor wallet data not found. Create it first");wt.cpSync(p,e,{recursive:!0,force:!0}),process.env.HEADLESS&&t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!");let s=await Et.launchPersistentContext(e,{headless:!1,args:[`--disable-extensions-except=${l}`,`--load-extension=${l}`],slowMo:process.env.HEADLESS?0:t});await s.grantPermissions(["clipboard-read"]);let{cookies:d,origins:P}=await r.storageState();d&&await s.addCookies(d),P&&P.length>0&&V(P,s);let A=await c.indexUrl();W=s.pages().find(x=>x.url().startsWith(A))||await $(s,A);for(let x of s.pages())x.url().includes("about:blank")&&await x.close();await W.bringToFront(),await f(W),await a(s),await D(s,e)},meteorPage:async({context:r},e)=>{await e(W)},meteor:async({context:r},e)=>{let a=new v(W);await e(a)}});import{test as Wt}from"@playwright/test";var Vr=({slowMo:t,profileName:o}={})=>Wt.extend({workerScopeContents:[async({browser:r},e,a)=>{let{context:c,contextPath:w,walletPage:l}=await ot({workerInfo:a,profileName:o,slowMo:t,wallet:new g});await c.grantPermissions(["clipboard-read"]);for(let s of c.pages())s.url().includes("about:blank")&&await s.close();let p=new v(l);await p.unlock(),await e({wallet:p,walletPage:l,context:c}),await D(c,w)},{scope:"worker"}]});export{v as Meteor,Ir as meteorFixture,Vr as meteorWorkerScopeFixture,ot as workerScopeContext};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chainwright",
3
- "version": "0.9.8",
3
+ "version": "0.9.10",
4
4
  "description": "Playwright Web3 wallet testing framework for end-to-end dApp automation with MetaMask, Phantom, Solflare, Petra, Meteor, and Keplr",
5
5
  "type": "module",
6
6
  "license": "MIT",