处理多个Capybara React-select下拉菜单?

时间:2017-10-02 14:13:31

标签: selenium automation capybara

因此,当使用Capybara和Chromedriver自动化网页时,我有一个包含多个下拉菜单(具有相同选项)的页面。

它们都是react-select(我有一个帮助文件)。可悲的是,他们都有相同的标签文本(但不是标签ID ......但我不认为page.select适用于标签ID)。

我想过做一个页面。所有关于反应选择?然后只是通过阵列?这可能吗?

反应选择看起来非常标准,我意识到跨度有一个id,但选择那个不能用于反应 - 从我能够分辨的选择。:

<div class="Select-control">
   <span class="Select-multi-value-wrapper" id="react-select-6--value">
      <div class="Select-placeholder">Select...</div>
      <div class="Select-input" style="display: inline-block;">
         <input role="combobox" aria-expanded="false" aria-owns="" aria-haspopup="false" aria-activedescendant="react-select-6--value" value="" style="width: 5px; box-sizing: content-box;">
         <div style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre;"></div>
      </div>
   </span>
   <span class="Select-arrow-zone"><span class="Select-arrow"></span></span>
</div>

我可以通过page.all把它拉进来吗?我做的反应助手就是这样做的:

module CapybaraReactHelper
  def capybara_react_select(selector, label)
    within selector do
      find('.Select-control').click
      expect(page).to have_css('.Select-menu-outer') # options should now be available
      expect(page).to have_css('.Select-option', text: label)
      find('.Select-option', text: label).click
    end
  end
end

有什么想法吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

id上的.Select-multi-value-wrapper选择是否有效,因为span不是react-select组件的顶级代码。使用react-select和Capybara通常很困难,因为Capybara表单助手不会使用react-select的自定义标记和行为。

正如您所提到的,您可以使用现有帮助程序版本以及范围within块和page.all()来解决此问题。例如:

# helper
def react_select_capybara(selector, option)
  within selector do
    find('.Select-arrow-zone').click
    expect(page).to have_css('.Select-menu-outer')
    find('.Select-option', text: option).click
    expect(page).to have_css('.Select-value-label', text: option)
  end
end

# usage
given(:select_values) { ['Grace Hopper', 'Ada Lovelace'] }

...

react_selects = page.all('.Select')

select_values.each do |select_value, i|
  react_select_capybara(react_selects[i], select_value)
end

虽然这会起作用,但它很脆弱 - 它依赖于页面上反应选择的隐式排序。更健壮的设置会为每个react-select组件传递一个自定义类名,以便在测试中唯一标识它。来自react-select docs on custom classnames

  

您可以为组件提供自定义className prop,它将添加到基础.Select外部容器的className。

实现这可能看起来像:

# JSX
<ReactSelect className="js-select-user-form-1" ... />    
<ReactSelect className="js-select-user-form-2" ... />     

# Spec
react_select_capybara(".js-select-user-form-1", 'Grace Hopper')
react_select_capybara(".js-select-user-form-2", 'Ada Lovelace')

答案 1 :(得分:1)

page.select不适用于此,因为它仅适用于HTNL <select>元素。这是一个JS驱动的小部件,而不是HTML <select>元素。

如果您只是自动化页面(而不是测试应用程序),那么使用JS(通过execute_script)设置隐藏<input>的值可能会更容易。

如果您正在测试应用,那么您可以使用page.all收集所有反应选择并逐步完成,只要从任何反应选择中选择并不替换任何其他反应选择页面(会留下过时的元素)。

如果这还没有提供足够的信息来解决您的问题,而您真正的问题是尝试选择特定的反应选择,那么请在您的问题中添加足够的HTML,以便我们可以看到实际的差异存在于您尝试选择的小部件之间(例如,2个不同的反应选择元素)