【问题标题】:How can I test Stripe.js using poltergeist and Capybara?如何使用 poltergeist 和 Capybara 测试 Stripe.js?
【发布时间】:2015-07-03 21:03:20
【问题描述】:

我一直在为我的用户注册页面编写自动化测试而发疯。用户将通过 Stripe 支付定期订阅费用。他们在同一张表格中输入他们的基本信息(电子邮件、密码等)和信用卡信息,然后发生以下流程:

  1. (在客户端)stripe.js 向 Stripe 的服务器发出 AJAX 请求,该服务器(假设一切都有效)返回一个信用卡令牌。
  2. 我的 javascript 使用信用卡令牌填充 HTML 表单中的隐藏输入,并将表单提交到我的 Rails 服务器。
  3. (现在在服务器端):我验证用户的基本详细信息。如果它们无效,请返回(因为如果他们的电子邮件地址无效,那么通过 Stripe 向他们收费是没有意义的,因此他们无论如何都无法创建帐户。)
  4. 如果它们有效,请尝试创建一个Stripe::Customer 对象,添加正确的订阅并使用 Stripe 的 ruby​​ gem 等向它们收费。

所有这些都非常好......除了我不知道如何测试它。测试步骤 #4 非常简单,因为它发生在服务器端,所以我可以使用 VCR 之类的 gem 模拟 Stripe 调用。

第 1 步给我带来了麻烦。我尝试使用puffing-billystripe-ruby-mock gem 对此进行测试,但没有任何效果。这是我自己的 javascript(简化):

    var stripeResponseHandler = function (status, response) {
      console.log("response handler called");
      if (response.error) {
        // show the errors on the form
      } else {
        // insert the token into the form so it gets submitted to the server
        $("#credit_card_token").val(response.id);

        // Now submit the form.
        $form.get(0).submit();
      }
    }


    $form.submit(function (event) {
      // Disable the submit button to prevent repeated clicks
      $submitBtn.prop("disabled", true);
      event.preventDefault();

      console.log("creating token...");
      Stripe.createToken(
        // Get the credit card details from the form
        // and input them here.
      }, stripeResponseHandler);

      // Prevent the form from submitting the normal way.
      return false;
    });

重申一下,当我手动测试时,这一切都很好。但是我的自动化测试失败了:

 Failure/Error: expect{submit_form}.to change{User.count}.by(1)
   expected result to have changed by 1, but was changed by 0

当我尝试使用 gem puffing-billy 时,它似乎正在缓存 stripe.js 本身(它是从 Stripe 自己的服务器在 js.stripe.com 加载的,而不是从我自己的应用程序中提供的,因为 Stripe 不支持这个.),但Stripe.createToken 发起的调用没有被缓存。事实上,当我登录到我的 Stripe 服务器日志时,似乎甚至没有进行调用(或者至少 Stripe 没有收到它。)

请注意上面我的 JS 中的那些 console.log 语句。当我运行我的测试套件时,“正在创建令牌...”这一行被打印出来,但“响应处理程序被调用”。没有。看起来响应处理程序从未被调用过。

我省略了一些细节,因为这个问题已经很长了,但可以根据要求添加更多内容。我在这里做错了什么?如何测试我的注册页面?

更新请参阅 stripe-ruby-mock 上的 [我对这个 Github 问题的评论],了解有关我尝试和失败的更多信息。

【问题讨论】:

  • 您的功能规范是什么样的?
  • 您在 JS 控制台中看到任何错误吗?
  • 另外,我没有找到Stripe.createToken的任何信息,不应该是Stripe.card.createToken吗?
  • Stripe.createToken 肯定存在,就像我说的那样,当我手动测试它时,这一切都有效,我只是在努力为它编写一个自动化测试。

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


【解决方案1】:

如果我理解正确的话……

Capybara 不会知道您的 ajax 请求。您应该能够使用 Sinatra 排除 AJAX 请求。让它返回一个与 VCR 大致相同的固定装置。

这是一篇关于它的文章。

https://robots.thoughtbot.com/using-capybara-to-test-javascript-that-makes-http

您需要在 Capybara 中启动 Sinatra 应用,然后匹配您的 ajax 调用中的 URL。

类似:

class FakeContinousIntegration < Sinatra::Base
  def self.boot
    instance = new
    Capybara::Server.new(instance).tap { |server| server.boot }
  end

  get '/some/ajax'
    # send ajax back to capybara
  end
end

当你启动服务器时,它会返回你可以写入的地址和端口到你的 js 可以使用的配置中。

@server = App.boot

然后我使用地址和端口来配置 JS 应用

def write_js_config
  config['api'] = "http://#{@server.host}:#{@server.port}"
  config.to_json
end

spec_helper.rb 中将配置发送到 js,以便您的脚本指向您的 sinatra 应用程序。我的用 gulp 编译。所以我只是在测试运行之前将配置构建为:

system('gulp build --env capybara')

【讨论】:

  • 我已经尝试过了,请在我刚刚添加到我的问题的链接中查看我的 Github 评论。我的问题是,无论我如何设置,stripe.js 似乎都不会调用我的“假”应用程序。我在 JS 中更改了 Stripe.endpoint 以指向我的 Sinatra 应用程序,并在 Ruby 中更改了 Stripe.api_base,我的应用程序永远不会被调用。 (而且我的测试也没有调用真正的 Stripe 服务器 - 我的日志中没有任何内容。)我怎样才能找出调用出错的地方?
  • (澄清一下:我已经在我的 Sinatra 应用程序中添加了一些日志功能,我可以看到它的操作(get/post /v1/tokens 等)在我运行测试时不会被调用。跨度>
  • 让我再补充一点。我可以用一个有角度的 js 应用程序来做到这一点,所以它应该可以工作......奇怪
  • 如果您 console.log 应用程序中的 api URL 是否与启动 sinatra 应用程序返回的端口和地址匹配?
  • 感谢您更新您的答案,但 @server = App.boot 不应该是 @server = FakeContinousIntegration.boot 吗?
【解决方案2】:

由于超时,我已经在 Capybara/poltergeist 中进行了手动失败的测试。就我而言,解决方案是等待所有 AJAX 请求完成。 Reference

不确定 Stripe.js 是否在内部使用 JQuery,请尝试检查 stripeResponseHandler 设置的条件。

【讨论】:

  • 我已经尝试过 wait_for_ajax 技巧,但我没有想到在 stripeResponseHandler 中使用条件而不是 jQuery.active... 想到这绝对是正确的想法,因为我很确定 Stripe 不使用 jQuery!让我试试看它是否有效.....
  • 不起作用。在我致电createToken 之前添加了window.stripeFlag = true。添加了window.stripeFlag = false 作为stripeResponseHandler 回调的第一行。将wait_for_ajax 中的方法更改为page.evaluate_script("window.stripeFlag").strip == "false"(并在我的规范中添加了wait_for_ajax ......好吧,实际上,它已经存在了)。它仍然不起作用。 stripeResponseHandler 永远不会被调用;似乎 stripe.js 并没有触及外部 API,无论是 Stripe 的真实 API 还是我自己的存根 API。
【解决方案3】:

除了提到的wait_for_ajax 技巧之外,您似乎在更新数据库之前调用了expect。一种检查方法是在代码中添加断点 (binding.pry),并检查它是否是竞争条件问题。

此外,根据Capybara's documentation,引入对 UI 更改的预期会使其“智能”等待 ajax 调用完成:

expect(page).not_to have_content('Enter credit card details')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多