如何使用capybara DSL测试Select2元素?

时间:2012-10-07 18:12:21

标签: ruby-on-rails capybara capybara-webkit jquery-select2

我在页面上有一个Select2元素,可以通过ajax加载结果。想用capybara / rspec(使用poltergeist驱动程序)来测试这个,但是因为Select2元素实际上是作为隐藏字段开始的,然后在处理完结果后填充<ul>,没有正常的{{1 }},selectfill_in助手可以使用。

我现在拥有的是像

choose

上面第4行,显然capybara可以找到元素,但值不会改变,Select2永远不会进行ajax调用。 (不能在那里使用普通 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 因为搜索字段元素没有标签,id或名称属性)

17 个答案:

答案 0 :(得分:8)

我创建了一个可以与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进行测试。

答案 1 :(得分:7)

不要挠挠头,这样做会有效

select "option_name_here", :from => "Id Of Your select field"

我尝试了每一个模块和每一个该死的东西,最后只是通过简单的代码行完成了没有任何助手和这样的事情。

答案 2 :(得分:4)

对于页面上的多个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

答案 3 :(得分:3)

我可以使用page.execute_script手动将所需的值和keyup事件破解到搜索字段中来解决此问题。

  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

答案 4 :(得分:2)

对于那些苦苦挣扎Select2 多重的人:

奇怪的是我发现select_tag有多个:true似乎热衷于为每个条目生成html,如:

<div class="select2-result-label">
  <span class="select2-match"></span>
  value
</div>

而不是

<div class="select2-result-label">
  <span class="select2-match">value</span>
</div>

无益地将内容放在跨度之外。

为了用水豚来测试它我有两种方法:

# 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();

答案 5 :(得分:2)

受益于这个答案和Capybara select2 helper的答案我想出了同一页面上单选和多选的多个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

答案 6 :(得分:2)

这适用于带有远程数据源的下拉样式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。

答案 7 :(得分:1)

我有两个远程select2。我在第一个中搜索一个字符串,根据找到的结果,第二个字符串被填充。 在尝试了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

答案 8 :(得分:0)

嘿,我不确定是否还有人关心,但我也有这个问题,我找到了一个简单的方法来处理它。

首先,我不会将这个类添加到每个下拉选择中,而是像全局那样添加:

    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-select2宝石,但好像它不再被维护了:(

答案 9 :(得分:0)

简单回答:

page.find('.select2-drop-active .select2-input').set('foo')
page.find('.select2-drop-active .select2-input').native.send_keys(:return)

答案 10 :(得分:0)

def select2(id, value)
  find("##{id} ~ span.select2").click
  within ".select2-results" do
    find("li", text: value).click
  end
end

答案 11 :(得分:0)

这是针对更新版本的select2的解决方案 - 特别是select2-rails(4.0.0)gem:

将其放在features/support/feature_helpers.rb中,然后将其包含在spec_helper.rb文件中,config.include FeatureHelpers块中包含RSpec.configure do |config|

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

然后像在Capybara中使用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中测试

答案 12 :(得分:0)

花了更长的时间比我更喜欢,我终于通过建立Brandon McInnis&#39;使用xpath选择器回答。

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

答案 13 :(得分:0)

指定js: true

https://github.com/goodwill/capybara-select2对我来说很好。干杯

答案 14 :(得分:0)

这对我有用,即使使用select2 AJAX自动完成:

find('#user_id').sibling('span.select2').click
find('.select2-search__field').set('ABCDEF')
find('.select2-results li', text: 'ABCDEF').click

答案 15 :(得分:0)

您可以使用capybara-select-2 gem来完成所有工作。只需将search: true传递到帮助器选项即可进行Ajax调用:

select2 'Marriage', from: 'Event', search: true

答案 16 :(得分:0)

此助手为我工作(使用占位符):

  # Add this helper
  def select2(placeholder, option)
    find("select[data-placeholder='#{placeholder}'] + .select2").click
    within '.select2-results' do
      find('span', text: option).click
    end
  end

并这样称呼它:

select2 'Placeholder', 'some option'