P粉8999507202023-08-22 15:30:51
I once had this problem, but unbeknownst to me, BackboneJS was running on the page and it replaced the element I was trying to click on. My code is as follows.
driver.findElement(By.id("checkoutLink")).click();
This is of course functionally the same as the code below.
WebElement checkoutLink = driver.findElement(By.id("checkoutLink")); checkoutLink.click();
What occasionally happens is that between the find and the click, javascript replaces the checkoutLink element, ie.
WebElement checkoutLink = driver.findElement(By.id("checkoutLink")); // javascript替换了checkoutLink checkoutLink.click();
This results in a StaleElementReferenceException exception when trying to click on the link. I couldn't find any reliable way to tell WebDriver to wait for the javascript to finish running, so this is how I ended up solving it.
new WebDriverWait(driver, timeout) .ignoring(StaleElementReferenceException.class) .until(new Predicate<WebDriver>() { @Override public boolean apply(@Nullable WebDriver driver) { driver.findElement(By.id("checkoutLink")).click(); return true; } });
This code will continue to try to click the link, ignoring the StaleElementReferenceException exception, until the click is successful or the timeout is reached. I like this solution because it takes away the hassle of writing retry logic and only uses WebDriver's built-in constructs.
P粉3431416332023-08-22 13:04:24
This can occur if DOM operations taking place on the page temporarily render the element inaccessible. To deal with these situations, you can try to access the element multiple times in a loop until finally an exception is thrown.
Try using this excellent solution from darrelgrainger.blogspot.com:
public boolean retryingFindClick(By by) { boolean result = false; int attempts = 0; while(attempts < 2) { try { driver.findElement(by).click(); result = true; break; } catch(StaleElementException e) { } attempts++; } return result; }