<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片段,它是一行,显示为具有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();
}
}
答案 0 :(得分:1)
使用StaleReferenceExceptions,先前创建的IWebElement不再附加到DOM(您可能已经知道这一点)。最可能发生的是:
1:点击搜索
2:Selenium执行driver.FindElement(...)
并找到匹配的元素
3:然后搜索功能完成并且DOM更新。之前找到的旧IWebElement已消失
4:然后 Selenium尝试点击元素(不再存在,导致StaleElementException。有一个元素匹配之前存在的元素,但它&# 39;在Selenium的眼中不是同一个元素。)
你的陈述发生了这种情况&#34;大部分时间&#34; 让我怀疑情况更是如此,因为异常将取决于事件的顺序,这会有所不同取决于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);
我建议让方法实现上面的显式等待。这些情况经常会出现。