How to select option in drop down using Capybara
Asked Answered
F

11

153

I'm trying to select an item from a drop down menu using Capybara (2.1.0).

I want to select by number (meaning select the second, third, etc option).

I've Googled like crazy trying all sorts of things but no luck.

I was able to select it by using the value:

 find("option[value='4c430d62-f1ba-474f-8e8a-4452c55ea0a8']").click

But I don't want to use that method b/c the value is something that will change and that will make my test brittle.

The HTML for the drop down is:

<td class="value">
    <select name="organizationSelect" id="organizationSelect" class="required">
     <option value="NULL">Choose...</option>
     <option value="4c430d62-f1ba-474f-8e8a-4452c55ea0a8">&nbsp;Institution1</option>
     <option value="e1a4efa7-352d-410a-957e-35c8a3b92944">&nbsp;Institution / test</option>
    </select>
</td>

I also tried this:

  option = find(:xpath, "//*[@id='organizationSelect']/option[2]").text  
  select(option, :from => organizationSelect)

But it results in this error:

Ambiguous match, found 2 elements matching option "Institution" (Capybara::Ambiguous)

So how can I select the first, second, third, etc option from the drop down (using Capybara) ?

Frond answered 21/11, 2013 at 23:28 Comment(0)
H
144

If you take a look at the source of the select method, you can see that what it does when you pass a from key is essentially:

find(:select, from, options).find(:option, value, options).select_option

In other words, it finds the <select> you're interested in, then finds the <option> within that, then calls select_option on the <option> node.

You've already pretty much done the first two things, I'd just rearrange them. Then you can tack the select_option method on the end:

find('#organizationSelect').find(:xpath, 'option[2]').select_option
Hamster answered 22/11, 2013 at 0:3 Comment(2)
Would like to add this reference for those researching this in the future: gist.github.com/zhengjia/428105Weft
Great answer! I would like to add that in Rails 5 you can do it in the following way as well: select('option_name', from: 'select_box'). Where the values can be: id, name, related label element. You can read more about Capybara and DSL options here.Finger
I
211

For some reason it didn't work for me. So I had to use something else.

select "option_name_here", :from => "organizationSelect"

worked for me.

Izolaiztaccihuatl answered 14/1, 2014 at 15:29 Comment(5)
Weird, that doesn't work for me as the method seems to take at least 3 options. Although the code you suggested matches the example code from the capybara guide.Dinitrobenzene
it's not form, it is from. Here is the documentation on selectAhola
Perhaps worth noting the from value is the name, id, or label text. i.e. "#organizationSelect" is incorrect, but "organizationSelect" should work.Sophy
This didn't work for me, but carols10cents's solution did. This is not a critic of your answer. I just find it really strange that even on the latest version of capybara, some calls work and some calls don't even when intution would lead you to believe that multiple solutions look valid. It's driving me insane. Is this related to firefox (or whatever browser capybara ends up using)?Hosmer
I think this will only work when the option name and option value are the same.Ground
H
144

If you take a look at the source of the select method, you can see that what it does when you pass a from key is essentially:

find(:select, from, options).find(:option, value, options).select_option

In other words, it finds the <select> you're interested in, then finds the <option> within that, then calls select_option on the <option> node.

You've already pretty much done the first two things, I'd just rearrange them. Then you can tack the select_option method on the end:

find('#organizationSelect').find(:xpath, 'option[2]').select_option
Hamster answered 22/11, 2013 at 0:3 Comment(2)
Would like to add this reference for those researching this in the future: gist.github.com/zhengjia/428105Weft
Great answer! I would like to add that in Rails 5 you can do it in the following way as well: select('option_name', from: 'select_box'). Where the values can be: id, name, related label element. You can read more about Capybara and DSL options here.Finger
A
12

another option is to add a method like this

  def select_option(css_selector, value)
    find(:css, css_selector).find(:option, value).select_option
  end
