বাসি উপাদান রেফারেন্স: উপাদান পৃষ্ঠা নথির সাথে সংযুক্ত নেই


97

আমার তালিকায় প্রতিটি বিভাগের অধীনে একাধিক লিঙ্ক রয়েছে। প্রতিটি বিভাগের একই লিঙ্ক রয়েছে আমাকে প্রতিটি বিভাগের অধীনে একটি নির্দিষ্ট লিঙ্কে ক্লিক করতে হবে। আমি নীচের কোডটি লিখেছি কিন্তু এটি কার্যকর করলে এটি আমাকে 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++;
    }
}

}

এটি এইচটিএমএল কাঠামোটি নীচের মতো রয়েছে

<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

উত্তর:


81

রেখাটি যা ব্যতিক্রম দেয় ??

এর কারণ হ'ল কারণ যে উপাদানটিতে আপনি উল্লেখ করেছেন সেটি ডিওএম কাঠামো থেকে সরানো হয়েছে

আইইডিগ্রাইভারের সাথে কাজ করার সময় আমি একই সমস্যার মুখোমুখি হয়েছিলাম। কারণটি ছিল কারণ জাভাস্ক্রিপ্টটি আমি উল্লেখ করার পরে আরও একবার উপাদানটি লোড করেছিলাম তাই আমার তারিখের রেফারেন্সটি একটি ইউএক্সিটিং অবজেক্টের দিকে ইঙ্গিত করে এমনকি এটি যদি ইউআইতে সঠিক হয়। আমি নিম্নলিখিত workaround ব্যবহার।

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

একই যদি আপনাকে সহায়তা করতে পারে তা দেখুন!


linkTexts [i] = e.getText (); লাইনগুলি দ্বিতীয়বার লুপ করার সময় আমাকে ত্রুটি দেয়
পাতিল প্রশান্ত

4
পৃষ্ঠার রিফ্রেশের কারণে সমস্যাটি সমাধান হয়েছে first (ওয়েবএলমেন্ট ই: বামনাভলিংকস) এর জন্য {linkTexts [i] = e.getText (); আমি ++; int এর জন্য (int j = 0; j <leftnavlen; j ++) {যদি (লিঙ্কটেক্সটস [জে] .সম্পাদনা (বেন)) {স্ট্রিং বেনিফিট স্ট্যাটলি = "// * [@ আইডি = 'স্লাইডিং-নেভিগেশন'] / লি [% s ] / ক "; ড্রাইভার.ফাইন্ডএলিমেন্ট (বাই.স্পাথ (স্ট্রিং.ফর্ম্যাট (বেনিফিটস্ট্যাটলি, জে + 1))) ক্লিক করুন (); ড্রাইভার.ফাইন্ডএলিমেন্ট (বাই.স্পাথ ("// * @ আইডি = 'ডিভি কনটেন্টহোল্ডার'] / ডিভি [1] / এ [1]")) ক্লিক করুন (); }
পাতিল প্রশান্ত

সুতরাং এটি একই কারণে ছিল। পৃষ্ঠাগুলি রিফ্রেশের কারণে এর আগে চিহ্নিত উপাদানগুলি ডিওএম থেকে অপসারণ করা হয়েছে :)
অভিষেক সিং

হ্যাঁ আসলেই তা করে দেয়। অনেক ধন্যবাদ @ অভিষেকসিংহ
রাহাল

আমার ক্ষেত্রে আমি এই ব্যতিক্রমটি পেয়েছি কারণ প্রয়োজনীয় উপাদানটি ক্লিক করার পরে আমার লুপে ব্রেক স্টেটমেন্ট নেই। সুতরাং এ জাতীয় পরিস্থিতিতেও নজর রাখুন।
রাজ আসপু

48

যখনই আপনি এই সমস্যার মুখোমুখি হন, কেবলমাত্র ত্রুটি পাচ্ছেন এমন রেখার উপরে ওয়েব উপাদানটিকে আবার একবার সংজ্ঞায়িত করুন

উদাহরণ:

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


আরে, মনে হচ্ছে এটি আমার ত্রুটিটি সমাধান করেছে। তবে কেন আমি একই উপাদানটিকে এর আগে সংজ্ঞায়িত করে সংজ্ঞায়িত করতে হবে তা আমি বুঝতে পারি না।
অভি

8

এটি পরিচালনা করতে, আমি নিম্নলিখিত ক্লিক পদ্ধতিটি ব্যবহার করি। এটি উপাদানটি খুঁজে পেতে এবং ক্লিক করার চেষ্টা করবে। যদি অনুসন্ধান এবং ক্লিকের মধ্যে 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;
}

8

এই ত্রুটিগুলির দুটি সাধারণ কারণ রয়েছে: উপাদানটি পুরোপুরি মুছে ফেলা হয়েছে, বা উপাদানটি আর ডোমের সাথে সংযুক্ত নেই।

আপনি যদি ইতিমধ্যে এটি পরীক্ষা না করে থাকেন তবে এটি আমার মতো সমস্যার মুখোমুখি হতে পারে।

