我一直在为此寻找解决方案,但没有成功。我有一个按钮正在点击,有时需要很长时间才能返回数据,而驱动程序正在超时,我想这只是扼杀了应用程序。
我正试图使用WebDriverWait类来实现这一点,但Click()方法在我使用它的方式中不可用
WebDriverWait wait = new WebDriverWait(browser, new TimeSpan(0, 5, 0));
bool clicked = wait.Until<bool>((elem) =>
{
elem.Click(); //Doesn't Work
return true;
});
ImplicitlyWait()方法只用于等待加载元素,但在Click()上会超时,因此它甚至无法查找元素。
SetScriptTimeout()方法只适用于执行javascript,我不这么做。
有人知道这样做的方法吗?
试试这个:
WebDriverWait wait = new WebDriverWait(driver , 1000) ;
wait.until(ExcepctedConditions.elementToBeClickable(ById("element"));
元素可以是重定向到的下一页上存在的任何元素的ID。一旦页面完全加载,它就会开始执行您的代码。
您可以尝试使用SendKeys
而不是Click
。与Click
不同,SendKeys
在恢复代码执行之前不等待页面完成加载。所以你可以这样做:
WebDriverWait wait = new WebDriverWait(browser, new TimeSpan(0, 5, 0));
elem.SendKeys(Keys.Enter);
wait.Until<bool>((_driver) =>
{
//Check here if results have loaded yet
return true;
});
顺便说一句,我确信Until
接受IWebBrowser
作为输入,而不是元素,这就是为什么你不能点击elem
的原因。
除了prestomanifesto的解决方案之外,我还可以提供一个不太理想的解决方案来解决这个问题。事实证明,它正在抛出一个异常-没有响应等…-所以我只是在一次尝试捕获中包围了它,然后等待弹出窗口关闭,这似乎很好。
你可以在循环中替换你想要的任何东西,只需确保放入一个计数器,这样它就不会永远循环。
try
{
element.Click();
}
catch
{
cnt++;
do
{
//wait for whatever
cnt++;
Thread.Sleep(1000);
// Wait for 30 seconds for popup to close
} while (!string.IsNullOrEmpty(browser.CurrentWindowHandle) && cnt < 30);
}
我使用这个脚本:
private static void waitUntilScriptFoundAndExecute(String script) {
int tries = 0;
boolean found = false;
do {
tries++;
try {
driver.executeScript(script);
found = true;
} catch (NoSuchElementException nse) {
System.out.println("Wait for script NSE (" + tries + ")");
} catch (WebDriverException wde) {
System.out.println("Wait for script WDE (" + tries + ")");
} catch (Exception e) {
System.out.println("Wait for script E (" + tries + ")");
}
// Waiting
if (!found) {
System.out.println("Wait for script Not found (" + tries + ")");
waiting(SCRIPT_WAITING_INTERVAL);
}
} while (!found && tries < MAX_SCRIPT_WAIT_TRIES);
if (!found) {
System.out.println("Script aborted: " + script);
}
}
使用LINQ Lambda表达式的RepeatUntil扩展方法
将此代码复制到您的项目:
public static class SeleniumExtensionMethods
{
public static IWebElement RepeatUntil<T>(this T obj,
Func<T, IEnumerable<IWebElement>> func,
Func<IWebElement, bool> compare,
int MaxRetry = 20)
{
//call function to get elements
var eles = func(obj);
IWebElement element = null;
while (element == null && MaxRetry > 0)
{
MaxRetry-=1;
//call the iterator
element = IterateCollection(compare, eles);
if (element == null)
{
Thread.Sleep(500);
//get new collection of elements
eles = func(obj);
}
};
return element;
}
private static IWebElement IterateCollection(
Func<IWebElement, bool> compare,
IEnumerable<IWebElement> eles){
IWebElement element = null;
eles.ToList().ForEach(
ele =>
{
//call the comparator
var found = compare(ele);
if (found) element = ele;
});
return element;
}
}
使用以下语法进行调用:
// You can change PageObjectType to IWebDriver or IWebElement so that
// cb is of any type.
var element = cb.RepeatUntil<MyPageObjectType>(
//This is the first function to provide the elements
p => p.FindElements(By.ClassName("TreeNode")),
//This is the comparator
ele => ele.Text == nodeText && ele.Location.Y>YLocation);
注意:在上面的例子中,我们传递了一个PageObjectType,但您可以将其更改为IWebDriver或事件IWebElement类型。所有类型参数都允许您将其用作指定类型的扩展方法。
请注意扩展方法的灵活性,因为调用者可以确定集合和比较器。
不要使用线程睡眠
public class(IWebDriver driver)
{
this.driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMinutes(1);
wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver,TimeSpan.FromMinutes(1));
}
public void class1()
{
wait.Until(ExpectedConditions.ElementToBeClickable(elem)).Click();
}