首页 文章

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

提问于
浏览
16

我've hit the wall trying to write an integration test for Stripe' s checkout.js [https://checkout.stripe.com/checkout.js]为我的Rails 3.2应用程序 .

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

我正在使用 poltergeist 用于无头javascript,虽然也用 capybara-webkit 甚至 selenium 测试了这个问题 .

我要测试的是完整的订阅注册流程,以显示新用户在Stripe中输入付款详细信息后可以创建订阅者帐户 - 但我无法通过Stripe checkout弹出窗口 .

这是我的 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弹出窗口,但是规格超时寻找要填写的电子邮件字段 .

有任何想法吗?

I've already tried:

  • 选择或查找电子邮件字段的各种方法 .

  • 更新我的所有宝石 .

  • 在此之前使用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 .

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

5 回答

  • 5

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

    相反,您可以使用以下(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密钥等,否则see the docs .

  • 0

    Problem solved!

    在帕罗夫的帮助下通过他的类似问答[Poltergeist Stripe checkout.js]我将问题追溯到使用旧版本的Capybara '~>1.1.2'以及随后的各种javascript测试宝石的依赖效应(即selenium,capybara-webkit,吵闹鬼......) .

    做一个 bundle update 的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:

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

    For poltergeist, parov's suggestion works:

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

    For capybara-webkit 我没有花太多时间去寻找一个capybara-webkit解决方案 .

    评论?

  • 2

    我尝试了詹姆斯的答案并根据我目前的环境进行了修改 . 这是我的代码(系统规格与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

    • rails 5.2.1

    • 红宝石2.5.1

    • vcr 4.0.0

    • webmock 3.4.2

    • Chrome 69

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

  • 9

    到目前为止,我无法得到任何解决方案为我工作,然后阅读这篇文章: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-webkitsleep 的解决方案并没有解决问题,而且我已经厌倦了试图解决这个问题所以我只是停下来了,但希望其他人能够得到它,因为我宁愿使用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
    
  • 3

    For capybara-webkit ,我能够让这个工作:

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

相关问题