Работа с элементами внутри iframe

Пример 10

Фреймворк также включает вспомогательные способы взаимодействия с браузером и его интерфейсом. Иногда приходится сталкиваться с поиском элементов iframe, что не всегда является приятным занятием. Изначально я хотел реализовать автоматическое переключение драйвера на нужный iframe при обращении к элементу внутри него, но эта идея оказалась нестабильной и требовала тщательного тестирования. Поэтому я решил пойти другим, менее удобным, но полностью стабильным путём.

Для работы с любым iframe используется класс Iframe – фактически его можно считать виджетом. Однако в отличие от простого виджета он обязан иметь корневой элемент, то есть локатор конкретного тега iframe. Поэтому при создании экземпляра необходимо передать аргументом локатор либо Selenide-элемент, аналогично объектам виджетов.

Рассмотрим пример. Ниже приведена интерактивная страница с формой и с формой внутри тега iframe:



Вариант на обычном Selenide

1. Описываем Page Object

@Getter
@Accessors(fluent = true)
public class IframePage {

    protected SelenideElement fieldName = $("#name").as("Name field");
    protected SelenideElement fieldEmail = $("#email").as("Email field");
    protected SelenideElement fieldPassword = $("#password").as("Password field");
    protected SelenideElement btnSubmit = $("#submit-main").as("Submit button");

    protected IframeLoginForm iframeLoginForm = new IframeLoginForm();

    @Getter
    @Accessors(fluent = true)
    public static class IframeLoginForm {
        protected SelenideElement fieldName = $("#name_iframe").as("Name field");
        protected SelenideElement fieldEmail = $("#email_iframe").as("Email field");
        protected SelenideElement fieldPassword = $("#password_iframe").as("Password field");
        protected SelenideElement btnSubmit = $("#submit-iframe").as("Submit button");
    }
}

2. Создаём сценарий

@Test
@DisplayName("Working with elements in an Iframe")
public void iframeExample() {
    Selenide.open(iframePageUrl);
    iframePage.fieldName().sendKeys("John");
    iframePage.fieldEmail().sendKeys("john.doe@email.com");
    iframePage.fieldPassword().sendKeys("hardAndLong");
    WebDriverRunner.getWebDriver().switchTo().frame($("#iframe_root"));
    iframePage.iframeLoginForm().fieldName().sendKeys("framed-John");
    iframePage.iframeLoginForm().fieldEmail().sendKeys("framed-doe@email.com");
    iframePage.iframeLoginForm().fieldPassword().sendKeys("framed_hardAndLong");
    WebDriverRunner.getWebDriver().switchTo().defaultContent();
    iframePage.fieldName().clear();
    iframePage.fieldName().sendKeys("JDoe");
}


Смотрим отчёт:

Отчёт Selenide: Iframe

Вариант на Allurium

1. Описываем Page Object

    
@PageObject
@Getter
@Accessors(fluent = true)
public class IframePage extends Page {

    @Name("Name")
    protected TextField fieldName = $textField("#name");

    @Name("Email")
    protected TextField fieldEmail = $textField("#email");

    @Name("Password")
    protected TextField fieldPassword = $textField("#password");

    @Name("Submit")
    protected Button btnSubmit = $button("#submit-main");

    @Name("Login form of iframe")
    protected IframeLoginForm iframeLoginForm = new IframeLoginForm("#iframe_root");

    @Widget
    @Getter
    @Accessors(fluent = true)
    public static class IframeLoginForm extends Iframe {
        public IframeLoginForm(String selenideLocator) {
            super(selenideLocator);
        }

        @Name("Name")
        protected TextField fieldName = $textField("#name_iframe");

        @Name("Email")
        protected TextField fieldEmail = $textField("#email_iframe");

        @Name("Password")
        protected TextField fieldPassword = $textField("#password_iframe");

        @Name("Submit")
        protected Button btnSubmit = $button("#submit-iframe");
    }
}

2. Создаём сценарий

@Test
@DisplayName("Using 'Iframe' class to easily work with iframe elements")
public void iframeExample() {
    UiSteps.openBrowser(iframePageUrl);
    iframePage.fieldName().write("John");
    iframePage.fieldEmail().write("john.doe@email.com");
    iframePage.fieldPassword().write("hardAndLong");
    iframePage.btnSubmit().click();
    iframePage.iframeLoginForm().switchDriverToIframe();
    iframePage.iframeLoginForm().fieldName().write("framed-John");
    iframePage.iframeLoginForm().fieldEmail().write("framed-doe@email.com");
    iframePage.iframeLoginForm().fieldPassword().write("framed_hardAndLong");
    iframePage.iframeLoginForm().switchDriverBack();
    iframePage.fieldName().clearAndWrite("JDoe");
}

Каждый объект, наследуемый от класса Iframe, имеет два дополнительных метода: .switchDriverToIframe() для переключения драйвера в данный iframe и .switchDriverBack() для возврата в главное окно. К iframe-ам можно применять те же аннотации для построения относительных путей, что делает работу с ними удобной.


Смотрим отчёт:

Отчёт Allurium: Iframe