什么会阻止 capybara/selenium 悬停在可见元素上?
What would prevent capybara/selenium from hovering over a visible element?
我正在为网页编写自动化测试。我无法分享任何具体细节,所以我正在寻找的只是一些一般性的头脑风暴,以帮助我找出导致问题的原因。一个远景,我知道,但我已经沉迷于这个问题。
网页上有一个 id="troublesome" 的元素。在手动测试中,将鼠标悬停在#troublesome 上会导致它消失,并在其位置弹出其他内容(应该如此)。我正在尝试使用自动化测试(Capybara、selenium 驱动程序、ruby)验证弹出窗口是否在悬停时发生。但是,无论我使用什么技术,悬停都不起作用。
访问该页面时可见麻烦。它不会被屏幕尺寸截断。水豚可以毫不费力地找到它并阅读它的文字和属性。即常规的 ol' find("#troublesome").text 将 return 正确的文本。
但是,我无法使用 Capybara 在不执行 javascript 的情况下点击#troublesome。
即find("#troublesome").click 不会做任何事情(它也不会抛出任何错误)。我必须使用 find("#troublesome").execute_script("this.click()") 来点击它。
但我不需要点击它。我只需要将鼠标悬停在上面即可。
使用水豚:
find("#troublesome").hover --> 将不起作用。也没有抛出错误。测试一直持续到失败,因为它找不到预期的结果。告诉 ruby 睡觉(however_many_seconds)没有帮助。
使用硒:
page.driver.browser.action.move_to(find("#troublesome").native).perform --> 这也不起作用。同样,没有抛出任何错误。
使用触发器:
find("#troublesome").trigger(:mouseover) --> 不起作用,因为 selenium 驱动程序不支持触发器(而且我不想使用其他驱动程序)。
使用jquery:
行不通。网站不使用 jquery
尝试使用 javascript 强制 :hover 在元素上为真无效:
mouseHover = 'var x = document.createEvent("MouseEvent");
x.initMouseEvent("鼠标悬停", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
document.getElementById("麻烦").dispatchEvent(x);'
page.execute_script(鼠标悬停)
(我可以将 mouseOver 更改为点击,但它会点击!)
显然,鼠标悬停不是 'trusted' 浏览器(但点击是),所以把它作为一个选项有点没用,不是吗?
我已经通过在 within("#id") do...end 块中工作尝试了上述所有方法。没有区别。
我什至尝试过非常规的方法让鼠标悬停在#troublesome:
find("#troublesome").right_click --> 鼠标直接移到#troublesome 上,右击,元素上方会弹出一个菜单!!!!!!
很明显,在我的自动化测试期间鼠标悬停在#troublesome 上,但它没有在浏览器上注册。该网站没有窃听。当我手动操作时悬停有效。
我可以在网页上找到其他元素并将鼠标悬停在它们上面就好了。事实上,我什至试过将鼠标放在另一个元素上,然后将它从那里移动到#troublesome,如下所示:
page.driver.browser.action.move_to(find("#somethingElse").native, 1200, -50).perform
这行不通,但是如果我将坐标调整到#somethingElse 下面的第三个元素,这将触发第三个元素的悬停状态,所以很明显这个策略在原则上和实践中都可行,但不适用于#麻烦!
请注意,#somethingElse 和 'third element' 存在于与 #troublesome 的祖先 div 相同 'heirarchy' 的 div 上。
网页上有iframe,但是#troublesome不在iframe上。
网页正文各处插入了随机脚本标签。我不知道那些脚本标签在做什么,因为我看不到代码。
#troublesome 变成了我的 Moby Dick。
这条鲸鱼快把我逼疯了。我已经投入了太多时间。我现在不能放弃,否则所有那些小时的辛劳都将白费。
请帮忙。
谢谢。
find("#troublesome").hover
page.driver.browser.action.move_to(find("#troublesome").native).perform
find("#troublesome").trigger(:mouseover)
mouseHover = 'var x = document.createEvent("MouseEvent");
x.initMouseEvent("鼠标悬停", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
document.getElementById("myDiv").dispatchEvent(x);'
page.execute_script(鼠标悬停)
page.driver.browser.action.move_to(find("#somethingElse").native, 1200, -50).perform
除了标准 capybara/rspec 失败日志外,没有其他错误消息,因为它找不到应该在悬停在 #troublesome
上时弹出的元素
我现在知道问题所在了,而且我有一个解决方案(虽然有点老套)。
问题是由于 iframe 覆盖了整个屏幕。这会阻止 selenium 悬停在#troublesome 上,即使#troublesome 不在 iframe 中并且#troublesome 的 z-index 设置为较高的数字(从而迫使它位于顶层)。
手动悬停有效,但使用 selenium 悬停失败。我相信这是一个错误,所以我已经在 selenium 的 github 上报告了它。
一个有效的解决方案是使用 javascript 强制 iframe 缩小,然后悬停(现在应该可以),然后使用 javascript 到 return iframe 到满屏幕(以免影响其他方面的测试)。
shrink_frame = 'document.getElementById("#frame").setAttribute("style", "width: 100px; height 100px");'
page.execute_script(shrink_frame)
这不是一个理想的解决方案,因为这显然不是真正的用户与网页交互的方式,但这是可以接受的,因为这是由于 selenium 错误并且手动测试有效。
您 运行 遇到的问题是因为 https://jsfiddle.net/pwo7zuL2/1/ 示例中的“.hoverme”元素大小为 0x0 像素(这也是您无法点击它的原因).大小为 0x0,因为它只包含绝对定位的元素,在计算父级的自动大小时,这些元素在技术上不计算在内。如果不是尝试将鼠标悬停在 .hoverme 元素上,而是将鼠标悬停在元素的可见绝对定位子元素(实际上具有大小)上,悬停将正常工作(这是您在示例中手动执行时实际执行的操作) .
find('#next').hover
我正在为网页编写自动化测试。我无法分享任何具体细节,所以我正在寻找的只是一些一般性的头脑风暴,以帮助我找出导致问题的原因。一个远景,我知道,但我已经沉迷于这个问题。
网页上有一个 id="troublesome" 的元素。在手动测试中,将鼠标悬停在#troublesome 上会导致它消失,并在其位置弹出其他内容(应该如此)。我正在尝试使用自动化测试(Capybara、selenium 驱动程序、ruby)验证弹出窗口是否在悬停时发生。但是,无论我使用什么技术,悬停都不起作用。
访问该页面时可见麻烦。它不会被屏幕尺寸截断。水豚可以毫不费力地找到它并阅读它的文字和属性。即常规的 ol' find("#troublesome").text 将 return 正确的文本。
但是,我无法使用 Capybara 在不执行 javascript 的情况下点击#troublesome。
即find("#troublesome").click 不会做任何事情(它也不会抛出任何错误)。我必须使用 find("#troublesome").execute_script("this.click()") 来点击它。
但我不需要点击它。我只需要将鼠标悬停在上面即可。
使用水豚:
find("#troublesome").hover --> 将不起作用。也没有抛出错误。测试一直持续到失败,因为它找不到预期的结果。告诉 ruby 睡觉(however_many_seconds)没有帮助。
使用硒:
page.driver.browser.action.move_to(find("#troublesome").native).perform --> 这也不起作用。同样,没有抛出任何错误。
使用触发器:
find("#troublesome").trigger(:mouseover) --> 不起作用,因为 selenium 驱动程序不支持触发器(而且我不想使用其他驱动程序)。
使用jquery:
行不通。网站不使用 jquery
尝试使用 javascript 强制 :hover 在元素上为真无效:
mouseHover = 'var x = document.createEvent("MouseEvent"); x.initMouseEvent("鼠标悬停", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); document.getElementById("麻烦").dispatchEvent(x);'
page.execute_script(鼠标悬停)
(我可以将 mouseOver 更改为点击,但它会点击!) 显然,鼠标悬停不是 'trusted' 浏览器(但点击是),所以把它作为一个选项有点没用,不是吗?
我已经通过在 within("#id") do...end 块中工作尝试了上述所有方法。没有区别。
我什至尝试过非常规的方法让鼠标悬停在#troublesome:
find("#troublesome").right_click --> 鼠标直接移到#troublesome 上,右击,元素上方会弹出一个菜单!!!!!!
很明显,在我的自动化测试期间鼠标悬停在#troublesome 上,但它没有在浏览器上注册。该网站没有窃听。当我手动操作时悬停有效。
我可以在网页上找到其他元素并将鼠标悬停在它们上面就好了。事实上,我什至试过将鼠标放在另一个元素上,然后将它从那里移动到#troublesome,如下所示:
page.driver.browser.action.move_to(find("#somethingElse").native, 1200, -50).perform
这行不通,但是如果我将坐标调整到#somethingElse 下面的第三个元素,这将触发第三个元素的悬停状态,所以很明显这个策略在原则上和实践中都可行,但不适用于#麻烦!
请注意,#somethingElse 和 'third element' 存在于与 #troublesome 的祖先 div 相同 'heirarchy' 的 div 上。
网页上有iframe,但是#troublesome不在iframe上。
网页正文各处插入了随机脚本标签。我不知道那些脚本标签在做什么,因为我看不到代码。
#troublesome 变成了我的 Moby Dick。
这条鲸鱼快把我逼疯了。我已经投入了太多时间。我现在不能放弃,否则所有那些小时的辛劳都将白费。
请帮忙。
谢谢。
find("#troublesome").hover
page.driver.browser.action.move_to(find("#troublesome").native).perform
find("#troublesome").trigger(:mouseover)
mouseHover = 'var x = document.createEvent("MouseEvent"); x.initMouseEvent("鼠标悬停", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); document.getElementById("myDiv").dispatchEvent(x);'
page.execute_script(鼠标悬停)
page.driver.browser.action.move_to(find("#somethingElse").native, 1200, -50).perform
除了标准 capybara/rspec 失败日志外,没有其他错误消息,因为它找不到应该在悬停在 #troublesome
上时弹出的元素我现在知道问题所在了,而且我有一个解决方案(虽然有点老套)。
问题是由于 iframe 覆盖了整个屏幕。这会阻止 selenium 悬停在#troublesome 上,即使#troublesome 不在 iframe 中并且#troublesome 的 z-index 设置为较高的数字(从而迫使它位于顶层)。
手动悬停有效,但使用 selenium 悬停失败。我相信这是一个错误,所以我已经在 selenium 的 github 上报告了它。
一个有效的解决方案是使用 javascript 强制 iframe 缩小,然后悬停(现在应该可以),然后使用 javascript 到 return iframe 到满屏幕(以免影响其他方面的测试)。
shrink_frame = 'document.getElementById("#frame").setAttribute("style", "width: 100px; height 100px");'
page.execute_script(shrink_frame)
这不是一个理想的解决方案,因为这显然不是真正的用户与网页交互的方式,但这是可以接受的,因为这是由于 selenium 错误并且手动测试有效。
您 运行 遇到的问题是因为 https://jsfiddle.net/pwo7zuL2/1/ 示例中的“.hoverme”元素大小为 0x0 像素(这也是您无法点击它的原因).大小为 0x0,因为它只包含绝对定位的元素,在计算父级的自动大小时,这些元素在技术上不计算在内。如果不是尝试将鼠标悬停在 .hoverme 元素上,而是将鼠标悬停在元素的可见绝对定位子元素(实际上具有大小)上,悬停将正常工作(这是您在示例中手动执行时实际执行的操作) .
find('#next').hover