我有一种情况,表单上的一个按钮,动画到视图中,如果在动画进行过程中发生了element.click(),它就无法工作。
element.click()不会抛出错误,不会返回失败状态(它返回未定义),它只是默默无效。
我已经尝试确保没有禁用被点击的元素,并且显示(可见)但是即使这两个测试都成功,点击也会失败。
如果我在点击之前等待0.4秒,它就会起作用,因为动画已经完成。
如果我能检测到点击工作的时间,并且如果没有自动重试,我不想添加延迟(这是不可靠的,并且是坦率的躲避)。
是否有通用的方法来检测click()是否实际上已被操作,因此我可以使用重试循环直到它为止?
答案 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不会将点击坐标调整为缩放级别。