Audit UX waiting states for web applications with long-running operations (30+ seconds)...
Evaluate how applications handle long-running operations (30+ seconds) using browser automation.
Screenshot First, DOM Second โ always take a screenshot when navigating or stuck. Visual inspection beats DOM probing.
๐ธ Screenshot โ ๐ Analyze visually โ ๐ฏ Click coordinates โ ๐ธ Verify โ Repeat
ALWAYS screenshot:
| DOM Approach | Screenshot Approach |
|---|---|
| Complex selectors fail silently | Visual shows exact UI state |
| "missing value" gives no info | Image reveals button locations |
| 10+ attempts to find element | 1 screenshot โ click coordinates |
| Can't see actual user experience | See exactly what user sees |
# 1. Navigate
Control Chrome:open_url(TARGET_URL)
sleep(2)
# 2. ALWAYS screenshot first
# Use browser screenshot or html2canvas
# Analyze the image before ANY interaction
# 3. If interaction needed, prefer coordinates over selectors
# After seeing screenshot: "The submit button is at ~(1200, 650)"
Control Chrome:execute_javascript("document.elementFromPoint(1200, 650).click()")
# 4. Screenshot again to verify
# 1. Navigate to target URL
Control Chrome:open_url(TARGET_URL)
sleep(3)
# 2. SCREENSHOT - See what loaded
# Analyze: What's visible? Where are interactive elements?
# 3. Ask user to help identify:
# - Which operation to test
# - How to trigger it (button location, input needed)
This is often where audits get stuck. Modern SPAs have complex UIs.
# Strategy 1: Ask user for guidance
# "I see the page. Can you describe where the button is or what to click?"
# Strategy 2: Use simple, targeted JS
Control Chrome:execute_javascript("document.querySelector('button[type=submit]').click()")
# Strategy 3: Coordinate-based clicking (after screenshot)
Control Chrome:execute_javascript("document.elementFromPoint(X, Y).click()")
# Strategy 4: Let user trigger manually
# "Please click the button to start the operation, then tell me when it's processing"
Once operation is running:
# T+0s: Screenshot immediately when operation starts
# T+10s: Screenshot after 10 seconds
sleep(10)
# Screenshot + capture_state.js
# T+30s: Screenshot after 30 seconds
sleep(20)
# Screenshot + capture_state.js
# T+Complete: Screenshot when done
# Watch for UI changes indicating completion
# 1. Evaluate screenshots against checklist (see references/checklist.md)
# 2. Generate report with annotated screenshots
# 3. Prioritize recommendations
โ WRONG: Keep trying different selectors
โ Wastes time, silent failures
โ
RIGHT: Take screenshot, analyze visually
โ Ask user for help if needed
โ Use coordinate-based clicking
This usually means:
Fix: Use simple one-liner JS, not complex functions.
// โ Complex (fails silently)
(function() { const elements = []; ... return JSON.stringify(elements); })()
// โ
Simple (clear result)
document.body.innerText.substring(0, 500)
document.querySelectorAll('button').length
document.querySelector('.loading') !== null
Try in order:
document.forms[0].submit()Ask user for:
If user is available: Ask them to trigger the operation manually while you capture screenshots. This avoids navigation complexity.
Always screenshot first. Then run simple state checks:
// Simple one-liners that won't fail silently:
// Check for spinner
!!document.querySelector('[class*="spin"], [class*="load"], .spinner')
// Check for progress bar
!!document.querySelector('progress, [role="progressbar"]')
// Get visible text (look for status messages)
document.body.innerText.substring(0, 1000)
// Count results appearing
document.querySelectorAll('[class*="result"], [class*="item"]').length
Capture Timeline:
| Time | Action |
|---|---|
| T+0s | Screenshot + note what triggered |
| T+10s | Screenshot + simple state checks |
| T+30s | Screenshot + simple state checks |
| T+Complete | Screenshot + final state |
Load and evaluate against references/checklist.md. Score each category:
Use template from references/report-template.md.
Look for:
// Partial results appearing
document.querySelectorAll('[class*="result"], [class*="item"], li, tr').length
// Streaming content
document.querySelector('[class*="stream"], [class*="typing"], [class*="cursor"]')
Look for:
// Counters
document.body.innerText.match(/\d+\s*(found|processed|complete|%)/gi)
// Animations (CSS or JS)
document.querySelectorAll('[class*="animate"], [class*="pulse"], [class*="spin"]')
Look for:
// Time remaining text
document.body.innerText.match(/(\d+\s*(sec|min|second|minute)|remaining|left|ETA)/gi)
// Progress percentage
document.querySelector('[role="progressbar"]')?.getAttribute('aria-valuenow')
For each interval, note:
Compare:
| Element | T+0s | T+10s | T+30s | Complete |
|---|---|---|---|---|
| Results visible | ||||
| Counter/progress | ||||
| Status message | ||||
| Animation active |
Generate markdown report with:
references/report-template.mdReference these examples of excellent waiting UX:
If possible, test:
// Simulate slow network (if DevTools available)
// Or disconnect briefly and observe behavior
| Issue | User Impact | Quick Fix |
|---|---|---|
| Spinner only | Anxiety, abandon | Add status text |
| No progress | "Is it stuck?" | Add heartbeat counter |
| No cancellation | Trapped feeling | Add cancel button |
| Silent completion | Missed results | Add completion animation |
| Full-page block | Can't multitask | Move to background |