Check select box has certain options with Capybara

30,534

Solution 1

Try using the capybara rspec matcher have_select(locator, options = {}) instead:

#Find a select box by (label) name or id and assert the given text is selected
Then /^"([^"]*)" should be selected for "([^"]*)"$/ do |selected_text, dropdown|
  expect(page).to have_select(dropdown, :selected => selected_text)
end

#Find a select box by (label) name or id and assert the expected option is present
Then /^"([^"]*)" should contain "([^"]*)"$/ do |dropdown, text|
  expect(page).to have_select(dropdown, :options => [text])
end

Solution 2

For what it's worth, I'd call it a drop-down menu, not a field, so I'd write:

Then the "cars" drop-down should contain the option "audi"

To answer your question, here's the RSpec code to implement this (untested):

Then /^the "([^"]*)" drop-down should contain the option "([^"]*)"$/ do |id, value|
  page.should have_xpath "//select[@id = '#{id}']/option[@value = '#{value}']"
end

If you want to test for the option text instead of the value attribute (which might make for more readable scenarios), you could write:

  page.should have_xpath "//select[@id = '#{id}']/option[text() = '#{value}']"

Solution 3

As an alternative solution, and as I'm not familiar with xpaths, I did this to solve a similar problem:

page.all('select#cars option').map(&:value).should == %w(volvo saab mercedes audi)

Its quite simple, but took me some time to figure out.

Solution 4

Well, since i was around and saw the question (and been testing today) decided to post my way:

within("select#cars") do
  %w(volvo saab mercedes audi).each do |option|
    expect(find("option[value=#{option}]").text).to eq(option.capitalize)
  end
end

Solution 5

Then I should see "audi" within "#cars"

should do the trick

Share:
30,534
Tom Maeckelberghe
Author by

Tom Maeckelberghe

Updated on July 09, 2022

Comments

  • Tom Maeckelberghe
    Tom Maeckelberghe almost 2 years

    How do I use Capybara to check that a select box has certain values listed as options? It has to be compatible with Selenium...

    This is the HTML that I have:

    <select id="cars"> 
      <option></option>
      <option value="volvo">Volvo</option>
      <option value="saab">Saab</option>
      <option value="mercedes">Mercedes</option>
      <option value="audi">Audi</option>
    </select>
    

    This is what I want to do:

    Then the "cars" field should contain the option "audi"
    
  • Tom Maeckelberghe
    Tom Maeckelberghe about 13 years
    Thanks but it's not working. In cucumber "cars" would be a "field" and "within" implies a scope. So a standard step that comes close is 'Then the "cars" field should contain "Audi"'. But if nothing is selected it returns an empty string: expected: /Audi/, got: ""
  • corroded
    corroded about 13 years
    how can cars be a field when it's clearly a select tag? you're checking if the option Audi exists in your cars dropdown right? or are you checking if it was the selected option?
  • Tom Maeckelberghe
    Tom Maeckelberghe about 13 years
    Options should be option.. ah well, i'm doing it with this page.should have_css('select option:contains('Audi')', :visible => true). Why? Code is more readable, plus checks that the element is visible...
  • Jo Liss
    Jo Liss about 13 years
    @Tom: The contains pseudo-class was taken out of the CSS spec, so I'm not sure if this will work everywhere, but other than that, CSS is just as good (and I agree it's more readable). You can use :visible on either method, by the way. Re learning XPath, I've been getting pretty far with just the examples in the spec (and these as well).
  • Tom Maeckelberghe
    Tom Maeckelberghe about 13 years
    Oh didn't now that... It's a shame they let go of 'contains()', it looks useful. I'll take a look at the XPath exemples thanks!
  • Joe Sak
    Joe Sak over 12 years
    For the RSpec users out there, I used page.should have_select('Something', :options => ['plain text'])
  • denis.peplin
    denis.peplin over 11 years
    With my rspec/capybara page.should.have_xpath does not work, but page.should have_xpath does.
  • Gabriel Osorio
    Gabriel Osorio over 10 years
    @hubble your comment should definitely have a response of its own :)
  • aceofspades
    aceofspades about 10 years
    You can also use with_options to check that specific option(s) exist without specifying all in order
  • peoplespete
    peoplespete about 8 years
    Capybara seems to suggest that options is a complete set, whereas with_options allows for a subset of the total options, handy for checking that a particular option is in the select without specifying all of the options. Still looking for something to specify the order. github.com/jnicklas/capybara/blob/master/lib/capybara/node/…
  • everyman
    everyman about 8 years
    Newer RSpec syntax: expect(page).to have_select(...)
  • Jeff Perrin
    Jeff Perrin about 8 years
    Thanks @everyman, I've updated the answer with the new syntax.
  • Yohann
    Yohann over 5 years
    has_select(locator, options = {}) page.has_select?('Language', with_options: ['English', 'German']) if you don't want your test to fail when it isn't not found