v1.4.0: Major Skills Expansion - 75 Total Skills
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "playwright-tools",
|
||||
"version": "2.0.3",
|
||||
"description": "Playwright browser automation with E2E testing skill and responsive design testing agent.",
|
||||
"author": {
|
||||
"name": "Fatih Akyon"
|
||||
},
|
||||
"homepage": "https://github.com/fcakyon/claude-codex-settings#plugins",
|
||||
"repository": "https://github.com/fcakyon/claude-codex-settings",
|
||||
"license": "Apache-2.0"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"playwright": {
|
||||
"command": "npx",
|
||||
"args": ["@playwright/mcp@latest"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
---
|
||||
name: responsive-tester
|
||||
description: |
|
||||
Use this agent when user asks to "test responsiveness", "check responsive design", "test viewport sizes", "test mobile layout", "test desktop layout", "check breakpoints", "responsive testing", or wants to verify components look correct across different screen widths.
|
||||
|
||||
<example>
|
||||
Context: User has a web page and wants to verify it works on mobile
|
||||
user: "Test the responsiveness of my dashboard page"
|
||||
assistant: "I'll use the responsive-tester agent to check your dashboard across all standard breakpoints from mobile to desktop."
|
||||
<commentary>
|
||||
User explicitly wants responsiveness testing, trigger the agent.
|
||||
</commentary>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
Context: User built a new component and wants to verify mobile-first design
|
||||
user: "Check if this page looks good on mobile and desktop"
|
||||
assistant: "I'll launch the responsive-tester agent to test your page across mobile (375px, 414px), tablet (640px, 768px), and desktop (1024px, 1280px, 1536px) viewports."
|
||||
<commentary>
|
||||
User wants visual verification across device sizes, this is responsive testing.
|
||||
</commentary>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
Context: User suspects layout issues at certain screen sizes
|
||||
user: "Something breaks at tablet width, can you test the breakpoints?"
|
||||
assistant: "I'll use the responsive-tester agent to systematically test each breakpoint and identify where the layout breaks."
|
||||
<commentary>
|
||||
User has breakpoint-specific issues, agent will test all widths systematically.
|
||||
</commentary>
|
||||
</example>
|
||||
model: inherit
|
||||
color: cyan
|
||||
---
|
||||
|
||||
You are a responsive design testing specialist using Playwright browser automation.
|
||||
|
||||
**Core Responsibilities:**
|
||||
|
||||
1. Test web pages across standard viewport breakpoints
|
||||
2. Identify layout issues, overflow problems, and responsive failures
|
||||
3. Verify mobile-first design patterns are correctly implemented
|
||||
4. Report specific breakpoints where issues occur
|
||||
|
||||
**Standard Breakpoints to Test:**
|
||||
|
||||
| Name | Width | Device Type |
|
||||
| -------- | ------ | ------------------------------ |
|
||||
| Mobile S | 375px | iPhone SE/Mini |
|
||||
| Mobile L | 414px | iPhone Plus/Max |
|
||||
| sm | 640px | Large phone/Small tablet |
|
||||
| md | 768px | Tablet portrait |
|
||||
| lg | 1024px | Tablet landscape/Small desktop |
|
||||
| xl | 1280px | Desktop |
|
||||
| 2xl | 1536px | Large desktop |
|
||||
|
||||
**Testing Process:**
|
||||
|
||||
1. Navigate to target URL using `browser_navigate`
|
||||
2. For each breakpoint width:
|
||||
- Resize browser using `browser_resize` (height: 800px default)
|
||||
- Wait for layout to settle
|
||||
- Take screenshot using `browser_take_screenshot`
|
||||
- Check for horizontal overflow via `browser_evaluate`
|
||||
3. Compile findings with specific breakpoints where issues occur
|
||||
|
||||
**Mobile-First Responsive Patterns:**
|
||||
|
||||
All layouts must follow mobile-first progression. Verify these patterns:
|
||||
|
||||
**Grid Layouts:**
|
||||
|
||||
- 2-column: Single column on mobile → 2 columns at md (768px)
|
||||
- 3-column: 1 col → 2 at md → 3 at lg (1024px)
|
||||
- 4-column: Progressive 1 → 2 at sm → 3 at lg → 4 at xl
|
||||
- Card grids: Stack on mobile → side-by-side at lg, optional ratio adjustments at xl
|
||||
- Sidebar layouts: Full-width mobile → fixed sidebar (280-360px range) + fluid content at lg+
|
||||
|
||||
**Flex Layouts:**
|
||||
|
||||
- Horizontal rows: MUST stack vertically on mobile (`flex-col`), go horizontal at breakpoint
|
||||
- Split panels: Vertical stack mobile → horizontal at lg, always include min-height
|
||||
|
||||
**Form Controls & Inputs:**
|
||||
|
||||
- Search inputs: Full width mobile → fixed ~160px at sm
|
||||
- Select dropdowns: Full width mobile → fixed ~176px at sm
|
||||
- Date pickers: Full width mobile → ~260px at sm
|
||||
- Control wrappers: Flex-wrap, full width mobile → auto width at sm+
|
||||
|
||||
**Sidebar Panel Widths:**
|
||||
|
||||
- Scale progressively: full width mobile → increasing fixed widths at md/lg/xl
|
||||
- Must include flex-shrink-0 to prevent compression
|
||||
|
||||
**Data Tables:**
|
||||
|
||||
- Wrap in horizontal scroll container
|
||||
- Set minimum width (400-600px) to prevent column squishing
|
||||
|
||||
**Dynamic Heights - CRITICAL:**
|
||||
When using viewport-based heights like `h-[calc(100vh-Xpx)]`, ALWAYS pair with minimum height:
|
||||
|
||||
- Split panels/complex layouts: min-h-[500px]
|
||||
- Data tables: min-h-[400px]
|
||||
- Dashboards: min-h-[600px]
|
||||
- Simple cards: min-h-[300px]
|
||||
|
||||
**Spacing:**
|
||||
|
||||
- Page padding should scale: tighter on mobile (px-4), more generous on desktop (lg:px-6)
|
||||
|
||||
**Anti-Patterns to Flag:**
|
||||
|
||||
| Bad Pattern | Issue | Fix |
|
||||
| ------------------------- | -------------------------------- | ------------------------------ |
|
||||
| `w-[300px]` | Fixed width breaks mobile | `w-full sm:w-[280px]` |
|
||||
| `xl:grid-cols-2` only | Missing intermediate breakpoints | `md:grid-cols-2 lg:... xl:...` |
|
||||
| `flex` horizontal only | No mobile stack | `flex-col lg:flex-row` |
|
||||
| `w-[20%]` | Percentage widths unreliable | `w-full lg:w-64 xl:w-80` |
|
||||
| `h-[calc(100vh-X)]` alone | Over-shrinks on short screens | Add `min-h-[500px]` |
|
||||
|
||||
**Overflow Detection Script:**
|
||||
|
||||
```javascript
|
||||
// Run via browser_evaluate to detect horizontal overflow
|
||||
(() => {
|
||||
const issues = [];
|
||||
document.querySelectorAll("*").forEach((el) => {
|
||||
if (el.scrollWidth > el.clientWidth) {
|
||||
issues.push({
|
||||
element:
|
||||
el.tagName + (el.className ? "." + el.className.split(" ")[0] : ""),
|
||||
overflow: el.scrollWidth - el.clientWidth,
|
||||
});
|
||||
}
|
||||
});
|
||||
return issues.length ? issues : "No overflow detected";
|
||||
})();
|
||||
```
|
||||
|
||||
**Touch Target Check:**
|
||||
|
||||
Verify interactive elements meet minimum 44x44px touch target size on mobile viewports.
|
||||
|
||||
**Output Format:**
|
||||
|
||||
Report findings as:
|
||||
|
||||
```
|
||||
## Responsive Test Results for [URL]
|
||||
|
||||
### Summary
|
||||
- Tested: [N] breakpoints
|
||||
- Issues found: [N]
|
||||
|
||||
### Breakpoint Results
|
||||
|
||||
#### 375px (Mobile S) ✅/❌
|
||||
[Screenshot reference]
|
||||
[Issues if any]
|
||||
|
||||
#### 414px (Mobile L) ✅/❌
|
||||
...
|
||||
|
||||
### Issues Found
|
||||
1. [Element] at [breakpoint]: [Description]
|
||||
- Current: [bad pattern]
|
||||
- Fix: [recommended pattern]
|
||||
|
||||
### Recommendations
|
||||
[Prioritized list of fixes]
|
||||
```
|
||||
|
||||
Always test from smallest to largest viewport to verify mobile-first approach.
|
||||
@@ -0,0 +1,104 @@
|
||||
---
|
||||
description: Configure Playwright MCP
|
||||
---
|
||||
|
||||
# Playwright Tools Setup
|
||||
|
||||
**Source:** [microsoft/playwright-mcp](https://github.com/microsoft/playwright-mcp)
|
||||
|
||||
Check Playwright MCP status and configure browser dependencies if needed.
|
||||
|
||||
## Step 1: Test Current Setup
|
||||
|
||||
Run `/mcp` command to check if playwright server is listed and connected.
|
||||
|
||||
If playwright server shows as connected: Tell user Playwright is configured and working.
|
||||
|
||||
If playwright server is missing or shows connection error: Continue to Step 2.
|
||||
|
||||
## Step 2: Browser Installation
|
||||
|
||||
Tell the user:
|
||||
|
||||
```
|
||||
Playwright MCP requires browser binaries. Install them with:
|
||||
|
||||
npx playwright install
|
||||
|
||||
This installs Chromium, Firefox, and WebKit browsers.
|
||||
|
||||
For a specific browser only:
|
||||
npx playwright install chromium
|
||||
npx playwright install firefox
|
||||
npx playwright install webkit
|
||||
```
|
||||
|
||||
## Step 3: Browser Options
|
||||
|
||||
The MCP server supports these browsers via the `--browser` flag in `.mcp.json`:
|
||||
|
||||
- `chrome` (default)
|
||||
- `firefox`
|
||||
- `webkit`
|
||||
- `msedge`
|
||||
|
||||
Example `.mcp.json` for Firefox:
|
||||
|
||||
```json
|
||||
{
|
||||
"playwright": {
|
||||
"command": "npx",
|
||||
"args": ["@playwright/mcp@latest", "--browser", "firefox"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Step 4: Headless Mode
|
||||
|
||||
For headless operation (no visible browser), add `--headless`:
|
||||
|
||||
```json
|
||||
{
|
||||
"playwright": {
|
||||
"command": "npx",
|
||||
"args": ["@playwright/mcp@latest", "--headless"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Step 5: Restart
|
||||
|
||||
Tell the user:
|
||||
|
||||
```
|
||||
After making changes:
|
||||
1. Exit Claude Code
|
||||
2. Run `claude` again
|
||||
|
||||
Changes take effect after restart.
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If Playwright MCP fails:
|
||||
|
||||
```
|
||||
Common fixes:
|
||||
1. Browser not found - Run `npx playwright install`
|
||||
2. Permission denied - Check file permissions on browser binaries
|
||||
3. Display issues - Use `--headless` flag for headless mode
|
||||
4. Timeout errors - Increase timeout with `--timeout-navigation 120000`
|
||||
```
|
||||
|
||||
## Alternative: Disable Plugin
|
||||
|
||||
If user doesn't need browser automation:
|
||||
|
||||
```
|
||||
To disable this plugin:
|
||||
1. Run /mcp command
|
||||
2. Find the playwright server
|
||||
3. Disable it
|
||||
|
||||
This prevents errors from missing browser binaries.
|
||||
```
|
||||
@@ -0,0 +1,333 @@
|
||||
---
|
||||
name: playwright-testing
|
||||
description: This skill should be used when user asks about "Playwright", "responsiveness test", "test with playwright", "test login flow", "file upload test", "handle authentication in tests", or "fix flaky tests".
|
||||
---
|
||||
|
||||
# Playwright Testing Best Practices
|
||||
|
||||
## Test Organization
|
||||
|
||||
### File Structure
|
||||
|
||||
```
|
||||
tests/
|
||||
├── auth/
|
||||
│ ├── login.spec.ts
|
||||
│ └── signup.spec.ts
|
||||
├── dashboard/
|
||||
│ └── dashboard.spec.ts
|
||||
├── fixtures/
|
||||
│ └── test-data.ts
|
||||
├── pages/
|
||||
│ └── login.page.ts
|
||||
└── playwright.config.ts
|
||||
```
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
- Files: `feature-name.spec.ts`
|
||||
- Tests: Describe user behavior, not implementation
|
||||
- Good: `test('user can reset password via email')`
|
||||
- Bad: `test('test reset password')`
|
||||
|
||||
## Page Object Model
|
||||
|
||||
### Basic Pattern
|
||||
|
||||
```typescript
|
||||
// pages/login.page.ts
|
||||
export class LoginPage {
|
||||
constructor(private page: Page) {}
|
||||
|
||||
async goto() {
|
||||
await this.page.goto("/login");
|
||||
}
|
||||
|
||||
async login(email: string, password: string) {
|
||||
await this.page.getByLabel("Email").fill(email);
|
||||
await this.page.getByLabel("Password").fill(password);
|
||||
await this.page.getByRole("button", { name: "Sign in" }).click();
|
||||
}
|
||||
}
|
||||
|
||||
// tests/login.spec.ts
|
||||
test("successful login", async ({ page }) => {
|
||||
const loginPage = new LoginPage(page);
|
||||
await loginPage.goto();
|
||||
await loginPage.login("user@example.com", "password");
|
||||
await expect(page).toHaveURL("/dashboard");
|
||||
});
|
||||
```
|
||||
|
||||
## Locator Strategies
|
||||
|
||||
### Priority Order (Best to Worst)
|
||||
|
||||
1. **`getByRole`** - Accessible, resilient
|
||||
2. **`getByLabel`** - Form inputs
|
||||
3. **`getByPlaceholder`** - When no label
|
||||
4. **`getByText`** - Visible text
|
||||
5. **`getByTestId`** - When no better option
|
||||
6. **CSS/XPath** - Last resort
|
||||
|
||||
### Examples
|
||||
|
||||
```typescript
|
||||
// Preferred
|
||||
await page.getByRole("button", { name: "Submit" }).click();
|
||||
await page.getByLabel("Email address").fill("user@example.com");
|
||||
|
||||
// Acceptable
|
||||
await page.getByTestId("submit-button").click();
|
||||
|
||||
// Avoid
|
||||
await page.locator("#submit-btn").click();
|
||||
await page.locator('//button[@type="submit"]').click();
|
||||
```
|
||||
|
||||
## Authentication Handling
|
||||
|
||||
### Storage State (Recommended)
|
||||
|
||||
Save logged-in state and reuse across tests:
|
||||
|
||||
```typescript
|
||||
// global-setup.ts
|
||||
async function globalSetup() {
|
||||
const browser = await chromium.launch();
|
||||
const page = await browser.newPage();
|
||||
await page.goto("/login");
|
||||
await page.getByLabel("Email").fill(process.env.TEST_USER_EMAIL);
|
||||
await page.getByLabel("Password").fill(process.env.TEST_USER_PASSWORD);
|
||||
await page.getByRole("button", { name: "Sign in" }).click();
|
||||
await page.waitForURL("/dashboard");
|
||||
await page.context().storageState({ path: "auth.json" });
|
||||
await browser.close();
|
||||
}
|
||||
|
||||
// playwright.config.ts
|
||||
export default defineConfig({
|
||||
globalSetup: "./global-setup.ts",
|
||||
use: {
|
||||
storageState: "auth.json",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Multi-User Scenarios
|
||||
|
||||
```typescript
|
||||
// Create different auth states
|
||||
const adminAuth = "admin-auth.json";
|
||||
const userAuth = "user-auth.json";
|
||||
|
||||
test.describe("admin features", () => {
|
||||
test.use({ storageState: adminAuth });
|
||||
// Admin tests
|
||||
});
|
||||
|
||||
test.describe("user features", () => {
|
||||
test.use({ storageState: userAuth });
|
||||
// User tests
|
||||
});
|
||||
```
|
||||
|
||||
## File Upload Handling
|
||||
|
||||
### Basic Upload
|
||||
|
||||
```typescript
|
||||
// Single file
|
||||
await page.getByLabel("Upload file").setInputFiles("path/to/file.pdf");
|
||||
|
||||
// Multiple files
|
||||
await page
|
||||
.getByLabel("Upload files")
|
||||
.setInputFiles(["path/to/file1.pdf", "path/to/file2.pdf"]);
|
||||
|
||||
// Clear file input
|
||||
await page.getByLabel("Upload file").setInputFiles([]);
|
||||
```
|
||||
|
||||
### Drag and Drop Upload
|
||||
|
||||
```typescript
|
||||
// Create file from buffer
|
||||
const buffer = Buffer.from("file content");
|
||||
|
||||
await page.getByTestId("dropzone").dispatchEvent("drop", {
|
||||
dataTransfer: {
|
||||
files: [{ name: "test.txt", mimeType: "text/plain", buffer }],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### File Download
|
||||
|
||||
```typescript
|
||||
const downloadPromise = page.waitForEvent("download");
|
||||
await page.getByRole("button", { name: "Download" }).click();
|
||||
const download = await downloadPromise;
|
||||
await download.saveAs("downloads/" + download.suggestedFilename());
|
||||
```
|
||||
|
||||
## Waiting Strategies
|
||||
|
||||
### Auto-Wait (Preferred)
|
||||
|
||||
Playwright auto-waits for elements. Use assertions:
|
||||
|
||||
```typescript
|
||||
// Auto-waits for element to be visible and stable
|
||||
await page.getByRole("button", { name: "Submit" }).click();
|
||||
|
||||
// Auto-waits for condition
|
||||
await expect(page.getByText("Success")).toBeVisible();
|
||||
```
|
||||
|
||||
### Explicit Waits (When Needed)
|
||||
|
||||
```typescript
|
||||
// Wait for navigation
|
||||
await page.waitForURL("**/dashboard");
|
||||
|
||||
// Wait for network idle
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Wait for specific response
|
||||
await page.waitForResponse((resp) => resp.url().includes("/api/data"));
|
||||
```
|
||||
|
||||
## Network Mocking
|
||||
|
||||
### Mock API Responses
|
||||
|
||||
```typescript
|
||||
await page.route("**/api/users", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify([{ id: 1, name: "Test User" }]),
|
||||
});
|
||||
});
|
||||
|
||||
// Mock error response
|
||||
await page.route("**/api/users", async (route) => {
|
||||
await route.fulfill({ status: 500 });
|
||||
});
|
||||
```
|
||||
|
||||
### Intercept and Modify
|
||||
|
||||
```typescript
|
||||
await page.route("**/api/data", async (route) => {
|
||||
const response = await route.fetch();
|
||||
const json = await response.json();
|
||||
json.modified = true;
|
||||
await route.fulfill({ response, json });
|
||||
});
|
||||
```
|
||||
|
||||
## CI/CD Integration
|
||||
|
||||
### GitHub Actions Example
|
||||
|
||||
```yaml
|
||||
- name: Run Playwright tests
|
||||
run: npx playwright test
|
||||
env:
|
||||
CI: true
|
||||
|
||||
- name: Upload test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
```
|
||||
|
||||
### Parallel Execution
|
||||
|
||||
```typescript
|
||||
// playwright.config.ts
|
||||
export default defineConfig({
|
||||
workers: process.env.CI ? 2 : undefined,
|
||||
fullyParallel: true,
|
||||
});
|
||||
```
|
||||
|
||||
## Debugging Failed Tests
|
||||
|
||||
### Debug Tools
|
||||
|
||||
```bash
|
||||
# Run with UI mode
|
||||
npx playwright test --ui
|
||||
|
||||
# Run with inspector
|
||||
npx playwright test --debug
|
||||
|
||||
# Show browser
|
||||
npx playwright test --headed
|
||||
```
|
||||
|
||||
### Trace Viewer
|
||||
|
||||
```typescript
|
||||
// playwright.config.ts
|
||||
use: {
|
||||
trace: 'on-first-retry', // Capture trace on failure
|
||||
}
|
||||
```
|
||||
|
||||
## Flaky Test Fixes
|
||||
|
||||
### Common Causes and Solutions
|
||||
|
||||
**Race conditions:**
|
||||
|
||||
- Use proper assertions instead of hard waits
|
||||
- Wait for network requests to complete
|
||||
|
||||
**Animation issues:**
|
||||
|
||||
- Disable animations in test config
|
||||
- Wait for animation to complete
|
||||
|
||||
**Dynamic content:**
|
||||
|
||||
- Use flexible locators (text content, not position)
|
||||
- Wait for loading states to resolve
|
||||
|
||||
**Test isolation:**
|
||||
|
||||
- Each test should set up its own state
|
||||
- Don't depend on other tests' side effects
|
||||
|
||||
### Anti-Patterns to Avoid
|
||||
|
||||
```typescript
|
||||
// Bad: Hard sleep
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
// Good: Wait for condition
|
||||
await expect(page.getByText("Loaded")).toBeVisible();
|
||||
|
||||
// Bad: Flaky selector
|
||||
await page.locator(".btn:nth-child(3)").click();
|
||||
|
||||
// Good: Semantic selector
|
||||
await page.getByRole("button", { name: "Submit" }).click();
|
||||
```
|
||||
|
||||
## Responsive Design Testing
|
||||
|
||||
For comprehensive responsive testing across viewport breakpoints, use the **responsive-tester** agent. It automatically:
|
||||
|
||||
- Tests pages across 7 standard breakpoints (375px to 1536px)
|
||||
- Detects horizontal overflow issues
|
||||
- Verifies mobile-first design patterns
|
||||
- Checks touch target sizes (44x44px minimum)
|
||||
- Flags anti-patterns like fixed widths without mobile fallback
|
||||
|
||||
Trigger it by asking to "test responsiveness", "check breakpoints", or "test mobile/desktop layout".
|
||||
Reference in New Issue
Block a user