How To Handle iFrames In Cypress

Enrique

Posted On: February 6, 2023

view count39270 Views

Read time17 Min Read

In today’s web development world, finding standalone web apps is challenging. However, we can find most of these web apps work with each other where the integrations happen either from the Front-end or Back-end. One of the oldest yet simple integration strategies is using iFrames when examining these integrations.

The < iframe > element has a somewhat convoluted history; introduced by Microsoft around 1997 and supported in early versions of Internet Explorer, it was incorporated into HTML 4.0, banished from XHTML, and reintroduced in HTML5.

Using iFrames is a good idea from the modern web development perspective. Still, it decreases the app’s testability from the UI perspective. Each iFrame is treated as a separate document via the browser, adding extra steps in our automation testing code as we need to map our elements inside those iFrames; imagine the complexity of handling nested iFrames. In addition, it could create flake test scripts if we don’t operate them correctly.

Cypress is an excellent framework for testing the front-end and back-end, but interacting with iFrames could be tricky. Testing iFrames with automated testing tools is necessary for many web apps. In this tutorial on how to handle iFrames in Cypress, you will learn how to write reliable tests for web applications that use iFrames and run them on the cloud Cypress grid.

So, let’s get started!

What are iFrames?

An I-frame, short for “inline frame,” is an HTML element that allows you to embed content from another source directly within a web page. Unlike traditional web content, which loads as a full page, I-frames enable you to display external content, such as videos, maps, or documents, within a designated portion of your webpage. This modular approach enhances user interactions and content integration.

When we add an iFrame to a page, we look through a window from that page into another site, with full interactivity within that space. It is why Google Maps, YouTube, and others encourage users to embed their content using an iFrame element; rather than hosting any portion of the complex web app ourselves, our page views the web service through an integrated window.

iFrame usage was much more popular before the explosion of JavaScript on the web (Resuscitated with HTML5). However, it remains vital in today’s web world (Especially with React and Flutter webs). Therefore, if we use iFrames to display external content on our website, we must ensure they work correctly.

Why is it essential to test the iFrames on our web pages? The logical answer is to guarantee everything is working as desired. Therefore, we test iFrames during the functional testing phase. Also, we validate the E2E flows to determine if the entire application is working at the point where the end-user interacts with it.

vimeo best of year

For a website, it means testing the website as it appears in a real browser. You’ll be loading up the website, serving accurate content, and then writing scripts to ensure you see what you expect. So let’s stop giving more context and start doing something worthwhile. Working with iFrames and Cypress.io is possible, and let’s demonstrate Cypress test automation with some functional code.

Cypress CTA

Is it possible to automate iFrames with Cypress?

Cypress has some difficulties working with iFrames primarily because for all built-in “cy” DOM traversal commands, there is an open Issue #136 about the iFrame support, saying that we can still use iFrames in Cypress. In this blog on how to handle iFrames in Cypress, we will share how to interact with DOM elements inside an iFrame.

For version purposes, we will use Cypress version 10.7; as a personal recommendation, always try stable versions before going directly to the latest version (Currently Cypress v12.5.1) as Cypress v11 has some changes related to Experimental features (cy.session errors), related Cypress v12, still evaluating the chrome web security configuration. Still using an older version of Cypress? or want to migrate to Cypress 10? Check out this blog on migrating your test automation suite to Cypress 10.

Cypress v10.7 was released on 08/30/2022.

Features:

  • The experimental feature of Cypress Studio has been brought back. It offers a visual method to create tests within Cypress by recording actions against the Application Under Test (AUT). This feature is only accessible for end-to-end tests and must be turned on through the e2e.experimentalStudio flag.
  • Support for Svelte component testing has been introduced. This feature has been released as an Alpha version, indicating the possibility of changes that could cause breaking in future Cypress releases. The issue #23037 has been resolved with this feature.
  • The “Latest Runs” and “Average Duration” columns in the specifications list now have hover-activated actions to help connect the project to the Cypress Dashboard. This resolves issue #22932.
  • Instructions for connecting projects to the Cypress Dashboard and recording a first test run have been added as informational banners. Users who do not plan to use the Cypress Dashboard can dismiss the banners to avoid seeing them in the future, resolving issues #22933, #22934, #22798, and #22935.
  • The “Create Spec from Component” feature, introduced in v10.5.0, is now available for Vue.js projects with a custom specification pattern configuration. This resolves issue #23071.
  • Custom configuration for the Webpack dev server in Angular component testing projects can now be provided through the “projectConfig” key. This enables support for projects that do not follow Angular CLI conventions, addressing issue #23161.
  • The setSystemTime function has been introduced, allowing the Cypress clock to be set to a new time. This resolves issue #15424.

