我有一个响应式设计,我需要与之交互的很多项目都有2个WebElements。一个用于桌面,一个用于移动,我正在尝试使用PageFactory。以下是我现在要识别并与元素交互的内容。
//this returns 2 webelements, one for desktop and one for mobile
@FindBy(xpath = "//selector-dropdown/p")
private WebElement dropdown;
public void ClickDropdown() throws InterruptedException {
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.visibilityOf(dropdown)).click();
}
我的印象是ExpectedConditions.visibilityOf(WebElement)
会发现第一个元素可见。现在,当我在桌面上打开应用程序时,它会找到该元素(桌面是DOM中的第一个)。但是在移动设备上,它等待可见性超时,因为它等待第一个显示器被卡住了。
我的替代方法是使用@FindBy来声明每个元素两次,然后创建一个if语句来决定采用哪个路径。这项额外工作是否能使其发挥作用?
答案 0 :(得分:5)
你的假设“... ExpectedConditions.visibilityOf(WebElement)会发现第一个元素可见。”是错的!您需要将WebElement声明为List,找到所有这些,然后选择一个可见的。以下是我过去成功使用的示例:
BITMAPV5HEADER bi;
bi.bV5Size = sizeof(BITMAPV5HEADER);
bi.bV5Width = width;
bi.bV5Height = -height;
bi.bV5Planes = 1;
bi.bV5BitCount = 32;
bi.bV5Compression = BI_RGB;
bi.bV5SizeImage = 0;
bi.bV5XPelsPerMeter = 0;
bi.bV5YPelsPerMeter = 0;
bi.bV5ClrUsed = 0;
bi.bV5ClrImportant = 0;
bi.bV5AlphaMask = 0x000000FF;
bi.bV5RedMask = 0x0000FF00;
bi.bV5GreenMask = 0x00FF0000;
bi.bV5BlueMask = 0xFF000000;
bi.bV5CSType = LCS_sRGB;
bi.bV5Endpoints = CIEXYZTRIPLE();
bi.bV5GammaRed = 0;
bi.bV5GammaGreen = 0;
bi.bV5GammaBlue = 0;
bi.bV5Intent = LCS_GM_IMAGES;
bi.bV5ProfileData = 0;
bi.bV5ProfileSize = 0;
bi.bV5Reserved = 0;
*hBmp = CreateDIBitmap(hdc, (BITMAPINFOHEADER *) &bi, CBM_INIT, data, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
根据其他地方的讨论,这里是CustomExpectedConditions:
@FindBy(xpath = "//input[@ng-model='loginData.username']")
private List<WebElement> txtUsername;
public String getUsername() {
driverWait.until(CustomExpectedConditions.presenceOfAllElements(txtUsername));
for (WebElement oneUsername : txtUsername) {
if (oneUsername.isDisplayed())
return oneUsername.getAttribute("value");
}
return null;
}
public void setUsername(String username) {
driverWait.until(CustomExpectedConditions.presenceOfAllElements(txtUsername));
for (WebElement oneUsername : txtUsername) {
if (oneUsername.isDisplayed()) {
oneUsername.clear();
oneUsername.sendKeys(username);
break;
}
}
}
答案 1 :(得分:1)
将@Andersons和@SiKing答案组合成一个可以在任何地方使用的解决方案,您可以为基础类中的所有PageObjects
提供一个方法,您可能已经拥有该方法:
protected WebElement getVisibleElement(List<WebElement> elements)
{
//Need a guard clause here to ensure there are exactly two elements,
//Or make the wait check for all elements more safely. Either way,
//consider changing the method name to be clear about expectations
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(
ExpectedConditions.or(
//This should be done more safely, unless already guarded to expect 2 elements
ExpectedConditions.visibilityOf(elements.get(0))),
ExpectedConditions.visibilityOf(elements.get(1)))
)
);
for (WebElement element : elements) {
if (element.isDisplayed())
{
return element;
}
}
//Throw element not visible exception or something
}
然后在你的PageObject:
@FindBy(xpath = "//selector-dropdown/p")
private List<WebElement> dropdown;
public void ClickDropdown() throws InterruptedException {
getVisibleElement(dropdown)).click();
}
答案 2 :(得分:0)
据我所知Java
,您可以将多个条件与ExpectedConditions.and()
结合使用,如下所示:
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(
ExpectedConditions.and(
ExpectedConditions.visibilityOf(driver.findElement(By.xpath("(//selector-dropdown/p)[1]"))),
ExpectedConditions.visibilityOf(driver.findElement(By.xpath("(//selector-dropdown/p)[2]" )))
)
);
或者只是尝试
ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//selector-dropdown/p"));
等待所有与指定选择器匹配的元素变为可见
答案 3 :(得分:-1)
这是我提出的方法,也许有人可以使用完整的解决方案。这将A.等待列表中的第一个元素可见,然后B.将可见的元素指定为单个元素。等待很短,因为它不应该花费超过一秒的时间来确定哪个元素是可见的。
protected WebElement getVisibleElement(List<WebElement> elements) {
WebDriverWait wait = new WebDriverWait(driver, 1);
WebElement rE = null;
int elementsSize = elements.size();
for (int i = 0; i < elementsSize; i++) {
System.out.println("test" + i);
try {
wait.until(ExpectedConditions.or(ExpectedConditions.visibilityOf(elements.get(i))));
break;
} catch (Exception e) {
//handle exception however you like
}
}
for (WebElement element : elements) {
if (element.isDisplayed()) {
System.out.println("found and assigning to rE");
rE = element;
break;
}
}
return rE;
}