Web App Testing
Test local web applications with Playwright automation for frontend verification, UI debugging, and screenshot capture.
You push a UI change and manually click through 20 pages to check nothing broke — every single time. This playbook uses Playwright to automate web application testing with frontend verification, visual regression detection, UI debugging, and screenshot capture across browsers.
Who it's for: frontend developers adding automated browser tests to their web applications, QA engineers building Playwright test suites for regression testing, full-stack developers verifying UI changes don't break existing functionality, solo developers who can't manually test every page after each deploy, teams transitioning from manual QA to automated browser testing
Example
"Set up automated testing for our React web app's critical flows" → Web testing pipeline: Playwright test scaffolding for login, checkout, and dashboard flows, element interaction testing (forms, buttons, navigation), visual screenshot comparison detecting UI regressions, cross-browser testing across Chrome, Firefox, and Safari, and CI integration running tests automatically on every pull request
New here? 3-minute setup guide → | Already set up? Copy the template below.
# Web App Testing
Test local web applications through Playwright automation scripts for frontend verification, UI debugging, screenshot capture, and browser log inspection.
## Core Capabilities
- Frontend functionality verification
- UI debugging and inspection
- Screenshot capture at any point
- Browser console log access
- Automated user flow testing
## Helper Script
```bash
scripts/with_server.py
```
Manages server lifecycle for testing. Always run with `--help` first to see usage options. Do not read source until you try running the script.
## Testing Approaches
### Approach 1: Static HTML Files
For static HTML without server requirements:
1. Read HTML file directly
2. Extract selectors from source
3. Create Playwright automation script
4. Execute tests
### Approach 2: Dynamic Webapp (Server Not Running)
For applications requiring server startup:
1. Use `with_server.py` helper script
2. Script manages server lifecycle
3. Run automation after server ready
4. Server terminates after tests
### Approach 3: Dynamic Webapp (Server Running)
For applications with server already active:
1. Perform reconnaissance first
2. Navigate and wait for load
3. Capture screenshots/inspect DOM
4. Discover selectors from rendered state
5. Execute automation actions
## Critical Pattern: Reconnaissance-Then-Action
For dynamic web applications, always follow this sequence:
```python
# Step 1: Navigate to application
await page.goto('http://localhost:3000')
# Step 2: Wait for JavaScript execution
await page.wait_for_load_state('networkidle')
# Step 3: Capture current state
await page.screenshot(path='screenshot.png')
# Step 4: Inspect DOM for selectors
elements = await page.query_selector_all('button')
# Step 5: Perform actions
await page.click('button[data-testid="submit"]')
```
## Important: Network Idle
**Critical**: Inspecting DOM before waiting for `networkidle` on dynamic applications yields incomplete results. JavaScript must finish executing before selectors are reliable.
## Common Testing Tasks
### Screenshot Capture
```python
await page.screenshot(path='current-state.png')
await page.screenshot(path='full-page.png', full_page=True)
```
### Element Interaction
```python
await page.click('button#submit')
await page.fill('input[name="email"]', 'test@example.com')
await page.select_option('select#country', 'US')
```
### Assertions
```python
await expect(page.locator('h1')).to_have_text('Welcome')
await expect(page.locator('.error')).not_to_be_visible()
```
### Console Log Access
```python
page.on('console', lambda msg: print(msg.text))
```
## Selector Discovery
After waiting for networkidle:
1. Take screenshot for visual reference
2. Query DOM for element structure
3. Look for data-testid attributes
4. Use ARIA roles for accessibility
5. Fall back to CSS selectors
## Workflow Example
```markdown
## Testing Session: Login Flow
### 1. Reconnaissance
- Navigate to http://localhost:3000/login
- Wait for networkidle
- Screenshot: login-page.png
- Discovered selectors:
- Email: input[name="email"]
- Password: input[name="password"]
- Submit: button[type="submit"]
### 2. Test Execution
- Fill email: test@example.com
- Fill password: ********
- Click submit
- Wait for navigation
### 3. Verification
- Screenshot: after-login.png
- Assert: Dashboard heading visible
- Console: No errors logged
```
## Best Practices
1. **Always wait for networkidle** on dynamic applications
2. **Run scripts with --help first** before reading source
3. **Screenshot before and after** each major action
4. **Check console logs** for JavaScript errors
5. **Use stable selectors** (data-testid, roles)
6. **Handle async operations** with appropriate waits
What This Does
Test local web applications using Playwright automation scripts. Verify frontend functionality, debug UI issues, capture screenshots, and inspect browser logs with a reconnaissance-then-action approach.
Quick Start
Step 1: Create a Testing Project
mkdir -p ~/Projects/webapp-testing
Step 2: Download the Template
Click Download above, then:
mv ~/Downloads/CLAUDE.md ~/Projects/webapp-testing/
Step 3: Start Testing
cd ~/Projects/webapp-testing
claude
Then say: "Test my web app running at localhost:3000"
Testing Approaches
| Scenario | Approach |
|---|---|
| Static HTML | Read file, extract selectors, automate |
| Dynamic (server not running) | Use helper script to manage server |
| Dynamic (server running) | Reconnaissance first, then actions |
Reconnaissance-Then-Action Pattern
Step 1: Navigate
await page.goto('http://localhost:3000');
Step 2: Wait for Load
await page.wait_for_load_state('networkidle');
Step 3: Capture State
- Take screenshots
- Inspect DOM structure
- Discover selectors
Step 4: Execute Actions
- Click, type, submit
- Verify results
- Capture final state
Key Capabilities
- Frontend Verification: Test UI components work correctly
- Visual Debugging: Screenshot capture at any point
- Log Inspection: Access browser console logs
- Automation: Script complex user flows
- Server Management: Handle server lifecycle
Example Prompts
- "Take a screenshot of my app at localhost:3000"
- "Test the login flow on my local server"
- "Verify the form submission works correctly"
- "Check for JavaScript errors in the console"
- "Automate clicking through the onboarding"
Helper Script
# Manage server lifecycle for testing
python scripts/with_server.py
Run with --help first to see usage options.
Common Testing Tasks
| Task | Action |
|---|---|
| Screenshot | Capture current state |
| Click | Interact with elements |
| Type | Fill form fields |
| Submit | Send forms |
| Assert | Verify content |
| Wait | Handle async operations |
Critical Tips
- Wait for networkidle: Dynamic apps need JavaScript to execute
- Check --help first: Don't read script source until you try running
- Discover selectors: Inspect rendered state, not source HTML
- Handle async: Web apps often have delayed content
Tips
- Always wait for network idle on dynamic sites
- Screenshot before and after actions
- Check console for JavaScript errors
- Use stable selectors (data-testid, roles)