Playwright 获取元素是否存在、获取元素数量 (Node.js)

文章介绍了在Playwright中如何优雅地判断页面元素是否存在,包括使用isVisible方法的问题,以及智能等待的实现。作者提出了一种通过catch异常来判断元素是否存在的方式,并提到了这种方法在元素状态快速变化时可能出现的问题。此外,还讨论了获取元素数量的方法,但指出waitFor在匹配多个元素时可能抛出异常,建议使用expect.poll替代。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

正文

很多时候我们需要绕过一些东西或者做预处理,需要判断一个元素是否存在,需要一个即使找不到元素也没用关系的处理方法。

官方提供了 locator.isVisible() 用来获取元素是否存在的。

但是!它会立即返回结果,不会智能等待。而且官方已经移除了 timeout 入参,所以就算传 timeout 也不会等待。

所以要么使用固定等待来使用这个方法

export async function sleep(delay: number) {
  await new Promise((resolve) => setTimeout(resolve, delay))
}


export async function locatorExists(locator: Locator, delay = 3000): Promise<boolean> {

  await sleep(delay)
  const exists = await locator.isVisible()

  return exists
}

但是这显示是很丑陋的,我看到了别人的解决方案可以智能等待。
ref: https://github.com/microsoft/playwright/issues/12224

export async function locatorExists(locator: Locator, timeout = 3000): Promise<boolean> {

  const __locatorExists = async (__locator: Locator) =>
    !((await __locator.waitFor({ timeout: timeout }).catch((e: Error) => e)) instanceof Error)
  const exists = await __locatorExists(locator)

  return exists
}

不过这个方法也有弊端,试想一下这个场景

  • 你完成了最后一个任务
  • 此时获取 去完成 按钮列表,接口可能花了200ms,弹出浮层可能花了 100ms,此时元素才从 1 -> 0
  • 而你的代码是密集执行的,这时 Playwright 会脏读到元素,而返回 exists = true

因此当元素从有到无的时候,这个方法就会有问题,解决方案就是再提供一个 locatorNotExists 方法,内部 waitFor方法传入 {state: “detached”}


举一反三,还可以写一个获取元素数量的方法

这个方法已经失效了,waitFor() 被证实 locator 匹配多条内容时会抛出异常。
可以直接在断言时使用 expect.poll() ,例:await expect.poll(() => page.locator(‘.winner’).count()).toBe(3)

export async function locatorLength(locator: Locator, timeout = 1000): Promise<number> {
  if (await locatorExists(locator, timeout)) {
    return await locator.count()
  }

  return 0
}

使用例

test('Start the task', async ({ tasksDetailPage }) => {
    if (await utils.locatorExists(tasksDetailPage.startBtnLocator)) {
        await tasksDetailPage.cancel()
    }
    await tasksDetailPage.start()

    await expect(page.getByText(/^Success$/)).toBeVisible()
})
test('Complete the task', async ({ tasksDetailPage }) => {

    const beforeTasksCount = await utils.locatorLength(tasksDetailPage.taskIcons)
    await tasksDetailPage.complete()
    const afterTasksCount = await utils.locatorLength(tasksDetailPage.taskIcons)
    
    expect(beforeTasksCount - 1).toEqual(studyPlanDetailPage)
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值