How to test your Stripe Checkout with Cypress

In this article we will look into how we can test a website that uses Stripe Checkout bringing more testing to your eCommerce!

By Riccardo Giorato in cypress e2e stripe
Published on Tue Oct 05 2021

cover for the article How to test your Stripe Checkout with Cypress

All the code from this tutorial here: https://github.com/riccardogiorato/cypress-for-everything/tree/main/examples/stripe


Introduction

Stripe Checkout is a prebuilt, hosted payment page optimized for conversion. It connects automatically to your Stripe Account being able to create complete eCommerce products without having to code or maintain a checkout.

Like every other part of your app you can also test Stripe Checkout with Cypress!

For this tutorial we will use the staging demo environments created directly by using Stripe APIs that we found out by playing with the official demo page:


Inserting Credit Card Info and Billing

describe("Stripe Checkout", () => {
  it("Stripe Checkout test mode works!", () => {
    cy.request(
      "https://checkout.stripe.dev/api/demo-session?country=us&billingPeriod=monthly&hasBgColor=false&hasBillingAndShipping=false&hasCoupons=false&hasFreeTrial=false&hasShippingRate=false&hasTaxes=false&mode=payment&wallet=googlePay&hasPolicies=false&billingType=flat"
    ).then((response) => {
      expect(response.status).to.eq(200)
      expect(response.body).to.have.property("url")
      cy.visit(response.body.url)
      cy.url().should("contains", "https://checkout.stripe.com/pay/")

      cy.get("#email").type("SatoshiNakamoto@email.com")
      cy.get("#cardNumber").type("4242424242424242")
      cy.get("#cardCvc").type("123")
      cy.get("#cardExpiry").type(
        "12" + (new Date().getFullYear() + 10).toString().substr(-2)
      )
      cy.get("#billingName").type("Satoshi Nakamoto")
      cy.get("#billingPostalCode").type("94043")

      cy.wait(1000)
      cy.get(".SubmitButton").should(($div) => {
        expect($div.text()).to.include("Pay")
      })
      cy.get(".SubmitButton").click()
      cy.get(".SubmitButton").should(($div) => {
        expect($div.text()).to.include("Processing")
      })
    })
  })
})

In the first 3 lines from 3 to 5 we fetch a new demo URL from the stripe API that we will use just for this demo, in a real environment you will just use cy.visit to load your checkout page after the previous user steps.

cy.request(
  "https://checkout.stripe.dev/api/demo-session?country=us&billingPeriod=monthly&hasBgColor=false&hasBillingAndShipping=false&hasCoupons=false&hasFreeTrial=false&hasShippingRate=false&hasTaxes=false&mode=payment&wallet=googlePay&hasPolicies=false&billingType=flat"
).then((response) => {
  expect(response.status).to.eq(200)
  expect(response.body).to.have.property("url")
  cy.visit(response.body.url)
  cy.url().should("contains", "https://checkout.stripe.com/pay/")
})

The beauty of testing Stripe Checkout is that you don’t need to learn to use iFrames or other plugins like you would have to do with Stripe Elements. (Stripe Elements use iFrame inserted in your page making the testing a bit harder)

cy.get("#email").type("SatoshiNakamoto@email.com")
cy.get("#cardNumber").type("4242424242424242")
cy.get("#cardCvc").type("123")
cy.get("#cardExpiry").type(
  "12" + (new Date().getFullYear() + 10).toString().substr(-2)
)
cy.get("#billingName").type("Satoshi Nakamoto")
cy.get("#billingPostalCode").type("94043")

In this case we will simply be able to run the lines from 11 to 18 inserting the different fields like “email” or “cardNumber”, etc.

As the final step we wait 1 seconds or 1000 milliseconds before continuing the steps, we do this to let Stripe Api process the input cause Cypress tends to execute the previous steps too fast compared to a human and in many occasions Stripe could be still loading or validating the fields. And then we conclude the Checkout process by clicking the “SubmitButton”!

cy.wait(1000)
cy.get(".SubmitButton").should(($div) => {
  expect($div.text()).to.include("Pay")
})
cy.get(".SubmitButton").click()
cy.get(".SubmitButton").should(($div) => {
  expect($div.text()).to.include("Processing")
})

Conclusion

There is no right or wrong way to build an E2E test. The only thing you should care about is building a proper test that will automate your manual actions.

Less time to do a manual test and more time to have fun building other things!

Let us know in the comments which kind of test you would like to see next!


Resources