Playwright TypeScript遍历定位器数组时最后一项报浏览器已关闭错误
Playwright遍历定位器数组时触发“Browser has been closed”错误的解决方法
在使用Playwright TypeScript遍历定位器数组时,点击数组内元素(即使修改循环长度)会触发错误:Error: locator.click: Browser has been closed。可复现的测试代码如下:
test('should test menu items', async ({page}) => { await page.goto(`https://ecommerce-playground.lambdatest.io/index.php?common/home`); //line below returns the locators let menuItems = await page.locator("#entry_217841 nav div ul li").all(); //just wanted to confirm menuItems //console.log(menuItems); for (let i=0;i <= (menuItems.length -1); i++ ){ //click Shop by Category to activate the slide out menu await page.getByRole('button', { name: 'Shop by Category' }).click(); //click on the item in the slide out menu await menuItems[i].click(); //console.log(await menuItems2[i].innerText()); } });
问题原因
- 初始通过
await page.locator(...).all()获取的menuItems是页面初始状态的静态元素引用集合,当点击菜单项触发页面导航跳转后,这些引用关联的旧DOM上下文已完全失效。 - 后续循环中调用这些失效的元素引用执行
click操作时,会触发浏览器上下文相关错误,哪怕缩短循环长度,只要涉及到跳转后的复用,问题依然存在。
解决方案
每次循环打开菜单后,重新获取当前页面的菜单项定位器,避免复用跨页面的静态元素引用。修改后的代码如下:
test('should test menu items', async ({page}) => { await page.goto(`https://ecommerce-playground.lambdatest.io/index.php?common/home`); // 先获取菜单项总数,减少重复操作 await page.getByRole('button', { name: 'Shop by Category' }).click(); const menuItemCount = await page.locator("#entry_217841 nav div ul li").count(); await page.getByRole('button', { name: '×' }).click(); // 关闭菜单 for (let i = 0; i < menuItemCount; i++ ){ // 打开侧边菜单 await page.getByRole('button', { name: 'Shop by Category' }).click(); // 动态定位当前页面的第i个菜单项 await page.locator("#entry_217841 nav div ul li").nth(i).click(); // 等待页面加载完成,确保下一次循环的上下文正确 await page.waitForLoadState('networkidle'); } });
关键说明
- 动态定位替代静态数组:使用
locator.nth(i)每次获取当前页面的目标元素,确保定位器始终关联最新的DOM上下文,不会因页面导航失效。 - 预取总数提升效率:先打开菜单获取菜单项总数,避免每次循环重复打开菜单计数。
- 等待页面加载:添加
waitForLoadState('networkidle')确保页面跳转完成后再进入下一次循环,避免操作过早导致异常。
内容的提问来源于stack exchange,提问作者Tony Carreon
相关产品推荐
相关产品推荐

