web-dev-qa-db-fra.com

référence d'élément périmé: l'élément n'est pas attaché au document de la page

J'ai la liste qui a plusieurs liens sous chaque section. Chaque section a les mêmes liens Je dois cliquer sur un lien particulier sous chaque section. J'ai écrit le code ci-dessous mais quand il s'exécute, il me donne l'erreur stale element reference: element is not attached to the page document.

Ceci est mon code:

public static void main(String[] args) throws InterruptedException 
{
    WebDriver driver = new ChromeDriver();
    driver.navigate().to("url......");
        driver.findElement(By.id("Login1_txtEmailID")).sendKeys("[email protected]");
    driver.findElement(By.id("Login1_txtPassword")).sendKeys("Testing1*");
    driver.findElement(By.id("Login1_btnLogin")).click();
    List<WebElement> LeftNavLinks=driver.findElements(By.xpath("//*[@id='sliding-navigation']//a"));
    Thread.sleep(1000);
    String ben="Benefit Status";
    String[] linkTexts = new String[LeftNavLinks.size()];
    int i = 0;
    for (WebElement e : LeftNavLinks) 
    {   
        linkTexts[i] = e.getText();
        System.out.print(i+" " + linkTexts[i]+"\n");
        if(linkTexts[i].equals(ben))
        {
            String BenefitStatLi="//*[@id='sliding-navigation']/li[%s]/a";
            System.out.print(i+" " + linkTexts[i]+"\n");
                driver.findElement(By.xpath(String.format(BenefitStatLi,i))).click();
            driver.findElement(By.xpath("//* [@id='divContentHolder']/div[1]/a[1]")).click();
        }
        i++;
    }
}

}

Ceci est la structure HTML est comme ci-dessous

<div id="ucAdminMenu_divMenu">
  <ul id="sliding-navigation">
    <li class="sliding-element">
      <a href=" ">Claims Status</a>
    </li>
    <li class="sliding-element">
      <a href=" ">Eligibility Status</a>
    </li>
    <li class="sliding-element">
      <h3>Section-1</h3>
    </li>
    <li class="sliding-element">
      <a href=" ">Forms and Documents</a>
    </li>
    <li class="sliding-element">
      <a href=" HourBank.aspx?id=002">Hour Bank</a>
    </li>
    <li class="sliding-element">
      <h3>Section-2</h3>
    </li>
    <li class="sliding-element">
      <a href=" ">Benefit Status</a>
    </li>
    <li class="sliding-element">
      <a href=" ">Forms and Documents</a>
    </li>
    <li class="sliding-element">
      <h3>Section-3</h3>
    </li>
    <li class="sliding-element">
      <a href=" ">Forms and Documents</a>
    </li>
    <li class="sliding-element">
      <h3>Testing Fund</h3>
    </li>
    <li class="sliding-element">
      <a href=" ">Benefit Status</a>
    </li>
    <li class="sliding-element">
      <a href=" ">Order ID Card</a>
    </li>
  </ul>
</div>

La trace d'erreur est: 

    Exception in thread "main" 
org.openqa.Selenium.StaleElementReferenceException: stale element 
reference: element is not attached to the page document
40
Patil Prashanth

Quelle est la ligne qui donne exception ??

La raison en est que l'élément auquel vous avez fait référence est supprimé de la structure DOM

Je faisais face au même problème lorsque je travaillais avec IEDriver. La raison était parce que javascript a chargé l'élément une fois de plus après que je me suis référé de sorte que ma référence de date pointait vers un objet non existant même s'il était juste sur leur interface utilisateur. J'ai utilisé la solution de contournement suivante.

try {
    WebElement date = driver.findElement(By.linkText(Utility.getSheetData(path, 7, 1, 2)));
    date.click();
}
catch(org.openqa.Selenium.StaleElementReferenceException ex)
{
    WebElement date = driver.findElement(By.linkText(Utility.getSheetData(path, 7, 1, 2)));
    date.click();
}

Voyez si la même chose peut vous aider!

46
Abhishek Singh

