1

I'm doing unit testing on a system using Selenium with a Page Object Model.

Usually I'm able to figure out a solution to such a problem in relatively short order, but this one is being rather tenacious, so I thought I should just get clarification on the root of the problem rather than write another workaround.

There is some PageObject class that has an IWebElement property with the necessary FindsBy attribute for locating a element on the page, and a method that uses said property:

public class Foo : BasePage
{
    
    ...
    
    [FindsBy(How = How.XPath, Using = "//a[@title='Edit']")]
    protected IWebElement LinkEdit { get; set; }
    
    ...
    
    public Bar ClickEdit()
    {
        WaitUntilInteractable(LinkEdit);
        LinkEdit.Click();
        
        return new Bar(driver);
    }
    
    ...
    
}

Note that this is the only reference to LinkEdit

For clarity, WaitUntilInteractable is defined in BasePage as:

    protected void WaitUntilInteractable(IWebElement webElement)
    {
        var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
        _ = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(webElement));
    }

My understanding of how the PageFactory works with Selenium is that whenever you reference a IWebElement property of a class, the IWebDriver will then find the element within the page.

This much is said on this page: https://github.com/seleniumhq/selenium/wiki/pagefactory

... every time we call a method on the WebElement, the driver will go and find it on the current page again.

Given that knowledge, I don't quite understand how I can run into StaleElementReferenceException when simply referencing one of these properties. Surely either the element cannot be found, in which case a NoSuchElementException will be thrown, or it can be found, in which case it is present on the document, and not "stale".

Perhaps I've misunderstood staleness.

Kieran Moynihan
  • 593
  • 3
  • 15

1 Answers1

0

A StaleElementException occurs when the element being reference is no longer attached to the HTML document. This can happen in amazingly small amounts of time, and generally occurs when JavaScript is updating the page. As a further frustration, the WebDriverWait object does not catch StaleElementException's and continue waiting. You must tell WebDriverWait to ignore these exceptions:

protected void WaitUntilInteractable(IWebElement webElement)
{
    var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));

    wait.IgnoreExceptionTypes(typeof(StaleElementException));

    wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(webElement));
}

Now when webElement is stale, it retries the operation until the wait object times out.

Greg Burghardt
  • 17,900
  • 9
  • 49
  • 92