如何为Rails上的条带签出编写集成测试?

时间:2021-06-14 20:21:46

I've hit the wall trying to write an integration test for Stripe's checkout.js [ https://checkout.stripe.com/checkout.js ] for my Rails 3.2 app.

我试图为Stripe的签出编写一个集成测试,但失败了。js [https://checkout.stripe.com/checkout.js]用于我的Rails 3.2应用。

Stripe checkout works correctly for me when manually tested (using Stripe's testing keys), but I cannot get Capybara to detect and fill_in the email field in the Stripe checkout iframe modal.

当手动测试(使用Stripe的测试键)时,Stripe签出对我来说是正确的,但我无法让Capybara在Stripe签出iframe模式下的电子邮件字段中检测和填写。

I am using poltergeist for headless javascript, though have also tested this with capybara-webkit and even selenium with the same problem.

我正在使用poltergeist进行无头javascript,尽管我也用capybara-webkit甚至selenium测试了同样的问题。

What I am trying to test is the complete subscription sign-up flow, to show that a new user can create a subscriber account after entering their payment details in Stripe - but I cannot get past the Stripe checkout pop-up.

我正在测试的是完整的订阅注册流程,以显示新用户在以条状输入支付细节后可以创建一个订阅帐户——但我无法通过条状结帐弹出窗口。

Here is my 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

Which errors with:

错误的:

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

If I swap out the attempt to choose the correct iframe (suggested here: Capybara trouble filling in JS modal ) like so:

如果我放弃尝试选择正确的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

I still get the similar:

我仍然得到相似的结果:

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

It appears that whichever javascript testing gem I use, rspec/capybara cannot find the Stripe checkout iframe. When I check with Selenium I see the Choose this Plan button pressed and the Checkout pop-up, but the spec times out looking for the email field to fill in.

看来无论我使用什么javascript测试gem, rspec/capybara都无法找到Stripe checkout iframe。当我使用Selenium检查时,我看到了选择这个计划按钮和签出弹出,但是spec超时寻找电子邮件字段来填充。

Any ideas?

什么好主意吗?

I've already tried:

我已经尝试:

  • Various ways of choosing or finding the email field.
  • 选择或寻找电子邮件领域的各种方法。
  • Updating all my gems.
  • 更新所有的宝石。
  • Using StripeMock before this (not that it should be involved, right?).
  • 在这之前使用StripeMock(不是说它应该包含这个,对吧?)
  • Running the same tests against Stripe's own site, which give the same errors:
  • 在Stripe自己的站点上运行相同的测试,会产生相同的错误:

Testing with:

测试:

  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

Depending which method I use to select the iframe I receive the same errors. Using just Capybara.within_frame 'stripe_checkout_app' do:

根据我使用什么方法来选择iframe,我将收到相同的错误。使用水豚。within_frame stripe_checkout_app”做的事:

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

or using Selenium with stripe_iframe = all('iframe[name=stripe_checkout_app]').last:

或者使用Selenium和stripe_iframe = all('iframe[name=stripe_checkout_app]]])。

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

or even just:

甚至是:

 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

...depending on which testing javascript gem I am using.

…取决于我使用的是哪个测试javascript gem。

Any help or wisdom is greatly appreciated!

非常感谢您的帮助和智慧!

4 个解决方案

#1


9  

I could not get any of the solutions here so far to work for me, and then reading this post: https://gist.github.com/nruth/b2500074749e9f56e0b7 I realized that the key was to add a delay to the test to give the Stripe enough time to 1) load the checkout window and 2) process the token.

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

For that reason the only code that I could get to work was this (feel free to play with timing) :

出于这个原因,我可以使用的唯一代码是这样的(请随意选择时间):

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

For Capybara-webkit, the sleep trick didn't work nor sadly did @Ryan's solution, and I got too tired of trying to figure this out so I just stopped, but hopefully someone else will get it because I'd rather use webkit for speed reasons! (I was using capybara-webkit 1.3.0)

对于Capybara-webkit来说,这个睡眠技巧也不管用,而且不幸的是,@Ryan的解决方案也不管用,我已经厌倦了试图解决这个问题,所以我就停了下来,但希望其他人也能理解,因为出于速度的原因,我宁愿使用webkit !(我使用的是capybara-webkit 1.3.0)

In case it helps, here are my relevant versions:

如果有帮助,以下是我的相关版本:

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


5  

Problem solved!

问题解决了!

With some help from parov via his similar question & answer [ Poltergeist Stripe checkout.js ] I tracked the problem down to using an old version of Capybara '~>1.1.2' and the subsequent dependency-effect this had on the various javascript testing gems (ie. selenium, capybara-webkit, poltergeist...).

在帕罗夫的一些帮助下,他通过类似的问题和答案[Poltergeist条纹检验。我将问题追溯到使用旧版本的Capybara '~>1.1.2',以及它对各种javascript测试宝石(ie)的依赖性。硒、capybara-webkit吵闹鬼……)。

Doing a bundle update of Capybara to 2.3.0, and so bringing poltergeist to 1.5.1, with selenium-webdriver at 2.42.0 and capybara-webkit at 1.1.0, gets (almost) everything working.

将Capybara升级为2.3.0,将poltergeist升级为1.5.1,selenium-webdriver升级为2.42.0,Capybara -webkit升级为1.1.0,几乎所有的东西都运行正常。

For selenium, this method via Capybara trouble filling in JS modal does work:

对于硒,这种通过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

However, that does not work in poltergeist or capybara-webkit.

然而,这在poltergeist或capybara-webkit中并不适用。

For poltergeist, parov's suggestion works:

对于poltergeist, parov的建议是:

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

For capybara-webkit I wasn't able to get anything working, though given I had something working with poltergeist I didn't put too much time into finding a capybara-webkit solution.

对于capybara-webkit来说,我无法得到任何工作,尽管我有一些与poltergeist合作的东西,但我并没有花太多时间去寻找capybara-webkit的解决方案。

Comments?

评论?

#3


3  

I've been fighting with this for some time (as the gist james mentions shows) and in the end found it's too brittle and too slow to test the checkout js.

我已经和这个问题斗争了一段时间(正如james提到的要点),最后发现它太脆弱,测试checkout js太慢。

Instead you can use the following (ruby, capybara, selenium) to stub checkout.js and post your form with a stripe token:

相反,您可以使用以下代码(ruby、capybara、selenium)来存根签出。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. this assumes you already have the stripe api gem loaded in your test environment (by your rails app) and have a registered API key etc, otherwise see the docs.

注意:这假定您已经在测试环境(通过rails应用程序)中加载了stripe api gem,并拥有一个注册的api密钥等等,否则请参阅文档。

#4


2  

For capybara-webkit, I was able to get this to work:

对于capybara-webkit来说,我能够让它发挥作用:

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

#1


9  

I could not get any of the solutions here so far to work for me, and then reading this post: https://gist.github.com/nruth/b2500074749e9f56e0b7 I realized that the key was to add a delay to the test to give the Stripe enough time to 1) load the checkout window and 2) process the token.

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

For that reason the only code that I could get to work was this (feel free to play with timing) :

出于这个原因,我可以使用的唯一代码是这样的(请随意选择时间):

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

For Capybara-webkit, the sleep trick didn't work nor sadly did @Ryan's solution, and I got too tired of trying to figure this out so I just stopped, but hopefully someone else will get it because I'd rather use webkit for speed reasons! (I was using capybara-webkit 1.3.0)

对于Capybara-webkit来说,这个睡眠技巧也不管用,而且不幸的是,@Ryan的解决方案也不管用,我已经厌倦了试图解决这个问题,所以我就停了下来,但希望其他人也能理解,因为出于速度的原因,我宁愿使用webkit !(我使用的是capybara-webkit 1.3.0)

In case it helps, here are my relevant versions:

如果有帮助,以下是我的相关版本:

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


5  

Problem solved!

问题解决了!

With some help from parov via his similar question & answer [ Poltergeist Stripe checkout.js ] I tracked the problem down to using an old version of Capybara '~>1.1.2' and the subsequent dependency-effect this had on the various javascript testing gems (ie. selenium, capybara-webkit, poltergeist...).

在帕罗夫的一些帮助下,他通过类似的问题和答案[Poltergeist条纹检验。我将问题追溯到使用旧版本的Capybara '~>1.1.2',以及它对各种javascript测试宝石(ie)的依赖性。硒、capybara-webkit吵闹鬼……)。

Doing a bundle update of Capybara to 2.3.0, and so bringing poltergeist to 1.5.1, with selenium-webdriver at 2.42.0 and capybara-webkit at 1.1.0, gets (almost) everything working.

将Capybara升级为2.3.0,将poltergeist升级为1.5.1,selenium-webdriver升级为2.42.0,Capybara -webkit升级为1.1.0,几乎所有的东西都运行正常。

For selenium, this method via Capybara trouble filling in JS modal does work:

对于硒,这种通过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

However, that does not work in poltergeist or capybara-webkit.

然而,这在poltergeist或capybara-webkit中并不适用。

For poltergeist, parov's suggestion works:

对于poltergeist, parov的建议是:

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

For capybara-webkit I wasn't able to get anything working, though given I had something working with poltergeist I didn't put too much time into finding a capybara-webkit solution.

对于capybara-webkit来说,我无法得到任何工作,尽管我有一些与poltergeist合作的东西,但我并没有花太多时间去寻找capybara-webkit的解决方案。

Comments?

评论?

#3


3  

I've been fighting with this for some time (as the gist james mentions shows) and in the end found it's too brittle and too slow to test the checkout js.

我已经和这个问题斗争了一段时间(正如james提到的要点),最后发现它太脆弱,测试checkout js太慢。

Instead you can use the following (ruby, capybara, selenium) to stub checkout.js and post your form with a stripe token:

相反,您可以使用以下代码(ruby、capybara、selenium)来存根签出。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. this assumes you already have the stripe api gem loaded in your test environment (by your rails app) and have a registered API key etc, otherwise see the docs.

注意:这假定您已经在测试环境(通过rails应用程序)中加载了stripe api gem,并拥有一个注册的api密钥等等,否则请参阅文档。

#4


2  

For capybara-webkit, I was able to get this to work:

对于capybara-webkit来说,我能够让它发挥作用:

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