I am using Selenium WebDriver for crawling a web site(only for example, I will be crawling other web sites too!) which has infinite scroll.
Problem statement:
For web pages with Ajax Response during the infinite scroll and using jQuery API(or other actions), before starting to opening the web page.
//Inject the pooling status variable
js.executeScript("window.status = 'fail';");
//Attach the Ajax call back method
js.executeScript( "$(document).ajaxComplete(function() {" +
"status = 'success';});");
Step 1: will remain the same as in the original question
Step 2 Pooling the following script(This is the one which removes the need of Thread.Sleep()
and makes the logic more dynamic)
String aStatus = (String)js.executeScript("return status;");
if(aStatus!=null && aStatus.equalsIgnoreCase("success")){
js.executeScript("status = 'fail';");
break poolingLoop;
}
Step 3: No need now!
Conclusion: No need to give blunt Thread.sleep(); again and again while using Selenium WebDriver!!
This approach works good only if there's jQuery api being used in the web application.
EDIT: As per the the link given by @jayati i injected the javascript-
Javascript one:
//XMLHttpRequest instrumentation/wrapping
var startTracing = function (onnew) {
var OldXHR = window.XMLHttpRequest;
// create a wrapper object that has the same interfaces as a regular XMLHttpRequest object
// see http://www.xulplanet.com/references/objref/XMLHttpRequest.html for reference on XHR object
var NewXHR = function() {
var self = this;
var actualXHR = new OldXHR();
// private callbacks (for UI):
// onopen, onsend, onsetrequestheader, onupdate, ...
this.requestHeaders = "";
this.requestBody = "";
// emulate methods from regular XMLHttpRequest object
this.open = function(a, b, c, d, e) {
self.openMethod = a.toUpperCase();
self.openURL = b;
ajaxRequestStarted = 'open';
if (self.onopen != null && typeof(self.onopen) == "function") {
self.onopen(a,b,c,d,e); }
return actualXHR.open(a,b,c,d,e);
}
this.send = function(a) {
ajaxRequestStarted = 'send';
if (self.onsend != null && typeof(this.onsend) == "function") {
self.onsend(a); }
self.requestBody += a;
return actualXHR.send(a);
}
this.setRequestHeader = function(a, b) {
if (self.onsetrequestheader != null && typeof(self.onsetrequestheader) == "function") { self.onsetrequestheader(a, b); }
self.requestHeaders += a + ":" + b + "\r\n";
return actualXHR.setRequestHeader(a, b);
}
this.getRequestHeader = function() {
return actualXHR.getRequestHeader();
}
this.getResponseHeader = function(a) { return actualXHR.getResponseHeader(a); }
this.getAllResponseHeaders = function() { return actualXHR.getAllResponseHeaders(); }
this.abort = function() { return actualXHR.abort(); }
this.addEventListener = function(a, b, c) { return actualXHR.addEventListener(a, b, c); }
this.dispatchEvent = function(e) { return actualXHR.dispatchEvent(e); }
this.openRequest = function(a, b, c, d, e) { return actualXHR.openRequest(a, b, c, d, e); }
this.overrideMimeType = function(e) { return actualXHR.overrideMimeType(e); }
this.removeEventListener = function(a, b, c) { return actualXHR.removeEventListener(a, b, c); }
// copy the values from actualXHR back onto self
function copyState() {
// copy properties back from the actual XHR to the wrapper
try {
self.readyState = actualXHR.readyState;
} catch (e) {}
try {
self.status = actualXHR.status;
} catch (e) {}
try {
self.responseText = actualXHR.responseText;
} catch (e) {}
try {
self.statusText = actualXHR.statusText;
} catch (e) {}
try {
self.responseXML = actualXHR.responseXML;
} catch (e) {}
}
// emulate callbacks from regular XMLHttpRequest object
actualXHR.onreadystatechange = function() {
copyState();
try {
if (self.onupdate != null && typeof(self.onupdate) == "function") { self.onupdate(); }
} catch (e) {}
// onreadystatechange callback
if (self.onreadystatechange != null && typeof(self.onreadystatechange) == "function") { return self.onreadystatechange(); }
}
actualXHR.onerror = function(e) {
ajaxRequestComplete = 'err';
copyState();
try {
if (self.onupdate != null && typeof(self.onupdate) == "function") { self.onupdate(); }
} catch (e) {}
if (self.onerror != null && typeof(self.onerror) == "function") {
return self.onerror(e);
} else if (self.onreadystatechange != null && typeof(self.onreadystatechange) == "function") {
return self.onreadystatechange();
}
}
actualXHR.onload = function(e) {
ajaxRequestComplete = 'loaded';
copyState();
try {
if (self.onupdate != null && typeof(self.onupdate) == "function") { self.onupdate(); }
} catch (e) {}
if (self.onload != null && typeof(self.onload) == "function") {
return self.onload(e);
} else if (self.onreadystatechange != null && typeof(self.onreadystatechange) == "function") {
return self.onreadystatechange();
}
}
actualXHR.onprogress = function(e) {
copyState();
try {
if (self.onupdate != null && typeof(self.onupdate) == "function") { self.onupdate(); }
} catch (e) {}
if (self.onprogress != null && typeof(self.onprogress) == "function") {
return self.onprogress(e);
} else if (self.onreadystatechange != null && typeof(self.onreadystatechange) == "function") {
return self.onreadystatechange();
}
}
if (onnew && typeof(onnew) == "function") { onnew(this); }
}
window.XMLHttpRequest = NewXHR;
}
window.ajaxRequestComplete = 'no';//Make as a global javascript variable
window.ajaxRequestStarted = 'no';
startTracing();
Or Javascript Two:
var startTracing = function (onnew) {
window.ajaxRequestComplete = 'no';//Make as a global javascript variable
window.ajaxRequestStarted = 'no';
XMLHttpRequest.prototype.uniqueID = function() {
if (!this.uniqueIDMemo) {
this.uniqueIDMemo = Math.floor(Math.random() * 1000);
}
return this.uniqueIDMemo;
}
XMLHttpRequest.prototype.oldOpen = XMLHttpRequest.prototype.open;
var newOpen = function(method, url, async, user, password) {
ajaxRequestStarted = 'open';
/*alert(ajaxRequestStarted);*/
this.oldOpen(method, url, async, user, password);
}
XMLHttpRequest.prototype.open = newOpen;
XMLHttpRequest.prototype.oldSend = XMLHttpRequest.prototype.send;
var newSend = function(a) {
var xhr = this;
var onload = function() {
ajaxRequestComplete = 'loaded';
/*alert(ajaxRequestComplete);*/
};
var onerror = function( ) {
ajaxRequestComplete = 'Err';
/*alert(ajaxRequestComplete);*/
};
xhr.addEventListener("load", onload, false);
xhr.addEventListener("error", onerror, false);
xhr.oldSend(a);
}
XMLHttpRequest.prototype.send = newSend;
}
startTracing();
And checking the status of the status vars ajaxRequestStarted, ajaxRequestComplete
in the java code, one can determine if the ajax was started or completed.
Now I have a way to wait till an Ajax is complete, I can also find if the Ajax was triggered on some action