2012-08-27 22 views
31

Tengo una página web con un iframe. Me gustaría acceder al contenido del iframe usando CasperJS. En particular, necesito hacer clic en los botones y completar un formulario. ¿Cómo puedo hacer eso?¿Cómo accedo a un iframe de CasperJS?

La página web principal es main.html:

<html><body> 
<a id='main-a' href="javascript:console.log('pressed main-a');">main-a</a> 
<iframe src="iframe.html"></iframe> 
<a id='main-b' href="javascript:console.log('pressed main-b');">main-b</a> 
</body></html> 

El marco flotante es:

<html><body> 
<a id='iframe-c' href="javascript:console.log('pressed iframe-c');">iframe-c</a> 
</body></html> 

Mi enfoque ingenuo:

var casper = require('casper').create({ 
    verbose: true, 
    logLevel: "debug" 
}); 

casper.start("http://jim.sh/~jim/tmp/casper/main.html", function() { 
    this.click('a#main-a'); 
    this.click('a#main-b'); 
    this.click('a#iframe-c'); 
}); 

casper.run(function() { 
    this.exit(); 
}); 

no funciona, por supuesto, debido a que la El selector a#iframe-c no es válido en el marco principal:

[info] [phantom] Starting... 
[info] [phantom] Running suite: 2 steps 
[debug] [phantom] opening url: http://jim.sh/~jim/tmp/casper/main.html, HTTP GET 
[debug] [phantom] Navigation requested: url=http://jim.sh/~jim/tmp/casper/main.html, type=Other, lock=true, isMainFrame=true 
[debug] [phantom] url changed to "http://jim.sh/~jim/tmp/casper/main.html" 
[debug] [phantom] Navigation requested: url=http://jim.sh/~jim/tmp/casper/iframe.html, type=Other, lock=true, isMainFrame=false 
[debug] [phantom] Successfully injected Casper client-side utilities 
[info] [phantom] Step 2/2 http://jim.sh/~jim/tmp/casper/main.html (HTTP 200) 
[debug] [phantom] Mouse event 'click' on selector: a#main-a 
[info] [remote] pressed main-a 
[debug] [phantom] Mouse event 'click' on selector: a#main-b 
[info] [remote] pressed main-b 
[debug] [phantom] Mouse event 'click' on selector: a#iframe-c 
FAIL CasperError: Cannot dispatch click event on nonexistent selector: a#iframe-c 
# type: uncaughtError 
# error: "CasperError: Cannot dispatch click event on nonexistent selector: a#iframe-c" 
CasperError: Cannot dispatch click event on nonexistent selector: a#iframe-c  
    /tmp:901 in mouseEvent 
    /tmp:365 in click 
    /tmp/test.js:9 
    /tmp:1103 in runStep 
    /tmp:324 in checkStep 

¿Hay alguna manera de hacer esto? Un truco que implique meterse en phantomjs directamente estaría bien, pero no sé qué hacer allí.

Estoy usando CasperJS versión 1.0.0-RC1 y phantomjs versión 1.6.0.

Respuesta

40

Pasé por siempre buscando esto, y por supuesto encontré la respuesta minutos después de publicar la pregunta.

Puedo usar los nuevos comandos de cambio de cuadro agregados a phantomjs en this commit. Específicamente, las funciones this.page.switchToChildFrame(0) y this.page.switchToParentFrame(). Parece ser indocumentado, y también parece que los métodos han sido changed para los próximos lanzamientos, pero funciona:

var casper = require('casper').create({ 
    verbose: true, 
    logLevel: "debug" 
}); 

casper.start("http://jim.sh/~jim/tmp/casper/main.html", function() { 
    this.click('a#main-a'); 
    this.click('a#main-b'); 
    this.page.switchToChildFrame(0); 
    this.click('a#iframe-c'); 
    this.page.switchToParentFrame(); 
}); 

casper.run(function() { 
    this.exit(); 
}); 
+0

Jim, ¿sabía usted si puede esto.test.assertVisible ('# someElemInsideIframe') después de cambiar? Parece barf para mí, pero this.click (...) funciona. –

+0

No lo siento, lo siento. La visibilidad puede ser probada de alguna otra manera que no funciona bien con los marcos, no estoy seguro. –

+1

¿Has visto la respuesta de @ olleolleolle? withFrame es un método documentado. –

4

Como cuestión de hecho, usted tendrá que utilizar la nueva característica --web-security=no proporcionada por Phantomjs 1.5 con el fin de poder acceder a los iFrames y sus contenidos.

+1

No muy relacionado - este ejemplo es un iframe del mismo dominio y la seguridad entre dominios no es mi problema. Vea mi propia respuesta para saber qué funcionó ('--web-security = no' aún no se requiere allí). –

35

Desde 1.0 se puede utilizar withFrame

casper.open("http://www.example.com/page.html", function() { 
    casper.withFrame('flashHolder', function() { 
     this.test.assertSelectorExists('#the-flash-thing', 'Should show Flash'); 
    }); 
    }); 
+0

¿Cómo podría funcionar esto con marcos que tienen nombres dinámicos? No puedo confiar en el índice de fotogramas (por ejemplo, 0 o 1) porque los servicios sociales como Twitter (a través de addthis) a menudo cargan en sus propios iframes en segundo plano. – DynamicDan

+0

puede usar el índice de fotogramas en lugar del nombre del fotograma - http://docs.casperjs.org/en/latest/modules/casper.html#withframe –

3

Supongamos que tenemos diferentes marcos (frame1 y frame2) y tenemos que acceder a diferentes elementos (como hacer clic o verificar si la etiqueta div sale o no) de esos fotogramas.

casper.withFrame('frame1', function() { 
    var file = '//*[@id="profile_file"]'; 
    casper.thenClick(x(file)); 
}); 

casper.withFrame('frame2', function() { 
    casper.then(function() { 
    casper.waitForSelector('#pageDIV', 
      function pass() { 
       console.log("pass"); 
      }, 
      function fail(){ 
       console.log("fail"); 
      } 
    ); 
    }); 
}); 
Cuestiones relacionadas