Aquí está mi intento de una solución completamente genérica, en Python:
Primero, una función genérica de "espera" (use un WebDriverWait si lo desea, los encuentro feos):
def wait_for(condition_function):
start_time = time.time()
while time.time() < start_time + 3:
if condition_function():
return True
else:
time.sleep(0.1)
raise Exception('Timeout waiting for {}'.format(condition_function.__name__))
Luego, la solución se basa en el hecho de que el selenio registra un número de identificación (interno) para todos los elementos de una página, incluido el <html>
elemento de nivel superior . Cuando una página se actualiza o carga, obtiene un nuevo elemento html con una nueva ID.
Entonces, suponiendo que desea hacer clic en un enlace con el texto "mi enlace", por ejemplo:
old_page = browser.find_element_by_tag_name('html')
browser.find_element_by_link_text('my link').click()
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
Para obtener más ayuda Pythonic, reutilizable, genérica, puede hacer un administrador de contexto:
from contextlib import contextmanager
@contextmanager
def wait_for_page_load(browser):
old_page = browser.find_element_by_tag_name('html')
yield
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
Y luego puede usarlo en casi cualquier interacción de selenio:
with wait_for_page_load(browser):
browser.find_element_by_link_text('my link').click()
Creo que es a prueba de balas! ¿Qué piensas?
Más información en una publicación de blog al respecto aquí