Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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...

like image 654
kesslern Avatar asked Jun 16 '14 20:06

kesslern


People also ask

How do you write page Factory elements without FindBy and findElement?

Answer is NO. there will be an element that can be located using the xpath expression “//*[@id='submit']” or “//*[@name='submit']”. WebElement SomeId; So to use other locators like xpath, css etc, we required FindBy annotation.

Which method is used to initialize WebElements through page Factory?

In Page Factory, testers use @FindBy annotation. The initElements method is used to initialize web elements. Similarly, one can use @FindBy with different location strategies to find web elements and perform actions on them.

Why should we initialize the pages in page Factory model?

This is done to ensure that the web elements are initialized before any relevant actions are performed. One of the Selenium best practices with Page Factory is to create all the web element variables at the beginning of the class and initialize those variables when the page is loaded.

Why PageFactory is used in Selenium?

Page Factory in Selenium is an inbuilt Page Object Model framework concept for Selenium WebDriver but it is very optimized. It is used for initialization of Page objects or to instantiate the Page object itself. It is also used to initialize Page class elements without using “FindElement/s.”


1 Answers

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;
like image 83
kesslern Avatar answered Sep 28 '22 01:09

kesslern