Replace the try/catch on observing the transient 'Submitting…' button text with a
two-phase disabled→enabled check. The button gains the `disabled` attribute the
moment `swapping=true` and loses it when the swap finishes. By placing
`toBeEnabled({ timeout: 60_000 })` unconditionally after the try block, both
paths (fast RPC where disabled state cycles in <100 ms and slow RPC where it is
clearly observable) now wait for the actual ready state rather than falling
through to only a 2-second static guard.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace all 10 bare waitForTimeout() calls in tests/e2e/usertest/helpers.ts
with proper event-driven Playwright waits per AGENTS.md Engineering Principle #3
("replace when touched"):
connectWallet():
- Remove 500ms resize-event sleep: connectButton.isVisible({ timeout: 5_000 })
already waits for the layout to settle after the resize event
- Remove 2000ms "connector init" sleep: the subsequent isVisible check was
already event-driven
- Replace 2x 1000ms panel-animation sleeps with
injectedConnector.waitFor({ state: 'visible' }) — the .connectors-element
appearing is the exact observable DOM event
- Remove 2x 2000ms "handshake" sleeps: walletDisplay.waitFor() at the end of
the function is the correct gate for connection completion
attemptStake():
- Remove 3000ms post-goto sleep: tokenAmountSlider.waitFor() at the next line
is the correct page-load gate
- Remove 2x 500ms debounce sleeps after fill/select: stakeButton.waitFor()
downstream is the correct reactive-state gate
- Remove 3000ms post-transaction sleep: the button returning to "Stake" text
(waitFor at line 619) is already the correct transaction-completion gate
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add eslint-disable-next-line no-restricted-syntax comments with
justification to the 10 bare waitForTimeout() calls in
tests/e2e/usertest/helpers.ts.
All waitForTimeout calls in the spec files (01–06 and all usertest
specs) were already properly documented after PR #417. helpers.ts was
the only remaining file with bare calls:
- 6 in connectWallet(): wallet connector panel animation and
connection handshake have no observable DOM event to await
- 4 in attemptStake(): Ponder indexing lag, debounced form handlers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
getByTestId('swap-buy-button').waitFor({ state: 'visible' }) resolved
immediately because the button is always rendered; only its text changes.
Replace with expect(...).toHaveText('Buy KRK', { timeout: 60_000 }) to
correctly gate on the button returning to its idle state.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Update 02-max-stake-all-tax-rates.spec.ts to buy KRK via /app/get-krk
instead of the removed cheats-page swap card
- Add VITE_ENABLE_LOCAL_SWAP=true to the webapp CI service so
LocalSwapWidget renders in the e2e pipeline
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace screen.width with window.innerWidth in useMobile composable.
screen.width reports the physical screen size (0 in headless Chromium),
while window.innerWidth reflects the actual viewport — the correct metric
for responsive layout. The previous Object.defineProperty workaround in
wallet-provider.ts could not override the native Screen.prototype getter,
so screen.width remained 0, isMobile stayed true, and ConnectButton was
never rendered. Fix wallet-provider.ts to pass viewport/screen options
directly to browser.newContext() and remove the broken init-script shim.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 01-acquire-and-stake: replace flat 3 s wait with a 30 s polling loop so
Ponder indexing lag no longer causes a spurious positions.length=0 failure.
- 05-optimizer-integration test 1: replace hard-coded OptimizerV3 bear-market
constants (anchorShare=3e17, anchorWidth=100, discoveryDepth=3e17) with
Optimizer.sol invariant checks:
capitalInefficiency + anchorShare == 1e18
discoveryDepth == anchorShare
anchorWidth ∈ [10, 80]
- 05-optimizer-integration test 2: decouple bootstrap-position assertion from
current optimizer state. Earlier tests change staking state, so the current
optimizer anchorWidth differs from the one used at bootstrap time. Instead,
reverse-calculate the implied anchorWidth from the observed anchor spread and
verify it lies within [10, 80].
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements window.__testHelpers.fillStakeForm() to enable stable E2E testing
of the staking form without fragile UI selectors.
## Changes
- Add window.__testHelpers interface (dev mode only)
- Implement fillStakeForm() in StakeHolder.vue with input validation
- Add TypeScript declarations in env.d.ts
- Update E2E test to use helper and verify full user journey
- Create INTEGRATION_TEST_STATUS.md documenting test coverage
- Document helper in web-app/README.md
## Test Coverage
Playwright E2E now validates complete flow:
- Mint ETH via cheats page UI
- Swap KRK via cheats page UI
- Stake KRK via stake page UI (helper + click)
- Verify position via GraphQL
Both Playwright and verify-swap.sh tests now work independently.
resolves#62
Co-authored-by: johba <johba@harb.eth>
Reviewed-on: https://codeberg.org/johba/harb/pulls/66
Replaces basic "service is up" checks with functional verification that tests can actually use the services.
## Changes
### New Health Checks
- **RPC Proxy**: Verifies eth_call works and deployed contracts are accessible
- **GraphQL**: Confirms Ponder has indexed data with non-zero stats
- **Web App**: Validates endpoint accessibility
### Improvements
- Clear error messages explain what failed and how to fix it
- Checks verify actual functionality, not just HTTP 200 responses
- Fails fast before tests run with cryptic errors
### Files
- `tests/setup/health-checks.ts` - Core health check functions
- `tests/setup/stack.ts` - Integration with waitForStackReady()
- `tests/HEALTH_CHECKS.md` - Documentation and troubleshooting guide
## Error Message Example
Before:
```
RPC health check failed with status 404
```
After:
```
❌ Stack health check failed
Failed services:
• RPC Proxy: RPC proxy returned HTTP 404
Expected 200, got 404. Check if Anvil is running and RPC_URL is correct.
• GraphQL Indexer: GraphQL has no indexed data yet
Ponder is running but has not indexed contract events.
Troubleshooting:
1. Check stack logs: tail tests/.stack.log
2. Verify services are running: ./scripts/dev.sh status
3. Restart stack: ./scripts/dev.sh restart --full
```
## Benefits
- ✅ Tests fail fast with clear error messages
- ✅ Catches configuration issues before tests run
- ✅ Verifies services are actually usable, not just running
resolves#61
Co-authored-by: johba <johba@harb.eth>
Reviewed-on: https://codeberg.org/johba/harb/pulls/65