Как выбрать дату в окне выбора, используя Capybara в Rails 3? - PullRequest
22 голосов
/ 18 июля 2011

Я пишу спецификацию для контроллера в проекте Rails 3 с использованием RSpec и Capybara, и я хочу выбрать текущую дату из поля выбора.Я пытался:

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

, но спецификация не работает, и я получаю ошибку:

Ошибка / Ошибка: выберите Date.today,: from => 'Дата рождения' NoMethodError: неопределенный метод `to_xpath 'за понедельник, 18 июля 2011: дата

Как это исправить?

PS В файле вида я использую тег simple_form_for, а поле выбора генерируется кодом:

f.input :date_of_birth

Ответы [ 11 ]

24 голосов
/ 22 февраля 2012

Была такая же проблема.Я гуглил по лоту и решил это так:

  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
    

Теперь в моих интеграционных тестах в спецификации / запросах я могу использовать

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

21 голосов
/ 18 июля 2011

Вам необходимо указать точное значение, так как оно находится в меню выбора в html.Поэтому, если ваш выбор имеет значения типа «2011/01/01», вам нужно написать:

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

Ваш код не выполняется, поскольку вы передаете объект даты.

9 голосов
/ 27 мая 2013

с благодарностью 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"
7 голосов
/ 02 декабря 2014

Я нашел чистое решение для тестирования 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 Select View создаст 5 полей выбора сидентификаторы, такие как id="modelname_start_date_1i", где к идентификатору добавляется 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).Проверьте форматы даты с помощью strftime

2) Затем вам нужно включить ваши вспомогательные методы даты и времени в spec / support / helpers.rb , чтобы вы могли использовать ихв любом spec-файле.

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
7 голосов
/ 08 мая 2012

Небольшая адаптация ответа Маркуса:

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
2 голосов
/ 06 февраля 2012

Спасибо Дилану за указание на это, но в случае, если кто-то ищет версию огурца, вы можете использовать это:

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

Для получения дополнительной информации см. select_date .

1 голос
/ 16 сентября 2014

В моей конкретной ситуации я добавляю потенциально несколько полей выбора даты на страницу с функцией accepts_nested_attributes_for.Это означает, что я не уверен, какими будут полные id или name полей.

Вот решение, которое я придумала на случай, если оно кому-нибудь еще поможет. Google:

Тогда в моей спецификации:

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')
1 голос
/ 08 мая 2013

Учитывая, что следующий код 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, но в настоящее время он работает с версиями гемов.

Драгоценные камни:

  • Капибара 2.1.0
  • Formtastic 2.2.1
  • Рельсы 3.2.13
  • RSpec 2.13.0
0 голосов
/ 09 марта 2018

Для Rails 4 , в случае, если кто-то дойдет до этого вопроса, не ограничиваясь Rails 3.

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

Конечно, вы можете извлечь это из помощника и сделать его динамичным.

0 голосов
/ 27 октября 2015

У меня сработало следующее, используя поле date_:

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