Sometimes web pages show content inside a small window called an iframe. We need special ways to test and interact with these iframes because they act like separate pages inside the main page.
Iframe interaction strategies in Cypress
cy.get('iframe').its('0.contentDocument.body').should('not.be.empty').then(cy.wrap)
This code gets the iframe element, accesses its document body, and wraps it so you can use Cypress commands inside the iframe.
Always wait for the iframe content to load before interacting.
cy.get('iframe#myFrame').its('0.contentDocument.body').should('not.be.empty').then(cy.wrap).find('button').click()
cy.get('iframe').its('0.contentDocument.body').should('not.be.empty').then(cy.wrap).find('input[name="email"]').type('test@example.com')
cy.get('iframe').its('0.contentDocument.body').should('not.be.empty').then(cy.wrap).contains('Welcome').should('be.visible')
This test visits a page with an iframe, finds the iframe by id 'loginFrame', waits for it to load, clicks the submit button inside it, and then checks the main page for a success message.
describe('Iframe interaction test', () => { it('Clicks a button inside iframe', () => { cy.visit('https://example.com/page-with-iframe') cy.get('iframe#loginFrame').its('0.contentDocument.body').should('not.be.empty').then(cy.wrap) .find('button#submit').click() cy.get('#result').should('contain.text', 'Success') }) })
Always ensure the iframe is fully loaded before interacting to avoid flaky tests.
Use unique and stable selectors for iframes and elements inside them.
Remember that cross-origin iframes may block access due to browser security.
Iframes need special handling because they are like separate pages inside a page.
Use cy.get('iframe').its('0.contentDocument.body').then(cy.wrap) to work inside iframes.
Wait for iframe content to load before interacting to keep tests stable.
Practice
Solution
Step 1: Understand iframe structure
An iframe loads a separate HTML document inside the main page, acting like a mini browser window.Step 2: Recognize Cypress limitation
Cypress commands by default work on the main page DOM, so special steps are needed to access iframe content.Final Answer:
Because iframes load separate HTML documents inside the main page -> Option AQuick Check:
Iframes = separate pages inside page [OK]
- Thinking iframe content is part of main DOM
- Assuming iframe is always hidden
- Believing Cypress can't access iframe at all
Solution
Step 1: Access iframe document body
Useits('0.contentDocument.body')to get the iframe's body element correctly.Step 2: Wrap body for Cypress commands
Usethen(cy.wrap)to wrap the body so Cypress commands can chain inside the iframe.Final Answer:
cy.get('iframe').its('0.contentDocument.body').then(cy.wrap) -> Option DQuick Check:
Correct iframe body access = cy.get('iframe').its('0.contentDocument.body').then(cy.wrap) [OK]
- Using contentWindow instead of contentDocument
- Trying to wrap without then()
- Calling wrap() directly on body without cy.wrap
cy.get('iframe').its('0.contentDocument.body').then(cy.wrap).find('button').click()Solution
Step 1: Wrap iframe body for chaining
The code gets the iframe, accesses its body, wraps it so Cypress commands can chain inside.Step 2: Find and click button inside iframe
After wrapping, it finds the button inside iframe body and clicks it correctly.Final Answer:
Clicks the button inside the iframe after wrapping the iframe body -> Option CQuick Check:
Wrapping iframe body enables find() and click() inside iframe [OK]
- Assuming find() works on iframe element directly
- Not wrapping iframe body before chaining
- Confusing iframe contentDocument with undefined
cy.get('iframe').its('0.contentDocument.body').then(cy.wrap).find('input').type('Hello')
What is the likely cause?Solution
Step 1: Understand error meaning
'Cannot read property body of undefined' means contentDocument is undefined because iframe content is not ready.Step 2: Recognize iframe loading timing
Iframe content loads asynchronously; accessing contentDocument too early causes undefined error.Final Answer:
The iframe content has not loaded yet when accessing contentDocument -> Option AQuick Check:
Wait for iframe load before accessing contentDocument [OK]
- Assuming selector is wrong without checking
- Thinking then() with cy.wrap is invalid
- Ignoring iframe load timing issues
Solution
Step 1: Wait for iframe body to load
Usingshould('not.be.empty')waits until iframe body has content, ensuring it's loaded.Step 2: Wrap and interact safely
After confirming content, wrap the body and find the button to click reliably.Final Answer:
Use cy.get('iframe').its('0.contentDocument.body').should('not.be.empty').then(cy.wrap).find('button').click() -> Option BQuick Check:
Wait for iframe content before actions = Usecy.get('iframe').its('0.contentDocument.body').should('not.be.empty').then(cy.wrap).find('button').click()[OK]
- Using fixed wait times instead of content checks
- Trying to find elements directly on iframe without wrapping
- Reloading page repeatedly instead of waiting properly
Ready to prove it?
Pass the test and this pattern moves unknown
