DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • How to Test QR Codes in Your Applications
  • JUnit 5 Custom TestListeners
  • Getting Started With Microsoft Tool Playwright for Automated Testing
  • Injecting Chaos: Easy Techniques for Simulating Network Issues in Redis Clusters

Trending

  • A Guide to Using Amazon Bedrock Prompts for LLM Integration
  • Intro to RAG: Foundations of Retrieval Augmented Generation, Part 1
  • Knowledge Graph Embeddings and NLP Innovations
  • Power BI Embedded Analytics — Part 3: Power BI Embedded Demo
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Testing, Tools, and Frameworks
  4. How To Handle iFrames In Cypress

How To Handle iFrames In Cypress

In this article, the reader will learn how to handle iFrames in Cypress using the cy.iframe() command on the cloud grid.

By 
Enrique A Decoss user avatar
Enrique A Decoss
·
Nov. 14, 23 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
1.4K Views

Join the DZone community and get the full member experience.

Join For Free

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.

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. 

 npm install cypress@10.7 


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."

 cy.visit('https://iframetester.com/?url=https://www.lambdatest.com/blog')
//let's test iframe
cy.get('#iframe-window')
 


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.

 cy.visit('https://iframetester.com/?url=https://www.lambdatest.com/blog')
       //let's test iframe
       cy.get('#iframe-window')
           .should('be.visible')
           .should('not.be.empty')
           .then(($iframe) => {
               const $body = $iframe.contents().find('body')
      
       cy.wrap($body)
           .find(`input[name='s']`)
           .type('Cypress{enter}')
      
       })


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.

cy.get("#frame1")
           .its('0.contentDocument')
           .its('body')
           .find('#frame3')
           .its('0.contentDocument')
           .its('body')
           .find('#frame4')
           .its('0.contentDocument')
           .its('body')
           .find("#click_me_4").click()


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.

import config from './config.json'
import MainPage from '../../page-objects/components/MainPage'

describe('iFrame Testing Cypress', () => {
   before(function(){
       cy.visit(`${config.URL3}`)
   })
 
   it('Verify iframe working', () =>{
       
       //let's test iframe
       MainPage.iframeInput("#iframe-window",`input[name='s']`)
   })

 

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

describe('iFrame Testing Cypress', () => {
   before(function(){
       cy.visit(`${config.URL3}`)
   })


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.

it('Verify iframe working', () =>{
       
       //let's test iframe
       MainPage.iframeInput("#iframe-window",`input[name='s']`)
   })

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. 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.

it("Using 'contentDocument' - Nested iframes", () => {

       cy.origin(`${config.URL4}`, () => {
           cy.visit('/frames.html')
           cy.get("#frame1")
               .its('0.contentDocument')
               .its('body')
               .find('#frame3')
               .its('0.contentDocument')
               .its('body')
               .find('#frame4')
               .its('0.contentDocument')
               .its('body')
               .find("#click_me_4").click()
           //
       })   
   })


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.

cy.origin(`${config.URL4}`, () => {
           cy.visit('/frames.html')


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

Cross-origin E2E

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:

  • Install LambdaTest Cypress CLI on your machine. Trigger the following command to install the same:
npm install -g lambdatest-cypress-cli


  • After installation is completed, set up the configuration using the below command:
lambdatest-cypress init


  • Once the command is completed, lambdatest-config.json is created in the project folder. Next, enter the LambdaTest credentials from the LambdaTest Profile Section.
"lambdatest_auth": {
      "username": "",
      "access_key": ""


  • Here is how you can configure the required browser & OS combinations in lambdatest-config.json:
{
  "lambdatest_auth": {
     "username": "",
     "access_key": ""
  },
  "browsers": [
     {
        "browser": "MicrosoftEdge",
        "platform": "Windows 10",
        "versions": [
           "latest"
        ]
     },
     {
        "browser": "Chrome",
        "platform": "Windows 11",
        "versions": [
           "latest"
        ]
     },
     {
        "browser": "Chrome",
        "platform": "MacOS Monterey",
        "versions": [
           "latest"
        ]
     }
  ],


  • 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.
"run_settings": {
     "cypress_config_file": "cypress.config.js",
     "build_name": "build-Cypress-iframes",
     "parallels": 5,
     "specs": "./cypress/e2e/e2e_tests/*.cy.js",
     "pluginsFile": true,
     "ignore_files": "",
     "npm_dependencies": {
        "cypress": "10.7.0"
     },
     "feature_file_suppport": true
  },


  • 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.
"tunnel_settings": {
    "tunnel": false,
    "tunnelName": null
}


  • 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.
lambdatest-cypress run


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.

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!

Command-line interface IFrame (video format) Testing Test case

Published at DZone with permission of Enrique A Decoss. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How to Test QR Codes in Your Applications
  • JUnit 5 Custom TestListeners
  • Getting Started With Microsoft Tool Playwright for Automated Testing
  • Injecting Chaos: Easy Techniques for Simulating Network Issues in Redis Clusters

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!