Atlante answered 6/6, 2017 at 4:38 Comment(2)
Helpful options find("select[name='organization_search[role]']").find(:option, text: :Staff).select_optionGround
find(:css, "#search_field").find(:option, "Opp Last Name").select_option, which is the displayed option text, worked for me, while the value of the option didn't.Committeeman
H
8

To add yet another answer to the pile (because apparently there's so many ways of doing it depending on your setup) - I did it by selecting the literal option element and clicking it

find(".some-selector-for-dropdown option[value='1234']").select_option

It's not very pretty, but it works :/

Horrific answered 28/12, 2017 at 1:23 Comment(0)
I
5

Unfortunately, the most popular answer did not work for me entirely. I had to add .select_option to end of the statement

select("option_name_here", from: "organizationSelect").select_option

without the select_option, no select was being performed

Infantile answered 27/3, 2017 at 21:55 Comment(1)
How come you could call .select_option, since the select method returns a boolean value?Homecoming
H
3

none of the answers worked for me in 2017 with capybara 2.7. I got "ArgumentError: wrong number of arguments (given 2, expected 0)"

But this did:

find('#organizationSelect').all(:css, 'option').find { |o| o.value == 'option_name_here' }.select_option
Honna answered 29/4, 2018 at 21:8 Comment(0)
R
3

This is by far the most simplest one:

select("month", from: "repeat_on")

The from parameter should be an id as in:

<select id="repeat_on">
    <option value="month">month</option>
    <option value="day">day</option>
</select>
Radiograph answered 2/2, 2023 at 11:27 Comment(1)
Does "month" refer to the value or the label? How would I select <option value="foo">bar</option>?Esquimau
C
1

Here's the most concise way I've found (using capybara 3.3.0 and chromium driver):

all('#id-of-select option')[1].select_option

will select the 2nd option. Increment the index as needed.

Clerihew answered 25/4, 2019 at 21:57 Comment(0)
M
0

In Capybara you can use only find with xpath

find(:xpath, "//*[@id='organizationSelect']/option[2]").click

and method click

Mend answered 26/9, 2019 at 13:8 Comment(0)
A
0

I was using simple_form:

When working with Associations:

= f.association :company, collection: Company.ordered, as: :select, include_blank: false
# output HTML
<select class="form__input" name="role[company_id]" id="role_company_id">
  <option value="1">APPLE</option>
  <option value="5">J.P. MORGAN</option>
  <option value="6">JOHNSON &amp; JOHNSON</option>
  <option value="4">KPMG</option>
  <option value="2">MICROSOFT</option>
  <option value="3">WALMART</option>
</select>

this one worked for me:

find('#role_company_id').find(:xpath, 'option[3]').select_option

When working with conventional select:

= f.input :work_type, as: :select, collection: Role.work_types.collect { |key, value| [key.to_s.titleize, value] }, include_blank: false
# output HTML
<select class="form__input" name="role[work_type]" id="role_work_type">
  <option selected="selected" value="in_person">In Person</option>
  <option value="remote">Remote</option>
  <option value="hybrid">Hybrid</option>
</select>

this worked for me:

find_by_id("role_work_type").find("option[value='remote']").click

Hope this helps.

Anglophobe answered 9/6, 2022 at 2:37 Comment(0)
I
-4

It is not a direct answer, but you can (if your server permit):

1) Create a model for your Organization; extra: It will be easier to populate your HTML.

2) Create a factory (FactoryGirl) for your model;

3) Create a list (create_list) with the factory;

4) 'pick' (sample) a Organization from the list with:

# Random select
option = Organization.all.sample 

# Select the FIRST(0) by id
option = Organization.all[0] 

# Select the SECOND(1) after some restriction
option = Organization.where(some_attr: some_value)[2]
option = Organization.where("some_attr OP some_value")[2] #OP is "=", "<", ">", so on... 
Imaginal answered 12/11, 2014 at 13:27 Comment(2)
if i have to create a model, there is no point in using capybaraBrother
It's not an answer at all. This is a question about Capybara.Antihalation

© 2022 - 2024 — McMap. All rights reserved.