单击 Angular 网页中的 TableRow 时发生 StaleElementException

StaleElementException when Clicking on a TableRow in an Angular WebPage

<div id="crm" class="row gridrow clickable ng-scope" ng-repeat="customer in customerList" ng-click="gotoRecord(customer.id)">
     <i class="col m1 s1 tiny fa fa-male"></i>
     <div class="col m3 s11 ng-binding"> Allard</div>
     <div class="col m2 s12 ng-binding"></div>
</div>

我有 HTML 的这个片段,它是对名称为 Customer 'Allard' 的客户的搜索操作结果显示的一行。我想单击此客户以继续到下一页,但大多数情况下这会导致 StaleElementException。

我尝试了两种不同的方法,使用 Protractor 和不使用 Protractor。

第一种方式:

IWebElement elem = driver.FindElement(By.XPath("//*[contains(text(),'" + nameCustomer + "')]//parent::div[contains(@id,'crm')]"));
        ExplicitWait.WaitAndClick(driver, elem);

第二种方式:

var customers = driver.FindElements(NgBy.Repeater("customer in customerList"));
        foreach (var customer in customers)
        {
            if (elem.Text.Equals(nameCustomer))
            {
                elem.Click();
            }
        }

问题(我认为)

使用 StaleReferenceExceptions,以前创建的 IWebElement 不再附加到 DOM(您可能已经知道这一点)。最有可能发生的是:
1:您点击搜索。
2:Selenium执行driver.FindElement(...),找到匹配元素
3: 然后 搜索功能完成,DOM 更新。之前找到的旧 IWebElement 不见了。
4: Then Selenium 尝试点击元素(不再存在,导致 StaleElementException。有一个元素 匹配 那个元素之前有过,但在 Selenium 眼中它不是同一个元素。)

你说这种情况“大部分时间”发生让我更加怀疑这种情况,因为例外情况取决于事件的顺序,这会有所不同取决于 Selenium 与网页的相对速度。

如何解决(如果这是你的问题)

您需要在页面上找到一些内容,以向 Selenium 指示搜索操作已完成。这就是编写 GUI 自动化脚本的创造力所在。如果您知道页面上的某些内容会因加载而发生变化,请设计一个明确的等待以确保完成。可能会显示一个加载栏,或者在搜索完成时出现一条消息。您可以在单击搜索之前抓取一个与您的搜索不匹配的元素,然后进行明确的等待以确保它消失,然后再继续寻找您的结果做期待在那里。

它看起来像下面这样。

# Search action performed before this.
WebDriverWait wait= new WebDriverWait(driver, TimeSpan.FromSeconds(secondsToWait));
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.XPath( expressionForElementThatWillDissapear )));


IWebElement elem = driver.FindElement(By.XPath("//*[contains(text(),'" + nameCustomer + "')]//parent::div[contains(@id,'crm')]"));
            ExplicitWait.WaitAndClick(driver, elem);

我建议制作方法来实现上面的显式等待。这些情况会经常出现。