2012-08-27 18 views
31

Tôi có trang web có khung nội tuyến. Tôi muốn truy cập nội dung của khung nội tuyến bằng cách sử dụng CasperJS. Đặc biệt, tôi cần phải bấm vào nút và điền vào một mẫu đơn. Làm thế nào tôi có thể làm điều đó?Làm cách nào để truy cập iframe từ CasperJS?

Trang web chính là 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> 

Iframe là:

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

cách tiếp cận ngây thơ của tôi:

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

Không làm việc, tất nhiên, bởi vì Bộ chọn a#iframe-c không hợp lệ trong khung chính:

[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ó cách nào để thực hiện công việc này không? Một vụ hack liên quan đến việc chọc vào các phantomj trực tiếp sẽ là tốt, nhưng tôi không biết phải làm gì ở đó.

Tôi đang sử dụng phiên bản CasperJS phiên bản 1.0.0-RC1 và phiên bản phantomjs 1.6.0.

Trả lời

40

Đã không ngừng tìm kiếm điều này và tất nhiên tôi đã tìm thấy phút trả lời sau khi đăng câu hỏi.

Tôi có thể sử dụng các lệnh chuyển đổi khung hình mới được thêm vào phantomjs trong this commit. Cụ thể, các hàm this.page.switchToChildFrame(0)this.page.switchToParentFrame(). Có vẻ không có cơ sở, và nó cũng có vẻ như các phương pháp đã được changed cho sắp tới phát hành, nhưng nó làm việc:

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, bạn có biết liệu bạn có thể this.test.assertVisible ('# someElemInsideIframe') sau khi chuyển đổi không? Dường như để barf cho tôi nhưng this.click (...) hoạt động. –

+0

Tôi không, xin lỗi. Khả năng hiển thị có thể được kiểm tra theo cách khác không hoạt động tốt với khung, tôi không chắc chắn. –

+1

Bạn có thấy câu trả lời của @ olleolleolle không? withFrame là một phương pháp được ghi lại. –

4

Như một vấn đề của thực tế, bạn sẽ phải sử dụng các tính năng mới --web-security=no cung cấp bởi Phantomjs 1.5 để có thể truy cập những iFrames và nội dung của họ.

+1

Không thực sự liên quan - ví dụ này là một iframe cùng tên miền và bảo mật tên miền chéo không phải là vấn đề của tôi. Xem câu trả lời của riêng tôi cho những gì đã làm việc ('- web-security = no' vẫn không được yêu cầu ở đó). –

35

Từ 1.0, bạn có thể sử dụng withFrame

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

Làm cách nào điều này có thể hoạt động với các khung có tên động? Tôi không thể dựa vào chỉ mục khung (ví dụ 0 hoặc 1) thay vì các dịch vụ xã hội như twitter (thông qua addthis) thường tải trong iframe riêng của chúng trong nền. – DynamicDan

+0

bạn có thể sử dụng chỉ mục khung thay vì tên khung - http://docs.casperjs.org/en/latest/modules/casper.html#withframe –

3

Giả sử chúng ta có khung khác nhau (frame 1 và frame2) và chúng tôi phải truy cập các yếu tố khác nhau (như nhấp hoặc kiểm tra xem thẻ div có thoát hay không) của các khung đó.

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