21

我在通过 ajax 加载结果的页面上有一个Select2元素。想用 capybara/rspec 测试这个(使用 poltergeist 驱动程序),但由于 Select2 元素实际上是作为一个隐藏字段开始的,然后填充<ul>一次结果被处理,所有的 normalselectfill_inhelperschoose都不会工作。

我现在拥有的是

  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在那里正常使用,因为搜索字段元素没有标签、id 或名称属性)

4

18 回答 18

9

停止挠头,这样做会奏效

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

我尝试了每个模块和我能做的所有该死的事情,最后只是通过一行简单的代码在没有任何帮助的情况下做到了这一点。

于 2016-04-13T18:16:29.753 回答
8

我创建了一个可以与 Cucumber 一起使用的助手,它没有,sleep所以它比上面的方法更快。如果您使用createSearchChoiceSelect2 提供的,这也有效。

把它放进去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 测试。

于 2014-06-22T13:30:19.500 回答
6

您可以使用capybara-select-2 gem,它将为您完成所有工作。只需传递search: true给辅助选项即可进行 Ajax 调用:

select2 'Marriage', from: 'Event', search: true
于 2018-10-25T08:49:44.233 回答
4

我能够通过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
于 2012-10-07T19:02:27.877 回答
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
于 2013-09-18T09:44:35.577 回答
2

对于那些与 Select2 multiple苦苦挣扎的人:

奇怪的是,我发现带有 multiple:true 的 select_tag 似乎热衷于为每个条目生成 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();
于 2014-11-21T12:50:27.563 回答
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
于 2015-03-10T17:43:25.460 回答
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 的常规选择标记的 ID。

于 2016-11-30T13:51:28.233 回答
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
于 2014-06-07T02:30:22.167 回答
1

https://github.com/goodwill/capybara-select2js: true我来说效果很好。干杯

于 2017-08-07T15:41:40.913 回答
1

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

find('#user_id').sibling('span.select2').click
find('.select2-search__field').set('ABCDEF')
find('.select2-results li', text: 'ABCDEF').click
于 2018-02-23T11:03:00.483 回答
0

简单的回答:

page.find('.select2-drop-active .select2-input').set('foo')
page.find('.select2-drop-active .select2-input').native.send_keys(:return)
于 2014-01-03T18:09:19.703 回答
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 gem,但它似乎不再被维护:(

于 2014-03-09T03:02:41.857 回答
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 中测试

于 2017-03-22T20:14:15.880 回答
0

在花费了比我想要的更长的时间之后,我终于通过使用 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
于 2017-04-30T16:42:30.223 回答
0
def select2(id, value)
  find("##{id} ~ span.select2").click
  within ".select2-results" do
    find("li", text: value).click
  end
end
于 2017-02-02T13:10:55.383 回答
0

对于 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) 才能完成这项工作。

于 2017-05-11T06:53:13.730 回答
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'
于 2020-11-16T00:01:16.210 回答