I\'m trying to write a page object in Selenium Webdriver using the page factory @FindBy
annotations. The page object is for a sidebar, and the parent WebElement
Answering my own question.
The answer is to implement an ElementLocatorFactory that allows you to provide a search context (meaning, a driver or a WebElement).
public class SearchContextElementLocatorFactory
implements ElementLocatorFactory {
private final SearchContext context;
public SearchContextElementLocatorFactory(SearchContext context) {
this.context = context;
}
@Override
public ElementLocator createLocator(Field field) {
return new DefaultElementLocator(context, field);
}
}
Then, when instantiating your page object, use this locator factory.
WebElement parent = driver.findElement(By.xpath("//div[contains(@class,'yui3-accordion-panel-content') and child::div[.='Sidebar']]"));
SearchContextElementLocatorFactory elementLocatorFactory = new SearchContextElementLocatorFactory(parent);
PageFactory.initElements(elementLocatorFactory, this);
Now your @FindBy
annotations will be relative to parent
. For example, to get the main sidebar WebElement
:
@FindBy(xpath = ".")
WebElement sideBar;
No, it is not possible this way. But you can use getter methods instead of annotation-based initialization:
public class SomePage {
@FindBy (xpath = "//div[contains(@class,'yui3-accordion-panel-content') and child::div[.='Sidebar']]")
private WebElement sidebar;
private WebElement getSomeChildElement() {
return siderbar.findElement(By.id("somechild"));
}
}