Let me start by confirming that this isn't a duplicate (in that the answers posted there didn't fix my problem). This post is essentially my exact problem: Capybara can't find the form fields in the Stripe modal to fill them in.
Here's my Capybara spec:
describe 'checkout', type: :feature, js: true do
it 'checks out correctly' do
visit '/'
page.should have_content 'Amount: $20.00'
page.find('#button-two').click_button 'Pay with Card'
Capybara.within_frame 'stripe_checkout_app' do
fill_in 'Email', with: '[email protected]'
fill_in 'Name', with: 'Nick Cox'
fill_in 'Street', with: '123 Anywhere St.'
fill_in 'ZIP', with: '98117'
fill_in 'City', with: 'Seattle'
click_button 'Payment Info'
fill_in 'Card number', with: '4242424242424242' #test card number
fill_in 'MM/YY', with: '02/22'
fill_in 'CVC', with: '222'
click_button 'Pay'
end
page.should have_content 'Thanks'
end
end
The text in that spec is my most recent attempt. The Capybara error is Unable to find field "Email"
.
fill_in 'email', with: '[email protected]'
)type: :feature
and js: true
hashes in the describe
within_frame
call on Capybara
page.find('.emailInput input').set('[email protected]'
)within
block: within('.panel') do
around the form inputs (fails with Unable to find css ".panel"
)sleep 3
before the previous step in case it's looking for that div too early (fails with Unable to find css ".panel"
)find
(and also page.find
) and passing the form manipulation as a block (with and without a within
block nested in the find
block):Capybara.within_frame 'stripe_checkout_app' do
page.find('.panel') do
fill_in 'Email', with: '[email protected]'
...
end
end
I've also tried this with poltergeist.
What's maddening about this is that I've changed the Capybara driver from poltergeist back to selenium/Firefox and I can physically see the driver opening the page, clicking the button and bringing up the modal.
Any thoughts on how to get Capybara to interact with this form?
I also tried sticking a binding.pry
in there and debugging with the pry gem. The page's HTML at the point that the modal loads is a few elements, and then script tags that dynamically insert JS into the head of the iframe. See this screenshot of the DOM at the point where the binding.pry
is hit (after the modal window opens with the Stripe form):
So that <div class="emailInput">
is clearly in there, but page.has_selector?('.emailInput')
returns false in the pry console.
Here is a GitHub gist of what happens when I print page.html
from the pry binding as the next line after Capybara.within_frame 'stripe_checkout_app' do
. That is, this is the markup from Capybara's perspective, and this varies wildly from the DOM as shown in the screenshot of the DOM of the actual form when it appears on screen, shown above. As you can see, there are no inputs or anything to work with in the markup that Capybara sees.
Here is the markup for the form that contains the JS that executes the modal. (Markup is in haml).
%form{ action: "/charge?amount=1400", method: 'post', class: 'payment', id: 'fourteen' }
%article
%label.amount
%span Amount: $14.00
.stripejs#button-one
%script{ src: 'https://checkout.stripe.com/checkout.js', class:'stripe-button', :'data-key' => settings.publishable_key, :'data-name' => 'Slow Coffee', :'data-description' => '2 8oz. bags (2/month)', :'data-shipping-address' => true }
I can't reproduce this issue against Stripe's demo checkout page.
require "capybara"
sess = Capybara::Session.new(:selenium)
sess.visit("https://stripe.com/docs/checkout")
sess.click_button('Pay with Card')
sess.within_frame('stripe_checkout_app') do
sess.fill_in 'Email', with: '[email protected]' # it's visible that field becomes filled in
sleep 3 # just to inspect that manually
end
The issue described by you is because there are two iframes with name stripe_checkout_app
. within_frame
finds the first of them that doesn't contain billing fields. To find second iframe you can do e.g.:
stripe_iframe = all('iframe[name=stripe_checkout_app]').last
within_frame stripe_iframe do
# your code here
end
Don't have 50 rep to comment but, have you tried adding some wait time on capybara so the modal has time to load completely, I came across a similar problem using testcafe and giving it 2-3 seconds wait time did the trick.
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