// for this to work you need to set `"chromeWebSecurity": false` in cypress.json | |
describe('Make Stripe Payment', function() { | |
before(function() { | |
cy.visit('http://localhost:3000/en/stripe/checkout/') | |
Cypress.Cookies.preserveOnce('sessionid') | |
}) | |
it('should enter credit card details and finalise payment', function() { | |
cy.get('[data-test="button-FormStripeCart-PayWithCreditCard"]').click() | |
// there are better ways to get the iFrame in a promise, I think, and there is | |
// a new API coming up soon to deal with iFrames, but I was lazy and just put a | |
// wait here - 6secs is usually enough to let the Stripe popup load fully | |
cy.wait(6000) | |
cy.get('iframe').then($iframe => { | |
const doc = $iframe.contents() | |
let input = doc.find('input')[0] | |
// super weird stuff here, if you just input '4242424242424242', the value | |
// that you end up seing in the input element is jumbled up a little, | |
// probably because of the way how Stripe inserts spaces while you are | |
// typing. By luck I found out that this issue can get worked around if | |
// you just chain-call type() | |
cy | |
.wrap(input) | |
.type('4242') | |
.type('4242') | |
.type('4242') | |
.type('4242') | |
input = doc.find('input')[1] | |
cy | |
.wrap(input) | |
.clear() | |
.type('12') | |
.type('20') | |
input = doc.find('input')[2] | |
cy | |
.wrap(input) | |
.type('123') | |
.type('{enter}') | |
}) | |
cy.url({ timeout: 20000 }).should('contain', '/en/profile/my-orders/') | |
Cypress.Cookies.preserveOnce('sessionid') | |
}) | |
}) |
This comment has been minimized.
This comment has been minimized.
Try: cy.get('iframe.stripe_checkout_app').then(function($iframe) {
const $body = $iframe.contents().find('body')
cy
.wrap($body)
.find('input:eq(0)')
.type('4242424242424242')
cy
.wrap($body)
.find('input:eq(1)')
.type('1222')
cy
.wrap($body)
.find('input:eq(2)')
.type('123')
}) You will need to disable chromeWebSecurity: // cypress.json
--disable-site-isolation-trials: Check: https://docs.cypress.io/api/plugins/browser-launch-api.html# AND #1951 // /plugins/index.js
|
This comment has been minimized.
This comment has been minimized.
This was helpful! Thanks. A few updates for future search results (and probably myself): • Stripe must have updated their markup, so I had to use CSS attribute selectors to get it: Here is a full test that seems to work pretty well:
|
This comment has been minimized.
This comment has been minimized.
Thank you everyone for sharing! This was very helpful. |
This comment has been minimized.
This comment has been minimized.
+1 to that! Thanks all |
This comment has been minimized.
This comment has been minimized.
Very useful, thank you for sharing. Was wondering though has anyone tried writing some tests that interact with the 3D secure pages? It seems as if the payment gateway is now housed in a modal ? |
This comment has been minimized.
This comment has been minimized.
Very helpful, thanks. If anyone is using Elements instead of Checkout, something like this might be helpful. The code below is designed to test a form with separate credit card and expiry elements.
|
This comment has been minimized.
This comment has been minimized.
THANK YOU @techieshark - That was super helpful and clean. I'm new to Cypress and encountered this issue today, and just extended to add CVC element. |
This comment has been minimized.
This comment has been minimized.
Thanks for all the help. Not sure if everyone else found the same, but it seemed to me that you do need the cy.wait, or you can use a
And then follow it up with the main code (esentially the same as @mjhea0 's above)....
I found I needed |
This comment has been minimized.
This comment has been minimized.
Thank you everyone |
This comment has been minimized.
This comment has been minimized.
If you're using separate element for each of the input fields (card number, cvc, expiry), then each one of those will be loaded in separate iframe. What worked for me is this:
|
This comment has been minimized.
This comment has been minimized.
How can I create a local page with stripe form? |
This comment has been minimized.
This comment has been minimized.
has anyone tried to test https://stripe.com/docs/payments/3d-secure#example-of-a-3d-secure-2-flow 3D secure payment test? when after adding card details new popup message comes for confirmation which is iframe inside an iframe? |
This comment has been minimized.
This comment has been minimized.
@nikhilesh009 we're doing something like: cy.get('.stripe-form__card-element iframe').then(($element) => {
const $body = $element.contents();
cy.wrap($body.find('input[name=cardnumber]')).type('4000002760003184');
cy.wrap($body.find('input[name=exp-date]')).type('0423');
cy.wrap($body.find('input[name=cvc]')).type('123');
});
cy.get('.stripe-form__card-element iframe').then(($element) => {
const $body = $element.contents();
cy.wrap($body.find('input[name=postal]')).type('12345');
});
cy.get('#stripeSubmitButton').click();
// Have to give the inner iframe (challenge) enough time to load.
cy.wait(6000);
cy.get('iframe[name="__privateStripeFrame8"]').then(($iframe) => {
const $body = $iframe.contents();
cy.wrap($body.find('iframe#challengeFrame')).then(($el) => {
const $challenge = $el.contents();
// authorise
cy.wrap($challenge.find('#test-source-authorize-3ds')).click();
});
}); |
This comment has been minimized.
This comment has been minimized.
For the 3D secure I cleaned it up a bit and made it into a utility, so I can both confirm and deny it. Hope it helps someone function confirm3DSecureDialog (confirm = true) {
cy.wait(5000)
cy.get('iframe[name^=__privateStripeFrame]')
.then(($firstIFrame) => {
cy.wrap($firstIFrame.contents().find('iframe#challengeFrame'))
.then(($secondIFrame) => {
// authorise
const target = confirm ? '#test-source-authorize-3ds' : '#test-source-fail-3ds'
cy.wrap($secondIFrame.contents().find(target)).click()
})
})
} |
This comment has been minimized.
This comment has been minimized.
this one worked for me. thank you everyone for sharing your work |
This comment has been minimized.
This comment has been minimized.
Hi all, |
This comment has been minimized.
This comment has been minimized.
Yeah I get that from time to time too, but I just re-run, its not that often :D You can await an extra few seconds probably. |
This comment has been minimized.
This comment has been minimized.
Which version of Cypress are you using @jeremygottfried? |
This comment has been minimized.
This comment has been minimized.
cypress: "^3.6.1" |
This comment has been minimized.
This comment has been minimized.
Thanks @dobromir-hristov |
This comment has been minimized.
This comment has been minimized.
I've had success with using |
This comment has been minimized.
This comment has been minimized.
Thank you @mjhea0 I will check that out |
This comment has been minimized.
This comment has been minimized.
Thank you very much @dobromir-hristov! This solved the stripe 3D Secure issue for me. |
This comment has been minimized.
This comment has been minimized.
See my comment above. |
This comment has been minimized.
This comment has been minimized.
Thanks all :) |
This comment has been minimized.
This comment has been minimized.
For me to test it without 3ds, it was enough: cy.get('iframe[name="__privateStripeFrame5"]').then(function($iframe) {
const $body = $iframe.contents().find('body')
cy
.wrap($body)
.find('input[autocomplete="cc-number"]')
.type('4242424242424242', { force: true })
cy
.wrap($body)
.find('input[autocomplete="cc-exp"]')
.type('03/30', { force: true })
cy
.wrap($body)
.find('input[autocomplete="cc-csc"]')
.type('737', { force: true })
cy
.wrap($body)
.find('input[autocomplete="postal-code"]')
.type('12345', { force: true })
}) However, for 3ds I was struggling for a while. I hadd to add this to support/commands.js: Cypress.Commands.add('iframe', { prevSubject: 'element' }, $iframe => {
return new Cypress.Promise(resolve => {
$iframe.ready(function() {
resolve($iframe.contents().find('body'));
});
});
}); Obviously, in plugins I also used: module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
on("before:browser:launch", (browser = {}, launchOptions) => {
if (browser.name === "chrome") {
launchOptions.args.push("--disable-site-isolation-trials");
}
})
} And finally in the test (for 3ds part): cy.get('iframe[name^="__privateStripeFrame"]:eq(0)', { timeout: 20000 })
.iframe()
.find('iframe#challengeFrame')
.iframe()
.find('#test-source-authorize-3ds')
.click() |
This comment has been minimized.
This comment has been minimized.
I wasn't able to pass it with any of those methods. Any help? thanks! |
This comment has been minimized.
This comment has been minimized.
i have this problem with payment cypress : https://stackoverflow.com/questions/64391115/cypress-automatic-tests-for-credit-card-payment can you help me please. I wasn't able to pass it with any of those methods. Any help? thanks! |
This comment has been minimized.
This comment has been minimized.
There is another complication, we have our own receipt and invoice generated after the transaction is made, so if we stub the response, we cannot check our invoice and We do not visit, when you click on the button it goes to a redirect (it's not the old stripe popup) but the new stripe checkout is not API, but it's a redirect github.com/stripe-samples/checkout-one-time-payments |
This comment has been minimized.
This comment has been minimized.
I've created a more stable way to test Stripe Elements and released it as an npm package. The API is fairly simple to use and abstracts away waiting for any cy.get('#card-element').within(() => {
cy.fillElementsInput('cardNumber', '4242424242424242');
cy.fillElementsInput('cardExpiry', '1025'); // MMYY
cy.fillElementsInput('cardCvc', '123');
cy.fillElementsInput('postalCode', '90210');
}); |
This comment has been minimized.
This comment has been minimized.
Nice @dbalatero, thanks for sharing! |
This comment has been minimized.
Was really hoping this would work. When I try getting the iframe, i get undefined :(