browser-testing-ocr-validation
Guide and workflow for Browser Testing with OCR Validation. Use when you need Browser Testing with OCR Validation.
What this skill does
# Browser Testing with OCR Validation
**CRITICAL**: Always validate browser screenshots with OCR when testing UI changes, especially for bugs where visual elements may or may not be present.
## Why OCR Validation is Essential
- **Human perception bias**: Looking at screenshots can lead to assumptions about what's visible
- **Memory errors**: Agents may remember what *should* be there rather than what *is* there
- **Proof of fix**: OCR provides concrete text evidence of what's actually rendered
- **No guessing**: OCR output is definitive - either the text is there or it's not
## Primary Method: Chrome Superpowers Auto-Capture (`page.md`)
Chrome Superpowers **automatically captures** `page.md` on every DOM-changing action (navigate, click, type, select, eval). This extracts text directly from the DOM - more accurate than image OCR.
### Auto-Captured Files Location
```
/tmp/chrome-session-{id}/{action-number}-{action}-{timestamp}/
├── page.md # DOM text extraction (primary OCR)
├── page.html # Full rendered DOM
├── screenshot.png # Visual page state
└── console-log.txt # Browser console output
```
### Using Auto-Captured page.md
```python
# 1. Navigate (triggers auto-capture)
mcp__chrome-superpower__use_browser(action="navigate", payload="https://example.com")
# 2. Read the auto-captured page.md for text validation
Read(file_path="/tmp/chrome-session-xxx/001-navigate-yyy/page.md")
# Contains all text content extracted from the DOM
```
**Advantages:**
- 100% accurate text from actual DOM (not image recognition)
- Automatic - no extra steps needed
- Includes all visible text content
- Works with dynamically loaded content
## Secondary Method: Claude Code Native Vision
Claude Code is a **multimodal LLM** that can directly see and analyze images. When you use the Read tool on a PNG file, Claude sees the image content directly.
### Using Claude Vision for OCR
```python
# Simply read the image file - Claude sees it directly
Read(file_path="/tmp/screenshots/test-screenshot.png")
# Claude will describe: user emails, button text, form content, UI state, etc.
```
**Advantages over external OCR:**
- Higher accuracy for complex layouts
- Understands context and UI elements
- Can describe visual state (colors, positioning, icons)
- No external dependencies needed
## Tertiary Method: Tesseract OCR (Cross-Validation)
Use Tesseract as an additional method for cross-validation when needed.
This system has Tesseract installed at `/opt/homebrew/bin/tesseract` with Python bindings.
### Verify Installation
```bash
which tesseract # Should return /opt/homebrew/bin/tesseract
tesseract --version
```
### Install Python Dependencies (if needed)
```bash
python3 -m pip install --user pillow pytesseract
```
## Standard OCR Validation Workflow
### 1. Take Screenshot
```bash
# Using Chrome Superpowers MCP
mcp__chrome-superpower__use_browser(action: "screenshot", payload: "/tmp/screenshots/test-name.png")
```
### 2. Run OCR to Extract Text
```python
python3 - <<'PY'
from PIL import Image
import pytesseract
image_path = "/tmp/screenshots/test-name.png"
img = Image.open(image_path)
text = pytesseract.image_to_string(img)
print(text)
PY
```
### 3. Validate Expected Content
```python
python3 - <<'PY'
from PIL import Image
import pytesseract
image_path = "/tmp/screenshots/after-send.png"
img = Image.open(image_path)
text = pytesseract.image_to_string(img)
# Check for specific content
if "expected user message" in text:
print("✅ SUCCESS: Message IS visible")
else:
print("❌ FAILURE: Message NOT visible")
print("\n=== Full OCR Output ===")
print(text)
PY
```
## Real-World Example: Disappearing Messages Bug
**Problem**: Messages appeared to disappear after clicking Send, but visual inspection of screenshots was unreliable.
**Solution**: Used OCR to definitively prove the bug:
```python
python3 - <<'PY'
from PIL import Image
import pytesseract
image_path = "/tmp/screenshots/after-send-before-response.png"
img = Image.open(image_path)
text = pytesseract.image_to_string(img)
# Look for the user's message text
if "verify bug fix test" in text or "VERIFY FIX" in text:
print("✅ Message IS visible (optimistic UI working)")
else:
print("❌ Message NOT visible (bug confirmed)")
print("\nOCR Output:")
print(text)
PY
```
**Result**: OCR showed the message was NOT in the OCR output, confirming the bug was still present even though the screenshot "looked fine" to human eyes.
## Best Practices
### ✅ DO:
- **Always use OCR for visual regression tests**
- **Verify both positive and negative cases** (element present vs absent)
- **Include OCR output in bug reports** as proof
- **Test immediately after UI actions** (click, type, submit)
- **Use descriptive test messages** that are easy to grep for ("VERIFY FIX - test message")
### ❌ DON'T:
- **Never rely solely on visual inspection** of screenshots
- **Don't assume** what you remember seeing in earlier screenshots
- **Don't skip OCR** because "it looks right"
- **Don't use generic messages** like "test" (hard to validate in OCR)
## When to Use OCR
**MANDATORY for:**
- ✅ Testing disappearing/appearing UI elements
- ✅ Validating message visibility in chat interfaces
- ✅ Confirming modal/dialog content
- ✅ Verifying form input/output
- ✅ Checking loading states and error messages
**OPTIONAL for:**
- Layout/styling changes (colors, spacing)
- Interactive element positioning
- Animation/transition testing
## OCR Limitations
- **Text must be readable**: Small fonts, low contrast may not OCR well
- **Complex layouts**: OCR may not preserve exact formatting
- **Images/icons**: OCR only reads text, not graphical elements
- **Dynamic content**: Take screenshot at the right moment
## Example Test Script
```bash
#!/bin/bash
# Test: Verify user message stays visible after Send
# 1. Navigate and type message
python3 - <<'PY'
# (use Chrome Superpowers to type message)
PY
# 2. Click Send
python3 - <<'PY'
# (use Chrome Superpowers to click Send button)
PY
# 3. Immediate screenshot
python3 - <<'PY'
# (use Chrome Superpowers to capture screenshot)
PY
# 4. OCR validation
python3 - <<'PY'
from PIL import Image
import pytesseract
img = Image.open("/tmp/screenshots/after-send.png")
text = pytesseract.image_to_string(img)
if "expected message text" in text:
print("✅ TEST PASSED")
exit(0)
else:
print("❌ TEST FAILED")
print(text)
exit(1)
PY
```
## Integration with Test Suites
Add OCR validation to Cypress/Playwright tests:
```javascript
// Cypress example
cy.task('ocrScreenshot', '/tmp/screenshots/test.png').then((text) => {
expect(text).to.include('expected message')
})
```
## Summary
**Golden Rule**: If you're testing whether UI elements are visible in a browser, ALWAYS use OCR to validate. Don't trust your eyes or memory - trust the OCR output.
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.