IT이야기

오래된 요소 참조: 요소가 페이지 문서에 연결되어 있지 않습니다.

cyworld 2022. 7. 3. 10:12
반응형

오래된 요소 참조: 요소가 페이지 문서에 연결되어 있지 않습니다.

각 섹션 아래에 여러 링크가 있는 목록이 있습니다.각 섹션에는 동일한 링크가 있으며 각 섹션 아래의 특정 링크를 클릭해야 합니다.만, 이 되면, 이 에게 주어집니다.stale element reference: element is not attached to the page document

코드는 다음과 같습니다.

public static void main(String[] args) throws InterruptedException 
{
    WebDriver driver = new ChromeDriver();
    driver.navigate().to("url......");
        driver.findElement(By.id("Login1_txtEmailID")).sendKeys("hourbank5@....com");
    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++;
    }
}

}

HTML 구조는 다음과 같습니다.

<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>

에러 트레이스는 다음과 같습니다.

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

예외를 두는 행은 무엇입니까?

그 이유는 참조한 요소가 DOM 구조에서 삭제되었기 때문입니다.

나는 IEDriver와 함께 일하는 동안 같은 문제에 직면해 있었다.그 이유는 javascript가 제가 참조한 후에 다시 한 번 요소를 로드했기 때문에 날짜 참조는 UI에 존재하지 않는 오브젝트를 가리키고 있었기 때문입니다.다음의 회피책을 사용했습니다.

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();
}

같은 방법으로 도움이 되는지 확인해 보세요!

이 문제가 발생할 때마다 오류가 발생하는 행 위에 웹 요소를 다시 정의하십시오.

예:

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

//here you do something like update or save 

//then you try to use the button WebElement again to click 
button.click();

업데이트액션을에 DOM이 됩니다.StaleElementReference

솔루션:

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

//here you do something like update or save 

//then you define the button element again before you use it
WebElement button1 = driver.findElement(By.xpath("xpath"));
//that new element will point to the same element in the new DOM
button1.click();

이 에러는, 다음의 2개의 일반적인 원인이 있습니다.요소가 완전히 삭제되었거나 요소가 더 이상 DOM에 연결되어 있지 않습니다.

만약 당신이 이미 당신의 경우가 아닌지를 확인했다면, 당신은 나와 같은 문제에 직면할 수 있습니다.

Selenium에서 요소를 검색할 때 페이지가 완전히 로드되지 않았기 때문에 DOM에서 요소를 찾을 수 없습니다.이 문제를 해결하려면 요소를 클릭할 수 있을 때까지 Selenium에게 대기하도록 지시하는 명시적 대기 조건을 설정할 수 있습니다.

from selenium.webdriver.support import expected_conditions as EC

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

참조: https://selenium-python.readthedocs.io/waits.html

자바어

import org.openqa.selenium.support.ui.ExpectedConditions;

WebDriverWait wait = new WebDriverWait(driver, 10);
element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

참조: https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/ui/Expected Conditions.html

이를 처리하기 위해 다음과 같은 클릭 방법을 사용합니다.요소를 찾아서 클릭하려고 합니다.[검색(Find)]와 [클릭(Click)] 사이에 DOM이 변경되면 다시 시도합니다.실패하면 바로 다시 시도하면 두 번째 시도는 성공한다는 생각이다.DOM 의 변경이 매우 빠른 경우는, 동작하지 않습니다.

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;
}

여기서 중요한 것은 조건문 이외의 for 루프를 사용하고 있다는 것입니다.

IF 문의 조건이 충족되면 다른 페이지로 이동할 수 있습니다.따라서 for 루프가 다시 반복되면 다른 페이지에 있기 때문에 오래된 요소 오류가 나타납니다.

if 스테이트먼트의 끝에 마침표를 붙일 수 있습니다.이것은 나에게 효과가 있었습니다.

클릭할 요소를 찾으면 루프를 끊습니다.다음은 예를 제시하겠습니다.

  List<WebElement> buttons = getButtonElements();
    for (WebElement b : buttons) {
        if (b.getText().equals("Next"){
            b.click();
            break;
        }

다음 코드 사용:

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");
            }
        }
}
}
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();
}

이 Try/Catch 코드는 실제로 효과가 있었습니다.동일한 오래된 요소 오류가 발생했습니다.

이것은 JS의 새로운 버전의 셀레늄에서 실행할 수 있습니다(다만, 모든 서포트하는 완전성 Of는 다음과 같습니다.

 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)
  );

@Abhishek Singh's에 따르면 문제를 이해해야 합니다.

