问题
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 containing all elements the page object needs to interact with is initialized in this way:
@FindBy (xpath = "//div[contains(@class,'yui3-accordion-panel-content') and child::div[.='Sidebar']]")
WebElement sidebar;
I then want the search input relative to this sidebar
element. Is there a way to do this referencing sidebar
element? I could copy and paste the entire path to the beginning:
@FindBy (xpath = "//div[contains(@class,'yui3-accordion-panel-content') and child::div[.='Sidebar']]//input[@id='search']")
But I'd much rather make it relative to the first element. Is anything like this possible?
@FindBy (parent = "sidebar", xpath = ".//input[@id='search']")
The Selenium documentation on the @FindBy annotation is a bit lacking...
回答1:
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;
回答2:
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"));
}
}
来源:https://stackoverflow.com/questions/24251739/selenium-webdriver-page-factory-initialization-using-paths-relative-to-other-el