playwright-reviewing

Review Playwright E2E tests for best practices violations. Detects mocked app data, explicit timeouts, CSS selectors, skipped tests, and assertion anti-patterns. Use when reviewing Playwright PRs or auditing test quality.

16 stars

Best use case

playwright-reviewing is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Review Playwright E2E tests for best practices violations. Detects mocked app data, explicit timeouts, CSS selectors, skipped tests, and assertion anti-patterns. Use when reviewing Playwright PRs or auditing test quality.

Teams using playwright-reviewing should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/playwright-reviewing/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/testing-security/playwright-reviewing/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/playwright-reviewing/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How playwright-reviewing Compares

Feature / Agentplaywright-reviewingStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Review Playwright E2E tests for best practices violations. Detects mocked app data, explicit timeouts, CSS selectors, skipped tests, and assertion anti-patterns. Use when reviewing Playwright PRs or auditing test quality.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Playwright Code Review

## Purpose
Audit Playwright E2E tests for violations of best practices. Detects anti-patterns that cause flaky tests, hide bugs, or reduce maintainability.

## When NOT to Use
- Writing new tests (use `playwright-writing` skill instead)
- Unit test reviews (different patterns)
- API-only test reviews
- Non-Playwright E2E frameworks (Cypress, etc.)

---

## Review Workflow

### Step 1: Identify Playwright Test Files

```bash
# Find all Playwright test files
find . -name "*.spec.ts" -o -name "*.test.ts" | grep -v node_modules

# Or check specific directory
ls -la tests/e2e/ playwright/
```

### Step 2: Run Automated Violation Checks

Execute these checks in parallel for efficiency:

```bash
# === CRITICAL VIOLATIONS ===

# Find mocked application APIs (FORBIDDEN)
grep -rn "page.route('/api\|page.route(\"/api" --include="*.spec.ts" --include="*.test.ts"

# Find skipped tests (FORBIDDEN)
grep -rn "test.skip\|\.skip(\|test\.fixme" --include="*.spec.ts" --include="*.test.ts"

# Find commented-out tests
grep -rn "// test(\|// it(\|/\* test" --include="*.spec.ts" --include="*.test.ts"

# === HIGH PRIORITY VIOLATIONS ===

# Find waitForTimeout (FORBIDDEN)
grep -rn "waitForTimeout\|waitForTime" --include="*.spec.ts" --include="*.test.ts"

# Find CSS class selectors (FORBIDDEN)
grep -rn "\.locator('\.\|\.locator(\"\." --include="*.spec.ts" --include="*.test.ts"

# Find manual assertions without web-first (FORBIDDEN)
grep -rn "\.isVisible()).toBe\|\.isHidden()).toBe\|\.textContent()).toBe\|\.innerText()).toBe" --include="*.spec.ts" --include="*.test.ts"

# Find expect(await pattern (usually wrong)
grep -rn "expect(await.*\.isVisible\|expect(await.*\.isEnabled\|expect(await.*\.isChecked" --include="*.spec.ts" --include="*.test.ts"

# === MEDIUM PRIORITY CHECKS ===

# Find selectOption (may not work with Mantine)
grep -rn "\.selectOption(" --include="*.spec.ts" --include="*.test.ts"

# Find potential setTimeout/delay patterns
grep -rn "setTimeout\|new Promise.*resolve.*setTimeout" --include="*.spec.ts" --include="*.test.ts"
```

### Step 3: Manual Review

For each file, check:

1. **Locator Quality**
   - Are `getByRole`, `getByText`, `getByLabel` used?
   - Are CSS selectors avoided?
   - Is `data-testid` only used when necessary?

2. **Assertion Quality**
   - Are all assertions web-first (`await expect(locator).toBeVisible()`)?
   - No manual `isVisible()` / `textContent()` checks?

3. **Test Structure**
   - Is `beforeEach` used for common setup?
   - Are tests independent (no shared state)?
   - Is navigation handled properly?

4. **Mantine Components**
   - Are Mantine Selects handled with click pattern?
   - No `selectOption()` on Mantine components?

### Step 4: Report Findings

Use the output template below to report issues.

---

## Severity Classification

### CRITICAL (Must Fix Before Merge)

| Violation | Why It's Critical | Detection |
|-----------|-------------------|-----------|
| Mocked application API | Tests don't verify real behavior | `page.route('/api` |
| Skipped tests | Hides bugs, false confidence | `test.skip`, `.skip()` |
| Commented-out tests | Dead code, hidden failures | `// test(` |

