Testing iframes with Cypress — including Stripe and HelloSign

Loran
Appear Here Product Engineering
4 min readApr 8, 2020

--

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:

Get the code

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:

Get the code

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:

Get the code

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:

Get the code

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.

--

--