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: 'example@example.com'
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"
.
What I've tried
- This most recent attempt at filling in the field by placeholder text as suggested here
- Finding the email field by the name attribute (e.g.,
fill_in 'email', with: 'example@example.com'
)
- With and without the
type: :feature
and js: true
hashes in the describe
- With and without the
within_frame
call on Capybara
- Trying to find the input by css (e.g.,
page.find('.emailInput input').set('example@example.com'
)
- Adding a
within
block: within('.panel') do
around the form inputs (fails with Unable to find css ".panel"
)
- Adding a
sleep 3
before the previous step in case it's looking for that div too early (fails with Unable to find css ".panel"
)
- Adding a call to
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: 'example@example.com'
...
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?
Edit
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.
Update
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 }