一键导入
playwright
Playwright E2E testing patterns. Trigger: When writing Playwright E2E tests (Page Object Model, selectors, MCP exploration workflow).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Playwright E2E testing patterns. Trigger: When writing Playwright E2E tests (Page Object Model, selectors, MCP exploration workflow).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Create distinctive, production-grade frontend interfaces with high design quality. Trigger: When the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.
Node.js development principles and decision-making. Framework selection, async patterns, security, and architecture. Teaches thinking, not copying. Triggers: When the user asks to build a Node.js application, API, backend, or any server-side JavaScript project.
Build production-ready Node.js backend services with Express/Fastify, implementing middleware patterns, error handling, authentication, database integration, and API design best practices. Trigger: When creating Node.js servers, REST APIs, GraphQL backends, or microservices architectures.
Optimize for search engine visibility and ranking. Use when asked to "improve SEO", "optimize for search", "fix meta tags", "add structured data", "sitemap optimization", or "search engine optimization". Trigger: when asked to "improve SEO", "optimize for search", "fix meta tags", "add structured data", "sitemap optimization", or "search engine optimization".
Provides comprehensive Tailwind CSS utility-first styling patterns including responsive design, layout utilities, flexbox, grid, spacing, typography, colors, and modern CSS best practices. Trigger: When styling components, building responsive layouts, implementing design systems, or optimizing CSS workflow.
Guide for styling with Tailwind CSS 4, including utility-first composition, `cn()` usage, theme variable handling, and project-safe class patterns. Trigger: Use when the task involves styling UI with Tailwind classes, composing conditional class names with `cn()`, working with Tailwind 4 theme variables, translating design/UI requirements into utility classes, or reviewing className usage to avoid invalid patterns such as wrapping theme variables with `var()` inside className-driven styling.
| name | playwright |
| description | Playwright E2E testing patterns. Trigger: When writing Playwright E2E tests (Page Object Model, selectors, MCP exploration workflow). |
| license | Apache-2.0 |
| metadata | {"author":"Mane087","version":"1.0","scope":["root","ui"],"auto_invoke":"Writing Playwright E2E tests"} |
| allowed-tools | Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task |
⚠️ If you have Playwright MCP tools, ALWAYS use them BEFORE creating any test:
If MCP NOT available: Proceed with test creation based on docs and code analysis.
Why This Matters:
e2e/
├── app
├── components/
├── {file-name}.2e2.spec.ts
File Naming:
modal.e2e.spec.ts (all sign-up tests)sign-up-critical-path.spec.ts (WRONG - no separate files)sign-up-validation.spec.ts (WRONG)// 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
| 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:
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');
}
}
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:
tests/ for existing page objects firstBasePage when:waitForPageLoad(), getCurrentUrl())isVisible(), waitForVisible())helpers.ts when:generateUniqueEmail(), generateTestUser())createTestUser(), cleanupTestData())expectNotificationToContain())seedDatabase(), resetState())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!',
};
}
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: 'user@test.com', password: 'pass123' });
await expect(page).toHaveURL('/dashboard');
},
);
});
Tag Categories:
@critical, @high, @medium, @low@e2e@signup, @signin, @dashboard@SIGNUP-E2E-001, @LOGIN-E2E-002### 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: