2016-07-08 3 views
0

나는 헤드리스 브라우저 (PhantomJS)와 모든 DOM 탐색 및 가능한 작업 (다운로드 제외)이 필요한 자동화 된 테스트 스크립트에서 작업하고 있습니다. PhantomJS가 맞아야합니다.PhantomJS를 사용하는 jQuery 버그

그러나 나는 다음과 같은 오류로 자바 스크립트와 jQuery PhantomJS를 사용할 수 없습니다

var page = require('webpage').create(); 
page.open('http://mywebsite.com/', function() { 
    function dothat() { 
     console.log('0 started'); 
     $('#id').children().eq(0).click(); 
     console.log('0 finished'); 
     return main(1, 0); 
    } 
} 
dothat() 

다음은 스크립트는 '0 시작'중지합니다. 내가로드 한 페이지는 jQuery를 사용하므로 다시 다운로드 할 필요가 없습니다. 그럼에도 불구하고 그것을 로딩 해보자.

var page = require('webpage').create(); 
page.open('http://mywebsite.com/', function() { 
    page.injectJs('jquery-2.2.1.min.js'); 
    function dothat() { 
     console.log('0 started'); 
     $('#id').children().eq(0).click(); 
     console.log('0 finished'); 
     return main(1, 0); 
    } 
} 
dothat() 

그래, 난 같은 디렉토리에 파일을 로컬로 가지고 ... 이 그리고 그것은 (매우 fastly) 그 오류를 보여줍니다 당신이 그 문제를 해결하는 일을 제안하는 일

TypeError: undefined is not a constructor (evaluating 'jQuery.easing[jQuery.easing.def](t,e,n,i,a)') 

? PhantomJS의 내부 버그입니까? 그렇기 때문에 우분투에서 Firefox 및 Xvfb를 사용해보아야합니까? 아니면 어딘가에서 내 오류가 있습니까? 처음에는 전체 non-jQuery 버전으로 코드를 변경하려고했지만 클래스가있는 선택기가 필요하고 일부 객체를 클릭해야했습니다 ...

해결책을 가르쳐 주셔서 대단히 감사합니다!

편집 1 : 첫 번째 대답에서 이해 한 내용에 따라 변경했습니다. 이제 콘솔에서 아무것도 인쇄하지 않습니다.

var page = require('webpage').create(); 
page.onConsoleMessage = function(msg, lineNum, sourceId) { 
    console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")'); 
}; 
page.open('http://mywebsite.com/', function() { 
    page.injectJs('jquery-2.2.1.min.js'); 
    var result = page.evaluate(function() { 
     function dothat() { 
      console.log('0 started'); 
      $('#id').children().eq(0).click(); 
      console.log('0 finished'); 
      return main(1, 0); 
     } 
     function main(x, y) { 
      if (x === 0) { 
       return setTimeout(dothat(), y); 
      } else if (x === 1) { 
       return setTimeout(dothis(), y); 
      } 
     } 
     return main(0, 5000); //first launch 
    } 
}); 

나는 그것이 당신이 지적한 것이 었는지 확신하지 못합니다.

EDIT 2 : google.com에서 로그인해야하는 실제 스크립트입니다. 그러나 스크립트가 의도 한대로 작동하지 않습니다. 아래를 참조하십시오.

var page = require('webpage').create(); 
page.onConsoleMessage = function(msg) { 
    console.log('CONSOLE: ' + msg); 
}; 
page.open('https://google.com/', function() { 
    page.injectJs('jquery-2.2.1.min.js'); 
    page.evaluate(function() { 
     function dofirst() { 
      $('#gb_70').click(); 
      return main(1, 0); 
     } 
     function dosecond() { 
      document.getElementById('Email').value = '[email protected]'; 
      $('#next').click(); 
      return main(2, 0); 
     } 
     function dothird() { 
      document.getElementById('Passwd').value = 'mypwd'; 
      $('#signIn').click(); 
     } 
     function main(i, j) { 
      if (i === 0) { 
       console.log('launching 0'); 
       return setTimeout(dofirst(), j); // connections 
      } 
      else if (i === 1) { 
       console.log('launching 1'); 
       return setTimeout(dosecond(), 5000); 
      } 
      else if (i === 2) { 
       console.log('launching 2'); 
       return setTimeout(dothird(), 5000); 
      } 
     } 
     return main(0, 5000); 
    }); 
}); 

자세히 알 수 있듯이 main은 내가 지연 단계에 사용하는 기능입니다.

TypeError: null is not an object (evaluating 'document.getElementById('Email').value = '[email protected]'') 

    undefined:7 in dosecond 
    :22 in main 
    :4 in dofirst 
    :18 in main 
    :29 
    :30 

저를 도우려고 유지 주셔서 감사합니다 : 코드가 작동하고 나에게이 오류 (또는 그)를 반환하지 않습니다 그러나 !

+0

doThat()은 비공개이므로 ' – dandavis

+0

'은 실패 할 수 있지만 실제 사례는 아닙니다. –

답변

0

다른 방법으로하지 않으시겠습니까? PhantomJS에서

function dothat() { 
    console.log('0 started'); 
    $('#id').children().eq(0).click(); 
    console.log('0 finished'); 
    return main(1, 0); 
} 

var page = require('webpage').create(); 
page.open('http://mywebsite.com/', dothat) 
+0

특별히 없습니다. 이제 @Vaviloff의 아주 좋은 답변으로 시간이 지남에 따라 코드가 크게 향상되었지만 여전히 작동하지 않습니다. 지금까지는 작동 코드가 아니라고 확신합니다! –

1

은 항상 함수와 변수가 존재하는 두 개의 javascirpt 컨텍스트있다 :

  1. PhantomJS 컨텍스트를
  2. 오픈 페이지 문맥 그들은 서로를 인식하지 못합니다과 그렇지 않은

교차하다!

PhantomJS는 대상 페이지 개체 또는 DOM에 액세스 할 수 없기 때문에 $('#id').children().eq(0).click();이 작동하지 않습니다. PhantomJS 스크립트에는 jQuery가없고 DOM 요소가 없습니다. 두 번째 상황, 즉 sandbox에 있습니다.

페이지에서 무엇인가를하려면 텔레포트 코드를 정렬해야합니다.그것은 page.evaluate() 방법의 도움으로 이루어집니다. 샌드 박스 페이지 문맥에서 콘솔 메시지를 receieve하는

var page = require('webpage').create(); 
page.open('http://mywebsite.com/', function() { 
    page.injectJs('jquery-2.2.1.min.js'); 
    var result = page.evaluate(function(){ 

     // You can certainly use functions 
     // Be sure to declare them also 
     // inside of page.evaluate 
     function dothat() { 
      console.log('0 started'); 
      $('#id').children().eq(0).click(); 
      console.log('0 finished'); 
      return main(1, 0); 
     } 

     // Important: don't forget to return result 
     // back to PhantomJS main context 
     return dothat(); 
    }); 
}); 

참고하면 page.onConsoleMessage 콜백을 통해 그들에 가입해야합니다

page.onConsoleMessage = function(msg, lineNum, sourceId) { 
    console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")'); 
}; 

EDIT 1 후 : 내 나쁜, 나는 브라켓 편집을 잃었습니다 PhantomJS v2.x가 불평하지 않는다는 사실을 문법 오류로 이끌었던 당신의 예 (위의 내용)는 단지 조용히 그곳에 매달릴 것입니다. 그게 당신이 콘솔 메시지가 없다고 착각 한 것입니다. v1.9.8에서 구문 오류를 먼저 테스트하거나 구문 강조 표시가있는 일부 IDE에서 스크립트를 테스트하는 데 유용 할 수 있습니다.

var page = require('webpage').create(); 
page.onConsoleMessage = function(msg, lineNum, sourceId) { 
    console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")'); 
}; 
page.open('http://mywebsite.com/', function() { 
    page.injectJs('jquery-2.2.1.min.js'); 
    var result = page.evaluate(function() { 
     function dothat() { 
      console.log('0 started'); 
      $('#id').children().eq(0).click(); 
      console.log('0 finished'); 
      return main(1, 0); 
     } 
     function main(x, y) { 
      if (x === 0) { 
       return setTimeout(dothat(), y); 
      } else if (x === 1) { 
       return setTimeout(dothis(), y); 
      } 
     } 
     return main(0, 5000); //first launch 
    }); // 
}); 

참고 : inextistent의하는 DoThis에 대해 불평한다() 함수

현재 코드는이 (또한 고정 누락 된 브라켓)을 보일 것입니다.

+0

이제 콘솔에 아무것도 인쇄하지 않습니다. 편집보기 –

+0

이제는 문제가 인쇄되지만 문제는 여전히 있습니다. 이제 편집 2에서 실제 코드의 일부를 보여 드리겠습니다. –

+0

죄송합니다. @ JohnDoe는 * for * 코드를 작성할 수 없습니다. 나는 이미 코드에 무엇이 잘못되었는지 (대상 페이지의 DOM을 처리하기 위해 page.evaluate를 사용하지 않음) 당신을 보여 주었기 때문에 EDIT 2는 별도의 질문으로 만들어야한다. – Vaviloff