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?
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!
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();
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With