问题
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