Проблемы с Capybara в JS modal

Позвольте мне начать с подтверждения того, что это не дубликат (в том, что ответы, опубликованные там, не исправили мою проблему). Этот пост - это, по сути, моя точная проблема: Capybara не может найти поля формы в модуле Stripe, чтобы заполнить их.

Здесь моя спецификация Capybara:

describe 'checkout', type: :feature, js: true do
  it 'checks out correctly' do
    visit '/'
    page.should have_content 'Amount: $20.00'
    page.find('#button-two').click_button 'Pay with Card'
    Capybara.within_frame 'stripe_checkout_app' do
      fill_in 'Email', with: '[email protected]'
      fill_in 'Name',  with: 'Nick Cox'
      fill_in 'Street', with: '123 Anywhere St.'
      fill_in 'ZIP', with: '98117'
      fill_in 'City', with: 'Seattle'
      click_button 'Payment Info'
      fill_in 'Card number', with: '4242424242424242' #test card number
      fill_in 'MM/YY', with: '02/22'
      fill_in 'CVC', with: '222'
      click_button 'Pay'
    end
    page.should have_content 'Thanks'
  end
end

Текст этой спецификации - моя самая последняя попытка. Ошибка Capybara Unable to find field "Email".

Что я пробовал

  • Эта последняя попытка заполнить поле текстом-заполнителем, предложенным здесь
  • Поиск поля электронной почты с помощью атрибута name (например, fill_in 'email', with: '[email protected]')
  • С и без хэшей type: :feature и js: true в describe
  • С вызовом within_frame и без него <<27 >
  • Попытка найти вход css (например, page.find('.emailInput input').set('[email protected]')
  • Добавление блока within: within('.panel') do вокруг входов формы (сбой с Unable to find css ".panel")
  • Добавление sleep 3 перед предыдущим шагом в случае, если он слишком рано ищет этот div (с ошибкой Unable to find css ".panel")
  • Добавление вызова к find (а также page.find) и передача формы в виде блока (с блоком within, вложенным в блок find):

Capybara.within_frame 'stripe_checkout_app' do
  page.find('.panel') do
    fill_in 'Email', with: '[email protected]'
    ...
  end
end

Я тоже пробовал это с помощью полтергейста.

Какое безумие в этом заключается в том, что я изменил драйвер Capybara от полтергейста до селена /Firefox, и я могу физически видеть, как драйвер открывает страницу, нажимая кнопку и поднимая модальность.

Любые мысли о том, как заставить Capybara взаимодействовать с этой формой?

Изменить

Я также попытался вставить binding.pry туда и отладить pry gem. HTML страницы в точке, где модальные нагрузки - это несколько элементов, а затем теги script, которые динамически вставляют JS в начало iframe. Смотрите этот снимок экрана DOM в точке, где поражен binding.pry (после того, как модальное окно открывается в форме Stripe):

enter image description here

Итак, <div class="emailInput"> явно там, но page.has_selector?('.emailInput') возвращает false в консоль pry.

Здесь - это описание GitHub того, что происходит, когда я печатаю page.html из привязки pry как следующую строку после Capybara.within_frame 'stripe_checkout_app' do. То есть это разметка с точки зрения Capybara, и это сильно отличается от DOM, как показано на скриншоте DOM фактической формы, когда она появляется на экране, показанной выше. Как вы можете видеть, нет никаких входов или чего-либо, с чем можно работать в разметке, которую видит Capybara.

Update

Вот разметка для формы, содержащей JS, которая выполняет модальную. (Разметка находится в haml).

  %form{ action: "/charge?amount=1400", method: 'post', class: 'payment', id: 'fourteen' }
    %article
      %label.amount
        %span Amount: $14.00

    .stripejs#button-one
      %script{ src: 'https://checkout.stripe.com/checkout.js', class:'stripe-button', :'data-key' => settings.publishable_key, :'data-name' => 'Slow Coffee', :'data-description' => '2 8oz. bags (2/month)', :'data-shipping-address' => true }

Ответы

Ответ 1

Я не могу воспроизвести эту проблему на странице Stripe demo checkout.

require "capybara"

sess = Capybara::Session.new(:selenium)
sess.visit("https://stripe.com/docs/checkout")
sess.click_button('Pay with Card')
sess.within_frame('stripe_checkout_app') do
  sess.fill_in 'Email', with: '[email protected]' # it visible that field becomes filled in
  sleep 3 # just to inspect that manually
end

Проблема, описанная вами, состоит в том, что существует два iframe с именем stripe_checkout_app. within_frame находит первый из них, который не содержит полей фактурирования. Чтобы найти второй iframe, вы можете сделать, например:

stripe_iframe = all('iframe[name=stripe_checkout_app]').last
within_frame stripe_iframe do
  # your code here
end

Ответ 2

У вас нет 50 комментариев для комментариев, но вы попробовали добавить некоторое время ожидания на capybara, чтобы модальное время полностью загрузилось, я столкнулся с подобной проблемой, используя testcafe и дав ей 2-3 секунды ожидания. трюк.

Ответ 3

Просто выкидывая идею здесь, так как я застрял в этих маленьких проблемных проблемах и знаю, как это расстраивает их... Как только я просто пытался заставить Capybara нажать кнопку "Закрыть" в Twitter Модифицированное диалоговое окно Bootstrap. Оказывается, чтобы заставить его работать, мне пришлось заключить модальный HTML-код Bootstrap в тег "form", а затем Capybara смог его найти. Интересно, является ли что-то вроде этого вашей проблемой?

Ответ 4

Capybara fill_in использует css ids не классы. Пример

<input autofocus="autofocus" class="center" id="user_login" name="user[login]" placeholder="Username/Email" type="text" >

Вы также можете использовать <input> вместо <div>

Ответ 5

Попробуйте с помощью Poltergeist, используя методы переключения окон

https://github.com/jonleighton/poltergeist#window-switching

stripe = page.driver.window_handles.last

page.within_window stripe do
  fill_in "Email", :with => "[email protected]"

  fill_in 'Card number', with: '4242424242424242' #test card number
  fill_in 'MM / YY', with: '02/22'
  fill_in 'CVC', with: '222'

  click_button 'Pay'
end

Я нашел решение в этом испанском блоге: numerica latina.