Testing Stripe Integration with Cypress

Writing E2E tests for custom Stripe payment flow integrated into a front-end application

Bartek Golota
SwingDev Insights
5 min readJun 29, 2021

--

One of my recent projects was a simple checkout application that was using Stripe to implement credit card payments. We’ve chosen Cypress as our end-to-end testing framework because of its ease of use and great debugging tools. Whilst writing tests with Cypress is pretty straightforward we did face few challenges when testing Stripe integration.

Illustration: Adrianna Pisarska, UI/UX Designer at SwingDev

Stripe integration

Stripe provides various ways to integrate payments into your application. The most common and easiest to implement is the pre-built checkout page, a “Stripe-hosted payment page that lets you collect payments quickly”. If you want quick implementation you’d probably choose this option. Furthermore, it doesn’t need end-to-end testing which makes the implementation even faster.

If you need more control over payment form appearance and behavior you’d have to choose Stripe custom payment flow which allows integrating payment form elements directly into your application and customizing styles according to your needs. You can choose between using a single card element (which displays all the fields) or displaying form fields separately. Our choice was the latter.

Testing custom payment flow

Custom payment flow integration requires end-to-end testing to make sure everything works as expected and we get a smooth user experience.

What do we need to test?

  • Form elements should be visible
  • The form should validate user input
  • Form submitting should be disabled until all fields are valid
  • The error should be shown when the form submit fails

Let’s create our test skeleton:

Mocking Stripe API

To avoid testing API and decrease the flakiness of our tests we should take full control over API responses by mocking all the Stripe-related requests. We’ll use Cypress intercept method and beforeEach hook to make sure it’s applied before every test.

Interacting with Stripe elements

Some of our tests require interacting with Stripe elements to check our application behavior in specific circumstances. Stripe elements are hosted on Stripe servers and are displayed on the page using an iframe. Cypress has some limitations when interacting with elements within an iframe. Here’s an official article that describes what are the limitations and how to get around some of them.

Disabling web security

To enable cross-domain iframe interaction, we’ll need to disable web security in Cypress.

Disabling web security comes with some consequences (e.g. we might miss some issues that we’d normally catch in a browser with web security enabled) therefore it’s generally better to run Stripe tests in separation from other test suites.

To disable web security we need to adjust chromeWebSecurity flag in cypress.json config file.

Finding Stripe elements

Now we can create a custom command to find Stripe element on our page. Stripe uses data-elements-stable-field-name attribute to store field name. Available field names are: cardCvc, cardNumber, cardExpiry and postalCode. Our custom command getStripeElement will dig into Stripe element iframe context and will try to find the input element we’ll need for our tests within that context.

This command needs to be executed within a context of an iframe wrapper to match only the field we’re looking for.

Creating tests

Before we start creating tests, we need to take care of one more thing. In our tests, we’ll need to find specific elements on the page. For that, we’re using a simple custom command getByTestId that leverages the test-id concept to make our tests resilient to change.

Ok, let’s start creating our tests. Let’s say we’re using card number, expiry and CVC elements from Stripe within card-number, card-expiry and card-cvc wrappers respectively.

Checking elements existence

First, we need to check whether stripe elements are displayed. Every Stripe element creates a wrapping div with class StripeElement. We can use that to check if an element is displayed on the page.

Testing validation

The next step is to test user input validation. Stripe JS SDK provides a convenient way of hooking into form element events and getting input validation state. We can use that to display validation information in our app. Let’s say we’re adding invalid class to Stripe element wrapper in case of a validation error. Our validation tests could look as follows:

Ensuring form is disabled until valid

Now we need to ensure form submission is disabled until all the field values have a valid format. Although validation is performed in Stripe API, it’s a good practice to pre-validate data on the client-side before submitting and processing it on the backend.

Testing submission errors

In order to provide a smooth user experience, our application should show descriptive error messages whenever there was a problem with user flow. Let’s create a test that will check that.

First, we need to mock Stripe endpoint to return erroneous status code. Our application should consume that error and display a relevant error message. The test case will simulate valid form submission and check whether an error message is displayed in this specific scenario.

And that’s it! We’ve created thorough test suites for our custom Stripe payment flow integration that will ensure our implementation is solid and gives a good user experience.

Summary

In this article, we’ve used Cypress to create a test suite for different aspects of Stripe custom payment flow integration including:

  • Mocking Stripe API
  • Testing Stripe elements
  • Testing payment form behavior

Depending on your implementation you might want to add or remove some tests but I hope this suite can serve as a good foundation for your Stripe end-to-end testing.

Conclusion

Cypress is a great framework for testing end-to-end scenarios of any front-end application. Its clean and intuitive API helps to create not only simple tests but is also capable of testing non-trivial 3rd party tools integration like Stripe custom payment flow.

If this article has been interesting to you, we encourage you to explore career opportunities at SwingDev.

--

--