我有用c#编写的selenium项目,我想将它迁移到java,但我有一个问题,我自己无法解决。
假设我有一个webElement elem1
,我希望找到另一个使用elem2
作为锚点的元素elem1
。
所以在java中,我可以这样做:
WebElement elem1 = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("div.uiContextualLayer.uiContextualLayerBelowLeft"))) ;
WebElement elem2 = elem1.findElement(By.tagName("li"));
现在,我的问题开始时我想要同样但wait.until()
elem2
。问题是elem1
总是出现在DOM中,但elem2
只会在一段时间后出现在DOM中(它取决于与此问题无关的一些代码),所以使用上面的代码将抛出异常。
在c#中我使用了lambda表达式,它非常简单:
IWebElement elem1 = wait.Until((d) => { return d.FindElement(By.CssSelector("div.uiContextualLayer.uiContextualLayerBelowLeft")); });
IWebElement elem2= wait.Until((d) => { return **elem1**.FindElement(By.TagName("li")); });
在java中我无法找到一种方法来wait.until
并使用elem1
作为findElement
函数的锚点。
这是我正在处理的html示例:
<div class="uiContextualLayer uiContextualLayerBelowLeft">
<div style="width: 240px;">
<div class="uiTypeaheadView uiContextualTypeaheadView">
<ul id="typeahead_list_u_jsonp_2_2" class="search" role="listbox">
<li id="js_2" class="user" aria-label="whatEver" role="option" aria-selected="false">
<a href="someLink" rel="ignore" target=""> … </a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
我不希望将所有具有“li”tagName的元素放入列表中,而是遍历每个元素以找到我需要的元素。我很确定我错过了一些非常基本的东西,并且会感谢任何建议/解释。
答案 0 :(得分:0)
最Java风格的方法是使用返回定位器的方法并编写使用这些方法的内联ExpectedCondition
。
public By getElem1Locator() {
return By.cssSelector(....);
}
public By getElem2Locator() {
return By.tagName(....);
}
...
WebElement elem2 = wait.until(new ExpectedCondition<WebElement>() {
public WebElement apply(WebDriver driver) {
try {
return driver.findElement(getElem1Locator()).findElement(getElem2Locator());
} catch (NoSuchElementException e) {
return null;
}
});
...
我们想要使用定位器而不是最终WebElement
实例的原因是,如果在我们等待时DOM发生变化,WebElement
可能会变得陈旧。
快速而肮脏的解决方案是为第二个元素使用单个Xpath选择器
WebElement elem2 = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//div[contains(concat(' ',normalize-space(@class),' '),' uiContextualLayer ') and contains(concat(' ',normalize-space(@class),' '),' uiContextualLayerBelowLeft ')]//li"));
您还应该查看Page Factory