webapp-playwright-testing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Web Application Testing

Web应用测试

This skill enables comprehensive browser-based testing and debugging for web applications using Playwright MCP. It provides live browser interaction, UI validation, screenshot capture, console log inspection, and accessibility verification to ensure your web application behaves as expected.
Activation: This skill is triggered when you need to interact with a browser, validate UI elements, capture screenshots, or debug web application issues.
本技能借助Playwright MCP实现Web应用的全流程浏览器测试与调试,提供实时浏览器交互、UI验证、截图捕获、控制台日志查看及可访问性校验功能,确保Web应用符合预期行为。
触发条件: 当你需要与浏览器交互、验证UI元素、捕获截图或调试Web应用问题时,将触发本技能。

When to Use This Skill

适用场景

Use this skill when you need to:
  • Create Playwright tests for web applications
  • Test frontend functionality in a real browser
  • Verify UI behavior and interactions
  • Debug web application issues
  • Capture screenshots for documentation or debugging
  • Inspect browser console logs
  • Validate form submissions and user flows
  • Check responsive design across viewports
在以下场景中使用本技能:
  • 为Web应用创建Playwright测试用例
  • 在真实浏览器中测试前端功能
  • 验证UI行为与交互逻辑
  • 调试Web应用问题
  • 捕获截图用于文档或调试
  • 查看浏览器控制台日志
  • 验证表单提交与用户流程
  • 跨视口检查响应式设计

Prerequisites

前置条件

  • Node.js installed on the system (v18+)
  • A locally running web application (or accessible URL)
  • Playwright MCP server configured
  • Playwright will be installed automatically if not present

  • 系统已安装Node.js(v18+版本)
  • 本地运行的Web应用(或可访问的URL)
  • 已配置Playwright MCP服务器
  • 若未安装Playwright,将自动完成安装

Playwright MCP Tools Reference

Playwright MCP工具参考

Navigation & Interaction

导航与交互

ToolPurposeExample Query
browser_navigate
Go to a URL"Navigate to http://localhost:3000/login"
browser_click
Click elements"Click the Submit button"
browser_fill_form
Fill input fields"Fill the email field with test@example.com"
browser_hover
Hover over elements"Hover over the dropdown menu"
browser_press_key
Keyboard input"Press Enter"
browser_select_option
Select from dropdown"Select 'Option 1' from the dropdown"
工具用途示例指令
browser_navigate
访问指定URL"Navigate to http://localhost:3000/login"
browser_click
点击元素"Click the Submit button"
browser_fill_form
填充输入字段"Fill the email field with test@example.com"
browser_hover
悬停在元素上"Hover over the dropdown menu"
browser_press_key
键盘输入"Press Enter"
browser_select_option
选择下拉选项"Select 'Option 1' from the dropdown"

Validation & Capture

验证与捕获

ToolPurposeExample Query
browser_snapshot
Get accessibility tree"Get the accessibility snapshot"
browser_take_screenshot
Capture visual state"Take a screenshot"
browser_console_messages
View browser logs"Check for console errors"
browser_network_requests
Monitor API calls"Show network requests"
工具用途示例指令
browser_snapshot
获取可访问性树"Get the accessibility snapshot"
browser_take_screenshot
捕获页面视觉状态"Take a screenshot"
browser_console_messages
查看浏览器日志"Check for console errors"
browser_network_requests
监控API调用"Show network requests"

Browser Management

浏览器管理

ToolPurposeExample Query
browser_resize
Change viewport"Resize to mobile (375x667)"
browser_tabs
Manage browser tabs"List open tabs"
browser_close
Close browser"Close the browser"
工具用途示例指令
browser_resize
更改视口尺寸"Resize to mobile (375x667)"
browser_tabs
管理浏览器标签页"List open tabs"
browser_close
关闭浏览器"Close the browser"

Core Capabilities

核心功能

1. Browser Automation

1. 浏览器自动化

  • Navigate to URLs
  • Click buttons and links
  • Fill form fields
  • Select dropdowns
  • Handle dialogs and alerts
  • 导航至指定URL
  • 点击按钮与链接
  • 填充表单字段
  • 选择下拉菜单
  • 处理对话框与提示框

2. Verification

