I have a select2 dropdown in my rails code that I am trying to set and assert via capybara.
<select class="select optional select2-offscreen" id="bar_effort" name="bar[effort]" tabindex="-1"><option value=""></option>
<option value="0">Small</option>
<option value="1">Medium</option>
<option value="2">Large</option>
<option value="3">Extra Large</option>
</select>
To set the value I have the following (which works fine):
def effort=(effort)
#page.select(effort, :from => 'bar_effort')
end
Once the value has been set, I close the form and when I return back to the form, I want to assert the value I set is still selected. To do this I attempted the following:
def effort
#page.find(:css, '#bar_effort').value #version 1
end
def effort
#page.find(:css, '#bar_effort').text #version 2
end
Version 1 gave me "0" when I was expecting "Small"
Version 2 gave me "Small Medium Large Extra Large" when I was expecting "Small"
For a select list, the value method will return the selected option's text only if it does not have a value attribute.
To get the selected option's text, you will need to manually locate the option and get its text:
#page.find('#bar_effort').all('option').find(&:selected?).text
#=> "Small"
Related
I'm spec-ing my form that will have some date pickers.
expect(page).to have_select('Start date') and expect(page).to have_select('deal[start_date]') both return no matches. The latter makes sense given that the html for date pickers is a little funky (name="deal[start_date(2i)])
expect(page).to have_date_select('deal[start_date]') says that Capybara doesn't recognize has_date_select.
Is there a way to do this?
Capybaras has_select? predicate and have_select matcher look for HTML <select> elements. Depending on what you mean by a date picker you'll have to use a matcher that would match the correct type of element, or have_selector if there isn't a specific matcher. If what you are actually checking for is an <input type="date"> element with an associated label containing the text 'Start date' then you can use the have_field matcher:
expect(page).to have_field 'Start date', type: 'date'
If you're using the Rails date_select view helper it produces HTML like
<div class="field">
<label for="post_start_date">Start date</label>
<select id="post_start_date_1i" name="post[start_date(1i)]">
<option value="2014">2014</option>
<option value="2015">2015</option>
...
</select>
<select id="post_start_date_2i" name="post[start_date(2i)]">
<option value="1" selected="selected">January</option>
<option value="2">February</option>
...
</select>
<select id="post_start_date_3i" name="post[start_date(3i)]">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
...
</select>
</div>
You can see from looking at that HTML that the <label> element isn't actually associated with any of the form fields (the for attribute doesn't match an id) which means you won't be able to match the <select> elements using the label text. Instead you'd need to use either the id or name and match them individually
expect(page).to have_select('post_start_date_1i')
expect(page).to have_select('post[start_date(2i)]')
...
or you could use the id filter with a regex and a count to check that there are 3 elements matching like
expect(page).to have_select(id: /^post_start_date_[123]i$/, count: 3)
Note, that's not technically as 'correct' as doing them individually since you could actually have 3 elements with id of post_start_date_1i and it would still pass, but in that case your HTML would also be invalid.
If that's not the type of HTML element you're checking for then you'll need to provide the HTML to get an exact answer.
I have this right now:
<%= f.select :credit, (0..500) %>
This will result in this:
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
...
How would I add another option in that select that would be "All" and which value should be nil?
This will almost do what you want:
<%= f.select :credit, ((0..500).map {|i| [i,i] } << ["No limit",nil]) %>
select can take a number of formats for the list of options. One of them is an array of arrays, as given here. Each element in the outer array is a 2-element array, containing the displayed option text and the form value, in that order.
The map above turns (0..500) into an array like this, where the option displayed is identical to the form value. Then one last option is added.
Note that this will produce a value of "" (an empty string) for the parameter if "Unlimited" is selected - if you put a select field into a form and the form is submitted, the browser will send something for that form parameter, and there is no way to send nil as a form parameter explicitly. If you really wanted to you could use some clever javascript to get the browser to not send the parmeter at all, but that would be more work than simply adding:
param[:credit] == "" and param[:credit] = nil
to your controller action.
If I understand the question correctly, you can use options_for_select and prompt to do this a little more cleanly than what is shown in the selected answer:
<%= f.select :credit, options_for_select(0..500), { prompt: "No Limit" } %>
See the docs here:
http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/select
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"
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
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}']"
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.
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
Then I should see "audi" within "#cars"
should do the trick
I want to set the value in a select list based on the value of a variable.
The variable here is #email_setting.frequency.
In the view the code looks like:
<%= select('email_setting', 'frequency','<option value="1">Daily</option>
<option value="2">Immediately</option>
<option value="3">Every Monday</option>
<option value="4">Every Tuesday</option>
<option value="5">Every Wednesday</option>
<option value="6">Every Thursday</option>
<option value="7">Every Friday</option>
<option value="8">Every Saturday</option>
<option value="9">Every Sunday</option>',
:class=>'fl-space2 required size-120',
:selected=>#email_setting.frequency) %>
I have tried few variations of the following with no luck.
Any advice on how to get this working right?
thanks
First check whether the value of #email_setting.frequency. Actually if you give 'email_setting', 'frequency' as the first 2 parameters, the selected value will be #email_setting.frequency. I believe it is actually integer(like 1) and you are providing string as the option value(like "1"). That should be the reason why it is not selected. Try
<%= select('email_setting', 'frequency', [['Daily', 1],['Immediately', 2], ..], {}, :class=>'fl-space2 required size-120' %>
Also the 4th parameter of select is options and the 5th parameter is html_options. So if you want to give html options like selected, class, you should provide it as 5th parameter by providing 4th parameter options as an empty hash. If you really want to give selected also, you should do that like this:
<%= select('email_setting', 'frequency', [['Daily', 1],['Immediately', 2], ..], {}, :class=>'fl-space2 required size-120', :selected => #email_setting.frequency %>
But the first would be enough in your case.
See select rails api
How would one get the contents of the 'value' attribute of a select tag, based on content of the select tag (i.e. the text wrapped by option), using Nokogiri?
For example, given the following HTML:
<select id="options" name="options">
<option value="1">First Option - 4</option>
<option value="2">Second Option - 5</option>
<option value="3">Third Option - 6</option>
</select>
I would like to be able to specify a string (e.g. 'First Option') and have the contents of the 'value' attribute returned (e.g. '1').
I have been able to achieve the inverse of this (get the content of the select tag based the 'value' attribute of the select tag), but this isn't quite what I need to do.
Try this:
require 'nokogiri'
require 'open-uri'
url = "abc.html"
doc = Nokogiri::HTML(open(url))
doc.xpath('//select[#id="options"]/option[contains(., "First Option")]').each do | node|
p node['value']
end