
Webapp Testing
Run headless Playwright smoke checks on a URL and get JSON health plus optional screenshots before you ship or iterate on a web app.
Overview
Webapp-testing is an agent skill most often used in Ship (also Validate and Build) that runs headless Playwright checks on a URL and returns JSON page health plus optional screenshots.
Install
npx skills add https://github.com/vudovn/antigravity-kit --skill webapp-testingWhat is this skill?
- Bundled `playwright_runner.py` returns JSON with URL, timestamp, status, page info, and optional screenshot path
- Headless Chromium at 1280×720 for consistent solo-builder smoke runs without manual browser babysitting
- Clear install path when Playwright is missing: pip install playwright and playwright install chromium
- Screenshots land in the OS temp directory so disk clutter stays low during quick checks
- Stdout/stderr UTF-8 handling on Windows avoids broken Unicode in agent logs
- Headless Chromium viewport固定为 1280×720
- JSON output includes url, timestamp, status, page info, and optional screenshot path
- Screenshots saved to system temp directory
Adoption & trust: 1 installs on skills.sh; 7.7k GitHub stars; 2/3 security scanners passed (skills.sh audits); trending (+100% hot-view momentum).
What problem does it solve?
You have a live or local web app URL but no quick, agent-friendly way to confirm it actually loads and looks right in a real browser before you ship or keep coding blind.
Who is it for?
Solo builders smoke-testing dev/staging URLs from an agent after UI or routing changes, with minimal setup beyond Python and Playwright.
Skip if: Teams needing full CI pipelines, cross-browser matrices, authenticated flows, or performance/load benchmarks—use a dedicated E2E or observability stack instead.
When should I use this skill?
You have a web app URL (local or deployed) and need a quick Playwright browser test with JSON results or a screenshot.
What do I get? / Deliverables
After the run you get structured JSON with page status and metadata (and a screenshot path when requested) so you can fix failures or proceed to deeper tests and deploy.
- JSON report with page info and health/status fields
- Optional PNG screenshot path in temp directory
- Actionable error payload when Playwright is not installed
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Ship is the canonical shelf because the skill validates running web apps in a real browser—exactly what solo builders do in the testing subphase before release. Testing subphase fits automated browser runs, page health signals, and screenshot capture rather than unit-test frameworks alone.
Where it fits
Hit the prototype deploy URL to confirm the landing route renders before you commit to a full build scope.
After a layout or router change, run the runner against localhost to catch blank pages before opening a PR.
Smoke-test staging with optional screenshot right before you tag a release or hand off to manual QA.
Re-check a production URL after a hotfix when you need a fast browser-level signal without logging into monitoring.
How it compares
Lightweight Playwright smoke JSON from the agent, not a hosted browser grid or a full Cypress/Playwright test suite in CI.
Common Questions / FAQ
Who is webapp-testing for?
Solo and indie builders shipping web apps with AI coding agents who want a fast Playwright smoke check without standing up a full test harness first.
When should I use webapp-testing?
Use it in Validate when a prototype URL needs a quick load check; in Build after frontend or routing edits; and in Ship before release or when debugging production-like URLs. Invoke when you have a URL and need JSON the agent can act on.
Is webapp-testing safe to install?
It runs local browser automation and may fetch arbitrary URLs you pass in—review the Security Audits panel on this page and only point it at URLs you trust in dev or staging.
SKILL.md
READMESKILL.md - Webapp Testing
#!/usr/bin/env python3 """ Skill: webapp-testing Script: playwright_runner.py Purpose: Run basic Playwright browser tests Usage: python playwright_runner.py <url> [--screenshot] Output: JSON with page info, health status, and optional screenshot path Note: Requires playwright (pip install playwright && playwright install chromium) Screenshots: Saved to system temp directory (auto-cleaned by OS) """ import sys import json import os import tempfile from datetime import datetime # Fix Windows console encoding for Unicode output try: sys.stdout.reconfigure(encoding='utf-8', errors='replace') sys.stderr.reconfigure(encoding='utf-8', errors='replace') except AttributeError: pass # Python < 3.7 try: from playwright.sync_api import sync_playwright PLAYWRIGHT_AVAILABLE = True except ImportError: PLAYWRIGHT_AVAILABLE = False def run_basic_test(url: str, take_screenshot: bool = False) -> dict: """Run basic browser test on URL.""" if not PLAYWRIGHT_AVAILABLE: return { "error": "Playwright not installed", "fix": "pip install playwright && playwright install chromium" } result = { "url": url, "timestamp": datetime.now().isoformat(), "status": "pending" } try: with sync_playwright() as p: browser = p.chromium.launch(headless=True) context = browser.new_context( viewport={"width": 1280, "height": 720}, user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" ) page = context.new_page() # Navigate response = page.goto(url, wait_until="networkidle", timeout=30000) # Basic info result["page"] = { "title": page.title(), "url": page.url, "status_code": response.status if response else None } # Health checks result["health"] = { "loaded": response.ok if response else False, "has_title": bool(page.title()), "has_h1": page.locator("h1").count() > 0, "has_links": page.locator("a").count() > 0, "has_images": page.locator("img").count() > 0 } # Console errors console_errors = [] page.on("console", lambda msg: console_errors.append(msg.text) if msg.type == "error" else None) # Performance metrics result["performance"] = { "dom_content_loaded": page.evaluate("window.performance.timing.domContentLoadedEventEnd - window.performance.timing.navigationStart"), "load_complete": page.evaluate("window.performance.timing.loadEventEnd - window.performance.timing.navigationStart") } # Screenshot - uses system temp directory (cross-platform, auto-cleaned) if take_screenshot: # Cross-platform: Windows=%TEMP%, Linux/macOS=/tmp screenshot_dir = os.path.join(tempfile.gettempdir(), "maestro_screenshots") os.makedirs(screenshot_dir, exist_ok=True) screenshot_path = os.path.join(screenshot_dir, f"screenshot_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png") page.screenshot(path=screenshot_path, full_page=True) result["screenshot"] = screenshot_path result["screenshot_note"] = "Saved to temp directory (auto-cleaned by OS)" # Element counts result["elements"] = { "links": page.locator("a").count(), "buttons": page.locator("button").count(), "inputs": page.locator("input").count(), "images": page.locator("img").count(), "forms": page.locator("form").count() } browser.close