我尝试进行一些智能验证,以确定在通过Selenium WebDriver执行自动化时网页文档何时完成加载。
将IJavaScriptExecutor.ExecuteScript()与WebDriverWait()一起使用已被证明非常有用。
我首先等待文件告诉我它已加载:
.ExecuteScript("return document.readyState == 'complete'");
我接下来等待所有AJAX库(如jQuery和Dojo)告诉我他们处于非活动状态:
.ExecuteScript("return jQuery.active == '0'");
.ExecuteScript("return Ajax.activeRequestCount == '0'");
.ExecuteScript("return dojo.io.XMLHTTPTransport.inFlight.length == '0'");
此时我仍然注意到在ajax检查开始之前加载的东西,仍在运行(屏幕上的微调器用数据行填充表格等)。我跟踪了其中一个,并在下面放了一个粗略的调用堆栈。
除了等待元素存在之外还有什么方法可以智能地告诉这个(.asmx)Web服务何时完成?它来自ASP.NET应用程序,并通过生成的代理类调用Web方法。我还可以看到访问Sys.Net的客户端代码,如果这有助于或可以用于进行某些检测。
// Target Web Page
// called from a script tag at the ending body tag
$("#@fillArea").bind({
"select_node.jstree": function (e, data) {
setTimeout(function() {
FillList();
}, 1);
return true;
}
});
// web service called by FillList()
Abc.Api.MyService.Fill(listParams, onFillSuccess, onFailure, param);
// web service code for Fill()
[WebService(Namespace = "http://abc.alphabet.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1]
[ScriptService]
public class ListService
{
[WebMethod(EnableSession = true)]
[ScriptMethod(UseHttpGet = true)]
public string Fill(ListParams listParams)
{
// get database data
// return html markup
}
}
已编辑:一个解决方案发现了如何检测Microsoft AJAX Library的AJAX流量
在document.ready =='完成'
之后,会立即插入以下代码来为其添加事件。((IJavaScriptExecutor)driver).ExecuteScript
(
@"MsftAjaxRequestCount = 0;
Sys.Net.WebRequestManager.add_invokingRequest
(
function onInvoke(sender, args)
{
MsftAjaxRequestCount++;
}
);
Sys.Net.WebRequestManager.add_completedRequest
(
function onComplete(sender, args)
{
MsftAjaxRequestCount--;
}
);"
);
以下代码检查是否插入了这个新变量的值以及另一个检查其他AJAX库的
.ExecuteScript("return MsftAjaxRequestCount == '0'");
这很有效。但是有一个轻微的竞争条件。有时,事件接线很晚,事件不会被触发,或者导致值变为-1。这是因为Selenium Webdriver的GotoUrl()在document.readyState完成之前不会返回。
GotoUrl()可以在完成之前异步返回以尽早连接事件吗?关于这个的任何其他想法?
答案 0 :(得分:0)
OP回答了大部分OP问题。答案将根据AJAX库的使用情况而有所不同。
要以不同的速度(document.readyState ==加载或交互或完成)从GotoUrl()返回,可以使用Selenium页面加载策略。 "正常"当"完成","渴望"时返回当"互动"时返回和"无"马上回来。
使用C#的FireFox驱动程序的示例如下所示。
var profile = new FireFoxProfile();
profile.SetPreference("webdriver.load.strategy", "eager");
var driver = new FireFoxDriver(profile);