在浏览器中生成元素后,有一个 Ui 块覆盖了所有元素几秒钟,因此我面临一个问题,由于元素已经存在,网络驱动程序尝试单击该元素,但单击由 Block UI 接收。 我尝试使用 wait Until 但没有帮助,因为我可以在 C# webdriver 中找到 isClickAble
var example = _wait.Until<IWebElement>((d) => d.FindElement(By.XPath("Example")));
var example2 = _wait.Until<IWebElement>(ExpectedConditions.ElementIsVisible(By.XPath("Example")));
example.click();
example2.click();
是否有 isClickAble 的 C# 等效项,提前致谢
查看 Java 源代码,告诉我它基本上做了两件事来确定它是否“可点击”:
首先,它会使用标准
ExpectedConditions.visibilityOfElementLocated
检查它是否“可见”,然后简单地检查 element.isEnabled()
是否为 true
。
这可以稍微压缩一下,这基本上意味着(在 C# 中简化):
.Displayed
属性为 true(这本质上是 visibilityOfElementLocated
正在检查的内容)。.Enabled
属性为 true(这本质上是 elementToBeClickable
正在检查的内容)。我会像这样实现它(添加到当前的
ExpectedConditions
集合中,但是有多种方法可以做到这一点:
/// <summary>
/// An expectation for checking whether an element is visible.
/// </summary>
/// <param name="locator">The locator used to find the element.</param>
/// <returns>The <see cref="IWebElement"/> once it is located, visible and clickable.</returns>
public static Func<IWebDriver, IWebElement> ElementIsClickable(By locator)
{
return driver =>
{
var element = driver.FindElement(locator);
return (element != null && element.Displayed && element.Enabled) ? element : null;
};
}
可用于:
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementIsClickable(By.Id("id")));
但是,您可能对 clickable 的含义有不同的想法,在这种情况下,此解决方案可能不起作用 - 但它是 Java 代码正在执行的操作的直接翻译。
这是我用来检查它是否可点击的代码,否则转到另一个 URL。
if (logOutLink.Exists() && ExpectedConditions.ElementToBeClickable(logOutLink).Equals(true))
{
logOutLink.Click();
}
else
{
Browser.Goto("/");
}
如果您遇到诸如“另一个元素将收到点击”之类的问题,解决此问题的方法是使用 while 循环等待该覆盖框消失。
//The below code waits 2 times in order for the problem element to go away.
int attempts = 2;
var elementsWeWantGone = WebDriver.FindElements(By.Id("id"));
while (attempts > 0 && elementsWeWantGone.Count > 0)
{
Thread.Sleep(500);
elementsWeWantGone = WebDriver.FindElements(By.Id("id"));
}
在我们较慢的测试运行计算机上,似乎输入元素首先可以找到,但当脚本尝试向输入控件发送按键或单击时仍然无法单击。等待“ElementToBeClickable”有帮助。更快、更强大的测试运行系统几乎不会出现这个问题。
这里的代码带有一些上下文,似乎对我基于 C# 的 Selenium 测试有所改进。还使用 SpecFlow 和 xUnit。我们使用的是 IE11 和 IEDriverServer.exe。
截至 2019 年 5 月,包含此内容的 NuGet 包是 DotNetSeleniumExtras.WaitHelpers。
关键是这一行:
wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(作者...
)使用指向您要交互的第一个输入字段的选择器,对新页面上的第一个输入字段执行此操作。 (通过.XPath("")
[Given(@"I have selected the link to the OrgPlus application")]
public void GivenIHaveSelectedTheLinkToTheOrgPlusApplication()
{
_driver.Navigate().GoToUrl("http://orgplus.myorg.org/ope?footer");
}
[Given(@"I have selected the link to the OrgPlus Directory lookup")]
public void GivenIHaveSelectedTheLinkToTheOrgPlusDirectoryLookup()
{
var wait = new WebDriverWait(_driver, new TimeSpan(0, 0, 30));
var element = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(By.XPath("//*[@id=\"lnkDir\"]")));
IWebElement btnSearch = _driver.FindElement(By.XPath("//*[@id=\"lnkDir\"]"));
btnSearch.SendKeys(Keys.Enter);
}
我想扩展亚伦的答案。
您可以使用弹性和瞬态故障处理,例如 polly。 找到元素并尝试使用 Polly 单击它并处理潜在的异常。 在这种情况下,NoSuchElementException。
var elementToBeRetried = Policy.Handle<NoSuchElementException>().Or<WebDriverTimeoutException>().WaitAndRetry(3, _ => TimeSpan.FromSeconds(3))
.Execute(() =>
{
LogInformation("Retrying");
var element=Page.GetElementById("xx", false, 1); //_driver.FindElement(byCriterion)
element.Click();
return element;
});
此外,以 Aaran 为例,您可以使用 DefaultWait 并忽略可能的异常类型。
var w = new DefaultWait<IWebElement>(_driver.FindElement(byCriterion))
{
Timeout = TimeSpan.FromSeconds(maxWaitSeconds)
};
w.IgnoreExceptionTypes(typeof(NoSuchElementException), typeof(StaleElementReferenceException), typeof(Exception));
return w.Until(e => e.Displayed && e.Enabled ? e : null);