with one click
review-pr
// Review a pull request for Playwright test automation using project standards. Use when user asks to review a PR, check a pull request, or mentions a PR number.
// Review a pull request for Playwright test automation using project standards. Use when user asks to review a PR, check a pull request, or mentions a PR number.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | review-pr |
| description | Review a pull request for Playwright test automation using project standards. Use when user asks to review a PR, check a pull request, or mentions a PR number. |
| allowed-tools | Bash(gh:*), Bash(git:*), Read, Grep, Glob |
# Get PR metadata
gh pr view <number> --json title,body,state,additions,deletions,changedFiles,baseRefName,headRefName
# Get full diff
gh pr diff <number>
Use Read tool to view complete files mentioned in the diff.
getByRole/getByText over CSS/XPathpage.waitForTimeout() is a red flagFile & Folder Organization:
Consistent structure makes the codebase navigable and predictable.
File naming conventions:
checkout.page.ts, not CheckoutPage.ts or checkout_page.ts.page.ts - page objects (cart.page.ts, payment.page.ts).component.ts - reusable UI components (header.component.ts, order-table.component.ts).types.ts - type definitions (cart.types.ts, product.types.ts).spec.ts - test files (complete-order.spec.ts).fixture.ts - test fixtures.factory.ts - data factories (person.factory.ts)table.ts, convert-data.ts (pure functions)Folder structure:
src/ui/pages/
āāā cart/ # cart.page.ts, checkout.page.ts, payment.page.ts
āāā product/ # product.page.ts, products.page.ts
āāā auth/ # login.page.ts, signup.page.ts
āāā components/ # Shared components (header, modals, tables)
tests/ui/
āāā e2e/ # End-to-end flows (complete-order.spec.ts)
āāā cart/ # Cart-specific tests
āāā product/ # Product-specific tests
src/ui/types/ - shared TypeScript typessrc/ui/test-data/constants/ - test data constantssrc/utils/ - utility functionsRed flags to catch:
Checkout.ts instead of checkout.page.ts)product/ folder)components/ but is nested in a page folder.spec.ts conventionNaming Conventions:
Variables/methods follow conventions - camelCase, descriptive, no abbreviations
File names are consistent - kebab-case, clear purpose
Declarative Naming - follow should [outcome] when [scenario] pattern
Constants are UPPER_CASE - configuration values, magic numbers extracted
Page Object method names match their return type and intent:
| Prefix | Return type | Purpose | Example |
|---|---|---|---|
waitFor* | Promise<this> | Wait for a condition, enable chaining | waitForLoad(): Promise<this> |
expect* | Promise<void> | Thin Playwright expect wrapper (single assertion) | expectUrl(url: string): Promise<void> |
assert* | Promise<void> | Custom business-logic assertion (may combine multiple checks) | assertCartTotal(expected: number): Promise<void> |
is* / has* | Promise<boolean> | Query state, must return boolean | isSubmitEnabled(): Promise<boolean> |
get* | Promise<string | number | ā¦> | Extract a value from the page | getHeaderText(): Promise<string> |
| verb (action) | Promise<void> | Describe user intent, not mechanism | goBack(): Promise<void>, fillEmail(v: string): Promise<void> |
Red flags to catch:
is* method that returns Promise<this> or Promise<void> instead of Promise<boolean> (e.g., isLoaded(): Promise<this> ā should be waitForLoad())click* method name ā describes mechanism, not intent (e.g., clickBack() should be goBack())assert* for a thin Playwright wrapper ā use expect* prefix instead (e.g., assertUrl() ā expectUrl())check* ā unclear whether it asserts or returns a booleanOver-Engineering:
Method Optimization:
Promise<void>, string, number). Non-exported local arrow functions may omit return types when obvious from context.Code Style:
const userData = user when user is already typed)protected for uniqueElement if BasePage uses protected)assertAddressBlock(locator, data))`${a} ${b}` over a + ' ' + b for string concatenationTypes & Constants Organization:
This is a tricky area with multiple valid approaches. Flag for discussion when patterns are inconsistent.
Where types should live:
src/ui/types/ - types used across multiple pages (e.g., CartItem used in cart.page.ts AND checkout.page.ts ā extract to types/cart.types.ts)typeof CONSTANT (e.g., type CreditCard = typeof CREDIT_CARDS[keyof typeof CREDIT_CARDS]), keep them together in constants file - this is OKPick, Omit, Partial for leaner typesid not User obj)as const string unionsConstants organization:
test-data/constants/ - test data like credit cards, URLs, timeoutscredit-card.ts for cards, urls.ts for URLs, don't mix domainsCREDIT_CARDS not creditCardsas const for literal types - enables type inference from valuesRecommended structure:
src/ui/
āāā types/ # Shared types
ā āāā cart.types.ts # CartItem, OrderItem
ā āāā user.types.ts # Person, Address
ā āāā index.ts # Re-exports
āāā test-data/
ā āāā constants/ # Test data with derived types
ā āāā credit-card.ts # CREDIT_CARDS + CreditCard type (OK together)
ā āāā timeouts.ts # TIMEOUTS
āāā pages/
āāā cart/
āāā cart.page.ts # Imports from types/, no local CartItem
Red flags to catch:
Config Organization:
Utils & Helpers:
Reporting & Debugging:
@step() usage is meaningful - steps tell a story in reportssubmitForm not clickSubmitnew Page(page))Review Style - Senior AQA Mindset:
Patterns to IGNORE (not issues):
pages in both fixtures/index.ts and api-fixtures/api-user.fixture.ts) ā these may coexist intentionally for A/B performance comparison between fixture strategies. Do not flag as duplication or suggest mergeTests unless the duplicates have diverged in behavior.Patterns to flag for extra review (not issues, just note them):
assertElementVisible(locator))as const is used for type inference## PR Review: [Title] (#[Number])
**Changes**: +X / -Y across Z files
---
[ONLY INCLUDE SECTIONS WITH ISSUES - SKIP SECTIONS THAT ARE FINE]
### š“ Blockers
Critical issues that must be fixed.
### ā ļø Issues
| File:Line | Issue | Suggestion |
|-----------|-------|------------|
| `file.ts:42` | Description | How to fix |
### š For Your Review
Design decisions that may be intentional - verify they fit your context:
- [pattern] at `file.ts:line` - [brief description]
### š” Discussion Points
Areas with multiple valid approaches - worth a team decision:
- [topic] - Option A: [approach]. Option B: [approach]. Recommendation: [suggestion]
*Common discussion topics: type location (page vs shared), helper extraction timing, assertion granularity*
### š Git Hygiene
**PR title:** `Current` ā `Suggested improvement`
**Commits to improve:**
| Current | Suggested |
|---------|-----------|
| `bad commit msg` | `feat: clear description of change` |
---
ā
**Good:** [list areas with no issues, e.g., "test isolation, factory patterns, step decorator usage"]
**Verdict:** Approved / Changes requested
š¤ Generated with [Claude Code](https://claude.com/claude-code)
After generating the review, ALWAYS post it as a comment on the PR:
gh pr review <number> --comment --body "$(cat <<'EOF'
[review content]
EOF
)"
Important: Do not ask the user if they want to post - automatically post the review after completing the analysis.
See docs/design-docs/core-beliefs.md for detailed testing standards.