2. 验证功能

  • Assert element presence
  • Verify text content
  • Check element visibility
  • Validate URLs
  • Test responsive behavior
  • 断言元素存在性
  • 验证文本内容
  • 检查元素可见性
  • 校验URL正确性
  • 测试响应式表现

3. Debugging

3. 调试功能

  • Capture screenshots
  • View console logs
  • Inspect network requests
  • Debug failed tests
  • 捕获截图
  • 查看控制台日志
  • 检查网络请求
  • 调试失败的测试用例

Usage Examples

使用示例

Example 1: Basic Navigation Test

示例1:基础导航测试

typescript
// Navigate to a page and verify heading
await page.goto('http://localhost:3000');
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
typescript
// Navigate to a page and verify heading
await page.goto('http://localhost:3000');
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();

Example 2: Form Interaction (Role-Based Locators)

示例2:表单交互(基于角色的定位器)

typescript
// Fill out and submit a form using accessible locators
await page.getByRole('textbox', { name: 'Username' }).fill('testuser');
await page.getByRole('textbox', { name: 'Password' }).fill('password123');
await page.getByRole('button', { name: 'Login' }).click();
await expect(page).toHaveURL(/.*dashboard/);
typescript
// Fill out and submit a form using accessible locators
await page.getByRole('textbox', { name: 'Username' }).fill('testuser');
await page.getByRole('textbox', { name: 'Password' }).fill('password123');
await page.getByRole('button', { name: 'Login' }).click();
await expect(page).toHaveURL(/.*dashboard/);

Example 3: Screenshot Capture

示例3:截图捕获

typescript
// Capture a full-page screenshot for debugging
await page.screenshot({ path: 'debug.png', fullPage: true });
typescript
// Capture a full-page screenshot for debugging
await page.screenshot({ path: 'debug.png', fullPage: true });

Example 4: Accessibility Snapshot Assertion

示例4:可访问性快照断言

typescript
// Verify page structure with aria snapshot
await expect(page.getByRole('main')).toMatchAriaSnapshot(`
  - main:
    - heading "Welcome" [level=1]
    - form:
      - textbox "Email"
      - textbox "Password"
      - button "Login"
`);
typescript
// Verify page structure with aria snapshot
await expect(page.getByRole('main')).toMatchAriaSnapshot(`
  - main:
    - heading "Welcome" [level=1]
    - form:
      - textbox "Email"
      - textbox "Password"
      - button "Login"
`);

Guidelines

操作指南

  1. Always verify the app is running - Check that the local server is accessible before running tests
  2. Use explicit waits - Wait for elements or navigation to complete before interacting
  3. Capture screenshots on failure - Take screenshots to help debug issues
  4. Clean up resources - Always close the browser when done
  5. Handle timeouts gracefully - Set reasonable timeouts for slow operations
  6. Test incrementally - Start with simple interactions before complex flows
  7. Use selectors wisely - Prefer data-testid or role-based selectors over CSS classes
  1. 始终验证应用运行状态 - 运行测试前确认本地服务器可正常访问
  2. 使用显式等待 - 交互前等待元素加载或导航完成
  3. 失败时捕获截图 - 借助截图辅助调试问题
  4. 清理资源 - 测试完成后务必关闭浏览器
  5. 优雅处理超时 - 为慢速操作设置合理超时时间
  6. 增量式测试 - 先测试简单交互,再推进到复杂流程
  7. 合理使用定位器 - 优先选择data-testid或基于角色的定位器,而非CSS类

Common Patterns

常见模式

Pattern: Wait for Element (Role-Based)

模式:等待元素(基于角色)

typescript
await page.getByRole('button', { name: 'Submit' }).waitFor({ state: 'visible' });
typescript
await page.getByRole('button', { name: 'Submit' }).waitFor({ state: 'visible' });

Pattern: Check if Element Exists

模式:检查元素是否存在

typescript
const exists = await page.getByRole('alert').count() > 0;
typescript
const exists = await page.getByRole('alert').count() > 0;

Pattern: Capture Console Logs

模式:捕获控制台日志

typescript
page.on('console', msg => console.log(`[${msg.type()}] ${msg.text()}`));
typescript
page.on('console', msg => console.log(`[${msg.type()}] ${msg.text()}`));

