dappress 0.1.1 → 0.2.0
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/README.md +10 -4
- package/package.json +1 -1
- package/src/actions.js +18 -1
- package/src/config.js +3 -0
- package/src/index.js +3 -0
- package/src/metamask.js +104 -4
- package/src/profile.js +1 -1
- package/src/support.js +9 -2
- package/types/index.d.ts +5 -0
- package/types/support.d.ts +6 -0
package/README.md
CHANGED
|
@@ -82,7 +82,7 @@ env:
|
|
|
82
82
|
DAPPRESS_SEED_PHRASE: ${{ secrets.DAPPRESS_SEED_PHRASE }}
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
When neither is provided, Dappress uses the public Hardhat / Anvil development wallet.
|
|
85
|
+
When neither is provided, Dappress uses the public Hardhat / Anvil development wallet. Give your test suite a seed phrase of its own: that one is shared with everybody.
|
|
86
86
|
|
|
87
87
|
Add the command types to `tsconfig.json`:
|
|
88
88
|
|
|
@@ -134,6 +134,9 @@ The wallet is imported once, before the first test of each spec. Each command wa
|
|
|
134
134
|
| `cy.rejectSwitchNetwork()` | Denies that permission |
|
|
135
135
|
| `cy.approveAddToken()` | Adds the token requested by `wallet_watchAsset` |
|
|
136
136
|
| `cy.rejectAddToken()` | Rejects the token |
|
|
137
|
+
| `cy.addAccount()` | Adds an account to the wallet and selects it. Yields its name, such as `Account 2`. |
|
|
138
|
+
| `cy.importAccount(privateKey)` | Imports an account from its private key and selects it. Yields its name. The key stays out of the command log. |
|
|
139
|
+
| `cy.switchAccount(name)` | Selects an account of the wallet by its name |
|
|
137
140
|
| `cy.useNetwork(network?)` | Moves the dapp onto a network, adding it to MetaMask when needed. Defaults to the network of the wallet setup. |
|
|
138
141
|
| `cy.getAccountAddress()` | Yields the address the dapp is connected with |
|
|
139
142
|
| `cy.setupMetaMask()` | Imports the wallet, or unlocks it. Called automatically before each spec. |
|
|
@@ -153,19 +156,20 @@ Settings normally live in `cypress/wallet.setup.ts`. Secrets go in `cypress.env.
|
|
|
153
156
|
| `seedPhrase` | `DAPPRESS_SEED_PHRASE` | `test test test test test test test test test test test junk`, the Hardhat / Anvil development wallet. Its first account is `0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266`. |
|
|
154
157
|
| `password` | `DAPPRESS_PASSWORD` | `Tester@1234`. It only protects the throwaway browser profile Cypress creates for each run. |
|
|
155
158
|
| `network` | | None. The dapp stays on the network MetaMask starts on, Ethereum mainnet. |
|
|
159
|
+
| `backupAndSync` | | `false`. Dappress turns off MetaMask's backup and sync while importing the wallet, so that an account a test adds is not restored by the next import of the same seed phrase. With `true`, MetaMask keeps saving and restoring the accounts and contacts of that phrase. |
|
|
156
160
|
| `autoSetup` | | `true`. Dappress imports or unlocks the wallet before the first test of each spec. Set to `false` to call `cy.setupMetaMask()` yourself. |
|
|
157
161
|
| `cache` | | `false`. The wallet is imported in every run, about fifteen seconds. With `true`, it is imported once, in a browser Dappress opens before the run, and the resulting profile is reused by later runs, which then start by unlocking the wallet. |
|
|
158
162
|
| `timeout` | | `20000` ms. The time allowed for MetaMask to display a request before a command fails. |
|
|
159
163
|
|
|
160
164
|
### Security
|
|
161
165
|
|
|
162
|
-
Use a wallet dedicated to testing, funded on test networks only. The default seed phrase is public. The seed phrase and password remain on the Node.js side: they are never exposed to the browser nor written to the Cypress command log. The wallet setup file contains no secret and can be committed.
|
|
166
|
+
Use a wallet dedicated to testing, funded on test networks only. The default seed phrase is public: anyone can spend from it, and its accounts can carry activity nobody controls. It is fine for a first run, not for a test suite you rely on. The seed phrase and password remain on the Node.js side: they are never exposed to the browser nor written to the Cypress command log. The wallet setup file contains no secret and can be committed.
|
|
163
167
|
|
|
164
168
|
With `cache: true`, the profile under `~/.cache/dappress/profiles` holds the wallet's vault, encrypted by MetaMask with the password. Treat that directory like the seed phrase: keep it on the machine, and do not store it in a CI cache that other people or workflows can restore.
|
|
165
169
|
|
|
166
170
|
## Conformance suite
|
|
167
171
|
|
|
168
|
-
The suite runs one test per command against [MetaMask's test dapp](https://metamask.github.io/test-dapp/), with a local [Anvil](https://getfoundry.sh) node
|
|
172
|
+
The suite runs one test per command against [MetaMask's test dapp](https://metamask.github.io/test-dapp/). Each run makes a wallet nobody has used, with Foundry's `cast`, and starts a local [Anvil](https://getfoundry.sh) node that funds it. It requires Chrome for Testing and Foundry.
|
|
169
173
|
|
|
170
174
|
```bash
|
|
171
175
|
npm run conformance # default MetaMask version
|
|
@@ -209,10 +213,12 @@ Selectors are MetaMask's `data-testid` attributes, each with the button's Englis
|
|
|
209
213
|
|
|
210
214
|
- **Cypress exits immediately with `MODULE_NOT_FOUND`.** The terminal sets `ELECTRON_RUN_AS_NODE=1`, as some IDEs do. Run `env -u ELECTRON_RUN_AS_NODE npx cypress run …`.
|
|
211
215
|
- **"MetaMask showed no confirmation".** The dapp sent no request, or sent it on a network whose RPC endpoint is unreachable.
|
|
216
|
+
- **Adding or importing an account never finishes.** `chromeWebSecurity: false` is set in the Cypress config. MetaMask then cannot start its snaps, which its account screens wait for. Leave Chrome's web security on, the Cypress default.
|
|
217
|
+
- **The wallet shows accounts you did not create.** The seed phrase is used elsewhere, and MetaMask restored what its cloud holds for it. This happens with the public default phrase. Use a phrase made for your tests.
|
|
212
218
|
|
|
213
219
|
## Status
|
|
214
220
|
|
|
215
|
-
Verified with MetaMask 13.49.0 and 13.50.0, Cypress 16 and Chrome for Testing 154
|
|
221
|
+
Verified with MetaMask 13.49.0 and 13.50.0, Cypress 16 and Chrome for Testing 154, in headed mode, on macOS and on GitHub's Linux runners. Headless execution is not validated yet.
|
|
216
222
|
|
|
217
223
|
## License
|
|
218
224
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dappress",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
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",
|
package/src/actions.js
CHANGED
|
@@ -27,6 +27,17 @@ function createTasks(options) {
|
|
|
27
27
|
return state;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/** A task that drives the wallet's own screens, from its full-screen page. */
|
|
31
|
+
const onHomePage = (flow) => async (browser, argument) => {
|
|
32
|
+
const home = await getHomePage(browser, await metamaskId(browser));
|
|
33
|
+
try {
|
|
34
|
+
await home.bringToFront();
|
|
35
|
+
return await flow(home, argument);
|
|
36
|
+
} finally {
|
|
37
|
+
await home.close();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
30
41
|
/** Approve the prompt a network change raised: "Add network" or the permission to switch. */
|
|
31
42
|
async function approveNetworkChange(browser) {
|
|
32
43
|
const page = await getConfirmationPage(browser, await metamaskId(browser), options.timeout);
|
|
@@ -39,7 +50,13 @@ function createTasks(options) {
|
|
|
39
50
|
await metamask.decide(decision, page, options.timeout);
|
|
40
51
|
};
|
|
41
52
|
|
|
42
|
-
const actions = {
|
|
53
|
+
const actions = {
|
|
54
|
+
setupWallet,
|
|
55
|
+
approveNetworkChange,
|
|
56
|
+
addAccount: onHomePage(metamask.addAccount),
|
|
57
|
+
switchAccount: onHomePage(metamask.switchAccount),
|
|
58
|
+
importAccount: onHomePage(metamask.importAccount),
|
|
59
|
+
};
|
|
43
60
|
for (const decision of Object.keys(metamask.decisions)) actions[decision] = decide(decision);
|
|
44
61
|
|
|
45
62
|
// cy.task() needs a value back: null when the action has nothing to say
|
package/src/config.js
CHANGED
|
@@ -9,6 +9,9 @@ const DEFAULTS = {
|
|
|
9
9
|
password: 'Tester@1234',
|
|
10
10
|
// The network cy.connectToDapp() moves the dapp onto, as a wallet_addEthereumChain parameter; none by default
|
|
11
11
|
network: null,
|
|
12
|
+
// MetaMask's backup and sync saves the accounts and contacts of a seed phrase
|
|
13
|
+
// and restores them on other installs. Off, a test's accounts don't come back.
|
|
14
|
+
backupAndSync: false,
|
|
12
15
|
// Run cy.setupMetaMask() automatically before the first test of each spec
|
|
13
16
|
autoSetup: true,
|
|
14
17
|
// Import the wallet once and reuse the profile across runs (keeps the vault under cacheDir)
|
package/src/index.js
CHANGED
|
@@ -16,6 +16,9 @@ const { createTasks } = require('./actions');
|
|
|
16
16
|
*/
|
|
17
17
|
function configureDappress(on, config, userOptions = {}) {
|
|
18
18
|
const options = resolveOptions(userOptions, config);
|
|
19
|
+
if (config.chromeWebSecurity === false) {
|
|
20
|
+
console.warn('[dappress] chromeWebSecurity is off: MetaMask cannot start its snaps, so adding or importing an account will hang');
|
|
21
|
+
}
|
|
19
22
|
|
|
20
23
|
// Build the wallet profile before the run, out of the time Cypress allows a browser to come up
|
|
21
24
|
on('before:run', async ({ browser }) => {
|
package/src/metamask.js
CHANGED
|
@@ -30,6 +30,13 @@ const selectors = {
|
|
|
30
30
|
metricsContinue: [testId('metametrics-i-agree'), buttonText('Continue')],
|
|
31
31
|
downloadAppContinue: testId('download-app-continue'),
|
|
32
32
|
done: [testId('onboarding-complete-done'), buttonText('Done')],
|
|
33
|
+
// "Manage default settings", offered next to "Done"
|
|
34
|
+
manageDefaultSettings: testId('manage-default-settings'),
|
|
35
|
+
// The first category, "General": its testid carries the translated label
|
|
36
|
+
generalSettings: 'xpath/(.//*[starts-with(@data-testid, "category-item-")])[1]',
|
|
37
|
+
backupAndSyncToggle: testId('backup-and-sync-toggle-button'),
|
|
38
|
+
categoryBack: testId('category-back-button'),
|
|
39
|
+
settingsBack: testId('privacy-settings-back-button'),
|
|
33
40
|
},
|
|
34
41
|
unlock: {
|
|
35
42
|
password: [testId('unlock-password'), passwordInput(1)],
|
|
@@ -37,6 +44,18 @@ const selectors = {
|
|
|
37
44
|
},
|
|
38
45
|
home: {
|
|
39
46
|
header: testId('parent-selector-header-navbar'),
|
|
47
|
+
accountMenu: testId('account-menu-icon'),
|
|
48
|
+
},
|
|
49
|
+
// The account list, opened from the home header
|
|
50
|
+
accounts: {
|
|
51
|
+
name: '[data-testid^="multichain-account-cell-name-"]',
|
|
52
|
+
cell: (name) => `xpath/.//*[contains(@class, "multichain-account-cell")][.//*[@data-testid="multichain-account-cell-name-${name}"]]`,
|
|
53
|
+
add: 'xpath/(.//*[@data-testid="add-multichain-account-button"])[1]',
|
|
54
|
+
addWallet: testId('account-list-add-wallet-button'),
|
|
55
|
+
importAccount: testId('choose-wallet-type-import-account'),
|
|
56
|
+
privateKey: '#private-key-box',
|
|
57
|
+
importConfirm: [testId('import-account-confirm-button'), buttonText('Import')],
|
|
58
|
+
back: testId('account-list-page-back-button'),
|
|
40
59
|
},
|
|
41
60
|
// "Connect this website with MetaMask"
|
|
42
61
|
connect: {
|
|
@@ -98,7 +117,7 @@ async function walletState(page) {
|
|
|
98
117
|
}
|
|
99
118
|
|
|
100
119
|
/** Import a wallet from its seed phrase on a fresh MetaMask install. */
|
|
101
|
-
async function onboard(page, { seedPhrase, password }) {
|
|
120
|
+
async function onboard(page, { seedPhrase, password, backupAndSync }) {
|
|
102
121
|
const s = selectors.onboarding;
|
|
103
122
|
await click(page, s.importWallet, { timeout: 30000 });
|
|
104
123
|
await click(page, s.importWithSrp);
|
|
@@ -111,7 +130,7 @@ async function onboard(page, { seedPhrase, password }) {
|
|
|
111
130
|
await click(page, s.passwordTerms);
|
|
112
131
|
await clickWhenEnabled(page, s.passwordSubmit);
|
|
113
132
|
|
|
114
|
-
await reachHome(page, { password });
|
|
133
|
+
await reachHome(page, { password, backupAndSync });
|
|
115
134
|
}
|
|
116
135
|
|
|
117
136
|
// MetaMask's sandbox (LavaMoat) blocks a scripted paste, so the phrase is
|
|
@@ -139,9 +158,10 @@ async function unlock(page, { password }) {
|
|
|
139
158
|
* "Done", MetaMask takes a moment to record the onboarding as complete and
|
|
140
159
|
* redirects to it until then, so the home page is reloaded.
|
|
141
160
|
*/
|
|
142
|
-
async function reachHome(page, { password }) {
|
|
161
|
+
async function reachHome(page, { password, backupAndSync }) {
|
|
143
162
|
const s = selectors.onboarding;
|
|
144
163
|
const deadline = Date.now() + 90000;
|
|
164
|
+
let syncTurnedOff = false;
|
|
145
165
|
while (Date.now() < deadline) {
|
|
146
166
|
if (await isVisible(page, selectors.home.header, 500)) return;
|
|
147
167
|
if (await isVisible(page, s.passkeyMaybeLater, 500)) await click(page, s.passkeyMaybeLater);
|
|
@@ -150,6 +170,10 @@ async function reachHome(page, { password }) {
|
|
|
150
170
|
await click(page, s.metricsContinue);
|
|
151
171
|
}
|
|
152
172
|
if (await isVisible(page, s.downloadAppContinue, 500)) await click(page, s.downloadAppContinue);
|
|
173
|
+
if (backupAndSync === false && !syncTurnedOff && (await isVisible(page, s.manageDefaultSettings, 500))) {
|
|
174
|
+
await turnOffBackupAndSync(page);
|
|
175
|
+
syncTurnedOff = true;
|
|
176
|
+
}
|
|
153
177
|
if (await isVisible(page, s.done, 500)) {
|
|
154
178
|
await click(page, s.done);
|
|
155
179
|
await sleep(1000);
|
|
@@ -163,6 +187,19 @@ async function reachHome(page, { password }) {
|
|
|
163
187
|
throw await failure(page, 'MetaMask did not show the wallet');
|
|
164
188
|
}
|
|
165
189
|
|
|
190
|
+
// Backup and sync restores, for a seed phrase, the accounts and contacts saved
|
|
191
|
+
// from other installs. Off, every import starts from the same state.
|
|
192
|
+
async function turnOffBackupAndSync(page) {
|
|
193
|
+
const s = selectors.onboarding;
|
|
194
|
+
await click(page, s.manageDefaultSettings);
|
|
195
|
+
await click(page, s.generalSettings);
|
|
196
|
+
const toggle = await waitFor(page, s.backupAndSyncToggle);
|
|
197
|
+
const on = await toggle.evaluate((el) => el.closest('.toggle-button')?.classList.contains('toggle-button--on') ?? el.className.includes('--on'));
|
|
198
|
+
if (on) await toggle.click();
|
|
199
|
+
await click(page, s.categoryBack);
|
|
200
|
+
await click(page, s.settingsBack);
|
|
201
|
+
}
|
|
202
|
+
|
|
166
203
|
async function optOutOfMetrics(page) {
|
|
167
204
|
const checkbox = await waitFor(page, selectors.onboarding.metricsCheckbox);
|
|
168
205
|
const checked = await checkbox.evaluate((el) => el.getAttribute('data-checked') === 'true');
|
|
@@ -177,6 +214,69 @@ async function reloadHome(page) {
|
|
|
177
214
|
await page.goto(homeUrl);
|
|
178
215
|
}
|
|
179
216
|
|
|
217
|
+
/** Add an account to the wallet and select it. Yields its name, "Account N". */
|
|
218
|
+
async function addAccount(page) {
|
|
219
|
+
await click(page, selectors.home.accountMenu);
|
|
220
|
+
const before = await accountNames(page);
|
|
221
|
+
await clickWhenEnabled(page, selectors.accounts.add, { timeout: 30000 });
|
|
222
|
+
const deadline = Date.now() + 30000;
|
|
223
|
+
while (Date.now() < deadline) {
|
|
224
|
+
const [added] = (await accountNames(page)).filter((name) => !before.includes(name));
|
|
225
|
+
if (added) {
|
|
226
|
+
await selectAccount(page, added);
|
|
227
|
+
return added;
|
|
228
|
+
}
|
|
229
|
+
await sleep(250);
|
|
230
|
+
}
|
|
231
|
+
throw await failure(page, 'MetaMask added no account');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async function accountNames(page) {
|
|
235
|
+
await waitFor(page, selectors.accounts.name);
|
|
236
|
+
return page.$$eval(selectors.accounts.name, (cells) => cells.map((cell) => cell.textContent.trim()));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** Make `name` the selected account of the wallet. */
|
|
240
|
+
async function switchAccount(page, name) {
|
|
241
|
+
await click(page, selectors.home.accountMenu);
|
|
242
|
+
await selectAccount(page, name);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Picking an account closes the list and shows it in the home header
|
|
246
|
+
async function selectAccount(page, name) {
|
|
247
|
+
await click(page, selectors.accounts.cell(name));
|
|
248
|
+
const deadline = Date.now() + 15000;
|
|
249
|
+
while (Date.now() < deadline) {
|
|
250
|
+
if ((await selectedAccount(page)) === name) return;
|
|
251
|
+
await sleep(250);
|
|
252
|
+
}
|
|
253
|
+
throw await failure(page, `MetaMask did not select "${name}"`);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async function selectedAccount(page) {
|
|
257
|
+
const menu = await page.$(selectors.home.accountMenu);
|
|
258
|
+
return menu ? menu.evaluate((el) => el.textContent.trim()) : null;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** Import an account from its private key and select it. Yields its name. */
|
|
262
|
+
async function importAccount(page, privateKey) {
|
|
263
|
+
await waitFor(page, selectors.home.accountMenu);
|
|
264
|
+
const before = await selectedAccount(page);
|
|
265
|
+
// Straight to the form the account list's "Add wallet" menu leads to
|
|
266
|
+
const homeUrl = page.url().split('#')[0];
|
|
267
|
+
await page.goto('about:blank');
|
|
268
|
+
await page.goto(`${homeUrl}#/add-wallet-page`);
|
|
269
|
+
await fill(page, selectors.accounts.privateKey, privateKey, { timeout: 30000 });
|
|
270
|
+
await clickWhenEnabled(page, selectors.accounts.importConfirm);
|
|
271
|
+
const deadline = Date.now() + 30000;
|
|
272
|
+
while (Date.now() < deadline) {
|
|
273
|
+
const selected = await selectedAccount(page);
|
|
274
|
+
if (selected && selected !== before) return selected;
|
|
275
|
+
await sleep(250);
|
|
276
|
+
}
|
|
277
|
+
throw await failure(page, 'MetaMask did not import the account');
|
|
278
|
+
}
|
|
279
|
+
|
|
180
280
|
/** Press the button of `decision` on the confirmation shown on `page`. */
|
|
181
281
|
function decide(decision, page, timeout) {
|
|
182
282
|
return pressAndWaitForDismissal(page, decisions[decision], timeout);
|
|
@@ -246,4 +346,4 @@ async function dismissModal(page) {
|
|
|
246
346
|
await dispatchClick(page, selectors.modal.lastButton);
|
|
247
347
|
}
|
|
248
348
|
|
|
249
|
-
module.exports = { decisions, walletState, onboard, unlock, decide, approveNetworkChange };
|
|
349
|
+
module.exports = { decisions, walletState, onboard, unlock, addAccount, switchAccount, importAccount, decide, approveNetworkChange };
|
package/src/profile.js
CHANGED
|
@@ -16,7 +16,7 @@ const builds = new Map();
|
|
|
16
16
|
|
|
17
17
|
/** The cached profile for these options, built on first use. */
|
|
18
18
|
function prepareProfile({ browserPath, extensionDir, options }) {
|
|
19
|
-
const key = crypto.createHash('sha256').update([options.metamaskVersion, options.seedPhrase, options.password].join('|')).digest('hex').slice(0, 16);
|
|
19
|
+
const key = crypto.createHash('sha256').update([options.metamaskVersion, options.seedPhrase, options.password, options.backupAndSync].join('|')).digest('hex').slice(0, 16);
|
|
20
20
|
if (!builds.has(key)) builds.set(key, buildProfile(path.join(options.cacheDir, 'profiles', key), { browserPath, extensionDir, options }));
|
|
21
21
|
return builds.get(key);
|
|
22
22
|
}
|
package/src/support.js
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
const options = Cypress.expose('dappress') || {};
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
// `shown` is what the command log displays for the argument, if anything
|
|
11
|
+
function metamask(action, argument = null, shown = '') {
|
|
12
|
+
Cypress.log({ name: 'metamask', message: `${action} ${shown}`.trim() });
|
|
12
13
|
return cy.task(`dappress:${action}`, argument, { log: false });
|
|
13
14
|
}
|
|
14
15
|
|
|
@@ -29,6 +30,12 @@ Cypress.Commands.add('rejectTransaction', () => metamask('rejectTransaction'));
|
|
|
29
30
|
Cypress.Commands.add('approveAddToken', () => metamask('approveAddToken'));
|
|
30
31
|
Cypress.Commands.add('rejectAddToken', () => metamask('rejectAddToken'));
|
|
31
32
|
|
|
33
|
+
// The wallet's own accounts. A new or imported account becomes the selected
|
|
34
|
+
// one; the dapp sees it once it connects with it.
|
|
35
|
+
Cypress.Commands.add('addAccount', () => metamask('addAccount'));
|
|
36
|
+
Cypress.Commands.add('switchAccount', (name) => metamask('switchAccount', name, name));
|
|
37
|
+
// The private key is kept out of the command log
|
|
38
|
+
Cypress.Commands.add('importAccount', (privateKey) => metamask('importAccount', privateKey));
|
|
32
39
|
|
|
33
40
|
// Connect, then move the dapp onto the network from the wallet setup, if there is one
|
|
34
41
|
Cypress.Commands.add('connectToDapp', () => {
|
package/types/index.d.ts
CHANGED
|
@@ -23,6 +23,11 @@ export interface DappressOptions extends WalletSetup {
|
|
|
23
23
|
password?: string;
|
|
24
24
|
/** MetaMask release to load, downloaded from GitHub on first run. */
|
|
25
25
|
metamaskVersion?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Keep MetaMask's backup and sync on. It saves the accounts and contacts of a
|
|
28
|
+
* seed phrase and restores them on other installs. Default: false.
|
|
29
|
+
*/
|
|
30
|
+
backupAndSync?: boolean;
|
|
26
31
|
/** Run cy.setupMetaMask() before the first test of each spec. Default: true. */
|
|
27
32
|
autoSetup?: boolean;
|
|
28
33
|
/** Import the wallet once and reuse the profile across runs. Keeps the vault under cacheDir. Default: false. */
|
package/types/support.d.ts
CHANGED
|
@@ -27,6 +27,12 @@ declare global {
|
|
|
27
27
|
/** Answers wallet_watchAsset ("Add suggested tokens"). */
|
|
28
28
|
approveAddToken(): Chainable<void>;
|
|
29
29
|
rejectAddToken(): Chainable<void>;
|
|
30
|
+
/** Adds an account to the wallet and selects it. Yields its name, "Account N". */
|
|
31
|
+
addAccount(): Chainable<string>;
|
|
32
|
+
/** Selects an account of the wallet by its name. */
|
|
33
|
+
switchAccount(name: string): Chainable<void>;
|
|
34
|
+
/** Imports an account from its private key and selects it. Yields its name. */
|
|
35
|
+
importAccount(privateKey: string): Chainable<string>;
|
|
30
36
|
/** Moves the dapp onto a network, adding it to MetaMask if needed. Defaults to the wallet setup's network. Yields the chain id. */
|
|
31
37
|
useNetwork(network?: Network): Chainable<string>;
|
|
32
38
|
/** The address the dapp is connected with. */
|