等待元素可见性后超时

时间:2016-04-19 23:13:04

标签: java selenium selenium-webdriver

我在旅行搜索网站上一直选择航班返回日期时遇到问题。有时候它有效,但大部分时间它都没有,而且我在这一点上很难过。我收到的错误是: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();
    }
}

3 个答案:

答案 0 :(得分:3)

我看到一些问题:

  1. depart_date是div,您不应该点击它,而是点击<input id="depart"

    driver.findElement(By.id("depart")).click();
    
  2. 不确定弹出窗口在做什么(我没有弹出窗口)。在任何情况下,首先检查弹出窗口是否真的存在:

    ...
    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);
    }
    ...
    
  3. 如果您关闭了弹出窗口,并切换回主窗口,则需要确保日历仍处于打开状态;如果没有,重新打开它:

    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();
    }
    
  4. 整齐采摘:以下内容无效:

    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.cssSelectorBy.cssSelector似乎也总是从我的明确表示修复那些讨厌的时间。所以我赞同查克。如果您的显式等待中的xpath元素超时,请尝试使用By.cssSelector。你可能会感到惊讶。