HTMLUnit no espera a Javascript

Tengo una página basada en GWT que me gustaría crear una instantánea HTML usando HtmlUnit. La página carga información de Ajax / JavaScript en un producto, por lo que durante aproximadamente 1 segundo hay un mensaje Cargando … y luego aparece el contenido.

El problema es que HtmlUnit no parece capturar la información y todo lo que obtengo es el tramo “Cargando …”.

A continuación, se muestra un código experimental con HtmlUnit en el que trato de darle tiempo suficiente para esperar a que se carguen los datos, pero no parece cambiar nada y aún no puedo capturar los datos cargados por el Javascript de GWT.

WebClient webClient = new WebClient(); webClient.setJavaScriptEnabled(true); webClient.setThrowExceptionOnScriptError(false); webClient.setAjaxController(new NicelyResynchronizingAjaxController()); WebRequest request = new WebRequest(new URL("")); HtmlPage page = webClient.getPage(request); int i = webClient.waitForBackgroundJavaScript(1000); while (i > 0) { i = webClient.waitForBackgroundJavaScript(1000); if (i == 0) { break; } synchronized (page) { System.out.println("wait"); page.wait(500); } } webClient.getAjaxController().processSynchron(page, request, false); System.out.println(page.asXml()); 

Algunas ideas…?

Gracias por responder. De hecho, debería haber informado esto antes de haber encontrado la solución yo mismo. Aparentemente al inicializar WebClient con FF:

 WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6); 

Parece estar funcionando. Al inicializar WebClient con el constructor predeterminado, usa IE7 de manera predeterminada y supongo que FF tiene mejor soporte para Ajax y es el emulador recomendado para usar.

Creo que por defecto NicelyResynchronizingAjaxController solo volverá a NicelyResynchronizingAjaxController las llamadas AJAX que fueron causadas por una acción del usuario, mediante el seguimiento de la cadena desde la que se originó. Quizás el JavaScript generado por GWT está siendo llamado por algún otro hilo que NicelyResynchronizingAjaxController no quiere esperar.

Intenta declarar tu propio AjaxController para sincronizar con todo sin importar el hilo de origen:

 webClient.setAjaxController(new AjaxController(){ @Override public boolean processSynchron(HtmlPage page, WebRequest request, boolean async) { return true; } }); 

Como dice la documentación, waitForBackgroundJavaScript es experimental:

API experimental: ¡Puede cambiarse en la próxima versión y es posible que todavía no funcione a la perfección!

El siguiente enfoque siempre me ha funcionado, independientemente de la BrowserVersion utilizada:

 int tries = 5; // Amount of tries to avoid infinite loop while (tries > 0 && aCondition) { tries--; synchronized(page) { page.wait(2000); // How often to check } } 

Tenga en cuenta que una aCondition es lo que está buscando. P.EJ:

 page.getElementById("loading-text-element").asText().equals("Loading...") 

Ninguna de las soluciones proporcionadas hasta ahora me funcionó. Terminé con la solución de Dan Alvizu + mi propio truco:

 private WebClient webClient = new WebClient(); public void scrapPage() { makeWebClientWaitThroughJavaScriptLoadings(); HtmlPage page = login(); //do something that causes JavaScript loading waitOutLoading(page); } private void makeWebClientWaitThroughJavaScriptLoadings() { webClient.setAjaxController(new AjaxController(){ @Override public boolean processSynchron(HtmlPage page, WebRequest request, boolean async) { return true; } }); } private void waitOutLoading(HtmlPage page) { while(page.asText().contains("Please wait while loading!")){ webClient.waitForBackgroundJavaScript(100); } } 

No hace falta decir: “¡Espere mientras carga!” debe reemplazarse con el texto que se muestre mientras se carga la página. Si no hay texto, tal vez haya una forma de verificar la existencia de algún gif (si se usa). Por supuesto, simplemente podría proporcionar un valor de milisegundos lo suficientemente grande si se siente aventurero.