我在旅行搜索网站上一直选择航班返回日期时遇到问题。有时候它有效,但大部分时间它都没有,而且我在这一点上很难过。我收到的错误是:Exception in thread "main" org.openqa.selenium.TimeoutException: Timed out after 20 seconds waiting for visibility of element located by By.id: ui-datepicker-div
我已经为我点击的日期元素设置了一些等待语句,但我仍然收到错误。我试图找到一个可以避免使用Thread.sleep的解决方案。任何帮助将不胜感激!
这是我的剧本:
public class DatePickerTest {
private static WebDriver driver = new FirefoxDriver();
static WebDriverWait wait = new WebDriverWait(driver, 20);
public static void main(String[] args) {
driver.get("http://lowfares.com");
selectDepartDate(2016, 5, 18);
selectReturnDate(2016, 5, 21);
}
public static void selectDepartDate(int year, int month, int day) {
month--; // replacing zero based index
Integer.toString(year);
Integer.toString(month);
Integer.toString(day);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("depart_date")));
// click on text box to open up date picker calendar
driver.findElement(By.id("depart_date")).click();
// close pop up window
String parentWindowHandler = driver.getWindowHandle();
String subWindowHandler = null;
Set<String> handles = driver.getWindowHandles();
Iterator<String> iterator = handles.iterator();
while (iterator.hasNext()) {
subWindowHandler = iterator.next();
}
driver.switchTo().window(subWindowHandler);
driver.close();
driver.switchTo().window(parentWindowHandler);
// wait for calendar interface to appear
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("ui-datepicker-div")));
// select depart date
driver.findElement(By.xpath("//td[contains(@data-month, " + month + ") and contains(@data-year, " + year + ")]//a[contains(text(), " + day + ")]")).click();
}
public static void selectReturnDate(int year, int month, int day) {
month--; // replacing zero based index
Integer.toString(year);
Integer.toString(month);
Integer.toString(day);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("return_date")));
// click on text box to open up date picker calendar
driver.findElement(By.id("return_date")).click();
// wait for calendar interface to appear
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("ui-datepicker-div")));
// select return date
driver.findElement(By.xpath("//td[contains(@data-month, " + month + ") and contains(@data-year, " + year + ")]//a[contains(text(), " + day + ")]")).click();
}
}
答案 0 :(得分:3)
我看到一些问题:
depart_date
是div,您不应该点击它,而是点击<input id="depart"
:
driver.findElement(By.id("depart")).click();
不确定弹出窗口在做什么(我没有弹出窗口)。在任何情况下,首先检查弹出窗口是否真的存在:
...
Set<String> handles = driver.getWindowHandles();
for (String windowHandle : handles) {
subWindowHandler = windowHandle;
}
if(subWindowHandler != null && !subWindowHandler.equals(parentWindowHandler) {
driver.switchTo().window(subWindowHandler);
driver.close();
driver.switchTo().window(parentWindowHandler);
}
...
如果您关闭了弹出窗口,并切换回主窗口,则需要确保日历仍处于打开状态;如果没有,重新打开它:
public void isCalendarVisible() {
try {
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("ui-datepicker-div")));
return true;
} catch (TimeOutException e) {
return false;
}
然后在
下// wait for calendar interface to appear
if(!isCalendarVisible()) {
// try to reopen calendar
driver.findElement(By.id("depart")).click();
}
整齐采摘:以下内容无效:
Integer.toString(year);
Integer.toString(month);
Integer.toString(day);
答案 1 :(得分:1)
要注意元素的可见性,请注意以下几点。
可见与存在的元素不同。如果您查找错误的子元素或实际不可见的对象的一部分,这可能会让您遇到麻烦。您可能想尝试presenceOfElementLocated(by)
或尝试可能是可见部分的其他元素。
有时(经常)同一页面上的元素具有相同的标识符。如果您使用findElement
(并且大多数事情都这样做),它只会获得它找到的第一个。如果隐藏了那一个,你可以整天等待它永远不可见。尝试使用By.cssSelector
来帮助更具体地选择对象。例如:
[class*='exampleContainer'] [id='ui-datepicker-div']
您还可以创建findDisplayedElement()
功能。这可以findElements()
并迭代它们,直到找到element.isDisplayed() = true;
答案 2 :(得分:0)
我通过Selenium的旅程注意到,有时我的明确等待,xpath
元素有问题,而driver.findElement
没有问题找到它。我也注意到,即使我试图远离使用By.cssSelector
,By.cssSelector
似乎也总是从我的明确表示修复那些讨厌的时间。所以我赞同查克。如果您的显式等待中的xpath
元素超时,请尝试使用By.cssSelector
。你可能会感到惊讶。