Ответ 1
var wait = new WebDriverWait(d, TimeSpan.FromSeconds(5));
var element = wait.Until(driver => driver.FindElement(By.Id("Hobbies")));
Я использую Selenium 2 WebDriver для тестирования пользовательского интерфейса, который использует AJAX.
Есть ли способ заставить драйвер немного подождать, пока запрос Ajax завершится.
В основном у меня есть это:
d.FindElement(By.XPath("//div[8]/div[3]/div/button")).Click();
// This click trigger an ajax request which will fill the below ID with content.
// So I need to make it wait for a bit.
Assert.IsNotEmpty(d.FindElement(By.Id("Hobbies")).Text);
var wait = new WebDriverWait(d, TimeSpan.FromSeconds(5));
var element = wait.Until(driver => driver.FindElement(By.Id("Hobbies")));
Если вы используете jQuery для своих запросов ajax, вы можете подождать, пока свойство jQuery.active
не будет равно нулю. Другие библиотеки могут иметь аналогичные варианты.
public void WaitForAjax()
{
while (true) // Handle timeout somewhere
{
var ajaxIsComplete = (bool)(driver as IJavaScriptExecutor).ExecuteScript("return jQuery.active == 0");
if (ajaxIsComplete)
break;
Thread.Sleep(100);
}
}
Вы также можете использовать явное ожидание Selenium здесь. Тогда вам не нужно обрабатывать тайм-аут самостоятельно
public void WaitForAjax()
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(15));
wait.Until(d => (bool)(d as IJavaScriptExecutor).ExecuteScript("return jQuery.active == 0"));
}
Java-решение, основанное на Morten Christiansens, отвечает
public void WaitForAjax() throws InterruptedException { while (true) { Boolean ajaxIsComplete = (Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0"); if (ajaxIsComplete){ break; } Thread.sleep(100); } }
Просто небольшое улучшение, добавив параметр тайм-аута:
internal static void WaitForAllAjaxCalls(this ISelenium selenium, IWebDriver driver, int timeout = 40)
{
Stopwatch sw = new Stopwatch();
sw.Start();
while (true)
{
if (sw.Elapsed.Seconds > timeout) throw new Exception("Timeout");
var ajaxIsComplete = (bool)driver.ExecuteScript("return jQuery.active == 0");
if (ajaxIsComplete)
break;
Thread.Sleep(100);
}
}
Вот мой код:
public static void WaitForCommission (WebDriver driver) throws Exception {
for (int second = 0;; second++) {
if (second >= 30) fail("timeout");
try {
if (IsElementActive(By.id("transferPurposeDDL"), driver))
break;
} catch (Exception e) {}
Thread.sleep(1000);
}
}
private static boolean IsElementActive(By id, WebDriver driver) {
WebElement we = driver.findElement(id);
if(we.isEnabled())
return true;
return false;
}
Этот код действительно работает.
Просто небольшое улучшение:
//Wait for Ajax call to complete
public void WaitForAjax1() throws InterruptedException
{
while (true)
{
if ((Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0")){
break;
}
Thread.sleep(100);
}
}
Если вы используете Graphene, вы можете использовать это:
Graphene.waitModel().until((Predicate<WebDriver>) input -> (Boolean) ((JavascriptExecutor) input).executeScript("return jQuery.active == 0"));
"XML Http Request" - это протокол, используемый для отправки Ajax-запросов на сервер, и поэтому наличие такого запроса указывает на текущую операцию на основе Ajax.
Существует несколько плагинов браузера, которые позволяют отслеживать запросы XML Http, отправленные браузером. Я лично использую плагин Firebug для Firefox, который является очень полезным инструментом. После установки Firebug отображает значок, похожий на ошибку, в нижнем правом углу окна браузера. Нажав на значок, похожий на ошибку, запускает Firebug, как показано на изображении выше. Выберите "Сеть", а затем "XHR", чтобы запустить консоль XHR, где будут отображаться все HTTP-запросы HTTP, отправленные браузером.
Избегайте использования thread.sleep() как можно больше. Вот фрагмент кода, который принимает время ожидания в качестве ввода и запускает секундомер в течение указанного времени.
Вы можете установить время ввода в секундах до 30, чтобы начать с.
protected void WaitForAjaxToComplete(int timeoutSecs)
{
var stopWatch = new Stopwatch();
try
{
while (stopWatch.Elapsed.TotalSeconds < timeoutSecs)
{
var ajaxIsComplete = (bool)(WebDriver as IJavaScriptExecutor).ExecuteScript("return jQuery.active == 0");
if (ajaxIsComplete)
{
break;
}
}
}
//Exception Handling
catch (Exception ex)
{
stopWatch.Stop();
throw ex;
}
stopWatch.Stop();
}
Если вы используете Coypu, вы можете проверить, существует ли элемент после вызова AJAX, а затем вы можете щелкнуть по нему:
private void WaitUntilExistsThenClick(string selectorId)
{
var searchBoxExists = new State(() => browser.FindId(selectorId).Exists());
if (browser.FindState(searchBoxExists) == searchBoxExists)
{
browser.FindId(selectorId).Click();
}
}