w3wallets 1.0.0-beta.7 → 1.0.0-beta.9
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/index.d.mts +28 -8
- package/dist/index.d.ts +28 -8
- package/dist/index.js +128 -63
- package/dist/index.mjs +128 -63
- package/dist/scripts/cache.js +24 -9
- package/package.json +2 -2
- package/src/scripts/download.js +668 -0
package/dist/index.d.mts
CHANGED
|
@@ -2,10 +2,16 @@ import * as playwright_test from 'playwright/test';
|
|
|
2
2
|
import { Page, test, BrowserContext } from '@playwright/test';
|
|
3
3
|
|
|
4
4
|
interface IWallet {
|
|
5
|
-
|
|
5
|
+
page: Page;
|
|
6
6
|
gotoOnboardPage(): Promise<void>;
|
|
7
7
|
approve(): Promise<void>;
|
|
8
8
|
deny(): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Called by the cache builder after setupFn completes, before the browser
|
|
11
|
+
* context is closed. Wallet implementations can override this to force
|
|
12
|
+
* persistence of in-memory state (e.g., locking the vault).
|
|
13
|
+
*/
|
|
14
|
+
beforeCacheClose?(): Promise<void>;
|
|
9
15
|
}
|
|
10
16
|
/**
|
|
11
17
|
* Configuration object for a wallet.
|
|
@@ -78,7 +84,7 @@ declare function withWallets<const T extends readonly WalletConfig[]>(test: type
|
|
|
78
84
|
}, playwright_test.PlaywrightWorkerArgs & playwright_test.PlaywrightWorkerOptions>;
|
|
79
85
|
|
|
80
86
|
declare abstract class Wallet implements IWallet {
|
|
81
|
-
|
|
87
|
+
page: Page;
|
|
82
88
|
readonly extensionId: string;
|
|
83
89
|
constructor(page: Page, extensionId: string);
|
|
84
90
|
abstract gotoOnboardPage(): Promise<void>;
|
|
@@ -121,10 +127,22 @@ declare class Metamask extends Wallet {
|
|
|
121
127
|
* confirmation-cancel-button is available.
|
|
122
128
|
*/
|
|
123
129
|
private dismissQueuedNotifications;
|
|
130
|
+
/**
|
|
131
|
+
* Close extra MetaMask extension pages that the service worker opened
|
|
132
|
+
* during onboarding (e.g. home.html#/onboarding/completion).
|
|
133
|
+
* Keeps only this.page alive.
|
|
134
|
+
*/
|
|
135
|
+
private closeExtraExtensionPages;
|
|
136
|
+
/**
|
|
137
|
+
* Poll the URL until it leaves a confirmation route. Uses polling instead
|
|
138
|
+
* of waitForURL because MetaMask uses HashRouter and hash-only changes
|
|
139
|
+
* are not reliably caught by Playwright's navigation events.
|
|
140
|
+
*/
|
|
141
|
+
private waitForConfirmRouteExit;
|
|
124
142
|
/**
|
|
125
143
|
* Wait for a target button while handling the Transaction Shield popup.
|
|
126
|
-
*
|
|
127
|
-
*
|
|
144
|
+
* Navigates to sidepanel.html so MetaMask's ConfirmationHandler routes
|
|
145
|
+
* to the pending approval, then waits for the button to become visible.
|
|
128
146
|
*/
|
|
129
147
|
private waitAndClickButton;
|
|
130
148
|
approve(): Promise<void>;
|
|
@@ -134,10 +152,12 @@ declare class Metamask extends Wallet {
|
|
|
134
152
|
*/
|
|
135
153
|
lock(): Promise<void>;
|
|
136
154
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
|
|
155
|
+
* Force-persist the vault by locking the wallet. Called by the cache builder
|
|
156
|
+
* before closing the browser context. MetaMask MV3 stores the vault lazily —
|
|
157
|
+
* locking forces the encrypted vault to be written to chrome.storage.local.
|
|
158
|
+
*/
|
|
159
|
+
beforeCacheClose(): Promise<void>;
|
|
160
|
+
/**
|
|
141
161
|
* Unlock MetaMask with password.
|
|
142
162
|
* After unlocking, stabilizes the wallet UI by handling post-unlock
|
|
143
163
|
* screens (metametrics, onboarding completion) and dismissing queued
|
package/dist/index.d.ts
CHANGED
|
@@ -2,10 +2,16 @@ import * as playwright_test from 'playwright/test';
|
|
|
2
2
|
import { Page, test, BrowserContext } from '@playwright/test';
|
|
3
3
|
|
|
4
4
|
interface IWallet {
|
|
5
|
-
|
|
5
|
+
page: Page;
|
|
6
6
|
gotoOnboardPage(): Promise<void>;
|
|
7
7
|
approve(): Promise<void>;
|
|
8
8
|
deny(): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Called by the cache builder after setupFn completes, before the browser
|
|
11
|
+
* context is closed. Wallet implementations can override this to force
|
|
12
|
+
* persistence of in-memory state (e.g., locking the vault).
|
|
13
|
+
*/
|
|
14
|
+
beforeCacheClose?(): Promise<void>;
|
|
9
15
|
}
|
|
10
16
|
/**
|
|
11
17
|
* Configuration object for a wallet.
|
|
@@ -78,7 +84,7 @@ declare function withWallets<const T extends readonly WalletConfig[]>(test: type
|
|
|
78
84
|
}, playwright_test.PlaywrightWorkerArgs & playwright_test.PlaywrightWorkerOptions>;
|
|
79
85
|
|
|
80
86
|
declare abstract class Wallet implements IWallet {
|
|
81
|
-
|
|
87
|
+
page: Page;
|
|
82
88
|
readonly extensionId: string;
|
|
83
89
|
constructor(page: Page, extensionId: string);
|
|
84
90
|
abstract gotoOnboardPage(): Promise<void>;
|
|
@@ -121,10 +127,22 @@ declare class Metamask extends Wallet {
|
|
|
121
127
|
* confirmation-cancel-button is available.
|
|
122
128
|
*/
|
|
123
129
|
private dismissQueuedNotifications;
|
|
130
|
+
/**
|
|
131
|
+
* Close extra MetaMask extension pages that the service worker opened
|
|
132
|
+
* during onboarding (e.g. home.html#/onboarding/completion).
|
|
133
|
+
* Keeps only this.page alive.
|
|
134
|
+
*/
|
|
135
|
+
private closeExtraExtensionPages;
|
|
136
|
+
/**
|
|
137
|
+
* Poll the URL until it leaves a confirmation route. Uses polling instead
|
|
138
|
+
* of waitForURL because MetaMask uses HashRouter and hash-only changes
|
|
139
|
+
* are not reliably caught by Playwright's navigation events.
|
|
140
|
+
*/
|
|
141
|
+
private waitForConfirmRouteExit;
|
|
124
142
|
/**
|
|
125
143
|
* Wait for a target button while handling the Transaction Shield popup.
|
|
126
|
-
*
|
|
127
|
-
*
|
|
144
|
+
* Navigates to sidepanel.html so MetaMask's ConfirmationHandler routes
|
|
145
|
+
* to the pending approval, then waits for the button to become visible.
|
|
128
146
|
*/
|
|
129
147
|
private waitAndClickButton;
|
|
130
148
|
approve(): Promise<void>;
|
|
@@ -134,10 +152,12 @@ declare class Metamask extends Wallet {
|
|
|
134
152
|
*/
|
|
135
153
|
lock(): Promise<void>;
|
|
136
154
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
|
|
155
|
+
* Force-persist the vault by locking the wallet. Called by the cache builder
|
|
156
|
+
* before closing the browser context. MetaMask MV3 stores the vault lazily —
|
|
157
|
+
* locking forces the encrypted vault to be written to chrome.storage.local.
|
|
158
|
+
*/
|
|
159
|
+
beforeCacheClose(): Promise<void>;
|
|
160
|
+
/**
|
|
141
161
|
* Unlock MetaMask with password.
|
|
142
162
|
* After unlocking, stabilizes the wallet UI by handling post-unlock
|
|
143
163
|
* screens (metametrics, onboarding completion) and dismissing queued
|
package/dist/index.js
CHANGED
|
@@ -98,12 +98,12 @@ var ARIA_CLOSE_TIMEOUT = 500;
|
|
|
98
98
|
var POPUP_HIDDEN_TIMEOUT = 3e3;
|
|
99
99
|
var POST_UNLOCK_TIMEOUT = 3e4;
|
|
100
100
|
var NOTIFICATION_CHECK_TIMEOUT = 5e3;
|
|
101
|
-
var CONFIRMATION_ROUTE_TIMEOUT = 15e3;
|
|
102
101
|
var POST_CLICK_TIMEOUT = 1e4;
|
|
103
102
|
var BUTTON_OR_POPUP_TIMEOUT = 3e4;
|
|
104
103
|
var LAST_RESORT_CLICK_TIMEOUT = 1e4;
|
|
105
104
|
var LOCK_SCREEN_TIMEOUT = 3e4;
|
|
106
105
|
var MENU_BUTTON_TIMEOUT = 3e4;
|
|
106
|
+
var ONBOARD_VISIBLE_TIMEOUT = 3e4;
|
|
107
107
|
var MNEMONIC_KEY_DELAY = 5;
|
|
108
108
|
var MNEMONIC_WORD_DELAY = 100;
|
|
109
109
|
|
|
@@ -293,7 +293,6 @@ async function findCachedExtension(context, ExtensionClass, expectedExtensionId,
|
|
|
293
293
|
const page = await context.newPage();
|
|
294
294
|
if (homeUrl) {
|
|
295
295
|
await page.goto(`chrome-extension://${expectedExtensionId}/${homeUrl}`);
|
|
296
|
-
await page.goto(`chrome-extension://${expectedExtensionId}/${homeUrl}`);
|
|
297
296
|
}
|
|
298
297
|
const extension = new ExtensionClass(page, expectedExtensionId);
|
|
299
298
|
return extension;
|
|
@@ -360,7 +359,7 @@ var Metamask = class extends Wallet {
|
|
|
360
359
|
await this.page.goto(`chrome-extension://${this.extensionId}/home.html`);
|
|
361
360
|
await (0, import_test3.expect)(
|
|
362
361
|
this.page.getByRole("button", { name: "I have an existing wallet" })
|
|
363
|
-
).toBeVisible({ timeout:
|
|
362
|
+
).toBeVisible({ timeout: ONBOARD_VISIBLE_TIMEOUT });
|
|
364
363
|
}
|
|
365
364
|
/**
|
|
366
365
|
* Onboard MetaMask with a mnemonic phrase
|
|
@@ -385,7 +384,6 @@ var Metamask = class extends Wallet {
|
|
|
385
384
|
}
|
|
386
385
|
const continueBtn = this.page.getByTestId("import-srp-confirm");
|
|
387
386
|
await (0, import_test3.expect)(continueBtn).toBeEnabled({ timeout: config.expectTimeout });
|
|
388
|
-
await (0, import_test3.expect)(continueBtn).toBeEnabled({ timeout: config.expectTimeout });
|
|
389
387
|
await continueBtn.click();
|
|
390
388
|
const passwordInputs = this.page.locator('input[type="password"]');
|
|
391
389
|
await passwordInputs.nth(0).fill(pwd);
|
|
@@ -399,10 +397,28 @@ var Metamask = class extends Wallet {
|
|
|
399
397
|
});
|
|
400
398
|
await openWalletBtn.click();
|
|
401
399
|
await this.page.goto(`chrome-extension://${this.extensionId}/home.html`);
|
|
402
|
-
|
|
400
|
+
const readyIndicator = this.page.getByTestId("account-options-menu-button");
|
|
401
|
+
const lockInput = this.page.getByTestId("unlock-password");
|
|
402
|
+
const state = await Promise.race([
|
|
403
|
+
readyIndicator.waitFor({ state: "visible", timeout: POST_UNLOCK_TIMEOUT }).then(() => "ready"),
|
|
404
|
+
lockInput.waitFor({ state: "visible", timeout: POST_UNLOCK_TIMEOUT }).then(() => "locked")
|
|
405
|
+
]).catch(() => "timeout");
|
|
406
|
+
debug(`metamask.onboard: post-navigate state=${state}`);
|
|
407
|
+
if (state === "locked") {
|
|
408
|
+
debug("metamask.onboard: vault locked after onboarding, auto-unlocking");
|
|
409
|
+
await lockInput.fill(password ?? this.defaultPassword);
|
|
410
|
+
await this.page.getByTestId("unlock-submit").click();
|
|
411
|
+
await this.page.waitForSelector('[data-testid="unlock-password"]', {
|
|
412
|
+
state: "hidden",
|
|
413
|
+
timeout: LOCK_SCREEN_TIMEOUT
|
|
414
|
+
});
|
|
415
|
+
await this.stabilizePostUnlock();
|
|
416
|
+
}
|
|
417
|
+
await this.closeExtraExtensionPages();
|
|
403
418
|
await this.page.goto(
|
|
404
419
|
`chrome-extension://${this.extensionId}/sidepanel.html`
|
|
405
420
|
);
|
|
421
|
+
await this.page.waitForLoadState("networkidle");
|
|
406
422
|
debug("metamask.onboard: complete");
|
|
407
423
|
}
|
|
408
424
|
/**
|
|
@@ -518,10 +534,37 @@ var Metamask = class extends Wallet {
|
|
|
518
534
|
}
|
|
519
535
|
await (0, import_test3.expect)(readyIndicator).toBeVisible({ timeout: POST_UNLOCK_TIMEOUT });
|
|
520
536
|
}
|
|
537
|
+
/**
|
|
538
|
+
* Close extra MetaMask extension pages that the service worker opened
|
|
539
|
+
* during onboarding (e.g. home.html#/onboarding/completion).
|
|
540
|
+
* Keeps only this.page alive.
|
|
541
|
+
*/
|
|
542
|
+
async closeExtraExtensionPages() {
|
|
543
|
+
const extOrigin = `chrome-extension://${this.extensionId}`;
|
|
544
|
+
const context = this.page.context();
|
|
545
|
+
const extras = context.pages().filter((p) => p !== this.page && p.url().startsWith(extOrigin));
|
|
546
|
+
if (extras.length > 0) {
|
|
547
|
+
debug(
|
|
548
|
+
`metamask.closeExtraExtensionPages: closing ${extras.length} extra page(s)`
|
|
549
|
+
);
|
|
550
|
+
await Promise.all(extras.map((p) => p.close()));
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Poll the URL until it leaves a confirmation route. Uses polling instead
|
|
555
|
+
* of waitForURL because MetaMask uses HashRouter and hash-only changes
|
|
556
|
+
* are not reliably caught by Playwright's navigation events.
|
|
557
|
+
*/
|
|
558
|
+
async waitForConfirmRouteExit(routePattern) {
|
|
559
|
+
const deadline = Date.now() + POST_CLICK_TIMEOUT;
|
|
560
|
+
while (routePattern.test(this.page.url()) && Date.now() < deadline) {
|
|
561
|
+
await this.page.waitForTimeout(500);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
521
564
|
/**
|
|
522
565
|
* Wait for a target button while handling the Transaction Shield popup.
|
|
523
|
-
*
|
|
524
|
-
*
|
|
566
|
+
* Navigates to sidepanel.html so MetaMask's ConfirmationHandler routes
|
|
567
|
+
* to the pending approval, then waits for the button to become visible.
|
|
525
568
|
*/
|
|
526
569
|
async waitAndClickButton(btnLocator) {
|
|
527
570
|
debug(`metamask.waitAndClickButton: navigating to sidepanel`);
|
|
@@ -532,63 +575,36 @@ var Metamask = class extends Wallet {
|
|
|
532
575
|
btnLocator.first().waitFor({ state: "visible", timeout }).then(() => "button"),
|
|
533
576
|
popup.first().waitFor({ state: "visible", timeout }).then(() => "popup")
|
|
534
577
|
]).catch(() => "timeout");
|
|
535
|
-
const handlePopupAndClick = async () => {
|
|
536
|
-
await this.dismissPopups();
|
|
537
|
-
await btnLocator.first().waitFor({ state: "visible", timeout: BUTTON_OR_POPUP_TIMEOUT });
|
|
538
|
-
await btnLocator.first().click();
|
|
539
|
-
};
|
|
540
578
|
await this.page.goto(sidepanelUrl);
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
} catch {
|
|
546
|
-
console.warn(
|
|
547
|
-
`[w3wallets] confirmation route not found, retrying. URL: ${this.page.url()}`
|
|
579
|
+
let result = await waitForButtonOrPopup(BUTTON_OR_POPUP_TIMEOUT);
|
|
580
|
+
if (result === "timeout") {
|
|
581
|
+
debug(
|
|
582
|
+
`metamask.waitAndClickButton: first wait timed out, reloading. URL: ${this.page.url()}`
|
|
548
583
|
);
|
|
549
584
|
await this.page.goto(sidepanelUrl);
|
|
550
|
-
|
|
551
|
-
await this.page.waitForURL(confirmRoutePattern, {
|
|
552
|
-
timeout: CONFIRMATION_ROUTE_TIMEOUT
|
|
553
|
-
});
|
|
554
|
-
} catch {
|
|
555
|
-
console.warn(
|
|
556
|
-
`[w3wallets] confirmation route not found after retry. URL: ${this.page.url()}`
|
|
557
|
-
);
|
|
558
|
-
}
|
|
585
|
+
result = await waitForButtonOrPopup(BUTTON_OR_POPUP_TIMEOUT);
|
|
559
586
|
}
|
|
560
|
-
const result = await waitForButtonOrPopup(BUTTON_OR_POPUP_TIMEOUT);
|
|
561
587
|
debug(
|
|
562
588
|
`metamask.waitAndClickButton: result=${result}, URL=${this.page.url()}`
|
|
563
589
|
);
|
|
564
590
|
if (result === "button") {
|
|
565
591
|
await btnLocator.first().click();
|
|
566
|
-
await this.
|
|
567
|
-
timeout: POST_CLICK_TIMEOUT
|
|
568
|
-
}).catch(() => {
|
|
569
|
-
console.warn(
|
|
570
|
-
`[w3wallets] still on confirmation route after click. URL: ${this.page.url()}`
|
|
571
|
-
);
|
|
572
|
-
});
|
|
592
|
+
await this.waitForConfirmRouteExit(confirmRoutePattern);
|
|
573
593
|
return;
|
|
574
594
|
}
|
|
575
595
|
if (result === "popup") {
|
|
576
|
-
await
|
|
577
|
-
await
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
console.warn(
|
|
581
|
-
`[w3wallets] still on confirmation route after popup dismiss. URL: ${this.page.url()}`
|
|
582
|
-
);
|
|
583
|
-
});
|
|
596
|
+
await this.dismissPopups();
|
|
597
|
+
await btnLocator.first().waitFor({ state: "visible", timeout: BUTTON_OR_POPUP_TIMEOUT });
|
|
598
|
+
await btnLocator.first().click();
|
|
599
|
+
await this.waitForConfirmRouteExit(confirmRoutePattern);
|
|
584
600
|
return;
|
|
585
601
|
}
|
|
586
602
|
const isOnConfirmRoute = confirmRoutePattern.test(this.page.url());
|
|
587
603
|
debug(
|
|
588
|
-
`metamask.waitAndClickButton: timeout
|
|
604
|
+
`metamask.waitAndClickButton: timeout. URL: ${this.page.url()}, onConfirmRoute: ${isOnConfirmRoute}`
|
|
589
605
|
);
|
|
590
606
|
console.warn(
|
|
591
|
-
`[w3wallets] no button or popup found after
|
|
607
|
+
`[w3wallets] no button or popup found after waiting. URL: ${this.page.url()}`
|
|
592
608
|
);
|
|
593
609
|
await btnLocator.first().click({ timeout: LAST_RESORT_CLICK_TIMEOUT });
|
|
594
610
|
}
|
|
@@ -610,14 +626,50 @@ var Metamask = class extends Wallet {
|
|
|
610
626
|
await this.page.goto(`chrome-extension://${this.extensionId}/home.html`);
|
|
611
627
|
const menuBtn = this.page.getByTestId("account-options-menu-button");
|
|
612
628
|
await menuBtn.waitFor({ state: "visible", timeout: MENU_BUTTON_TIMEOUT });
|
|
613
|
-
await menuBtn.click();
|
|
629
|
+
await menuBtn.click({ force: true });
|
|
614
630
|
await this.page.locator("text=Log out").click();
|
|
615
631
|
}
|
|
616
632
|
/**
|
|
617
|
-
*
|
|
618
|
-
*
|
|
619
|
-
*
|
|
620
|
-
|
|
633
|
+
* Force-persist the vault by locking the wallet. Called by the cache builder
|
|
634
|
+
* before closing the browser context. MetaMask MV3 stores the vault lazily —
|
|
635
|
+
* locking forces the encrypted vault to be written to chrome.storage.local.
|
|
636
|
+
*/
|
|
637
|
+
async beforeCacheClose() {
|
|
638
|
+
debug("metamask.beforeCacheClose: locking wallet to force vault persistence");
|
|
639
|
+
await this.page.goto(`chrome-extension://${this.extensionId}/home.html`);
|
|
640
|
+
const menuBtn = this.page.getByTestId("account-options-menu-button");
|
|
641
|
+
const lockInput = this.page.getByTestId("unlock-password");
|
|
642
|
+
const state = await Promise.race([
|
|
643
|
+
menuBtn.waitFor({ state: "visible", timeout: MENU_BUTTON_TIMEOUT }).then(() => "ready"),
|
|
644
|
+
lockInput.waitFor({ state: "visible", timeout: MENU_BUTTON_TIMEOUT }).then(() => "locked")
|
|
645
|
+
]).catch(() => "timeout");
|
|
646
|
+
debug(`metamask.beforeCacheClose: state=${state}`);
|
|
647
|
+
if (state === "ready") {
|
|
648
|
+
await this.lock();
|
|
649
|
+
await lockInput.waitFor({ state: "visible", timeout: LOCK_SCREEN_TIMEOUT }).catch(() => {
|
|
650
|
+
});
|
|
651
|
+
} else if (state === "timeout") {
|
|
652
|
+
debug("metamask.beforeCacheClose: forcing state sync via new UI connection");
|
|
653
|
+
const syncPage = await this.page.context().newPage();
|
|
654
|
+
await syncPage.goto(`chrome-extension://${this.extensionId}/home.html`);
|
|
655
|
+
await syncPage.waitForLoadState("networkidle");
|
|
656
|
+
const syncMenuBtn = syncPage.getByTestId("account-options-menu-button");
|
|
657
|
+
const syncLockInput = syncPage.getByTestId("unlock-password");
|
|
658
|
+
const syncState = await Promise.race([
|
|
659
|
+
syncMenuBtn.waitFor({ state: "visible", timeout: MENU_BUTTON_TIMEOUT }).then(() => "ready"),
|
|
660
|
+
syncLockInput.waitFor({ state: "visible", timeout: MENU_BUTTON_TIMEOUT }).then(() => "locked")
|
|
661
|
+
]).catch(() => "timeout");
|
|
662
|
+
debug(`metamask.beforeCacheClose: syncPage state=${syncState}`);
|
|
663
|
+
if (syncState === "ready") {
|
|
664
|
+
await syncMenuBtn.click({ force: true });
|
|
665
|
+
await syncPage.locator("text=Log out").click();
|
|
666
|
+
await syncLockInput.waitFor({ state: "visible", timeout: LOCK_SCREEN_TIMEOUT }).catch(() => {
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
await syncPage.close();
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
621
673
|
* Unlock MetaMask with password.
|
|
622
674
|
* After unlocking, stabilizes the wallet UI by handling post-unlock
|
|
623
675
|
* screens (metametrics, onboarding completion) and dismissing queued
|
|
@@ -627,14 +679,21 @@ var Metamask = class extends Wallet {
|
|
|
627
679
|
debug("metamask.unlock: starting");
|
|
628
680
|
const pwd = password ?? this.defaultPassword;
|
|
629
681
|
await this.page.goto(`chrome-extension://${this.extensionId}/home.html`);
|
|
630
|
-
|
|
631
|
-
const
|
|
632
|
-
await
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
682
|
+
const lockInput = this.page.getByTestId("unlock-password");
|
|
683
|
+
const readyIndicator = this.page.getByTestId("account-options-menu-button");
|
|
684
|
+
const state = await Promise.race([
|
|
685
|
+
lockInput.waitFor({ state: "visible", timeout: POST_UNLOCK_TIMEOUT }).then(() => "locked"),
|
|
686
|
+
readyIndicator.waitFor({ state: "visible", timeout: POST_UNLOCK_TIMEOUT }).then(() => "ready")
|
|
687
|
+
]).catch(() => "timeout");
|
|
688
|
+
debug(`metamask.unlock: state=${state}`);
|
|
689
|
+
if (state === "locked") {
|
|
690
|
+
await lockInput.fill(pwd);
|
|
691
|
+
await this.page.getByTestId("unlock-submit").click();
|
|
692
|
+
await this.page.waitForSelector('[data-testid="unlock-password"]', {
|
|
693
|
+
state: "hidden",
|
|
694
|
+
timeout: LOCK_SCREEN_TIMEOUT
|
|
695
|
+
});
|
|
696
|
+
}
|
|
638
697
|
await this.stabilizePostUnlock();
|
|
639
698
|
debug("metamask.unlock: complete");
|
|
640
699
|
}
|
|
@@ -646,7 +705,7 @@ var Metamask = class extends Wallet {
|
|
|
646
705
|
debug(`metamask.switchNetwork: ${networkName} (${networkType})`);
|
|
647
706
|
await this.page.getByTestId("sort-by-networks").click();
|
|
648
707
|
if (networkType === "Custom") {
|
|
649
|
-
await this.page.getByRole("tab", { name: "Custom" }).click();
|
|
708
|
+
await this.page.getByRole("tab", { name: "Custom" }).click({ force: true });
|
|
650
709
|
}
|
|
651
710
|
await this.page.getByText(networkName).click();
|
|
652
711
|
await (0, import_test3.expect)(this.page.getByTestId("sort-by-networks")).toHaveText(
|
|
@@ -672,7 +731,7 @@ var Metamask = class extends Wallet {
|
|
|
672
731
|
await this.page.getByRole("button", { name: /save/i }).click();
|
|
673
732
|
}
|
|
674
733
|
async addCustomNetwork(settings) {
|
|
675
|
-
await this.page.getByTestId("account-options-menu-button").click();
|
|
734
|
+
await this.page.getByTestId("account-options-menu-button").click({ force: true });
|
|
676
735
|
await this.page.getByTestId("global-menu-networks").click();
|
|
677
736
|
await this.page.getByRole("button", { name: "Add a custom network" }).click();
|
|
678
737
|
await this.page.getByTestId("network-form-network-name").fill(settings.name);
|
|
@@ -683,11 +742,17 @@ var Metamask = class extends Wallet {
|
|
|
683
742
|
await this.page.getByTestId("rpc-url-input-test").fill(settings.rpc);
|
|
684
743
|
await this.page.getByRole("button", { name: "Add URL" }).click();
|
|
685
744
|
await this.page.getByRole("button", { name: "Save" }).click();
|
|
745
|
+
await this.page.goto(`chrome-extension://${this.extensionId}/home.html`);
|
|
746
|
+
await this.page.waitForLoadState("domcontentloaded");
|
|
686
747
|
}
|
|
687
748
|
async enableTestNetworks() {
|
|
688
|
-
await this.page.getByTestId("account-options-menu-button").click();
|
|
749
|
+
await this.page.getByTestId("account-options-menu-button").click({ force: true });
|
|
689
750
|
await this.page.getByTestId("global-menu-networks").click();
|
|
690
|
-
|
|
751
|
+
const toggle = this.page.locator(
|
|
752
|
+
"text=Show test networks >> xpath=following-sibling::label"
|
|
753
|
+
);
|
|
754
|
+
await (0, import_test3.expect)(toggle).toBeVisible({ timeout: config.expectTimeout });
|
|
755
|
+
await toggle.click();
|
|
691
756
|
await this.page.keyboard.press("Escape");
|
|
692
757
|
}
|
|
693
758
|
async importAccount(privateKey) {
|