首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >WebDriver click()与 JavaScript click()对比?

WebDriver click()与 JavaScript click()对比?
EN

Stack Overflow用户
提问于 2018-03-01 01:32:14
回答 2查看 0关注 0票数 0

我看到用户报告他们不能通过selenium WebDriver“单击”命令单击元素,并且可以通过执行脚本通过JavaScript单击来解决此问题。

Python中的示例:

代码语言:javascript
运行
复制
element = driver.find_element_by_id("myid")
driver.execute_script("arguments[0].click();", element)

WebDriverJS /量角器中的示例:

代码语言:javascript
运行
复制
var elm = $("#myid");
browser.executeScript("arguments[0].click();", elm.getWebElement());

问题:

为什么点击“通过JavaScript”在普通的WebDriver点击没有的情况下工作?何时发生这种情况,以及该解决方法(如果有)的缺点是什么?

我个人使用这种解决方法时没有完全理解为什么我必须这样做,以及它可能导致什么问题。

EN

回答 2

Stack Overflow用户

发布于 2018-03-01 09:38:02

对于WebDriver执行点击操作和在JavaScript中执行操作之间的区别,PhantomJS没有任何特定功能。

区别

这两种方法之间的本质区别对所有浏览器都很常见,可以很简单地解释:

  • WebDriver:当WebDriver执行点击时,它会尽可能地模拟真实用户使用浏览器时发生的情况。假设你有一个元素A,它是一个按钮,表示“点击我”,元素B是一个div透明的元素,但它的尺寸和zIndex设置完全覆盖了A.然后你告诉WebDriver点击A. WebDriver将会模拟点击以便B 首先收到点击。为什么?因为B覆盖A,并且如果用户尝试点击A,则B将首先获得事件。A是否最终会获得点击事件取决于B如何处理事件。无论如何,在这种情况下,WebDriver的行为与真实用户尝试点击A时的行为相同。
  • JavaScript:现在,假设您使用JavaScript来完成A.click()这种点击方法并不能重现用户尝试点击A时真正发生的事情。JavaScriptclick直接将事件发送给A,而B不会收到任何事件。

为什么单击WebDriver时JavaScript不起作用?

正如我上面提到的,WebDriver会尽量模拟真实用户使用浏览器时发生的情况。事实是,DOM可以包含用户无法与之交互的元素,WebDriver不允许您单击这些元素。除了我提到的重叠情况外,这也意味着不可见的元素不能被点击。我在堆栈溢出问题中看到的一个常见情况是,尝试与已存在于DOM中的GUI元素进行交互,但只有在处理了其他元素时才可见。这有时会在下拉菜单中发生:您必须先点击按钮才能选择菜单项,然后调出下拉菜单。如果有人在菜单可见之前尝试点击菜单项,如果这个人然后试图用JavaScript来做,它将会工作,因为事件直接传递给元素,而不管可见性如何。

您应该何时使用JavaScript进行点击?

如果您使用Selenium来测试应用程序,我对这个问题的回答是“几乎从不”。总的来说,您的Selenium测试应该重现用户使用浏览器所做的事情。以下拉菜单为例:测试应该点击首先弹出下拉菜单的按钮,然后点击菜单项。如果因为按钮不可见而导致GUI出现问题,或者按钮未能显示菜单项或类似内容,则测试将失败,并且您将检测到该错误。如果您使用JavaScript来点击,您将无法通过自动测试检测到这些错误。

我说“几乎从不”,因为在使用JavaScript时可能会有例外。不过,它们应该非常少见。

如果您使用Selenium来抓取网站,那么尝试重现用户行为并不重要。所以使用JavaScript来绕过GUI不是一个问题。

票数 0
EN

Stack Overflow用户

发布于 2018-03-01 11:31:46

当JavaScript HTMLElement.click()执行click事件的默认操作时,驱动程序执行的点击试图模拟真实用户的行为尽可能接近,即使元素不可交互。

