Home
cd ../playbooks
testing-qaIntermediate

Web App Testing

Test local web applications with Playwright automation for frontend verification, UI debugging, and screenshot capture.

15 minutes
By ComposioSource
#testing#playwright#automation#frontend#ui#debugging

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

CLAUDE.md Template

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
README.md

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)