Here it is. (It seems that IEBrowserBot uses the same method as KonquerorBrowserBot.)
/**
* For Konqueror (and Safari), we can't catch the onload event for a separate window (as opposed to an IFrame)
* So we set up a polling timer that will keep checking the readyState of the document until it's complete.
* Since we might call this before the original page is unloaded, we check to see that the completed document
* is different from the original one.
*/
KonquerorBrowserBot.prototype.pollForLoad = function(loadFunction, windowObject, originalDocument) {
if (windowObject.closed) {
return;
}
var sameDoc = (originalDocument === windowObject.document);
var rs = windowObject.document.readyState;
if (!sameDoc && rs == 'complete') {
LOG.debug("pollForLoad complete: " + rs + " (" + sameDoc + ")");
loadFunction();
return;
}
var self = this;
LOG.debug("pollForLoad continue");
window.setTimeout(function() {self.pollForLoad(loadFunction, windowObject, originalDocument);}, 500);
};
BTW, i have a question. How to set myself up to view the logs? Also, is this a recursive poller? Also, we are seeing this hang, but shouldn't setTimeout cause a timeout after 1/2 a second?
I thought i would share the related code from Watir. It's ugly, but the great thing about Watir is that it is used mostly by testers who don't know what bad code looks like. Oh. Did i say that? Anyhow, you can ignore all the code about spinners (which we don't really use anymore) and frames (which Selenium doesn't support anyhow). You might also note that we actually time the time it takes to download and store it. (Marick actually blogged about this recently, showing how to add this feature, not realizing that we already had it.) As an aside, it might be cool for Selenium to measure download times and post them to the results.
# This method is used internally to cause an execution to stop until the page has loaded in Internet Explorer.
def wait(no_sleep = false)
begin
@down_load_time=0
pageLoadStart = Time.now
@pageHasReloaded= false
s= Spinner.new(@enable_spinner)
while @ie.busy
@pageHasReloaded = true
sleep 0.02
s.spin
end
s.reverse
log "wait: readystate=" + @ie.readyState.to_s
until @ie.readyState == READYSTATE_COMPLETE
@pageHasReloaded = true
sleep 0.02
s.spin
end
sleep 0.02
until @ie.document.readyState == "complete"
sleep 0.02
s.spin
end
if @ie.document.frames.length > 1
begin
0.upto @ie.document.frames.length-1 do |i|
until @ie.document.frames[i.to_s].document.readyState == "complete"
sleep 0.02
s.spin
end
@url_list << @ie.document.frames[i.to_s].document.url unless url_list.include?(@ie.document.frames[i.to_s].document.url)
end
rescue=>e
#puts 'Setting rexmlDomobject to nil'. Used for finding element using xpath.
@rexmlDomobject = nil
@logger.warn 'frame error in wait' +e.to_s + "\n" + e.backtrace.join("\n")
end
else
@url_list << @ie.document.url unless @url_list.include?(@ie.document.url)
end
@down_load_time = Time.now - pageLoadStart
run_error_checks
print "\b" unless @enable_spinner == false
s=nil
#Variables used for supporting xpath queries.
#puts 'Setting rexmlDomobject to nil'
@rexmlDomobject = nil
rescue WIN32OLERuntimeError => e
@logger.info "runtime error in wait: #{e}\n#{e.backtrace.join("\\\n")}"
end
sleep 0.01
sleep @defaultSleepTime unless no_sleep == true
end
It never assumes (like the Selenium code) that a new page is being loaded. Rather it simply tests three states: browser.busy, browser.readyState and document.readyState. Note that we also wait 0.02 seconds before polling the final item (document.readyState). This is to make sure the page load has had a chance to start. I know it sounds hokey, but it works.
I'm not sure whether all these states are all accessible via _javascript_. (We use COM in Watir).
Anyhow, i'm not sure of what our next step needs to be. We're only using IE, so we aren't so concerned about the cross-browser issues. But my Watir experience also leads me to think that polling can be reliable -- we don't need to depend on events, even if that is theoretically a better idea. Two ideas really, then:
1. Change the Selenium polling algorithm to be more like Watir. Don't have it care whether the document is new or not.
2. Add a timeout, so that after a certain period it returns automatically (with a timeout error).
Another idea would be to blend the two ideas. Essentially put a timeout on the idea that the document must be different. After x seconds, just make sure that the document readystate is complete.
What do you think?
Bret
_______________________________________________ Selenium-devel mailing list [email protected] http://lists.public.thoughtworks.org/mailman/listinfo/selenium-devel