예외를 두는 행은 무엇입니까?그 이유는 참조한 요소가 DOM 구조에서 삭제되었기 때문입니다.

더 이상 참조할 수 없습니다(어떤 요소의 ID가 변경되었는지 상상해 보십시오).

코드를 따릅니다.

class TogglingPage {
  @FindBy(...)
  private WebElement btnTurnOff;

  @FindBy(...)
  private WebElement btnTurnOn;

  TogglingPage turnOff() {
    this.btnTurnOff.isDisplayed();  
    this.btnTurnOff.click();          // when clicked, button should swap into btnTurnOn
    this.btnTurnOn.isDisplayed();
    this.btnTurnOn.click();           // when clicked, button should swap into btnTurnOff
    this.btnTurnOff.isDisplayed();    // throws an exception
    return new TogglingPage();
  }
}

이제, 왜 그런지 궁금해지죠?

  1. btnTurnOff발견 - - OK - OK
  2. btnTurnOff에 의해 대체되었습니다.btnTurnOn - OK (OK)
  3. btnTurnOn - ok - ok - 운 was 。 - 네 。
  4. btnTurnOn에 의해 대체되었습니다.btnTurnOff - OK (OK)
  5. 는 리는부 we we we라고 부른다this.btnTurnOff.isDisplayed();셀레늄의 의미에서는 존재하지 않는 원소에 대해 설명합니다.-보실 수 있습니다.완벽하게 동작하지만, 같은 버튼의 다른 예입니다.

가능한 수정:

  TogglingPage turnOff() {
    this.btnTurnOff.isDisplayed();  
    this.btnTurnOff.click();

    TogglingPage newPage = new TogglingPage();
    newPage.btnTurnOn.isDisplayed();
    newPage.btnTurnOn.click();

    TogglingPage newerPage = new TogglingPage();
    newerPage.btnTurnOff.isDisplayed();    // ok
    return newerPage;
  }

제, in, , 그, 그, in, ininput type='date'로드에 레퍼런스와 작용하려고 에, 이 레퍼런스가 되고 있었습니다.exception그리고 그건 굉장히 의미 있는 일이었고Javascript 저는 수 없이 이 이 분리되었습니다.re-get한 후 할 수 있습니다.예외 전 코드는 다음과 같습니다.

if (elemDate != null)
{ 
    elemDate.Clear(); 
    elemDate.SendKeys(model.Age);
}

예외가 발생한 후의 코드:

int tries = 0;
do
{
    try
    {
        tries++;
        if (elemDate != null)
        {
            // these lines were causing the exception so I had break after these are successfully executed because if they are executed that means the control was found and attached to the document and we have taken the reference of it again.
            elemDate.Clear();
            elemDate.SendKeys(model.Age);
            break;
        }
    }
    catch (StaleElementReferenceException)
    {
        System.Threading.Thread.Sleep(10); // put minor fake delay so Javascript on page does its actions with controls
        elemDate = driver.FindElement(By.Id(dateId));
    }
} while (tries < 3); // Try it three times.

따라서 이제 코드로 추가 작업을 수행하거나 제어가 작동하지 않으면 드라이버를 종료할 수 있습니다.

if(tries > 2)
{
   // element was not found, find out what is causing the control detachment.
   // driver.Quit();
   return;
}

// Hurray!! Control was attached and actions were performed.
// Do something with it...

코드 를 잡는 것은 방법이 해야 했고, 된 것을 되었습니다.work-around이 경우 잘 작동해야 합니다.

PS:모든 한 후, 이.「 」 「 」 「 」 「 」 「 」java인데, 이 코드 샘플은 에 에게 도움이 될 수 이 샘플은 문제가 있는 사람에게 도움이 될 수 있습니다.C#언어.또는 쉽게 번역할 수 있습니다.java별로 없기 때문에C#특정 코드

내 경우, 사용하던 로케이터가 여러 개의 결과를 가지고 있기 때문에 액션을 수행하기 위한 적절한 요소를 특정할 수 없었기 때문에 예외가 발생하였습니다.그래서 독특한 로케이터를 가지고 있었더니 문제가 해결되었다.

요소가 연결될 때까지 기다리려면 다음 코드를 사용합니다.

boolean breakIt = true;
        while (true) {
        breakIt = true;
        try {
            // write your code here
        } catch (Exception e) {
            if (e.getMessage().contains("element is not attached")) {
                breakIt = false;
            }
        }
        if (breakIt) {
            break;
        }

    }

언급URL : https://stackoverflow.com/questions/18225997/stale-element-reference-element-is-not-attached-to-the-page-document

반응형