Performance:

  • The behavior of the cy.session() command has been improved such that it no longer clears the DOM after a validation function runs. As a result, the need for a cy.visit() command after running cy.session() when using a validation function has been eliminated, addressing issue #22368.

Now, let’s focus on the iFrame test part.

Step 1: First, we need to identify our iFrame inside the DOM and perform any action inside the iFrame.

iframe tester

Step 2: Write spec file cypress/e2e/e2e_tests/test-iframe-cypress.cy.js that visit our web page and identifies the iFrame; we will use “iframetester.”

Our test looks good, and we can see the loaded iFrame.

lambdatest blog page

Step 3: Let’s update our spec file to type something and click on search input for the LambdaTest blog web page. Those elements are located inside the document’s body iFrame element.

Unfortunately, the test fails; Browsers adhere to a strict same-origin policy. It means that browsers restrict access between < iframes > when their origin policies do not match.

Step 4: To enable cross-domain iFrame access, we must set the property chromeWebSecurity to false in the file cypress.config.js and re-run the test.

security error page

After that, our test looks ok!

iframe testers

However, what about nested iFrames accessing an iFrame into an iFrame?

Step 5: We will use the iFrames web page for testing purposes. In this case, we will click the “iFrame 2” button, “Click Me 2.”

automation camp

We will use the “contentDocument” property; if the iFrame and the iFrame’s parent document are the Same Origins. It returns a Document that is the active document in the inline Frame’s nested browsing context.

Let’s run our spec file and see if the button is clicked successfully.

test iframe cypress

How to perform iFrames testing with Cypress?

Now, let’s focus on Cypress and iFrame and understand the code step by step. We are using Cypress v10.7 for testing iFrames with Cypress.

Subscribe to the LambdaTest YouTube channel for tutorials around Selenium testing, Playwright browser testing, Appium, and more.

Code Walkthrough:

Github button

Let’s start defining our config.json file; here, we can include some data and URLs.

Next, we need to establish our structure. As demonstrated in the following line of code, import MainPage from ‘../../page-objects/components/MainPage’, we aim to separate our Cypress locators from our tests using the Page Object Model (POM) approach. This structure can be found within the “page-objects” folder.

generate-iframe-cypress

As mentioned above, our methods and locators can be found there; in our example, we try to search on Google using an iFrame webpage (embedded Google search).

For this case, we are using a before() hook that will open up our page before all of our tests, and after that, we can test, keeping in mind if we need to switch URLs, we must use “cy.origin” as we will mention below.

Slow loading and empty iFrames validation

Let’s understand the code below; first it is vital to get the iFrame locator. Since, as we know, many iFrames are a bit slower to load, or sometimes iFrames are broken, for those cases, we must implement some assertions “be.visible” or “not.be.empty” can do the work. Second, assign an alias, and then we can navigate inside the elements of the iFrame.

Reusing our Code

We will probably access the iFrame’s elements in multiple tests; as we can see, we are using a static method and a class. The other approach is using Cypress custom commands inside the cypress/support/index.js. Not a big fan of using custom commands, but you can reuse the same code and create a custom command.

We can now see that after it went through all those steps, it was able to grab the body of the iFrame. So then we can wrap it with Cypress, using that .find() to navigate inside the iFrame body.

Cypress wrap command is used to yield objects placed in it and their resolved value, meaning that when you want to use Cypress commands like should, type, or click on an object or jQuery element, you should wrap.

Nested iFrames

What about dealing with nested iFrames? It could be a nightmare and happens very often on multiple web pages. In those cases, we can use the “contentDocument” approach, which is relevant when navigating with various iFrames, as we can see from the image.

Nested iFrames

Cross-origin E2E

One last part I would like to discuss is the “cy.origin”, as we are using version 10.7. This feature is not fully available if we don’t activate the experimental feature -> “experimentalSessionAndOrigin: true.” As you probably noticed, we used a new domain -> “https://www.play1.automationcamp.ir” but also we need to visit the specific web page.

