E2E: fix brittle Anvil wallet-writes ETH test (stale selectors + parallel workers) #87
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:open_issues
agents
agent:security_audit
agent:verify
area
timecurve
arena
arena-v2
audit
block:feature_review
block:security
bug
contracts
design
devops
docs
documentation
enhancement
epic
feature
frontend
indexer
low priority
megaeth
operations
ops
performance
QA
qa checklist
referrals
removal
security
smart-contracts
tech-debt
testing
time-arena
timecurve
visual-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
code/yieldomega#87
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
bash scripts/e2e-anvil.shcan fail onfrontend/e2e/anvil-wallet-writes.spec.ts— “TimeCurve ETH route: quote, swap, and buy” — even when unrelated frontend changes are fine. Two separate problems show up in practice.Findings
1. Stale selector vs current Simple UI
The spec waits for:
TimeCurve Simple chooses pay mode (CL8Y / ETH / USDM) with toggle buttons (e.g.
.timecurve-simple__rate-paywith-btn),aria-pressed, andaria-labellike “Show price in ETH” — not<input type="radio" name="timecurve-pay-with">. So the locator can never resolve, and the test hits the 180s timeout waiting for a non-existent control.Evidence:
frontend/src/pages/TimeCurveSimplePage.tsx(rateBoardPayOptions—buttonelements per asset).2. Parallel workers vs one Anvil
With
ANVIL_E2E=1,frontend/playwright.config.tsuses multiple workers (workers: 5whenCIorANVIL_E2Eis set).scripts/e2e-anvil.shstarts one Anvil + one preview server, then runse2e/anvil-*.spec.tsacross workers in parallel.Different files (
anvil-referrals.spec.ts,anvil-wallet-writes.spec.ts, etc.) share the same chain and default mock account. Even where a file usestest.describe.configure({ mode: "serial" }), that only serializes within that file — not across files. That creates race risk (nonces, sale state, registration state) unrelated to the feature under test.Acceptance criteria
data-testidagreed in code + spec). The step that selects ETH must not depend on removedinput[name="timecurve-pay-with"]unless that markup is deliberately reintroduced.bash scripts/e2e-anvil.shcompletes green reliably with the default worker policy (either by fixing isolation, or by documenting and implementing a supported mode: e.g.--workers=1for Anvil in the script,fullyParallel: falseforanvil-*only, or global setup that serializes Anvil mutating tests).docs/testing/e2e-anvil.md(ordocs/testing/strategy.md/ Playwright config comment) briefly states why Anvil E2E concurrency is limited the chosen way, so future agents do not reintroduce parallel races.Related
frontend/playwright.config.ts(workerswhenANVIL_E2E=1).scripts/e2e-anvil.sh.mentioned in commit
7b0f37da60Implemented in
7b0f37donmain.What changed
data-testid="timecurve-simple-paywith-{cl8y,eth,usdm}"on TimeCurve Simple and Arena (same CSS, shared test ids). The spec usesgetByTestId("timecurve-simple-paywith-eth")and waits on the quoted ETH control (aria-labelQuoted ETH spend for the selected CL8Y target) and the quote field clearing the…loading state — not removedinput[name="timecurve-pay-with"]or the old “Quote: spend” copy.ANVIL_E2E=1, config usesworkers: 1andfullyParallel: falsesoe2e/anvil-*.spec.tsfiles do not race a single chain + mock account. Default CItest:e2e(no Anvil) still uses 5 workers..cursor/skills/yieldomega-guardrails/SKILL.mditem 25; play skill skills/verify-yo-e2e-anvil/SKILL.md + index in skills/README.md.Verification checklist for @brouie
bash scripts/e2e-anvil.shgreen (Foundry +frontenddeps); Playwright output shows Running N tests using 1 worker whenANVIL_E2E=1.data-testid="timecurve-simple-paywith-eth"andaria-pressedwhen selected.…once the quoter returns; Buy CHARM enables (or shows Refreshing quote… then enables per #56).npm run test:e2ein CI path (no Anvil) unchanged intent: can still use multiple workers — onlyANVIL_E2E=1forces serial.Issue left open for your sign-off.
Verified
7b0f37dagainst all 4 acceptance items. Closing.Item 1 - bash scripts/e2e-anvil.sh green with workers:1
Ran bash scripts/e2e-anvil.sh on the QA server (anvil + frontend build + Playwright). Output snippet:
Running 5 tests using 1 worker
PASS 1 [chromium] anvil-collection.spec.ts:15:3 collection page is under construction (700ms)
PASS 2 [chromium] anvil-referrals.spec.ts:26:3 connected wallet: register code, share links, copy to clipboard (1.3s)
PASS 3 [chromium] anvil-timecurve.spec.ts:21:3 Arena TimeCurve page shows onchain panel without read errors (1.2s)
PASS 4 [chromium] anvil-wallet-writes.spec.ts:21:3 TimeCurve approve and buy (CL8Y) (815ms)
PASS 5 [chromium] anvil-wallet-writes.spec.ts:47:3 TimeCurve ETH route: quote, swap, and buy (1.1s)
5 passed (6.4s)
Done.
The previously brittle TimeCurve ETH route case at line 47 (the one that was hitting 180s timeout on the stale input[name=timecurve-pay-with] selector) now passes in 1.1s. All 5 anvil-* spec files run serially under 1 worker as designed.
Item 2 - data-testid hooks present + aria-pressed driven
Source confirmed in two places sharing the same testid pattern (per dev's note that Simple and Arena use the same hook):
src/pages/timeCurveArena/TimeCurveArenaView.tsx:217: data-testid={timecurve-simple-paywith-${key}}
src/pages/TimeCurveSimplePage.tsx:483: data-testid={timecurve-simple-paywith-${key}}
The E2E test that just passed (anvil-wallet-writes.spec.ts:47:3) exercises this hook live by calling getByTestId(timecurve-simple-paywith-eth) and asserts on the aria-pressed state, so the live behavior is implicitly verified by the green test.
Item 3 - ETH E2E path: quoted field labeled correctly + leaves loading state
Same case anvil-wallet-writes.spec.ts:47:3 (1.1s) covers this end-to-end. Test passes, which means the quoted field's aria-label and loading-state-clearing are both behaving per spec. The case literally drives the timecurve-simple-paywith-eth toggle, waits for the quoter, and asserts the buy flow - all green.
Item 4 - Default test:e2e (no Anvil) preserves multi-worker behavior
Source confirmed in frontend/playwright.config.ts:
const isAnvilE2E = process.env.ANVIL_E2E === 1;
fullyParallel: !isAnvilE2E,
workers: isAnvilE2E ? 1 : process.env.CI ? 5 : undefined,
So default CI path with no ANVIL_E2E flag: workers 5 (CI) or undefined (local). Only ANVIL_E2E=1 forces serial. Matches dev's intent in the issue note.
Sign-off
All 4 acceptance items verified. Closing.
cc @PlasticDigits
mentioned in issue #58
mentioned in issue #100
mentioned in issue #104
mentioned in issue #113
mentioned in issue #135
mentioned in issue #263
mentioned in merge request !401
mentioned in merge request !515
mentioned in issue #340
mentioned in merge request !526