如何在Rails 3中使用Capybara从选择框中选择日期?

时间:2022-08-25 19:25:51

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 =>'出生日期'NoMethodError:未定义的方法`to_xpath'for Mon,2011年7月18日:日期

How to fix it?

怎么解决?

P.S. In view file I use simple_form_for tag and the select box is generated by code:

附:在视图文件中,我使用simple_form_for标记,并且选择框由代码生成:

f.input :date_of_birth

11 个解决方案

#1


21  

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.

您的代码失败,因为您传递了日期对象。

#2


24  

Had the same problem. I googled at lot and solved it this way:

有同样的问题。我用谷歌搜索并以这种方式解决了它:

  1. Wrote date select macros into /spec/request_macros.rb The select_by_id method is necessary for me, because the month is dependent on the translation

    写日期选择宏到/spec/request_macros.rb select_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
    
  2. Added them to my /spec/spec_helper.rb

    将它们添加到我的/spec/spec_helper.rb中

    config.include RequestMacros, :type => :request
    

Now in my integration tests in spec/requests i can use

现在在我可以使用的spec / requests中的集成测试中

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 :)

#3


9  

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"

#4


7  

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

#5


7  

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.

DateTime Select View帮助器将创建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

规格/支持/助理/ 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 %-d that gives you a non-padded numeric value (i.e. 4) instead of %d that has a zero-padded numeric value (i.e. 04). Check the date formats with strftime

请注意,对于我使用%-d的那一天,它给出了非填充数值(即4)而不是具有零填充数值(即04)的%d。使用strftime检查日期格式

2) You then need to include your date and time helpers methods in spec/support/helpers.rb so 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

#6


2  

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。

#7


1  

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 '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
  • Capybara 2.1.0
  • Formtastic 2.2.1
  • Formtastic 2.2.1
  • Rails 3.2.13
  • Rails 3.2.13
  • RSpec 2.13.0
  • RSpec 2.13.0

#8


1  

In my particular situation, I'm adding potentially multiple date select fields to the page with accepts_nested_attributes_for functionality. This means, I'm not sure what the full id or name of the fields are going to be.

在我的特定情况下,我正在使用accepts_nested_attributes_for功能向页面添加可能的多个日期选择字段。这意味着,我不确定字段的完整ID或名称是什么。

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')

#9


0  

The following worked for me, using a date_field:

以下是使用date_field为我工作的:

fill_in "Date", with: DateTime.now.strftime('%m/%d/%Y')

#10


0  

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.

您当然可以将其提取到帮助程序并使其动态化。

#11


-1  

It looks like this one has been sufficiently covered, but see Capybara's docs for an official answer. You can select by name, id, or label text.

看起来这个已被充分覆盖,但请参阅Capybara的文档以获得正式答案。您可以按名称,ID或标签文本进行选择。

#1


21  

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.

您的代码失败,因为您传递了日期对象。

#2


24  

Had the same problem. I googled at lot and solved it this way:

有同样的问题。我用谷歌搜索并以这种方式解决了它:

  1. Wrote date select macros into /spec/request_macros.rb The select_by_id method is necessary for me, because the month is dependent on the translation

    写日期选择宏到/spec/request_macros.rb select_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
    
  2. Added them to my /spec/spec_helper.rb

    将它们添加到我的/spec/spec_helper.rb中

    config.include RequestMacros, :type => :request
    

Now in my integration tests in spec/requests i can use

现在在我可以使用的spec / requests中的集成测试中

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 :)

#3


9  

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"

#4


7  

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

#5


7  

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.

DateTime Select View帮助器将创建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

规格/支持/助理/ 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 %-d that gives you a non-padded numeric value (i.e. 4) instead of %d that has a zero-padded numeric value (i.e. 04). Check the date formats with strftime

请注意,对于我使用%-d的那一天,它给出了非填充数值(即4)而不是具有零填充数值(即04)的%d。使用strftime检查日期格式

2) You then need to include your date and time helpers methods in spec/support/helpers.rb so 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

#6


2  

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。

#7


1  

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 '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
  • Capybara 2.1.0
  • Formtastic 2.2.1
  • Formtastic 2.2.1
  • Rails 3.2.13
  • Rails 3.2.13
  • RSpec 2.13.0
  • RSpec 2.13.0

#8


1  

In my particular situation, I'm adding potentially multiple date select fields to the page with accepts_nested_attributes_for functionality. This means, I'm not sure what the full id or name of the fields are going to be.

在我的特定情况下,我正在使用accepts_nested_attributes_for功能向页面添加可能的多个日期选择字段。这意味着,我不确定字段的完整ID或名称是什么。

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')

#9


0  

The following worked for me, using a date_field:

以下是使用date_field为我工作的:

fill_in "Date", with: DateTime.now.strftime('%m/%d/%Y')

#10


0  

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.

您当然可以将其提取到帮助程序并使其动态化。

#11


-1  

It looks like this one has been sufficiently covered, but see Capybara's docs for an official answer. You can select by name, id, or label text.

看起来这个已被充分覆盖,但请参阅Capybara的文档以获得正式答案。您可以按名称,ID或标签文本进行选择。