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

匆匆过客 提交于 2019-12-18 17:00:49

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!