Working with Elements inside an iframe

Example 10

The framework also includes helper methods for interacting with the browser and its interface. Sometimes you have to deal with finding iframe elements, which is not always a pleasant task. Initially, I wanted to implement an automatic driver switch to the required iframe when accessing an element inside it, but this idea turned out to be unstable and required thorough testing. Therefore, I decided to take another, less convenient but completely stable approach.

For working with any iframe, the Iframe class is used – essentially, it can be considered as a widget. However, unlike a simple widget, it must have a root element, i.e. a locator for the specific iframe tag. Therefore, when creating an instance, you must pass a locator or a Selenide element as an argument, similar to widget objects.

Let's consider an example. Below is an interactive page with a form and a form inside an iframe tag:



Variant using plain Selenide

1. Describing the 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. Creating the Test Scenario

@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");
}

View the Report:

Selenide Report: Iframe

Variant using Allurium

1. Describing the 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. Creating the Test Scenario

@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");
}

Every object inherited from the Iframe class has two additional methods: .switchDriverToIframe() to switch the driver to the given iframe and .switchDriverBack() to return to the main window. The same annotations can be applied to iframes for building relative paths, which makes working with them convenient.


View the Report:

Allurium Report: Iframe