puppeteer element.click()不工作,不会抛出错误

Aus*_*nce 7 puppeteer

我有一种情况,在窗体上的一个按钮,动画到视图中,如果在动画正在进行中发生element.click(),它不起作用.

element.click()不会抛出错误,不会返回失败的状态(它返回undefined)它只是默默地不起作用.

我已经尝试确保没有禁用被点击的元素,并且显示(可见),但即使这两个测试都成功,点击也会失败.

如果我在点击前等待0.4秒,它会起作用,因为动画已经完成.

如果我可以检测到点击工作的时间,如果没有自动重试,我不想要添加延迟(这是不可靠的,并且是坦率的躲避).

是否有一种通用的方法来检测click()是否实际上已经被操作,所以我可以使用重试循环直到它呢?

Aus*_*nce 11

我已确定正在发生的事情,为什么没有收到错误以及如何解决该问题。

主要问题在于element.click()工作方式。使用DEBUG="puppeteer:*"我能够看到内部发生了什么。什么element.click()实际上做的是: -

const box = element.boundingBox();
const x = box.x + (box.width/2);
const y = box.y + (box.height/2);
page.mouse.move(x,y);
page.mouse.down();
sleep(delay);
page.mouse.up();
Run Code Online (Sandbox Code Playgroud)

问题在于,因为视图(div)使元素的boundingBox()处于动画状态,并且在询问框位置和完成click()的时间之间,元素已移动或不可单击。

不会引发错误(承诺被拒绝),因为它只是用鼠标单击视口中的一个点,而不链接到任何元素。鼠标事件被发送,只是没有响应。

一种解决方法是添加足够的延迟以允许动画完成。另一个是在测试期间禁用动画。

对我来说,解决方案是等待元素的位置稳定在其目标位置,即我旋转查询boundingBox()并等待x,y报告先前确定的元素的位置。

就我而言,这at 10,10就像单击之前添加到我的测试脚本中一样简单,或者

test-id "form1.button3" at 10,10 click
Run Code Online (Sandbox Code Playgroud)

实际上,它的工作方式如下,在这种情况下,视图是从左侧向后动画化的。

00.571 [selector.test,61] at 8,410
以-84,410大小显示的test-id“ main.add”信息标签按钮大小116,33启用未选中检查“ Add”
显示为-11,410大小的test-id“ main.add”信息标签按钮启用了116,33尺寸未选中检查“ Add”
以8,410大小显示的test-id“ main.add”信息标签按钮116,33启用未选中检查“ Add”
00.947 [selector.test,61]点击

对于持续移动的元素或被其他东西覆盖的元素,它将不起作用。对于这些情况,请尝试page.evaluate(el => el.click(), element)。


Aus*_*nce 5

具有超时功能的通用点击,灵感来自 Andrea 的答案。一旦元素可点击,这个就会返回,因此不会减慢测试速度。

click: async function (page, selector, timeout = 30000) {

    await page.waitForSelector(selector, { visible: true, timeout })

    let error;
    while (timeout > 0) {
        try {
            await page.click(selector);
            return;
        } catch (e) {
            await page.waitFor(100);
            timeout -= 100;
            error = e;
        }
    }
    throw error;
}
Run Code Online (Sandbox Code Playgroud)