ruby on rails - unitarias - ¿Cómo escribir pruebas de integración para la comprobación de bandas en Rails?
rspec (5)
He golpeado el muro tratando de escribir una prueba de integración para el checkout.js [ https://checkout.stripe.com/checkout.js ] de Stripe para mi aplicación Rails 3.2.
La verificación de fill_in
funciona correctamente para mí cuando se prueba manualmente (usando las claves de prueba de Stripe), pero no puedo hacer que Capybara detecte y fill_in
el campo de correo electrónico en el iframe modal de fill_in
.
Estoy usando poltergeist para javascript sin cabeza, aunque también lo he probado con capybara-webkit e incluso con selenio con el mismo problema.
Lo que estoy tratando de probar es el flujo completo de suscripción, para mostrar que un nuevo usuario puede crear una cuenta de suscriptor después de ingresar sus detalles de pago en Stripe, pero no puedo pasar la ventana emergente de pago de Stripe.
Aquí está mi 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
Que errores con:
Failure/Error: Capybara.within_frame stripe_iframe do
Capybara::Poltergeist::TimeoutError:
Timed out waiting for response to {"name":"push_frame","args":[null]}
Si cambio el intento de elegir el iframe correcto (sugerido aquí: problemas con Capybara para completar el modo JS ) así:
# stripe_iframe = all(''iframe[name=stripe_checkout_app]'').last
# Capybara.within_frame stripe_iframe do
Capybara.within_frame ''stripe_checkout_app'' do
Todavía me sale el similar:
Capybara::Poltergeist::TimeoutError:
Timed out waiting for response to {"name":"push_frame","args":["stripe_checkout_app"]}
Parece que cualquiera que sea la gema de prueba de javascript que use, rspec / capybara no puede encontrar el iframe de comprobación de rayas. Cuando verifico con Selenium veo que se presiona el botón Choose this Plan
y la ventana emergente de Checkout, pero la especificación agota el tiempo de espera para que se complete el campo de correo electrónico.
¿Algunas ideas?
Ya lo he intentado
- Varias formas de elegir o encontrar el campo de correo electrónico.
- Actualizando todas mis gemas.
- Usar StripeMock antes de esto (no es que deba involucrarse, ¿verdad?).
- Ejecutando las mismas pruebas en el propio sitio de Stripe, que dan los mismos errores:
Pruebas con:
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
Dependiendo del método que utilice para seleccionar el iframe, recibo los mismos errores. Usando solo 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]}
o usando Selenium con stripe_iframe = all(''iframe[name=stripe_checkout_app]'').last
Failure/Error: Unable to find matching line from backtrace
SystemStackError:
stack level too deep
o incluso simplemente:
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
... dependiendo de la prueba que esté usando la gema de javascript.
Cualquier ayuda o sabiduría es muy apreciada!
He estado luchando con esto por algún tiempo (como lo muestra la esencia james) y al final descubrí que es demasiado frágil y demasiado lento para probar la comprobación de js.
En su lugar, puede usar lo siguiente (ruby, capybara, selenium) para apalear checkout.js y publicar su formulario con un token de banda:
# optionally ensure the iframe was opened
expect(page).to have_css(''iframe[name="stripe_checkout_app"]'')
# post the form
token = Stripe::Token.create(
:card => {
:number => "4242424242424242",
:exp_month => 7,
:exp_year => 2019,
:cvc => "314",
address_line1: Faker::Address.street_address,
address_city: Faker::Address.city,
address_zip: Faker::Address.postcode,
address_country: ''United Kingdom''
},
)
page.execute_script("$(''#payment_token'').val(''#{token.id}'');")
page.execute_script("$(''#our-stripe-payment-form'').submit();")
nb esto supone que ya tiene la api gema de banda cargada en su entorno de prueba (por su aplicación de rieles) y tiene una clave API registrada, etc. De lo contrario, consulte la documentación .
No pude obtener ninguna de las soluciones aquí hasta ahora para trabajar para mí, y luego leyendo este post: https://gist.github.com/nruth/b2500074749e9f56e0b7 Me di cuenta de que la clave era agregar un retraso en la prueba para dar la Banda es suficiente para 1) cargar la ventana de verificación y 2) procesar el token.
Por esa razón, el único código que pude obtener para trabajar fue este (siéntase libre de jugar con el tiempo):
SELENIO
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
Para Capybara-webkit , el truco para sleep
no funcionó ni lamentablemente la solución de @ Ryan, y me cansé de intentar resolver esto, así que simplemente me detuve, pero espero que alguien más lo obtenga porque prefiero usar webkit para razones de velocidad! (Estaba usando capybara-webkit 1.3.0
)
En caso de que ayude, aquí están mis versiones relevantes:
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
Probé la respuesta de James y la modifiqué para mi entorno actual. Aquí está mi código (especificación del sistema con Chrome sin cabeza):
require ''rails_helper''
describe ''Orders'', type: :system do
before do
# Temporarily change default_max_wait_time to wait for Stripe response
@old_wait_time = Capybara.default_max_wait_time
Capybara.default_max_wait_time = 10
end
after do
Capybara.default_max_wait_time = @old_wait_time
end
scenario ''Payment via Stripe'', js: true do
visit payment_path
click_button ''Pay with Card''
# Use VCR to avoid actual data creation
VCR.use_cassette ''orders/payment_via_stripe'' do
expect(page).to have_css(''iframe[name="stripe_checkout_app"]'')
stripe_iframe = all(''iframe[name=stripe_checkout_app]'').last
Capybara.within_frame stripe_iframe do
# Set values by placeholders
fill_in ''Card number'', with: ''4242424242424242''
fill_in ''MM / YY'', with: ''08/44''
fill_in ''CVC'', with: ''999''
# You might need to fill more fields...
click_button ''Pay $9.99''
end
# Confirm payment completed
expect(page).to have_content ''Payment completed.''
end
end
end
Estoy usando:
- Selenio-webdriver 3.14.0
- rspec-rails 3.8.0
- capibara 3.7.1
- raya 3.26.0
- carriles 5.2.1
- ruby 2.5.1
- vcr 4.0.0
- webmock 3.4.2
- Cromo 69
Mi aplicación está construida de acuerdo con https://stripe.com/docs/checkout/rails .
¡Problema resuelto!
Con un poco de ayuda de Parov a través de su pregunta y respuesta similares [ Poltergeist Stripe checkout.js ] localicé el problema utilizando una versión antigua de Capybara ''~> 1.1.2'' y el posterior efecto de dependencia que esto tuvo en las diversas pruebas de JavaScript. gemas (es decir, selenio, capybara-webkit, poltergeist ...).
Hacer una bundle update
del bundle update
de Capybara a 2.3.0, y así llevar a poltergeist a 1.5.1, con Selenio-webdriver en 2.42.0 y capybara-webkit en 1.1.0, hace que (casi) todo funcione.
Para el selenio, este método a través de la captura de problemas de Capybara en JS modal funciona:
stripe_iframe = all(''iframe[name=stripe_checkout_app]'').last
Capybara.within_frame stripe_iframe do
fill_in "email", with: "[email protected]"
...
end
Sin embargo, eso no funciona en poltergeist o capybara-webkit.
Para poltergeist, la sugerencia de parov funciona:
stripe = page.driver.window_handles.last
page.within_window stripe do
fill_in "email", with: "[email protected]"
...
end
Para capybara-webkit no pude hacer que nada funcionara, aunque dado que tenía algo que trabajaba con Poltergeist, no dediqué mucho tiempo a encontrar una solución para capybara-webkit.
¿Comentarios?
Para capybara-webkit , pude hacer que esto funcionara:
stripe_iframe = page.driver.window_handles.last
page.within_window stripe_iframe do
fill_in "email", with: "[email protected]"
...
end