@tobelabs/chainwright 0.6.1-alpha.0 → 0.6.1-alpha.1
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/wallets/keplr/index.d.ts +152 -0
- package/dist/wallets/keplr/index.js +3 -0
- package/dist/wallets/metamask/index.d.ts +203 -0
- package/dist/wallets/metamask/index.js +3 -0
- package/dist/wallets/meteor/index.d.ts +150 -0
- package/dist/wallets/meteor/index.js +7 -0
- package/dist/wallets/petra/index.d.ts +157 -0
- package/dist/wallets/petra/index.js +3 -0
- package/dist/wallets/phantom/index.d.ts +195 -0
- package/dist/wallets/phantom/index.js +3 -0
- package/dist/wallets/solflare/index.d.ts +142 -0
- package/dist/wallets/solflare/index.js +2 -0
- package/dist/worker-scope-context-ze2hEh79.d.ts +12 -0
- package/package.json +24 -6
- package/dist/wallets/index.d.ts +0 -975
- package/dist/wallets/index.js +0 -16
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var h={networkSettings:"li-settings-network",selectNetwork:"select-network",confirmModal:"modal-confirm",confifmButton:"btn-confirm",securityAndPrivacyButton:"nav-item-security-and-privacy",lockButton:"btn-lock"},A={portfolioButton:"nav-item-portfolio",walletSelectorButton:"icon-section-wallet-picker-arrow-right"};import C from"zod";var H=C.object({walletName:C.string().min(1,"Wallet name cannot be an empty string"),privateKey:C.array(C.number()).length(64)});async function b({page:t,privateKey:e,walletName:r}){let o=H.parse({privateKey:e,walletName:r});await t.getByTestId(A.walletSelectorButton).click(),await t.getByTestId("icon-btn-add").click(),await t.getByTestId("li-add-wallet-privateKey-add").click();let p=t.getByTestId("input-name"),c=t.getByTestId("input-private-key");await p.fill(o.walletName),await c.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 mt}from"@playwright/test";var v={approveButton:"btn-approve",rejectButton:"btn-reject"};async function K(t){let e=t.getByTestId(v.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 mt(e).toBeEnabled(),await e.click()}async function E(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 j(t,e){e&&await E(t,e),await t.getByRole("button",{name:"Connect",exact:!0}).click()}async function z(t){return await t.getByTestId("icon-section-wallet-picker-copy").click(),await t.evaluate(async()=>await navigator.clipboard.readText())}async function W(t){let e=t.getByRole("button",{name:"settings",exact:!0});await e.waitFor({state:"attached",timeout:3e4}),await e.click()}async function q(t){await W(t),await t.getByTestId(h.securityAndPrivacyButton).click(),await t.getByTestId("li-settings-lock").getByTestId(h.lockButton).click()}import{styleText as Y}from"util";import Q from"fs";import wt from"path";import ut from"path";var X=".wallet-cache",J=".wallet-context";var G="13.22.0",S="https://github.com/amaify/chainwright/releases/download/v0.1.0/",oe=`https://github.com/MetaMask/metamask-extension/releases/download/v${G}/metamask-chrome-${G}.zip`,re=`${S}solflare-wallet-extension-v2.19.1.zip`,ae=`${S}petra-wallet-extension-v2.4.8.zip`,ne=`${S}phantom-wallet-extension-v26.10.0.zip`,ie=`${S}meteor-wallet-extension-v0.7.0.zip`,se=`${S}keplr-wallet-extension-v0.13.3.zip`;function d(t){return ut.resolve(process.cwd(),X,t)}async function N(t){let e=d(t),r=wt.resolve(e,"password.txt");try{if(!Q.existsSync(r))throw new Error("\u274C password.txt not found. Run setup script first.");return Q.readFileSync(r,"utf-8")}catch(o){throw new Error(`\u274C Failed to get ${t} password from cache: ${o.message}`)}}var y={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 _({page:t,currentAccountName:e,newAccountName:r}){await t.getByTestId(A.walletSelectorButton).click();let a=t.locator(`button[data-testid^='li-wallets']:has-text('${e}')`);if(!await a.isVisible().catch(()=>!1))throw new Error(`Account "${e}" not found. Make sure the account is available.`);await a.hover({timeout:2e4}),await a.getByTestId("icon-btn-three-dots").click({timeout:2e4});let p=t.getByTestId("li-manage-wallet-rename-wallet");await p.click();let c=t.getByTestId("input-name");await c.clear(),await c.fill(r),await t.getByTestId("btn-save").click(),await p.waitFor({state:"attached",timeout:15e3}),await t.getByTestId("icon-btn-close").click()}async function F(t,e){await W(t);let o=t.getByTestId("li-settings-network").getByRole("combobox");await o.locator(" > p").textContent()!==e?(await o.click(),await t.getByTestId(h.selectNetwork).getByRole("option",{name:e,exact:!0}).click(),(e==="Devnet"||e==="Testnet")&&await t.getByTestId(h.confirmModal).getByTestId(h.confifmButton).click()):console.info(`Network is already set to ${e}`),await t.getByTestId(A.portfolioButton).click()}async function Z({page:t,recoveryPhrase:e,network:r,walletName:o,addWallet:a}){console.info(Y("yellowBright",`
|
|
2
|
+
Solflare onboarding started...`,{validateStream:!1}));let n=await N("solflare");await t.getByTestId(y.alreadyHaveAWalletButton).click();let p=e.split(" ");for(let[I,g]of Object.entries(p))await t.getByTestId(`${y.recoveryPhraseInput}-${Number(I)+1}`).fill(g);let c=t.getByTestId(y.continueButton);await c.click();let w=t.getByTestId(y.passwordInput),m=t.getByTestId(y.repeatPasswordInput);if(await w.fill(n),await m.fill(n),await c.click(),await t.locator("div",{hasText:"Detecting your existing accounts. This process can take up to a minute."}).waitFor({state:"detached"}),await t.getByTestId(y.quickSetupButton).click(),await t.getByTestId(y.IAgreeButton).click(),await _({page:t,currentAccountName:"Main Wallet",newAccountName:o}),r&&await F(t,r),a&&a?.length>0)for(let{privateKey:I,walletName:g}of a)await b({page:t,privateKey:I,walletName:g});console.info(Y("greenBright","\u2728 Solflare onboarding completed successfully",{validateStream:!1}))}async function tt(t){await t.getByTestId(v.rejectButton).click()}async function M(t){let e=await N("solflare");await t.getByTestId("input-password").fill(e),await t.getByTestId("btn-unlock").click(),await t.getByTestId("nav-main").waitFor({state:"attached",timeout:3e4})}import{expect as dt}from"@playwright/test";async function et({context:t,path:e,locator:r}){let o;try{await dt.poll(async()=>(o=t.pages().filter(a=>a.url().startsWith("chrome-extension://")).find(a=>a.url().match(e)),!!o),{timeout:3e4}).toBe(!0)}catch{let a=t.pages().filter(n=>n.url().startsWith("chrome-extension://")).map(n=>n.url());throw new Error(`Popup page with path "${e}" not found in context after 30s. Pages in context: ${JSON.stringify(a)}`)}if(!o)throw new Error(`Popup page with path ${e} not found in context.`);return await ft(o,r),await o.setViewportSize({width:360,height:592}),o}async function ft(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 ot from"fs";import gt from"path";async function rt(t){let e=d(t),r=gt.resolve(e,"extension-id.txt");try{if(!ot.existsSync(r))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return ot.readFileSync(r,"utf-8")}catch(o){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${o.message}`)}}var x=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 rt(this.name)}async promptPage(e){let r=await this.promptUrl();return await et({context:e,path:r,locator:"div[data-testid='page-dapp-connect'], div[data-testid='page-tx-sign']"})}};var P=class extends x{page;constructor(e){super(),this.page=e}async onboard({recoveryPhrase:e,network:r,addWallet:o,walletName:a}){await Z({page:this.page,recoveryPhrase:e,network:r,addWallet:o,walletName:a})}async unlock(){await M(this.page)}async lock(){await q(this.page)}async renameAccount({currentAccountName:e,newAccountName:r}){await _({page:this.page,currentAccountName:e,newAccountName:r})}async switchNetwork(e){await F(this.page,e)}async switchAccount(e){await E(this.page,e)}async getAccountAddress(){return await z(this.page)}async addAccount({privateKey:e,walletName:r}){await b({page:this.page,privateKey:e,walletName:r})}async connectToApp(e){await j(await this.promptPage(this.page.context()),e)}async confirmTransaction(){await K(await this.promptPage(this.page.context()))}async rejectTransaction(){await tt(await this.promptPage(this.page.context()))}};import st from"fs";import St from"path";import{test as Bt,chromium as kt}from"@playwright/test";import yt from"path";async function B(t){return yt.resolve(process.cwd(),J,t)}import{expect as xt}from"@playwright/test";async function k(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}async function U(t,e){let r=await t.newPage();return await xt(async()=>{await r.goto(e),await k(r)}).toPass(),r}async function V(t,e){let r=await e.newPage();for(let{origin:o,localStorage:a}of t){let n=r.mainFrame();await n.goto(o),await n.evaluate(l=>{l.forEach(({name:p,value:c})=>{window.localStorage.setItem(p,c)})},a)}await r.close()}import ht from"fs/promises";async function at(t){await ht.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var Pt=35e3;async function D(t,e){try{await Promise.race([t.close(),new Promise((r,o)=>setTimeout(()=>o(new Error("Context close timed out")),Pt))])}catch(r){console.warn(`Browser context close did not complete cleanly: ${r.message}`)}try{await at(e)}catch(r){console.error(`Failed to remove temporary context directory at ${e}. Error:`,r)}}import nt from"fs";import At from"path";async function O(t){try{let e=d(t),r=At.resolve(e,"extension-path.txt");if(!nt.existsSync(r))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let o=nt.readFileSync(r,"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}`)}}function it(t){return new Promise(e=>setTimeout(e,t))}async function L(t,e){let o=!1;for(;!e();){let a=e();if(a||o||t.isClosed())break;try{let n=t.locator("div[role='dialog']").locator("button[data-testid='icon-btn-whats-new-modal-close']");await n.isVisible().catch(()=>!1)&&(await n.click(),o=!0)}catch(n){console.error("[autoCloseSolflareNotification]: ",n)}if(a||o||t.isClosed())break;await it(150)}}var T,or=({slowMo:t=0,profileName:e}={})=>Bt.extend({contextPath:async({browserName:r},o,a)=>{let n=await B(`${r}-${a.testId}`);await o(n)},context:async({context:r,contextPath:o},a)=>{let n=new x,l=d(n.name),p=await O(n.name),c=St.resolve(l,e??"wallet-data");if(!st.existsSync(c))throw new Error("\u274C Cache for Solflare wallet data not found. Create it first");await st.promises.cp(c,o,{recursive:!0,force:!0});let w=[`--disable-extensions-except=${p}`,`--load-extension=${p}`];process.env.HEADLESS&&(w.push("--headless=new"),t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!"));let m=await kt.launchPersistentContext(o,{headless:!1,args:[`--disable-extensions-except=${p}`],slowMo:process.env.HEADLESS?0:t});await m.grantPermissions(["clipboard-read"]);let{cookies:f,origins:u}=await r.storageState();f&&await m.addCookies(f),u&&u.length>0&&V(u,m);let R=await n.indexUrl(),$=R.split("#")[0]??"";await m.waitForEvent("page",{predicate:g=>g.url().includes($),timeout:15e3}),T=m.pages().find(g=>g.url().startsWith($))||await U(m,R);for(let g of m.pages())g.url().includes("about:blank")&&await g.close();await M(T),await a(m),await D(m,o)},solflarePage:async({context:r},o)=>{await o(T)},solflare:async({context:r},o)=>{let a=new P(T);await o(a)},autoCloseNotification:[async({context:r},o)=>{let a=!1,l=L(T,()=>a);await o(void 0),a=!0,await l.catch(p=>{console.error(`Auto close notification error: ${p.message}`)})},{auto:!0}]});import{test as Ct}from"@playwright/test";import ct from"fs";import Tt from"path";import{chromium as It}from"@playwright/test";async function lt({workerInfo:t,profileName:e,slowMo:r}){let o=new x,a=await B(t.workerIndex.toString()),n=d(o.name),l=Tt.resolve(n,e??"wallet-data");if(!ct.existsSync(l))throw new Error(`Cache for ${o.name} does not exist. Create it first!`);ct.cpSync(l,a,{recursive:!0,force:!0});let p=await O(o.name),c=await It.launchPersistentContext(a,{headless:!1,args:[`--disable-extensions-except=${p}`],slowMo:process.env.HEADLESS?0:r}),w=await o.indexUrl(),m=w.split("#")[0]??"";await c.waitForEvent("page",{predicate:u=>u.url().includes(m),timeout:15e3});let f=c.pages().find(u=>u.url().startsWith(m));f||(f=await c.newPage(),await f.goto(w),await k(f));for(let u of c.pages())u.url().includes("about:blank")&&await u.close();return{context:c,walletPage:f,contextPath:a}}var Pr=({slowMo:t,profileName:e,dappUrl:r}={})=>Ct.extend({workerScopeContents:[async({browser:o},a,n)=>{let{context:l,contextPath:p,walletPage:c}=await lt({workerInfo:n,profileName:e,slowMo:t});await l.grantPermissions(["clipboard-read"]);let w=new P(c);await w.unlock(),await a({wallet:w,walletPage:c,context:l}),await D(l,p)},{scope:"worker"}],dappPage:[async({workerScopeContents:o},a)=>{let{context:n}=o,l=await n.newPage();r&&await l.goto(r),await a(l)},{scope:"worker"}],solflarePage:async({workerScopeContents:o},a)=>{await a(o.walletPage)},solflare:async({workerScopeContents:o},a)=>{let n=new P(o.walletPage);await a(n)},autoCloseNotification:[async({workerScopeContents:o},a)=>{let n=!1,l=()=>n,p=L(o.walletPage,l);await a(void 0),n=!0,await p.catch(c=>{console.error(`Auto close notification error: ${c.message}`)})},{auto:!0}]});export{P as Solflare,or as solflareFixture,Pr as solflareWorkerScopeFixture};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Page, BrowserContext } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
type WorkerScopeFixture<Wallet> = {
|
|
4
|
+
workerScopeContents: {
|
|
5
|
+
wallet: Wallet;
|
|
6
|
+
walletPage: Page;
|
|
7
|
+
context: BrowserContext;
|
|
8
|
+
};
|
|
9
|
+
dappPage: Page;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type { WorkerScopeFixture as W };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tobelabs/chainwright",
|
|
3
|
-
"version": "0.6.1-alpha.
|
|
3
|
+
"version": "0.6.1-alpha.1",
|
|
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",
|
|
@@ -23,17 +23,35 @@
|
|
|
23
23
|
"dapp"
|
|
24
24
|
],
|
|
25
25
|
"exports": {
|
|
26
|
-
"./
|
|
27
|
-
"types": "./dist/wallets/index.d.ts",
|
|
28
|
-
"import": "./dist/wallets/index.js"
|
|
26
|
+
"./keplr": {
|
|
27
|
+
"types": "./dist/wallets/keplr/index.d.ts",
|
|
28
|
+
"import": "./dist/wallets/keplr/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./metamask": {
|
|
31
|
+
"types": "./dist/wallets/metamask/index.d.ts",
|
|
32
|
+
"import": "./dist/wallets/metamask/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./meteor": {
|
|
35
|
+
"types": "./dist/wallets/meteor/index.d.ts",
|
|
36
|
+
"import": "./dist/wallets/meteor/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./petra": {
|
|
39
|
+
"types": "./dist/wallets/petra/index.d.ts",
|
|
40
|
+
"import": "./dist/wallets/petra/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./phantom": {
|
|
43
|
+
"types": "./dist/wallets/phantom/index.d.ts",
|
|
44
|
+
"import": "./dist/wallets/phantom/index.js"
|
|
45
|
+
},
|
|
46
|
+
"./solflare": {
|
|
47
|
+
"types": "./dist/wallets/solflare/index.d.ts",
|
|
48
|
+
"import": "./dist/wallets/solflare/index.js"
|
|
29
49
|
},
|
|
30
50
|
"./core": {
|
|
31
51
|
"types": "./dist/core/index.d.ts",
|
|
32
52
|
"import": "./dist/core/index.js"
|
|
33
53
|
}
|
|
34
54
|
},
|
|
35
|
-
"main": "./dist/wallets/index.js",
|
|
36
|
-
"types": "./dist/wallets/index.d.ts",
|
|
37
55
|
"bin": {
|
|
38
56
|
"chainwright": "dist/cli/index.js"
|
|
39
57
|
},
|