[JAVA] Examine HTML elements and create Page class (using Selenide)

Introduction

Building an E2E test environment with Selenium (Java)

Although I built it, I'm likely to get a heavy back when asked "Do you want to make a Page class?", So I will record how to make a Page class as easily as possible. In my experience, I'm probably saying a lot: innocent:

Identify the element you want to work with (such as a CSS selector)

Explained in the Windows version. Use Chrome's developer tools.

  1. Display the screen you want to check aWS050241.JPG

  2. Press F12 to display the developer tools aWS050242.JPG

  3. Click the select button and select the element you want to operate aWS050243.JPG

  4. Right-click on the inverted HTML source and use Copy --Copy selector to copy information such as "#q". aWS050244.JPG

Try creating a Page class

The following Page class will be created by reflecting the elements examined earlier.

Google.java


package page;

import static com.codeborne.selenide.Selenide.*;

import org.openqa.selenium.WebDriver;

public class Google extends PageBase {

    public static final String _url = "https://www.google.co.jp/webhp";

    public Google(WebDriver webDriver) {
        super(webDriver);
    }

    private String _id_search = "#lst-ib";

    // ****************************************
    //Search page
    // ****************************************

    public Google __Search word input(String s) {
        $(_id_search).setValue(s);
        return this;
    }

    public Google __Do a search() {
        $(_id_search).submit();
        return this;
    }
}

The test is the following code.

GoogleTest.java


package test;

import org.junit.Test;

import com.htmlhifive.pitalium.core.model.ScreenshotArgument;

import page.Google;

public class GoogleTest extends TestBase {

    @Test
    public void OK() throws Exception {

        driver.get(Google._url);
        Google page = new Google(driver);

        page.__Search word input("test")
            .__Do a search();

        ScreenshotArgument arg = ScreenshotArgument.builder("result").addNewTarget().build();
        assertionView.verifyView(arg);
    }
}

Create a Page class that can handle click menus

Try adding a method that can be operated by clicking the tool after displaying the search results. How to check the elements is the same as before.

Selenium seems to operate too quickly and can cause errors like missing elements. It will be stable if you wait for the element displayed after clicking.

Google.java


package page;

import static com.codeborne.selenide.Condition.*;
import static com.codeborne.selenide.Selenide.*;

import java.util.Iterator;

import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;

import com.codeborne.selenide.SelenideElement;

public class Google extends PageBase {

    public static final String _url = "https://www.google.co.jp/webhp";

    public Google(WebDriver webDriver) {
        super(webDriver);
    }

    private String _id_search = "#lst-ib";

    // ****************************************
    //Search page
    // ****************************************

    public Google __Search word input(String s) {
        $(_id_search).setValue(s);
        return this;
    }

    public Google __Do a search() {
        $(_id_search).submit();
        return this;
    }

    // ****************************************
    //Search result page (the following is a different class)
    //Originally "__Do a search()Return the search result Page class with the method
    // ****************************************

    public Google __Click the tool() {
        $("#hdtb-tls").click();
        return this;
    }

    public Google __tool$Click the period() {
        //Check if the menu after selecting the tool is displayed
        if (!$("#hdtbMenus").isDisplayed()) {
            __Click the tool();
        }
        //Wait 60 seconds for the item displayed after selection
        $("#hdtbMenus").waitUntil(appear, 60000);

        $("#hdtbMenus > div > div:nth-child(5) > div").click();

        return this;
    }

    public Google __tool$period$Click within 1 hour() {
        return __tool$period$Click the specified character("Within one hour");
    }

    public Google __tool$period$Click within 1 year() {
        return __tool$period$Click the specified character("Within 1 year");
    }

