剧作家如何等待匹配多个元素的定位器不可见

bee*_*hor 12 node.js playwright

我试图等待一个指示页面仍在加载并且多次存在于页面上的元素不可见(想想带有加载数据占位符的表)。

Playwright 文档建议使用定位器是最佳实践,因此我最初尝试通过执行以下操作来实现此目的:

locator.waitFor({state: "hidden")
Run Code Online (Sandbox Code Playgroud)

然而,由于定位器非常严格并且只允许匹配一个元素,所以会出现错误。

我现在用下面的代码来做:

page.waitForSelector(".foo .bar", {state: "hidden"})
Run Code Online (Sandbox Code Playgroud)

由于以下几个原因,这并不理想:

  • 我将页面元素存储为页面对象模型中的定位器,并且您似乎无法访问定位器的选择器,这意味着选择器在代码中重复
  • 我相信 page.waitForSelector 将使用 ElementHandle ,这是不鼓励的

有什么办法可以关闭定位器的严格约束吗?或者使用定位器来实现此目的的方法。我知道您可以.count在匹配多个元素的定位器上执行此操作,但我还没有找到将其与等待计数为 0 结合起来的好方法。

bee*_*hor 3

我最终使用该evaluateAll方法完成了这项工作。示例代码:

async waitForAllHidden(locator: Locator, timeout: number = 10000) {
    const start = Date.now()
    const elementsVisible = async () => (
        await locator.evaluateAll(elements =>
            elements.map(element => element.hidden))
    ).includes(false)

    while (await elementsVisible()) {
        if (start + timeout < Date.now()) {
            throw (`Timeout waiting for all elements to be hidden.
                    Locator: ${locator}. Timeout: ${timeout}ms`);
        }
    }
    console.log(`All elements hidden: ${locator}`)
}
Run Code Online (Sandbox Code Playgroud)

2023 年更新:

现在可以使用新方法来实现此目的:

toHaveCount() 例如

await expect(yourLocator).toHaveCount(0);
Run Code Online (Sandbox Code Playgroud)

轮询() 例如

await expect.poll(async () => {
  for (const e of await yourLocator.all()) {
    if (await e.isVisible()) return false
  }
  return true
}, {
  message: 'youLocator is still visible', // optional custom error message
  intervals: [1_000, 2_000, 10_000], // optional polling overrides
  timeout: 10000, // optional timeout override
}).toBe(true);
Run Code Online (Sandbox Code Playgroud)