Как написать интеграционные тесты для проверки Stripe на Rails?

Я ударил стену, пытаясь написать тест интеграции для Stripe checkout.js [https://checkout.stripe.com/checkout.js] для моего приложения Rails 3.2.

Выполнение проверок на полосах работает корректно для меня при проверке вручную (с использованием клавиш тестирования Stripe), но я не могу заставить Capybara обнаружить и fill_in поле электронной почты в модуле checkout iframe.

Я использую полтергейст для безголового javascript, хотя также тестировал это с помощью capybara-webkit и даже селена с той же проблемой.

То, что я пытаюсь проверить, - это полный поток подписки на подписку, чтобы показать, что новый пользователь может создать учетную запись абонента после ввода своих платежных реквизитов в Stripe, но я не могу пройти мимо всплывающего окна Stripe.

Вот мой before .. do:

describe "show Stripe checkout", :js => true do
  before do
    visit pricing_path
    click_button 'plan-illuminated'
    stripe_iframe = all('iframe[name=stripe_checkout_app]').last
    Capybara.within_frame stripe_iframe do        
      fill_in "email", :with => "[email protected]"
      fill_in "billing-name", :with => "Mr Name"
      fill_in "billing-street", :with => "test Street"
      fill_in "billing-zip", :with => 10000
      fill_in "billing-city", :with => "Berlin"
      click_button "Payment Info"
    end
  end
  it { should have_selector('button', text: "Subscribe") }
end

Какие ошибки с:

Failure/Error: Capybara.within_frame stripe_iframe do
 Capybara::Poltergeist::TimeoutError:
   Timed out waiting for response to {"name":"push_frame","args":[null]}

Если я поменяю попытку выбрать правильный iframe (предлагаемый здесь: проблема с Capybara, заполняющая JS-модальный), вот так:

# stripe_iframe = all('iframe[name=stripe_checkout_app]').last
# Capybara.within_frame stripe_iframe do  
Capybara.within_frame 'stripe_checkout_app' do

Я все равно получаю подобное:

Capybara::Poltergeist::TimeoutError:
   Timed out waiting for response to {"name":"push_frame","args":["stripe_checkout_app"]}

Похоже, что в зависимости от того, какой я использую javascript для тестирования, rspec/capybara не может найти проверку iframe в Stripe. Когда я проверю с помощью Selenium, я вижу кнопку Choose this Plan нажатой и всплывающее окно Checkout, но время истекает, ища поле электронной почты для заполнения.

Любые идеи?

Я уже пробовал:

  • Различные способы выбора или поиска поля электронной почты.
  • Обновление всех моих драгоценных камней.
  • Использование StripeMock до этого (не так, чтобы оно было задействовано, верно?).
  • Выполнение тех же тестов с собственным сайтом Stripe, которые дают те же ошибки:

Тестирование с помощью:

  visit "https://stripe.com/docs/checkout"
  click_button 'Pay with Card'
  stripe_iframe = all('iframe[name=stripe_checkout_app]').last
  Capybara.within_frame stripe_iframe do
    fill_in 'Email', with: '[email protected]'
    sleep 3
  end

В зависимости от того, какой метод я использую для выбора iframe, я получаю те же ошибки. Используя только Capybara.within_frame 'stripe_checkout_app' do:

 Failure/Error: Capybara.within_frame stripe_iframe do
 Capybara::Poltergeist::TimeoutError:
   Timed out waiting for response to {"name":"push_frame","args":[null]}

или с использованием селена с stripe_iframe = all('iframe[name=stripe_checkout_app]').last:

 Failure/Error: Unable to find matching line from backtrace
 SystemStackError:
   stack level too deep

или даже просто:

 Failure/Error: fill_in 'Email', with: '[email protected]'
 Capybara::ElementNotFound:
   cannot fill in, no text field, text area or password field with id, name, or label 'Email' found

... в зависимости от того, какой тест javascript я использую.

Приветствуется любая помощь или мудрость!

Ответы

Ответ 1

Я не мог получить какие-либо решения, которые до сих пор работают для меня, а затем читать это сообщение: https://gist.github.com/nruth/b2500074749e9f56e0b7 Я понял, что ключ должен был добавить задержка на тест, чтобы дать полосе достаточно времени, чтобы 1) загрузить окно проверки и 2) обработать токен.

По этой причине единственным кодом, с которым я мог бы работать, было это (не стесняйтесь играть со временем):

СЕЛЕН

describe "test stripe" do, js: true, driver: :selenium do

  before do
    ... # fill in order form or whatever
    click_button "checkout_with_stripe"
    sleep(2) # allows stripe_checkout_app frame to load
    stripe_iframe = all('iframe[name=stripe_checkout_app]').last
    Capybara.within_frame stripe_iframe do
      page.execute_script(%Q{ $('input#email').val('[email protected]'); })
        page.execute_script(%Q{ $('input#card_number').val('4242424242424242'); })
        page.execute_script(%Q{ $('input#cc-exp').val('08/44'); })
        page.execute_script(%Q{ $('input#cc-csc').val('999'); })
        page.execute_script(%Q{ $('#submitButton').click(); })
      sleep(3) # allows stripe_checkout_app to submit
    end
  end

  it "should successfully process the request" do
     ... # test should pass
  end 
end

Для Capybara-webkit трюк sleep не работал и не грустно делал решение @Ryan, и я слишком устал, пытаясь понять это, поэтому я просто остановился, но, надеюсь, кто-то иначе это получится, потому что я предпочел бы использовать webkit по причинам скорости! (Я использовал capybara-webkit 1.3.0)

В случае, если это помогает, вот мои соответствующие версии:

selenium-webdriver 2.35.1
rspec-rails 2.14.2
capybara 2.1.0
stripe 1.16.0 da216fd
rails 4.1.1
ruby 2.1.2

Ответ 2

Проблема решена!

С некоторой помощью от parov через его похожий вопрос и ответ [Poltergeist Stripe checkout.js] Я отследил проблему до использования старой версии Capybara '~ > 1.1.2 'и последующий эффект зависимостей, который это имело на различных драгоценных камнях javascript (например, selenium, capybara-webkit, poltergeist...).

Выполнение bundle update Capybara до 2.3.0, и поэтому приведение полтергейста в 1.5.1, с селеном-webdriver на 2.42.0 и capybara-webkit в 1.1.0, получает (почти) все, что работает.

Для селена этот метод через заполнение проблемы Capybara в JS modal работает:

  stripe_iframe = all('iframe[name=stripe_checkout_app]').last
  Capybara.within_frame stripe_iframe do
    fill_in "email", with: "[email protected]"
    ...
  end

Однако это не работает в poltergeist или capybara-webkit.

Для полтергейста работает предложение parov:

  stripe = page.driver.window_handles.last
  page.within_window stripe do
    fill_in "email", with: "[email protected]"
    ...
  end

Для capybara-webkit Я не смог ничего работать, хотя, учитывая, что у меня что-то работало с полтергейстом, я не уделял слишком много времени поиску решения capybara-webkit.

Комментарии?

Ответ 3

Я боролся с этим в течение некоторого времени (как показывает james james), и, в конце концов, он слишком хрупкий и слишком медленный, чтобы проверить чек.

Вместо этого вы можете использовать следующие (ruby, capybara, selenium) для stub checkout.js и опубликовать свою форму с помощью токена полосы:

  # optionally ensure the iframe was opened
  expect(page).to have_css('iframe[name="stripe_checkout_app"]')
  # post the form
  token = Stripe::Token.create(
    :card => {
      :number => "4242424242424242",
      :exp_month => 7,
      :exp_year => 2019,
      :cvc => "314",
      address_line1: Faker::Address.street_address,
      address_city: Faker::Address.city,
      address_zip: Faker::Address.postcode,
      address_country: 'United Kingdom'
    },
  )
  page.execute_script("$('#payment_token').val('#{token.id}');")
  page.execute_script("$('#our-stripe-payment-form').submit();")

n.b. это предполагает, что у вас уже есть stripe api gem, загруженный в тестовую среду (вашим приложением rails), и у вас есть зарегистрированный ключ API и т.д., иначе см. docs.

Ответ 4

Для capybara-webkit я смог заставить это работать:

  stripe_iframe = page.driver.window_handles.last
  page.within_window stripe_iframe do
    fill_in "email", with: "[email protected]" 
    ...
  end