Ruby-on-rails 如何使用Rails 3中的Capybara从选择框中选择日期?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6729786/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to select date from a select box using Capybara in Rails 3?
提问by Aleksandr Shvalev
I'm writing a spec for a controller in Rails 3 project using RSpec and Capybara, and I want to select current date from a select box. I tried:
我正在使用 RSpec 和 Capybara 为 Rails 3 项目中的控制器编写规范,我想从选择框中选择当前日期。我试过:
select Date.today, :from => 'Date of birth'
but the spec fails and I get error:
但规范失败,我得到错误:
Failure/Error: select Date.today, :from => 'Date of birth' NoMethodError: undefined method `to_xpath' for Mon, 18 Jul 2011:Date
失败/错误:选择 Date.today, :from => 'Date ofbirth' NoMethodError: undefined method `to_xpath' for Mon, 18 Jul 2011:Date
How to fix it?
如何解决?
P.S. In view file I use simple_form_for tag and the select box is generated by code:
PS 在视图文件中,我使用 simple_form_for 标记,选择框由代码生成:
f.input :date_of_birth
采纳答案by solnic
You need to specify the exact value as it's in the select menu in html. So if your select has values like "2011/01/01" then you need to write:
您需要在 html 的选择菜单中指定确切的值。因此,如果您的选择具有“2011/01/01”之类的值,那么您需要编写:
select '2011/01/01', :from => 'Date of birth'
Your code fails because you pass a date object.
您的代码失败,因为您传递了一个日期对象。
回答by Markus Hartmair
Had the same problem. I googled at lot and solved it this way:
有同样的问题。我搜索了很多并以这种方式解决了它:
Wrote date select macros into /spec/request_macros.rbThe select_by_id method is necessary for me, because the month is dependent on the translation
module RequestMacros def select_by_id(id, options = {}) field = options[:from] option_xpath = "//*[@id='#{field}']/option[#{id}]" option_text = find(:xpath, option_xpath).text select option_text, :from => field end def select_date(date, options = {}) field = options[:from] select date.year.to_s, :from => "#{field}_1i" select_by_id date.month, :from => "#{field}_2i" select date.day.to_s, :from => "#{field}_3i" end endAdded them to my /spec/spec_helper.rb
config.include RequestMacros, :type => :request
将日期选择宏写入/spec/request_macros.rbselect_by_id方法对我来说是必须的,因为月份是依赖翻译的
module RequestMacros def select_by_id(id, options = {}) field = options[:from] option_xpath = "//*[@id='#{field}']/option[#{id}]" option_text = find(:xpath, option_xpath).text select option_text, :from => field end def select_date(date, options = {}) field = options[:from] select date.year.to_s, :from => "#{field}_1i" select_by_id date.month, :from => "#{field}_2i" select date.day.to_s, :from => "#{field}_3i" end end将它们添加到我的/spec/spec_helper.rb
config.include RequestMacros, :type => :request
Now in my integration tests in spec/requestsi can use
现在在我可以使用的规范/请求中的集成测试中
select_date attr[:birthday], :from => "user_birthday"
Thanks to http://jasonneylon.wordpress.com/2011/02/16/selecting-from-a-dropdown-generically-with-capybara/and https://gist.github.com/558786:)
感谢http://jasonneylon.wordpress.com/2011/02/16/selecting-from-a-dropdown-generically-with-capybara/和https://gist.github.com/558786:)
回答by Les Nightingill
with credit to Markus Hartmair for an excellent solution, I prefer to use labels as selectors because of improved readability. So my version of his helper module is:
感谢 Markus Hartmair 提供的出色解决方案,我更喜欢使用标签作为选择器,因为它提高了可读性。所以我的助手模块版本是:
module SelectDateHelper
def select_date(date, options = {})
field = options[:from]
base_id = find(:xpath, ".//label[contains(.,'#{field}')]")[:for]
year, month, day = date.split(',')
select year, :from => "#{base_id}_1i"
select month, :from => "#{base_id}_2i"
select day, :from => "#{base_id}_3i"
end
end
call it like this:
像这样称呼它:
select_date "2012,Jan,1", :from => "From date"
回答by Aurelien Schlumberger
I found a clean solution for rspec and capybara to test using date and time select methods, where in your HTML you use a datetime select or date select. This works with Rails 4, RSpec 3.1 and Capybara 2.4.4.
我为 rspec 和 capybara 找到了一个干净的解决方案来使用日期和时间选择方法进行测试,在您的 HTML 中,您使用日期时间选择或日期选择。这适用于 Rails 4、RSpec 3.1 和 Capybara 2.4.4。
Say in your HTML form you have the following:
在你的 HTML 表单中说你有以下内容:
<%= f.datetime_select(:start_date, {default: DateTime.now, prompt: {day: 'Choose day', month: "Choose month", year: "Choose year"}}, {class: "date-select"}) %>
the DateTime Select View helper will create 5 select fields with ids such as id="modelname_start_date_1i", where the id the is appended with 1i, 2i, 3i, 4i, 5i. By default Year, Month, Day, Hour, Minute. If you change the order of the fields, make sure to change the feature helper below.
日期时间选择视图助手将创建 5 个带有 id 的选择字段id="modelname_start_date_1i",其中 id 附加有 1i、2i、3i、4i、5i。默认年、月、日、小时、分钟。如果您更改字段的顺序,请确保更改下面的功能助手。
1) Create a Feature Helper for dates and times helpers
1) 为日期和时间助手创建一个功能助手
spec/support/helpers/date_time_select_helpers.rb
规格/支持/helpers/date_time_select_helpers.rb
module Features
module DateTimeSelectHelpers
def select_date_and_time(date, options = {})
field = options[:from]
select date.strftime('%Y'), :from => "#{field}_1i" #year
select date.strftime('%B'), :from => "#{field}_2i" #month
select date.strftime('%-d'), :from => "#{field}_3i" #day
select date.strftime('%H'), :from => "#{field}_4i" #hour
select date.strftime('%M'), :from => "#{field}_5i" #minute
end
def select_date(date, options = {})
field = options[:from]
select date.strftime('%Y'), :from => "#{field}_1i" #year
select date.strftime('%B'), :from => "#{field}_2i" #month
select date.strftime('%-d'), :from => "#{field}_3i" #day
end
end
end
Note that for the day I use %-dthat gives you a non-padded numeric value (i.e. 4) instead of %dthat has a zero-padded numeric value (i.e. 04). Check the date formats with strftime
请注意,在我使用的%-d那一天,它为您提供了一个非填充的数值(即 4),而不是%d具有零填充的数值(即 04)。使用 strftime检查日期格式
2) You then need to include your date and time helpers methods in spec/support/helpers.rbso you can use them in any spec file.
2) 然后您需要在spec/support/helpers.rb 中包含您的日期和时间助手方法,以便您可以在任何规范文件中使用它们。
require 'support/helpers/date_time_select_helpers'
RSpec.configure do |config|
config.include Features::DateTimeSelectHelpers, type: :feature
end
3) In your Spec file you can call your helper. For example:
3) 在您的 Spec 文件中,您可以调用您的助手。例如:
feature 'New Post' do
scenario 'Add a post' do
visit new_post_path
fill_in "post[name]", with: "My post"
select_date_and_time(2.days.from_now, from:"post_start_date")
click_button "Submit"
expect(page).to have_content "Your post was successfully saved"
end
end
回答by Kris
A slight adaption of Markus's answer:
对马库斯的回答稍作改编:
def select_date(date, options = {})
raise ArgumentError, 'from is a required option' if options[:from].blank?
field = options[:from].to_s
select date.year.to_s, :from => "#{field}_1i"
select Date::MONTHNAMES[date.month], :from => "#{field}_2i"
select date.day.to_s, :from => "#{field}_3i"
end
回答by Jaryl
Thanks to Dylan for pointing it out, but in case anyone is looking for the cucumber version, you can use this:
感谢 Dylan 指出,但如果有人正在寻找黄瓜版本,你可以使用这个:
select_date("Date of birth", :with => "1/1/2011")
For more information, see select_date.
有关更多信息,请参阅select_date。
回答by Elliot Larson
In my particular situation, I'm adding potentially multiple date select fields to the page with accepts_nested_attributes_forfunctionality. This means, I'm not sure what the full idor nameof the fields are going to be.
在我的特定情况下,我向具有accepts_nested_attributes_for功能的页面添加了潜在的多个日期选择字段。这意味着,我不确定字段的全部id或name全部将是什么。
Here's the solution I came up with in case it helps anyone else Googling this:
这是我想出的解决方案,以防它可以帮助其他人使用谷歌搜索:
I'm wrapping the date select field in a container div with a class:
我正在用一个类将日期选择字段包装在一个容器 div 中:
<div class='date-of-birth-container'>
<%= f.date_select :date_of_birth %>
</div>
Then in my feature spec:
然后在我的功能规范中:
within '.date-of-birth-container' do
find("option[value='1']", text: 'January').select_option
find("option[value='1']", text: '1').select_option
find("option[value='1955']").select_option
end
Here's a helper method I wrote for it:
这是我为它编写的辅助方法:
def select_date_within_css_selector(date, css_selector)
month_name = Date::MONTHNAMES.fetch(date.month)
within css_selector do
find("option[value='#{date.month}']", text: month_name).select_option
find("option[value='#{date.day}']", text: date.day.to_s).select_option
find("option[value='#{date.year}']").select_option
end
end
Then using the helper:
然后使用助手:
select_date_within_css_selector(Date.new(1955, 1, 1), '.date-of-birth-container')
回答by scarver2
Given the following Formtastic code renders Rails default date selector:
鉴于以下 Formtastic 代码呈现 Rails 默认日期选择器:
= f.input :born_on, end_year: Time.now.year, start_year: 60.years.ago.year
In your spec, break the date into separate calls to each individual select tag:
在您的规范中,将日期分解为对每个单独的 select 标签的单独调用:
select '1956', from: 'person_born_on_1i'
select 'July', from: 'person_born_on_2i'
select '9', from: 'person_born_on_3i'
I don't like that this code is so aware of the HTML, but it does work with the versions of gems at this time.
我不喜欢这段代码对 HTML 如此敏感,但它此时确实适用于 gems 版本。
Gems:
宝石:
- Capybara 2.1.0
- Formtastic 2.2.1
- Rails 3.2.13
- RSpec 2.13.0
- 水豚 2.1.0
- Formtastic 2.2.1
- 导轨 3.2.13
- RSpec 2.13.0
回答by npostolovski
The following worked for me, using a date_field:
以下使用 date_field 对我有用:
fill_in "Date", with: DateTime.now.strftime('%m/%d/%Y')
回答by Mugur 'Bud' Chirica
For Rails 4, in case somebody gets to this question without being limited to Rails 3.
对于Rails 4,万一有人在不限于 Rails 3 的情况下遇到这个问题。
select '2020', from: 'field_name_{}_1i'
select 'January', from: 'field_name_{}_2i'
select '1', from: 'field_name_{}_3i'
You can of course extract this to a helper and make it dynamic.
您当然可以将其提取到帮助程序并使其动态化。

