如何使用capybara DSL测试Select2元素?
我在页面上有一个Select2元素,通过ajax加载结果。 想用capybara / rspec(使用poltergeist驱动程序)测试这个,但是因为Select2元素实际上是作为隐藏字段开始的,然后在处理完结果后填充
- ,没有正常的
select
, fill_in
或者choose
帮手会工作。
我现在拥有的是类似的东西
it "should have a search field for events" do click_link "Select an Event" # this works as expected within('.select2-container') do # works find('.select2-search input').set(event.description[0,5]) # won't work! find(:xpath, "li[text()='#{event.description}']").click end click_button "Search" page.should have_content("Displaying all 2 photos") end
上面的第4行,显然capybara可以找到元素,但值不会改变,Select2永远不会进行ajax调用。 (不能使用普通的fill_in
,因为搜索字段元素没有label,id或name属性)
我创建了一个可以与Cucumber一起使用的帮助器,它没有sleep
所以它比上面的方法更快。 如果您使用Select2提供的createSearchChoice
这也适用。
把它放在features/support/select2_helper.rb
module Select2Helper def select2(value, attrs) first("#s2id_#{attrs[:from]}").click find(".select2-input").set(value) within ".select2-result" do find("span", text: value).click end end end World(Select2Helper)
像这样用它:
Then(/^I select2 "([^"]*)" from "([^"]*)"$/) do |value, select_name| select2 value, from: select_name end
用Rails 4.1.1和Cucumber 1.3.15测试。
不要挠挠头,这样做会有效
select "option_name_here", :from => "Id Of Your select field"
我尝试了每一个模块和每一个该死的东西,最后只是通过简单的代码行完成了没有任何助手和这样的事情。
对于页面上的多个select2组件,我创建了以下适用于我的帮助器方法:
def select2(id, value) page.execute_script %Q{ i = $('#s2id_#{id} .select2-input'); i.trigger('keydown').val('#{value}').trigger('keyup'); } sleep 2 find('div.select2-result-label').click end def remove_all_from_select2(id) page.execute_script %Q{ $('#s2id_#{id} .select2-choices a').click(); } end def remove_from_select2(id, value) page.execute_script %Q{ $('#s2id_#{id} .select2-choices div:contains("#{value}")').closest('li').find('a').click(); } end
我能够通过使用page.execute_script
手动将所需的值和keyup
事件page.execute_script
到搜索字段中来解决这个问题。
it "should have a search field for events" do click_link "Select an Event" page.execute_script("i = $('.select2-container input').first(); i.val('#{event.description[0,4]}').trigger('keyup');"); sleep 2 find('.select2-results li:first-child').click click_button "Search" page.should have_content("Displaying all 2 photos") end
对于那些苦苦挣扎Select2 倍数的人 :
奇怪的是我发现select_tag有多个:true似乎热衷于为每个条目生成html,如:
value
而不是
value
无益地将内容放在跨度之外。
为了用水豚来测试它我有两种方法:
# for most select2s def select2_select(value, id) # This methods requires @javascript in the Scenario first("#s2id_#{id}").click find(".select2-input").set(value) within ".select2-result" do if !find("span").text.empty? find("span", text: value).click elsif !find("div").text.empty? find("div", text: value).click else fail 'neither span nor div within this select2, did you get the id of the select2 right?' end end end # for select_tag select2s which are multiple:true def select2_select_multiple(select_these, id) # This methods requires @javascript in the Scenario [select_these].flatten.each do | value | first("#s2id_#{id}").click found = false within("#select2-drop") do all('li.select2-result').each do | result | unless found if result.text == value result.click found = true end end end end end end
后者因我的喜好而过于苛刻,所以我尽可能使用第一个,并希望最终取代后者。
HAML使用:
= select_tag "some_id", options_for_select(['hello','world']), multiple: true, include_blank: true
JS:
$("#some_id").select2();
灵感来自这个答案和一个Capybara select2帮手,我想出了同一页面上单选和多选的多个select2字段看起来很健壮的东西:
def select2(value, attrs) s2c = first("#s2id_#{attrs[:from]}") (s2c.first(".select2-choice") || s2c.find(".select2-choices")).click find(:xpath, "//body").all("input.select2-input")[-1].set(value) page.execute_script(%|$("input.select2-input:visible").keyup();|) drop_container = ".select2-results" find(:xpath, "//body").all("#{drop_container} li", text: value)[-1].click end
这适用于带有远程数据源的下拉样式select2:
def select2(value, from:) execute_script("$('##{from}').select2('open')") find(".select2-search__field").set(value) find(".select2-results li", text: /#{value}/).click end
from
必须是构建select2的常规select标记的ID。
我有两个远程select2s。 我在第一个中搜索一个字符串,根据找到的结果,第二个字符串被填充。 在尝试了capybara-select2 gem以及此处列出的所有解决方案后,我不得不提出自己的解决方案,因为它们都没有用于搜索。 在我的情况下,我选择的并不重要,所以没有尝试选择具有特定值的结果标签。 希望这有助于我的情况。
Given(/^I have selected "(.*?)" category$/) do |arg1| page.find(:css, ".select2-choice.select2-default").click page.find(:css, "#s2id_autogen1_search").set "Dip Boya" sleep 2 page.all(:css, '.select2-result-label')[1].click end Given(/^I have selected "(.*?)" variation$/) do |arg1| page.find(:css, ".select2-choice.select2-default").click page.all(:css, '.select2-result-label')[1].click end
简单回答:
page.find('.select2-drop-active .select2-input').set('foo') page.find('.select2-drop-active .select2-input').native.send_keys(:return)
嘿,我不确定是否还有人关心,但我也有这个问题,我找到了一个简单的方法来处理它。
首先,我不会将类添加到每个下拉选择中,而是像全局那样添加:
class CollectionSelectInput < SimpleForm::Inputs::CollectionSelectInput def input_html_classes super.push('chosen-select') end end
因此,当我开始遇到capybara无法使用select2下拉列表的问题时,我的解决方案是仅在测试环境中使用全局推送:
class CollectionSelectInput < SimpleForm::Inputs::CollectionSelectInput unless Rails.env.test? def input_html_classes super.push('chosen-select') end end end
我曾经使用capybara-select2gem,但似乎它不再被维护:(
def select2(id, value) find("##{id} ~ span.select2").click within ".select2-results" do find("li", text: value).click end end
这是针对更新版本的select2的解决方案 – 特别是select2-rails(4.0.0)gem:
将它放在features/support/feature_helpers.rb
,然后将其包含在spec_helper.rb
文件中, config.include FeatureHelpers
在RSpec.configure do |config|
config.include FeatureHelpers
。 块。
module FeatureHelpers def fill_in_select2(container_selector, with: '') page.execute_script %Q{ i = $('#{container_selector} .select2-search__field'); i.trigger('keydown').val('#{with}').trigger('keyup'); } sleep 2 find('.select2-results__option--highlighted').click end end
然后像在fill_in
中使用fill_in_select2
一样使用fill_in
,但是包含具有适当前缀符号的容器元素的类或id。 (例如fill_in_select2 '.actions_list', with: 'bob@testmaster1000.com'
)。
注意 :这会在输入文本后选择下拉列表中的第一个元素。
在Rails 4.2.5.2,Capybara 2.7.1和Capybara-Webkit 1.11.1中进行了测试
在花费了更长的时间之后,我终于通过使用xpath选择器构建Brandon McInnis的答案了。
module Select2Helper def fill_in_select2(container_selector, with: '') page.execute_script %Q{ i = $('#{container_selector} .select2-search__field'); i.trigger('keydown').val('#{with}').trigger('keyup'); } sleep 2 find(:xpath, "//body").all("#{container_selector} li", text: with)[-1].click end end
对于select2 4.0与capybara-webkit的组合,我尝试了基于execute_script的解决方案,但它们不起作用,因为capybara无法找到生成的’li’元素。 我终于根据send_keys确定了这个简单的解决方案。 因为我使用远程数据源,所以我添加了一个小睡眠以允许结果显示:
module Select2Helpers def fill_in_select2(field_name, with: '') field = find("##{field_name}") parent = field.find(:xpath, './/..') ui = parent.find('.select2-search__field') ui.send_keys(with) sleep 0.5 ui.send_keys(:enter) sleep 0.1 end end
请注意,您可能需要更新到最新的capybara-webkit(1.14.0)才能使其正常工作。
https://github.com/goodwill/capybara-select2与js: true
指定对我来说很好。 干杯
这对我来说有用,即使使用select2 AJAX自动完成:
find('#user_id').sibling('span.select2').click find('.select2-search__field').set('ABCDEF') find('.select2-results li', text: 'ABCDEF').click
您可以使用capybara-select-2 gem ,它将为您完成所有工作。 只需将search: true
传递给helper选项即可进行Ajax调用:
select2 'Marriage', from: 'Event', search: true
- 用水豚进行平行selenium试验
- 为什么我的Capybara / Poltergeist测试不能从jQuery自动完成字段中选择?
- 在RSpec请求规范中使用Capybara时,设置自定义请求标头的最佳方法是什么?
- Capybara不会填写表格字段(虽然它找到了)
- Capybara webkit的数据库清理问题
- 在rails上的ruby中运行测试时有一个默认端口
- RSpec和数据库清理程序 – 将某些对象永久保留在测试数据库中
- Capybara :: ElementNotFound仅适用于特拉维斯的所有规格
- Capybara-webkit引发了Capybara :: Driver :: Webkit :: WebkitInvalidResponseError