ডিওমে উপাদানটি পাওয়া যায় নি কারণ যখন সেলেনিয়াম উপাদানটির সন্ধান করছে তখন আপনার পৃষ্ঠা সম্পূর্ণ লোড হয় না। এটি সমাধান করার জন্য, আপনি একটি সুস্পষ্ট অপেক্ষা শর্ত রাখতে পারেন যা সেলেনিয়ামকে উপাদানটি ক্লিক করার জন্য উপলব্ধ হওয়া পর্যন্ত অপেক্ষা করতে বলে।

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


এটি আমার জন্য কাজ করেছে। এছাড়াও দস্তাবেজের লিঙ্কটি এটি কীভাবে কাজ করে তা বুঝতে সহায়তা করে। ধন্যবাদ @ ব্রুনো_স্যাঞ্চস
নিকুঞ্জ কাকাদিয়া

4

এখানে জিনিসটি হ'ল আপনি নিজের শর্তাধীন বিবৃতিটির বাইরে লুপের জন্য ব্যবহার করছেন।

আপনার আইএফ বিবৃতিতে শর্ত পূরণ হওয়ার পরে আপনি সম্ভবত অন্য পৃষ্ঠায় নেভিগেট করতে পারেন, সুতরাং যখন লুপের জন্য আরও একবার পুনরুক্তি করার চেষ্টা করা হয়, আপনি বাসি উপাদানটির ত্রুটি পাবেন কারণ আপনি অন্য পৃষ্ঠায় রয়েছেন।

আপনি যদি আপনার বিবৃতি শেষে একটি বিরতি যোগ করতে পারেন, এটি আমার জন্য কাজ করেছে।


ত্রুটি কেন ঘটছে তা বুঝতে আমাকে কিছুক্ষণ সময় লাগল!
বুভারব

3

আপনি যে উপাদানটিতে ক্লিক করতে চান তা খুঁজে পেলেই লুপটি ভাঙ্গুন। উদাহরণ স্বরূপ:

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

2

এই কোডটি ব্যবহার করুন:

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

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

এই চেষ্টা / ক্যাচ কোডটি আসলে আমার পক্ষে কাজ করেছিল। আমি একই বাসি উপাদান ত্রুটি পেয়েছি।


4
এই উত্তরটি কি এখানে শীর্ষ-ভোট প্রাপ্ত উত্তরের চেয়ে আলাদা?
সিকিং

1

এটি জেএসে সেলেনিয়ামের নতুন সংস্করণগুলিতে করা যেতে পারে (তবে সমস্ত সমর্থনকারী stalenessOf কাজ করবে):

 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

@ অভিষেক সিংয়ের মতে আপনার সমস্যাটি বুঝতে হবে:

রেখাটি যা ব্যতিক্রম দেয় ?? এর কারণ হ'ল কারণ যে উপাদানটিতে আপনি উল্লেখ করেছেন সেটি ডিওএম কাঠামো থেকে সরানো হয়েছে

এবং আপনি এটি আর উল্লেখ করতে পারবেন না (ধারণা করুন কী উপাদানটির আইডি পরিবর্তিত হয়েছে)।

কোডটি অনুসরণ করুন:

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 একটি ড্রাইভারের দ্বারা পাওয়া গেছে - ঠিক আছে
  2. btnTurnOffদ্বারা প্রতিস্থাপন করা হয়েছিল btnTurnOn- ঠিক আছে
  3. btnTurnOnএকটি ড্রাইভার দ্বারা পাওয়া গেছে। - ঠিক আছে
  4. btnTurnOnদ্বারা প্রতিস্থাপন করা হয়েছিল btnTurnOff- ঠিক আছে
  5. আমরা 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;
  }

0

আমার ক্ষেত্রে, আমার একটি পৃষ্ঠা ছিল যেখানে এটি input 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#নির্দিষ্ট কোড না থাকায় এটি সহজে অনুবাদ করা যায় ।


-7

উপাদান সংযুক্ত না হওয়া পর্যন্ত অপেক্ষা করতে এই কোডটি ব্যবহার করুন:

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

    }

4
আমার জন্য কাজ করেনি তবে এখনও একটি আকর্ষণীয় পদ্ধতির
ইয়ার

28
এটি কি কখনও বোঝা যায় না।
সাম

4
এটি উপলব্ধি করে, এর ভেরিয়েবল নাম "ব্রেকআইটি" এর ক্ষেত্রে এটি কেবল সবচেয়ে পরিষ্কার নয়। "এলিমেন্টটি সংযুক্ত করা হয়নি" ত্রুটিটি আর ছুঁড়ে ফেলা হচ্ছে না বলে এটি (সত্য) লুপটি ভেঙে যায়।
এমেরি

'বুলিয়ান doIt = সত্য; যখন (doIt) {চেষ্টা করুন {// আপনার কোডটি এখানে লিখুন} ধরা (ব্যতিক্রম ই) {যদি (e.getMessage ()। থাকে ("উপাদানটি সংযুক্ত থাকে না")) I doIt = মিথ্যা; }}} '
তাও ঝাং

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.