Selenium Webdriver: Page factory initialization using paths relative to other elements?

I am trying to write a page object in Selenium Webdriver using factory @FindBy annotations. The page object is intended for the sidebar, and the parent WebElement, containing all the elements with which the page object should interact, is initialized as follows:

 @FindBy (xpath = "//div[contains(@class,'yui3-accordion-panel-content') and child::div[.='Sidebar']]") WebElement sidebar; 

Then I want the search input to relate to this sidebar element. Is there a way to do this by referencing the sidebar element? I could copy and paste all the way to the beginning:

 @FindBy (xpath = "//div[contains(@class,'yui3-accordion-panel-content') and child::div[.='Sidebar']]//input[@id='search']") 

But I would rather make it relative to the first element. Is this possible?

 @FindBy (parent = "sidebar", xpath = ".//input[@id='search']") 

Selenium's documentation on @FindBy annotation is a bit missing ...

+6
source share
2 answers

Answering my own question.

The answer is to implement an ElementLocatorFactory that allows you to provide a search context (value, driver, or 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 the page object, use this factory locator.

 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 refer to parent . For example, to get the main WebElement :

 @FindBy(xpath = ".") WebElement sideBar; 
+10
source

No, It is Immpossible. 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")); } } 
0
source

Source: https://habr.com/ru/post/970907/


All Articles