E2E spec covering the full conversion funnel: landing page CTA →
web-app get-krk page → Uniswap deep link verification → stake route.
Tests desktop (1280×720) and mobile (375×812) viewports, validates
Uniswap deep link structure (correct chain + token address), and
verifies analytics events fire at each funnel stage via injected
mock tracker.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
recenterAccess() was removed from LiquidityManager in this PR.
The old tests called recenterAccess() (selector 0xdef51130) which now
reverts, causing both recenter tests to fail.
Update tests to match the new public recenter() behavior:
- Test 1: verify any address may call recenter() without "access denied"
- Test 2: same caller pattern, guard errors are still acceptable
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
taxPaidGes = taxDue + taxPaid, so the displayed value includes both
outstanding tax and historically paid tax. Rename the UI label from
'Tax Paid' to 'Tax Cost' to accurately reflect the combined amount.
Update the matching E2E test selector accordingly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace waitForLoadState('networkidle') with a comment explaining that callers
must assert on a route-specific element. The SPA keeps persistent WebSocket
connections for blockchain event subscriptions, so networkidle never fires
within the 10 s window, causing spurious TimeoutErrors in 01-acquire-and-stake
and 02-max-stake-all-tax-rates.
Vue Router processes popstate synchronously inside page.evaluate(), so the
route transition has already started by the time evaluate() resolves. Callers'
toBeVisible() assertions (with their own timeouts) serve as the readiness gate.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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