Jack Jason F
Jack Jason F

Reputation: 143

element is not attached to the page document

While clicking on javascript components Im getting:

org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document

One way to fix it is to stop script for some short period of time with : Thread.sleep(200);

I have my implicitlyWait set for 10 seconds, and I think there wasnt such problems with older selenium

But is there any other way to do it globally ?

driver.findElement(By.cssSelector("button.btn.btn-default")).click();
driver.findElement(By.xpath("//div[@id='content']/div/form")).click();
driver.findElement(By.linkText("Order")).click();

But in the middle of this i have to put sleep's to make it work:

    driver.findElement(By.cssSelector("button.btn.btn-default")).click(); 
Thread.sleep(200);
        driver.findElement(By.xpath("//div[@id='content']/div/form")).click(); 
Thread.sleep(200);
        driver.findElement(By.linkText("Order")).click();

Upvotes: 2

Views: 16822

Answers (4)

ekostadinov
ekostadinov

Reputation: 6950

Your problems are indicator that you need to construct the test cases better and/or lack of understanding of how the website you are automating works. Especially

stop script for some short period of time with : Thread.sleep(200);

is considered a really bad practice. Whatever you do don't mix implicit and explicit waits, things will start going wrong, explicit waits are the recommended solution.

Waiting for the page to be loaded won't work if (as it seems to be your case) the page is being modified by AJAX operations. Instead of waiting for the page to load, wait for the condition you are testing to become true. This way, you give the AJAX operation time to execute and if your there is a problem you will get an error when the time out occurs.

StaleElementReferenceException is caused by the DOM being refreshed after you found an element. Remember that a WebElement is a reference to a specific element on the page, if the DOM get's refreshed this reference is broken and you need to find the element again to be able to interact with it.

Upvotes: 4

Thanh Le
Thanh Le

Reputation: 1

Error "element is not attached to the page document" display when the element is not exist in current page anymore. It happen because you got element for page 1, and used it in page 1 (or the page was refresh after getting the element, HTML was change by AJAX)

Upvotes: 0

Würgspaß
Würgspaß

Reputation: 4820

In order to avoid that, you should locate the element again. After you aquired the element, the reference of its Java object might become stale. Do something like: WebElement element = WebDriver.findElement(By by) again.

EDIT: For your example try this

driver.findElement(By.cssSelector("button.btn.btn-default")).click(); 
//30s timeout, use timeout not sleep
WebDriverWait wait = new WebDriverWait(driver, 30); 
By xpath = By.xpath("//div[@id='content']/div/form")
//wait for element to be clickable, then click
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(xpath));
element.click(); 

Upvotes: 2

Anuj Kumar
Anuj Kumar

Reputation: 163

In my example replace getWebDriver() with your drive instance.

The best practice is to first assert & verify that, that particular element is present or not. if you see function assertAndVerifyElement() --- it continuously checks for element for 5 secs and then assert it accordingly.

package com.stackoverflow;

import org.openqa.selenium.By;
import org.testng.Assert;
import org.testng.annotations.Test;

import com.services.Init;

public class Issue3 extends Init {

    @Test
    public void solutionOfIssue() throws InterruptedException {

        /*
         * The best thing is to first assert & verify that, that particular
         * element is present or not. if you see function
         * assertAndVerifyElement() --- it continuously checks for element for 5
         * secs and then assert it accordingly.
         */

        assertAndVerifyElement(By.cssSelector("button.btn.btn-default"));
        getWebDriver().findElement(By.cssSelector("button.btn.btn-default")).click();

        assertAndVerifyElement(By.xpath("//div[@id='content']/div/form"));
        getWebDriver().findElement(By.xpath("//div[@id='content']/div/form")).click();

        assertAndVerifyElement(By.linkText("Order"));
        getWebDriver().findElement(By.linkText("Order")).click();

    }

    public void assertAndVerifyElement(By element) throws InterruptedException {
        boolean isPresent = false;

        for (int i = 0; i < 5; i++) {
            try {
                if (getWebDriver().findElement(element) != null) {
                    isPresent = true;
                    break;
                }
            } catch (Exception e) {
                // System.out.println(e.getLocalizedMessage());
                Thread.sleep(1000);
            }
        }
        Assert.assertTrue(isPresent, "\"" + element + "\" is not present.");
    }

}

Hope this will work for you. :)

Upvotes: 2

Related Questions