{"id":"e7d1963e-7d6f-4c38-b0bb-d4badf519137","shortId":"VmuJkK","kind":"skill","title":"webapp-testing","tagline":"To test local web applications, write native Python Playwright scripts.","description":"# Web Application Testing\n\nTo test local web applications, write native Python Playwright scripts.\n\n**Helper Scripts Available**:\n- `scripts/with_server.py` - Manages server lifecycle (supports multiple servers)\n\n**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.\n\n## Decision Tree: Choosing Your Approach\n\n```\nUser 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```\n\n## Example: Using with_server.py\n\nTo start a server, run `--help` first, then use the helper:\n\n**Single server:**\n```bash\npython scripts/with_server.py --server \"npm run dev\" --port 5173 -- python your_automation.py\n```\n\n**Multiple servers (e.g., backend + frontend):**\n```bash\npython scripts/with_server.py \\\n  --server \"cd backend && python server.py\" --port 3000 \\\n  --server \"cd frontend && npm run dev\" --port 5173 \\\n  -- python your_automation.py\n```\n\nTo create an automation script, include only Playwright logic (servers are managed automatically):\n```python\nfrom 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```\n\n## Reconnaissance-Then-Action Pattern\n\n1. **Inspect rendered DOM**:\n   ```python\n   page.screenshot(path='/tmp/inspect.png', full_page=True)\n   content = page.content()\n   page.locator('button').all()\n   ```\n\n2. **Identify selectors** from inspection results\n\n3. **Execute actions** using discovered selectors\n\n## Common Pitfall\n\n❌ **Don't** inspect the DOM before waiting for `networkidle` on dynamic apps\n✅ **Do** wait for `page.wait_for_load_state('networkidle')` before inspection\n\n## Best Practices\n\n- **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 `--help` to see usage, then invoke directly. \n- Use `sync_playwright()` for synchronous scripts\n- Always close the browser when done\n- Use descriptive selectors: `text=`, `role=`, CSS selectors, or IDs\n- Add appropriate waits: `page.wait_for_selector()` or `page.wait_for_timeout()`\n\n## Reference Files\n\n- **examples/** - Examples showing common patterns:\n  - `element_discovery.py` - Discovering buttons, links, and inputs on a page\n  - `static_html_automation.py` - Using file:// URLs for local HTML\n  - `console_logging.py` - Capturing console logs during automation\n\n## When to Use\nThis skill is applicable to execute the workflow or actions described in the overview.\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.","tags":["webapp","testing","antigravity","awesome","skills","sickn33","agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding","ai-workflows"],"capabilities":["skill","source-sickn33","skill-webapp-testing","topic-agent-skills","topic-agentic-skills","topic-ai-agent-skills","topic-ai-agents","topic-ai-coding","topic-ai-workflows","topic-antigravity","topic-antigravity-skills","topic-claude-code","topic-claude-code-skills","topic-codex-cli","topic-codex-skills"],"categories":["antigravity-awesome-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/sickn33/antigravity-awesome-skills/webapp-testing","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add sickn33/antigravity-awesome-skills","source_repo":"https://github.com/sickn33/antigravity-awesome-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 34404 github stars · SKILL.md body (3,996 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T00:51:58.126Z","embedding":null,"createdAt":"2026-04-18T21:47:27.455Z","updatedAt":"2026-04-22T00:51:58.126Z","lastSeenAt":"2026-04-22T00:51:58.126Z","tsv":"'/tmp/inspect.png':302 '1':153,295 '2':159,311 '3':165,317 '3000':218 '4':171 '5173':201,226,269 'abslut':65 'accomplish':356 'action':152,173,293,319,461 'add':411 'alreadi':133,271 'alway':37,258,396 'api':245 'app':336 'applic':8,15,21,455 'approach':101 'appropri':412 'ask':499 'autom':232,287,448 'automat':241 'avail':29,365 'backend':207,214 'bash':193,209 'best':347 'black':87,353 'black-box':86 'boundari':507 'box':88,354 'browser':254,399 'browser.close':289 'browser.new':265 'bundl':350 'button':309,430 'call':83 'captur':444 'cd':213,220 'choos':99 'chromium':260 'clarif':501 'clear':474 'close':397 'clutter':378 'common':323,373,426 'complex':374 'consid':359 'consol':445 'console_logging.py':443 'content':306 'context':77,95,380 'creat':230 'criteria':510 'critic':280 'css':407 'custom':62 'decis':97 'describ':462,478 'descript':403 'dev':199,224 'direct':84,112,389 'discov':175,321,429 'dom':164,298,329 'done':401 'dynam':125,128,335 'e.g':206 'element_discovery.py':428 'environ':490 'environment-specif':489 'exampl':177,423,424 'execut':172,285,318,457 'exist':80 'expert':495 'fails/incomplete':122 'file':111,422 'find':59 'first':42,57,186 'frontend':208,221 'full':303 'handl':372 'headless':256,262 'help':41,139,185,369,383 'helper':27,143,190 'html':107,110,442 'id':410 'identifi':114,166,312 'import':246 'includ':234 'ingest':92 'input':433,504 'inspect':163,296,315,327,346 'invok':388 'js':283 'larg':72 'launch':259 'lifecycl':33 'limit':466 'link':431 'load':277,342 'local':6,19,441 'localhost':268 'log':446 'logic':237,288 'manag':31,240 'match':475 'miss':512 'mode':263 'multipl':35,204 'nativ':10,23 'navig':154 'necessari':66 'networkidl':158,279,333,344 'npm':197,222 'one':361 'output':484 'overview':465 'p':253 'p.chromium.launch':255 'page':264,266,304,436 'page.content':307 'page.goto':267 'page.locator':308 'page.screenshot':300 'page.wait':275,340,414,418 'path':301 'pattern':294,427 'permiss':505 'pitfal':324 'playwright':12,25,118,146,236,248,251,392 'playwright.sync':244 'pollut':75 'port':200,217,225 'practic':348 'python':11,24,137,194,202,210,215,227,242,299 'rather':90 'read':48,109 'readi':274 'reconnaiss':150,291 'reconnaissance-then-act':149,290 'refer':421 'reliabl':376 'render':169,297 'requir':503 'result':316 'review':496 'role':406 'run':38,54,134,136,184,198,223,272 'safeti':506 'scope':477 'screenshot':161 'script':13,26,28,39,56,68,89,119,147,233,351,364,367,371,395 'scripts/with_server.py':30,138,195,211 'see':44,385 'selector':115,121,167,176,313,322,404,408,416 'server':32,36,132,183,192,196,205,212,219,238,270 'server.py':216 'show':425 'simplifi':145 'singl':191 'skill':453,469 'skill-webapp-testing' 'solut':63 'sourc':50 'source-sickn33' 'specif':491 'start':181 'state':170,278,343 'static':106 'static_html_automation.py':437 'stop':497 'substitut':487 'success':116,509 'support':34 'sync':247,250,391 'synchron':394 'take':160 'task':103,358,473 'test':3,5,16,18,493 'text':405 'thus':74 'timeout':420 'topic-agent-skills' 'topic-agentic-skills' 'topic-ai-agent-skills' 'topic-ai-agents' 'topic-ai-coding' 'topic-ai-workflows' 'topic-antigravity' 'topic-antigravity-skills' 'topic-claude-code' 'topic-claude-code-skills' 'topic-codex-cli' 'topic-codex-skills' 'treat':123,482 'tree':98 'tri':53 'true':257,305 'url':439 'usag':45,386 'use':120,141,178,188,320,349,382,390,402,438,451,467 'user':102 'valid':492 'wait':156,281,331,338,413 'web':7,14,20 'webapp':2,129 'webapp-test':1 'whether':360 'window':78,96,381 'with_server.py':179 'without':377 'workflow':375,459 'write':9,22,117,144 'yes':108,148 'your_automation.py':203,228","prices":[{"id":"929426f2-360a-464f-904c-a0ae910961ed","listingId":"e7d1963e-7d6f-4c38-b0bb-d4badf519137","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"sickn33","category":"antigravity-awesome-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T21:47:27.455Z"}],"sources":[{"listingId":"e7d1963e-7d6f-4c38-b0bb-d4badf519137","source":"github","sourceId":"sickn33/antigravity-awesome-skills/webapp-testing","sourceUrl":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/webapp-testing","isPrimary":false,"firstSeenAt":"2026-04-18T21:47:27.455Z","lastSeenAt":"2026-04-22T00:51:58.126Z"}],"details":{"listingId":"e7d1963e-7d6f-4c38-b0bb-d4badf519137","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"sickn33","slug":"webapp-testing","github":{"repo":"sickn33/antigravity-awesome-skills","stars":34404,"topics":["agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding","ai-workflows","antigravity","antigravity-skills","claude-code","claude-code-skills","codex-cli","codex-skills","cursor","cursor-skills","developer-tools","gemini-cli","gemini-skills","kiro","mcp","skill-library"],"license":"mit","html_url":"https://github.com/sickn33/antigravity-awesome-skills","pushed_at":"2026-04-21T16:43:40Z","description":"Installable GitHub library of 1,400+ agentic skills for Claude Code, Cursor, Codex CLI, Gemini CLI, Antigravity, and more. Includes installer CLI, bundles, workflows, and official/community skill collections.","skill_md_sha":"fa43d86153f14ba395ed5d299e47d80394917ddb","skill_md_path":"skills/webapp-testing/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/webapp-testing"},"layout":"multi","source":"github","category":"antigravity-awesome-skills","frontmatter":{"name":"webapp-testing","description":"To test local web applications, write native Python Playwright scripts."},"skills_sh_url":"https://skills.sh/sickn33/antigravity-awesome-skills/webapp-testing"},"updatedAt":"2026-04-22T00:51:58.126Z"}}