Here is the test execution, which indicates that our Cypress iFrame testing approach is working:

Cross-origin E2E

In the next section of this tutorial on how to handle iFrames in Cypress, we will learn how to run our tests in the Cypress cloud grid.

How to handle iFrames in Cypress on the cloud grid?

We can utilize a Cypress cloud grid such as LambdaTest, which offers automated cross-browser testing on over 40 browsers and operating systems, and Cypress parallel testing to speed up test execution and facilitate large-scale Cypress testing. This will result in enhanced overall test coverage, leading to a better quality product, as we can test various combinations using the same test scripts.

To get started with Cypress e2e testing, follow the below-mentioned steps:

  1. Install LambdaTest Cypress CLI on your machine. Trigger the following command to install the same:
  2. After installation is completed, set up the configuration using the below command:
  3. Once the command is completed, lambdatest-config.json is created in the project folder. Next, enter the LambdaTest credentials from the LambdaTest Profile Section.
  4. Here is how you can configure the required browser & OS combinations in lambdatest-config.json:
  5. The run_settings section in the JSON file contains the desired Cypress test suite capabilities, including Cypress_version, build_name (Cypress-iframe), number of parallel sessions, etc.
  6. The “tunnel_settings” in the JSON file allows you to establish a connection between your local system and the LambdaTest servers through an SSH-based integration tunnel. With this tunnel in place, you can test locally hosted pages on all browsers supported by Cypress on LambdaTest.
  7. With the setup complete, it’s time to run the tests. Keep in mind that the “parallels” field in the “run_settings” file is set to five, meaning the tests will run in parallel without additional parameters. Note that the code used in previous tests remains unchanged when utilizing the cloud grid.

Shown below is the test execution status from the LambdaTest Automation Dashboard.

execution status from the LambdaTest Automation Dashboard

If we click on any of the tests, we can see the details of our Cypress test scripts video of the execution and the actual code executed in Cypress Grid; pretty neat.

Cypress test scripts video

Now, let’s see more details about our test code, click on the button next to our test title. It will open a page, and we can explore our code or identify some issues in case of failure.

Verify Nested Iframes

To view test performance metrics, go to the LambdaTest Analytics Dashboard. The Test Overview provides an overview of tests with stable behavior, while the Test Summary shows the total number of passed or failed tests and any completed or pending tests.

test performance metrics

If you are a developer or a tester and have a basic understanding of Cypress and want to take your knowledge to the next level, then this Cypress 101 certification course is for you.

Cypress 101 Certification

Wrapping Up

Working with iFrames could be a big deal with Cypress, but I hope this blog on how to handle iFrames in Cypress helps you overcome common issues I ran into with them. Even though Cypress has limitations with iFrames, there are ways to work around them.

“We must guarantee what we deliver works for everyone.” – Enrique A Decoss.

I hope the Cypress team addresses the native way to use “switchToFrame” soon; in the meantime, let’s continue using the workarounds available. Feel free to leave any comments or suggestions.

Happy Bug Hunting!

Frequently Asked Questions (FAQs)

How do you handle iframes with Cypress?

Cypress does not have direct access to the contents of an iFrame. However, you can switch to an iFrame by using the cy.iframe() command and interact with its content just like you would with the main document. The method requires the iFrame’s DOM element, which can be selected using a CSS selector.

How do you handle nested frames in Cypress?

In Cypress, you can handle nested frames by chaining multiple calls to the cy.iframe() command. For example, if you have a main document that contains an iframe, which in turn contains another iframe, you can interact with the nested iframe as follows:

cy.iframe(‘.outer-iframe’)
.iframe(‘.inner-iframe’)
.find(‘#element-in-inner-iframe’)
.click()

Note that you need to switch back to the main document after interacting with each iframe in the chain, by using the .its(‘document’) command.

Author Profile Author Profile Author Profile

Author’s Profile

Enrique

Enrique DeCoss, Senior Quality Assurance Manager at FICO is an industry leader in quality strategy with 16+ of experience implementing automation tools. Enrique has a strong background in Testing Tools, API testing strategies, performance testing, Linux OS and testing techniques. Enrique loves to share his in-depth knowledge in competencies including, Selenium, JavaScript, Python, ML testing tools, cloud computing, agile methodologies, and people Management.

Blogs: 10



linkedintwitter

Test Your Web Or Mobile Apps On 3000+ Browsers

Signup for free