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 + 多上下文),随时告诉我!