dappress 0.5.1 → 0.6.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/CHANGELOG.md CHANGED
@@ -4,6 +4,19 @@ What changes for the users of Dappress, version by version. The format follows [
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.6.1] - 2026-10-05
8
+
9
+ ### Fixed
10
+
11
+ - `cy.confirmTransaction({ gas })` no longer confirms, now and then, with the fee MetaMask estimated in place of the one asked. MetaMask's confirmation carries the new fee a moment after the fee editor closes, and confirming meanwhile sent it the old one, which it kept. The command now waits for the "Network fee" row to change, as it did for the spending cap.
12
+
13
+ ## [0.6.0] - 2026-10-05
14
+
15
+ ### Fixed
16
+
17
+ - The peer dependency on Cypress asks for 15.10 or later, the first version with `Cypress.expose()`, which the commands read their options with. Earlier versions were accepted at install, then failed as soon as the support file loaded.
18
+ - A command sent right after another was answered in the popup no longer fails on "Timed out waiting for confirm-footer-button". The popup closes a moment after its button goes, and the next command could find it, still listed on the request just answered, then lose it. A decision now waits for the popup to close, and a confirmation that closes before it is acted on is looked for again.
19
+
7
20
  ## [0.5.1] - 2026-10-05
8
21
 
9
22
  ### Changed
