我正在尝试从 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天。关于如何解决这个问题的任何建议。 提前致谢
答案 0 :(得分:4)
在您的第一个代码中,点击元素后,DOM发生了变化,就像日期变为 &#34; 14&#34; 一样,自从for-loop仍然在迭代,因此它抛出了 StaleElementReferenceException 。
同样,在第二个代码中,您确实打破了&#34;内部for循环&#34; ,它正在迭代 td 元素,但你没有打破&#34; outside&#34; 之一,继续迭代 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 :(得分:1)
您应该使用WebDriverWait
和ExpectedConditions
来解决元素的陈旧问题。下面是我测试过的代码的修改块,它可以工作。
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;
}
}
}
}
有关详细信息,请在此处查看WebDriverWait和ExpectedConditions
答案 2 :(得分: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;
}
}
答案 3 :(得分:0)
根据我的理解,当你执行for循环DOM中的element.click()重新加载时,这就是它显示陈旧元素异常的原因。 使用以下css选择器[它将仅从预期日期选择器中选择元素,因为页面上有多个日期选择器,因此使用此选项]&amp;在匹配日期中应用break for for循环,如下所示。它将选择日期14&amp;毫无例外地打破循环 -
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;
}
}