Pregunta

I'm working with a Hobo app using the input_many tag to handle a many-to-many relationship on a form. This puts + and - buttons on the page, and the + adds a new select tag for picking the model on the other side of the relationship. This means that there can be an arbitrary number of select menus with very similar characteristics, distinguished only by an array index, like this:

<select class="input belongs_to data_set_graph" name="graph_pane[data_set_graphs][0][data_set_id]">
[...options...]
</select>
<select class="input belongs_to data_set_graph" name="graph_pane[data_set_graphs][1][data_set_id]">
[...options...]
</select>

N.B. the join of GraphPanes and DataSets is polymorphic (there are many kinds of GraphPanes) so the actual CSS class name varies according to the kind of pane - it could be data_set_a_graph_pane_data_set or data_set_b_graph_pane_data_set.

We've been using Capybara 1.1.2 to test this. As long as we're only associating one DataSet with a GraphPane, we've been able to select them with a step definition like this:

included_defs.each do |data_set_name|
  click_button "+"
  select_node = find(:css, '.input-many-item select') # There may be more than one of these?
  select_node.find(:xpath, XPath::HTML.option(data_set_name), :message => "cannot select option with text '#{data_set_name}'").select_option
end

However, now we need to associate two DataSets with a GraphPane, and the find(:css, '.input-many-item select') fails because there are two matching nodes.

It seems to me that if I could just always pick the last one, this would work, but I can't figure out how to do this with Capybara's selectors. (I think part of the problem is that it's not clear to me, in most of the examples I find, whether they refer to the 1.x DSL or the 2.x series.)

Ideas for sorting this out elegantly are welcome.

¿Fue útil?

Solución

The answer turns out to be using the "all" finder in Capybara:

included_defs.each do |data_set_name|
  click_button "+"
  select_node = all(:css, '.input-many-item select').last # There may be more than one of these
  select_node.find(:xpath, XPath::HTML.option(data_set_name), :message => "cannot select option with text '#{data_set_name}'").select_option
end

all is like find, but it returns an array of matching nodes, so I can use .last and always get the last one.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top