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

时间:2011-07-18 07:24:46

标签: ruby-on-rails ruby-on-rails-3 date rspec capybara

我正在使用RSpec和Capybara在Rails 3项目中为控制器编写规范,我想从选择框中选择当前日期。我试过了:

select Date.today, :from => 'Date of birth'

但是规范失败了,我收到了错误:

失败/错误:选择Date.today,:from => '出生日期' NoMethodError:   2011年7月18日星期一的未定义方法`to_xpath':日期

如何解决?

P.S。在视图文件中,我使用simple_form_for标记,选择框由代码生成:

f.input :date_of_birth

11 个答案:

答案 0 :(得分:24)

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

  1. 将日期选择宏写入 /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. 将它们添加到我的 /spec/spec_helper.rb

    config.include RequestMacros, :type => :request
    
  3. 现在在规范/请求的集成测试中,我可以使用

    select_date attr[:birthday], :from => "user_birthday"
    

    感谢http://jasonneylon.wordpress.com/2011/02/16/selecting-from-a-dropdown-generically-with-capybara/https://gist.github.com/558786:)

答案 1 :(得分:21)

您需要在html的选择菜单中指定确切的值。因此,如果您的选择具有“2011/01/01”之类的值,那么您需要写:

select '2011/01/01', :from => 'Date of birth'

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

答案 2 :(得分:9)

由于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

这样称呼:

select_date "2012,Jan,1", :from => "From date"

答案 3 :(得分:7)

略微改编马库斯的答案:

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

答案 4 :(得分:7)

我找到了一个干净的rspec和capybara解决方案来测试使用日期和时间选择方法,在HTML中你使用日期时间选择或日期选择。这适用于Rails 4,RSpec 3.1和Capybara 2.4.4。

在HTML表单中说明您有以下内容:

<%= f.datetime_select(:start_date, {default: DateTime.now, prompt: {day: 'Choose day', month: "Choose month", year: "Choose year"}}, {class: "date-select"}) %>

日期时间选择视图助手将创建5个选择字段,其中包含id="modelname_start_date_1i"等ID,其中id附加有1i,2i,3i,4i,5i。默认情况下,年,月,日,小时,分钟。如果更改字段的顺序,请确保更改下面的功能助手。

1)为日期和时间助手创建功能助手

<强>规格/支持/助手/ 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 

请注意,在我使用%-d的那一天,它为您提供了非填充数值(即4),而不是具有零填充数值的%d(即04)。查看the date formats with strftime

2)然后,您需要在 spec / support / helpers.rb 中包含日期和时间助手方法,以便在任何规范文件中使用它们。

require 'support/helpers/date_time_select_helpers'
RSpec.configure do |config|
  config.include Features::DateTimeSelectHelpers, type: :feature
end

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

答案 5 :(得分:2)

感谢Dylan指出它,但如果有人在寻找黄瓜版本,你可以使用它:

select_date("Date of birth", :with => "1/1/2011")

有关详细信息,请参阅select_date

答案 6 :(得分:1)

鉴于以下Formtastic代码呈现Rails默认日期选择器:

= f.input :born_on, end_year: Time.now.year, start_year: 60.years.ago.year

在您的规范中,将日期分成对每个单独选择标记的单独调用:

select '1956', from: 'person_born_on_1i'
select 'July', from: 'person_born_on_2i'
select '9', from: 'person_born_on_3i'

我不喜欢这段代码非常了解HTML,但它确实适用于此时的gems版本。

宝石:

  • Capybara 2.1.0
  • Formtastic 2.2.1
  • Rails 3.2.13
  • RSpec 2.13.0

答案 7 :(得分:1)

在我的特定情况下,我可能会向具有accepts_nested_attributes_for功能的页面添加多个日期选择字段。这意味着,我不确定字段的完整idname是什么。

这是我提出的解决方案,以防其他任何人谷歌搜索:

我将日期选择字段包装在带有类的容器div中:

<div class='date-of-birth-container'>
  <%= f.date_select :date_of_birth %>
</div>

然后在我的功能规范中:

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

这是我为它写的一个辅助方法:

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

然后使用帮助器:

select_date_within_css_selector(Date.new(1955, 1, 1), '.date-of-birth-container')

答案 8 :(得分:0)

以下对我有用,使用date_field:

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

答案 9 :(得分:0)

对于 Rails 4 ,以防有人在不限于Rails 3的情况下解决此问题。

  select '2020',  from: 'field_name_{}_1i'
  select 'January',  from: 'field_name_{}_2i'
  select '1', from: 'field_name_{}_3i'

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

答案 10 :(得分:-1)

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