prowler-cloud/prowler/skills/playwright/SKILL.md
playwright
Playwright E2E testing patterns. Trigger: When writing Playwright E2E tests (Page Object Model, selectors, MCP exploration workflow). For Prowler-specific UI conventions under ui/tests, also use prowler-test-ui.
- Source repository stars
- 14,533
- Declared platforms
- 0
- Static risk flags
- 1
- Last source update
- 2026-08-04
- Source checked
- 2026-08-05
Decision brief
What it does—and where it fits
⚠️ If you have Playwright MCP tools, ALWAYS use them BEFORE creating any test:
Not for
- Tasks that require unconfirmed production actions or broad system permissions.
- Environments where the pinned source and install steps cannot be inspected.
Compatibility matrix
Platform support, with evidence labels
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
Inspect first. Install second.
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/prowler-cloud/prowler --skill "skills/playwright"Inspect the Agent Skill "playwright" from https://github.com/prowler-cloud/prowler/blob/87bc1eceae6213e195a38b9337a03454f9e7e742/skills/playwright/SKILL.md at commit 87bc1eceae6213e195a38b9337a03454f9e7e742. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
What the source asks the agent to do
- 01
MCP Workflow (MANDATORY If Available)
⚠️ If you have Playwright MCP tools, ALWAYS use them BEFORE creating any test:
Navigate to target pageTake snapshot to see page structure and elementsInteract with forms/elements to verify exact user flow - 02
Key verification points:
{Assertion 1}
{Assertion 1}{Assertion 2}- {Assertion 1} - {Assertion 2} - 03
File Structure
File Naming: - ✅ sign-up.spec.ts (all sign-up tests) - ✅ sign-up-page.ts (page object) - ✅ sign-up.md (documentation) - ❌ sign-up-critical-path.spec.ts (WRONG - no separate files) - ❌ sign-up-validation.spec.ts (WRONG)
✅ sign-up.spec.ts (all sign-up tests)✅ sign-up-page.ts (page object)✅ sign-up.md (documentation) - 04
Selector Priority (REQUIRED)
Review the “Selector Priority (REQUIRED)” section in the pinned source before continuing.
Review and apply the “Selector Priority (REQUIRED)” source section. - 05
Scope Detection (ASK IF AMBIGUOUS)
Examples: - "Create a test for user sign-up" → ONE test only - "Generate E2E tests for login page" → Full suite - "Add a test to verify form validation" → ONE test to existing spec
"Create a test for user sign-up" → ONE test only"Generate E2E tests for login page" → Full suite"Add a test to verify form validation" → ONE test to existing spec
Permission review
Static risk signals and limitations
Runs scripts
The documentation asks the agent to run terminal commands or scripts.
npx playwright test # Run allRuns scripts
The documentation asks the agent to run terminal commands or scripts.
npx playwright test --grep "login" # Filter by nameEvidence record
Why each signal appears
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 88/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 14,533 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Provenance and original SKILL.md
- Repository
- prowler-cloud/prowler
- Skill path
- skills/playwright/SKILL.md
- Commit
- 87bc1eceae6213e195a38b9337a03454f9e7e742
- License
- Apache-2.0
- Collected
- 2026-08-05
- Default branch
- master
View the original SKILL.md
MCP Workflow (MANDATORY If Available)
⚠️ If you have Playwright MCP tools, ALWAYS use them BEFORE creating any test:
- Navigate to target page
- Take snapshot to see page structure and elements
- Interact with forms/elements to verify exact user flow
- Take screenshots to document expected states
- Verify page transitions through complete flow (loading, success, error)
- Document actual selectors from snapshots (use real refs and labels)
- Only after exploring create test code with verified selectors
If MCP NOT available: Proceed with test creation based on docs and code analysis.
Why This Matters:
- ✅ Precise tests - exact steps needed, no assumptions
- ✅ Accurate selectors - real DOM structure, not imagined
- ✅ Real flow validation - verify journey actually works
- ✅ Avoid over-engineering - minimal tests for what exists
- ✅ Prevent flaky tests - real exploration = stable tests
- ❌ Never assume how UI "should" work
File Structure
tests/
├── base-page.ts # Parent class for ALL pages
├── helpers.ts # Shared utilities
└── {page-name}/
├── {page-name}-page.ts # Page Object Model
├── {page-name}.spec.ts # ALL tests here (NO separate files!)
└── {page-name}.md # Test documentation
File Naming:
- ✅
sign-up.spec.ts(all sign-up tests) - ✅
sign-up-page.ts(page object) - ✅
sign-up.md(documentation) - ❌
sign-up-critical-path.spec.ts(WRONG - no separate files) - ❌
sign-up-validation.spec.ts(WRONG)
Selector Priority (REQUIRED)
// 1. BEST - getByRole for interactive elements
this.submitButton = page.getByRole("button", { name: "Submit" });
this.navLink = page.getByRole("link", { name: "Dashboard" });
// 2. BEST - getByLabel for form controls
this.emailInput = page.getByLabel("Email");
this.passwordInput = page.getByLabel("Password");
// 3. SPARINGLY - getByText for static content only
this.errorMessage = page.getByText("Invalid credentials");
this.pageTitle = page.getByText("Welcome");
// 4. LAST RESORT - getByTestId when above fail
this.customWidget = page.getByTestId("date-picker");
// ❌ AVOID fragile selectors
this.button = page.locator(".btn-primary"); // NO
this.input = page.locator("#email"); // NO
Scope Detection (ASK IF AMBIGUOUS)
| User Says | Action |
|---|---|
| "a test", "one test", "new test", "add test" | Create ONE test() in existing spec |
| "comprehensive tests", "all tests", "test suite", "generate tests" | Create full suite |
Examples:
- "Create a test for user sign-up" → ONE test only
- "Generate E2E tests for login page" → Full suite
- "Add a test to verify form validation" → ONE test to existing spec
Page Object Pattern
import { Page, Locator, expect } from "@playwright/test";
// BasePage - ALL pages extend this
export class BasePage {
constructor(protected page: Page) {}
async goto(path: string): Promise<void> {
await this.page.goto(path);
await this.page.waitForLoadState("networkidle");
}
// Common methods go here (see Refactoring Guidelines)
async waitForNotification(): Promise<void> {
await this.page.waitForSelector('[role="status"]');
}
async verifyNotificationMessage(message: string): Promise<void> {
const notification = this.page.locator('[role="status"]');
await expect(notification).toContainText(message);
}
}
// Page-specific implementation
export interface LoginData {
email: string;
password: string;
}
export class LoginPage extends BasePage {
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
constructor(page: Page) {
super(page);
this.emailInput = page.getByLabel("Email");
this.passwordInput = page.getByLabel("Password");
this.submitButton = page.getByRole("button", { name: "Sign in" });
}
async goto(): Promise<void> {
await super.goto("/login");
}
async login(data: LoginData): Promise<void> {
await this.emailInput.fill(data.email);
await this.passwordInput.fill(data.password);
await this.submitButton.click();
}
async verifyCriticalOutcome(): Promise<void> {
await expect(this.page).toHaveURL("/dashboard");
}
}
Page Object Reuse (CRITICAL)
Always check existing page objects before creating new ones!
// ✅ GOOD: Reuse existing page objects
import { SignInPage } from "../sign-in/sign-in-page";
import { HomePage } from "../home/home-page";
test("User can sign up and login", async ({ page }) => {
const signUpPage = new SignUpPage(page);
const signInPage = new SignInPage(page); // REUSE
const homePage = new HomePage(page); // REUSE
await signUpPage.signUp(userData);
await homePage.verifyPageLoaded(); // REUSE method
await homePage.signOut(); // REUSE method
await signInPage.login(credentials); // REUSE method
});
// ❌ BAD: Recreating existing functionality
export class SignUpPage extends BasePage {
async logout() { /* ... */ } // ❌ HomePage already has this
async login() { /* ... */ } // ❌ SignInPage already has this
}
Guidelines:
- Check
tests/for existing page objects first - Import and reuse existing pages
- Create page objects only when page doesn't exist
- If test requires multiple pages, ensure all page objects exist (create if needed)
Refactoring Guidelines
Move to BasePage when
- ✅ Navigation helpers used by multiple pages (
waitForPageLoad(),getCurrentUrl()) - ✅ Common UI interactions (notifications, modals, theme toggles)
- ✅ Verification patterns repeated across pages (
isVisible(),waitForVisible()) - ✅ Error handling that applies to all pages
- ✅ Screenshot utilities for debugging
Move to helpers.ts when
- ✅ Test data generation (
generateUniqueEmail(),generateTestUser()) - ✅ Setup/teardown utilities (
createTestUser(),cleanupTestData()) - ✅ Custom assertions (
expectNotificationToContain()) - ✅ API helpers for test setup (
seedDatabase(),resetState()) - ✅ Time utilities (
waitForCondition(),retryAction())
Before (BAD):
// Repeated in multiple page objects
export class SignUpPage extends BasePage {
async waitForNotification(): Promise<void> {
await this.page.waitForSelector('[role="status"]');
}
}
export class SignInPage extends BasePage {
async waitForNotification(): Promise<void> {
await this.page.waitForSelector('[role="status"]'); // DUPLICATED!
}
}
After (GOOD):
// BasePage - shared across all pages
export class BasePage {
async waitForNotification(): Promise<void> {
await this.page.waitForSelector('[role="status"]');
}
}
// helpers.ts - data generation
export function generateUniqueEmail(): string {
return `test.${Date.now()}@example.com`;
}
export function generateTestUser() {
return {
name: "Test User",
email: generateUniqueEmail(),
password: "TestPassword123!",
};
}
Test Pattern with Tags
import { test, expect } from "@playwright/test";
import { LoginPage } from "./login-page";
test.describe("Login", () => {
test("User can login successfully",
{ tag: ["@critical", "@e2e", "@login", "@LOGIN-E2E-001"] },
async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login({ email: "[email protected]", password: "pass123" });
await expect(page).toHaveURL("/dashboard");
}
);
});
Tag Categories:
- Priority:
@critical,@high,@medium,@low - Type:
@e2e - Feature:
@signup,@signin,@dashboard - Test ID:
@SIGNUP-E2E-001,@LOGIN-E2E-002
Test Documentation Format ({page-name}.md)
### E2E Tests: {Feature Name}
**Suite ID:** `{SUITE-ID}`
**Feature:** {Feature description}
---
## Test Case: `{TEST-ID}` - {Test case title}
**Priority:** `{critical|high|medium|low}`
**Tags:**
- type → @e2e
- feature → @{feature-name}
**Description/Objective:** {Brief description}
**Preconditions:**
- {Prerequisites for test to run}
- {Required data or state}
### Flow Steps:
1. {Step 1}
2. {Step 2}
3. {Step 3}
### Expected Result:
- {Expected outcome 1}
- {Expected outcome 2}
### Key verification points:
- {Assertion 1}
- {Assertion 2}
### Notes:
- {Additional considerations}
Documentation Rules:
- ❌ NO general test running instructions
- ❌ NO file structure explanations
- ❌ NO code examples or tutorials
- ❌ NO troubleshooting sections
- ✅ Focus ONLY on specific test case
- ✅ Keep under 60 lines when possible
Commands
npx playwright test # Run all
npx playwright test --grep "login" # Filter by name
npx playwright test --ui # Interactive UI
npx playwright test --debug # Debug mode
npx playwright test tests/login/ # Run specific folder
Prowler-Specific Patterns
For Prowler UI E2E testing with authentication setup, environment variables, and test IDs, see:
- Documentation: references/prowler-e2e.md
Alternatives
Compare before choosing
openai/skills
playwright
Use when the task requires automating a real browser from the terminal (navigation, form filling, snapshots, screenshots, data extraction, UI-flow debugging) via `playwright-cli` or the bundled wrapper script.
mgiovani/cc-arsenal
team-review
Multi-agent review team: architecture, security, performance, testing, style, docs/UX, plus an adversary that cross-examines the other 6, for security-sensitive, architectural, or large PRs (15+ files) where a single-agent pass risks missing cross-cutting issues. Use for auth/payments/PII changes, schema/pattern changes, compliance sign-off, or when asked to 'get the review team on this' / 'multi-agent review' / 'thorough review before merge'. For a standard PR or a quick pre-merge check, use /r
github/awesome-copilot
screen-recording
Create annotated animated GIF demos and screen recordings for pull requests and documentation. Covers frame capture, timing, imageio-based GIF creation, and per-frame annotation workflows.
alirezarezvani/claude-skills
research-ops-skills
Use when planning, funding, scoping, or synthesizing enterprise research across workstreams — clinical study design, R&D program finance, market sizing/surveys, or product/user research. Triggers on "design this clinical study", "what sample size", "R&D budget", "burn rate", "capitalize or expense", "TAM SAM SOM", "market sizing", "survey design", "segment the market", "plan user interviews", "usability test", "synthesize research insights". Forks context to route to one of four Research-Operati