2012-08-27 9 views
31

Ich habe eine Webseite mit einem iframe. Ich möchte auf den Inhalt des Iframe zugreifen, indem Sie CasperJS verwenden. Insbesondere muss ich auf Schaltflächen klicken und ein Formular ausfüllen. Wie kann ich das machen?Wie greife ich auf einen Iframe von CasperJS zu?

Die Haupt-Webseite ist 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> 

Der iframe ist:

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

Mein naiver Ansatz:

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

funktioniert nicht, natürlich, weil die a#iframe-c Selektor ist nicht im Hauptrahmen gültig:

[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 

Gibt es eine Möglichkeit, dies zu funktionieren? Ein Hack, bei dem man direkt in Phantomjs stochert, wäre in Ordnung, aber ich weiß nicht, was ich dort tun soll.

Ich verwende CasperJS Version 1.0.0-RC1 und Phantomjs Version 1.6.0.

Antwort

40

Ich war immer auf der Suche nach diesem, und natürlich fand ich die Antwort Minuten nach dem Posten der Frage.

Ich kann die neuen Rahmenschaltbefehle verwenden, die Phantomjs in this commit hinzugefügt werden. Genauer gesagt, die this.page.switchToChildFrame(0) und this.page.switchToParentFrame() Funktionen. Es scheint nicht dokumentiert, und es scheint auch, dass die Methoden changed für kommende Releases gewesen sein, aber es funktioniert:

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, wussten Sie zufällig, ob Sie this.test.assetVisible ('# someElemInsideIframe') nach dem Wechsel haben können? Scheint für mich zu barf, aber this.click (...) funktioniert. –

+0

Ich nicht, tut mir leid. Die Sichtbarkeit könnte auf eine andere Weise getestet werden, die mit Frames nicht gut funktioniert, da bin ich mir nicht sicher. –

+1

Haben Sie @ olleolleolle's Antwort gesehen? withFrame ist eine dokumentierte Methode. –

4

Als eine Frage der Tatsache, dass Sie die neue --web-security=no Funktion von Phantomjs 1.5 vorgesehen, um verwenden müssen werden jene iFrames und deren Inhalte zugreifen zu können.

+1

Nicht wirklich verwandt - dieses Beispiel ist ein IfRame der gleichen Domäne und domänenübergreifende Sicherheit ist nicht mein Problem. Siehe meine eigene Antwort für das, was funktioniert hat ('--web-security = no 'ist dort immer noch nicht erforderlich). –

35

Von 1.0 können Sie withFrame

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

Wie könnte das mit Frames funktionieren, die dynamische Namen haben? Ich kann mich nicht auf den Frame-Index verlassen (zB 0 oder 1), weil soziale Dienste wie Twitter (via addthis) oft ihre eigenen iFrames im Hintergrund laden. – DynamicDan

+0

können Sie Frame-Index anstelle von Frame-Namen verwenden - http://docs.casperjs.org/en/latest/modules/casper.html#withframe –

3

Angenommen, wir haben verschiedene Frames verwenden (frame1 und frame2) und wir müssen auf verschiedene Elemente (wie click oder check, ob div tag existiert oder nicht) dieser Frames zugreifen.

Verwandte Themen