Commit 301d6345 301d63454d0f1bd9a337ce02f585d2a7d23828dd by Nicolas Perriault

continued migration to a full require() based layout

1 parent d5ff7c42
......@@ -106,6 +106,28 @@ phantom.casperArgs = (function(cliArgs) {
return extract;
})(phantom.args);
var sourceIds = {};
// Inspired by phantomjs-nodify: https://github.com/jgonera/phantomjs-nodify/
// TODO: remoive when phantomjs has js engine upgrade
if (!new Error().hasOwnProperty('stack')) {
Object.defineProperty(Error.prototype, 'stack', {
set: function(string) {
this._stack = string;
},
get: function() {
if (this._stack) {
return this._stack;
} else if (this.fileName || this.sourceId) {
return this.toString() + '\nat ' + getErrorMessage(this);
}
return this.toString() + '\nat unknown';
},
configurable: true,
enumerable: true
});
}
// Inspired by phantomjs-nodify: https://github.com/jgonera/phantomjs-nodify/
// TODO: remove when PhantomJS has full module support
require = (function(require, requireDir) {
......@@ -159,7 +181,14 @@ require = (function(require, requireDir) {
return requireCache[file].exports;
}
code = fs.read(file);
if (file.match(/\.coffee$/)) {
if (file.match(/\.js$/i)) {
try {
// TODO: esprima syntax check
} catch (e) {
e.fileName = file;
throw e;
}
} else if (file.match(/\.coffee$/i)) {
try {
code = CoffeeScript.compile(code);
} catch (e) {
......@@ -168,12 +197,12 @@ require = (function(require, requireDir) {
}
}
// a trick to associate Error's sourceId with file
//code += ";throw new Error('__sourceId__');";
code += ";throw new Error('__sourceId__');";
try {
fn = new Function('module', 'exports', code);
fn(module, module.exports);
} catch (e) {
if (typeof sourceIds === "object" && !sourceIds.hasOwnProperty(e.sourceId)) {
if (!sourceIds.hasOwnProperty(e.sourceId)) {
sourceIds[e.sourceId] = file;
}
if (e.message !== '__sourceId__') {
......
......@@ -26,12 +26,9 @@
*
*/
exports.create = create;
exports.Colorizer = Colorizer;
function create() {
exports.create = function() {
return new Colorizer();
}
};
/**
* This is a port of lime colorizer.
......@@ -95,3 +92,4 @@ var Colorizer = function() {
return "\033[" + codes.join(';') + 'm' + text + "\033[0m";
};
};
exports.Colorizer = Colorizer;
......
......@@ -27,15 +27,15 @@
*/
exports.create = create;
exports.FunctionArgsInjector = FunctionArgsInjector;
function create(fn) {
exports.create = function(fn) {
return new FunctionArgsInjector(fn);
}
};
/**
* Function argument injector.
*
* FIXME: use new Function() instead of eval()
*/
var FunctionArgsInjector = function(fn) {
if (!isType(fn, "function")) {
......@@ -82,3 +82,4 @@ var FunctionArgsInjector = function(fn) {
return inject.join('\n') + '\n';
};
};
exports.FunctionArgsInjector = FunctionArgsInjector;
......
......@@ -27,10 +27,11 @@
*/
var fs = require('fs');
var utils = require('./lib/utils');
function create(casper, options) {
exports.create = function(casper, options) {
return new Tester(casper, options);
}
};
/**
* Casper tester: makes assertions, stores test results and display then.
......@@ -39,9 +40,9 @@ function create(casper, options) {
var Tester = function(casper, options) {
this.running = false;
this.suites = [];
this.options = isType(options, "object") ? options : {};
this.options = utils.isType(options, "object") ? options : {};
if (!casper instanceof require('./lib/casper').Casper) {
if (!utils.isCasperObject(casper)) {
throw new Error("Tester needs a Casper instance");
}
......@@ -219,7 +220,7 @@ var Tester = function(casper, options) {
* @param String message Test description
*/
this.assertType = function(input, type, message) {
return this.assertEquals(betterTypeOf(input), type, message);
return this.assertEquals(utils.betterTypeOf(input), type, message);
};
/**
......@@ -368,7 +369,7 @@ var Tester = function(casper, options) {
* @param Boolean exit
*/
this.renderResults = function(exit, status, save) {
save = isType(save, "string") ? save : this.options.save;
save = utils.isType(save, "string") ? save : this.options.save;
var total = this.testResults.passed + this.testResults.failed, statusText, style, result;
if (this.testResults.failed > 0) {
statusText = FAIL;
......@@ -379,7 +380,7 @@ var Tester = function(casper, options) {
}
result = statusText + ' ' + total + ' tests executed, ' + this.testResults.passed + ' passed, ' + this.testResults.failed + ' failed.';
casper.echo(this.colorize(fillBlanks(result), style));
if (save && isType(require, "function")) {
if (save && utils.isType(require, "function")) {
try {
fs.write(save, exporter.getXML(), 'w');
casper.echo('result log stored in ' + save, 'INFO');
......@@ -455,10 +456,10 @@ var Tester = function(casper, options) {
* @param Boolean
*/
this.testEquals = function(v1, v2) {
if (betterTypeOf(v1) !== betterTypeOf(v2)) {
if (utils.betterTypeOf(v1) !== utils.betterTypeOf(v2)) {
return false;
}
if (isType(v1, "function")) {
if (utils.isType(v1, "function")) {
return v1.toString() === v2.toString();
}
if (v1 instanceof Object && v2 instanceof Object) {
......@@ -475,3 +476,4 @@ var Tester = function(casper, options) {
return v1 === v2;
};
};
exports.Tester = Tester;
......
......@@ -41,105 +41,7 @@ function betterTypeOf(input) {
return typeof input;
}
}
/**
* Creates a new WebPage instance for Casper use.
*
* @param Casper casper A Casper instance
* @return WebPage
*/
function createPage(casper) {
var page;
if (phantom.version.major <= 1 && phantom.version.minor < 3 && isType(require, "function")) {
page = new WebPage();
} else {
page = require('webpage').create();
}
page.onAlert = function(message) {
casper.log('[alert] ' + message, "info", "remote");
if (isType(casper.options.onAlert, "function")) {
casper.options.onAlert.call(casper, casper, message);
}
};
page.onConsoleMessage = function(msg) {
var level = "info", test = /^\[casper:(\w+)\]\s?(.*)/.exec(msg);
if (test && test.length === 3) {
level = test[1];
msg = test[2];
}
casper.log(msg, level, "remote");
};
page.onLoadStarted = function() {
casper.resources = [];
casper.loadInProgress = true;
};
page.onLoadFinished = function(status) {
if (status !== "success") {
var message = 'Loading resource failed with status=' + status;
if (casper.currentHTTPStatus) {
message += ' (HTTP ' + casper.currentHTTPStatus + ')';
}
message += ': ' + casper.requestUrl;
casper.log(message, "warning");
if (isType(casper.options.onLoadError, "function")) {
casper.options.onLoadError.call(casper, casper, casper.requestUrl, status);
}
}
if (casper.options.clientScripts) {
if (betterTypeOf(casper.options.clientScripts) !== "array") {
casper.log("The clientScripts option must be an array", "error");
} else {
for (var i = 0; i < casper.options.clientScripts.length; i++) {
var script = casper.options.clientScripts[i];
if (casper.page.injectJs(script)) {
casper.log('Automatically injected ' + script + ' client side', "debug");
} else {
casper.log('Failed injecting ' + script + ' client side', "warning");
}
}
}
}
// Client-side utils injection
var injected = page.evaluate(replaceFunctionPlaceholders(function() {
eval("var ClientUtils = " + decodeURIComponent("%utils%"));
__utils__ = new ClientUtils();
return __utils__ instanceof ClientUtils;
}, {
utils: encodeURIComponent(require('./lib/clientutils').ClientUtils.toString())
}));
if (!injected) {
casper.log("Failed to inject Casper client-side utilities!", "warning");
} else {
casper.log("Successfully injected Casper client-side utilities", "debug");
}
// history
casper.history.push(casper.getCurrentUrl());
casper.loadInProgress = false;
};
page.onResourceReceived = function(resource) {
if (isType(casper.options.onResourceReceived, "function")) {
casper.options.onResourceReceived.call(casper, casper, resource);
}
if (resource.stage === "end") {
casper.resources.push(resource);
}
if (resource.url === casper.requestUrl && resource.stage === "start") {
casper.currentHTTPStatus = resource.status;
if (isType(casper.options.httpStatusHandlers, "object") &&
resource.status in casper.options.httpStatusHandlers &&
isType(casper.options.httpStatusHandlers[resource.status], "function")) {
casper.options.httpStatusHandlers[resource.status].call(casper, casper, resource);
}
casper.currentUrl = resource.url;
}
};
page.onResourceRequested = function(request) {
if (isType(casper.options.onResourceRequested, "function")) {
casper.options.onResourceRequested.call(casper, casper, request);
}
};
return page;
}
exports.betterTypeOf = betterTypeOf;
/**
* Dumps a JSON representation of passed value to the console. Used for
......@@ -150,6 +52,7 @@ function createPage(casper) {
function dump(value) {
console.log(serialize(value));
}
exports.dump = dump;
/**
* Returns the file extension in lower case.
......@@ -164,6 +67,7 @@ function fileExt(file) {
return '';
}
}
exports.fileExt = fileExt;
/**
* Takes a string and append blank until the pad value is reached.
......@@ -179,6 +83,18 @@ function fillBlanks(text, pad) {
}
return text;
}
exports.fillBlanks = fillBlanks;
/**
* Checks if passed argument is an instance of Capser object.
*
* @param mixed value
* @return Boolean
*/
function isCasperObject(value) {
return value instanceof require('./lib/casper').Casper;
}
exports.isCasperObject = isCasperObject;
/**
* Checks if a file is apparently javascript compatible (.js or .coffee).
......@@ -190,6 +106,7 @@ function isJsFile(file) {
var ext = fileExt(file);
return isType(ext, "string") && ['js', 'coffee'].indexOf(ext) !== -1;
}
exports.isJsFile = isJsFile;
/**
* Shorthands for checking if a value is of the given type. Can check for
......@@ -202,6 +119,7 @@ function isJsFile(file) {
function isType(what, typeName) {
return betterTypeOf(what) === typeName;
}
exports.isType = isType;
/**
* Checks if the provided var is a WebPage instance
......@@ -219,6 +137,7 @@ function isWebPage(what) {
return what.toString().indexOf('WebPage(') === 0;
}
}
exports.isWebPage = isWebPage;
/**
* Object recursive merging utility.
......@@ -241,6 +160,7 @@ function mergeObjects(obj1, obj2) {
}
return obj1;
}
exports.mergeObjects = mergeObjects;
/**
* Replaces a function string contents with placeholders provided by an
......@@ -262,6 +182,7 @@ function replaceFunctionPlaceholders(fn, replacements) {
}
return fn;
}
exports.replaceFunctionPlaceholders = replaceFunctionPlaceholders;
/**
* Serializes a value using JSON.
......@@ -277,3 +198,4 @@ function serialize(value) {
}
return JSON.stringify(value, null, 4);
}
exports.serialize = serialize;
......
......@@ -26,12 +26,9 @@
*
*/
exports.create = create;
exports.XUnitExporter = XUnitExporter;
function create() {
exports.create = function() {
return new XUnitExporter();
}
};
/**
* JUnit XML (xUnit) exporter for test results.
......@@ -97,3 +94,5 @@ XUnitExporter = function() {
return xml;
};
};
exports.XUnitExporter = XUnitExporter;
......