| name | e2e-page-test |
| description | Systematically test all pages for errors, functionality, and proper rendering using Playwright MCP |
E2E Page Testing Skill
Overview
This skill systematically tests every page in an application using Playwright MCP. It verifies page loading, element rendering, interaction functionality, and error detection.
Standard Test Plan Location
Plan file: tests/e2e-test-plan.md
This skill reads the page inventory from the test plan at tests/e2e-test-plan.md. If the plan file doesn't exist, the calling command should invoke the e2e-test-plan skill first to generate it.
Purpose
Ensure that:
- All pages load without errors
- All expected elements are present
- All interactions work correctly
- No console or network errors occur
- Pages are accessible and functional
Workflow
Step -1: Test Plan Verification (REQUIRED FIRST)
CRITICAL: Before testing pages, verify the test plan exists.
Check for Test Plan
- Look for
tests/e2e-test-plan.md - If the file exists, read the "Pages to Test" section
- If the file does NOT exist, STOP and report that the plan must be generated first
- Look for
Read Page List from Plan
- Extract public pages
- Extract authenticated pages
- Extract admin pages
- Use this list for testing
Step 0: Build Assets & Verify URL (CRITICAL - DO THIS FIRST)
Before testing any pages, build assets and verify the application is accessible.
0a. Build Application Assets
Missing assets are a common cause of E2E test failures. Before testing:
Check for package.json
Look for package.json in project root If found, assets likely need buildingRun Build Commands
npm install # If node_modules missing npm run build # Compile production assets # or for dev server: npm run dev # Start Vite/webpack dev serverDetect Build Issues After loading a page, check for:
- Unstyled content (missing CSS)
- Blank pages (missing JS)
- Console errors: "Failed to load resource"
- Network 404s for .js, .css, .png files
- Errors about /build/, /dist/, /assets/
If assets are missing:
- Stop testing
- Run
npm install && npm run build - Restart and retest
0b. URL/Port Verification
Navigate to Base URL
browser_navigate({ url: base_url }) browser_snapshot()Verify Correct Application Check the snapshot for:
- ✅ Application name, logo, or known branding
- ✅ Expected navigation structure
- ✅ Known page elements from codebase analysis
- ❌ Default server pages ("Welcome to nginx!", "It works!", "Apache2 Ubuntu Default Page")
- ❌ Connection errors ("This site can't be reached", "Connection refused")
- ❌ Different/unexpected application content
Port Discovery (if verification fails) If the page doesn't match expected application:
Common ports to try: - http://localhost:8000 (Laravel/Django) - http://localhost:8080 (Common alternative) - http://localhost:3000 (Node.js/React/Next.js) - http://localhost:5173 (Vite dev server) - http://localhost:5174 (Vite alternative port) - http://localhost:5000 (Flask/Python) - http://localhost:4200 (Angular) - http://localhost:8888 (Jupyter/custom)For each port:
browser_navigate({ url: "http://localhost:{port}" }) browser_snapshot() // Check if this matches the expected application // If yes, use this as the new base URLCheck Project Configuration If port discovery fails, look for hints in:
.envfile (APP_PORT, PORT, VITE_PORT, SERVER_PORT)package.jsonscripts (look for --port flags)vite.config.js/ts(server.port setting)docker-compose.yml(port mappings).env.examplefor default port values
Proceed or Stop
- If correct URL found: Update base_url and continue testing
- If URL differs from provided: Log warning in test report
- If no working URL found: STOP TESTING and report error
- "Application not accessible at {provided_url}"
- "Ports attempted: 8000, 8080, 3000, 5173, 5000, 4200"
- "Suggestion: Verify the development server is running"
Step 1: Page Inventory
List All Pages
- Extract from route definitions
- Include dynamic route patterns
- Note authentication requirements
Categorize Pages
- Public pages
- Authenticated pages
- Admin pages
- Special pages (error pages, maintenance, etc.)
Define Expected Elements
- Navigation elements
- Main content areas
- Forms and inputs
- Action buttons
- Footer elements
Step 2: Page Load Testing
For EACH page:
Navigate to Page
browser_navigate({ url: "/page-path" })Wait for Load
browser_wait_for({ text: "Expected content" }) OR browser_wait_for({ time: 2 })Capture Snapshot
browser_snapshot()Check Console Messages
browser_console_messages({ level: "error" })Check Network Requests
browser_network_requests()
Step 3: Element Verification
For each page, verify:
Navigation
- Header present
- Menu items visible
- Logo displayed
- Navigation links work
Main Content
- Title/heading present
- Expected content visible
- Images loaded
- Data displayed (if applicable)
Forms (if present)
- All inputs visible
- Labels present
- Submit button enabled
- Validation messages work
Footer
- Footer visible
- Links work
- Copyright present
Step 4: Interaction Testing
Link Testing
For each link on page: browser_click on link browser_snapshot to verify destination browser_navigate_backButton Testing
For each button: browser_click on button Verify expected action occurs Check for errorsForm Testing
browser_fill_form with test data browser_click submit Verify success or validation errorsDropdown Testing
browser_select_option on dropdowns Verify selection applied
Step 5: Error Detection
Console Errors
browser_console_messages({ level: "error" }) Common errors to detect: - Uncaught exceptions - Failed to load resource - CORS errors - API errors - Component errorsNetwork Errors
browser_network_requests() Check for: - 4xx errors (client errors) - 5xx errors (server errors) - Failed requests - Timeout errorsVisual Errors
browser_snapshot() Look for: - Broken layout - Missing images - Overlapping elements - Unreadable text
Step 6: Responsive Testing
Test each page at multiple viewports:
Desktop (1920x1080)
browser_resize({ width: 1920, height: 1080 }) browser_navigate to page browser_snapshot Verify desktop layoutTablet (768x1024)
browser_resize({ width: 768, height: 1024 }) browser_navigate to page browser_snapshot Verify tablet layoutMobile (375x812)
browser_resize({ width: 375, height: 812 }) browser_navigate to page browser_snapshot Verify mobile layout Verify mobile menu works
Test Patterns
Asset Build Verification (RUN BEFORE TESTING)
// Step 1: Check if assets need building
1. Check for package.json in project root
2. If node_modules missing: run npm install
3. Run npm run build (or npm run prod)
// Step 2: Verify assets after page load
4. browser_navigate to any page
5. browser_snapshot() - check for styled content
6. browser_console_messages({ level: "error" })
- Look for "Failed to load resource"
- Look for "404 (Not Found)"
- Look for module/import errors
7. browser_network_requests()
- Check for 404s on .js, .css, .png files
- Check for failed requests to /build/, /dist/, /assets/
// If assets missing:
8. STOP testing
9. Report: "Assets not built. Run: npm install && npm run build"
10. After build, restart testing
URL Verification Test (RUN FIRST)
// Step 1: Try provided URL
1. browser_navigate({ url: base_url })
2. snapshot = browser_snapshot()
// Step 2: Check if correct application
3. If snapshot shows:
- "Welcome to nginx!" → WRONG URL
- "It works!" → WRONG URL
- "Apache2 Ubuntu Default Page" → WRONG URL
- "This site can't be reached" → CONNECTION ERROR
- Expected app content → CORRECT URL ✓
// Step 3: Port discovery if needed
4. If WRONG URL:
ports = [8000, 8080, 3000, 5173, 5174, 5000, 4200]
for port in ports:
browser_navigate({ url: `http://localhost:${port}` })
snapshot = browser_snapshot()
if snapshot shows expected app content:
base_url = `http://localhost:${port}`
break
// Step 4: Report result
5. If correct URL found:
Log: "Application verified at {base_url}"
Continue with testing
6. If no correct URL:
STOP TESTING
Report: "Cannot find application. Ports tried: ..."
Basic Page Test
1. browser_navigate({ url: "/page" })
2. browser_wait_for({ time: 2 }) // Wait for load
3. snapshot = browser_snapshot()
4. errors = browser_console_messages({ level: "error" })
5. requests = browser_network_requests()
// Verify
Assert: snapshot contains expected elements
Assert: errors is empty
Assert: no failed requests in network
Form Page Test
1. browser_navigate({ url: "/form-page" })
2. browser_snapshot() // Verify form present
// Test empty submission
3. browser_click({ element: "Submit button", ref: "[submit-ref]" })
4. browser_snapshot() // Should show validation errors
// Test valid submission
5. browser_fill_form({
fields: [
{ name: "Name", type: "textbox", ref: "[name-ref]", value: "Test User" },
{ name: "Email", type: "textbox", ref: "[email-ref]", value: "test@example.com" }
]
})
6. browser_click({ element: "Submit button", ref: "[submit-ref]" })
7. browser_wait_for({ text: "Success" })
8. browser_snapshot() // Verify success
Navigation Test
1. browser_navigate({ url: "/" })
2. browser_snapshot() // Get all navigation refs
For each nav link:
3. browser_click({ element: "Nav link", ref: "[link-ref]" })
4. browser_snapshot() // Verify correct page loaded
5. browser_navigate_back()
Dynamic Content Test
1. browser_navigate({ url: "/data-page" })
2. browser_wait_for({ text: "Loading..." }) // Wait for loading state
3. browser_wait_for({ textGone: "Loading..." }) // Wait for content
4. browser_snapshot() // Verify data displayed
5. browser_console_messages({ level: "error" }) // Check for errors
Common Page Types
Home Page
Expected Elements:
- Hero section with headline
- Feature highlights
- Call-to-action buttons
- Navigation header
- Footer
Tests:
- [ ] Hero content visible
- [ ] CTA buttons clickable
- [ ] Navigation works
- [ ] Footer links work
Login Page
Expected Elements:
- Email/username field
- Password field
- Submit button
- Forgot password link
- Register link
Tests:
- [ ] Form displays correctly
- [ ] Empty submission shows errors
- [ ] Invalid credentials show error
- [ ] Valid credentials redirect
- [ ] Forgot password link works
Dashboard Page
Expected Elements:
- Welcome message
- Statistics/widgets
- Navigation sidebar
- User menu
- Action buttons
Tests:
- [ ] Loads for authenticated users
- [ ] Redirects unauthenticated users
- [ ] Widgets display data
- [ ] Actions are functional
List Page
Expected Elements:
- Data table or list
- Pagination
- Search/filter
- Action buttons (edit, delete)
Tests:
- [ ] Data displays correctly
- [ ] Pagination works
- [ ] Search filters data
- [ ] Actions are functional
- [ ] Empty state handled
Form Page
Expected Elements:
- Form fields
- Labels
- Validation messages
- Submit button
- Cancel button
Tests:
- [ ] All fields editable
- [ ] Validation works
- [ ] Submit saves data
- [ ] Cancel returns to list
- [ ] Required fields enforced
Output Format
Page Test Results
# Page Test Results
## Pre-Test Verification
### Asset Build Status
- Build command run: npm run build ✓
- Assets compiled: Yes
- CSS loaded: Yes
- JavaScript loaded: Yes
- No 404 errors on assets: Yes
(or if assets were missing:)
- Build command run: No ⚠️
- Assets compiled: No
- Issue: Missing /build/assets/app.js (404)
- Resolution: Ran `npm install && npm run build`
- Retested: All assets now loading ✓
### URL Verification
- Provided URL: http://localhost:8000
- Verified URL: http://localhost:8000 ✓
- Status: Application confirmed
(or if port was different:)
- Provided URL: http://localhost:8000
- Verified URL: http://localhost:3000 ⚠️
- Status: Application found on different port
- Note: Server appears to be running on port 3000
## Summary
- Total Pages: 25
- Passed: 23
- Failed: 2
- Skipped: 0
## Detailed Results
### Public Pages
#### Home (/)
- Status: PASSED
- Load Time: 1.2s
- Console Errors: 0
- Network Errors: 0
- Elements Verified:
- [x] Header navigation
- [x] Hero section
- [x] Feature cards
- [x] Footer
#### About (/about)
- Status: PASSED
- Load Time: 0.8s
- Console Errors: 0
- Network Errors: 0
- Elements Verified:
- [x] Page title
- [x] Content sections
- [x] Team members
### Authenticated Pages
#### Dashboard (/dashboard)
- Status: FAILED
- Load Time: 2.5s
- Console Errors: 1
- Error: "Cannot read property 'name' of undefined"
- Network Errors: 0
- Elements Verified:
- [x] Welcome message
- [ ] Statistics widget - MISSING
- [x] Recent activity
#### Profile (/profile)
- Status: PASSED
- Load Time: 1.1s
- Console Errors: 0
- Network Errors: 0
- Elements Verified:
- [x] User information
- [x] Edit button
- [x] Avatar
### Responsive Tests
#### Home Page
- Desktop (1920x1080): PASSED
- Tablet (768x1024): PASSED
- Mobile (375x812): FAILED
- Issue: Navigation menu overlaps content
## Errors Found
1. **Dashboard Widget Error**
- Page: /dashboard
- Error: Cannot read property 'name' of undefined
- Likely Cause: User data not loaded before rendering
2. **Mobile Navigation Issue**
- Page: /home
- Issue: Navigation overlaps on mobile
- Likely Cause: CSS media query issue
## Recommendations
1. Fix Dashboard data loading sequence
2. Adjust mobile navigation CSS
3. Add loading states for async data
Best Practices
- Wait for Page Load - Don't check elements too quickly
- Use Snapshots - Capture state at each step
- Check Console/Network - Look for hidden errors
- Test All Viewports - Responsive issues are common
- Document Everything - Note all elements tested
- Test Interactions - Don't just check static content
- Handle Dynamic Content - Wait for data to load