Extend Selenium WebDriver WebElement?

2022-09-04 05:56:54

我正在遵循Selenium建议的页面对象模式,但是我如何为页面创建更专业的WebElement。具体来说,我们的页面上有表格,我编写了一些帮助程序函数来获取表格的特定行,返回表格的内容等。

目前,以下是我创建的具有表的页面对象的代码段:

public class PermissionsPage  {

    @FindBy(id = "studyPermissionsTable")
    private WebElement permissionTable;

    @FindBy(id = "studyPermissionAddPermission")
    private WebElement addPermissionButton;

    ... 

}

所以,我想做的是拥有该权限表,使其成为一个更自定义的WebElement,其中包含我之前提到的一些方法。

例如:

public class TableWebElement extends WebElement {
    WebElement table;
    // a WebDriver needs to come into play here too I think

    public List<Map<String, String>> getTableData() {
        // code to do this
    }

    public int getTableSize() {
        // code to do this
    }

    public WebElement getElementFromTable(String id) {
        // code to do this
    }
}

我希望这是有道理的,我试图解释的。我想我正在寻找的是一种方法,让这个自定义的WebElement做一些特定于表的额外事情。将此自定义元素添加到页面,并利用Selenium根据注释将webelements连接到页面的方式。

可能吗?如果是这样,有谁知道这是怎么做到的?


答案 1

我创建了一个结合了所有WebDriver接口的界面:

public interface Element extends WebElement, WrapsElement, Locatable {}

它只是用来包装WebElements在包装元素时可以做的所有事情。

然后实现:

public class ElementImpl implements Element {

    private final WebElement element;

    public ElementImpl(final WebElement element) {
        this.element = element;
    }

    @Override
    public void click() {
        element.click();
    }

    @Override
    public void sendKeys(CharSequence... keysToSend) {
        element.sendKeys(keysToSend);
    }

    // And so on, delegates all the way down...

}

然后,例如一个复选框:

public class CheckBox extends ElementImpl {

    public CheckBox(WebElement element) {
        super(element);
    }

    public void toggle() {
        getWrappedElement().click();
    }

    public void check() {
        if (!isChecked()) {
            toggle();
        }
    }

    public void uncheck() {
        if (isChecked()) {
            toggle();
        }
    }

    public boolean isChecked() {
        return getWrappedElement().isSelected();
    }
}

在我的脚本中使用它时:

CheckBox cb = new CheckBox(element);
cb.uncheck();

我还想出了一种包装类的方法。您必须创建一些工厂来替换 内置的 ,但这是可行的,并且它提供了很大的灵活性。ElementPageFactory

我已经在我的网站上记录了这个过程:

我还有一个名为selophane的项目,它受到这个问题和其他问题的启发:selophane。


答案 2

您可以使用 WebDriver Extensions 框架创建自定义 WebElements,该框架提供实现 WebElement 接口的 WebComponent 类

创建自定义 WebElement

public class Table extends WebComponent {
    @FindBy(tagName = "tr")
    List<Row> rows;

    public Row getRow(int row) {
        return rows.get(row - 1);
    }

    public int getTableSize() {
        return rows.size();
    }

    public static class Row extends WebComponent {
        @FindBy(tagName = "td")
        List<WebElement> columns;

        public WebElement getCell(int column) {
            return columns.get(column - 1);
        }
    }
}

...然后将其添加到带有@FindBy注释的PageObject中,并在调用PageFactory.initElements方法时使用WebDriverExtensionFieldDecorator。

public class PermissionPage {
    public PermissionPage(WebDriver driver) {
        PageFactory.initElements(new WebDriverExtensionFieldDecorator(driver), this);
    }

    @FindBy(id = "studyPermissionsTable")
    public Table permissionTable;

    @FindBy(id = "studyPermissionAddPermission")
    public WebElement addPermissionButton;
}

...然后在测试中使用它

public class PermissionPageTest {
    @Test
    public void exampleTest() {
        WebDriver driver = new FirefoxDriver();
        PermissionPage permissionPage = new PermissionPage(driver);

        driver.get("http://www.url-to-permission-page.com");
        assertEquals(25, permissionPage.permissionTable.getTableSize());
        assertEquals("READ", permissionPage.permissionTable.getRow(2).getCell(1).getText());
        assertEquals("WRITE", permissionPage.permissionTable.getRow(2).getCell(2).getText());
        assertEquals("EXECUTE", permissionPage.permissionTable.getRow(2).getCell(3).getText());
    }
}




或者更好地使用 WebDriver Extensions PageObject 实现

public class PermissionPage extends WebPage {
    @FindBy(id = "studyPermissionsTable")
    public Table permissionTable;

    @FindBy(id = "studyPermissionAddPermission")
    public WebElement addPermissionButton;

    @Override
    public void open(Object... arguments) {
        open("http://www.url-to-permission-page.com");
        assertIsOpen();
    }

    @Override
    public void assertIsOpen(Object... arguments) throws AssertionError {
        assertIsDisabled(permissionTable);
        assertIsDisabled(addPermissionButton);
    }
}

和带有 WebElements 的静态 asserts 方法的 JUnitRunner

import static com.github.webdriverextensions.Bot.*;

@RunWith(WebDriverRunner.class)
public class PermissionPageTest {

    PermissionPage permissionPage;

    @Test
    @Firefox
    public void exampleTest() {
        open(permissionPage);
        assertSizeEquals(25, permissionPage.permissionTable.rows);
        assertTextEquals("READ", permissionPage.permissionTable.getRow(2).getCell(1));
        assertTextEquals("WRITE", permissionPage.permissionTable.getRow(2).getCell(2));
        assertTextEquals("EXECUTE", permissionPage.permissionTable.getRow(2).getCell(3));
    }
}

推荐