webapp-testing — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited webapp-testing (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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.comSee 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.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.