vendredi 24 avril 2015

How can I test Stripe.js using poltergeist and Capybara?

I've been going nuts trying to write an automated test for my user sign up page. Users will be charged a recurring subscription via Stripe. They input their basic details (email, password, etc) and their credit card details on the same form, then the following flow happens:

  1. (On the client-side) stripe.js makes an AJAX request to Stripe's servers, which (assuming everything is valid) returns a credit card token.
  2. My javascript fills in a hidden input in the HTML form with the credit card token, and submits the form to my Rails server.
  3. (Now on the server-side): I validate the user's basic details. If they're invalid, return (because there's no point charging them via Stripe if e.g. their email address is invalid so they can't create an account anyway.)
  4. If they're valid, attempt to create a Stripe::Customer object, add the right subscription and charge them using Stripe's ruby gem etc.

All of this works perfectly fine... except I can't figure out how to test it. Testing step #4 is easy enough as it takes place on the server-side so I can mock out the Stripe calls with a gem like VCR.

Step #1 is what's giving me trouble. I've tried to test this using both puffing-billy and the stripe-ruby-mock gem, but nothing works. Here's my own javascript (simplified):

    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;
    });

Just to reiterate, this all works fine when I test it manually. But my automated tests fail:

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

When I try to use the gem puffing-billy, it seems to be caching stripe.js itself (which is loaded from Stripe's own servers at js.stripe.com, not served from my own app, as Stripe don't support this.), but the call initiated by Stripe.createToken isn't being cached. In fact, when I log into my Stripe server logs, it doesn't seem that the call is even been made (or at least Stripe isn't receiving it.)

Note those console.log statements in my JS above. When I run my test suite, the line "creating token..." gets printed, but "creating token..." doesn't. Looks like the response handler is never being called.

I've left out some details because this question is already very long, but can add more on request. What am I doing wrong here? How can I test my sign up page?

Aucun commentaire:

Enregistrer un commentaire