Selenium/PageFactory: Find child elements using parent element's @FindBy?

我们两清 提交于 2020-01-02 11:06:12

问题


I'm trying to convert my selenium tests to use the Page Object Model (and, by extension, @FindBy). I have several object definitions like this:

public WebElement objectParent() {
    return driver.findElement(By.name("parent-id")) ;
}

public WebElement objectChild() {
    WebElement elem = objectParent();
    return elem.findElement(By.name("child-id")) ;
}

Converting the parent object to using @FindBy is easy:

@FindBy(name = "parent-id")
WebElement parentObj;

Basically, I want to do something like this, if possible (I know this isn't real code, this is just a pseudo example:

@FindBy(name = "parent-id")
WebElement parentObj;

@FindBy(parentObj.name = "child-id")
WebElement childObj;

But is there a way too target the child element within the parent element using @FindBy?. I need to do it this way because I am targeting specific elements on the page that may share the same name or class name with other elements on the page. Thanks!


回答1:


What you are trying to do is not easily achievable without writing custom ElementLocatorFactory.

Firstly I would really recommend using XPath. This would make it easy lot to grab the:
3rd <table> just like this: @FindBy(xpath = "\\table[3]") and...
2nd <li> in the 3rd table just like this: @FindBy(xpath = "\\table[3]\li[2]").

But if you really want to do it with shorter @FindBy annotations, you can go for ElementLocatorFactory.

public class FindByContextModifier implements ElementLocatorFactory {

    private final SearchContext context;

    public FindByContextModifier(final SearchContext context) {
        this.context = context;
    }

    public ElementLocator createLocator(final Field field) {
        return new DefaultElementLocator(context, field);
    }
}

Class with an element that will provide you with the context:

public class Parent {
    @FindBy(name = "myTable")
    WebElement table;

    public WebElement getTable() {
      return this.table;
    }
}

Its child:

public class Child {
    @FindBy(name = "particular")
    WebElement specialTableListElement;
}

Usage:

Parent parent = PageFactory.initElements(driver, Parent.class);
FindByContextModifier parentContext = new FindByContextModifier(parent.getTable());
Child child = new Child();
// This will look for the name "particular" inside the element with "myTable" name
PageFactory.initElements(parentContext, child);



回答2:


You do not need to write a custom ElemLocatorFactory, just use org.openqa.selenium.support.pagefactory.DefaultElementLocatorFactory instead:

Parent parent = PageFactory.initElements(driver, Parent.class);
DefaultElementLocatorFactory parentContext = new DefaultElementLocatorFactory(parent.getTable());
Child child = new Child();
PageFactory.initElements(parentContext, child);



回答3:


The approach mentioned above works, but if you're using xpath, make sure that your 'child' element has a .// in front to make it relative.



来源:https://stackoverflow.com/questions/42140987/selenium-pagefactory-find-child-elements-using-parent-elements-findby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!