    private Google __tool$period$Click the specified character(String text) {
        //Check if the period menu is displayed
        if (!$("#hdtbMenus > div > ul.hdtbU.hdtb-mn-o").isDisplayed()) {
            __tool$Click the period();
        }
        //Wait 60 seconds for the item displayed after selection
        $("#hdtbMenus > div > ul.hdtbU.hdtb-mn-o").waitUntil(appear, 60000);

        return matchTextClick(text, $$("#hdtbMenus > div > ul.hdtbU.hdtb-mn-o > li").iterator());
    }

    private Google matchTextClick(String text, Iterator<SelenideElement> seItr) {

        boolean ckickFlg = false;

        while (seItr.hasNext()) {
            SelenideElement se = seItr.next();
            if (text.equals(se.getText())) {
                se.click();
                ckickFlg = true;
                break;
            }
        }

        if (!ckickFlg) {
            throw new NoSuchElementException("Click error:" + text);
        }

        return this;
    }
}

The test is the following code.

GoogleTest.java


package test;

import org.junit.Test;

import com.htmlhifive.pitalium.core.model.ScreenshotArgument;

import page.Google;

public class GoogleTest extends TestBase {

    @Test
    public void OK() throws Exception {

        driver.get(Google._url);
        Google page = new Google(driver);

        page.__Search word input("test")
            .__Do a search();

        ScreenshotArgument arg = ScreenshotArgument.builder("result1").addNewTarget().build();
        assertionView.verifyView(arg);

        page.__tool$period$Click within 1 hour();
//If you can understand the screen condition perfectly, the following description is faster
//        page.__Click the tool()
//            .__tool$Click the period()
//            .__tool$period$Click within 1 hour();


        arg = ScreenshotArgument.builder("result2").addNewTarget().build();
        assertionView.verifyView(arg);

        page.__tool$period$Click within 1 year();


        arg = ScreenshotArgument.builder("result3").addNewTarget().build();
        assertionView.verifyView(arg);
    }
}

Let's create a Page class that processes screens with separate Frames

It seems that you have to switch pages with separate frames. I think it's better to cover this control with the Page class as well. (Please teach if there is a way to go without switching)

18/04/23 Changed I understand what you commented on, but I couldn't reflect it in the code due to lack of ability: scream: I wish I could write a similar description in the "__Enter in item 1" method, but I can't think of it.

FrameSample.java


package page;

import static com.codeborne.selenide.Selenide.*;

import org.openqa.selenium.WebDriver;

import com.codeborne.selenide.SelenideElement;
import com.codeborne.selenide.WebDriverRunner;

public class FrameSample extends PageBase {

    public static final String _url = "https://";

    public FrameSample(WebDriver webDriver) {
        super(webDriver);
    }

    /**Input to the element that exists in the default frame*/
    public FrameSample __Enter in item 1(String s) throws InterruptedException {
        $("#in1").setValue(s);
        return this;
    }

    /**Input to an element that exists in another frame*/
    public FrameSample __Enter in item 2(String s) throws InterruptedException {
        switcFrame($(".iframe"));
        $("#in2").setValue(s);
        switchDefaultFrame();
        return this;
    }

    /***
     *Switch to default frame
     * @throws InterruptedException
     */
    private void switchDefaultFrame() throws InterruptedException{
        //Since the processing is not stable, wait is included in the frame change for the time being
        WebDriverRunner.getWebDriver().switchTo().defaultContent();
        Thread.sleep(2000);
    }

    /***
     *Switch to another frame
     * @Element of param se frame
     * @throws InterruptedException
     */
    private void switcFrame(SelenideElement se) throws InterruptedException{
        //Since the processing is not stable, wait is included in the frame change for the time being
        WebDriverRunner.getWebDriver().switchTo().frame(se);
        Thread.sleep(2000);
    }
}

Recommended Posts

Examine HTML elements and create Page class (using Selenide)
A memo to simply create a form using only HTML and CSS in Rails 6
Create API using Retrofit2, Okhttp3 and Gson (Java)
[ruby] Create DHT11 / 22 class from scratch using datasheet