{"slug":"webapp-testing-3","title":"webapp-testing","summary":"Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-15T18:24:39.940791Z","repo":{"url":"https://github.com/shajith003/awesome-claude-skills","stars":25,"forks":2,"license":null,"updatedAt":"2026-09-28T07:09:32Z"},"bodyHtml":"<hr>\n<h2>name: webapp-testing\ndescription: Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.\nlicense: Complete terms in LICENSE.txt</h2>\n<h1>Web Application Testing</h1>\n<p>To test local web applications, write native Python Playwright scripts.</p>\n<p><strong>Helper Scripts Available</strong>:</p>\n<ul>\n<li><code>scripts/with_server.py</code> - Manages server lifecycle (supports multiple servers)</li>\n</ul>\n<p><strong>Always run scripts with <code>--help</code> first</strong> 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.</p>\n<h2>Decision Tree: Choosing Your Approach</h2>\n<pre><code>User task → Is it static HTML?\n    ├─ Yes → Read HTML file directly to identify selectors\n    │         ├─ Success → Write Playwright script using selectors\n    │         └─ Fails/Incomplete → Treat as dynamic (below)\n    │\n    └─ No (dynamic webapp) → Is the server already running?\n        ├─ No → Run: python scripts/with_server.py --help\n        │        Then use the helper + write simplified Playwright script\n        │\n        └─ Yes → Reconnaissance-then-action:\n            1. Navigate and wait for networkidle\n            2. Take screenshot or inspect DOM\n            3. Identify selectors from rendered state\n            4. Execute actions with discovered selectors\n</code></pre>\n<h2>Example: Using with_server.py</h2>\n<p>To start a server, run <code>--help</code> first, then use the helper:</p>\n<p><strong>Single server:</strong></p>\n<pre><code>python scripts/with_server.py --server \"npm run dev\" --port 5173 -- python your_automation.py\n</code></pre>\n<p><strong>Multiple servers (e.g., backend + frontend):</strong></p>\n<pre><code>python scripts/with_server.py \\\n  --server \"cd backend &amp;&amp; python server.py\" --port 3000 \\\n  --server \"cd frontend &amp;&amp; npm run dev\" --port 5173 \\\n  -- python your_automation.py\n</code></pre>\n<p>To create an automation script, include only Playwright logic (servers are managed automatically):</p>\n<pre><code>from playwright.sync_api import sync_playwright\n\nwith sync_playwright() as p:\n    browser = p.chromium.launch(headless=True) # Always launch chromium in headless mode\n    page = browser.new_page()\n    page.goto('http://localhost:5173') # Server already running and ready\n    page.wait_for_load_state('networkidle') # CRITICAL: Wait for JS to execute\n    # ... your automation logic\n    browser.close()\n</code></pre>\n<h2>Reconnaissance-Then-Action Pattern</h2>\n<ol>\n<li><p><strong>Inspect rendered DOM</strong>:</p>\n<pre><code>page.screenshot(path='/tmp/inspect.png', full_page=True)\ncontent = page.content()\npage.locator('button').all()\n</code></pre>\n</li>\n<li><p><strong>Identify selectors</strong> from inspection results</p>\n</li>\n<li><p><strong>Execute actions</strong> using discovered selectors</p>\n</li>\n</ol>\n<h2>Common Pitfall</h2>\n<p>❌ <strong>Don't</strong> inspect the DOM before waiting for <code>networkidle</code> on dynamic apps\n✅ <strong>Do</strong> wait for <code>page.wait_for_load_state('networkidle')</code> before inspection</p>\n<h2>Best Practices</h2>\n<ul>\n<li><strong>Use bundled scripts as black boxes</strong> - To accomplish a task, consider whether one of the scripts available in <code>scripts/</code> can help. These scripts handle common, complex workflows reliably without cluttering the context window. Use <code>--help</code> to see usage, then invoke directly.</li>\n<li>Use <code>sync_playwright()</code> for synchronous scripts</li>\n<li>Always close the browser when done</li>\n<li>Use descriptive selectors: <code>text=</code>, <code>role=</code>, CSS selectors, or IDs</li>\n<li>Add appropriate waits: <code>page.wait_for_selector()</code> or <code>page.wait_for_timeout()</code></li>\n</ul>\n<h2>Reference Files</h2>\n<ul>\n<li><strong>examples/</strong> - Examples showing common patterns:\n<ul>\n<li><code>element_discovery.py</code> - Discovering buttons, links, and inputs on a page</li>\n<li><code>static_html_automation.py</code> - Using file:// URLs for local HTML</li>\n<li><code>console_logging.py</code> - Capturing console logs during automation</li>\n</ul>\n</li>\n</ul>\n","files":[{"path":"examples/console_logging.py","sizeBytes":1027,"isText":true},{"path":"examples/element_discovery.py","sizeBytes":1463,"isText":true},{"path":"examples/static_html_automation.py","sizeBytes":953,"isText":true},{"path":"LICENSE.txt","sizeBytes":11357,"isText":true},{"path":"scripts/with_server.py","sizeBytes":3693,"isText":true},{"path":"SKILL.md","sizeBytes":3913,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-15T18:27:32.89775Z","sha256":"E7E20F8C89595CF1C0045038BEB41F214C5711E0D318F42B55B001DF8ABD934B","sizeBytes":9418},"review":null,"source":{"repositoryUrl":"https://github.com/shajith003/awesome-claude-skills","path":"webapp-testing","license":null,"commit":"619018723747e29c5c4853afea46e49becdf765f","subtreeSha":"04E9AE669349D1FD26D9CD7E94A6A3BAEFF4E4B1F2F4EDAD2BA80604068BB59D","lastSyncedAt":"2026-09-28T20:56:13.798279Z"},"reviewedAt":"2026-09-15T18:34:32.398685Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/shajith003/awesome-claude-skills/tree/main/webapp-testing"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install shajith003-awesome-claude-skills@llmmart"},{"target":"git","command":"git clone https://github.com/shajith003/awesome-claude-skills.git"}]}