Install
$ agentstack add skill-jnzader-repoforge-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
Purpose
Patterns for browser-based UI verification using Playwright. Reliable, maintainable, fast E2E tests.
Selector Priority
| Priority | Selector | Example | Why | |----------|----------|---------|-----| | 1 | Role | getByRole('button', { name: 'Submit' }) | Accessible, semantic | | 2 | Label | getByLabel('Email') | Accessible, user-facing | | 3 | Test ID | getByTestId('submit-btn') | Stable, explicit | | 4 | Text | getByText('Sign in') | Readable but fragile | | 5 | CSS | page.locator('.btn-primary') | Last resort |
NEVER: XPath, auto-generated IDs, DOM structure selectors.
Page Object Model
export class LoginPage {
constructor(private page: Page) {}
get emailInput() { return this.page.getByLabel('Email'); }
get passwordInput() { return this.page.getByLabel('Password'); }
get submitButton() { return this.page.getByRole('button', { name: 'Sign in' }); }
async login(email: string, password: string) {
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.submitButton.click();
}
}
Visual Regression
test('dashboard renders correctly', async ({ page }) => {
await page.goto('/dashboard');
await page.waitForLoadState('networkidle');
await expect(page).toHaveScreenshot('dashboard.png', { maxDiffPixelRatio: 0.01 });
});
Network Interception
test('handles API errors', async ({ page }) => {
await page.route('**/api/users', route =>
route.fulfill({ status: 500, body: 'Server Error' })
);
await page.goto('/users');
await expect(page.getByText('Something went wrong')).toBeVisible();
});
Anti-Flakiness
- Wait for state, not time — never
page.waitForTimeout() - Isolate tests — fresh context per test
- Web-first assertions —
expect(locator).toBeVisible()auto-retries - Mock external APIs
- CI retries:
retries: 2in config
Critical Rules
- NEVER use
page.waitForTimeout()— wait for specific conditions - ALWAYS use Page Object Model for pages with 3+ interactions
- Selectors MUST follow priority: role > label > testid > text > CSS
- Visual regression MUST set
maxDiffPixelRatio - E2E tests MUST NOT depend on seed data
- ALWAYS use
--trace on-first-retryin CI
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: JNZader
- Source: JNZader/repoforge
- License: MIT
- Homepage: https://repoforge.javierzader.com
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.