Iframe — это HTML-элемент, позволяющий встраивать один документ HTML
внутрь другого. В тестировании на Cypress взаимодействие с iframe
представляет особую сложность, так как стандартные команды Cypress
(cy.get, cy.click, cy.type)
напрямую не работают с содержимым iframe. Это связано с тем, что iframe
создает отдельный контекст документа и отдельный DOM, что требует
специального подхода для получения доступа к элементам внутри него.
Для взаимодействия с элементами внутри iframe необходимо сначала
получить body внутреннего документа.
Прямое использование cy.get('iframe').find('selector')
обычно не работает. Правильная последовательность действий:
cy.get('iframe')
.its('0.contentDocument.body')
.should('not.be.empty')
.then(cy.wrap)
.find('selector')
.click();
Разбор шагов:
cy.get('iframe') — выбор самого iframe
на странице..its('0.contentDocument.body') —
обращение к DOM документа внутри iframe. 0 здесь указывает
на первый найденный элемент iframe..should('not.be.empty') — проверка,
что тело iframe загружено. Без этой проверки часто возникают ошибки
из-за асинхронной загрузки..then(cy.wrap) — оборачивает
содержимое body в объект Cypress, чтобы можно было
применять стандартные команды (find, click,
type).Чтобы не повторять одно и то же в тестах, удобно создать кастомную команду Cypress. Например:
Cypress.Commands.add('getIframeBody', (iframeSelector) => {
return cy.get(iframeSelector)
.its('0.contentDocument.body')
.should('not.be.empty')
.then(cy.wrap);
});
Использование команды в тесте:
cy.getIframeBody('iframe#my-frame')
.find('button.submit')
.click();
Это делает тесты чище и позволяет легко работать с различными iframe.
Если iframe загружает страницу с другого домена, возникает ограничение политики CORS (Same-Origin Policy). В таком случае Cypress не может получить доступ к содержимому iframe напрямую. Возможные подходы:
Важно понимать, что при работе с iframe стороннего домена Cypress ограничен, и любые обходные решения требуют дополнительной инфраструктуры.
Cypress позволяет работать не только с DOM, но и с событиями внутри iframe. Например, симуляция клика или заполнение формы:
cy.getIframeBody('iframe#login-frame')
.find('input[name="username"]')
.type('admin');
cy.getIframeBody('iframe#login-frame')
.find('input[name="password"]')
.type('12345');
cy.getIframeBody('iframe#login-frame')
.find('button[type="submit"]')
.click();
Каждое действие проходит через getIframeBody, что
обеспечивает синхронизацию и обработку асинхронной загрузки
контента.
Загрузка iframe может занимать время, особенно если внутри него подгружается внешний контент. В Cypress важно использовать цепочку команд, которые автоматически ожидают появление элементов:
.should('exist') — проверка
существования элемента..should('be.visible') — проверка
видимости..wait() — явное ожидание, только если
другие методы не помогают (использовать минимально).Пример:
cy.getIframeBody('iframe#my-frame')
.find('div.content')
.should('be.visible')
.then((div) => {
// дополнительные действия
});
cy.wrap,
чтобы использовать все преимущества Cypress..should('not.be.empty') или .should('exist')
перед взаимодействием с элементами.Работа с iframe в Cypress требует понимания изоляции контекстов и правильной синхронизации. Систематическое использование кастомных команд и проверок позволяет создавать надежные, стабильные тесты, даже когда iframe загружает сложный динамический контент.