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!
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);
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);
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