Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't find variable: page in PhantomJS

I'm beginner in test, both in Unit Test and UI Test

I'm trying to create a UI test for my login page using following code:

console.log("Teste de Login");

var page = require('webpage').create();
page.open('http://localhost/login', function(status) {
    console.log("Page loadeed");

    if(status === "success") {
        page.render('example1.png');
    }

    page.evaluate(function() {
        // $("#numeroUsuario").val("99734167");
        document.getElementById('numeroUsuario').value = "99734167";
        page.render('exampl2.png');

        // $("#formLogin").submit();
        page.render('example3.png');
    });

    phantom.exit();
});

But this code returns the following error:

> phantomjs.exe ./testLogin.js
Teste de Login
Page loadeed
ReferenceError: Can't find variable: page

  phantomjs://webpage.evaluate():4
  phantomjs://webpage.evaluate():8

Where element $("#numeroUsuario") exists. What have I done wrong?

like image 590
Lai32290 Avatar asked Oct 05 '15 17:10

Lai32290


2 Answers

The documentation says the following about the page context (emphasis mine):

The execution is sandboxed, the web page has no access to the phantom object and it can't probe its own setting.

This means that variables defined outside of the page.evaluate() callback function are not accessible inside of it. It also means that this refers to the window object.

You can of course split the page.evaluate() call into multiple calls and move the move the calls that use outer variables in between the page.evaluate() calls like Platinum Azure showed, but this doesn't work if you want to call some PhantomJS function from inside of a callback inside of the page.evaluate() callback.

The solution would be to use the window.callPhantom and page.onCallback pair. This is perfect for asynchronous functions:

var renderId = 0;
page.onCallback = function(data){
    console.log("Callback: " + data.type);
    if (data.type === "exit") {
        phantom.exit();
    } else if (data.type === "render") {
        page.render(data.fname || ("screenshot_" + (renderId++) + ".png"));
    }
};

page.onConsoleMessage = function(msg){
    console.log("remote> " + msg);
};

var getUrl = "http://example.com";
page.open(url, function(){
    page.evaluate(function(getUrl){
        $.get(getUrl, "", function(data){
            console.log(JSON.stringify(data));
            window.callPhantom({ type: "render" });
            window.callPhantom({ type: "exit" });
        });
    }, getUrl);
});

The exit might interfere with the previously triggered render operation. It surely is possible to delay the exit in that case by some fixed amount of time such as half a second:

if (data.type === "exit") {
    setTimeout(function(){
        phantom.exit();
    }, 500);
}

Furthermore it isn't possible to pass the page object into the page context, because only serializable objects can be passed in:

Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.

Closures, functions, DOM nodes, etc. will not work!

like image 82
Artjom B. Avatar answered Oct 30 '22 12:10

Artjom B.


Pretty sure that in a page.evaluate environment, you can't reference anything from the Phantom script.

In your case, you could actually have multiple evaluate calls:

console.log("Teste de Login");

var page = require('webpage').create();
page.open('http://localhost/login', function(status) {
    console.log("Page loadeed");

    if(status === "success") {
        page.render('example1.png');
    }

    page.evaluate(function() {
        // $("#numeroUsuario").val("99734167");
        document.getElementById('numeroUsuario').value = "99734167";
    });

    page.render('exampl2.png');

    page.evaluate(function() {
        // $("#formLogin").submit();
    });

    page.render('example3.png');

    phantom.exit();
});
like image 26
Platinum Azure Avatar answered Oct 30 '22 12:10

Platinum Azure