2012-08-27 15 views
31

Ho una pagina web con un iframe. Mi piacerebbe accedere al contenuto dell'iframe usando CasperJS. In particolare, ho bisogno di fare clic sui pulsanti e compilare un modulo. Come lo posso fare?Come accedere ad un iframe da CasperJS?

La pagina web principale è 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> 

L'IFRAME è:

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

Il mio approccio 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(); 
}); 

non funziona, ovviamente, perché la Il selettore a#iframe-c non è valido nel frame principale:

[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 

C'è un modo per farlo funzionare? Un trucco che coinvolge direttamente i phantomjs andrebbe bene, ma non so cosa fare lì.

Sto usando CasperJS versione 1.0.0-RC1 e phantomjs versione 1.6.0.

risposta

40

Ho trascorso la perenne ricerca di questo, e ovviamente ho trovato la risposta pochi minuti dopo aver postato la domanda.

Posso usare i nuovi comandi di cambio frame aggiunti a phantomjs in this commit. In particolare, le funzioni this.page.switchToChildFrame(0) e this.page.switchToParentFrame(). Sembra non documentato, e sembra anche che i metodi sono stati changed per le prossime uscite, ma funziona:

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, hai saputo se è possibile this.test.assertVisible ('# someElemInsideIframe') dopo il passaggio? Sembra sfuggire per me, ma this.click (...) funziona. –

+0

Io no, mi dispiace. La visibilità potrebbe essere testata in un altro modo che non funziona bene con i frame, non ne sono sicuro. –

+1

Hai visto la risposta di @ olleolleolle? withFrame è un metodo documentato. –

4

È un dato di fatto che si dovrà utilizzare la nuova funzionalità --web-security=no fornito da Phantomjs 1.5 al fine di essere in grado di accedere a tali iFrames e il loro contenuto.

+1

Non proprio correlato - questo esempio è un iframe dello stesso dominio e la sicurezza tra domini non è un mio problema. Vedere la mia risposta per ciò che ha funzionato ('--web-security = no' non è ancora richiesto). –

35

Da 1.0 è possibile utilizzare withFrame

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

Come può funzionare con frame con nomi dinamici? Non posso fare affidamento sull'indice dei fotogrammi (ad esempio 0 o 1), perché i servizi sociali come Twitter (tramite addthis) spesso caricano i loro iframe in background. – DynamicDan

+0

puoi usare l'indice del frame invece del nome del frame - http://docs.casperjs.org/en/latest/modules/casper.html#withframe –

3

Supponiamo di avere strutture differenti (frame1 e frame2) e dobbiamo accedere a diversi elementi (come fare clic o controllare se il tag div esce o meno) di quei frame.

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"); 
      } 
    ); 
    }); 
}); 
Problemi correlati