travist / jquery.go.js

An easy-to-use web testing and automation tool that uses the jQuery interface within Node.js to interact with the Phantom.js browser.
MIT License
150 stars 35 forks source link

Undefined result when retrieving the document object #28

Open obihill opened 9 years ago

obihill commented 9 years ago

I'm having a bit of trouble accessing the document object.

When I run the code below:

var $ = require('jquerygo');

$.visit('https://www.google.com', function(){
  $.waitForPage(function(){
    $.getPage(function(page) {
      page.evaluate(function(args) {

        // Just return the passed in params.
        return document.title;
      }, function(err, retVal) {

        // Called when you return from the evaluation.
        console.log(retVal);
        $.close();
      }, {
        hello: 'HELLO THERE!!!'
      });
    });
  });
});

I get undefined as the result, instead of the page title.

However, the following using phantomjs:

var page = require('webpage').create();
var url = 'http://www.restive.io';
page.open(url, function(status) {
  var title = page.evaluate(function() {
    return document.title;
  });
  console.log('Page title is ' + title);
  phantom.exit();
});

I get the proper result.

Any idea why this is happening?

balmasi commented 9 years ago

@obihill can you check something?

Does the document.title exist before in your first evaluate function block?

obihill commented 9 years ago

Hi Borna,

I tried to see how to get things to work, but did not succeed. I also didn't receive any response here so I gave up on JqueryGo and instead tried to see how else to use JQuery with PhantomJS. I was able to find a solution.

Below is a template you can use.

var page = require('webpage').create();
var args = require('system').args;
var url_str = 'http://'+args[1];

/**
 * Set the viewport size (if you need to)
 */
page.viewportSize = {
    width: 320,
    height: 480
};

/**
 * Sets the User Agent (if you need to)
 */
page.settings.userAgent = 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7';

/**
 * From PhantomJS documentation:
 * This callback is invoked when there is a JavaScript console. The callback may accept up to three arguments:
 * the string for the message, the line number, and the source identifier.
 */
page.onConsoleMessage = function (msg, line, source) {
    console.log('console> ' + msg);
};

/**
 * From PhantomJS documentation:
 * This callback is invoked when there is a JavaScript alert. The only argument passed to the callback is the string for the message.
 */
page.onAlert = function (msg) {
    console.log('alert!!> ' + msg);
};

/**
 * Open the web page
 */
page.open(url_str, function(status) {
    if (status === 'success') {
        page.injectJs('https://code.jquery.com/jquery-1.11.2.min.js');

        // Our "event loop"
        if(!phantom.state)
        {
            //ADD YOUR JAVASCRIPT/JQUERY CODE HERE!!!
        }
        else {
            phantom.state();
        }
    }

    phantom.exit();
});

Save your code in a .js file, and then run it using the following command:

phantomjs your_file.js your_url

Note: The url you provide should not include http:// as this is already taken care of in the script. You can of course update the script if you need to specify a different scheme like https://.

When using this approach, I have full access to document and also functions that didn't seem to work for me in JQueryGo, like find().

Try this out and see if it works for you.

travist commented 9 years ago

I appreciate your input @obihill . I will say that the jQuery interface is an abstraction of the actual jQuery features and instead of returning a DOM object (which would require a JavaScript DOM engine like jsdom), it returns a reference ID that is then used to identify that DOM object when operations are performed from within node.js. If you want an actual DOM object, then that may be harder to do within NodeJS without using JSDOM or the like, which would not be PhantomJS.