如何判断AG Grid加载渲染及动画完成以稳定Playwright测试?
解决AG Grid动画导致Playwright测试不稳定的问题
问题概述
我们使用Playwright测试包含AG Grid的Angular应用时,遇到了测试不稳定的情况:AG Grid的动画(如行展开)会干扰元素交互,当前等待加载指示器消失后立即操作网格,存在两类执行过快的问题:
- 过快点击分页大小选择器会导致下拉框重新关闭
- 过快悬停单元格触发提示框时,提示框会直接消失
我们希望避免使用任意延迟,转而通过DOM变化或AG Grid API来判断网格是否完全加载、渲染且动画完成。
最小复现示例(C#)
using var playwright = await Playwright.CreateAsync(); await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions { Headless = false, }); var context = await browser.NewContextAsync(); var page = await context.NewPageAsync(); await page.GotoAsync("https://c5kg58.csb.app/"); await page.GetByLabel("Page Size").ClickAsync(); await page.WaitForTimeoutAsync(1000); // 等待动画完成,否则分页大小选项会消失 await page.GetByRole(AriaRole.Option, new() { Name = "50" }).ClickAsync();
可行解决方案
1. 观察DOM类判断动画状态
AG Grid在执行动画时会给对应元素添加特定类名,动画结束后自动移除,我们可以等待这些类消失:
- 分页下拉框:点击展开后,下拉框容器会带有
ag-popup-animation类,等待该类消失即可确保动画完成:await page.GetByLabel("Page Size").ClickAsync(); var popupLocator = page.Locator(".ag-popup"); // 先等待弹窗可见,再等待动画类消失 await popupLocator.WaitForAsync(new LocatorWaitForOptions { State = WaitForSelectorState.Visible }); await popupLocator.WaitForAsync(new() { Predicate = locator => locator.EvaluateAsync("el => !el.classList.contains('ag-popup-animation')") }); await page.GetByRole(AriaRole.Option, new() { Name = "50" }).ClickAsync(); - 单元格提示框:提示框元素会带有
ag-tooltip-animation类,同样等待该类消失后再进行断言或交互。
2. 利用AG Grid API监听状态
AG Grid提供了丰富的事件和API来获取组件状态,可通过注入JS代码监听动画相关事件:
- 监听行动画结束:针对行展开/收起动画,可监听
rowAnimationEnd事件:await page.EvaluateAsync(@"() => { return new Promise(resolve => { // 假设网格实例已挂载到window对象,需根据实际项目调整获取方式 const gridApi = window.agGridInstances[0]; gridApi.addEventListener('rowAnimationEnd', resolve); }); }"); - 分页组件状态确认:通过API获取分页面板元素,循环检查动画类是否存在:
await page.GetByLabel("Page Size").ClickAsync(); await page.EvaluateAsync(@"() => { return new Promise(resolve => { const gridApi = window.agGridInstances[0]; const paginationPanel = gridApi.getPaginationPanel(); const checkAnimationComplete = () => { if (!paginationPanel.classList.contains('ag-popup-animation')) { resolve(); } else { requestAnimationFrame(checkAnimationComplete); } }; checkAnimationComplete(); }); }"); await page.GetByRole(AriaRole.Option, new() { Name = "50" }).ClickAsync();
3. 优化Playwright内置等待机制
Playwright的Stable状态等待可以检测元素是否停止布局或DOM变化,适合用来等待动画结束:
await page.GetByLabel("Page Size").ClickAsync(); var sizeOption = page.GetByRole(AriaRole.Option, new() { Name = "50" }); // 等待元素状态稳定(无动画引起的变化) await sizeOption.WaitForAsync(new LocatorWaitForOptions { State = WaitForSelectorState.Stable }); await sizeOption.ClickAsync();
内容的提问来源于stack exchange,提问作者Matt Immer
相关产品推荐
相关产品推荐

