skills/autumnsgrove/webapp-testing/SKILL.md
Professional web application testing and automation using Playwright with support for multiple browsers, mobile emulation, screenshot capture, network interception, and comprehensive test assertions. Use for: (1) E2E testing across browsers, (2) UI automation, (3) Form testing and validation, (4) Visual regression testing, (5) API mocking and interception, (6) Mobile responsive testing
npx skillsauth add aiskillstore/marketplace webapp-testingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Playwright is a powerful framework for web testing and automation that supports all modern browsers (Chromium, Firefox, WebKit). It provides reliable, fast, and capable automation with auto-waiting, network control, and comprehensive testing capabilities.
Use this skill when you need to:
Create a simple test with Playwright's auto-waiting:
import pytest
from playwright.sync_api import Page, expect
def test_homepage_loads(page: Page):
"""Test that homepage loads successfully."""
page.goto("https://example.com")
expect(page).to_have_title("Example Domain")
expect(page.locator("h1")).to_contain_text("Example Domain")
def test_navigation(page: Page):
"""Test navigation between pages."""
page.goto("https://example.com")
page.click("text=More information")
expect(page).to_have_url("https://www.iana.org/domains/reserved")
Test form filling, validation, and submission:
def test_login_form(page: Page):
"""Test login form submission."""
page.goto("https://example.com/login")
# Fill form fields
page.fill("#username", "[email protected]")
page.fill("#password", "SecurePassword123")
page.check("#remember-me")
# Submit and verify
page.click("button[type='submit']")
expect(page).to_have_url("https://example.com/dashboard")
expect(page.locator(".welcome-message")).to_be_visible()
Mock API responses for controlled testing:
def test_with_mocked_api(page: Page):
"""Test with mocked API response."""
# Mock API response
page.route("**/api/user", lambda route: route.fulfill(
status=200,
content_type="application/json",
body='{"name": "Test User", "premium": true}'
))
page.goto("https://example.com/profile")
expect(page.locator(".user-name")).to_contain_text("Test User")
Test responsive designs on mobile devices:
@pytest.fixture
def mobile_page(playwright):
"""Create mobile browser context."""
iphone = playwright.devices['iPhone 12']
browser = playwright.chromium.launch()
context = browser.new_context(**iphone)
page = context.new_page()
yield page
context.close()
browser.close()
def test_mobile_menu(mobile_page: Page):
"""Test mobile navigation."""
mobile_page.goto("https://example.com")
expect(mobile_page.locator(".hamburger-menu")).to_be_visible()
mobile_page.click(".hamburger-menu")
expect(mobile_page.locator(".mobile-menu")).to_be_visible()
Capture screenshots for visual comparison:
def test_homepage_screenshot(page: Page):
"""Capture homepage screenshot."""
page.goto("https://example.com")
# Full page screenshot
page.screenshot(path="screenshots/homepage.png", full_page=True)
# Element screenshot
page.locator("header").screenshot(path="screenshots/header.png")
# Screenshot with masks for dynamic content
page.screenshot(
path="screenshots/dashboard.png",
mask=[page.locator(".timestamp"), page.locator(".session-id")]
)
# ✅ GOOD: Test IDs and semantic selectors
page.click("[data-testid='submit-button']")
page.click("button:text('Submit')")
page.click("role=button[name='Submit']")
# ❌ BAD: Fragile structural selectors
page.click("div > div > button:nth-child(3)")
# ✅ GOOD: Playwright auto-waits
page.click("button")
expect(page.locator(".result")).to_be_visible()
# ⚠️ Avoid: Manual waits
time.sleep(2) # Only when absolutely necessary
# ✅ GOOD: Clean state between tests
@pytest.fixture(autouse=True)
def clear_state(page: Page):
yield
page.context.clear_cookies()
page.evaluate("localStorage.clear()")
# ✅ GOOD: Wait for specific conditions
page.click("button")
page.wait_for_selector(".result")
result = page.locator(".result").text_content()
# ✅ GOOD: Use soft assertions
expect.soft(page.locator(".title")).to_be_visible()
expect.soft(page.locator(".price")).to_contain_text("$")
Organize tests using the Page Object pattern for maintainability:
class LoginPage:
"""Login page object."""
def __init__(self, page: Page):
self.page = page
self.username_input = page.locator("#username")
self.password_input = page.locator("#password")
self.submit_button = page.locator("button[type='submit']")
def login(self, username: str, password: str):
"""Perform login."""
self.username_input.fill(username)
self.password_input.fill(password)
self.submit_button.click()
# Use in tests
def test_login(page: Page):
login_page = LoginPage(page)
login_page.login("[email protected]", "password123")
expect(page).to_have_url("/dashboard")
@pytest.fixture
def authenticated_page(page: Page):
"""Provide authenticated session."""
page.goto("https://example.com/login")
page.fill("#username", "[email protected]")
page.fill("#password", "password")
page.click("button[type='submit']")
page.wait_for_url("**/dashboard")
yield page
# Upload
page.set_input_files("#file-input", "path/to/file.pdf")
# Download
with page.expect_download() as download_info:
page.click("a:text('Download')")
download = download_info.value
download.save_as("downloads/file.pdf")
requests = []
page.on("request", lambda req: requests.append(req))
page.goto("https://example.com")
# Verify API calls were made
api_requests = [r for r in requests if "/api/" in r.url]
assert len(api_requests) > 0
# Install Playwright
pip install playwright pytest-playwright
playwright install
# Run all tests
pytest tests/
# Run specific browser
pytest --browser chromium --browser firefox
# Run in headed mode (see browser)
pytest --headed
# Debug mode
PWDEBUG=1 pytest tests/test_login.py
# Parallel execution
pytest -n auto
# Generate test code
playwright codegen https://example.com
See references/setup-configuration.md for:
Ensure tests meet these criteria:
Tests are flaky:
wait_for_selector, wait_for_url)expect() assertions which auto-retrySelectors not finding elements:
PWDEBUG=1 pytest test.pyTests slow in CI:
pytest -n autoFor more troubleshooting tips, see Common Pitfalls.
development
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
tools
Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
testing
Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programming, concurrency, and architecture guidance.
tools
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.