带Firefox的Capybara Select2帮助

时间:2018-07-02 20:09:14

标签: ruby-on-rails selenium-webdriver capybara

出于某种原因,我在使用Geckodriver的Select2和Firefox时遇到了问题。

我曾经只能说page.select 'Text', from: 'Label'的Select2字段,但是不再起作用了,我只是得到了Element <option> could not be scrolled into view(尽管被滚动到视图中)。现在我正在做类似的事情:

  select2Fields = page.all('.select2-selection')
  select2Fields[0].click
  page.find('.select2-search__field').set('Text To Set')
  within('.select2-results') do
    page.find('li', text: 'Text To Click').click
  end

这很丑陋,不适合我的Page Object Model方法,因为我必须先知道它是哪个select2字段。似乎不是带有标签的。

有什么想法吗?自从它与Chrome一起使用以来,这非常令人沮丧,但是最新的chromedriver在最新的水豚版本中存在问题。

2 个答案:

答案 0 :(得分:1)

不确定使用的内容是否可以将select与select2小部件一起使用,它永远都不应该起作用,事实上它确实是一个错误。原因是实际的<select>元素(Capybaras select方法使用的元素)在页面上不可见,而select2则用JS驱动的小部件替换了它。您需要做的正是用户将要执行的操作,即单击以显示小部件,然后单击代表正确条目的<li>元素。所有这些都可以移到一个辅助方法中,并可能包含一些自定义选择器,这些选择器可以归结为类似

Capybara.add_selector(:select2) do
  xpath do |locator, **options|
    xpath = XPath.descendant(:select)
    xpath = locate_field(xpath, locator, options)
    xpath = xpath.next_sibling(:span)[XPath.attr(:class).contains_word('select2')][XPath.attr(:class).contains_word('select2-container')]
    xpath
  end
end

Capybara.add_selector(:select2_option) do
  xpath do |locator|
    # Use anywhere to escape from the current scope since select2 appends
    # the choices to the end of the document
    xpath = XPath.anywhere(:ul)[XPath.attr(:class).contains_word('select2-results__options')][XPath.attr(:id)]
    xpath = xpath.descendant(:li)[XPath.attr(:role) == 'treeitem']
    xpath = xpath[XPath.string.n.is(locator.to_s)] unless locator.nil?
    xpath
  end
end

def select_from_select2(value, from: nil, **options)
  select2 = if from
    find(:select2, from, options.merge(visible: false))
  else
    select = find(:option, value, options).ancestor(:css, 'select', visible: false)
    select.find(:xpath, XPath.next_sibling(:span)[XPath.attr(:class).contains_word('select2')][XPath.attr(:class).contains_word('select2-container')])
  end
  select2.click
  find(:select2_option, value).click
end

这应该让您调用select_from_select2,就像调用select一样,它将找到与给定<select>元素相关联的select2小部件(被select2隐藏)并选择正确的条目从它。

答案 1 :(得分:0)

我已经测试了托马斯的答案,但对我来说不起作用。当水豚单击所需的选项时,select2框将自身关闭并设置为0选项。最终,我做了一个遍历,因为我选中了我想要的选项并触发了change.select2事件。我知道我并没有真正测试select2框。

    def self.select2 (page, datos)

        page.execute_script("$('##{datos[:from]}').select2('open')")

        if page.find(".select2-results li", text: datos[:texto]).click

            page.execute_script("$('##{datos[:from]} option[value=\"#{datos[:valor]}\"]').prop('selected', true)")
            page.execute_script("$('##{datos[:from]}').trigger('change.select2')")
        end

        page.find(:css, '#' + datos[:from]).value
    end

由于我的模块助手不包含在测试中,因此我需要在方法名称中包含self,并将capybaratest中的“ page”作为参数。 变量“ datos”是包含选择器,选项文本及其值的哈希。

在单击水豚时,关闭select2框,我将遍历内容包裹在if子句中,以确保select2框的某些部分正常工作。

最后,我返回了select的当前值以对其进行测试(确实,当我将该选项的值设置为'selected'时并不需要它)

我希望它会帮助任何人。