如何在尝试从日期选择器中选择日期时修复“陈旧元素引用异常”?

问题描述 投票:5回答:4

我试图从Datepicker中选择日期。以下是代码

WebDriver d=new FirefoxDriver();
Actions a=new Actions(d);
String date="14";
d.get("http://www.eyecon.ro/bootstrap-datepicker/");
d.findElement(By.cssSelector("div#dp3>span")).click();
List<WebElement> trs=d.findElements(By.cssSelector("div.datepicker-days>table>tbody>tr"));
       for(WebElement tr:trs) {
            List<WebElement> tds=tr.findElements(By.tagName("td"));
            for(WebElement td:tds) {
                if(date.equals(td.getText())) {
                    a.moveToElement(td).click().build().perform();

                }
            }

}

使用上面的代码,我在这行代码中得到了陈旧的元素引用异常

"if(date.equals(td.getText())) {"

所以我已将代码更改为此

for(WebElement td:tds) {
                while(i<4) {
                    try {
                        if(date.equals(td.getText())) {
                            a.moveToElement(td).click().build().perform();

                        }
                        break;
                    }catch(Exception ex) {

                    }
                    System.out.println(i);
                    i++;
                }
            }

现在我可以选择日期。但是脚本仍然抛出过时的元素引用异常。脚本现在在此行显示错误

List<WebElement> tds=tr.findElements(By.tagName("td"));

我正在研究过去3天。关于如何解决这个问题的任何建议。提前致谢

selenium selenium-webdriver webdriver
4个回答
4
投票

在您的第一个代码中,在您单击该元素之后,DOM发生了更改,就像Date变为“14”一样,并且因为for循环仍然在迭代,因此它抛出了StaleElementReferenceException。

类似地,在第二个代码中,你确实打破了迭代td元素的“内部for循环”,但你没有打破“外部”,继续迭代tr元素,因此它再次抛出StaleElementReferenceException 。

解决方案: - 在单击元素后,您应该使用break从两个for循环中退出,从而避免在此过程中使用StaleElementReferenceException。

下面的代码显示了如何在没有任何异常的情况下打破两个for循环:

    WebDriver d=new FirefoxDriver();
    d.manage().window().maximize(); //Maximizing window
    d.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); //Implicit wait for 20 seconds

    Actions a=new Actions(d);
    String date="14";
    int flag=0;

    d.get("http://www.eyecon.ro/bootstrap-datepicker/");
    d.findElement(By.cssSelector("div#dp3>span")).click();
    List<WebElement> trs=d.findElements(By.cssSelector("div.datepicker-days>table>tbody>tr"));
    for(WebElement tr:trs) {
        List<WebElement> tds=tr.findElements(By.tagName("td"));
        for(WebElement td:tds) {
            if(date.equals(td.getText())) {
                a.moveToElement(td).click().build().perform();
                flag=1; // Set to 1 when the required element was found and clicked.
                break; //To come out of the first for-loop
            }
        }
        if(flag==1)
            break; //Since the element was found, come out of the second for-loop.
    }

注意: - 我已经添加了用于最大化窗口和提供隐式等待的代码,这实际上是在编写selenium脚本时建议的。


1
投票

你应该使用WebDriverWaitExpectedConditions来解决元素的陈旧问题。下面是我测试过的代码的修改块,它的工作原理。

 driver.findElement(By.cssSelector("div#dp3>span")).click();
 WebDriverWait wait = new WebDriverWait(driver, 30);
 List<WebElement> trs = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.cssSelector("div.datepicker-days>table>tbody>tr")));
 datePicker:
 {
    for (WebElement tr : trs) {
       List<WebElement> tds = tr.findElements(By.tagName("td"));
       for (WebElement td : tds) {
                 wait.until(ExpectedConditions.not(ExpectedConditions.stalenessOf(td)));
                 if (date.equals(td.getText())) {
                        td.click();
                        break datePicker;
                 }
        }
     }
 }

有关更多信息,请在此处查看WebDriverWaitExpectedConditions


1
投票

找到了一种更简单的方法来解决我的陈旧元素参考例外。

在Java中使用Selenium2尝试下面的代码:

 public WebElement cleanAndRebuildElement(final WebElement ee) {
        WebElement e2;
        try {
            e2=ee;
            e2.isDisplayed();
            logger.info("Element is cleaned : Not Stale Anymore !");
        } catch (StaleElementReferenceException e) {
              e2=null;
              cleanAndrebuildElement(ee);

        } catch(NoSuchElementException nse) {
nse.printstacktrace(); 
          }
        return e2;
    }
}

0
投票

根据我的理解,当你执行for循环DOM中的element.click()重新加载时,这就是它显示陈旧元素异常的原因。使用以下css选择器[它将仅选择预期日期选择器中的元素,因为页面上有多个日期选择器]并在匹配日期应用中断for循环。它将选择日期14并且无异常地打破循环 -

String date="14";
d.get("http://www.eyecon.ro/bootstrap-datepicker/");
d.findElement(By.cssSelector("div#dp3>span")).click();
List<WebElement> trs=d.findElements(By.cssSelector(".datepicker.dropdown-menu:nth-of-type(4)>div.datepicker-days>table>tbody>tr>td"));
     for(WebElement td:trs) {
         if(date.equals(td.getText())) {
            td.click();
            break;
         }
     }
© www.soinside.com 2019 - 2024. All rights reserved.