Install
$ agentstack add skill-lucface-claude-skills-webapp-testing ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Web Application Testing
Test local web applications using browser automation.
Tool Selection
| Use Case | Tool | Why | |----------|------|-----| | AI agent browser interaction | agent-browser | AI-optimized refs, low token cost | | Automated test suites (CI/CD) | Playwright | Rich assertions, parallelization | | PDF generation from HTML | Puppeteer | Specialized PDF APIs | | Visual regression testing | Playwright | Screenshot comparison |
Default: Use agent-browser for interactive testing, Playwright for test suites.
Decision Tree
- Is this AI-driven exploration or automated test suite?
- AI exploration: Use
agent-browser(refs system, AI-optimized) - Automated tests: Use Playwright (assertions, CI/CD)
- Is target static HTML or dynamic webapp?
- Static: Direct page load and inspect
- Dynamic: Use
with_server.pyhelper for server lifecycle
- Do you need visual or programmatic testing?
- Visual: Screenshots and visual comparison
- Programmatic: DOM queries and assertions
Agent-Browser (AI Agent Testing)
Install globally: bun add -g agent-browser
Quick Start
# Navigate and get AI-optimized snapshot
agent-browser navigate "http://localhost:3000"
agent-browser snapshot
# Interact using refs from snapshot
agent-browser click @e3
agent-browser fill @e5 "test@example.com"
agent-browser snapshot # Verify changes
The Refs Advantage
After snapshot, each element gets a unique ref (@e1, @e2):
- Deterministic: No CSS selector guessing
- Fast: No DOM re-querying
- AI-friendly: LLMs parse refs reliably
Common Patterns
# Login flow
agent-browser navigate "http://localhost:3000/login"
agent-browser snapshot
agent-browser fill @e2 "user@example.com"
agent-browser fill @e3 "password123"
agent-browser click @e4
agent-browser wait-for "Dashboard"
agent-browser snapshot
# Form submission
agent-browser navigate "http://localhost:3000/contact"
agent-browser snapshot
agent-browser fill @e1 "John Doe"
agent-browser fill @e2 "john@example.com"
agent-browser type @e3 "Hello, this is my message"
agent-browser click @e4 # Submit button
agent-browser wait-for "Thank you"
See ~/.claude/context/agent-browser.md for full command reference.
Playwright (Automated Test Suites)
Setup
bun add -D playwright @playwright/test
bunx playwright install
Basic Test Structure
import { test, expect } from '@playwright/test';
test('homepage loads correctly', async ({ page }) => {
await page.goto('http://localhost:3000');
// Wait for dynamic content
await page.waitForLoadState('networkidle');
// Check title
await expect(page).toHaveTitle(/My App/);
// Check element exists
await expect(page.locator('h1')).toContainText('Welcome');
});
Critical Practice
Always wait for network idle on dynamic apps:
await page.waitForLoadState('networkidle');
This prevents testing incomplete page states caused by ongoing JavaScript execution.
Element Selection
// By text
await page.getByText('Submit').click();
// By role
await page.getByRole('button', { name: 'Submit' }).click();
// By test ID (recommended)
await page.getByTestId('submit-button').click();
// By CSS selector
await page.locator('.submit-btn').click();
// By placeholder
await page.getByPlaceholder('Enter email').fill('test@example.com');
Screenshots
// Full page
await page.screenshot({ path: 'screenshot.png', fullPage: true });
// Specific element
await page.locator('.header').screenshot({ path: 'header.png' });
// Hide elements
await page.screenshot({
path: 'clean.png',
mask: [page.locator('.ads')]
});
Form Interaction
// Fill form
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Password').fill('secret123');
// Select dropdown
await page.getByLabel('Country').selectOption('US');
// Checkbox
await page.getByLabel('Remember me').check();
// Submit
await page.getByRole('button', { name: 'Sign In' }).click();
API Mocking
await page.route('**/api/users', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify([{ id: 1, name: 'Test User' }])
});
});
Console Logging
page.on('console', msg => {
console.log(`Browser console [${msg.type()}]: ${msg.text()}`);
});
page.on('pageerror', err => {
console.error('Page error:', err.message);
});
Testing Dynamic Content
// Wait for element to appear
await page.waitForSelector('.loading', { state: 'hidden' });
await page.waitForSelector('.content', { state: 'visible' });
// Wait for specific text
await page.waitForFunction(() =>
document.body.innerText.includes('Data loaded')
);
// Wait for network request
const responsePromise = page.waitForResponse('**/api/data');
await page.click('#load-button');
const response = await responsePromise;
Workflow Pattern
- Reconnaissance: Capture screenshots, inspect DOM
- Identify: Find selectors from rendered state
- Execute: Automate using discovered selectors
- Verify: Assert expected outcomes
// Reconnaissance
await page.screenshot({ path: 'before.png' });
console.log(await page.content());
// Find and interact
const buttons = await page.locator('button').all();
for (const btn of buttons) {
console.log(await btn.textContent());
}
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Lucface
- Source: Lucface/claude-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.