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

时间:2018-04-23 10:39:52

标签: puppeteer

我有一种情况,表单上的一个按钮,动画到视图中,如果在动画进行过程中发生了element.click(),它就无法工作。

element.click()不会抛出错误,不会返回失败状态(它返回未定义),它只是默默无效。

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

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

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

是否有通用的方法来检测click()是否实际上已被操作,因此我可以使用重试循环直到它为止?

5 个答案:

答案 0 :(得分:6)

我已经确定了发生了什么,为什么我没有收到错误,以及如何解决这个问题。

主要问题在于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();

问题在于,因为视图(div)是动画元素的boundingBox()正在变化,并且在请求框位置和完成click()之间,元素已移动或不可单击。 / p>

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

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

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

在我的情况下,这就像在点击之前将at 10,10添加到我的测试脚本一样简单,或者特别是

test-id "form1.button3" at 10,10 click

它的动作如下,在这种情况下,视图从左侧动画回来。

00.571 [selector.test,61] at 8,410
test-id "main.add" info tag button displayed at -84,410 size 116,33 enabled not selected check "Add"
test-id "main.add" info tag button displayed at -11,410 size 116,33 enabled not selected check "Add"
test-id "main.add" info tag button displayed at 8,410 size 116,33 enabled not selected check "Add"
00.947 [selector.test,61] click

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

答案 1 :(得分:1)

page.click()返回一个promise,请确保按原样处理它,但是请注意,如果不将它作为xpath引用,则可能会出现问题。这就是为了让它发挥作用我必须做的事情。我尝试过使用querySelectors并以这种方式与对象进行交互,但我遇到了问题。

page.evaluate(()=>{
await Promise.all([
    page.click("a[id=tab-default-2__item]"),
    //The page.waitFor is set to 15000 for my personal use. 
    //Feel free to play around with this.
    page.waitFor(15000)
]);
});    

我希望这会有所帮助。

答案 2 :(得分:0)

我使用助手功能来处理点击


    click: async function (page, selector) {

        //selector must to exists
        await page.waitForSelector(selector, {visible: true, timeout: 30000})
        //give time to extra rendering time
        await page.waitFor(500)

        try {
            await page.click(selector)
        } catch (error) {
          console.log("error clicking " + selector + " : " + error ;
        }
    }

使用page.waitFor(500)在理论世界中是一个非常糟糕的做法,但是在使用复杂接口的实用程序中,它消除了很多误报。

我宁愿等待500毫秒而不是获得误报。

答案 3 :(得分:0)

具有超时功能的通用点击受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 err;
}

答案 4 :(得分:0)

我有一个非常类似的问题:我曾经使用过Puppeteer脚本,现在突然单击停止工作。罪魁祸首是变焦级别。当我将缩放比例切换到100%后,它又开始工作。显然,Puppeteer不会将点击坐标调整为缩放级别。