ajax 如何让硒等待ajax响应?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2835179/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get selenium to wait for ajax response?
提问by Zombies
How can I get selenium to wait for something like a calendar widget to load? Right now I am just doing a Thread.sleep(2500)after exporting the testcase to a junit program.
我怎样才能让 selenium 等待日历小部件之类的东西加载?现在我只是Thread.sleep(2500)在将测试用例导出到 junit 程序后做一个。
采纳答案by Neil Aitken
I would use
我会用
waitForElementPresent(locator)
This will wait until the element is present in the DOM.
这将等到元素出现在 DOM 中。
If you need to check the element is visible, you may be better using
如果您需要检查元素是否可见,最好使用
waitForElementHeight(locator)
回答by Morten Christiansen
A more general solution than waiting for an element would be to wait for all the connections to the server to close. This will allow you to wait for all ajax calls to finish, even if they don't have any callback and thus don't affect the page. More details can be found here.
比等待元素更通用的解决方案是等待与服务器的所有连接关闭。这将允许您等待所有 ajax 调用完成,即使它们没有任何回调,因此不会影响页面。可以在此处找到更多详细信息。
Using C# and jQuery, I have created the following method to wait for all AJax calls to complete (if anyone have more direct ways of accessing JS variables from C#, please comment):
使用 C# 和 jQuery,我创建了以下方法来等待所有 AJax 调用完成(如果有人有更直接的方法从 C# 访问 JS 变量,请发表评论):
internal void WaitForAjax(int timeOut = 15)
{
var value = "";
RepeatUntil(
() => value = GetJavascriptValue("jQuery.active"),
() => value == "0",
"Ajax calls did not complete before timeout"
);
}
internal void RepeatUntil(Action repeat, Func<bool> until, string errorMessage, int timeout = 15)
{
var end = DateTime.Now + TimeSpan.FromSeconds(timeout);
var complete = false;
while (DateTime.Now < end)
{
repeat();
try
{
if (until())
{
complete = true;
break;
}
}
catch (Exception)
{ }
Thread.Sleep(500);
}
if (!complete)
throw new TimeoutException(errorMessage);
}
internal string GetJavascriptValue(string variableName)
{
var id = Guid.NewGuid().ToString();
_selenium.RunScript(String.Format(@"window.$('body').append(""<input type='text' value='""+{0}+""' id='{1}'/>"");", variableName, id));
return _selenium.GetValue(id);
}
回答by Nimo
If using python, you may use this function, which clicks the button and waits for the DOM change:
如果使用 python,你可以使用这个函数,它点击按钮并等待 DOM 变化:
def click_n_wait(driver, button, timeout=5):
source = driver.page_source
button.click()
def compare_source(driver):
try:
return source != driver.page_source
except WebDriverException:
pass
WebDriverWait(driver, timeout).until(compare_source)
(CREDIT: based on this stack overflow answer)
(信用:基于此堆栈溢出答案)
回答by toutpt
With webdriver aka selenium2 you can use implicit wait configuration as mentionned on http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp#implicit-waits
使用 webdriver aka selenium2,您可以使用http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp#implicit-waits 上提到的隐式等待配置
Using Java:
使用 Java:
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));
Or using python:
或者使用python:
from selenium import webdriver
ff = webdriver.Firefox()
ff.implicitly_wait(10) # seconds
ff.get("http://somedomain/url_that_delays_loading")
myDynamicElement = ff.find_element_by_id("myDynamicElement")
回答by Hrabosch
I wrote next method as my solution (I hadn't any load indicator):
我写了下一个方法作为我的解决方案(我没有任何负载指示器):
public static void waitForAjax(WebDriver driver, String action) {
driver.manage().timeouts().setScriptTimeout(5, TimeUnit.SECONDS);
((JavascriptExecutor) driver).executeAsyncScript(
"var callback = arguments[arguments.length - 1];" +
"var xhr = new XMLHttpRequest();" +
"xhr.open('POST', '/" + action + "', true);" +
"xhr.onreadystatechange = function() {" +
" if (xhr.readyState == 4) {" +
" callback(xhr.responseText);" +
" }" +
"};" +
"xhr.send();");
}
Then I jsut called this method with actual driver. More description in this post.
然后我用实际的驱动程序调用了这个方法。在这篇文章中有更多描述。
回答by neonidian
This works like a charm for me :
这对我来说就像一个魅力:
public void waitForAjax() {
try {
WebDriverWait driverWait = new WebDriverWait(driver, 10);
ExpectedCondition<Boolean> expectation;
expectation = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driverjs) {
JavascriptExecutor js = (JavascriptExecutor) driverjs;
return js.executeScript("return((window.jQuery != null) && (jQuery.active === 0))").equals("true");
}
};
driverWait.until(expectation);
}
catch (TimeoutException exTimeout) {
// fail code
}
catch (WebDriverException exWebDriverException) {
// fail code
}
return this;
}
回答by Artem Kislicyn
This work for me
这对我有用
public void waitForAjax(WebDriver driver) {
new WebDriverWait(driver, 180).until(new ExpectedCondition<Boolean>(){
public Boolean apply(WebDriver driver) {
JavascriptExecutor js = (JavascriptExecutor) driver;
return (Boolean) js.executeScript("return jQuery.active == 0");
}
});
}
回答by George Kargakis
The code (C#) bellow ensures that the target element is displayed:
下面的代码 (C#) 确保显示目标元素:
internal static bool ElementIsDisplayed()
{
IWebDriver driver = new ChromeDriver();
driver.Url = "http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp";
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
By locator = By.CssSelector("input[value='csharp']:first-child");
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
{
return d.FindElement(locator);
});
return myDynamicElement.Displayed;
}
If the page supports jQuery it can be used the jQuery.active functionto ensure that the target element is retrieved after all the ajax calls are finished:
如果页面支持 jQuery,则可以使用jQuery.active 函数确保在所有 ajax 调用完成后检索目标元素:
public static bool ElementIsDisplayed()
{
IWebDriver driver = new ChromeDriver();
driver.Url = "http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp";
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
By locator = By.CssSelector("input[value='csharp']:first-child");
return wait.Until(d => ElementIsDisplayed(d, locator));
}
public static bool ElementIsDisplayed(IWebDriver driver, By by)
{
try
{
if (driver.FindElement(by).Displayed)
{
//jQuery is supported.
if ((bool)((IJavaScriptExecutor)driver).ExecuteScript("return window.$ != undefined"))
{
return (bool)((IJavaScriptExecutor)driver).ExecuteScript("return $.active == 0");
}
else
{
return true;
}
}
else
{
return false;
}
}
catch (Exception)
{
return false;
}
}
回答by Cirem
Here's a groovy version based on Morten Christiansen's answer.
这是基于 Morten Christiansen 的回答的 groovy 版本。
void waitForAjaxCallsToComplete() {
repeatUntil(
{ return getJavaScriptFunction(driver, "return (window.jQuery || {active : false}).active") },
"Ajax calls did not complete before timeout."
)
}
static void repeatUntil(Closure runUntilTrue, String errorMessage, int pollFrequencyMS = 250, int timeOutSeconds = 10) {
def today = new Date()
def end = today.time + timeOutSeconds
def complete = false;
while (today.time < end) {
if (runUntilTrue()) {
complete = true;
break;
}
sleep(pollFrequencyMS);
}
if (!complete)
throw new TimeoutException(errorMessage);
}
static String getJavaScriptFunction(WebDriver driver, String jsFunction) {
def jsDriver = driver as JavascriptExecutor
jsDriver.executeScript(jsFunction)
}
回答by Amir Shenouda
I had a similar situation, i wanted to wait for ajax requests so that the loading panel would have disappeared, I have inspected the html before and after the requests, found that there is a div for the ajax loading panel, the dix is displayed during the ajax request, and hidden after the request ends. I have created a function to wait for the panel to be displayed, then wait for it to be hidden
我也遇到过类似的情况,我想等待ajax请求,这样加载面板就会消失,我检查了请求前后的html,发现ajax加载面板有一个div,dix显示在ajax 请求,并在请求结束后隐藏。我已经创建了一个函数来等待面板显示,然后等待它被隐藏
public void WaitForModalPanel()
{
string element_xpath = ".//*[@id='ajaxLoadingModalPanelContainer' and not(contains(@style,'display: none'))]";
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 2, 0));
wait.Until(ExpectedConditions.ElementIsVisible(By.XPath(element_xpath)));
element_xpath = ".//*[@id='ajaxLoadingModalPanelContainer' and contains(@style,'DISPLAY: none')]";
wait.Until(ExpectedConditions.ElementExists(By.XPath(element_xpath)));
}
Check thisfor more details
检查这个以获取更多详细信息