### HIGH (Should Fix Before Merge)

| Violation | Why It's High Priority | Detection |
|-----------|------------------------|-----------|
| `waitForTimeout()` | Arbitrary delays cause flakiness | `waitForTimeout` |
| CSS class selectors | Fragile, break on styling changes | `.locator('.'` |
| Manual assertions | Race conditions, false positives | `isVisible()).toBe(true)` |
| `expect(await` pattern | Not web-first, misses auto-retry | `expect(await.*isVisible` |

### MEDIUM (Should Fix)

| Violation | Why It's Medium Priority | Detection |
|-----------|--------------------------|-----------|
| `selectOption` with Mantine | Won't work, test fails | Context review |
| Missing test isolation | Tests affect each other | No `beforeEach` |
| Poor locator choice | Less resilient to changes | `locator('#id')` |

### LOW (Suggestions)

| Suggestion | Benefit |
|------------|---------|
| Use `getByRole` over `getByTestId` | Better accessibility coverage |
| Add descriptive test names | Easier debugging |
| Group related tests in `describe` | Better organization |

---

## Critical Violation Details

### Mocked Application APIs

**FORBIDDEN:** Mocking YOUR application's API endpoints.

```typescript
// ❌ CRITICAL VIOLATION
await page.route('/api/users', route => route.fulfill({
  body: JSON.stringify([{ id: 1, name: 'Mock' }])
}));

// ❌ CRITICAL VIOLATION
await page.route('/api/products/**', route => route.fulfill({
  body: JSON.stringify({ price: 99.99 })
}));
```

**ALLOWED:** Mocking external third-party APIs only:
```typescript
// ✅ ACCEPTABLE - external service
await page.route('https://api.stripe.com/**', route => route.fulfill({ ... }));
```

**Review action:** Check if the mocked URL is YOUR API or an external service.

### Skipped Tests

**FORBIDDEN:** Using `.skip()` to hide failing tests.

```typescript
// ❌ CRITICAL VIOLATION
test.skip('checkout flow', async ({ page }) => { ... });

// ❌ CRITICAL VIOLATION
test('checkout flow', async ({ page }) => {
  test.skip(true, 'TODO: fix later');
});

// ❌ CRITICAL VIOLATION
test.fixme('broken test', async ({ page }) => { ... });
```

**Review action:** Require fix or removal. No exceptions without documented ticket.

---

## High Violation Details

### Explicit Timeouts

```typescript
// ❌ HIGH VIOLATION
await page.waitForTimeout(2000);
await page.waitForTimeout(500);

// ❌ HIGH VIOLATION
await new Promise(resolve => setTimeout(resolve, 1000));

// ✅ CORRECT - web-first assertion
await expect(page.getByText('Loaded')).toBeVisible();
```

### CSS Class Selectors

```typescript
// ❌ HIGH VIOLATION
page.locator('.btn-primary')
page.locator('.MuiButton-root')
page.locator('div.container > .item')

// ✅ CORRECT
page.getByRole('button', { name: 'Submit' })
page.getByTestId('submit-button')  // if disambiguation needed
```

### Manual Assertions

```typescript
// ❌ HIGH VIOLATION - no auto-wait/retry
expect(await page.locator('#status').isVisible()).toBe(true);
expect(await page.getByText('Hello').textContent()).toBe('Hello');

// ✅ CORRECT - web-first, auto-waits
await expect(page.getByTestId('status')).toBeVisible();
await expect(page.getByText('Hello')).toHaveText('Hello');
```

---

## Mantine Component Checks

### Select Components

```typescript
// ❌ HIGH VIOLATION - selectOption doesn't work with Mantine
await page.getByRole('combobox').selectOption('value');

// ✅ CORRECT pattern for Mantine Select
await page.locator('[data-testid="StatusSelect"]').click();
await page.locator('div[value="active"]').click();
```

**Review action:** If you see `selectOption`, check if it's a Mantine component.

---

## Review Output Template

```markdown
## Playwright Test Review: [File/PR Name]

### Summary
[1-2 sentence overview of findings]

### Critical Issues (Must Fix)
- [ ] **Mocked app API** - `tests/checkout.spec.ts:45` - Mocking `/api/cart`
- [ ] **Skipped test** - `tests/auth.spec.ts:23` - `test.skip('login flow')`

### High Priority (Should Fix)
- [ ] **waitForTimeout** - `tests/dashboard.spec.ts:67` - `waitForTimeout(2000)`
- [ ] **CSS selector** - `tests/form.spec.ts:34` - `.locator('.submit-btn')`
- [ ] **Manual assertion** - `tests/profile.spec.ts:89` - `isVisible()).toBe(true)`

### Medium Priority
- [ ] **selectOption on Mantine** - `tests/filters.spec.ts:56` - Review if Mantine component

### Passed Checks
- [x] No skipped tests
- [x] Web-first assertions used
- [x] User-facing locators preferred
- [x] Test isolation with beforeEach

### Recommendations
- [Optional improvements and suggestions]
```

