本文介绍了WebDriver click() 与 JavaScript click()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

故事:

在 StackOverflow 上,我看到用户报告说他们无法通过 selenium WebDriver单击"命令单击元素,并且可以通过执行脚本通过 JavaScript 单击来解决该问题.

Here on StackOverflow, I've seen users reporting that they cannot click an element via selenium WebDriver "click" command and can work around it with a JavaScript click by executing a script.

Python 示例:

element = driver.find_element_by_id("myid")
driver.execute_script("arguments[0].click();", element)

WebDriverJS/Protractor 中的示例:

Example in WebDriverJS/Protractor:

var elm = $("#myid");
browser.executeScript("arguments[0].click();", elm.getWebElement());

问题:

为什么在常规 WebDriver 单击不起作用时单击通过 JavaScript"起作用?这究竟是什么时候发生的,这种解决方法的缺点是什么(如果有的话)?

Why is clicking "via JavaScript" works when a regular WebDriver click does not? When exactly is this happening and what is the downside of this workaround (if any)?

推荐答案

目前接受的答案所建议的相反,当谈到让 WebDriver 执行单击操作和在 JavaScript 中执行操作之间的区别时,没有任何特定于 PhantomJS 的内容.

Contrarily to what the currently accepted answer suggests, there's nothing specific to PhantomJS when it comes to the difference between having WebDriver do a click and doing it in JavaScript.

这两种方法的本质区别对所有浏览器都是通用的,可以非常简单地解释:

The essential difference between the two methods is common to all browsers and can be explained pretty simply:

  • WebDriver:当 WebDriver 执行点击时,它会尽其所能模拟真实用户使用浏览器时发生的情况.假设您有一个元素 A,它是一个按钮上面写着点击我"和一个元素 B,它是一个 div 元素,它是透明的,但它的尺寸和 zIndex 设置为完全覆盖 A.然后你告诉 WebDriver单击 A.WebDriver 将模拟单击,以便 B 首先接收单击.为什么?因为 B 覆盖 A,如果用户尝试点击 A,那么 B 将首先获得该事件.A 最终是否会获得 click 事件取决于 B 如何处理该事件.无论如何,在这种情况下,WebDriver 的行为与真实用户尝试单击 A 时的行为相同.

  • WebDriver: When WebDriver does the click, it attempts as best as it can to simulate what happens when a real user uses the browser. Suppose you have an element A which is a button that says "Click me" and an element B which is a div element which is transparent but has its dimensions and zIndex set so that it completely covers A. Then you tell WebDriver to click A. WebDriver will simulate the click so that B receives the click first. Why? Because B covers A, and if a user were to try to click on A, then B would get the event first. Whether or not A would eventually get the click event depends on how B handles the event. At any rate, the behavior with WebDriver in this case is the same as when a real user tries to click on A.

JavaScript:现在,假设您使用 JavaScript 来执行 A.click().这种点击方法无法重现用户尝试点击 A 时的真实情况. JavaScript 将 click 事件直接发送给 A,而 B 不会收到任何事件.

JavaScript: Now, suppose you use JavaScript to do A.click(). This method of clicking does not reproduce what really happens when the user tries to click A. JavaScript sends the click event directly to A, and B will not get any event.

正如我上面提到的,WebDriver 将尽量模拟真实用户使用浏览器时发生的情况.事实是 DOM 可以包含用户无法与之交互的元素,而 WebDriver 不允许您单击这些元素.除了我提到的重叠情况之外,这也意味着无法点击不可见元素.我在 Stack Overflow 问题中看到的一个常见情况是有人试图与 DOM 中已经存在的 GUI 元素进行交互,但只有在操作其他元素时才可见.下拉菜单有时会发生这种情况:在选择菜单项之前,您必须先单击弹出下拉菜单的按钮.如果有人试图在菜单可见之前单击菜单项,WebDriver 会犹豫并说该元素无法操作.如果此人随后尝试使用 JavaScript 执行此操作,它将起作用,因为该事件会直接传递给元素,而与可见性无关.

As I mentioned above WebDriver will try to simulate as best it can what happens when a real user is using a browser. The fact of the matter is that the DOM can contain elements that a user cannot interact with, and WebDriver won't allow you to click on these element. Besides the overlapping case I mentioned, this also entails that invisible elements cannot be clicked. A common case I see in Stack Overflow questions is someone who is trying to interact with a GUI element that already exists in the DOM but becomes visible only when some other element has been manipulated. This sometimes happens with dropdown menus: you have to first click on the button the brings up the dropdown before a menu item can be selected. If someone tries to click the menu item before the menu is visible, WebDriver will balk and say that the element cannot be manipulated. If the person then tries to do it with JavaScript, it will work because the event is delivered directly to the element, irrespective of visibility.

如果您使用 Selenium 来测试应用程序,我对这个问题的回答是几乎从不".总的来说,您的 Selenium 测试应该重现用户会用浏览器做.以下拉菜单为例:测试应该先点击弹出下拉菜单的按钮,然后再点击菜单项.如果 GUI 出现问题,因为按钮不可见,或者按钮无法显示菜单项或类似情况,那么您的测试将失败并且您已经检测到错误.如果您使用 JavaScript 四处点击,您将无法通过自动化测试检测到这些错误.

If you are using Selenium for testing an application, my answer to this question is "almost never". By and large, your Selenium test should reproduce what a user would do with the browser. Taking the example of the drop down menu: a test should click on the button that brings up the drop down first, and then click on the menu item. If there is a problem with the GUI because the button is invisible, or the button fails to show the menu items, or something similar, then your test will fail and you'll have detected the bug. If you use JavaScript to click around, you won't be able to detect these bugs through automated testing.

我说几乎从不"是因为可能存在使用 JavaScript 有意义的例外情况.不过,它们应该非常罕见.

I say "almost never" because there may be exceptions where it makes sense to use JavaScript. They should be very rare, though.

如果您使用 Selenium 来抓取网站,那么尝试重现用户行为并不那么重要.因此,使用 JavaScript 绕过 GUI 问题不大.

If you are using Selenium for scraping sites, then it is not as critical to attempt to reproduce user behavior. So using JavaScript to bypass the GUI is less of an issue.

这篇关于WebDriver click() 与 JavaScript click()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 09:26