元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
入门指南
Playwright安装与配置
环境要求与验证
第一个自动化测试脚本
▶
核心概念
Browser对象详解
Page对象操作指南
Frame与上下文管理
网络请求拦截与Mock
▶
元素定位与操作
CSS选择器实战
XPath高级定位技巧
文本定位与正则匹配
动态元素等待策略
▶
高级操作指南
文件上传下载处理
多标签页与弹窗管理
浏览器上下文隔离
设备模拟与地理定位
▶
测试框架集成
Jest集成配置
Mocha测试报告生成
持续集成CI/CD配置
▶
最佳实践
测试用例组织结构
性能优化策略
跨浏览器测试方案
▶
疑难解答
常见错误代码解析
元素定位失败分析
浏览器启动问题排查
▶
录制功能指南
录制功能基础入门
录制脚本生成与编辑
高级录制配置与技巧
录制脚本调试与优化
发布时间:
2025-03-27 19:13
↑
☰
# 动态元素等待策略 本文将详细介绍Playwright中的等待策略,帮助你有效处理动态加载的元素和异步操作,确保自动化测试的稳定性。 ## 基本等待策略 ### 1. 自动等待 ```typescript // Playwright默认会自动等待元素可见和可操作 await page.getByRole('button').click(); // 自动等待表单元素准备就绪 await page.getByLabel('用户名').fill('admin'); // 自动等待导航完成 await page.goto('https://example.com'); ``` ### 2. 显式等待 ```typescript // 等待元素出现 await page.waitForSelector('.loading', { state: 'visible' }); // 等待元素消失 await page.waitForSelector('.loading', { state: 'hidden' }); // 等待元素可用 await page.waitForSelector('button', { state: 'attached' }); // 等待元素被移除 await page.waitForSelector('button', { state: 'detached' }); ``` ## 高级等待策略 ### 1. 网络请求等待 ```typescript // 等待API请求完成 await page.waitForResponse('**/api/data'); // 等待特定状态码 await page.waitForResponse(response => { return response.url().includes('/api/data') && response.status() === 200; }); // 等待多个请求完成 await Promise.all([ page.waitForResponse('**/api/user'), page.waitForResponse('**/api/profile'), page.click('button#refresh') ]); ``` ### 2. 条件等待 ```typescript // 等待元素包含特定文本 await page.waitForSelector('div', { hasText: '加载完成' }); // 等待元素属性变化 await page.waitForSelector('button[disabled="false"]'); // 等待元素数量变化 await page.waitForFunction(() => { return document.querySelectorAll('.item').length > 5; }); ``` ## 超时处理 ### 1. 全局超时设置 ```typescript // 配置文件中设置全局超时 // playwright.config.ts import { PlaywrightTestConfig } from '@playwright/test'; const config: PlaywrightTestConfig = { timeout: 30000, // 30秒 expect: { timeout: 5000 // 断言超时5秒 } }; ``` ### 2. 局部超时设置 ```typescript // 单个操作的超时设置 await page.click('button', { timeout: 10000 }); // 等待元素的超时设置 await page.waitForSelector('.loading', { state: 'hidden', timeout: 15000 }); // 自定义等待的超时设置 await page.waitForFunction( () => document.readyState === 'complete', { timeout: 20000 } ); ``` ## 最佳实践 ### 1. 智能等待策略 ```typescript // 组合使用多个等待条件 await Promise.all([ page.waitForResponse('**/api/data'), page.waitForSelector('.loading', { state: 'hidden' }), page.click('button#submit') ]); // 使用race处理多种可能的状态 await Promise.race([ page.waitForSelector('.success'), page.waitForSelector('.error') ]); ``` ### 2. 自定义等待函数 ```typescript // 创建可重用的等待函数 async function waitForTableLoad(page) { await page.waitForFunction(() => { const table = document.querySelector('table'); return table && table.rows.length > 1; }); } // 创建条件等待函数 async function waitForCondition(page, condition, timeout = 30000) { await page.waitForFunction(condition, { timeout }); } ``` ## 调试技巧 ### 1. 等待状态检查 ```typescript // 检查元素是否存在 const isVisible = await page.isVisible('.loading'); // 检查元素是否可用 const isEnabled = await page.isEnabled('button'); // 检查元素是否被选中 const isChecked = await page.isChecked('input[type="checkbox"]'); ``` ### 2. 调试辅助 ```typescript // 添加调试日志 await page.waitForSelector('.loading', { state: 'hidden', timeout: 10000 }).catch(e => { console.log('等待加载状态消失超时'); throw e; }); // 使用暂停调试 await page.pause(); ``` ## 常见问题 ### 1. 等待超时 ```typescript // 处理等待超时异常 try { await page.waitForSelector('.dynamic-content', { timeout: 5000 }); } catch (error) { console.error('等待元素超时:', error); // 执行降级处理或重试逻辑 } // 实现重试机制 async function retryWait(action, maxAttempts = 3) { for (let i = 0; i < maxAttempts; i++) { try { await action(); return; } catch (error) { if (i === maxAttempts - 1) throw error; await page.waitForTimeout(1000); } } } ``` ### 2. 动态内容处理 ```typescript // 处理动态加载的内容 await page.waitForFunction(() => { const element = document.querySelector('.dynamic-list'); return element && element.children.length > 0; }); // 处理无限滚动 async function waitForMoreItems(page, currentCount) { await page.waitForFunction( (count) => document.querySelectorAll('.item').length > count, currentCount ); } ``` ## 下一步 1. 了解[文件上传下载处理](/article/playwright/advanced/file-transfer) 2. 探索[多标签页与弹窗管理](/article/playwright/advanced/tab-management) 3. 学习[浏览器上下文隔离](/article/playwright/advanced/browser-context) ## 参考资料 - [Playwright等待机制](https://playwright.dev/docs/actionability) - [Playwright超时配置](https://playwright.dev/docs/test-timeouts) - [Playwright自动等待](https://playwright.dev/docs/auth)