70

For the HTML

<select id="date">
  <option value="20120904">Tue 4 Sep 2012</option>
  <option value="20120905">Wed 5 Sep 2012</option>
  <option value="20120906">Thu 6 Sep 2012</option>
</select>

I have the following Capybara Ruby code:

select "20120905", :from => "date"

But this errors with:

cannot select option, no option with text '20120905' in select box 'date' (Capybara::ElementNotFound)

However, if I do

select "Wed 5 Sep 2012", :from => "date"

It's ok.

Is it possible to select an option in Capybara by Value not Text?

Thanks

Flip
  • 6,233
  • 7
  • 46
  • 75
Paul
  • 1,188
  • 1
  • 11
  • 21

10 Answers10

77

This will work to select an option by value:

find("option[value='20120905']").click

To maintain the scope of the selector you could wrap it in a within block as such:

within '#date' do
  find("option[value='20120905']").click
end
robynhenderson
  • 1,348
  • 10
  • 8
  • 23
    After switching from Selenium to Poltergeist found that this method do not work. Therefore replaced by find('#select_id').find('option[value="1"]').select_option Sorry for bad English. – woto Jun 21 '13 at 17:23
  • 1
    @woto All this options do not work for me. Basically the option is found without problems. I have checked the result and it finds the correct option, but it does not click or select it. I think it needs to first open the select before selecting the option. – Fabrizio Bertoglio Apr 27 '17 at 13:02
43

With Poltergeist as driver I can't click on an option like suggested in some of the other options above, instead you can do the following:

page.find_by_id('date').find("option[value='20120905']").select_option

Mark
  • 1,058
  • 10
  • 13
  • Super useful. I created a helper method in spec/support/capybara.rb: def select_option params id = params[:id] value = params[:value] page.find_by_id(id).find("option[value='#{value}']").select_option end – justingordon Mar 27 '13 at 08:17
  • 4
    `click` cause for me `The element you are trying to interact with is either not part of the DOM, or is not currently visible on the page` but `select_option` works for me just fine. Thanks! – Artur Małecki Nov 17 '14 at 11:09
  • This is the answer for capybara-webkit as well. – Doug Johnston Mar 24 '15 at 16:52
21

I wrote a helper method:

def select_by_value(id, value)
  option_xpath = "//*[@id='#{id}']/option[@value='#{value}']"
  option = find(:xpath, option_xpath).text
  select(option, :from => id)
end

Save in a .rb file in spec/support/

Example use:

before do
  select_by_value 'some_field_id', 'value'
  click_button 'Submit'
end
d_rail
  • 4,109
  • 32
  • 37
4

You can also achieve it by doing the following:

find_by_id('date').find("option[value='20120905']").click
TrashyMcTrash
  • 1,234
  • 2
  • 15
  • 39
3

That helper method is pretty clever. I would change it just a little bit:

def select_by_value(id, value)

  option_xpath = "//*[@id='#{id}']/option[@value='#{value}']"

  find(:xpath, option_xpath).click

end

or just:

find(:xpath, "//select[@id='date']/option[@value='20120904']").click
Obi-Wan
  • 846
  • 1
  • 11
  • 26
GeneK
  • 31
  • 3
1

In my case I have a few options with same text, that's the reason why I need select by value. Combining a few answers together I've found the best solution for me:

def select_by_value(id, value)
  option_xpath = "//*[@id='#{id}']/option[@value='#{value}']"
  find(:xpath, option_xpath).select_option
end
iRet
  • 31
  • 3
0

Click using find_field works fine:

find_field("date").find("option[value='20120905']").click
cage
  • 103
  • 1
  • 8
0

You could also use capybara-ui which will look first to match the text, then to match the value.

# define your form widget, in this case in a role
class UserRole < Capybara::UI::Role
  form :my_form do
    select :my_select, 'my_select'
  end
end

# then just submit your form params via #submit
role = UserRole.new

role.submit :my_form, my_select: '20120905'

See more about capybara-ui forms here.

steel
  • 11,883
  • 7
  • 72
  • 109
0

In case of not visible field, try this

find("#date", visible: false).find("option[value='20120905']").click

Or with scope as:

within '#date', visible: false do
    find("option[value='20120905']").click
end
0

You're setting the value.

find(selector).set(value)

kwerle
  • 2,225
  • 22
  • 25