We ended up writing a layer over selenium that handled this scenario by wrapping the calls in an optional loop. So when you d do:
@browser.click "#my_button_id"
it would do something similar to what AutomatedTester suggested above:
class Browser
def click(locator)
wait_for_element(locator, :timeout => PAGE_EVENT_TIMEOUT)
@selenium.click(locator)
end
def wait_for_element(locator, options)
timeout = options[:timeout] || PAGE_LOAD_TIMEOUT
selenium_locator = locator.clone
expression = <<EOF
var element;
try {
element = selenium.browserbot.findElement( #{selenium_locator} );
} catch(e) {
element = null;
};
element != null;
EOF
begin
selenium.wait_for_condition(expression, timeout)
rescue ::Selenium::SeleniumException
raise "Couldn t find element with locator #{locator} on the page: #{$!}.
The locator passed to selenium was #{selenium_locator} "
end
end
end
the wrapper also did other things, like allowing to search by the button/input label etc. (so the wrapper didn t only exist for the timing issues, this was just one of the things we put in there.)