javaseleniumgenericsselenium-webdriverautotest

Generic fields initialization in Selenium


I am describing a grid or table view using Selenium. What I want to do is to develop an abstract class Table from which another classes will inherit. Here is the idea:

AbstractTable class:

public abstract class AbstractTable extends HtmlElement {
    public abstract Class<? extends AbstractRow> getHeader();
    public abstract Class<? extends AbstractRow> getRow();

    private Class<? extends AbstractRow> tableHeader = getHeader();
    private Class<? extends AbstractRow> tableRow = getRow();

    public AbstractTable() { // init method }
}

AbstractRow class:

@FindBy(xpath = ".//thead/tr")
public abstract class AbstractRow extends HtmlElement {

    @Override
    public Rectange getRect() { return null; }
}

MyTable class:

class MyTable extends AbstractTable {

    @Override
    public Class<? extends AbstractRow> getHeader() { return TableHead.class; }
    @Override
    public Class<? extends AbstractRow> getRow() { return TableRow.class; }

    @FindBy(xpath = ".//thead/tr")
    public static class TableHead extends AbstractRow { // some fields }

    @FindBy(xpath = ".//tbody/tr[not(@class = 'clicked')]")
    public static class TableRow extends AbstractRow { // some fields }
}

Imagine that there are more than one class which is similar to MyTable.

So, my main question is: will my inner classes of class MyTable be decorated and initialized? Or, if not, then maybe there is a way to do this more efficient?


Solution

  • I tried to do something similar in the past. However, it was much more simple.

    Here is code snippet:

    public class Table extends AbstractPageElement {
    
        public Table(WebElement wrappedElement, String name, String page) {
            super(wrappedElement, name, page);
        }
    
        public static final String ROW_XPATH_LOCATOR = "//tbody/tr";
    
        private static String getCellXpathLocator(int row, int column) {
            return ROW_XPATH_LOCATOR + "[" + row + "]/td[" + column + "]";
        }
    
        public int getRowCount() {
            return findAllByXPath(ROW_XPATH_LOCATOR).size();
        }
    
        public String getCellValue(int row, int column) {
            Cell cell = new Cell(row, column, this.name, this.page);
            return cell.getText();
        }
    
    
        public class Cell extends AbstractPageElement {
            private int row;
            private int column;
    
            public Cell(WebElement wrappedElement, String name, String page) {
                super(wrappedElement, name, page);
            }
    
            public Cell(int row, int column, String name, String page) {
                super(Table.this.findByXPath(getCellXpathLocator(row, column)), name, page);
                this.row = row;
                this.column = column;
            }
    
            public String getText() {
                return wrappedElement.getText();
            }
    
            public Cell nextInRow() {
                return new Cell(row, column + 1, name, page);
            }
    
            public Cell previousInRow() {
                return new Cell(row, column - 1, name, page);
            }
    
            public Cell nextInColumn() {
                return new Cell(row + 1, column, name, page);
            }
    
            public Cell previousInColumn() {
                return new Cell(row - 1, column, name, page);
            }
        }
    }
    

    AbstractPageElement was used with default implementation for FieldDecorator.
    Project structure was like:

    enter image description here

    Also, you can have a look to yandex-qatools htmlelements. They created custom decorator and wrapper classes for elements.

    BTW: they have implementation for Table