---

## Quick Commands Reference

```bash
# Full audit - run all checks
grep -rn "waitForTimeout\|test\.skip\|\.skip(\|page\.route('/api\|\.locator('\.\|isVisible()).toBe" --include="*.spec.ts" --include="*.test.ts"

# Count violations by type
echo "=== waitForTimeout ===" && grep -c "waitForTimeout" **/*.spec.ts 2>/dev/null || echo "0"
echo "=== test.skip ===" && grep -c "test.skip\|\.skip(" **/*.spec.ts 2>/dev/null || echo "0"
echo "=== CSS selectors ===" && grep -c "\.locator('\." **/*.spec.ts 2>/dev/null || echo "0"
```

---

## Integration

**Related skills:**
- `playwright-writing` - Writing new tests (use for guidance)
- `run-tests` - Executing test suite
- `quality-check` - General code quality

**Cross-reference:** All rules in this review skill match those in `playwright-writing`.


---

## Related Agent

For comprehensive E2E testing guidance that coordinates this and other Playwright skills, use the **`playwright-e2e-expert`** agent.

Related Skills

reviewing-security

16
from diegosouzapw/awesome-omni-skill

Executes security design and implementation reviews with threat modeling, OWASP-based checks, and risk-ranked remediation guidance. Activates when reviewing security, threat modeling, checking for vulnerabilities, auditing auth flows, performing OWASP reviews, or assessing security posture. Does not handle code quality or test coverage (code-reviewer), writing production code (backend-developer or frontend-developer), or infrastructure deployment (devops).

qa-testing-playwright

16
from diegosouzapw/awesome-omni-skill

End-to-end web application testing with Playwright: scope control, stable selectors, parallelization/sharding, flake control, network mocking vs real services, visual testing tradeoffs, and CI/CD integration.

playwright

16
from diegosouzapw/awesome-omni-skill

Playwright E2E testing, page objects, fixtures, visual regression, accessibility testing, and CI integration patterns.

playwright-visual-regression

16
from diegosouzapw/awesome-omni-skill

Playwright browser automation patterns for E2E testing, visual regression, screenshot capture, and accessibility validation. Use when implementing or debugging browser-based tests.

playwright-test

16
from diegosouzapw/awesome-omni-skill

Generate robust, zero-flakiness Playwright E2E tests following OpenMetadata patterns. Creates comprehensive test files with proper waits, API validation, multi-role permissions, and complete entity lifecycle management.

Playwright E2E Testing

16
from diegosouzapw/awesome-omni-skill

Comprehensive Playwright end-to-end testing patterns with Page Object Model, fixtures, and best practices

playwright-e2e-tester

16
from diegosouzapw/awesome-omni-skill

Expert in end-to-end testing with Playwright, the modern cross-browser testing framework. Specializes in test generation, page object patterns, visual regression testing, and CI/CD integration. Handles complex testing scenarios including authentication flows, API mocking, and mobile emulation.

playwright-best-practices

16
from diegosouzapw/awesome-omni-skill

Review code for Playwright Guidelines compliance. Use when asked to "review my playwright tests", "check accessibility", or "check my tests against best practices".

azure-resource-manager-playwright-dotnet

16
from diegosouzapw/awesome-omni-skill

Azure Resource Manager SDK for Microsoft Playwright Testing in .NET.

reviewing-documentation

16
from diegosouzapw/awesome-omni-skill

Use when reviewing documentation quality, auditing README or CLAUDE.md files, or standardizing AI instruction files.

playwright-expert

16
from diegosouzapw/awesome-omni-skill

Use when writing E2E tests with Playwright, setting up test infrastructure, or debugging flaky browser tests. Invoke for browser automation, E2E tests, Page Object Model, test flakiness, visual testing, CI/CD pipeline optimization.

azure-microsoft-playwright-testing-ts

16
from diegosouzapw/awesome-omni-skill

Run Playwright tests at scale using Azure Playwright Workspaces (formerly Microsoft Playwright Testing). Use when scaling browser tests across cloud-hosted browsers, integrating with CI/CD pipeline...