Pour le gérer, j'utilise la méthode de clic suivante . Cela tentera de trouver et de cliquer sur l'élément. Si le DOM change entre la recherche et le clic, il essaiera à nouveau. L'idée est que si cela échoue et que j'essaie de nouveau immédiatement, la deuxième tentative réussira. Si les modifications du DOM sont très rapides, cela ne fonctionnera pas.

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;
}
5
Alisha Raju

Chaque fois que vous faites face à ce problème, définissez une fois encore l'élément Web au-dessus de la ligne dans laquelle se produit une erreur, Ex: -

WebElement button = driver.findElement(By.xpath("xpath"));

button.click();

// ici vous faites quelque chose comme mettre à jour ou sauvegarder 

// vous utilisez à nouveau le bouton WebElement pour cliquer 

button.click();

Solution:-

WebElement button = driver.findElement(By.xpath("xpath"));
button.click();

// ici vous faites quelque chose comme mettre à jour ou sauvegarder 

// encore une fois vous définissez l'élément de bouton avant d'utiliser

WebElement button1 = driver.findElement(By.xpath("xpath"));
button1.click();

// afin que le nouvel élément pointe vers le même élément dans le nouveau DOM 

4
rohit goudar

Ces erreurs ont deux causes communes: L'élément a été entièrement supprimé ou l'élément n'est plus attaché au DOM.

Si vous avez déjà vérifié si ce n'est pas votre cas, vous pourriez être confronté au même problème que moi.

L'élément dans le DOM est introuvable car votre page n'est pas entièrement chargée lorsque Selenium recherche l'élément. Pour résoudre ce problème, vous pouvez définir une condition d’attente explicite qui indique à Selenium d’attendre que l’élément soit accessible.

from Selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))

Voir: https://Selenium-python.readthedocs.io/waits.html

2
Bruno Sanches

Le problème ici est que vous utilisez une boucle for en dehors de votre instruction conditionnelle.

Une fois que les conditions de votre instruction IF sont remplies, vous accédez probablement à une autre page. Ainsi, lorsque la boucle for tente de répéter une nouvelle tentative, vous obtenez l'erreur de l'élément obsolète, car vous êtes sur une autre page.

Vous pouvez ajouter un break à la fin de votre déclaration if, cela a fonctionné pour moi.

2
Adrian Coroi

Utilisez ce code:

public class LinkTest 
{   
    public static void main(String[] args) 
    {
        WebDriver driver = new FirefoxDriver();
        driver.navigate().to("file:///C:/Users/vkiran/Desktop/xyz.html");
        List<WebElement> alllinks =driver.findElements(By.xpath("//*[@id='sliding-navigation']//a"));
        String a[]=new String[alllinks.size()];
        for(int i=0;i<alllinks.size();i++)
        {
            a[i]=alllinks.get(i).getText(); 
            if(a[i].startsWith("B"))
            {
                System.out.println("clicking on this link::"+driver.findElement(By.linkText(a[i])).getText());
                driver.findElement(By.linkText(a[i])).click();  

            }
            else
            {
                System.out.println("does not starts with B so not clicking");
            }
        }
}
}
2
kiran

Il suffit de rompre la boucle lorsque vous trouvez l'élément sur lequel vous souhaitez cliquer .. .. par exemple:

  List<WebElement> buttons = getButtonElements();
    for (WebElement b : buttons) {
        if (b.getText().equals("Next"){
            b.click();
            break;
        }
1
try {
    WebElement button = driver.findElement(By.xpath("xpath"));
            button.click();
}
catch(org.openqa.Selenium.StaleElementReferenceException ex)
{
    WebElement button = driver.findElement(By.xpath("xpath"));
            button.click();
}

Ce code try/catch a réellement fonctionné pour moi. J'ai la même erreur d'élément périmé.

1
Charan Raz

Cela pourrait être fait dans les nouvelles versions de Selenium dans JS (mais toutes les opérations supportant stalenessOf fonctionneront): 

 const { until } = require('Selenium-webdriver');
 driver.wait(
        until.stalenessOf(
          driver.findElement(
            By.css(SQLQueriesByPhpMyAdminSelectors.sqlQueryArea)
          )
        ),
        5 * 1000
      )
      .then( driver.findElement(By.css(SQLQueriesByPhpMyAdminSelectors.sqlQueryArea))
      .sendKeys(sqlString)
  );
0
SkorpEN