为什么我的Capybara / Poltergeist测试不能从jQuery自动完成字段中选择?


更新:经过我自己的大量艰苦工作后,我解决了这个问题。 我很高兴成为任何需要帮助的人的资源。 这是我工作设置的要点。


我已经尝试了所有可以找到Google和SO的解决方案。 以下是我尝试过的一些不同的事情:

page.execute_script %Q{$('#{selector}').val('#{value}').trigger('keydown')} 

 fill_in field, with: options[:with] page.execute_script %Q{ $('##{field}').trigger('focus') } page.execute_script %Q{ $('##{field}').trigger('keydown') } 

这是失败的:

 page.should have_selector('ul.ui-autocomplete li.ui-menu-item a') 

但是当我在Firebug中查看并在浏览器中测试它时,它肯定存在。

以下是所有细节,包括上述内容的重述。 请记住,自动填充字段在浏览器中正常工作。

listing_integration_spec.rb

 require "spec_helper" describe "Listing Integration" do let!(:user) { login_user } it "lets a user add information listing", js: true do listing = create(:listing, user: user) click_link('Additional Information') click_link('Create') fill_autocomplete('listings_search', with: listing.item_id) end end 

spec/support/feature_helper.rb

 def fill_autocomplete(field, options = {}) fill_in field, with: options[:with] page.execute_script %Q{ $('##{field}').trigger('focus') } page.execute_script %Q{ $('##{field}').trigger('keydown') } selector = %Q{ul.ui-autocomplete li.ui-menu-item a:contains('#{options[:with]}')} page.should have_selector('ul.ui-autocomplete li.ui-menu-item a') page.execute_script %Q{ $("##{selector}").trigger('mouseenter').click() } end 

ERB from view template

    

和Coffeescript:

 $("#listings_search").autocomplete source: (request, response) -> options = term: request.term $.get "/search_listings", options, (data) -> if data.length == 0 alert "No listings found." response data minLength: 2 select: (event, ui) -> add_listing_hash = type: "GET" url: "/add_listing" data: { id: ui.item.id } success: () -> $.ajax(add_listing_hash) 

JS驱动程序通常都是meh,它们很慢而且没有一个单独覆盖100%的function,而且它们通常很古怪而且难以调试,但我相信你现在已经弄明白了。

我有类似的代码片段工作在rails 3.2,minitest和poltergeist 1.3.0(一个ajaxed下拉列表)但是它有一种周期性的断裂没有充分的理由(有人可能会说它有一个恶作剧者?我已经使用了切换测试到目前为止,在selenium和poltergeist之间的几次),不确定为什么autocompleter对你不起作用但感觉就像一个bug,

提交问题到https://github.com/jonleighton/poltergeist (你已经有了? https://github.com/jonleighton/poltergeist/issues/439 ),尝试更改为selenium或webkit,看看它是否有效,你可以如果它让你走出困境,那么在这一个测试中使用不同的驱动程序(它会因为工作的小部件而失去工作时间)。

我在网上找到了几种解决方案,但这些解决方案都不适用于当前版本的Poltergeist,Capybara和Autocomplete。 但是我从他们那里学到了足够的东西来制作一个有效的辅助方法,没有睡眠呼叫。

 def fill_autocomplete(css_id, page, options = {}) find("#{css_id}").native.send_keys options[:with] page.execute_script %{ $('#{css_id}').trigger('focus') } page.execute_script %{ $('#{css_id}').trigger('keydown') } selector = %{ul.ui-autocomplete li.ui-menu-item:contains("#{options[:select]}")} expect(page).to have_selector('ul.ui-autocomplete li.ui-menu-item') page.execute_script %{ $('#{selector}').trigger('mouseenter').click() } end 

用法示例:

 fill_autocomplete( '#contact_filter_company', listing_page, with: 'acm', select: 'Acme' ) 

我有一个page参数,因为我正在使用SitePrism – 如果你不是,你可以将其删除。

我正在使用它:

  • jQuery UI自动完成1.11.2
  • 恶作剧者1.5.1
  • 水豚2.4.4
  • rspec 3.1.0

我能够用Poltergeist测试我的自动填充文本字段而不会有太多麻烦。 要了解的主要内容是Poltergeist的.native.send_keys方法。

将这些代码行实际存在于我的项目中的Cucumber步骤中的摘要汇总在一起:

 find('#username').native.send_keys "the" # this field autocompletes usernames wait_until { all('a', text: "the_username").any? } find('a', text: "the_username").click 

然后我以通常的方式提交表单并在下一页上声明预期结果。

wait_until ( 从Capybara 2中删除的方法的重新实现 )需要一个块,当我们应该停止等待时它返回true。 它比等待5秒或者每次都要快。

 def wait_until(delay = 1) seconds_waited = 0 while ! yield && seconds_waited < Capybara.default_wait_time sleep delay seconds_waited += 1 end raise "Waited for #{Capybara.default_wait_time} seconds but condition did not become true" unless yield end 

我想也许您需要混合触发KEYDOWN,还要将键码设置为DOWN。

例如

 var keyEvent = $.Event("keydown"); keyEvent.keyCode = $.ui.keyCode.DOWN; $("#autocomplete").val("j"); $("#autocomplete").trigger(keyEvent); 

这是一个工作jsfiddle示例,显示自动完成选择的项目: http : //jsfiddle.net/alexkey/74BST/我不确定为什么需要两次触发keydown,但这是一个单独解决的问题(如果有问题)在所有)。

但是我不熟悉你正在使用的unit testing框架,但我希望上面有所帮助。

信用转到JQuery AutoComplete,手动选择第一个搜索项并绑定点击

我正在使用示例代码表单: http : //api.jqueryui.com/autocomplete/#entry-examples

自动完成unit testingjquery-ui团队使用可能对灵感有用: https : //github.com/jquery/jquery-ui/tree/master/tests/unit/autocomplete

也是对密钥的引用: http : //api.jqueryui.com/jQuery.ui.keyCode/

我有这个问题,没有提出的解决方案可以解决它。 尝试查找ul.ui-autocomplete元素时,我的测试总是失败。 我终于注意到,jQuery自动完成将ul附加到html页面的末尾而不是有问题的输入字段。 在我的规范中,我遵循within my_form do明确定位表单的做法,并执行此块中的所有fill_in内容:

 within my_form do fill_autocomplete … end 

当然,这可能永远不会找到附加OUTSIDE这个表单元素的ul 。 我的解决方案很简单:在初始化自动完成时使用jQuery autocomplete的属性appendTo: '#id_of_input_field' 。 现在它可以找到我的ul ,一切正常。