GWT, Selenium WebDriver, and the dreaded StaleElementReferenceException

Automating GWT (Google Web Toolkit) applications with Selenium WebDriver can be challenging.  One hurdle is that as page events fire, GWT applications tend to drop existing DOM elements and replace them with new DOM elements that are identical, or very similar to, elements in the old DOM.  Consequently, even simple commands like driver.findElement(By.id("someElementId")).click() will fail sporadically with stale element reference exceptions.

The reason is that in the tiny time gap between when the WebDriver finds the element and when the WebDriver tries to click the element, GWT may drop the existing DOM element that you are trying to click and replace it with a new, identical element.  The WebDriver, which is blissfully unaware that GWT has modified the DOM in this way, tries to click on the old element (which is no longer attached to the DOM), and your test fails with a StaleElementReferenceException.

Luckily, this problem is easy enough to fix.  If you are using Selenium WebDriver on a GWT application, you probably already have built up some kind of framework with a utilities class that has static helper methods that you use often.  Drop the method shown below into this class, and replace your existing click methods with this new one.  This method will try to find and then click on the specified WebElement up to the MAX_STALE_ELEMENT_RETRIES count, after which, the exception is propagated to the calling method.  I’ve found that setting the number of retries to 5 is more than enough.

 /**
     * Attempts to click on an element multiple times (to avoid stale element
     * exceptions caused by rapid DOM refreshes)
     *
     * @param d
     *            The WebDriver
     * @param by
     *            By element locator
     */
    public static void dependableClick(WebDriver d, By by)
    {
        final int MAXIMUM_WAIT_TIME = 10;
        final int MAX_STALE_ELEMENT_RETRIES = 5;

        WebDriverWait wait = new WebDriverWait(d, MAXIMUM_WAIT_TIME);
        int retries = 0;
        while (true)
        {
            try
            {
                wait.until(ExpectedConditions.elementToBeClickable(by)).click();

                return;
            }
            catch (StaleElementReferenceException e)
            {
                if (retries < MAX_STALE_ELEMENT_RETRIES)
                {
                    retries++;
                    continue;
                }
                else
                {
                    throw e;
                }
            }
        }
    }
If you liked this post, say thanks by sharing it:

Also read...

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>