@@ -85,7 +98,9 @@ What changes for the users of Dappress, version by version. The format follows [
85
98
  - The wallet setup file, `cypress/wallet.setup.ts`, and the opt-in profile cache.
86
99
  - TypeScript declarations.
87
100
 
88
- [Unreleased]: https://github.com/blassaut/dappress/compare/v0.5.1...HEAD
101
+ [Unreleased]: https://github.com/blassaut/dappress/compare/v0.6.1...HEAD
102
+ [0.6.1]: https://github.com/blassaut/dappress/compare/v0.6.0...v0.6.1
103
+ [0.6.0]: https://github.com/blassaut/dappress/compare/v0.5.1...v0.6.0
89
104
  [0.5.1]: https://github.com/blassaut/dappress/compare/v0.5.0...v0.5.1
90
105
  [0.5.0]: https://github.com/blassaut/dappress/compare/v0.4.0...v0.5.0
91
106
  [0.4.0]: https://github.com/blassaut/dappress/compare/v0.3.3...v0.4.0
package/dist/actions.js CHANGED
@@ -86,16 +86,27 @@ function createTasks(options) {
86
86
  await metamask.leaveUnlockForm(page, options);
87
87
  return state;
88
88
  }
89
- /** Approve the prompt a network change raised: "Add network" or the permission to switch. */
90
- async function approveNetworkChange(browser) {
91
- const page = await (0, metamask_pages_1.getConfirmationPage)(browser, await metamaskId(browser), options.timeout);
92
- await metamask.approveNetworkChange(page, options.timeout);
89
+ /**
90
+ * Find the confirmation and act on it. One that closes before it is acted
91
+ * on was the popup of the request before, found as it closed: the request's
92
+ * own is looked for once more.
93
+ */
94
+ async function onConfirmation(browser, act) {
95
+ for (let attempt = 0;; attempt++) {
96
+ const page = await (0, metamask_pages_1.getConfirmationPage)(browser, await metamaskId(browser), options.timeout);
97
+ try {
98
+ return await act(page);
99
+ }
100
+ catch (error) {
101
+ if (attempt > 0 || !(error instanceof metamask.ConfirmationClosed))
102
+ throw error;
103
+ }
104
+ }
93
105
  }
106
+ /** Approve the prompt a network change raised: "Add network" or the permission to switch. */
107
+ const approveNetworkChange = (browser) => onConfirmation(browser, (page) => metamask.approveNetworkChange(page, options.timeout));
94
108
  /** The task for a decision: find the confirmation, press its button. */
95
- const decide = (decision) => async (browser, argument) => {
96
- const page = await (0, metamask_pages_1.getConfirmationPage)(browser, await metamaskId(browser), options.timeout);
97
- await metamask.decide(decision, page, options.timeout, argument);
98
- };
109
+ const decide = (decision) => (browser, argument) => onConfirmation(browser, (page) => metamask.decide(decision, page, options.timeout, argument));
99
110
  const actions = {
100
111
  setupWallet,
101
112
  approveNetworkChange,
package/dist/browser.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  // Connects Puppeteer to the browser Cypress launched, through the debugging
3
- // URL Cypress hands out in after:browser:launch (Cypress 13.6+).
3
+ // URL Cypress hands out in after:browser:launch (Cypress 15.10+).
4
4
  var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  return (mod && mod.__esModule) ? mod : { "default": mod };
6
6
  };
@@ -20,7 +20,7 @@ function captureDebuggerUrl(on) {
20
20
  */
21
21
  async function withBrowser(action) {
22
22
  if (!debuggerUrl) {
23
- throw new Error('[dappress] No browser to connect to. Is configureDappress() called in setupNodeEvents, with Cypress 13.6 or later?');
23
+ throw new Error('[dappress] No browser to connect to. Is configureDappress() called in setupNodeEvents, with Cypress 15.10 or later?');
24
24
  }
25
25
  const browser = await puppeteer_core_1.default.connect({ browserWSEndpoint: debuggerUrl, defaultViewport: null });
26
26
  try {
@@ -12,6 +12,16 @@ export declare function getRequestPages(browser: Browser, extensionId: string):
12
12
  * The page a dapp request is shown on. Waits for the popup to open, or takes
13
13
  * the side panel. A popup still on its home route is one closing after the
14
14
  * previous request, or one that hasn't routed to the request yet: skipped.
15
+ * The route is read from the page, which follows a change of hash at once,
16
+ * where the target can still name the request just answered.
15
17
  */
16
18
  export declare function getConfirmationPage(browser: Browser, extensionId: string, timeout: number): Promise<Page>;
19
+ /**
20
+ * Once the request shown on a popup is answered, wait for the popup to close,
21
+ * at most `timeout` ms. MetaMask closes it a moment after its button goes, and
22
+ * left to close on its own, the next command could find it, still listed on
23
+ * `request`, and act on a page that vanishes under it. A popup that goes on
24
+ * to another request instead is left to it; so is the side panel, which stays.
25
+ */
26
+ export declare function waitForDismissal(page: Page, request: string, timeout: number): Promise<void>;
17
27
  export declare function withUsableWindow(page: Page): Promise<Page>;
@@ -7,6 +7,7 @@ exports.findExtensionId = findExtensionId;
7
7
  exports.getHomePage = getHomePage;
8
8
  exports.getRequestPages = getRequestPages;
9
9
  exports.getConfirmationPage = getConfirmationPage;
10
+ exports.waitForDismissal = waitForDismissal;
10
11
  exports.withUsableWindow = withUsableWindow;
11
12
  const page_helpers_1 = require("./page-helpers");
12
13
  const HOME_PATH = '/home.html';
@@ -97,14 +98,20 @@ async function getRequestPages(browser, extensionId) {
97
98
  * The page a dapp request is shown on. Waits for the popup to open, or takes
98
99
  * the side panel. A popup still on its home route is one closing after the
99
100
  * previous request, or one that hasn't routed to the request yet: skipped.
101
+ * The route is read from the page, which follows a change of hash at once,
102
+ * where the target can still name the request just answered.
100
103
  */
101
104
  async function getConfirmationPage(browser, extensionId, timeout) {
102
105
  const deadline = Date.now() + timeout;
103
106
  while (Date.now() < deadline) {
104
107
  for (const pathname of CONFIRMATION_PATHS) {
105
- const [target] = pagesOf(browser, extensionId, pathname).filter((candidate) => !isHomeRoute(candidate.url()));
106
- if (target)
107
- return pathname === '/notification.html' ? withUsableWindow(await pageOf(target)) : pageOf(target);
108
+ for (const target of pagesOf(browser, extensionId, pathname)) {
109
+ // A target closing while its page is taken has none: not a confirmation either
110
+ const page = await target.page().catch(() => null);
111
+ if (!page || page.isClosed() || isHomeRoute(page.url()))
112
+ continue;
113
+ return pathname === '/notification.html' ? withUsableWindow(page) : page;
114
+ }
108
115
  }
109
116
  await (0, page_helpers_1.sleep)(250);
110
117
  }
@@ -115,6 +122,26 @@ async function getConfirmationPage(browser, extensionId, timeout) {
115
122
  .join(', ');
116
123
  throw new Error(`[dappress] MetaMask showed no confirmation within ${timeout}ms. Did the dapp send a request? MetaMask pages seen: ${seen || 'none'}`);
117
124
  }
125
+ /**
126
+ * Once the request shown on a popup is answered, wait for the popup to close,
127
+ * at most `timeout` ms. MetaMask closes it a moment after its button goes, and
128
+ * left to close on its own, the next command could find it, still listed on
129
+ * `request`, and act on a page that vanishes under it. A popup that goes on
130
+ * to another request instead is left to it; so is the side panel, which stays.
131
+ */
132
+ async function waitForDismissal(page, request, timeout) {
133
+ if (!request.includes('/notification.html'))
134
+ return;
135
+ const deadline = Date.now() + timeout;
136
+ while (Date.now() < deadline) {
137
+ if (page.isClosed())
138
+ return;
139
+ const url = page.url();
140
+ if (url !== request && !isHomeRoute(url))
141
+ return;
142
+ await (0, page_helpers_1.sleep)(100);
143
+ }
144
+ }
118
145
  // MetaMask asks Chrome for a 400x620 popup. Under Xvfb on a GitHub runner the
119
146
  // window it gets is 1x1: nothing is laid out, the pane of a confirmation that
120
147
  // must be read to the end has no height, so it can never be scrolled there and
@@ -126,7 +153,7 @@ async function withUsableWindow(page) {
126
153
  const { windowId, bounds } = await session.send('Browser.getWindowForTarget');
127
154
  if (bounds.windowState === 'normal' && (bounds.width ?? 0) >= 200 && (bounds.height ?? 0) >= 200)
128
155
  return page;
129
- console.log(`[dappress] MetaMask's popup is ${bounds.width}x${bounds.height} (${bounds.windowState}); resizing it to ${POPUP.width}x${POPUP.height}`);
156
+ console.log(`[dappress] MetaMask's popup is ${bounds.width}x${bounds.height} (${bounds.windowState}), as under Xvfb without a window manager; resizing it to ${POPUP.width}x${POPUP.height}`);
130
157
  if (bounds.windowState !== 'normal')
131
158
  await session.send('Browser.setWindowBounds', { windowId, bounds: { windowState: 'normal' } });
132
159
  await session.send('Browser.setWindowBounds', { windowId, bounds: { ...POPUP } });
@@ -48,6 +48,13 @@ export declare function disconnectSite(page: Page, origin: string): Promise<void
48
48
  type CommandOptions = ConnectOptions & TransactionOptions;
49
49
  /** Press the button of `decision` on the confirmation shown on `page`, once it is set as `options` ask. */
50
50
  export declare function decide(decision: Decision, page: Page, timeout: number, options?: CommandOptions): Promise<void>;
51
+ /**
52
+ * Thrown when the confirmation page closed before its button was pressed: it
53
+ * was the popup of the request before, found as it closed. The request's own
54
+ * popup is there to be looked for.
55
+ */
56
+ export declare class ConfirmationClosed extends Error {
57
+ }
51
58
  /** wallet_addEthereumChain on a network MetaMask knows behaves like a switch: either prompt may show. */
52
59
  export declare function approveNetworkChange(page: Page, timeout: number): Promise<void>;
53
60
  export {};
package/dist/metamask.js CHANGED
@@ -7,7 +7,7 @@
7
7
  // first, then a fallback on the button's English text. When a MetaMask release
8
8
  // moves something, this is the file to fix.
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.decisions = void 0;
10
+ exports.ConfirmationClosed = exports.decisions = void 0;
11
11
  exports.walletState = walletState;
12
12
  exports.onboard = onboard;
13
13
  exports.unlock = unlock;
@@ -20,6 +20,7 @@ exports.disconnectSite = disconnectSite;
20
20
  exports.decide = decide;
21
21
  exports.approveNetworkChange = approveNetworkChange;
22
22
  const page_helpers_1 = require("./page-helpers");
23
+ const metamask_pages_1 = require("./metamask-pages");
23
24
  const testId = (id) => `[data-testid="${id}"]`;
24
25
  // XPath rather than Puppeteer's ::-p-text(): the latter needs MutationObserver,
25
26
  // which MetaMask's sandbox (LavaMoat) blocks in its pages.
@@ -136,6 +137,8 @@ const selectors = {
136
137
  gasForm: testId('gas-fee-advanced-eip1559-modal'),
137
138
  gasField: (id) => [`#${id}`, `${testId(id)} input`],
138
139
  gasSave: [testId('gas-fee-modal-save-button'), buttonText('Save')],
140
+ // The "Network fee" row: its amount and the name of its estimate
141
+ feeSection: testId('gas-fee-section'),
139
142
  },
140
143
  // The older footer, still used by the permission update a network switch
141
144
  // asks for, by "Add suggested tokens", and by template confirmations
@@ -553,11 +556,30 @@ async function decide(decision, page, timeout, options) {
553
556
  const adjust = adjustments[decision];
554
557
  if (!adjust)
555
558
  throw new Error(`[dappress] ${decision} takes no options`);
556
- await (0, page_helpers_1.waitFor)(page, exports.decisions[decision], { timeout });
559
+ await waitForButton(page, exports.decisions[decision], timeout);
557
560
  await adjust(page, options, timeout);
558
561
  }
559
562
  return pressAndWaitForDismissal(page, exports.decisions[decision], timeout);
560
563
  }
564
+ /**
565
+ * Thrown when the confirmation page closed before its button was pressed: it
566
+ * was the popup of the request before, found as it closed. The request's own
567
+ * popup is there to be looked for.
568
+ */
569
+ class ConfirmationClosed extends Error {
570
+ }
571
+ exports.ConfirmationClosed = ConfirmationClosed;
572
+ // The button of a confirmation, or ConfirmationClosed if the page went meanwhile
573
+ async function waitForButton(page, button, timeout) {
574
+ try {
575
+ await (0, page_helpers_1.waitFor)(page, button, { timeout });
576
+ }
577
+ catch (error) {
578
+ if (page.isClosed())
579
+ throw new ConfirmationClosed(`[dappress] The confirmation closed before "${(0, page_helpers_1.describe)(button)}" was pressed`);
580
+ throw error;
581
+ }
582
+ }
561
583
  /** wallet_addEthereumChain on a network MetaMask knows behaves like a switch: either prompt may show. */
562
584
  function approveNetworkChange(page, timeout) {
563
585
  return pressAndWaitForDismissal(page, [...selectors.confirmation.confirm, ...selectors.pageContainer.confirm], timeout);
@@ -617,7 +639,7 @@ async function setSpendingCap(page, cap) {
617
639
  const s = selectors.transaction;
618
640
  if (!(await (0, page_helpers_1.isVisible)(page, s.editSpendingCap, 10000)))
619
641
  throw await (0, page_helpers_1.failure)(page, 'MetaMask shows no spending cap to edit: spendingCap is for an ERC-20 approval');
620
- const shown = await textOf(page, s.spendingCap);
642
+ const shown = await (0, page_helpers_1.textOf)(page, s.spendingCap);
621
643
  const asked = await openSpendingCap(page);
622
644
  await type(page, s.spendingCapInput, cap, 'spending cap');
623
645
  if (!(await pressToClose(page, s.spendingCapSave, s.spendingCapInput)))
@@ -625,9 +647,7 @@ async function setSpendingCap(page, cap) {
625
647
  // The modal closes before the confirmation has the new cap, and confirming
626
648
  // meanwhile approves the old one. Two caps may read the same once MetaMask
627
649
  // has rounded them, so a row that stays as it was is not a failure.
628
- const deadline = Date.now() + (Number(asked) === Number(cap) ? 0 : 5000);
629
- while (Date.now() < deadline && (await textOf(page, s.spendingCap)) === shown)
630
- await (0, page_helpers_1.sleep)(250);
650
+ await (0, page_helpers_1.waitForTextChange)(page, s.spendingCap, shown, Number(asked) === Number(cap) ? 0 : 5000);
631
651
  }
632
652
  /** Open the spending cap's modal. Yields the cap the dapp asked for, which its field starts with. */
633
653
  async function openSpendingCap(page) {
@@ -648,11 +668,14 @@ async function setGas(page, gas) {
648
668
  const s = selectors.transaction;
649
669
  if (!(await (0, page_helpers_1.isVisible)(page, s.editGas, 10000)))
650
670
  throw await (0, page_helpers_1.failure)(page, 'MetaMask shows no network fee to edit on this confirmation');
671
+ const shown = await (0, page_helpers_1.textOf)(page, s.feeSection);
651
672
  await openFeeEditor(page);
652
- if (typeof gas === 'string')
653
- await pickGasEstimate(page, gas);
654
- else
655
- await fillGasForm(page, gas);
673
+ const changed = typeof gas === 'string' ? await pickGasEstimate(page, gas) : await fillGasForm(page, gas);
674
+ // The editor closes before the confirmation carries the new fee, and
675
+ // confirming meanwhile sends MetaMask the old one, which it keeps: the row
676
+ // is waited for to change. A fee set as it already was changes nothing.
677
+ if (changed)
678
+ await (0, page_helpers_1.waitForTextChange)(page, s.feeSection, shown, 5000);
656
679
  }
657
680
  async function openFeeEditor(page) {
658
681
  const s = selectors.transaction;
@@ -667,32 +690,45 @@ async function openFeeEditor(page) {
667
690
  // Picking an estimate closes the editor. MetaMask lists the estimates it has
668
691
  // for the network: Low, Market and Aggressive where it has fee estimates,
669
692
  // "Network suggested" where it only has a gas price, as on a local node.
693
+ // Yields whether the transaction had another estimate before.
670
694
  async function pickGasEstimate(page, name) {
671
695
  const s = selectors.transaction;
672
696
  const option = s.gasOption(...gasEstimates[name]);
673
697
  if (!(await (0, page_helpers_1.isVisible)(page, option, 5000)))
674
698
  throw await (0, page_helpers_1.failure)(page, `MetaMask offers no "${name}" fee for this transaction`);
699
+ const selected = await hasEstimate(page, option);
675
700
  for (let attempt = 0; attempt < 3; attempt++) {
676
701
  await (0, page_helpers_1.click)(page, option);
677
702
  if (await (0, page_helpers_1.isGone)(page, s.gasEstimates, 10000))
678
- return;
703
+ return !selected;
679
704
  }
680
705
  throw await (0, page_helpers_1.failure)(page, `MetaMask did not take the "${name}" fee`);
681
706
  }
707
+ // The estimate the transaction has is marked by a class on its row
708
+ async function hasEstimate(page, option) {
709
+ const element = await (0, page_helpers_1.waitFor)(page, option);
710
+ return element.evaluate((el) => el.className.includes('--selected')).catch(() => false);
711
+ }
712
+ // Yields whether a field is given another value than it had
682
713
  async function fillGasForm(page, values) {
683
714
  const s = selectors.transaction;
684
715
  await openGasForm(page);
716
+ const asked = Object.keys(gasFields).filter((field) => values[field] !== undefined);
717
+ let changed = false;
718
+ for (const field of asked) {
719
+ if (Number(await valueOf(page, s.gasField(gasFields[field]))) !== Number(values[field]))
720
+ changed = true;
721
+ }
685
722
  // The form checks each fee against the other as it stood, and keeps the old
686
723
  // value of a fee it refused: the max base fee is typed again once the
687
724
  // priority fee is in, for two fees that both move below or above the old ones.
688
- const fields = Object.keys(gasFields).filter((field) => values[field] !== undefined);
689
- if (values.maxBaseFee !== undefined && values.priorityFee !== undefined)
690
- fields.push('maxBaseFee');
725
+ const fields = values.maxBaseFee !== undefined && values.priorityFee !== undefined ? [...asked, 'maxBaseFee'] : asked;
691
726
  for (const field of fields)
692
727
  await type(page, s.gasField(gasFields[field]), values[field], field);
693
728
  // "Save" stays disabled on a value the form refuses, and the error quotes what the form says of it
694
729
  if (!(await pressToClose(page, s.gasSave, s.gasForm)))
695
730
  throw await (0, page_helpers_1.failure)(page, 'MetaMask did not save the network fee');
731
+ return changed;
696
732
  }
697
733
  // "Advanced", in the list of estimates, replaces the list with the form. A
698
734
  // transaction with a gas price gets another form, which has none of these fields.
@@ -728,10 +764,6 @@ async function valueOf(page, selector) {
728
764
  const field = await (0, page_helpers_1.waitFor)(page, selector);
729
765
  return field.evaluate((el) => el.value);
730
766
  }
731
- async function textOf(page, selector) {
732
- const element = await page.$(selector);
733
- return element ? element.evaluate((el) => (el.textContent ?? '').trim()).catch(() => null) : null;
734
- }
735
767
  /**
736
768
  * Press a footer button, then wait for the confirmation to go away: the
737
769
  * popup closes, the side panel goes back to the home screen. A click that
@@ -741,7 +773,7 @@ async function textOf(page, selector) {
741
773
  * what MetaMask logged.
742
774
  */
743
775
  async function pressAndWaitForDismissal(page, button, timeout) {
744
- await (0, page_helpers_1.waitFor)(page, button, { timeout });
776
+ await waitForButton(page, button, timeout);
745
777
  await dismissModal(page);
746
778
  const logged = recordErrors(page);
747
779
  const request = page.url();
@@ -751,7 +783,7 @@ async function pressAndWaitForDismissal(page, button, timeout) {
751
783
  if (await (0, page_helpers_1.isVisible)(page, selectors.alert.acknowledge, 500))
752
784
  await (0, page_helpers_1.click)(page, selectors.alert.acknowledge);
753
785
  if (await (0, page_helpers_1.isGone)(page, button, 3000))
754
- return;
786
+ return (0, metamask_pages_1.waitForDismissal)(page, request, 3000);
755
787
  await dismissModal(page);
756
788
  await (0, page_helpers_1.dispatchClick)(page, button, { timeout: 3000 }).catch(() => { });
757
789
  }
@@ -29,5 +29,13 @@ export declare function fill(page: Page, selector: Selector, text: string, optio
29
29
  * words for the log and as a screenshot to look at.
30
30
  */
31
31
  export declare function failure(page: Page, message: string): Promise<Error>;
32
+ /** The text of the first element `selector` matches, or null when there is none. */
33
+ export declare function textOf(page: Page, selector: string): Promise<string | null>;
34
+ /**
35
+ * Wait for the text of `selector` to differ from `shown`, at most `timeout`
36
+ * ms. For a value MetaMask sets on its page a moment after a modal that
37
+ * edits it closes: acting on the page meanwhile acts on the old value.
38
+ */
39
+ export declare function waitForTextChange(page: Page, selector: string, shown: string | null, timeout: number): Promise<void>;
32
40
  export declare function sleep(ms: number): Promise<void>;
33
41
  export {};
@@ -18,6 +18,8 @@ exports.clickWhenEnabled = clickWhenEnabled;
18
18
  exports.dispatchClick = dispatchClick;
19
19
  exports.fill = fill;
20
20
  exports.failure = failure;
21
+ exports.textOf = textOf;
22
+ exports.waitForTextChange = waitForTextChange;
21
23
  exports.sleep = sleep;
22
24
  const node_fs_1 = __importDefault(require("node:fs"));
23
25
  const node_os_1 = __importDefault(require("node:os"));
@@ -194,6 +196,21 @@ async function pageText(page) {
194
196
  return '';
195
197
  }
196
198
  }
199
+ /** The text of the first element `selector` matches, or null when there is none. */
200
+ async function textOf(page, selector) {
201
+ const element = await page.$(selector);
202
+ return element ? element.evaluate((el) => (el.textContent ?? '').trim()).catch(() => null) : null;
203
+ }
204
+ /**
205
+ * Wait for the text of `selector` to differ from `shown`, at most `timeout`
206
+ * ms. For a value MetaMask sets on its page a moment after a modal that
207
+ * edits it closes: acting on the page meanwhile acts on the old value.
208
+ */
209
+ async function waitForTextChange(page, selector, shown, timeout) {
210
+ const deadline = Date.now() + timeout;
211
+ while (Date.now() < deadline && (await textOf(page, selector)) === shown)
212
+ await sleep(250);
213
+ }
197
214
  function sleep(ms) {
198
215
  return new Promise((resolve) => setTimeout(resolve, ms));
199
216
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dappress",
3
- "version": "0.5.1",
3
+ "version": "0.6.1",
4
4
  "description": "MetaMask automation for Cypress: load the real extension, import a test wallet, answer dapp requests with cy.* commands. Tracks the latest MetaMask release.",
5
5
  "license": "MIT",
6
6
  "author": "Benjamin Lassaut",
@@ -61,7 +61,7 @@
61
61
  "format:check": "prettier --check ."
62
62
  },
63
63
  "peerDependencies": {
64
- "cypress": ">=13.6.0"
64
+ "cypress": ">=15.10.0"
65
65
  },
66
66
  "dependencies": {
67
67
  "@scure/bip39": "^1.6.0",