How to interact with Stripe’s iframes using WebdriverIO

Many test automation developers will, at some point, come across the challenging task of automating a payment flow for the app that they’re testing. This task becomes even more challenging when the integration with the payment services provider in the UI is done through iframes, as commonly happens with Stripe. In this guide, I will try to make the process of interacting with those iframes a little more straightforward using JavaScript and the WebdriverIO framework.

What are iframes?

Inline frames or iframes can be thought of as little windows within a web page. Developers use them to embed one web page inside another, which allows them to display content from an external source within their own website. Stripe makes use of this concept and provides its own web elements, which are used inside iframes.
Now, while this is very handy for web developers as they can integrate different web elements smoothly, it’s also tricky for QA engineers to automate tests that involve working with iframes, because of their encapsulated nature. The automation tool that we choose is important because it needs to be able to switch the context to interact with the elements inside the iframe.

Example

We’ll use WebdriverIO to automate the flow to add new credit card information to a web app that integrates with Stripe.

1. Obtaining the iframe locator:
Screenshot of the iframe element locator through the DevTools.
We’ll have to inspect the input element through the Chrome DevTools and search for the Stripe iframe that contains it. In this case, the iframe doesn’t have a unique ID, so one way to identify it could be with its title value. The xpath will look like this: 'iframe[title="Secure card payment input frame"]'.

2. Switching the browsing context to the Stripe iframe:
Once we have found the correct locator for pointing out to the desired iframe, we have to switch the context from the parent frame (webpage) to the particular one that we want to interact with, in WebdriverIO this can be done like this:
await browser.switchToFrame(await $('iframe[title="Secure card payment input frame"]'));
Basically, we create an Element object with await $(‘locator’) and pass it as a parameter to the switchToFrame() command.

3. Interacting with the elements inside the iframe:
Now that we have switched the browsing context to the particular iframe, we can perform some actions to the elements inside of it. Like adding the card number:

Screenshot of the card number input element locator inside the Stripe iframe through the DevTools.
One possible locator for the Card number input field could be //input[@name="cardnumber"], so we can write something like:
await $('//input[@name="cardnumber"]').setValue(cardNumber);
And the same goes for the rest of the input fields, like the expiration date, CVC and zip code.
It’s important to note that if we don’t switch the context to the iframe like we did in step 2, this locator //input[@name="cardnumber"] will not be recognized by the test-runner, the only way to access it is by previously switching to the specific iframe context.

4. Switching back to parent frame:
After we have filled all the necessary values for the credit card info, we’ll want to click the “Save Payment Method” button, which is outside of the Stripe iframe, so if we try to run something like:
await $('//button[contains(text(),"SAVE PAYMENT METHOD")]').click()
it won’t work since we’re still inside the Stripe iframe context; we first need to switch back to the parent frame context to interact with the elements of the main webpage. For this we can use the switchToParentFrame() WebdriverIO command:

await browser.switchToParentFrame();
await $('//button[contains(text(),"SAVE PAYMENT METHOD")]').click();
Enter fullscreen mode
Exit fullscreen mode

Finally, our method for adding the credit card info will look something like this:

async addNewCreditCard(cardNumber, expirationDate, cvc, zip) { await browser.switchToFrame(await $('iframe[title="Secure card payment input frame"]')); await $('//input[@name="cardnumber"]').setValue(cardNumber); await $('//input[@name="exp-date"]').setValue(expirationDate); await $('//input[@name="cvc"]').setValue(cvc); await $('//input[@name="zip"]').setValue(zip); await browser.switchToParentFrame(); await $('//button[contains(text(),"SAVE PAYMENT METHOD")]').click();
} 
Enter fullscreen mode
Exit fullscreen mode

And this is how, using WebdriverIO’s switchToFrame() and switchToParentFrame() commands, we can interact with the elements inside Stripe’s iframes after correctly identifying all the necessary locators.


Discover more from Coursity

Subscribe to get the latest posts sent to your email.

Leave a Comment

Your email address will not be published. Required fields are marked *

Discover more from Coursity

Subscribe now to keep reading and get access to the full archive.

Continue reading

Scroll to Top
Martins ad network.