Pattern: Handle Errors with Screenshot

模式:结合截图处理错误

typescript
try {
  await page.getByRole('button', { name: 'Submit' }).click();
} catch (error) {
  await page.screenshot({ path: 'error.png' });
  throw error;
}
typescript
try {
  await page.getByRole('button', { name: 'Submit' }).click();
} catch (error) {
  await page.screenshot({ path: 'error.png' });
  throw error;
}

Pattern: Test Responsive Viewports

模式:测试响应式视口

typescript
const viewports = [
  { width: 375, height: 667, name: 'mobile' },
  { width: 768, height: 1024, name: 'tablet' },
  { width: 1920, height: 1080, name: 'desktop' },
];

for (const vp of viewports) {
  await page.setViewportSize({ width: vp.width, height: vp.height });
  await page.screenshot({ path: `${vp.name}.png` });
}

typescript
const viewports = [
  { width: 375, height: 667, name: 'mobile' },
  { width: 768, height: 1024, name: 'tablet' },
  { width: 1920, height: 1080, name: 'desktop' },
];

for (const vp of viewports) {
  await page.setViewportSize({ width: vp.width, height: vp.height });
  await page.screenshot({ path: `${vp.name}.png` });
}

Step-by-Step Workflows

分步工作流

Workflow 1: Validate a Page with Playwright MCP

工作流1:使用Playwright MCP验证页面

  1. Navigate to the page
    "Navigate to http://localhost:3000/login"
  2. Get accessibility snapshot
    "Get the accessibility snapshot"
  3. Verify expected elements exist
    • Check for form fields, buttons, headings in the snapshot
  4. Take a screenshot for documentation
    "Take a screenshot"
  5. Check for console errors
    "Show console messages"
  1. 访问目标页面
    "Navigate to http://localhost:3000/login"
  2. 获取可访问性快照
    "Get the accessibility snapshot"
  3. 验证预期元素是否存在
    • 在快照中检查表单字段、按钮、标题等元素
  4. 捕获截图用于文档
    "Take a screenshot"
  5. 检查控制台错误
    "Show console messages"

Workflow 2: Debug a Failing Test

工作流2:调试失败的测试用例

  1. Navigate to the problematic page
    "Navigate to http://localhost:3000/checkout"
  2. Capture initial state
    "Take a screenshot"
  3. Get accessibility snapshot to understand structure
    "Get the accessibility snapshot"
  4. Identify the correct locator from the snapshot
  5. Test the interaction
    "Click the 'Add to Cart' button"
  6. Verify result and capture evidence
    "Take a screenshot"
    "Check for console errors"
  1. 访问问题页面
    "Navigate to http://localhost:3000/checkout"
  2. 捕获初始状态
    "Take a screenshot"
  3. 获取可访问性快照以了解页面结构
    "Get the accessibility snapshot"
  4. 从快照中确定正确的定位器
  5. 测试交互逻辑
    "Click the 'Add to Cart' button"
  6. 验证结果并捕获证据
    "Take a screenshot"
    "Check for console errors"

Workflow 3: Test Responsive Design

工作流3:测试响应式设计

  1. Navigate to the page
    "Navigate to http://localhost:3000"
  2. Test mobile viewport
    "Resize browser to 375x667"
    "Take a screenshot"
    "Verify hamburger menu is visible"
  3. Test tablet viewport
    "Resize browser to 768x1024"
    "Take a screenshot"
  4. Test desktop viewport
    "Resize browser to 1920x1080"
    "Verify navigation links are visible"

  1. 访问目标页面
    "Navigate to http://localhost:3000"
  2. 测试移动端视口
    "Resize browser to 375x667"
    "Take a screenshot"
    "Verify hamburger menu is visible"
  3. 测试平板端视口
    "Resize browser to 768x1024"
    "Take a screenshot"
  4. 测试桌面端视口
    "Resize browser to 1920x1080"
    "Verify navigation links are visible"

Troubleshooting

故障排除

