Cypress - Frames
Cypress - Working with Iframes
Section titled “Cypress - Working with Iframes”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.
Native Iframe Interaction
Section titled “Native Iframe Interaction”Cypress can interact with iframe elements natively. The general approach involves:
- Locating the iframe element on the page.
- Accessing its
contentDocumentproperty, which holds the iframe’s DOM. - Ensuring the document has loaded, then wrapping its
body(or a specific element within the iframe) withcy.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.
Custom Command for Reusability (Recommended)
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.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();Direct Interaction Example
Section titled “Direct Interaction Example”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!'); });});Historical Note: cypress-iframe Plugin
Section titled “Historical Note: cypress-iframe Plugin”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.
Considerations for Iframes
Section titled “Considerations for Iframes”- Cross-Origin Iframes: Interacting with cross-origin iframes has security restrictions. Cypress can interact with them if
chromeWebSecurityis set tofalsein yourcypress.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.