Cypress and Stripe payments testing

One component of the web site I'm writing tests for at work uses Stripe for processing payments. Except the way we have it, the Stripe fields are broken out into separate fields and using separate iframes (as opposed to being in one iframe). Looking at Google search results, I saw that others were trying to test sites set up in the same way, but I wasn't able to find a solution.

I managed to figure it out.

Add to cypress.json:

"chromeWebSecurity": false,

Add to commands.js:

Cypress.Commands.add('iframeLoaded', { prevSubject: 'element' }, ($iframe) => {
const contentWindow = $iframe.prop('contentWindow')
return new Promise((resolve) => {
if (contentWindow && contentWindow.document.readyState === 'complete') {
  resolve(contentWindow)
} else {
  $iframe.on('load', () => {
    resolve(contentWindow)
  })
}
}) }) Cypress.Commands.add(
'getInDocument',
{ prevSubject: 'document' },
(document, selector) => Cypress.$(selector, document),
)
Cypress.Commands.add('getWithinIframe', (targetElement) =>
cy
.get('iframe')
.iframeLoaded()
.its('document')
.getInDocument(targetElement),
)

We're also using faker utils to generate random names and email addresses are randomly assigned to mailinator.com or yopmail.com. The relevant portion for that to be added to the script is:

const faker = require('faker')
let userData = {
randomFName: faker.name.firstName(),
randomLName: faker.name.lastName(), 
}

This uses the faker data to populate the renter details

cy.get('[name="renterInformation.email"]')
.focus()
.type('TEST-')
.type(userData.randomFName)
.type(userData.randomLName)
.type(getTestEmailString())
cy.wait(4000)
cy.get('[name="renterInformation.firstName"]')
.focus()
.type('TEST-')
.type(userData.randomFName)
cy.get('[name="renterInformation.lastName"]')
.focus()
.type(userData.randomLName)
cy.get('[id="phone-field"]').type('5125551212')

This reuses the same faker data for the credit card (invalid card used in this example):

cy.getWithinIframe('[name="cardnumber"]')
.type('4000000000000002') 
cy.get('[name="ccInformation.nameOnCard"]')
.focus()
.type(userData.randomFName)
.type(' ')
.type(userData.randomLName)
cy.get('[class="__PrivateStripeElement"]')
.eq(1)
.within(() => {
cy.getWithinIframe('[name="exp-date"]')
    .type('1232')  
}) cy.get('[class="__PrivateStripeElement"]')
.eq(2)
.within(() => {
cy.getWithinIframe('[name="cvc"]')
    .type('987')  
})
cy.get('[name="ccInformation.zipCode"]')
.type('78701')  
cy.get('[class="MuiIconButton-label"]')
.eq(14).click() // SAVE CARD TOGGLE

This is one of the wrappers around the iframe so that the Cypress script can find it:

cy.get('[class="__PrivateStripeElement"]')
.eq(1)
.within(() => {
cy.getWithinIframe('[name="exp-date"]')
    .type('1232')  
})
Previous
Previous

Useful debugging code for Cypress