差异是:

  • 驱动程序通过将元素滚动到视图中并确保元素是可交互的,确保该元素可见。 司机会提出一个错误:
    • 当点击坐标顶部的元素不是目标元素或后代时
    • 当元素没有正面大小或完全透明时
    • 当元素是禁用的输入或按​​钮(属性/属性disabledtrue
    • 当元素禁用了鼠标指针(CSS pointer-eventsnone

    JavaScript HTMLElement.click()将始终执行默认操作,或者如果该元素为禁用状态,最多只会默默失败。

  • 如果可调焦的话,该驱动程序有望将该元件带入焦点。 JavaScript HTMLElement.click()不会。
  • 预计驱动程序会像真实用户一样发出所有事件(mousemove,mousedown,mouseup,click,...)。 JavaScript HTMLElement.click()只发出click事件。页面可能依赖于这些额外的事件,并且如果它们没有被发射,其行为可能会有所不同。 这些是司机用Chrome浏览器点击发出的事件: mouseover {target:#topic, clientX:222, clientY:343, isTrusted:true, ... } mousemove {target:#topic, clientX:222, clientY:343, isTrusted:true, ... } mousedown {target:#topic, clientX:222, clientY:343, isTrusted:true, ... } mouseup {target:#topic, clientX:222, clientY:343, isTrusted:true, ... } click {target:#topic, clientX:222, clientY:343, isTrusted:true, ... } 这是用JavaScript注入发射的事件: click {target:#topic, clientX:0, clientY:0, isTrusted:false, ... }
  • JavaScript发出的事件.click() 不受信任,并且可能不会调用默认操作: https://developer.mozilla.org/en/docs/Web/API/Event/isTrusted https://googlechrome.github.io/samples/event-istrusted/index.html 请注意,有些驱动程序仍在生成不受信任的事件。PhantomJS 2.1版本就是这种情况。
  • JavaScript发出的事件.click() 没有点击的坐标。 属性clientX, clientY, screenX, screenY, layerX, layerY设置为0。该页面可能依赖于他们,并可能会有不同的表现。

使用JavaScript .click()来取消某些数据可能没有问题,但它不在测试环境中。由于它不模拟用户的行为,因此它打败了测试的目的。因此,如果来自驱动程序的点击失败,那么真正的用户很可能也无法在相同的条件下执行相同的点击。

当我们期望它成功时,驱动程序是否无法点击某个元素?

  • 由于延迟或过渡效应,目标元素尚未可见/可交互。 一些例子 : https://developer.mozilla.org/fr/docs/Web(下拉导航菜单) http://materializecss.com/side-nav.html(下拉边栏) Workarrounds: 添加一个服务员等待可见度,最小尺寸或稳定位置: // wait visible browser.wait(ExpectedConditions.visibilityOf(elem), 5000); // wait visible and not disabled browser.wait(ExpectedConditions.elementToBeClickable(elem), 5000); // wait for minimum width browser.wait(function minimumWidth() { return elem.getSize().then(size => size.width > 50); }, 5000); 重试点击,直到成功: browser.wait(function clickSuccessful() { return elem.click().then(() => true, (ex) => false); }, 5000); 添加一个匹配动画/转换时间的延迟: browser.sleep(250);
  • 一旦滚动到视图中,目标元素最终会被浮动元素覆盖: 驱动程序自动将元素滚动到视图中以使其可见。如果页面包含浮动/粘滞元素(菜单,广告,页脚,通知,cookie策略..),则该元素可能会被覆盖并且不再可见/可交互。 例如:https : //twitter.com/?lang=en 解决方法: 将窗口的大小设置为较大的值以避免滚动或浮动元素。 将元素移到具有负Y偏移量的元素上,然后单击它: browser.actions() .mouseMove(elem, {x: 0, y: -250}) .click() .perform(); 点击前将元素滚动到窗口的中心: browser.executeScript(function scrollCenter(elem) { var win = elem.ownerDocument.defaultView || window, box = elem.getBoundingClientRect(), dy = box.top - (win.innerHeight - box.height) / 2; win.scrollTo(win.pageXOffset, win.pageYOffset + dy); }, element); element.click(); 如果无法避免,请隐藏浮动元素: browser.executeScript(function scrollCenter(elem) { elem.style.display = 'none'; }, element);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100007468

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档