Automate Web Application Testing with Playwright
Skill for writing native Python Playwright scripts to test local web apps, with a server-lifecycle helper and a reconnaissance-then-action pattern.
Maintainer of this project? Claim this page to edit the listing.
15.5.1Add to Favorites
Why it matters
Automate the testing of local web applications by writing native Python Playwright scripts. This skill helps manage server lifecycles and provides a decision tree for choosing the right testing approach.
Outcomes
What it gets done
Write Playwright scripts for web application testing.
Manage local web server lifecycles using helper scripts.
Automate reconnaissance and action patterns for dynamic web apps.
Execute tests for static HTML files.
Install
Add it to your toolbox
Run in your project directory:
curl -fsSL https://spark.entire.vc/get/ag-webapp-testing | bash Overview
Web Application Testing
A skill for testing local web apps with native Python Playwright scripts, using a bundled scripts/with_server.py helper for server lifecycle and a reconnaissance-then-action pattern: wait for networkidle, inspect the rendered DOM, then act on discovered selectors. Use it to test or automate a local static or dynamic web app with Playwright; the bundled server-lifecycle helper is most useful when the app needs a dev server started around the test run.
What it does
A skill for testing local web applications by writing native Python Playwright scripts, built around a decision tree and a bundled helper script rather than ad-hoc automation. scripts/with_server.py manages server lifecycle, including multiple servers at once, and is meant to be run with --help first and invoked as a black box - the skill explicitly warns not to read the helper's source until a run has been tried and a customized solution is proven necessary, since these scripts can be large enough to pollute the context window. Its decision tree branches on the task: for static HTML, read the file directly to find selectors and write a Playwright script against them, falling back to the dynamic path if that's incomplete; for a dynamic webapp with no server running, run with_server.py --help then use the helper plus a simplified Playwright script; for a dynamic webapp with a server already running, follow a reconnaissance-then-action pattern - navigate and wait for networkidle, take a screenshot or inspect the DOM, identify selectors from the rendered state, then execute actions with those selectors. Its single-server example runs python scripts/with_server.py --server "npm run dev" --port 5173 -- python your_automation.py; its multi-server example chains two --server/--port pairs, for example a backend on port 3000 and a frontend on 5173, before the automation command. The automation script itself should contain only Playwright logic, since server management is handled automatically. The skill names a specific common pitfall: inspecting the DOM before waiting for networkidle on dynamic apps is wrong; waiting for page.wait_for_load_state('networkidle') before inspection is correct. Its best practices: treat any script in scripts/ as a black box invoked via --help then direct call rather than something to read into context, use sync_playwright() for synchronous scripts, always close the browser when done, prefer descriptive selectors (text=, role=, CSS selectors, or IDs), and add explicit waits (page.wait_for_selector() or page.wait_for_timeout()). Three reference examples live in examples/: element_discovery.py (finding buttons, links, and inputs on a page), static_html_automation.py (automating local HTML via file:// URLs), and console_logging.py (capturing console logs during a run).
When to use - and when NOT to
Use it whenever you need to test or automate a local web application - static HTML or a dynamic app with its own dev server - and want a Python Playwright script rather than a browser extension or manual testing. It's specifically built around a bundled helper for server lifecycle management, so it's most useful when the app under test needs a dev server started and stopped around the test run; for pure static HTML with no server, the direct-selector path applies instead.
Inputs and outputs
Input is a local web application, either a static HTML file or a dynamic app with a start command, plus the actions or assertions to automate. Output is a runnable Python Playwright script, invoked either directly or via with_server.py for server lifecycle management. Its core automation script pattern, quoted verbatim:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True) # Always launch chromium in headless mode
page = browser.new_page()
page.goto('http://localhost:5173') # Server already running and ready
page.wait_for_load_state('networkidle') # CRITICAL: Wait for JS to execute
# ... your automation logic
browser.close()
Integrations
Built on Python's playwright.sync_api, specifically Chromium in headless mode, plus its own bundled scripts/with_server.py helper for managing one or more dev-server processes, such as an npm run dev frontend alongside a separate backend process, around the automation run.
Who it's for
Developers who need to write reliable Playwright-based tests or automation against a local web app, static or dynamic, without hand-rolling server startup and shutdown or rediscovering the networkidle-before-inspection pitfall each time.
Source README
Web Application Testing
To test local web applications, write native Python Playwright scripts.
Helper Scripts Available:
scripts/with_server.py- Manages server lifecycle (supports multiple servers)
Always run scripts with --help first to see usage. DO NOT read the source until you try running the script first and find that a customized solution is abslutely necessary. These scripts can be very large and thus pollute your context window. They exist to be called directly as black-box scripts rather than ingested into your context window.
Decision Tree: Choosing Your Approach
User task → Is it static HTML?
├─ Yes → Read HTML file directly to identify selectors
│ ├─ Success → Write Playwright script using selectors
│ └─ Fails/Incomplete → Treat as dynamic (below)
│
└─ No (dynamic webapp) → Is the server already running?
├─ No → Run: python scripts/with_server.py --help
│ Then use the helper + write simplified Playwright script
│
└─ Yes → Reconnaissance-then-action:
1. Navigate and wait for networkidle
2. Take screenshot or inspect DOM
3. Identify selectors from rendered state
4. Execute actions with discovered selectors
Example: Using with_server.py
To start a server, run --help first, then use the helper:
Single server:
python scripts/with_server.py --server "npm run dev" --port 5173 -- python your_automation.py
Multiple servers (e.g., backend + frontend):
python scripts/with_server.py \
--server "cd backend && python server.py" --port 3000 \
--server "cd frontend && npm run dev" --port 5173 \
-- python your_automation.py
To create an automation script, include only Playwright logic (servers are managed automatically):
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True) # Always launch chromium in headless mode
page = browser.new_page()
page.goto('http://localhost:5173') # Server already running and ready
page.wait_for_load_state('networkidle') # CRITICAL: Wait for JS to execute
# ... your automation logic
browser.close()
Reconnaissance-Then-Action Pattern
Inspect rendered DOM:
page.screenshot(path='/tmp/inspect.png', full_page=True) content = page.content() page.locator('button').all()Identify selectors from inspection results
Execute actions using discovered selectors
Common Pitfall
❌ Don't inspect the DOM before waiting for networkidle on dynamic apps
✅ Do wait for page.wait_for_load_state('networkidle') before inspection
Best Practices
- Use bundled scripts as black boxes - To accomplish a task, consider whether one of the scripts available in
scripts/can help. These scripts handle common, complex workflows reliably without cluttering the context window. Use--helpto see usage, then invoke directly. - Use
sync_playwright()for synchronous scripts - Always close the browser when done
- Use descriptive selectors:
text=,role=, CSS selectors, or IDs - Add appropriate waits:
page.wait_for_selector()orpage.wait_for_timeout()
Reference Files
- examples/ - Examples showing common patterns:
element_discovery.py- Discovering buttons, links, and inputs on a pagestatic_html_automation.py- Using file:// URLs for local HTMLconsole_logging.py- Capturing console logs during automation
When to Use
This skill is applicable to execute the workflow or actions described in the overview.
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
FAQ
Common questions
Discussion
Questions & comments · 0
Sign In Sign in to leave a comment.