【问题标题】:StaleElementException when Clicking on a TableRow in an Angular WebPage单击 Angular 网页中的 TableRow 时出现 StaleElementException
【发布时间】:2017-06-07 14:29:27
【问题描述】:
<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 的 sn-p,它是作为对 nameCustomer '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();
            }
        }

【问题讨论】:

  • 1.在此表出现之前是否有任何事件发生?即表格隐藏在页面上,或者它可能预先填充了一些其他数据? 2.你试过更精确的xpath吗?您的 xpath 只是尝试查找与页面上的文本匹配的 smthn
  • 1. 最初,该表填充了数据库中的前 20 位客户,在搜索后,他们将被满足搜索条件的客户替换。 2.文本即客户名是唯一标识表格行的唯一属性。
  • 1.我假设 Allard 是前 20 个客户之一? 2. //div[@id='crm']/div[text()='Allard'] - 或者如果你 100% 确定元素是唯一的并且上面的情况是正确的,那么就不需要它.
  • 1.你是对的,我正在寻找的客户在第一页上,并且在我开始搜索操作时已经出现,但与搜索操作后的位置相比,它位于另一个位置。当相同的测试正在寻找没有出现在第一页的客户时,它永远不会失败(我尝试了超过 30 次)。 @Tyler Nielsen 下面的答案是对这种行为的完美解释。

标签: c# angularjs selenium-webdriver protractor-net


【解决方案1】:

问题(我认为)

使用 StaleReferenceExceptions,之前创建的 IWebElement 不再附加到 DOM(您可能已经知道这一点)。最有可能发生的是:
1:你点击搜索。
2:Selenium 执行driver.FindElement(...) 并找到匹配的元素。
3:然后搜索功能结束,DOM更新。之前找到的旧 IWebElement 已消失。
4:然后 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);

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

【讨论】:

  • 你说得对,你准确地描述了我的问题的原因。我通过在启动搜索功能之前等待消息出现并等待搜索结果可见的组合来解决它。
猜你喜欢
  • 2020-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-08
  • 2012-07-05
相关资源
最近更新 更多