【问题标题】:How to select date from a select box using Capybara in Rails 3?如何在 Rails 3 中使用 Capybara 从选择框中选择日期?
【发布时间】:2011-07-18 07:24:46
【问题描述】:

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

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

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

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

如何解决?

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

f.input :date_of_birth

【问题讨论】:

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


    【解决方案1】:

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

    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
      

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

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

    【讨论】:

    • 很好的解决方案和实施。谢谢!
    【解决方案2】:

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

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

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

    【讨论】:

    • 它不起作用。我收到错误:失败/错误:选择'2011/07/18',:来自=>'出生日期' Capybara::ElementNotFound:无法选择选项,在选择框中没有带有文本'2011/07/18'的选项'出生日期' 顺便说一下,R​​ails 为每个日期部分生成 3 个选择框。
    • 然后你需要从 3 个选择框中选择 3 个选项,并使用与页面上看到的相同的值。
    【解决方案3】:

    感谢 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"
    

    【讨论】:

    • 我不得不使用find(:xpath, ".//label[contains(.,'#{field}')]")[:for][0..-4]和Date::MONTHNAMES[date.month]
    【解决方案4】:

    我为 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"}) %>
    

    DateTime 选择视图助手将创建 5 个带有 id 的选择字段,例如 id="modelname_start_date_1i",其中 id 附加了 1i、2i、3i、4i、5i。默认情况下,年、月、日、小时、分钟。如果您更改字段的顺序,请务必更改下面的功能助手。

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

    spec/support/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 
    

    请注意,我使用%-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】:

      稍微改编一下马库斯的回答:

      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
      

      【讨论】:

        【解决方案6】:

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

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

        有关详细信息,请参阅select_date。

        【讨论】:

        • 这是黄瓜法的链接。问题是询问如何将水豚与 rspec 一起使用。
        【解决方案7】:

        鉴于以下 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 的版本。

        宝石:

        • 水豚2.1.0
        • Formtastic 2.2.1
        • Rails 3.2.13
        • RSpec 2.13.0

        【讨论】:

          【解决方案8】:

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

          这是我想出的解决方案,以防其他人在谷歌上搜索:

          我将日期选择字段包装在一个带有类的容器 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')
          

          【讨论】:

            【解决方案9】:

            以下对我有用,使用 date_field:

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

            【讨论】:

              【解决方案10】:

              对于 Rails 4,以防有人在不受 Rails 3 限制的情况下遇到这个问题。

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

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

              【讨论】:

                【解决方案11】:

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2014-03-17
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-09-22
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多