Stripe checkout fill in form in Capybara-webkit
Asked Answered
I

7

17

I'm using capybara-webkit driver for my JS enabled tests. However when I try to fill in the form fields for the stripe checkout iframe, I'm not able to do it using the capybara fill_in helper in both the drivers. Selenium driver provides methods that facilitates in achieving this task though.

4.times {page.driver.browser.find_element(:id, 'card_number').send_keys('4242')}         
page.driver.browser.find_element(:id, 'cc-exp').send_keys '5'
page.driver.browser.find_element(:id, 'cc-exp').send_keys '18'
page.driver.browser.find_element(:id, 'cc-csc').send_keys '123'
page.driver.browser.find_element(:id,'billing-zip').send_keys '600004'

If I use the fill_in helper, I'm not able to input the details fully. For example for a 16 digit card number, the input field gets filled only with 4 digits & in the date field I'm able to input only the month and not the year.

I want to know if there are helpers in the webkit driver that would enable me to fill in forms in the Stripe checkout form. Any heads up on this would be great! Thanks in advance.

Inopportune answered 13/8, 2014 at 6:3 Comment(0)
P
16

I was having similar problems with Selenium that both

find(:css, "input[id$='card_number']").set("4242 4242 4242 4242")
fill_in('card_number', with: "4242 4242 4242 4242")

stopped working. I had find(:css, ...) earlier, which still worked a few months ago, but I guess changes in checkout.js made it so that it didn't work any more. With the help of Capybara cannot fill Stripe Checkout.js fields I managed to get it working. It's not a pretty (or really behavior-driven) solution, but it does the job:

stripe_iframe = all('iframe[name=stripe_checkout_app]').last
Capybara.within_frame stripe_iframe do
  page.execute_script(%Q{ $('input#card_number').val('4242 4242 4242 4242'); })
  page.execute_script(%Q{ $('input#cc-exp').val('12/16'); })
  #rest of the Stripe-capybara
end

I am not sure if it works with Webkit though.

Prom answered 6/10, 2014 at 7:36 Comment(3)
And you didn't get "Unsafe JavaScript attempt to access frame with URL"? How is this possible?Tincal
Nope, didn't get any errors with this. Maybe it is marked as unsafe by some browser versions?Prom
This no longer works because stripe changed their field names. See below for working code. Use find_field and set.Concavoconvex
E
9

It looks like Stripe has changed the IDs on the checkout elements. Many have dynamic IDs that aren't matched by some of the other examples here.

What worked for me is matching elements by the placeholder text. Here's a working snippet as of 12/06/16:

stripe_card_number = '4242424242424242'

within_frame 'stripe_checkout_app' do
  find_field('Card number').send_keys(stripe_card_number)
  find_field('MM / YY').send_keys "01#{DateTime.now.year + 1}"
  find_field('CVC').send_keys '123'

  find('button[type="submit"]').click
end

page.has_content?('Success!', wait: 30)
Endurant answered 6/12, 2016 at 15:12 Comment(0)
C
8

For completeness, here's working code.

    Capybara.within_frame stripe_iframe do
      page.find_field('Email').set '[email protected]'
      page.find_field('Card number').set '4242 4242 4242 4242'
      page.find_field('MM / YY').set '12/42'
      page.find_field('CVC').set '123'
      find('button[type="submit"]').click
    end

You can always find the latest working version in https://github.com/dblock/slack-gamebot/blob/master/spec/integration/update_cc_spec.rb

Concavoconvex answered 26/1, 2017 at 1:59 Comment(0)
F
2

I had exactly the same issue, and found that the following solution works with capybara-webkit as well as with selenium-chrome:

page.find_field('Email').set "[email protected]"
page.find_field('Card number').set ('4242424242424242')

The "Email" and "Card number" here are the placeholders. The reason it works this way and doesn't with find('#email') is because there's no element with id='email' on the page. Capybara correctly can't find this element, it doesn't exist many times. The reason there's no element is because sometimes stripe's iframe is rendered without proper id, like so: element-with-dynamic-id

find_field searches by id, name, or placeholder, and in this case, placeholder is the only attribute that doesn't change in both situations and that can be found by capybara (for ex. "type" doesn't change either, but I couldn't find the way to make capybara search by type and also the test would be much less readable then).

Why does Stripe's iframe sometimes miss these correct ids and replaces them with dynamic ids? No idea.

Foreworn answered 19/10, 2016 at 2:17 Comment(0)
S
0

If you're using Stripe from an iframe (perhaps https://www.paymentiframe.com/?), you should be able to change the scope of your tests to the frame using Capybara's within_frame method:

within_frame('stripe-iframe') do
    fill_in 'card_number', :with => '4242'
end

If you give your iframe a name (stripe-iframe in that example) then that should do it.

Hope that's of help!

Symbolize answered 13/8, 2014 at 9:59 Comment(3)
I'm doing it within a stripe iframe only. Forgot to mention that!Inopportune
@Ananth: Have you tried using .set on the element to set the value of the field?Symbolize
I'm seeing the same issue and using within_iframe isn't helping me either.Mazzola
T
0

I made it similar to @humpah, but without evil JS code.

form_iframe = all('iframe.wysihtml5-sandbox').last
within_frame form_iframe do
  page.find('body').set('SomeContent')
end
Thrush answered 9/1, 2015 at 23:48 Comment(0)
S
0

Make sure you:

  1. Wrap your query method in a Capybara.within_frame block
  2. Use the placeholder value in Stripe's input fields to fill in the field.

Example that is currently working for me:

Capybara.within_frame first("iframe") do
  fill_in "Card number", with: "4242424242424242"
  fill_in "MM / YY", with: "12 / #{ (Time.now.year + 1).to_s[-2..-1] }"
  fill_in "CVC", with: "123"
  fill_in "ZIP", with: "12345"
end
Stortz answered 19/12, 2022 at 22:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.