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

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

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

我正在使用无端 javascript的poltergeist ,虽然也用capybara-webkit和甚至selenium测试了同样的问题。

我要测试的是完整的订阅注册流程,以显示新用户在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麻烦填充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测试gem,rspec / capybara都找不到Stripe checkout iframe。 当我查看Selenium时,我看到按下了Choose this Plan按钮和Checkout弹出窗口,但是规格超时寻找要填写的电子邮件字段。

有任何想法吗?

我已经尝试过了:

  • 选择或查找电子邮件字段的各种方法。
  • 更新我的所有gem。
  • 在此之前使用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。

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

到目前为止,我无法获得任何解决方案为我工作,然后阅读这篇文章: https : //gist.github.com/nruth/b2500074749e9f56e0b7我意识到关键是要给测试添加一个延迟给Stripe有足够的时间来1)加载结账窗口和2)处理令牌。

出于这个原因,我可以使用的唯一代码就是这个(随意玩定时):

selenium

 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 

问题解决了!

通过parov通过他的类似问题和答案[ Poltergeist Stripe checkout.js ]的一些帮助我跟踪问题到使用旧版本的Capybara’〜> 1.1.2’以及随后的各种javascript测试的依赖效应gem(即selenium,capybara-webkit,poltergeist ……)。

做一个Capybara的bundle update到2.3.0,所以把poltergeist带到1.5.1,selenium-webdriver在2.42.0和capybara-webkit在1.1.0,得到(几乎)一切正常。

对于selenium,这种通过Capybara填充JS模式的方法 确实有效:

  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中不起作用。

对于恶作剧者来说,帕罗夫的建议是有效的:

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

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

评论?

我已经和它斗争了一段时间(正如主要詹姆斯提到的那样)并且最终发现它太脆弱而且太慢而无法测试结账js。

相反,您可以使用以下(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();") 

这假设你已经在测试环境中加载了条带api gem(由你的rails应用程序),并且有一个注册的API密钥等,否则请参阅文档 。

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

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

我尝试了詹姆斯的答案并根据我目前的环境进行了修改。 这是我的代码(系统规格与Chrome无头):

 require 'rails_helper' describe 'Orders', type: :system do before do # Temporarily change default_max_wait_time to wait for Stripe response @old_wait_time = Capybara.default_max_wait_time Capybara.default_max_wait_time = 10 end after do Capybara.default_max_wait_time = @old_wait_time end scenario 'Payment via Stripe', js: true do visit payment_path click_button 'Pay with Card' # Use VCR to avoid actual data creation VCR.use_cassette 'orders/payment_via_stripe' do expect(page).to have_css('iframe[name="stripe_checkout_app"]') stripe_iframe = all('iframe[name=stripe_checkout_app]').last Capybara.within_frame stripe_iframe do # Set values by placeholders fill_in 'Card number', with: '4242424242424242' fill_in 'MM / YY', with: '08/44' fill_in 'CVC', with: '999' # You might need to fill more fields... click_button 'Pay $9.99' end # Confirm payment completed expect(page).to have_content 'Payment completed.' end end end 

我在用:

  • selenium-webdriver 3.14.0
  • rspec-rails 3.8.0
  • 水豚3.7.1
  • 条纹3.26.0
  • 铁轨5.2.1
  • ruby2.5.1
  • vcr 4.0.0
  • webmock 3.4.2
  • Chrome 69

我的应用程序是根据https://stripe.com/docs/checkout/rails构建的。