无法在无头模式下使用 watir Webdriver 执行按钮元素的 onclick 事件 javascript

Can't get a button element's onclick event javascript to execute using watir webdriver in headless mode

本文关键字:按钮 执行 元素 javascript 事件 onclick Webdriver watir 模式      更新时间:2023-09-26

我正在使用Cucumber和watir-webdriver使用无头浏览器为我的应用程序编写自动测试。我正在尝试自动单击下面的"应用过滤器"按钮,该按钮运行一个 javascript 函数来应用用户定义的过滤条件来对表中的数据进行排序。

<button id="apply_filter" style="width: 190px;" onclick="javascript:
                        document.getElementById( 'orderBy' ).value='none';
                        document.getElementById( 'sortOrder' ).value='none';
                        document.getElementById( 'input' ).action='gl_tasks';
                        document.getElementById( 'page' ).value=1;
                        document.getElementById( 'input' ).submit();" type="button">

问题是表中的订单数据似乎没有被正确过滤,因为我在表的第一行中没有得到预期的订单号。我相信我用来设置过滤器的代码是正确的,因此我相信我的问题是执行附加到apply_filter按钮的 onclick 事件的 javascript。

下面是我定义的用于执行按钮单击的函数。注释掉的代码片段是我尝试过的替代解决方案,但没有任何成功。

def apply_filter_button
 b = @browser.div(:id => 'tabs').frame(:id => 'container').div(:id =>'sidebar').button(:id => 'apply_filter')
 puts "Does the Apply Filter button exist"
 puts b.exists?
 b.click
 #b.when_present.click
 #el = @browser.driver.find_element(:id, "apply_filter")
 #@browser.driver.action.click(el).perform
 #b.fire_event "onclick"
end

当我使用以下任一方式时

    b.click
    b.when_present.click
    @browser.driver.action.click(el).perform

我得到的结果相同,这是不正确的,因为我希望订单号 5010064 在表的第一行,但我得到了1636348。这表示未正确应用设置的过滤器:

Does the Apply Filter button exist
true
RSpec::Expectations::ExpectationNotMetError: expected "1636348" to include "5010064"
./features/step_definitions/atom_steps.rb:275:in `/^I should see ('d+) as the order number for line item ('d+)$/'
E:'ATOM_TEST'AcceptanceTest'atom'features'filtering.feature:16:in `And I should see 5010064 as the order number for line item 1'
1 scenario (1 failed)
11 steps (1 failed, 10 passed)
1m33.625s
Process finished with exit code 1

当我尝试使用

b.fire_event "onclick"

我得到以下瓦蒂尔异常:

Does the Apply Filter button exist
true
Selenium::WebDriver::Error::UnknownError: TypeError: Cannot set property [MouseEvent].altKey that has only a getter to false. (injected script#24) (net.sourceforge.htmlunit.corejs.javascript.EcmaError)
[remote server] net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime(ScriptRuntime.java):3629:in `constructError'
[remote server] net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime(ScriptRuntime.java):3613:in `constructError'
[remote server] net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime(ScriptRuntime.java):3634:in `typeError'
[remote server] net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime(ScriptRuntime.java):3656:in `typeError3'
[remote server] com.gargoylesoftware.htmlunit.javascript.SimpleScriptable(SimpleScriptable.java):462:in `isReadOnlySettable'
[remote server] net.sourceforge.htmlunit.corejs.javascript.ScriptableObject$GetterSlot(ScriptableObject.java):259:in `setValue'
[remote server] net.sourceforge.htmlunit.corejs.javascript.ScriptableObject(ScriptableObject.java):2796:in `putImpl'
[remote server] net.sourceforge.htmlunit.corejs.javascript.ScriptableObject(ScriptableObject.java):521:in `put'
[remote server] net.sourceforge.htmlunit.corejs.javascript.ScriptableObject(ScriptableObject.java):2479:in `putProperty'
[remote server] net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime(ScriptRuntime.java):1574:in `setObjectProp'
[remote server] net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime(ScriptRuntime.java):1569:in `setObjectProp'
[remote server] net.sourceforge.htmlunit.corejs.javascript.Interpreter(Interpreter.java):1253:in `interpretLoop'
[remote server] net.sourceforge.htmlunit.corejs.javascript.Interpreter(Interpreter.java):798:in `interpret'
[remote server] net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction(InterpretedFunction.java):105:in `call'
[remote server] net.sourceforge.htmlunit.corejs.javascript.ContextFactory(ContextFactory.java):411:in `doTopCall'
[remote server] com.gargoylesoftware.htmlunit.javascript.HtmlUnitContextFactory(HtmlUnitContextFactory.java):309:in `doTopCall'
[remote server] net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime(ScriptRuntime.java):3057:in `doTopCall'
[remote server] net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction(InterpretedFunction.java):103:in `call'
[remote server] com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$4(JavaScriptEngine.java):630:in `doRun'
[remote server] com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$HtmlUnitContextAction(JavaScriptEngine.java):690:in `run'
[remote server] net.sourceforge.htmlunit.corejs.javascript.Context(Context.java):620:in `call'
[remote server] net.sourceforge.htmlunit.corejs.javascript.ContextFactory(ContextFactory.java):513:in `call'
[remote server] com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine(JavaScriptEngine.java):637:in `callFunction'
[remote server] com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine(JavaScriptEngine.java):612:in `callFunction'
[remote server] com.gargoylesoftware.htmlunit.html.HtmlPage(HtmlPage.java):1001:in `executeJavaScriptFunctionIfPossible'
[remote server] org.openqa.selenium.htmlunit.HtmlUnitDriver(HtmlUnitDriver.java):618:in `executeScript'
[remote server] sun.reflect.NativeMethodAccessorImpl():-2:in `invoke0'
[remote server] sun.reflect.NativeMethodAccessorImpl():-1:in `invoke'
[remote server] sun.reflect.DelegatingMethodAccessorImpl():-1:in `invoke'
[remote server] java.lang.reflect.Method():-1:in `invoke'
[remote server] org.openqa.selenium.support.events.EventFiringWebDriver$2(EventFiringWebDriver.java):101:in `invoke'
[remote server] $Proxy14():-1:in `executeScript'
[remote server] org.openqa.selenium.support.events.EventFiringWebDriver(EventFiringWebDriver.java):213:in `executeScript'
[remote server] org.openqa.selenium.remote.server.handler.ExecuteScript(ExecuteScript.java):53:in `call'
[remote server] java.util.concurrent.FutureTask$Sync():-1:in `innerRun'
[remote server] java.util.concurrent.FutureTask():-1:in `run'
[remote server] org.openqa.selenium.remote.server.DefaultSession$1(DefaultSession.java):168:in `run'
[remote server] java.util.concurrent.ThreadPoolExecutor():-1:in `runWorker'
[remote server] java.util.concurrent.ThreadPoolExecutor$Worker():-1:in `run'
[remote server] java.lang.Thread():-1:in `run'
./features/step_definitions/atom_steps.rb:112:in `apply_filter_button'
./features/step_definitions/atom_steps.rb:267:in `/^I click on the apply filter button$/'
E:'ATOM_TEST'AcceptanceTest'atom'features'filtering.feature:13:in `And I click on the apply filter button'

当我使用 ie 浏览器的本地实例运行我的代码时,它会按预期运行。我已经没有关于使用无头浏览器时可能出现的问题的想法。看起来javascript在真正的IE浏览器和无头浏览器之间的处理方式不同。任何建议将不胜感激。

注意我正在使用selenium-server-standalone-2.44.0.jar作为我的无头浏览器。

问题如下:需要更改"应用过滤器"按钮代码,以便将对 document.getElementById( 'input' ) 的引用更改为 document.getElementById( 'task_filter' )。

这就是变化:

<button id="apply_filter" style="width: 190px;" onclick="javascript:
                        document.getElementById( 'orderBy' ).value='none';
                        document.getElementById( 'sortOrder' ).value='none';
                        document.getElementById( 'input' ).action='gl_tasks';
                        document.getElementById( 'page' ).value=1;
                        document.getElementById( 'input' ).submit();" type="button">

<button id="apply_filter" style="width: 190px;" onclick="javascript:
                        document.getElementById( 'orderBy' ).value='none';
                        document.getElementById( 'sortOrder' ).value='none';
                        document.getElementById( 'task_filter' ).action='gl_tasks';
                        document.getElementById( 'page' ).value=1;
                        document.getElementById( 'task_filter' ).submit();" type="button">

如果您查看实际表单的实际 html,它的定义如下:

<form name="input" id="task_filter" action="gl_tasks" method="post">

在我们为IE8设计的应用程序代码中,我们使用document.getElementById('input')调用中name属性的值,而不是id属性的值。所以在IE中,document.getElementById('input')会找到正确的元素,document.getElementById('task_filter')也会找到正确的元素;但是,正确的行为应该只是后者。这就是导致 html 单元无头浏览器无法识别表单元素的原因,因此无法通过 watir-webdriver 单击命令执行 onclick 事件 javascript。

以下是一篇文章,它为我们提供了解决方案的提示:http://www.456bereastreet.com/archive/200802/beware_of_id_and_name_attribute_mixups_when_using_getelementbyid_in_internet_explorer/