Selenium - StaleElementReferenceException - 元素未附加到页面文档 (C#)

Selenium - StaleElementReferenceException - element is not attached to the page document (C#)

我很感激这个问题之前已经被问过很多次,但是当你觉得你已经尝试过 stack overflow 上发布的每一个解决方案时,那么是时候问一个问题了......

我在循环 table 并单击特定行中的链接时收到 StaleElementReferenceException。第一次它运行良好,就在第一次迭代完成时出现错误。我完全明白这个错误想对我说什么,我只是不知道如何解决它:/

有问题的table如下:

与之相对应的HTML来源:

<table  CLASS="datadisplaytable" SUMMARY="This table displays the components of the course." WIDTH = "100%"><caption class="captiontext">Components</caption>
  <tr>
    <td CLASS="ntheader" scope="col" >Description</td>
    <td CLASS="ntheader" scope="col" >Weight </td>
    <td CLASS="ntheader" scope="col" >Grade<br />Scale</td>
    <td CLASS="ntheader" scope="col" >Must<br />Pass</td>
    <td CLASS="ntheader" scope="col"  style="display:NONE;"  >Include in<br />Midterm or Final</td>
    <td CLASS="ntheader" scope="col" >Incomplete<br />Scores</td>
    <td CLASS="ntheader" scope="col" >Subcomponents</td>
   </tr>
   <tr>
    <td CLASS="ntdefault">COURSEWORK - <a href="/pls/ubano1/BYLKEGRB.P_FacDispShrmrks?term=202210&amp;crn=50493&amp;gcom_id=322913">Portfolio of clinical learning - 2000 words</a></td>
   <td CLASS="ntdefault">70/100</td>
   <td CLASS="ntdefault">0-100 PG</td>
   <td CLASS="ntdefault"><SPAN class="fieldmediumtext">Yes</SPAN></td>
    <td CLASS="ntdefault" style="display:NONE;"  >F</td>
    <td CLASS="ntdefault">12</td>
    <TD CLASS="ntdefault">
None
    </TD>
   <tr>
    <td CLASS="ntdefault">PRACTICAL - <a href="/pls/ubano1/BYLKEGRB.P_FacDispShrmrks?term=202210&amp;crn=50493&amp;gcom_id=322914">Online Objective Structured Clinical Examination (OSCE) - 1 hour</a></td>
    <td CLASS="ntdefault">30/100</td>
    <td CLASS="ntdefault">0-100 PG</td>
    <td CLASS="ntdefault"><SPAN class="fieldmediumtext">Yes</SPAN></td>
    <td CLASS="ntdefault" style="display:NONE;"  >F</td>
    <td CLASS="ntdefault">13</td>
    <TD CLASS="ntdefault">
     None
    </TD>
</tr>
</table>
<br />
<table  CLASS="plaintable" SUMMARY="This table displays the links for composite information if applicable.">
<tr>
<td CLASS="pldefault"><a href="/pls/ubano1/BYLKEGRB.P_FacDispShrcmrk?term=202210&amp;crn=50493&amp;rectype_ind=F">View Final Composite Grades</a></td>
</table>

有问题的代码如下:

** 编辑 **

IWebElement dataDisplayTable = driver.FindElement(By.XPath("/html/body/div[4]/table[2]"));
List<IWebElement> dataDisplayTableRows = dataDisplayTable.FindElements(By.TagName("tr")).ToList();

foreach (IWebElement row in dataDisplayTableRows.Skip(1)) {
  // Works first time round but then erros on 2nd iteration of loop
  IWebElement assessmentTypeLink = row.FindElement(By.TagName("a"));
  assessmentTypeLink.Click();

List<IWebElement> studentComponentListView = 
GradebookCommon.getStudentComponentListView(row, driver);

foreach (IWebElement tr in studentComponentListView.Skip(2))
{
  List<IWebElement> tableDataList = tr.FindElements(By.TagName("td")).ToList();
  String studentId = tableDataList.ElementAt(1).Text;

  if (Common.studentIdsMatch(studentIdToMatch, tableDataList, studentId))
    {
      driver.Manage().Window.Maximize();

      IWebElement scoreColumnDiv = tableDataList.ElementAt(4);
      IWebElement scoreColumnTextField = scoreColumnDiv.FindElement(By.TagName("input"));

                                
 scoreColumnTextField.SendKeys("60");
 IWebElement submitBtn = driver.FindElement(By.XPath("/html/body/div[4]/form/input[8]"));
 submitBtn.Click();

 IWebElement selectComponentButton = driver.FindElement(By.LinkText("Select Component"));
 selectComponentButton.Click();
 break;
 }
}
}

导致此问题的代码行是:

IWebElement assessmentTypeLink = row.FindElement(By.TagName("a"));

我尝试了其他几种解决方案,但每一种都没有成功。其中一些解决方案如下:

下面的解决方案只是循环了 x 次然后失败了。

public static bool clickAssessmentLink(By by, IWebDriver driver)
        {
            bool result = false;
            int attempts = 0;
            while (attempts == 0)
            {
                try
                {
                    driver.FindElement(by).Click();
                    result = true;
                    break;
                }
                catch (StaleElementReferenceException e)
                {
                    Console.WriteLine("Caught exception.. Retrying.");
                }
                attempts++;
            }
            return result;
        }

我还尝试了以下方法(创建 WebElement 的副本): 来自这里:StaleReference

WebElement link = driver.findElement(By.TagName("a"));
link.click();


WebElement link1 = driver.findElement(By.TagName("a"));
link1.click();

我也试过

WebDriverWait 解决方案
public static void WaitAndClick(this IWebDriver driver, IWebElement webelement)
{
    WebDriverWait fluentWait = new WebDriverWait(driver,TimeSpan.fromSeconds(20));
    //No need to set PollingInterval, default is already 500ms
    fluentWait.IgnoreExceptionTypes(typeof(NoSuchElementException));
    fluentWait.Until(ExpectedConditions.ElementToBeClickable(webelement));

    webelement.Click();
}

无论我求助于哪个解决方案,我都无法进一步解决。以前有没有其他人经历过这样的事情?我一定花了 15-16 多个小时来弄清楚这个问题!

在此先致谢,如有更多信息,请告诉我。

谢谢!

我已经通过以下方式解决了这个问题。这是否是最佳实践,我不太确定,但老实说,这是唯一对我有用的解决方案。我已经尝试了所有其他方法,但没有成功。

  List<IWebElement> aHrefs = driver.FindElements(By.XPath("/html/body/div[4]/table[2]//a")).ToList();
  List<String> links = new List<String>();
  aHrefs.ForEach(link => { links.Add(link.GetAttribute("href")); });
                    
  foreach (String link in links) {
   driver.Url = link;
   Thread.Sleep(3000);
   List<IWebElement> studentComponentListView = GradebookCommon.getStudentComponentListView(driver);

我所做的基本解释:

获取所有 <a> 标签并将它们保存在列表中(通过 XPATH)

List<IWebElement> aHrefs = driver.FindElements(By.XPath("/html/body/div[4]/table[2]//a")).ToList();

声明将保存 <a hrefs>

的新 List<String>

遍历每个 <a> 标签并获取 <href> 属性并存储在列表中

然后可以遍历 <href> 中的每个 link 并通过 driver.Url = link

打开它