Files
Jules ac76ed4f06 test(e2e): wallet extension send/swap suites on Anvil forks
* refactor(e2e): extract shared extension launcher from MetaMask fixture

Move the persistent-context + temp-profile + SW-derived extension-id
logic into launchExtensionContext (with beforeLaunch, afterClose,
extraChromeArgs, profilePrefix, viewport options) so other extensions
can reuse it. MetaMask fixture becomes a thin wrapper; behavior
unchanged for the existing Hub suite.

* feat(e2e): add congestion and balance controls to Anvil helper

Add setNextBlockBaseFee, setBlockGasLimit, disableAutoMining,
dropTransaction, setEthBalanceFor, and getEthBalance for staging
network conditions and localizing accounts on the forks.

* feat(e2e): add rpc-router and opt-in wallet test-server orchestration

Anvil only answers JSON-RPC at / while apps/api appends path suffixes
(/ethereum/mainnet/alchemy), so add a small host-side router that
strips the prefix and forwards by chain segment to the forks.

Wire wallet-send/wallet-swap Playwright projects behind the
RUN_WALLET_E2E env flag (env rather than argv: workers re-evaluate the
config without --project) with apps/api and the router as web servers,
narrow the @wallet grep so it no longer swallows the new tags, and add
setup:wallet / test:wallet-* scripts. setup:wallet passes
WXT_STATUS_API_URL explicitly because wxt build --mode development
otherwise bakes the production API URL.

* chore: add changeset

* ci: point changesets and workflow triggers at master

The main branch was renamed to master, so origin/main no longer exists:
the changeset status step failed to find the divergence point, and the
CI/E2E/Release push triggers never fired.

* feat(e2e): add wallet page objects

Onboarding (seed import), portfolio, send modal (Max fees parsing,
password step, Confirm-with-new-gas-price, success toast), and a thin
LiFi swap-drawer wrapper. Add a clickVisible helper to BasePage since
the wallet renders controls twice (desktop + hidden mobile variant).

* feat(e2e): add wallet extension fixture stack with API data seam and LiFi mock

wallet-extension.fixture provides anvilRpc with per-test
snapshot/revert isolation, the dev-built extension context, seed-import
onboarding (compliant password decoupled from WALLET_PASSWORD), and
page-object fixtures.

status-api-mocks intercepts only the Alchemy enhanced-API tRPC routes
(assets.all, assets.nativeToken, activities.page) with fork-consistent
fixtures and exposes setFeeRate for the gas-shift test; rpc.proxy and
nodes.* pass through to the real backend and fork. lifi-mock serves
every li.quest endpoint the widget/SDK call; the mocked step calldata
is a real WETH9 deposit() so the swap executes genuinely on the fork
with an exactly assertable 1:1 output.

* test(e2e): add wallet send network-condition suite

Happy path with on-chain delta assertion, slow inclusion (no state
change until mineBlock), high base fee reflected in quoted Max fees and
actually paid, and a deterministic GasShiftedError -> Confirm with new
gas price flow via a pinned fee quote bumped mid-signing. The planned
tight-gas-limit row was dropped: Anvil estimates a 21k transfer fine
under a 20k block limit, making the scenario artificial.

* test(e2e): add wallet swap suite against mocked LiFi quotes

ETH -> WETH via the exchange drawer with recorded li.quest fixtures:
happy path with exact 1:1 on-chain output assertion, slow inclusion
(widget pending until mineBlock), and high base fee (swap executes,
elevated gas provably paid). Deliberately shallow on adverse-condition
UX, which LiFi owns; the deep matrix lives in the send suite.

* ci: add wallet e2e job

Build the extension in dev mode (WXT_STATUS_API_URL pointed at the
local api), start the forks (optionally against an archive upstream
via the E2E_MAINNET_FORK_URL secret), and run the wallet-send and
wallet-swap projects under xvfb with RUN_WALLET_E2E=1. apps/api boots
with dummy secrets since chain calls hit the fork and enhanced
endpoints are seam-mocked.

* chore: add changeset

* fix(e2e): disambiguate send success toast from its aria-live announcer

Radix Toast renders a hidden screen-reader announcer that duplicates the
toast message as "Notification Transaction signed and sent", so the
substring locator intermittently resolved to two elements and tripped
Playwright strict mode in CI.

* fix(e2e): keep vault accounting consistent when seeding shares

The live WETH pre-deposit vault drained below 1 token of totalSupply, so
seeding 1e18 shares via a bare balance-slot write made the on-chain
withdraw revert InvalidState() (amount exceeds stored totalAssets, burn
exceeds totalSupply) -- the forks track the latest block, so state drift
broke the test without a code change.

fundVaultShares now bumps the vault's totalSupply and stored totalAssets
by the seeded delta. Backing slots are discovered by value match plus a
write probe (the vaults keep both values equal, so a match alone is
ambiguous) and cached per vault.

* chore: add changeset
2026-07-10 19:25:43 +09:00
..