ProblemCauseSolution
Element not foundWrong locator or element not renderedUse
browser_snapshot
to verify structure
Timeout waiting for elementElement hidden or slow to loadCheck for overlays, increase timeout
Strict mode violationMultiple elements match locatorAdd more specific filters like
{ exact: true }
Click interceptedAnother element covering targetScroll into view or wait for overlay to close
Console errors in appJavaScript runtime errorsUse
browser_console_messages
to debug
Screenshot blankPage not fully loadedWait for network idle or specific element
Form submission failsValidation errors not visibleCheck for error messages in snapshot

问题原因解决方案
元素未找到定位器错误或元素未渲染使用
browser_snapshot
验证页面结构
等待元素超时元素隐藏或加载缓慢检查是否有遮罩层,增加超时时间
严格模式违规多个元素匹配定位器添加更具体的筛选条件,如
{ exact: true }
点击被拦截目标元素被其他元素覆盖滚动至可见区域或等待遮罩层关闭
应用控制台报错JavaScript运行时错误使用
browser_console_messages
调试
截图空白页面未完全加载等待网络空闲或特定元素加载完成
表单提交失败验证错误不可见在快照中检查错误提示信息

Locator Strategy (Priority Order)

定位器策略(优先级顺序)

typescript
// ✅ BEST: Role-based (accessible, resilient)
page.getByRole('button', { name: 'Submit' })
page.getByRole('textbox', { name: 'Email' })
page.getByRole('link', { name: 'Sign up' })

// ✅ GOOD: User-facing text
page.getByLabel('Email address')
page.getByPlaceholder('Enter your email')
page.getByText('Welcome back')

// ✅ GOOD: Test IDs (stable, explicit)
page.getByTestId('submit-button')

// ⚠️ AVOID: CSS selectors (brittle)
page.locator('.btn-primary')

// ❌ NEVER: XPath (extremely brittle)
page.locator('//div[@class="container"]/button[1]')

typescript
// ✅ 最优:基于角色(可访问、稳定)
page.getByRole('button', { name: 'Submit' })
page.getByRole('textbox', { name: 'Email' })
page.getByRole('link', { name: 'Sign up' })

// ✅ 良好:面向用户的文本
page.getByLabel('Email address')
page.getByPlaceholder('Enter your email')
page.getByText('Welcome back')

// ✅ 良好:测试ID(稳定、明确)
page.getByTestId('submit-button')

// ⚠️ 尽量避免:CSS选择器(脆弱)
page.locator('.btn-primary')

// ❌ 绝对避免:XPath(极度脆弱)
page.locator('//div[@class="container"]/button[1]')

Limitations

局限性

  • Requires Node.js environment (v18+)
  • Cannot test native mobile apps (use Appium or Detox instead)
  • Complex authentication flows may require session storage or API login
  • Some modern frameworks with shadow DOM require specific configuration
  • Heavy animations may require disabling for stable tests

  • 依赖Node.js环境(v18+)
  • 无法测试原生移动应用(建议使用Appium或Detox)
  • 复杂认证流程可能需要会话存储或API登录
  • 部分包含Shadow DOM的现代框架需要特定配置
  • 复杂动画可能需要禁用以保证测试稳定性

References

参考资料

  • Locator Strategies Guide - Detailed locator patterns and best practices
  • Common Test Patterns - Reusable test patterns and utilities
  • Page Object Model Guide - POM implementation and best practices
  • API Testing Guide - API testing, mocking, and request interception
  • Test Helper Utilities - JavaScript helper functions

  • Locator Strategies Guide - 详细的定位器模式与最佳实践
  • Common Test Patterns - 可复用的测试模式与工具
  • Page Object Model Guide - POM实现与最佳实践
  • API Testing Guide - API测试、Mock与请求拦截
  • Test Helper Utilities - JavaScript辅助函数

Quick Commands

快速指令

TaskPlaywright MCP Query
Open page"Navigate to {URL}"
Check structure"Get the accessibility snapshot"
Capture evidence"Take a screenshot"
Fill form"Fill the {field} with {value}"
Click element"Click the {name} button"
Check errors"Show console messages"
Test mobile"Resize browser to 375x667"
任务Playwright MCP指令
打开页面"Navigate to {URL}"
检查页面结构"Get the accessibility snapshot"
捕获证据"Take a screenshot"
填充表单"Fill the {field} with {value}"
点击元素"Click the {name} button"
检查错误"Show console messages"
测试移动端"Resize browser to 375x667"