Testing iframes in Cypress requires a different approach because Cypress cannot directly access the contents of an iframe due to browser security restrictions. To interact with elements inside an iframe, you must first get the iframe’s document and body, then wrap the contents using Cypress commands.
This article explains everything related to iframes in Cypress, including how to automate it.
What is an iFrame in Web Development
An iframe is an HTML element used to embed another HTML page within the current document. It works like a window inside a page that displays external content such as videos, forms, or entire websites without redirecting the user. An iframe has its own DOM and JavaScript context, separate from the parent page.
When to use an iframe in Cypress?
Cypress does not natively support iframe traversal like it does with standard DOM elements. However, you may need to interact with iframe content in scenarios such as:
- Testing third-party content embedded via iframes (like payment gateways or external forms)
- Verifying dynamic or modular content loaded inside iframes
- Simulating user interactions within iframe-hosted components
- Checking layout, data, or behavior inside embedded applications
Read More: How to handle Cypress Asynchronous Behavior?
Why are iframes in Cypress Challenging?
Cypress runs within a single browser context and tightly controls the DOM to ensure stable and predictable tests. However, iframes create a separate browsing context, which makes automation difficult.
Key challenges include:
- Separate DOM Context: Since iframes maintain their own DOM, Cypress cannot directly access or interact with elements inside an iframe without special handling.
- Cross-Origin Restrictions: If the iframe loads content from a different origin, browser security policies prevent Cypress from accessing it.
- Asynchronous Loading Issues: If iframes are not appropriately handled, Cypress may try to interact with the iframe before fully loading, leading to errors or flaky tests.
Read More: How to handle Cypress Asynchronous Behavior?
- No Native Support in Core Cypress Commands: Cypress does not provide built-in commands for iframes, so you must rely on custom solutions or third-party plugins.
How to Automate iFrames in Cypress?
You can automate iframe elements using plugins like cypress-iframe or by writing custom commands. However, you can only interact with iframe content on the same origin (domain, port, and protocol) as your main application. Cypress cannot access cross-origin iframes due to browser security restrictions.
What you can do with same-origin iframes:
- Access and interact with elements inside the iframe.
- Wait for the iframe to load before performing actions.
- Use Cypress assertions to validate content within the iframe.
How to Perform iFrames Testing with Cypress?
To test iframe content in Cypress, you can either use the cypress-iframe plugin or define a custom command tailored to your project.
Approach 1: Using the Cypress-iframe Plugin
This plugin simplifies iframe interactions using frameLoaded() and iframe() helpers. It works well for teams looking for a plug-and-play solution.
npm install -D cypress-iframe import 'cypress-iframe'; cy.frameLoaded('#my-iframe'); cy.iframe('#my-iframe').find('button.submit').click();
Approach 2: Using a Custom Command
This method manually accesses the iframe’s contentDocument.body, waits for it to load, and wraps it so that Cypress can interact with its elements. It’s useful when you need more control or plugins don’t work for your specific iframe structure.
Cypress.Commands.add('getIframeBody', (selector) => { return cy.get(selector) .its('0.contentDocument.body') .should('not.be.empty') .then(cy.wrap); }); cy.getIframeBody('#my-iframe').within(() => { cy.get('input#name').type('Ayush'); cy.get('button#submit').click(); });
How to Test iFrame in Cypress Using Native Commands?
You can test iframe content in Cypress using only native commands if the iframe is on the same origin as your test suite. Cross-origin iframes are blocked due to browser security policies.
Here are the two methods to be used for interacting with iFrames in Cypress:
1. Using .get(0)
This fetches the iframe’s raw DOM node and accesses its contentDocument.body to interact with the content.
cy.get('iframe#my-frame') .get(0) .then((iframe) => { const body = iframe.contentDocument.body; cy.wrap(body) .find('h1') .should('contain.text', 'Welcome'); });
2. Using .find(‘body’)
This method uses .its() to access the iframe’s content document and body, then wraps it for further interaction. It supports proper command chaining.
cy.get('iframe#my-frame') .its('0.contentDocument') .should('exist') .its('body') .should('not.be.empty') .then(cy.wrap) .find('input[name="email"]') .type('thakurayushsingh82@gmail.com');
How to Handle iframe in Cypress Using a Plugin?
To handle iframes in Cypress, firstly install the plugin cypress-iframe
Execute the below command from the root of your project where the package.json file exist
npm install -D cypress-iframe
This will install the cypress-iframe plugin as dev dependency.
After the installation, open the cypress/support/commands.ts file and add the below line to import the plugin globally
import 'cypress-iframe'; // or require('cypress-iframe');
Cypress-iframe plugin provides three commands to interact with iframes.
- frameLoaded
- iframe
- enter
cy.frameLoaded(<selector>) will ensure that the frame is loaded within the webpage
Example
cy.frameLoaded("#myframeID")
cy.iframe(<selector>) will get the reference for the iframe based on the iframe selector provided. You can then chain the command to perform further actions on the iframe
Example
cy.iframe("#iframeID").contains("button", "Click Here").click()
cy.enter(<selector>) will allow to perform multiple actions within the iframe.
Example
cy.enter("#myiframeID").then(iframeBody => { iframeBody().find(".button").click() iframeBody().contains("p", "someText").should("be.visible") )
How to Handle Slow-Loading, Empty, and Nested iframes in Cypress?
iFrame testing becomes more complex when dealing with slow-loading content, dynamic rendering, or nested iframe structures. Below are key strategies to handle these cases effectively.
1. Slow Loading and Empty iFrames Validation
Cypress will fail if the iframe’s body is still empty. To prevent such issues, validate that the iframe has loaded before interacting. Here’s how.
cy.get('iframe#my-frame') .its('0.contentDocument.body') .should('not.be.empty') .then(cy.wrap) .find('h1') .should('contain.text', 'Welcome');
To improve readability, implement this logic into a custom command:
Cypress.Commands.add('getIframeBody', (selector) => { return cy.get(selector) .its('0.contentDocument.body') .should('not.be.empty') .then(cy.wrap); });
2. Reusing Code for Multiple Tests
Instead of repeating iframe access logic in every test, split it into utility functions or custom commands. This improves test maintainability and makes it easy to update handling in one place if the DOM changes.
Cypress.Commands.add('iframeFind', (iframeSelector, innerSelector) => { return cy.get(iframeSelector) .its('0.contentDocument.body') .should('not.be.empty') .then(cy.wrap) .find(innerSelector); });
Read More: Code Reusability In Software Development
3. Navigating Inside the iframe
Once the iframe’s body is wrapped using cy.wrap(), continue using Cypress commands as usual like .click(), .type(), .select(), and assertions.
cy.getIframeBody('#login-frame').within(() => { cy.get('input#username').type('admin'); cy.get('input#password').type('123456'); cy.get('button[type="submit"]').click(); });
Read More: Using Cy.wrap in Cypress
4. Handling Nested iFrames
Nested iframes are more complex due to the traversal across multiple document layers. To handle this, you’ll need to access the inner iframe through the outer one’s document.
cy.get('iframe#outer-frame') .its('0.contentDocument.body') .should('not.be.empty') .then(cy.wrap) .within(() => { cy.get('iframe#inner-frame') .its('0.contentDocument.body') .should('not.be.empty') .then(cy.wrap) .find('p') .should('contain.text', 'Nested Content'); });
5. Cross-Origin Testing with cy.origin()
If the iframe loads content from a different domain, Cypress focuses on browser security and won’t allow direct DOM access. However, starting with Cypress v10+, cy.origin() command can interact with cross-origin content by defining logic inside a special context.
cy.origin('https://external-domain.com', () => { cy.visit('/iframe-content'); cy.get('h2').should('contain.text', 'External Frame'); });
Read More: Cross-Origin Testing in Cypress
Why Use BrowserStack Automate to Run Cypress Tests?
Here’s why you should run your Cypress tests on Real Devices & Browsers using BrowserStack Automate:
- Diverse Environment Testing: It enables the execution of Cypress tests across a broad selection of browsers and operating systems, eliminating the necessity for maintaining local testing infrastructure. This ensures consistent application performance across various platforms.
Read More: Cross-browser testing with Cypress
- Parallel Testing: BrowserStack Automate significantly reduces total testing time by allowing simultaneous execution of multiple Cypress test suites, facilitating quicker iterative feedback and accelerated deployment cycles.
Read More: Run Cypress tests in parallel
- CI/CD Integration: The platform seamlessly integrates with major CI/CD systems, including Jenkins, Travis CI, CircleCI, and GitHub Actions, automating the testing process within the development pipeline.
- Diagnostic Tools for Better Debugging: BrowserStack provides comprehensive diagnostic capabilities, including detailed logs, screenshots, and video recordings of test sessions, aiding in the swift identification and resolution of issues.
- Testing on Real Devices: Beyond simulated environments, BrowserStack also supports testing on real devices and browsers on the cloud, offering more precise and real-world test outcomes.
- Customizable Test Execution: Users can tailor test executions to meet specific needs through BrowserStack’s user interface or APIs, enabling adaptable and controlled test runs.
BrowserStack Automate is an excellent choice for running Cypress tests because it offers a scalable, cloud-based infrastructure that eliminates the need for complex local setups.
With support for real-time cross-browser testing, parallel execution, and integrations with CI/CD pipelines, BrowserStack ensures faster test runs and streamlined workflows.
Choose BrowserStack Automate to enhance the reliability and performance of your Cypress test suite with ease.
Best Practices for Testing iframe in Cypress Using Native Methods
Here are some of the best practices for testing iframe in Cypress using native methods:
- Use Custom Commands: Accessing iframe content with native Cypress methods involves multiple chained steps. Creating custom commands improves readability and reduces duplication. This also centralizes iframe logic, so you can update it in one place when needed.
- Avoid Cross-Origin iFrames: Cypress cannot access iframe content from a different domain using native methods due to browser security restrictions. Always test iframe content hosted on the same origin as your application.
- Wait for the iframe to Load Fully: iFrames often load asynchronously. Always verify the iframe’s content has loaded by checking that the body is not empty before interacting with its elements to avoid test failures.
Read More: What is Lazy loading?
- Modularize Tests: Instead of embedding iframe logic into every test case, separate it into reusable components or helper functions. This reduces duplication, making tests easier to understand and maintain.
- Validate the Visibility and State of iFrames: Before interacting with iframe content, ensure that the iframe is visible and interactive. Depending on user behavior or the page’s state, iFrames can be hidden, collapsed, or conditionally rendered.
Conclusion
Testing iframes in Cypress can be challenging due to the complexities of handling slow-loading, nested, and cross-origin frames. However, by leveraging native commands and plugins, you can overcome these challenges and ensure your tests are efficient and reliable.
BrowserStack Automate provides an added advantage by offering real device cloud testing, cross-browser compatibility, and a scalable infrastructure for running Cypress tests. This allows you to ensure that your iframe interactions work seamlessly across different environments.
Useful Resources for Cypress
Understanding Cypress
- Cross Browser Testing with Cypress : Tutorial
- Run Cypress tests in parallel without Dashboard: Tutorial
- Handling Test Failures in Cypress A Comprehensive Guide
- Cypress Test Runner: Tutorial
- Handling Touch and Mouse events using Cypress
- Cypress Automation Tutorial
- CSS Selectors in Cypress
- Performance Testing with Cypress: A detailed Guide
- Cypress Best Practices for Test Automation
- Test React Native Apps with Cypress
- Cypress E2E Angular Testing: Advanced Tutorial
- Cypress Locators : How to find HTML elements
- Maximizing Web Security with Cypress: A Step-by-Step Guide
- Conditional Testing in Cypress: Tutorial
- Cypress Web Testing Framework: Getting Started
- Cypress Disable Test: How to use Skip and Only in Cypress
- What’s new in Cypress 10? How it will change your current testing requirements
Use Cases
- How to Record Cypress Tests? (Detailed Guide)
- How to run your first Visual Test with Cypress
- How to Fill and Submit Forms in Cypress
- How to Automate Localization Testing using Cypress
- How to run Cypress Tests in Chrome and Edge
- How to use Cypress App Actions?
- How to Run Cypress Tests for your Create-React-App Application
- How to Run Cypress Tests in Parallel
- How to handle Click Events in Cypress
- How to Test React using Cypress
- How to Perform Visual Testing for Components in Cypress
- How to run UI tests in Cypress
- How to test redirect with Cypress
- How to Perform Screenshot Testing in Cypress
- How to write Test Case in Cypress: (with testing example)
Tool Comparisons