Testing iframes with Cypress — including Stripe and HelloSign
At Appear Here our mission is to help anyone with an idea find space to make it happen. And to make sure we can keep serving that mission, we need to ensure stability of our core functionality to pay and sign contracts, so brands can complete their booking after they’ve found their space.
One of the challenges with this are our end to end tests. And more specifically, that testing iframes with Cypress can be a bit of a nightmare at its current state and the solutions out there don’t really solve the issue of needing arbitrary waits here and there.
This is why we decided to give you the code to unlock testing iframes in Cypress the right way. And don’t worry, it’s simpler than you expect.
We know the pain, you want to test a credit card, or 3D-Secure Stripe iframe and you first go to Google. You start copy pasting code, but you always end up needing a 5s cy.wait()
. And as a good developer, at the back of your head you always have that nagging voice reminding you of what's in that part of the codebase. Especially because it means you've essentially written a flaky spec (what if it takes 5001ms for that iframe to load?).
Well we had the same problem and we had the flaky specs, we tried some workarounds and solutions from Google but nothing helped us move away from the waits. In the end we decided it will be best if we just spend the time to fix this properly, and voila — it paid off. We know we could create a package for it, but we opted to just post the source code and explain how it works instead. One, because it’s simple to understand, and 2, because we think this should be core Cypress functionality and not a package.
And if a person from Cypress is reading this — feel free to take the ideas in this code and apply them directly to Cypress. We’ll be more than happy if an upgrade allows us to delete this from our codebase.
So, here’s the solution to the biggest pain — waiting for iframes to load. Further down we also give you the exact code to test Stripe and HelloSign iframes.
Waiting for iframes to load
Add the following code to your commands.js
file, to add an .iframe()
command in your Cypress suite:
Why does this work and how is it different to other solutions online about it at the moment?
The main difference is, most posts out there don’t account for Chrome’s behaviour when it loads iframes. And that is, it first loads an about:blank
page, fires all the load events and sets the readyState
to complete
. This can trick any listener into thinking the iframe has loaded, and that is because it actually has - it has fully loaded an about:blank
frame. But it is just getting started with loading the source you've actually set and want to wait for.
Our command takes this into account and doesn’t stop listening for the load event until the source we’ve set is the location the iframe actually starts loading.
How to use the .iframe()
command
Here’s how you would wait for and interact with an iframe, using the command above:
Using the command with Stripe or HelloSign
Fill in a Stripe credit card form
Here’s how you’d use this command to fill in a Stripe credit card form. For this one we’ve used the help of the moment
library. If you don't already use moment
, you can either hardcode the dates for now, or replace that bit with your own logic.
Add the following to your commands.js
Then use it from any test like so:
Fail/succeed a Stripe 3D Secure check
Snippet for commands.js
to wait for the 3D Secure iframe:
Then in combination with fillOutCreditCardForm
, you can use it from any test file like so:
Sign a HelloSign contract
Here are the commands.js
commands you need:
And using this from a test file becomes a piece of cake, just call:
If you have any other examples testing 3rd party integrations in Cypress, post them in the comments.
We expect (and hope) Cypress will eventually fix these iframe issues on their end and make this blog post redundant. So keep an eye out on their updates to make sure you don’t implement this for nothing. At the moment of writing, we’re on Cypress version 4.0.2.