webapp-testing
Expert guidance for testing web applications using Playwright and other testing frameworks. Use when testing UIs, automating browser interactions, or validating web app behavior.
$ Installieren
git clone https://github.com/LangConfig/langconfig /tmp/langconfig && cp -r /tmp/langconfig/backend/skills/builtin/webapp-testing ~/.claude/skills/langconfig// tip: Run this command in your terminal to install the skill
name: webapp-testing description: "Expert guidance for testing web applications using Playwright and other testing frameworks. Use when testing UIs, automating browser interactions, or validating web app behavior." version: 1.0.0 author: LangConfig tags:
- testing
- playwright
- selenium
- e2e
- browser
- automation triggers:
- "when user mentions Playwright"
- "when user mentions browser testing"
- "when user mentions e2e testing"
- "when user mentions UI testing"
- "when user mentions selenium" allowed_tools:
- filesystem
- shell
- python
Instructions
You are an expert web application tester specializing in browser automation with Playwright. Follow these guidelines for comprehensive testing.
Testing Strategy Decision Tree
Step 1: Determine Application Type
- Static HTML â Use simple page inspection
- Dynamic SPA â Wait for network idle before inspection
- Server-rendered â Check both initial HTML and hydrated state
Step 2: Choose Testing Approach
Is the server running?
âââ Yes â Use live server testing
â âââ Can you start it? â Use with_server.py helper
âââ No â Static file testing or start server first
Core Playwright Patterns
1. Basic Test Structure (Python)
from playwright.sync_api import sync_playwright
def test_login_flow():
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
# Navigate and wait for load
page.goto("http://localhost:3000")
page.wait_for_load_state("networkidle")
# Interact with elements
page.fill('[data-testid="email"]', "user@example.com")
page.fill('[data-testid="password"]', "password123")
page.click('button[type="submit"]')
# Assert result
page.wait_for_url("**/dashboard")
assert page.title() == "Dashboard"
browser.close()
2. Critical Wait Patterns
# ALWAYS wait for network idle on SPAs
page.wait_for_load_state("networkidle")
# Wait for specific element
page.wait_for_selector('[data-testid="loaded"]', state="visible")
# Wait for navigation
page.wait_for_url("**/success")
# Wait for network request
with page.expect_response("**/api/data") as response_info:
page.click("#load-data")
response = response_info.value
3. Selector Best Practices
# PREFERRED: Test IDs (most stable)
page.click('[data-testid="submit-btn"]')
# GOOD: Role-based selectors
page.click('role=button[name="Submit"]')
# GOOD: Text content
page.click('text=Submit Form')
# ACCEPTABLE: CSS selectors
page.click('.submit-button')
# AVOID: XPath (fragile)
# AVOID: nth-child selectors (fragile)
4. Form Testing
# Fill form fields
page.fill('#username', 'testuser')
page.fill('#email', 'test@example.com')
# Select dropdowns
page.select_option('#country', 'US')
# Checkboxes and radios
page.check('#agree-terms')
page.click('input[name="plan"][value="premium"]')
# File uploads
page.set_input_files('#avatar', 'path/to/image.png')
# Submit and verify
page.click('button[type="submit"]')
page.wait_for_selector('.success-message')
Multi-Server Testing
When testing apps with separate frontend/backend:
# Helper script usage
# python scripts/with_server.py --help
# Start multiple servers
# python scripts/with_server.py \
# --server "cd backend && python main.py" --port 8000 \
# --server "cd frontend && npm run dev" --port 3000 \
# -- python tests/e2e_test.py
Visual Testing Patterns
# Screenshot comparison
page.screenshot(path="screenshots/homepage.png")
# Full page screenshot
page.screenshot(path="full_page.png", full_page=True)
# Element screenshot
element = page.locator('.hero-section')
element.screenshot(path="hero.png")
# Compare with baseline (using pixelmatch or similar)
Console and Network Monitoring
# Capture console logs
console_messages = []
page.on("console", lambda msg: console_messages.append(msg.text))
# Monitor network requests
requests = []
page.on("request", lambda req: requests.append(req.url))
# Check for errors
errors = []
page.on("pageerror", lambda err: errors.append(str(err)))
# After test
assert len(errors) == 0, f"Page errors: {errors}"
API Testing Integration
# Intercept and mock API calls
page.route("**/api/users", lambda route: route.fulfill(
status=200,
content_type="application/json",
body='[{"id": 1, "name": "Test User"}]'
))
# Verify API calls were made
with page.expect_request("**/api/submit") as request_info:
page.click("#submit")
request = request_info.value
assert request.method == "POST"
Common Testing Scenarios
-
Authentication Flow
- Test login with valid/invalid credentials
- Verify session persistence
- Test logout and session cleanup
- Check protected route redirects
-
Form Validation
- Test required field validation
- Test format validation (email, phone)
- Test min/max length constraints
- Test form submission success/failure
-
Navigation
- Test all navigation links
- Verify back/forward browser buttons
- Test deep linking
- Check 404 handling
-
Responsive Design
- Test at mobile breakpoints (375px, 414px)
- Test at tablet breakpoints (768px, 1024px)
- Test at desktop breakpoints (1280px, 1920px)
Examples
User asks: "Test the login page of my React app"
Response approach:
- Start the dev server
- Navigate to login page
- Wait for networkidle (React hydration)
- Test valid login flow
- Test invalid credentials
- Test form validation
- Verify redirect after login
- Take screenshots for documentation
Repository
