lib/teaspoon/driver/phantomjs/runner.js
(function() {
var system = require("system");
var webpage = require("webpage");
this.Runner = (function() {
function Runner() {
this.url = system.args[1];
this.timeout = parseInt(system.args[2] || 180) * 1000;
var _this = this;
this.waitForResults = function() { Runner.prototype.waitForResults.apply(_this, arguments) };
}
Runner.prototype.run = function() {
this.initPage();
this.loadPage();
};
Runner.prototype.initPage = function() {
this.page = webpage.create();
this.page.viewportSize = {
width: 800,
height: 800
};
};
Runner.prototype.loadPage = function() {
this.page.open(this.url);
var callbacks = this.pageCallbacks();
for (var name in callbacks) {
this.page[name] = callbacks[name];
}
};
Runner.prototype.waitForResults = function() {
if ((new Date().getTime() - this.start) >= this.timeout) this.fail("Timed out");
var finished = this.page.evaluate(function() { return window.Teaspoon && window.Teaspoon.finished });
finished ? this.finish() : setTimeout(this.waitForResults, 200);
};
Runner.prototype.fail = function(msg, errno) {
if (msg == null) msg = null;
if (errno == null) errno = 1;
console.log(JSON.stringify({
_teaspoon: true,
type: "exception",
message: msg
}));
phantom.exit(errno);
};
Runner.prototype.finish = function() {
phantom.exit(0);
};
Runner.prototype.pageCallbacks = function() {
var _this = this;
return {
onError: function(message, trace) {
var started = _this.page.evaluate(function() {
return window.Teaspoon && window.Teaspoon.started;
});
console.log(JSON.stringify({
_teaspoon: true,
type: started ? "error" : "exception",
message: message,
trace: trace
}));
_this.errored = true;
if (/^TeaspoonError: /.test(message || "")) {
_this.fail("Execution halted.");
}
},
onConsoleMessage: function(msg) {
console.log(msg);
if (_this.errorTimeout) clearTimeout(_this.errorTimeout);
if (_this.errored) {
_this.errorTimeout = setTimeout((function() {
return _this.fail("Javascript error has caused a timeout.");
}), _this.timeout);
return _this.errored = false;
}
},
onLoadFinished: function(status) {
if (_this.start) return;
_this.start = new Date().getTime();
var defined = _this.page.evaluate(function() {
return window.Teaspoon;
});
if (!(status === "success" && defined)) {
if (status === "success") {
// Could not load the window.Teaspoon object from the JavaScript on the
// rendered page. This indicates that a problem occured. Lets therfore
// print the page as a failure description.
// Get plain text of the page, intend all lines (better readable)
var ind = " ";
var error = _this.page.plainText.replace(/(?:\n)/g, "\n" + ind);
// take only first 10 lines, as they usually provide a good entry
// point for debugging and we should not spam our console.
var erroroutput = error.split("\n").slice(0, 10);
if (erroroutput !== error) {
erroroutput.push("... (further lines have been removed)");
}
var fail = [
"Failed to get Teaspoon result object on page: " + _this.url,
"The title of this page was '" + _this.page.title + "'.",
"",
erroroutput.join("\n")
];
_this.fail(fail.join(" \n" + ind));
}
else {
// Status is not 'success'
_this.fail("Failed to load: " + _this.url + ". Status: " + status);
return;
}
}
_this.waitForResults();
}
};
};
return Runner;
})();
new Runner().run();
}).call(this);