Playwright 高级页面操作

Playwright 高级页面操作(2025 年最新版)

掌握基础后,高级操作能让你处理现代 Web 应用的复杂场景,如弹窗、iframe、Shadow DOM、文件下载、网络拦截、模拟设备等。下面以 Node.js/TypeScript(Playwright Test)为主,附 Python 对应写法。

1. 处理弹窗与对话框(Alert、Confirm、Prompt、BeforeUnload)

// 监听所有对话框事件
page.on('dialog', async dialog => {
  console.log(`弹窗类型: ${dialog.type()}, 消息: ${dialog.message()}`);

  // 自动接受(alert/confirm/prompt)
  await dialog.accept('输入的文本');  // prompt 时传入值
  // 或拒绝:await dialog.dismiss();
});

// 触发弹窗的操作
await page.getByRole('button', { name: '删除' }).click();

2. 文件下载

// 监听下载事件
const [download] = await Promise.all([
  page.waitForEvent('download'),  // 等待下载开始
  page.getByText('下载文件').click(),
]);

// 获取下载路径并保存
const path = await download.path();          // 本地路径(headless 模式)
await download.saveAs('downloads/myfile.zip');  // 自定义保存路径

// 取消下载
await download.cancel();

3. 文件上传(高级:拖拽上传、剪贴板)

// 拖拽上传(模拟 drag & drop)
await page.locator('#upload-area').dragTo(page.locator('#file-input'), {
  sourcePosition: { x: 10, y: 10 },
  targetPosition: { x: 0, y: 0 },
});

// 剪贴板上传(现代 Web App 常用)
await page.evaluate(() => navigator.clipboard.write([
  new ClipboardItem({ 'image/png': fetch('/image.png').then(r => r.blob()) })
]));

4. iframe 操作

// 定位 iframe 并获取其 contentFrame
const frame = await page.frameLocator('#my-iframe').frame();  // 或 page.frame({ name: 'frameName' })

// 在 iframe 内操作
await frame.getByLabel('用户名').fill('admin');
await frame.locator('button >> text=登录').click();

5. Shadow DOM 操作

// 穿透 Shadow DOM(支持多层)
const shadowInput = page.locator('my-component')
  .locator('pierce >> input[type="password"]');  // pierce 穿透 shadow

await shadowInput.fill('secret');

6. 网络拦截与 Mock(最强大功能之一)

// 拦截所有请求并修改响应
await page.route('**/api/user', async route => {
  // Mock 响应
  await route.fulfill({
    status: 200,
    contentType: 'application/json',
    body: JSON.stringify({ name: 'Mock User', role: 'admin' }),
  });
});

// 拦截并继续(修改请求头)
await page.route('**/*', async route => {
  await route.continue({
    headers: { ...route.request().headers(), 'x-mock': 'true' }
  });
});

// 拦截并中止(模拟网络错误)
await page.route('**/bad-api', route => route.abort('connectionfailed'));

7. 模拟设备与地理位置

// 在 playwright.config.ts 中定义项目,或运行时使用
test.use({ 
  viewport: { width: 375, height: 812 },     // iPhone 尺寸
  deviceScaleFactor: 3,
  isMobile: true,
  hasTouch: true,
  userAgent: 'Mobile Safari',
  locale: 'zh-CN',
  timezoneId: 'Asia/Shanghai',
  geolocation: { longitude: 116.397, latitude: 39.909 },  // 北京
  permissions: ['geolocation'],
});

// 测试中自动生效
await page.goto('https://maps.google.com');

8. 多页面/多上下文(Browser Context)

// 创建独立上下文(隔离 cookie、localStorage)
const context = await browser.newContext();
const page1 = await context.newPage();
const page2 = await context.newPage();

// 模拟多用户登录
const user1 = await browser.newContext({ storageState: 'user1.json' });
const user2 = await browser.newContext({ storageState: 'user2.json' });

9. 截取视频与 Trace(调试神器)

// playwright.config.ts 中启用视频
use: {
  video: 'on-first-retry',  // 仅失败时录制
  trace: 'on',              // 始终记录 trace(包含截图、网络、console)
}

// 测试失败后查看
npx playwright show-trace trace.zip

10. Python 版高级示例(网络拦截 + 下载)

# 网络拦截
def handle_route(route):
    if "api/user" in route.request.url:
        route.fulfill(json={"name": "Mock User"})
    else:
        route.continue_()

page.route("**/api/**", handle_route)

# 文件下载
async with page.expect_download() as download_info:
    await page.get_by_text("下载").click()
download = await download_info.value
await download.save_as("myfile.zip")

最佳实践总结

  • 优先使用 Locator + auto-waiting
  • 网络拦截用于 Mock API、测试错误场景、加速测试(跳过真实请求)。
  • 复杂页面用 frameLocator + pierce 穿透封装组件。
  • 生产测试:开启 trace + video + screenshotOnFailure。
  • 调试技巧:--headed --slowMo 500 慢速运行观察。

这些高级操作能让你轻松应对 99% 的现代 Web 应用场景(如 React/Vue/Angular SPA、Web Components)。下一步建议:用 npx playwright codegen --target=typescript 录制一个复杂页面(如登录 + iframe),看看生成的代码如何处理高级场景。

需要某个高级功能的完整测试用例(如网络 Mock + 多上下文),随时告诉我!

文章已创建 4391

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部