Несколько wait.unll внутри обычного клика
Я создал собственный метод щелчка, который ждет, пока элемент станет кликабельным, прежде чем он щелкнет по элементу. метод работает хорошо, но мне нужно добавить еще wait.Until
чтобы сделать метод кликов более стабильным.
Это то, что у меня есть.
public static void WaitAndJsClick(this Browser browser, IWebElement element, int seconds = 30)
{
var LoadingProgressBar = "(//*[@class='progress-bar'])[2]";
var loading = "loading";
var spinner = "spinner";
var wait = new WebDriverWait(browser.Driver, new TimeSpan(0, 0, seconds));
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName(loading)));
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName(spinner)));
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.XPath(LoadingProgressBar)));
wait.Until(ExpectedConditions.ElementToBeClickable(element));
element.JsClick(browser); // Click
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName(loading)));
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName(spinner)));
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.XPath(LoadingProgressBar)));
wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
}
Теперь, как вы можете видеть, я жду, пока три элемента будут "невидимыми", прежде чем они щелкнут, а после щелчка он ждет, пока элементы снова станут "невидимыми".
Мои вопросы действительно, как я могу улучшить это? это даже хорошее решение? это выглядит как беспорядок, но работает действительно хорошо.
3 ответа
У меня была похожая проблема, и это то, что я сделал, чтобы обеспечить стабильность в таких случаях.
private const int RetryIntervalInMilliSeconds = 2000;
private const int AjaxReqTimeoutInMilliSeconds = 20000;
public void WaitForAjax()
{
var stopwatch = Stopwatch.StartNew();
while (stopwatch.ElapsedMilliseconds < AjaxReqTimeoutInMilliSeconds)
{
try
{
Thread.Sleep(RetryIntervalInMilliSeconds);
var ajaxIsComplete = (bool)browser.ExecuteJavascript("return window.jQuery && jQuery.active == 0");
if (ajaxIsComplete)
{
break;
}
}
catch
{
return;
}
}
}
Затем я заменил все вызовы, которые у меня есть, которые ждут счетчики и индикаторы выполнения, на вызов WaitForAjax().
Вы можете технически удалить спящие состояния и просто использовать javascript ajaxComplete в ожидаемом условии, чтобы вернуть true.
Надеюсь это поможет
Я не большой поклонник общих методов, которые ждут кучу вещей. Я думаю, что это делает вещи более запутанными и труднее отлаживать, когда что-то идет не так. Я написал бы функцию для каждой "вещи", которую нужно подождать... индикатор выполнения, спиннер, загрузка сообщения и т. Д., А затем вызывать их, когда они вам нужны.
public static void WaitForLoading(this Browser browser)
{
new WebDriverWait(browser.Driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName("loading")));
}
public static void WaitForProgressBar(this Browser browser)
{
new WebDriverWait(browser.Driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.InvisibilityOfElementLocated(By.XPath("(//*[@class='progress-bar'])[2]")));
}
public static void WaitForSpinner(this Browser browser)
{
new WebDriverWait(browser.Driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName("spinner")));
}
Затем, когда вам нужно дождаться индикатора выполнения после нажатия на элемент, вы делаете что-то вроде этого
element.JsClick(browser);
WaitForProgressBar(browser);
Теперь ваш код для ожидания каждой "вещи" существует только в одном месте (следует принципу СУХОЙ) и его легче поддерживать.
wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
здесь нет смысла. Если вы действительно хотите игнорировать некоторые исключения, выполните этот метод сразу после создания этого нового объекта Wait