我使用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"
我得到以下watir例外:
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在真实浏览器和无头浏览器之间的处理方式不同。任何建议将不胜感激。
注意我正在为无头浏览器使用 selenium-server-standalone-2.44.0.jar 。
答案 0 :(得分:0)
问题如下:需要更改Apply过滤器按钮代码,以便对 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/