如何在Rails上编写Stripe checkout的集成测试?

时间:2014-06-06 11:57:54

标签: ruby-on-rails ruby-on-rails-3 testing capybara stripe-payments

我试图为我的Rails 3.2应用程序为Stripe的checkout.js [https://checkout.stripe.com/checkout.js]编写集成测试。

条纹检查在手动测试时(使用Stripe的测试键)可以正常使用,但我无法让Capybara检测到并fill_in条纹结帐iframe模式中的电子邮件字段。

我正在使用 poltergeist 进行无头javascript,不过也用 capybara-webkit 甚至 selenium 测试了这个问题。< / p>

我要测试的是完整的订阅注册流程,以显示新用户在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 => "test-user@example.com"
      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 trouble filling in JS modal),请执行以下操作:

# 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都找不到Stripe checkout iframe。当我查看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: 'test@example.com'
    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]}

或将Selenium与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: 'test@example.com'
 Capybara::ElementNotFound:
   cannot fill in, no text field, text area or password field with id, name, or label 'Email' found

...取决于我正在使用的测试javascript gem。

非常感谢任何帮助或智慧!

4 个答案:

答案 0 :(得分:10)

到目前为止,我无法获得任何解决方案为我工作,然后阅读这篇文章:https://gist.github.com/nruth/b2500074749e9f56e0b7我意识到关键是要给测试添加一个延迟,让Stripe有足够的时间来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('jamesdd9302@yahoo.com'); })
        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

答案 1 :(得分:5)

问题解决了!

parov 的帮助下通过他的类似问题&amp;回答[Poltergeist Stripe checkout.js]我将问题追溯到使用旧版本的Capybara'〜&gt; 1.1.2'以及随后的各种javascript测试宝石的依赖效应(即selenium,capybara-webkit) ,恶作剧......)。

bundle update的Capybara做到2.3.0,然后将poltergeist带到1.5.1,使用2.42.0的selenium-webdriver和1.1.0的capybara-webkit,让(几乎)一切正常。

对于selenium,此方法通过Capybara trouble filling in JS modal 工作

  stripe_iframe = all('iframe[name=stripe_checkout_app]').last
  Capybara.within_frame stripe_iframe do
    fill_in "email", with: "test-user@example.com"
    ...
  end

然而,这在poltergeist或capybara-webkit中不起作用。

对于吵闹的人来说,parov的建议有效:

  stripe = page.driver.window_handles.last
  page.within_window stripe do
    fill_in "email", with: "test-user@example.com"
    ...
  end

对于capybara-webkit 我无法获得任何工作,但考虑到我有一些与恶作剧家合作的事情,我没有花太多时间去寻找一个capybara-webkit解决方案。

评论

答案 2 :(得分:3)

我一直在与这个斗争一段时间(正如詹姆斯的詹姆斯提到的那样)并且最终发现它太脆弱而且太慢而无法测试结账时间。

相反,您可以使用以下(ruby,capybara,selenium)来存储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。假设您已经在测试环境(由rails应用程序)中加载了条带api gem,并且已经注册了API密钥等,否则为see the docs

答案 3 :(得分:2)

对于capybara-webkit ,我能够让它工作:

  stripe_iframe = page.driver.window_handles.last
  page.within_window stripe_iframe do
    fill_in "email", with: "test-user@example.com" 
    ...
  end