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 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.
I am using poltergeist for headless javascript, though have also tested this with capybara-webkit and even selenium with the same problem.
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 => "[email protected]"
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:
# 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.
Any ideas?
I've already tried:
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: '[email protected]'
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
:
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
:
Failure/Error: Unable to find matching line from backtrace
SystemStackError:
stack level too deep
or even just:
Failure/Error: fill_in 'Email', with: '[email protected]'
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.
Any help or wisdom is greatly appreciated!
While unit tests make sure that individual parts of your application work, integration tests are used to test that different parts of your application work together.
To test it, create a subscription in test mode. Then, log in to the portal as the test user and update the subscription. Check the Dashboard or API to see whether the subscription reflects the customer's change. Read the integration guide to learn how to set up the customer portal.
Testing paymentsYou can issue cards and simulate purchases using your own Stripe integration in test mode. This allows you to test your integration before you go live without having to make real purchases. You can only use these cards for testing within your Stripe account and not for external purchases.
You can use Stripe's standard test credit card number (4242 4242 4242 4242), CVV (123), and any future date to check if your application gets back the token from Stripe. Once you’ve completed all the steps described above, you’ve successfully integrated Stripe Checkout into your Rails application.
Integration tests are used to test how various parts of our application interact. They are generally used to test important workflows within our application. For creating Rails integration tests, we use the test/integration directory for our application. Rails provides a generator to create an integration test skeleton for us.
Since April 2019, Stripe provides a new Checkout service. Let's see how to integrate it step by step. I'll show you how to integrate the new Stripe Checkout service into your Rails application. This service allows us to seamlessly integrate a Stripe Checkout form, conform to the new Strong Customer Authentication EU regulation.
we can define this Javascript to implement a checkout: once clicked, the button starts a request to the server to generate a session for the selected plan. The session id is then returned to the browser that redirects to the checkout window offered by Stripe. We cannot just rely on a call to the success_url we defined above.
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.
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('[email protected]'); })
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
)
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With