Skip to content

Cypress - Frames

Web pages sometimes use iframes (inline frames) to embed content from another source or to isolate parts of a page. Cypress provides mechanisms to interact with elements inside iframes.

Cypress can interact with iframe elements natively. The general approach involves:

  1. Locating the iframe element on the page.
  2. Accessing its contentDocument property, which holds the iframe’s DOM.
  3. Ensuring the document has loaded, then wrapping its body (or a specific element within the iframe) with cy.wrap() to continue using Cypress commands within the iframe’s context.

It’s important to ensure the iframe has fully loaded before attempting to interact with its content. Cypress’s retry-ability helps, but explicit checks might sometimes be necessary.

Section titled “Custom Command for Reusability (Recommended)”

For cleaner tests, you can create a custom command in cypress/support/commands.js to encapsulate iframe interaction logic:

cypress/support/commands.js
Cypress.Commands.add('getIframeBody', (iframeSelector) => {
// Get the iframe > CGet the document > CGet the body
cy.log('Getting iframe body');
return cy.get(iframeSelector, { timeout: 10000 })
.its('0.contentDocument.body').should('not.be.empty')
// Tthen wrap the body
.then(cy.wrap);
});

You would then use this custom command in your tests:

cy.getIframeBody('iframe#my-iframe').find('#element-inside-iframe').click();

Below is an example of directly interacting with an iframe without a custom command. Let’s assume you have an iframe with the ID the-iframe and a button with ID iframe-button inside it.

describe('Iframe Interaction Test', () => {
it('should interact with an element inside an iframe', () => {
cy.visit('your-page-with-an-iframe.html'); // Replace with your test page
// Get the iframe element
cy.get('iframe#the-iframe')
.its('0.contentDocument.body') // Access the body of the iframe's document
.should('not.be.empty') // Ensure the body is loaded
.then(cy.wrap) // Wrap the body to use Cypress commands
.find('#iframe-button') // Find the button within the iframe
.should('be.visible')
.click();
// You can also assert changes outside the iframe if the click triggers them
// cy.get('#status-message').should('contain.text', 'Button clicked!');
});
});

In earlier versions of Cypress, or for specific complex scenarios, the cypress-iframe plugin was a common solution. It provided commands like cy.frameLoaded() and cy.iframe().

// Example using cypress-iframe (less common now)
// First, install: npm install -D cypress-iframe
// Then, in cypress/support/e2e.js (or commands.js):
// import 'cypress-iframe';
describe('Iframe with cypress-iframe plugin', () => {
it.skip('Test Case with cypress-iframe', () => { // .skip as native is preferred
cy.visit("https://jqueryui.com/draggable/"); // Example site
cy.frameLoaded('.demo-frame'); // Load the frame using its selector
cy.iframe().find("#draggable").then((el) => {
const text = el.text();
expect(text).to.contains('Drag me around');
cy.log(text);
});
});
});

While cypress-iframe still works, Cypress’s native capabilities for iframe handling have improved, and creating a custom command as shown above is often preferred for better control and consistency with Cypress’s built-in command structure.

  • Cross-Origin Iframes: Interacting with cross-origin iframes has security restrictions. Cypress can interact with them if chromeWebSecurity is set to false in your cypress.config.js, but this is generally discouraged for production testing as it doesn’t reflect real user browser security. Test content within cross-origin iframes in isolation if possible.
  • Loading Time: Iframes can take time to load. Ensure your commands wait for the iframe and its content to be ready. Cypress’s default timeouts and retry-ability often handle this, but explicit waits or assertions on iframe content might be needed.
  • Multiple Iframes: If a page has multiple iframes, you’ll need to uniquely identify the one you want to interact with using its selector.

Interacting with iframes requires careful targeting, but Cypress provides the tools to do so effectively.