Commit 55103a57 55103a57e0560d4687d049ec38701be1f02e6d41 by Nicolas Perriault

fixes #148 - broken utils.isWebPage()

1 parent 0245dcfb
......@@ -5,7 +5,8 @@ XXXX-XX-XX, v0.6.11
-------------------
- closed [#132](https://github.com/n1k0/casperjs/issues/132) - added ability to include js/coffee files using a dedicated option when using the `casper test` command
- fixes [#140](https://github.com/n1k0/casperjs/issues/140) - `casper test` now resolves local paths urls
- fixed [#140](https://github.com/n1k0/casperjs/issues/140) - `casper test` now resolves local paths urls
- fixed [#148](https://github.com/n1k0/casperjs/issues/148) - `utils.isWebPage()` was broken
- closed [#144](https://github.com/n1k0/casperjs/issues/144) - added a `safeLogs` option to blur password values in debug logs. **This option is set to `true` by default.**
- added [`Casper.userAgent()`](http://casperjs.org/api.html#casper.userAgent) to ease a more dynamic setting of user-agent string
- added `Tester.assertTitleMatch()` method
......
Subproject commit ed91017f48fd77e8c3a268ecdbb78adac7bce0b5
Subproject commit 76cc32f262a3ef924a67f33bb17432e3a5c33e03
......
......@@ -400,6 +400,8 @@ Casper.prototype.die = function die(message, status) {
*
* @param String url The url of the resource to download
* @param String targetPath The destination file path
* @param String method The HTTP method to use (default: GET)
* @param String data Optional data to pass performing the request
* @return Casper
*/
Casper.prototype.download = function download(url, targetPath, method, data) {
......
......@@ -100,7 +100,7 @@ var Tester = function Tester(casper, options) {
if (failure.details) {
this.comment(' details: ' + failure.details);
}
if (failure.values && Object.keys(failure.values).length > 0) {
if (utils.isObject(failure.values) && Object.keys(failure.values).length > 0) {
for (var name in failure.values) {
this.comment(' ' + name + ': ' + utils.serialize(failure.values[name]));
}
......
......@@ -30,361 +30,341 @@
/*global CasperError console exports phantom require*/
/**
* Provides a better typeof operator equivalent, able to retrieve the array
* type.
*
* @param mixed input
* @return String
* @see http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
*/
function betterTypeOf(input) {
"use strict";
try {
return Object.prototype.toString.call(input).match(/^\[object\s(.*)\]$/)[1].toLowerCase();
} catch (e) {
return typeof input;
}
}
exports.betterTypeOf = betterTypeOf;
/**
* Dumps a JSON representation of passed value to the console. Used for
* debugging purpose only.
*
* @param Mixed value
*/
function dump(value) {
(function(exports) {
"use strict";
console.log(serialize(value));
}
exports.dump = dump;
/**
* Returns the file extension in lower case.
*
* @param String file File path
* @return string
*/
function fileExt(file) {
"use strict";
try {
return file.split('.').pop().toLowerCase().trim();
} catch(e) {
return '';
/**
* Provides a better typeof operator equivalent, able to retrieve the array
* type.
*
* @param mixed input
* @return String
* @see http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
*/
function betterTypeOf(input) {
try {
return Object.prototype.toString.call(input).match(/^\[object\s(.*)\]$/)[1].toLowerCase();
} catch (e) {
return typeof input;
}
}
}
exports.fileExt = fileExt;
exports.betterTypeOf = betterTypeOf;
/**
* Takes a string and append blanks until the pad value is reached.
*
* @param String text
* @param Number pad Pad value (optional; default: 80)
* @return String
*/
function fillBlanks(text, pad) {
"use strict";
pad = pad || 80;
if (text.length < pad) {
text += new Array(pad - text.length + 1).join(' ');
/**
* Dumps a JSON representation of passed value to the console. Used for
* debugging purpose only.
*
* @param Mixed value
*/
function dump(value) {
console.log(serialize(value));
}
return text;
}
exports.fillBlanks = fillBlanks;
exports.dump = dump;
/**
* Formats a string with passed parameters. Ported from nodejs `util.format()`.
*
* @return String
*/
function format(f) {
"use strict";
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(/%[sdj%]/g, function _replace(x) {
if (i >= len) return x;
switch (x) {
case '%s':
return String(args[i++]);
case '%d':
return Number(args[i++]);
case '%j':
return JSON.stringify(args[i++]);
case '%%':
return '%';
default:
return x;
/**
* Returns the file extension in lower case.
*
* @param String file File path
* @return string
*/
function fileExt(file) {
try {
return file.split('.').pop().toLowerCase().trim();
} catch(e) {
return '';
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (x === null || typeof x !== 'object') {
str += ' ' + x;
} else {
str += '[obj]';
}
exports.fileExt = fileExt;
/**
* Takes a string and append blanks until the pad value is reached.
*
* @param String text
* @param Number pad Pad value (optional; default: 80)
* @return String
*/
function fillBlanks(text, pad) {
pad = pad || 80;
if (text.length < pad) {
text += new Array(pad - text.length + 1).join(' ');
}
return text;
}
return str;
}
exports.format = format;
exports.fillBlanks = fillBlanks;
/**
* Inherit the prototype methods from one constructor into another.
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
function inherits(ctor, superCtor) {
"use strict";
ctor.super_ = ctor.__super__ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
/**
* Formats a string with passed parameters. Ported from nodejs `util.format()`.
*
* @return String
*/
function format(f) {
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(/%[sdj%]/g, function _replace(x) {
if (i >= len) return x;
switch (x) {
case '%s':
return String(args[i++]);
case '%d':
return Number(args[i++]);
case '%j':
return JSON.stringify(args[i++]);
case '%%':
return '%';
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (x === null || typeof x !== 'object') {
str += ' ' + x;
} else {
str += '[obj]';
}
}
});
}
exports.inherits = inherits;
return str;
}
exports.format = format;
/**
* Checks if value is a javascript Array
*
* @param mixed value
* @return Boolean
*/
function isArray(value) {
"use strict";
return Array.isArray(value) || isType(value, "array");
}
exports.isArray = isArray;
/**
* Inherit the prototype methods from one constructor into another.
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
function inherits(ctor, superCtor) {
ctor.super_ = ctor.__super__ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
}
exports.inherits = inherits;
/**
* Checks if passed argument is an instance of Capser object.
*
* @param mixed value
* @return Boolean
*/
function isCasperObject(value) {
"use strict";
return value instanceof require('casper').Casper;
}
exports.isCasperObject = isCasperObject;
/**
* Checks if value is a javascript Array
*
* @param mixed value
* @return Boolean
*/
function isArray(value) {
return Array.isArray(value) || isType(value, "array");
}
exports.isArray = isArray;
/**
* Checks if value is a phantomjs clipRect-compatible object
*
* @param mixed value
* @return Boolean
*/
function isClipRect(value) {
"use strict";
return isType(value, "cliprect") || (
isObject(value) &&
isNumber(value.top) && isNumber(value.left) &&
isNumber(value.width) && isNumber(value.height)
);
}
exports.isClipRect = isClipRect;
/**
* Checks if passed argument is an instance of Capser object.
*
* @param mixed value
* @return Boolean
*/
function isCasperObject(value) {
return value instanceof require('casper').Casper;
}
exports.isCasperObject = isCasperObject;
/**
* Checks if value is a javascript Function
*
* @param mixed value
* @return Boolean
*/
function isFunction(value) {
"use strict";
return isType(value, "function");
}
exports.isFunction = isFunction;
/**
* Checks if value is a phantomjs clipRect-compatible object
*
* @param mixed value
* @return Boolean
*/
function isClipRect(value) {
return isType(value, "cliprect") || (
isObject(value) &&
isNumber(value.top) && isNumber(value.left) &&
isNumber(value.width) && isNumber(value.height)
);
}
exports.isClipRect = isClipRect;
/**
* Checks if a file is apparently javascript compatible (.js or .coffee).
*
* @param String file Path to the file to test
* @return Boolean
*/
function isJsFile(file) {
"use strict";
var ext = fileExt(file);
return isString(ext, "string") && ['js', 'coffee'].indexOf(ext) !== -1;
}
exports.isJsFile = isJsFile;
/**
* Checks if value is a javascript Function
*
* @param mixed value
* @return Boolean
*/
function isFunction(value) {
return isType(value, "function");
}
exports.isFunction = isFunction;
/**
* Checks if the provided value is null
*
* @return Boolean
*/
function isNull(value) {
"use strict";
return isType(value, "null");
}
exports.isNull = isNull;
/**
* Checks if a file is apparently javascript compatible (.js or .coffee).
*
* @param String file Path to the file to test
* @return Boolean
*/
function isJsFile(file) {
var ext = fileExt(file);
return isString(ext, "string") && ['js', 'coffee'].indexOf(ext) !== -1;
}
exports.isJsFile = isJsFile;
/**
* Checks if value is a javascript Number
*
* @param mixed value
* @return Boolean
*/
function isNumber(value) {
"use strict";
return isType(value, "number");
}
exports.isNumber = isNumber;
/**
* Checks if the provided value is null
*
* @return Boolean
*/
function isNull(value) {
return isType(value, "null");
}
exports.isNull = isNull;
/**
* Checks if value is a javascript Object
*
* @param mixed value
* @return Boolean
*/
function isObject(value) {
"use strict";
return isType(value, "object");
}
exports.isObject = isObject;
/**
* Checks if value is a javascript Number
*
* @param mixed value
* @return Boolean
*/
function isNumber(value) {
return isType(value, "number");
}
exports.isNumber = isNumber;
/**
* Checks if value is a javascript String
*
* @param mixed value
* @return Boolean
*/
function isString(value) {
"use strict";
return isType(value, "string");
}
exports.isString = isString;
/**
* Checks if value is a javascript Object
*
* @param mixed value
* @return Boolean
*/
function isObject(value) {
var objectTypes = ["array", "object", "qtruntimeobject"];
return objectTypes.indexOf(betterTypeOf(value)) >= 0;
}
exports.isObject = isObject;
/**
* Shorthands for checking if a value is of the given type. Can check for
* arrays.
*
* @param mixed what The value to check
* @param String typeName The type name ("string", "number", "function", etc.)
* @return Boolean
*/
function isType(what, typeName) {
"use strict";
if (typeof typeName !== "string" || !typeName) {
throw new CasperError("You must pass isType() a typeName string");
/**
* Checks if value is a javascript String
*
* @param mixed value
* @return Boolean
*/
function isString(value) {
return isType(value, "string");
}
return betterTypeOf(what).toLowerCase() === typeName.toLowerCase();
}
exports.isType = isType;
exports.isString = isString;
/**
* Checks if the provided value is undefined
*
* @return Boolean
*/
function isUndefined(value) {
"use strict";
return isType(value, "undefined");
}
exports.isUndefined = isUndefined;
/**
* Shorthands for checking if a value is of the given type. Can check for
* arrays.
*
* @param mixed what The value to check
* @param String typeName The type name ("string", "number", "function", etc.)
* @return Boolean
*/
function isType(what, typeName) {
if (typeof typeName !== "string" || !typeName) {
throw new CasperError("You must pass isType() a typeName string");
}
return betterTypeOf(what).toLowerCase() === typeName.toLowerCase();
}
exports.isType = isType;
/**
* Checks if the provided var is a WebPage instance
*
* @param mixed what
* @return Boolean
*/
function isWebPage(what) {
"use strict";
if (!what || !isObject(what)) {
return false;
/**
* Checks if the provided value is undefined
*
* @return Boolean
*/
function isUndefined(value) {
return isType(value, "undefined");
}
return what.toString().indexOf('WebPage(') === 0;
}
exports.isWebPage = isWebPage;
exports.isUndefined = isUndefined;
/**
* Object recursive merging utility.
*
* @param Object origin the origin object
* @param Object add the object to merge data into origin
* @return Object
*/
function mergeObjects(origin, add) {
"use strict";
for (var p in add) {
try {
if (add[p].constructor === Object) {
origin[p] = mergeObjects(origin[p], add[p]);
} else {
origin[p] = add[p];
/**
* Checks if the provided var is a WebPage instance
*
* @param mixed what
* @return Boolean
*/
function isWebPage(what) {
return betterTypeOf(what) === "qtruntimeobject" && what.objectName === 'WebPage';
}
exports.isWebPage = isWebPage;
/**
* Object recursive merging utility.
*
* @param Object origin the origin object
* @param Object add the object to merge data into origin
* @return Object
*/
function mergeObjects(origin, add) {
for (var p in add) {
try {
if (add[p].constructor === Object) {
origin[p] = mergeObjects(origin[p], add[p]);
} else {
origin[p] = add[p];
}
} catch(e) {
origin[p] = add[p];
}
} catch(e) {
origin[p] = add[p];
}
return origin;
}
return origin;
}
exports.mergeObjects = mergeObjects;
exports.mergeObjects = mergeObjects;
/**
* Creates an (SG|X)ML node element.
*
* @param String name The node name
* @param Object attributes Optional attributes
* @return HTMLElement
*/
function node(name, attributes) {
"use strict";
var _node = document.createElement(name);
for (var attrName in attributes) {
var value = attributes[attrName];
if (attributes.hasOwnProperty(attrName) && isString(attrName)) {
_node.setAttribute(attrName, value);
/**
* Creates an (SG|X)ML node element.
*
* @param String name The node name
* @param Object attributes Optional attributes
* @return HTMLElement
*/
function node(name, attributes) {
var _node = document.createElement(name);
for (var attrName in attributes) {
var value = attributes[attrName];
if (attributes.hasOwnProperty(attrName) && isString(attrName)) {
_node.setAttribute(attrName, value);
}
}
return _node;
}
return _node;
}
exports.node = node;
exports.node = node;
/**
* Serializes a value using JSON.
*
* @param Mixed value
* @return String
*/
function serialize(value) {
"use strict";
if (isArray(value)) {
value = value.map(function _map(prop) {
return isFunction(prop) ? prop.toString().replace(/\s{2,}/, '') : prop;
});
/**
* Serializes a value using JSON.
*
* @param Mixed value
* @return String
*/
function serialize(value) {
if (isArray(value)) {
value = value.map(function _map(prop) {
return isFunction(prop) ? prop.toString().replace(/\s{2,}/, '') : prop;
});
}
return JSON.stringify(value, null, 4);
}
return JSON.stringify(value, null, 4);
}
exports.serialize = serialize;
exports.serialize = serialize;
/**
* Returns unique values from an array.
*
* Note: ugly code is ugly, but efficient: http://jsperf.com/array-unique2/8
*
* @param Array array
* @return Array
*/
function unique(array) {
"use strict";
var o = {},
r = [];
for (var i = 0, len = array.length; i !== len; i++) {
var d = array[i];
if (o[d] !== 1) {
o[d] = 1;
r[r.length] = d;
/**
* Returns unique values from an array.
*
* Note: ugly code is ugly, but efficient: http://jsperf.com/array-unique2/8
*
* @param Array array
* @return Array
*/
function unique(array) {
var o = {},
r = [];
for (var i = 0, len = array.length; i !== len; i++) {
var d = array[i];
if (o[d] !== 1) {
o[d] = 1;
r[r.length] = d;
}
}
return r;
}
return r;
}
exports.unique = unique;
exports.unique = unique;
})(exports);
......
......@@ -29,6 +29,13 @@ t.comment('fillBlanks()');
}
})();
t.comment('isArray()');
(function() {
t.assertEquals(utils.isArray([]), true, 'isArray() checks for an Array');
t.assertEquals(utils.isArray({}), false, 'isArray() checks for an Array');
t.assertEquals(utils.isArray("foo"), false, 'isArray() checks for an Array');
})();
t.comment('isClipRect()');
(function() {
testCases = [
......@@ -44,6 +51,26 @@ t.comment('isClipRect()');
});
})();
t.comment('isObject()');
(function() {
t.assertEquals(utils.isObject({}), true, 'isObject() checks for an Object');
t.assertEquals(utils.isObject([]), true, 'isObject() checks for an Object');
t.assertEquals(utils.isObject(1), false, 'isObject() checks for an Object');
t.assertEquals(utils.isObject("1"), false, 'isObject() checks for an Object');
t.assertEquals(utils.isObject(function(){}), false, 'isObject() checks for an Object');
t.assertEquals(utils.isObject(new Function('return {};')()), true, 'isObject() checks for an Object');
t.assertEquals(utils.isObject(require('webpage').create()), true, 'isObject() checks for an Object');
t.assertEquals(utils.isObject(null), false, 'isObject() checks for an Object');
})();
t.comment('isWebPage()');
(function() {
var pageModule = require('webpage');
t.assertEquals(utils.isWebPage(pageModule), false, 'isWebPage() checks for a WebPage instance');
t.assertEquals(utils.isWebPage(pageModule.create()), true, 'isWebPage() checks for a WebPage instance');
t.assertEquals(utils.isWebPage(null), false, 'isWebPage() checks for a WebPage instance');
})();
t.comment('isJsFile()');
(function() {
testCases = {
......