@marigoldlabs/web3-tester 0.1.1 → 0.4.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/.env.example +26 -17
- package/LICENSE +21 -0
- package/README.md +167 -41
- package/dist/anvil.d.ts +90 -2
- package/dist/anvil.d.ts.map +1 -1
- package/dist/anvil.js +215 -13
- package/dist/anvil.js.map +1 -1
- package/dist/contracts/test-erc20.d.ts +227 -0
- package/dist/contracts/test-erc20.d.ts.map +1 -0
- package/dist/contracts/test-erc20.js +8 -0
- package/dist/contracts/test-erc20.js.map +1 -0
- package/dist/erc20.d.ts +38 -0
- package/dist/erc20.d.ts.map +1 -0
- package/dist/erc20.js +229 -0
- package/dist/erc20.js.map +1 -0
- package/dist/fixtures.d.ts +44 -2
- package/dist/fixtures.d.ts.map +1 -1
- package/dist/fixtures.js +162 -17
- package/dist/fixtures.js.map +1 -1
- package/dist/index.d.ts +17 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/injected-provider.d.ts.map +1 -1
- package/dist/injected-provider.js +142 -79
- package/dist/injected-provider.js.map +1 -1
- package/dist/live-fixtures.d.ts +32 -3
- package/dist/live-fixtures.d.ts.map +1 -1
- package/dist/live-fixtures.js +64 -27
- package/dist/live-fixtures.js.map +1 -1
- package/dist/matchers.d.ts +90 -0
- package/dist/matchers.d.ts.map +1 -0
- package/dist/matchers.js +268 -0
- package/dist/matchers.js.map +1 -0
- package/dist/metamask-extension.d.ts +34 -0
- package/dist/metamask-extension.d.ts.map +1 -0
- package/dist/metamask-extension.js +97 -0
- package/dist/metamask-extension.js.map +1 -0
- package/dist/mock-wallet-controller.d.ts +205 -3
- package/dist/mock-wallet-controller.d.ts.map +1 -1
- package/dist/mock-wallet-controller.js +843 -46
- package/dist/mock-wallet-controller.js.map +1 -1
- package/dist/private-key-rpc-client.d.ts +1730 -0
- package/dist/private-key-rpc-client.d.ts.map +1 -1
- package/dist/private-key-rpc-client.js +105 -12
- package/dist/private-key-rpc-client.js.map +1 -1
- package/dist/real-wallet-cache.d.ts +65 -0
- package/dist/real-wallet-cache.d.ts.map +1 -0
- package/dist/real-wallet-cache.js +245 -0
- package/dist/real-wallet-cache.js.map +1 -0
- package/dist/real-wallet-fixtures.d.ts +52 -0
- package/dist/real-wallet-fixtures.d.ts.map +1 -0
- package/dist/real-wallet-fixtures.js +73 -0
- package/dist/real-wallet-fixtures.js.map +1 -0
- package/dist/real-wallet-setup.d.ts +4 -0
- package/dist/real-wallet-setup.d.ts.map +1 -0
- package/dist/real-wallet-setup.js +5 -0
- package/dist/real-wallet-setup.js.map +1 -0
- package/dist/real-wallet.d.ts +124 -15
- package/dist/real-wallet.d.ts.map +1 -1
- package/dist/real-wallet.js +1682 -138
- package/dist/real-wallet.js.map +1 -1
- package/dist/transactions.d.ts +118 -0
- package/dist/transactions.d.ts.map +1 -0
- package/dist/transactions.js +207 -0
- package/dist/transactions.js.map +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/walletconnect.d.ts +206 -0
- package/dist/walletconnect.d.ts.map +1 -0
- package/dist/walletconnect.js +359 -0
- package/dist/walletconnect.js.map +1 -0
- package/examples/live-sepolia.spec.ts +21 -2
- package/examples/local-wallet.spec.ts +1 -1
- package/package.json +62 -6
- package/docs/API.md +0 -223
- package/docs/ARCHITECTURE.md +0 -81
- package/docs/CONSUMING_FROM_FJORD.md +0 -123
- package/docs/FJORD_LIVE_QA.md +0 -87
- package/docs/RELEASE_CHECKLIST.md +0 -55
package/package.json
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marigoldlabs/web3-tester",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"private": false,
|
|
3
|
+
"version": "0.4.1",
|
|
5
4
|
"type": "module",
|
|
6
5
|
"description": "A Playwright, Anvil, and Viem based Web3 E2E harness with an injected programmable wallet provider.",
|
|
7
|
-
"license": "
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"playwright",
|
|
9
|
+
"anvil",
|
|
10
|
+
"viem",
|
|
11
|
+
"metamask",
|
|
12
|
+
"walletconnect",
|
|
13
|
+
"web3",
|
|
14
|
+
"ethereum",
|
|
15
|
+
"e2e",
|
|
16
|
+
"testing",
|
|
17
|
+
"wallet",
|
|
18
|
+
"eip-1193",
|
|
19
|
+
"dapp"
|
|
20
|
+
],
|
|
8
21
|
"repository": {
|
|
9
22
|
"type": "git",
|
|
10
23
|
"url": "git+https://github.com/AndyMarigoldLabs/web3-tester.git"
|
|
@@ -24,6 +37,22 @@
|
|
|
24
37
|
"types": "./dist/anvil.d.ts",
|
|
25
38
|
"import": "./dist/anvil.js"
|
|
26
39
|
},
|
|
40
|
+
"./erc20": {
|
|
41
|
+
"types": "./dist/erc20.d.ts",
|
|
42
|
+
"import": "./dist/erc20.js"
|
|
43
|
+
},
|
|
44
|
+
"./matchers": {
|
|
45
|
+
"types": "./dist/matchers.d.ts",
|
|
46
|
+
"import": "./dist/matchers.js"
|
|
47
|
+
},
|
|
48
|
+
"./walletconnect": {
|
|
49
|
+
"types": "./dist/walletconnect.d.ts",
|
|
50
|
+
"import": "./dist/walletconnect.js"
|
|
51
|
+
},
|
|
52
|
+
"./transactions": {
|
|
53
|
+
"types": "./dist/transactions.d.ts",
|
|
54
|
+
"import": "./dist/transactions.js"
|
|
55
|
+
},
|
|
27
56
|
"./fixtures": {
|
|
28
57
|
"types": "./dist/fixtures.d.ts",
|
|
29
58
|
"import": "./dist/fixtures.js"
|
|
@@ -43,30 +72,57 @@
|
|
|
43
72
|
"./real-wallet": {
|
|
44
73
|
"types": "./dist/real-wallet.d.ts",
|
|
45
74
|
"import": "./dist/real-wallet.js"
|
|
46
|
-
}
|
|
75
|
+
},
|
|
76
|
+
"./real-wallet-fixtures": {
|
|
77
|
+
"types": "./dist/real-wallet-fixtures.d.ts",
|
|
78
|
+
"import": "./dist/real-wallet-fixtures.js"
|
|
79
|
+
},
|
|
80
|
+
"./metamask-extension": {
|
|
81
|
+
"types": "./dist/metamask-extension.d.ts",
|
|
82
|
+
"import": "./dist/metamask-extension.js"
|
|
83
|
+
},
|
|
84
|
+
"./package.json": "./package.json"
|
|
85
|
+
},
|
|
86
|
+
"engines": {
|
|
87
|
+
"node": ">=20.0.0"
|
|
47
88
|
},
|
|
48
89
|
"files": [
|
|
49
90
|
"dist",
|
|
50
|
-
"docs",
|
|
51
91
|
"examples",
|
|
52
92
|
"README.md",
|
|
93
|
+
"LICENSE",
|
|
53
94
|
".env.example"
|
|
54
95
|
],
|
|
55
96
|
"scripts": {
|
|
56
97
|
"build": "tsc -p tsconfig.build.json",
|
|
98
|
+
"build:contracts": "node scripts/build-contracts.mjs",
|
|
57
99
|
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
58
100
|
"prepare": "npm run build",
|
|
59
|
-
"test": "playwright test",
|
|
101
|
+
"test": "playwright test --project=library",
|
|
102
|
+
"test:fjord": "playwright test --project=fjord",
|
|
103
|
+
"test:all": "playwright test",
|
|
104
|
+
"smoke:real-wallet": "node scripts/real-wallet-smoke.mjs",
|
|
60
105
|
"typecheck": "tsc --noEmit",
|
|
61
106
|
"verify": "npm run typecheck && npm run build && npm test"
|
|
62
107
|
},
|
|
63
108
|
"peerDependencies": {
|
|
64
109
|
"@playwright/test": ">=1.56.0",
|
|
110
|
+
"@walletconnect/sign-client": ">=2.17 <3",
|
|
111
|
+
"@walletconnect/types": ">=2.17 <3",
|
|
112
|
+
"@walletconnect/utils": ">=2.17 <3",
|
|
65
113
|
"viem": ">=2.39.3 <3"
|
|
66
114
|
},
|
|
115
|
+
"peerDependenciesMeta": {
|
|
116
|
+
"@walletconnect/sign-client": { "optional": true },
|
|
117
|
+
"@walletconnect/types": { "optional": true },
|
|
118
|
+
"@walletconnect/utils": { "optional": true }
|
|
119
|
+
},
|
|
67
120
|
"devDependencies": {
|
|
68
121
|
"@playwright/test": "^1.56.1",
|
|
69
122
|
"@types/node": "^24.10.1",
|
|
123
|
+
"@walletconnect/sign-client": "^2.23.9",
|
|
124
|
+
"@walletconnect/types": "^2.23.9",
|
|
125
|
+
"@walletconnect/utils": "^2.23.9",
|
|
70
126
|
"typescript": "^5.9.3",
|
|
71
127
|
"viem": "^2.52.0"
|
|
72
128
|
}
|
package/docs/API.md
DELETED
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
# API Reference
|
|
2
|
-
|
|
3
|
-
This package exposes two Playwright fixture families and one real-wallet adapter:
|
|
4
|
-
|
|
5
|
-
- `fixtures`: local deterministic Anvil tests.
|
|
6
|
-
- `live-fixtures`: live Sepolia tests that sign with a runtime-only private key.
|
|
7
|
-
- `real-wallet`: persistent Chromium and MetaMask automation for fully in-UI Web3 tests.
|
|
8
|
-
|
|
9
|
-
## Local Fixtures
|
|
10
|
-
|
|
11
|
-
```ts
|
|
12
|
-
import { expect, test } from '@marigoldlabs/web3-tester/fixtures';
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Fixtures:
|
|
16
|
-
|
|
17
|
-
| Fixture | Scope | Description |
|
|
18
|
-
| --- | --- | --- |
|
|
19
|
-
| `wallet` | test | `MockWalletController` injected into the page before app scripts run. |
|
|
20
|
-
| `chain` | worker | `ChainController` connected to the worker's Anvil node. |
|
|
21
|
-
| `anvil` | worker | Running `AnvilInstance`. |
|
|
22
|
-
| `walletOptions` | option | Per-test overrides for wallet identity and behavior. |
|
|
23
|
-
| `anvilOptions` | option | Worker-level Anvil runtime overrides. |
|
|
24
|
-
|
|
25
|
-
Each `wallet` test snapshots chain state before test code runs and reverts after the test finishes.
|
|
26
|
-
|
|
27
|
-
## Live Fixtures
|
|
28
|
-
|
|
29
|
-
```ts
|
|
30
|
-
import { expect, test } from '@marigoldlabs/web3-tester/live-fixtures';
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Fixtures:
|
|
34
|
-
|
|
35
|
-
| Fixture | Scope | Description |
|
|
36
|
-
| --- | --- | --- |
|
|
37
|
-
| `wallet` | test | `MockWalletController` backed by a real Sepolia private-key signer. |
|
|
38
|
-
| `liveClient` | test | `PrivateKeyRpcClient` for Sepolia RPC and transaction submission. |
|
|
39
|
-
|
|
40
|
-
Required environment:
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
FJORD_PRIVATE_KEY=<runtime-only-private-key>
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Optional:
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
SEPOLIA_RPC_URL=https://...
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Real Wallet
|
|
53
|
-
|
|
54
|
-
```ts
|
|
55
|
-
import { launchRealWallet } from '@marigoldlabs/web3-tester/real-wallet';
|
|
56
|
-
|
|
57
|
-
const session = await launchRealWallet({
|
|
58
|
-
extensionPath: process.env.FJORD_REAL_WALLET_EXTENSION_PATH as string,
|
|
59
|
-
profileDir: process.env.FJORD_REAL_WALLET_PROFILE_DIR as string,
|
|
60
|
-
expectedAddress: process.env.FJORD_REAL_WALLET_ADDRESS,
|
|
61
|
-
setup: process.env.FJORD_REAL_WALLET_PASSWORD
|
|
62
|
-
? {
|
|
63
|
-
password: process.env.FJORD_REAL_WALLET_PASSWORD,
|
|
64
|
-
seedPhrase: process.env.FJORD_REAL_WALLET_SECRET_RECOVERY_PHRASE,
|
|
65
|
-
}
|
|
66
|
-
: undefined,
|
|
67
|
-
});
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
`launchRealWallet` starts a persistent Chromium context with the configured unpacked MetaMask extension. `profileDir` can be either a dedicated Playwright user data directory or a Chrome profile directory such as `Default` or `Profile 1`; Chrome profile paths are mapped back to their user data root and launched with `--profile-directory`.
|
|
71
|
-
|
|
72
|
-
Options:
|
|
73
|
-
|
|
74
|
-
| Option | Description |
|
|
75
|
-
| --- | --- |
|
|
76
|
-
| `extensionPath` | Required path to the unpacked MetaMask extension. |
|
|
77
|
-
| `profileDir` | Required persistent Chromium user data directory, or a Chrome profile directory. |
|
|
78
|
-
| `baseURL` | Optional Playwright base URL for pages opened from the returned context. |
|
|
79
|
-
| `expectedAddress` | Optional account address assertion after unlock/import. |
|
|
80
|
-
| `extensionName` | Extension name used to resolve the extension ID. Defaults to `MetaMask`. |
|
|
81
|
-
| `headless` | Chromium headless setting. Defaults to `false` because extensions require headed Chromium in normal use. |
|
|
82
|
-
| `setup.password` | Password used to unlock MetaMask, or to import a seed phrase when onboarding is visible. |
|
|
83
|
-
| `setup.seedPhrase` | Seed phrase used only if MetaMask opens on onboarding. |
|
|
84
|
-
| `slowMo` | Optional Playwright slow-motion delay. |
|
|
85
|
-
|
|
86
|
-
Returned session methods:
|
|
87
|
-
|
|
88
|
-
| Method | Description |
|
|
89
|
-
| --- | --- |
|
|
90
|
-
| `connectToDapp(accounts?)` | Approves a dapp connection request in MetaMask. |
|
|
91
|
-
| `confirmSignature()` | Confirms a pending signature request. |
|
|
92
|
-
| `confirmTransaction(options?)` | Confirms a pending transaction request. |
|
|
93
|
-
| `approveTokenPermission(options?)` | Approves a pending ERC-20 spending permission request. |
|
|
94
|
-
| `rejectSignature()` | Rejects a pending signature request. |
|
|
95
|
-
| `rejectTransaction()` | Rejects a pending transaction request. |
|
|
96
|
-
| `getAccountAddress()` | Returns the selected MetaMask account. |
|
|
97
|
-
| `close()` | Closes the persistent browser context. |
|
|
98
|
-
|
|
99
|
-
## MockWalletController
|
|
100
|
-
|
|
101
|
-
```ts
|
|
102
|
-
const wallet = new MockWalletController(page, rpcClient, {
|
|
103
|
-
accounts: ['0x...'],
|
|
104
|
-
chainId: 31337,
|
|
105
|
-
autoApprove: true,
|
|
106
|
-
connected: true,
|
|
107
|
-
});
|
|
108
|
-
await wallet.injectMockProvider();
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
Properties:
|
|
112
|
-
|
|
113
|
-
| Property | Type | Description |
|
|
114
|
-
| --- | --- | --- |
|
|
115
|
-
| `primaryAccount` | `Address` | First exposed account. |
|
|
116
|
-
| `currentChainId` | `Hex` | Current EIP-1193 chain ID. |
|
|
117
|
-
| `providerInfo` | `WalletProviderInfo` | Primary EIP-6963 provider metadata. |
|
|
118
|
-
| `providerInfos` | `WalletProviderInfo[]` | All announced provider metadata. |
|
|
119
|
-
|
|
120
|
-
Methods:
|
|
121
|
-
|
|
122
|
-
| Method | Description |
|
|
123
|
-
| --- | --- |
|
|
124
|
-
| `injectMockProvider()` | Adds the RPC bridge and injects `window.ethereum`. |
|
|
125
|
-
| `autoApprove(enabled)` | Toggles automatic approval for future signing methods. |
|
|
126
|
-
| `simulateRejection(methods?, message?)` | Rejects the next matching request with code `4001`. |
|
|
127
|
-
| `setAccounts(accounts)` | Updates accounts and emits `accountsChanged`. |
|
|
128
|
-
| `disconnect()` | Emits `accountsChanged` and `disconnect`. |
|
|
129
|
-
| `reconnect()` | Emits `connect` and `accountsChanged`. |
|
|
130
|
-
| `switchNetwork(chainId)` | Updates chain ID and emits `chainChanged`. |
|
|
131
|
-
|
|
132
|
-
Supported wallet methods include:
|
|
133
|
-
|
|
134
|
-
- `eth_accounts`
|
|
135
|
-
- `eth_requestAccounts`
|
|
136
|
-
- `eth_chainId`
|
|
137
|
-
- `net_version`
|
|
138
|
-
- `wallet_getPermissions`
|
|
139
|
-
- `wallet_requestPermissions`
|
|
140
|
-
- `wallet_switchEthereumChain`
|
|
141
|
-
- `wallet_addEthereumChain`
|
|
142
|
-
- `wallet_watchAsset`
|
|
143
|
-
- `metamask_getProviderState`
|
|
144
|
-
- `eth_sendTransaction`
|
|
145
|
-
- `personal_sign`
|
|
146
|
-
- `eth_sign`
|
|
147
|
-
- `eth_signTypedData`
|
|
148
|
-
- `eth_signTypedData_v3`
|
|
149
|
-
- `eth_signTypedData_v4`
|
|
150
|
-
|
|
151
|
-
Unhandled methods are forwarded to the configured RPC client.
|
|
152
|
-
|
|
153
|
-
## ChainController
|
|
154
|
-
|
|
155
|
-
`ChainController` wraps a Viem Anvil test client.
|
|
156
|
-
|
|
157
|
-
| Method | Description |
|
|
158
|
-
| --- | --- |
|
|
159
|
-
| `snapshot()` | Calls `evm_snapshot`. |
|
|
160
|
-
| `revert(id)` | Calls `evm_revert`. |
|
|
161
|
-
| `accounts()` | Returns Anvil default accounts. |
|
|
162
|
-
| `request(request)` | Sends a raw JSON-RPC request. |
|
|
163
|
-
| `impersonateAccount(address)` | Starts Anvil account impersonation. |
|
|
164
|
-
| `stopImpersonatingAccount(address)` | Stops Anvil account impersonation. |
|
|
165
|
-
| `setBalance(address, value)` | Sets an account balance. |
|
|
166
|
-
| `fastForward(seconds)` | Increases time and mines one block. |
|
|
167
|
-
| `mine(blocks)` | Mines blocks. |
|
|
168
|
-
|
|
169
|
-
The underlying Viem test client is available as `chain.client` for advanced calls.
|
|
170
|
-
|
|
171
|
-
## AnvilInstance
|
|
172
|
-
|
|
173
|
-
```ts
|
|
174
|
-
const anvil = await AnvilInstance.start({
|
|
175
|
-
runtime: 'docker',
|
|
176
|
-
port: 8546,
|
|
177
|
-
chainId: 31337,
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
await anvil.stop();
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
Options:
|
|
184
|
-
|
|
185
|
-
| Option | Description |
|
|
186
|
-
| --- | --- |
|
|
187
|
-
| `runtime` | `binary` or `docker`. |
|
|
188
|
-
| `executable` | Anvil binary path for `binary` runtime. |
|
|
189
|
-
| `dockerImage` | Foundry Docker image. |
|
|
190
|
-
| `host` | Host interface. |
|
|
191
|
-
| `port` | Host RPC port. |
|
|
192
|
-
| `chainId` | Local chain ID. |
|
|
193
|
-
| `accounts` | Number of generated accounts. |
|
|
194
|
-
| `balance` | ETH balance per generated account. |
|
|
195
|
-
| `mnemonic` | Deterministic mnemonic. |
|
|
196
|
-
| `blockTime` | Optional automatic mining interval. |
|
|
197
|
-
| `forkUrl` | Optional fork RPC URL. |
|
|
198
|
-
| `timeoutMs` | Startup timeout. |
|
|
199
|
-
| `silent` | Suppress or stream Anvil logs. |
|
|
200
|
-
|
|
201
|
-
## PrivateKeyRpcClient
|
|
202
|
-
|
|
203
|
-
`PrivateKeyRpcClient` is for live-chain QA only.
|
|
204
|
-
|
|
205
|
-
```ts
|
|
206
|
-
const client = new PrivateKeyRpcClient({
|
|
207
|
-
privateKey: process.env.FJORD_PRIVATE_KEY as `0x${string}`,
|
|
208
|
-
rpcUrl: process.env.SEPOLIA_RPC_URL,
|
|
209
|
-
});
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
It supports:
|
|
213
|
-
|
|
214
|
-
- `personal_sign`
|
|
215
|
-
- `eth_sign`
|
|
216
|
-
- `eth_signTypedData_v4`
|
|
217
|
-
- `eth_sendTransaction`
|
|
218
|
-
- read-only RPC forwarding through Viem public client
|
|
219
|
-
|
|
220
|
-
It records sent transaction hashes in:
|
|
221
|
-
|
|
222
|
-
- `sentTransactions`
|
|
223
|
-
- `sentTransactionRequests`
|
package/docs/ARCHITECTURE.md
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
# Architecture
|
|
2
|
-
|
|
3
|
-
Web3 Tester replaces extension automation with a programmable provider and deterministic chain control.
|
|
4
|
-
|
|
5
|
-
## Local Test Flow
|
|
6
|
-
|
|
7
|
-
1. Playwright creates a worker.
|
|
8
|
-
2. The worker fixture starts Anvil on a unique port.
|
|
9
|
-
3. The test fixture snapshots Anvil state with `evm_snapshot`.
|
|
10
|
-
4. `MockWalletController` exposes a Playwright function bridge.
|
|
11
|
-
5. `page.addInitScript` injects `window.ethereum` before dApp scripts load.
|
|
12
|
-
6. The dApp sends EIP-1193 requests to `window.ethereum.request`.
|
|
13
|
-
7. The injected provider forwards requests through the Playwright bridge.
|
|
14
|
-
8. The Node-side controller approves, rejects, emits events, or forwards RPC to Anvil.
|
|
15
|
-
9. The fixture reverts the chain with `evm_revert`.
|
|
16
|
-
10. The worker fixture stops Anvil after worker completion.
|
|
17
|
-
|
|
18
|
-
## Why This Avoids Synpress-Style Flakiness
|
|
19
|
-
|
|
20
|
-
No browser extension is installed. There is no extension popup, no wallet UI selector, no browser-extension process boundary, and no cached wallet profile. Tests exercise the dApp's wallet integration contract directly.
|
|
21
|
-
|
|
22
|
-
## Browser Injection
|
|
23
|
-
|
|
24
|
-
The injected provider implements the wallet behavior expected by most dApps:
|
|
25
|
-
|
|
26
|
-
- `window.ethereum`
|
|
27
|
-
- `request`
|
|
28
|
-
- `send`
|
|
29
|
-
- `sendAsync`
|
|
30
|
-
- `on`
|
|
31
|
-
- `once`
|
|
32
|
-
- `removeListener`
|
|
33
|
-
- `removeAllListeners`
|
|
34
|
-
- `_metamask.isUnlocked`
|
|
35
|
-
- EIP-6963 `announceProvider`
|
|
36
|
-
|
|
37
|
-
The injected script is installed with `page.addInitScript`, so it exists before the application bundle executes. It is also evaluated immediately for pages that have already loaded.
|
|
38
|
-
|
|
39
|
-
## RPC Boundary
|
|
40
|
-
|
|
41
|
-
Browser code cannot access Node objects directly. The harness uses:
|
|
42
|
-
|
|
43
|
-
```ts
|
|
44
|
-
page.exposeFunction('__invisibleWalletRpcBridge', async (request) => {
|
|
45
|
-
return controller.handleRpcRequest(request);
|
|
46
|
-
});
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
The browser receives only a serialized success or error envelope. Provider-shaped errors are rehydrated in the browser with their original `code`, `message`, and optional `data`.
|
|
50
|
-
|
|
51
|
-
## Chain Isolation
|
|
52
|
-
|
|
53
|
-
Local tests isolate state with both process and chain controls:
|
|
54
|
-
|
|
55
|
-
- One Anvil node per Playwright worker.
|
|
56
|
-
- One chain snapshot per `wallet` test.
|
|
57
|
-
- A revert after each `wallet` test.
|
|
58
|
-
- Unique worker ports derived from `ANVIL_PORT + workerIndex`.
|
|
59
|
-
|
|
60
|
-
This prevents nonce bleeding and lets Playwright run tests in parallel.
|
|
61
|
-
|
|
62
|
-
## Live Sepolia Mode
|
|
63
|
-
|
|
64
|
-
Live mode intentionally does not use Anvil snapshots. It uses a runtime-only private key through `PrivateKeyRpcClient` and sends real Sepolia transactions only when an explicit opt-in flag is set.
|
|
65
|
-
|
|
66
|
-
Live mutation specs should always:
|
|
67
|
-
|
|
68
|
-
- Check the required opt-in env var.
|
|
69
|
-
- Use unique QA names.
|
|
70
|
-
- Record transaction hashes.
|
|
71
|
-
- Avoid committing any private key.
|
|
72
|
-
- Continue to the next doc line after a product failure.
|
|
73
|
-
|
|
74
|
-
## Package Boundaries
|
|
75
|
-
|
|
76
|
-
Reusable package code lives in `src/`. Fjord-specific tests and reports live outside the package export surface:
|
|
77
|
-
|
|
78
|
-
- Exported: `src/*`
|
|
79
|
-
- Not exported: `tests/*`, `reports/*`, `tmp/*`, `tools/*`
|
|
80
|
-
|
|
81
|
-
The `files` field in `package.json` keeps install output focused on `dist`, `docs`, `examples`, `README.md`, and `.env.example`.
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
# Consuming Web3 Tester From Fjord V4
|
|
2
|
-
|
|
3
|
-
This guide covers adding the published package to Fjord v4 as a dependency.
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install --save-dev @marigoldlabs/web3-tester
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
For a pinned dependency, use an exact package version:
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
npm install --save-dev @marigoldlabs/web3-tester@<version>
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Playwright Config
|
|
18
|
-
|
|
19
|
-
Use Fjord's existing Playwright config if it already exists. The important parts are:
|
|
20
|
-
|
|
21
|
-
```ts
|
|
22
|
-
import { defineConfig, devices } from '@playwright/test';
|
|
23
|
-
|
|
24
|
-
export default defineConfig({
|
|
25
|
-
fullyParallel: true,
|
|
26
|
-
retries: process.env.CI ? 2 : 0,
|
|
27
|
-
use: {
|
|
28
|
-
baseURL: process.env.DAPP_URL ?? 'http://localhost:3000',
|
|
29
|
-
trace: 'on-first-retry',
|
|
30
|
-
},
|
|
31
|
-
projects: [
|
|
32
|
-
{
|
|
33
|
-
name: 'chromium',
|
|
34
|
-
use: { ...devices['Desktop Chrome'] },
|
|
35
|
-
},
|
|
36
|
-
],
|
|
37
|
-
});
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Local Deterministic Tests
|
|
41
|
-
|
|
42
|
-
```ts
|
|
43
|
-
import { expect, test } from '@marigoldlabs/web3-tester/fixtures';
|
|
44
|
-
|
|
45
|
-
test('connects through the injected provider', async ({ page, wallet }) => {
|
|
46
|
-
await page.goto('/');
|
|
47
|
-
|
|
48
|
-
await page.getByRole('button', { name: /connect wallet/i }).click();
|
|
49
|
-
await page.getByText('Mock Wallet').click();
|
|
50
|
-
|
|
51
|
-
await expect(page.getByText(wallet.primaryAccount.slice(0, 6))).toBeVisible();
|
|
52
|
-
});
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Test Options
|
|
56
|
-
|
|
57
|
-
Customize provider identity for wallet selector coverage:
|
|
58
|
-
|
|
59
|
-
```ts
|
|
60
|
-
test.use({
|
|
61
|
-
walletOptions: {
|
|
62
|
-
providerInfo: { name: 'MetaMask', rdns: 'io.metamask' },
|
|
63
|
-
additionalProviders: [
|
|
64
|
-
{ name: 'Rabby', rdns: 'io.rabby' },
|
|
65
|
-
{ name: 'Rainbow', rdns: 'me.rainbow' },
|
|
66
|
-
],
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Customize Anvil:
|
|
72
|
-
|
|
73
|
-
```ts
|
|
74
|
-
test.use({
|
|
75
|
-
anvilOptions: {
|
|
76
|
-
runtime: 'docker',
|
|
77
|
-
chainId: 31337,
|
|
78
|
-
forkUrl: process.env.ANVIL_FORK_URL,
|
|
79
|
-
},
|
|
80
|
-
});
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## Live Sepolia Tests
|
|
84
|
-
|
|
85
|
-
```ts
|
|
86
|
-
import { expect, test } from '@marigoldlabs/web3-tester/live-fixtures';
|
|
87
|
-
|
|
88
|
-
test.skip(!process.env.FJORD_PRIVATE_KEY, 'FJORD_PRIVATE_KEY is required.');
|
|
89
|
-
|
|
90
|
-
test('loads the Sepolia account', async ({ page, wallet }) => {
|
|
91
|
-
await page.goto('/');
|
|
92
|
-
await expect(page.getByText(wallet.primaryAccount.slice(0, 6))).toBeVisible();
|
|
93
|
-
});
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
Run with:
|
|
97
|
-
|
|
98
|
-
```powershell
|
|
99
|
-
$env:FJORD_PRIVATE_KEY = '<runtime-only-key>'
|
|
100
|
-
$env:SEPOLIA_RPC_URL = '<optional-rpc-url>'
|
|
101
|
-
npm test
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## Mutation Gates
|
|
105
|
-
|
|
106
|
-
Use explicit flags for anything that spends funds or mutates backend state:
|
|
107
|
-
|
|
108
|
-
```powershell
|
|
109
|
-
$env:FJORD_RUN_TRANSACTIONS = 'true'
|
|
110
|
-
$env:FJORD_MUTATE_STATE = 'true'
|
|
111
|
-
$env:FJORD_PUBLISH_SALES = 'true'
|
|
112
|
-
$env:FJORD_ADMIN_MUTATE = 'true'
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
Keep destructive or expensive tests behind separate flags so normal CI remains read-only.
|
|
116
|
-
|
|
117
|
-
## CI Recommendations
|
|
118
|
-
|
|
119
|
-
- Run deterministic Anvil tests on every PR.
|
|
120
|
-
- Run live Sepolia read-only tests on a scheduled job or protected branch.
|
|
121
|
-
- Run live mutation tests manually with approval.
|
|
122
|
-
- Store `FJORD_PRIVATE_KEY` and `SEPOLIA_RPC_URL` only as CI secrets.
|
|
123
|
-
- Pin the npm dependency to an exact version once Fjord depends on it.
|
package/docs/FJORD_LIVE_QA.md
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
# Fjord V4 Live QA
|
|
2
|
-
|
|
3
|
-
The Fjord QA specs in `tests/fjord*.spec.ts` are the working executable version of the manual QA document.
|
|
4
|
-
|
|
5
|
-
Target:
|
|
6
|
-
|
|
7
|
-
```text
|
|
8
|
-
https://v4.fjordfoundry.com
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Network:
|
|
12
|
-
|
|
13
|
-
```text
|
|
14
|
-
Sepolia
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Any legacy "mainnet" wording in the manual QA doc is treated as Sepolia for this test harness.
|
|
18
|
-
|
|
19
|
-
## Test Categories
|
|
20
|
-
|
|
21
|
-
| Category | Specs | Default behavior |
|
|
22
|
-
| --- | --- | --- |
|
|
23
|
-
| Public read-only | `fjord-public`, `fjord`, public parts of other specs | Runs without private key where possible. |
|
|
24
|
-
| Live wallet read-only | `fjord-live-sepolia`, `fjord-auth-edge`, `fjord-partials-live` | Requires `FJORD_PRIVATE_KEY`. |
|
|
25
|
-
| Live transaction | `fjord-live-transaction` | Requires `FJORD_RUN_TRANSACTIONS=true`. |
|
|
26
|
-
| Live mutations | `fjord-live-mutations` | Requires `FJORD_MUTATE_STATE=true`. |
|
|
27
|
-
| Sale publishing | `fjord-live-mutations` publish branch | Requires `FJORD_PUBLISH_SALES=true`. |
|
|
28
|
-
| Admin mutations | `fjord-admin-mutations` | Requires `FJORD_ADMIN_MUTATE=true`. |
|
|
29
|
-
|
|
30
|
-
## Read-Only Run
|
|
31
|
-
|
|
32
|
-
```powershell
|
|
33
|
-
$env:FJORD_PRIVATE_KEY = '<runtime-only-key>'
|
|
34
|
-
$env:DAPP_URL = 'https://v4.fjordfoundry.com'
|
|
35
|
-
npm test -- --reporter=list tests/fjord-public.spec.ts tests/fjord-live-sepolia.spec.ts tests/fjord-auth-edge.spec.ts tests/fjord-partials-live.spec.ts
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Live Mutation Run
|
|
39
|
-
|
|
40
|
-
```powershell
|
|
41
|
-
$env:FJORD_PRIVATE_KEY = '<runtime-only-key>'
|
|
42
|
-
$env:DAPP_URL = 'https://v4.fjordfoundry.com'
|
|
43
|
-
$env:FJORD_MUTATE_STATE = 'true'
|
|
44
|
-
$env:FJORD_QA_RUN_ID = 'YYYYMMDDXX'
|
|
45
|
-
npm test -- --reporter=list tests/fjord-live-mutations.spec.ts
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Sale Publish Attempt
|
|
49
|
-
|
|
50
|
-
```powershell
|
|
51
|
-
$env:FJORD_PRIVATE_KEY = '<runtime-only-key>'
|
|
52
|
-
$env:FJORD_MUTATE_STATE = 'true'
|
|
53
|
-
$env:FJORD_PUBLISH_SALES = 'true'
|
|
54
|
-
$env:FJORD_QA_RUN_ID = 'YYYYMMDDPX'
|
|
55
|
-
npm test -- --reporter=list tests/fjord-live-mutations.spec.ts
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Admin Mutation Attempt
|
|
59
|
-
|
|
60
|
-
```powershell
|
|
61
|
-
$env:FJORD_PRIVATE_KEY = '<runtime-only-key>'
|
|
62
|
-
$env:FJORD_ADMIN_MUTATE = 'true'
|
|
63
|
-
npm test -- --reporter=list tests/fjord-admin-mutations.spec.ts
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
## Reporting Rules
|
|
67
|
-
|
|
68
|
-
- Record `PASS`, `FAIL`, `PARTIAL`, `BLOCKED`, `NOT RUN`, or `N/A` for every doc line.
|
|
69
|
-
- When a line fails, note the observable behavior and continue to the next line.
|
|
70
|
-
- Do not collapse a doc mismatch into a product failure if the live UI has moved the control.
|
|
71
|
-
- Never paste private keys into reports.
|
|
72
|
-
- Include transaction hashes and deployed QA addresses when they help debugging.
|
|
73
|
-
|
|
74
|
-
## Current Report Artifacts
|
|
75
|
-
|
|
76
|
-
- `reports/fjord-full-line-by-line-qa-2026-05-14.md`
|
|
77
|
-
- `reports/fjord-qa-results-2026-05-14.md`
|
|
78
|
-
|
|
79
|
-
## Known Findings From The 2026-05-14 Run
|
|
80
|
-
|
|
81
|
-
- ERC-20 deployment from the Fjord UI succeeded.
|
|
82
|
-
- Token supply input minted raw units rather than the expected human-token amount.
|
|
83
|
-
- Fixed-price sale draft creation reached review.
|
|
84
|
-
- The review step did not show the documented full sale summary.
|
|
85
|
-
- Publishing submitted an ERC-20 approval transaction but did not continue to pool creation.
|
|
86
|
-
- Saved QA drafts were not listed in the resume dialog.
|
|
87
|
-
- `/admin/cache` failed loading admin data with backend `401`.
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# Release Checklist
|
|
2
|
-
|
|
3
|
-
Use this before publishing a new version or pinning it inside Fjord v4.
|
|
4
|
-
|
|
5
|
-
## Required
|
|
6
|
-
|
|
7
|
-
- `npm run typecheck`
|
|
8
|
-
- `npm run build`
|
|
9
|
-
- `npm test`
|
|
10
|
-
- `rg -n "FJORD_PRIVATE_KEY\\s*=\\s*0x[0-9a-fA-F]{64}|PRIVATE_KEY=.*[0-9a-fA-F]{64}" . -g "!node_modules/**" -g "!dist/**" -g "!.npm-cache/**"`
|
|
11
|
-
- Confirm `.env` is ignored.
|
|
12
|
-
- Confirm `dist/` is generated locally but not required in source review unless the team wants committed build output.
|
|
13
|
-
|
|
14
|
-
## Dependency Consumer Check
|
|
15
|
-
|
|
16
|
-
From a clean consumer repo:
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npm install --save-dev @marigoldlabs/web3-tester@<version>
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Then import:
|
|
23
|
-
|
|
24
|
-
```ts
|
|
25
|
-
import { expect, test } from '@marigoldlabs/web3-tester/fixtures';
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Run one provider smoke test.
|
|
29
|
-
|
|
30
|
-
## Live QA Check
|
|
31
|
-
|
|
32
|
-
Run live tests only with runtime secrets:
|
|
33
|
-
|
|
34
|
-
```powershell
|
|
35
|
-
$env:FJORD_PRIVATE_KEY = '<runtime-only-key>'
|
|
36
|
-
$env:DAPP_URL = 'https://v4.fjordfoundry.com'
|
|
37
|
-
npm test -- --reporter=list tests/fjord-live-sepolia.spec.ts
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Mutation runs require explicit flags and should not be part of default CI.
|
|
41
|
-
|
|
42
|
-
## Push
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
git status --short
|
|
46
|
-
git add .
|
|
47
|
-
git commit -m "Document and package Web3 tester"
|
|
48
|
-
git push -u origin main
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Publish
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
npm publish --access public
|
|
55
|
-
```
|