catjs
Version:
(Mobile) Web Automation Framework
646 lines (524 loc) • 20 kB
JavaScript
var _ = require("underscore"),
_fs = require("fs.extra"),
_global = catrequire("cat.global"),
_log = _global.log(),
_props = catrequire("cat.props"),
_os = require("os"),
_globmatch = require("glob"),
_nodeutil = require("util"),
_path = require("path");
module.exports = function () {
/**
* Synchronized process for creating folder recursively
*/
var _module,
_mkdirSync = function (folder) {
if (!_fs.existsSync(folder)) {
try {
_fs.mkdirRecursiveSync(folder);
//_log.debug("[copy action] target folder was created: " + folder);
} catch (e) {
_log.error("[copy action] failed to create target dir: " + folder);
throw e;
}
}
},
/**
* Copy file synchronized
*/
_copySync = function (source, target, cb) {
var cbCalled = false,
me = this,
rd, wr;
if (!_fs.existsSync(source)) {
return undefined;
}
rd = _fs.createReadStream(source);
rd.on("error", function (err) {
done(err);
});
wr = _fs.createWriteStream(target);
wr.on("error", function (err) {
done(err);
});
wr.on("close", function (ex) {
done();
});
rd.pipe(wr);
function done(err) {
if (!cbCalled) {
if (err) {
throw err;
}
if (cb) {
cb(err);
}
cbCalled = true;
}
}
};
_module = {
/**
* Get a specific property's value
*
* @param obj {Object} The reference object
* @param key {String} The key to look for
*/
getProperty: function(obj, key) {
var value;
value = (key in obj ? obj[key] : undefined);
if (value === undefined) {
key = key.toLowerCase();
value = (key in obj ? obj[key] : undefined);
if (value === undefined) {
key = _module.capitalise(key);
value =(key in obj ? obj[key] : undefined);
}
}
return value;
},
capitalise: function(string) {
if (!string) {
return string;
}
return string.charAt(0).toUpperCase() + string.slice(1);
},
/**
*
*
* @param refobject {Object} The target object
* @param values {Array} The properties to be assigned to the target object
* key {String} The property key
* obj {Object} The object to be copied the property from
* default {Object} The default value to be set
*/
setProps: function (refobject, values) {
if (values) {
values.forEach(function (value) {
var defaultval = ("default" in value ? value["default"] : undefined);
if (value) {
if (value.key in value.val) {
if (value.val !== undefined) {
refobject[value.key] = value.val;
} else if (defaultval !== undefined) {
refobject[value.key] = defaultval;
}
}
}
});
}
},
/**
*
*
* @param value {Object} The source object
* key {String} The property key
* obj {Object} The object to be copied the property from
* default {Object} [optional] A default value
*
* @returns {*}
*/
getProp: function (value) {
if (value) {
var defaultval = ("default" in value ? value["default"] : undefined);
return (value.key in value.obj ? value.obj[value.key] : (defaultval || undefined));
}
return undefined;
},
/**
* Setting the reference object with default values or undefined for unassigned properties
* e.g. { global: {obj: obj}, props: [{key: "test", default: 1}] }
*
*
* @param value {Object} props values
* global {Object} global references
* obj {Object} [optional] The object to be copied the property from
*
* props {Array} prop value
* key {String} The property key
* obj {Object} [optional] The object to be copied the property from
* default {Object} [optional] A default value
* require {Boolean} Warning about undefined value, default set to false
*
*/
prepareProps: function (value) {
var globalreference, refobj;
if (value) {
if ("global" in value && value.global) {
globalreference = value.global.obj
}
if ("props" in value && value.props && _nodeutil.isArray(value.props)) {
value.props.forEach(function (prop) {
var defaultval;
if (!("require" in prop)) {
prop.require = false;
}
if (!"key" in prop) {
throw new Error("[catjs utils] 'key' is a required property for method 'getProps' ");
}
defaultval = ("default" in prop ? prop.default : undefined);
refobj = ("obj" in prop ? prop.obj : globalreference);
refobj[prop.key] = (prop.key in refobj ? refobj[prop.key] : defaultval);
if (prop.require && (refobj[prop.key] === undefined || refobj[prop.key] === null)) {
throw new Error("[catjs utils prepareProps] property '" + prop.key + "' is required ");
}
});
}
}
},
/**
* check if the path argument exists in the current location
*
* @param request {Object} standard request object
* @param path {*} a given path list of type Array or String
* @returns {boolean} whether one of the path exists
*/
pathMatch: function (request, path) {
var location = request.originalUrl,
referer = request.headers['referer'],
type, n = 0;
if (path) {
if (_.isString(path)) {
path = [path];
}
path.forEach(function (item) {
if (item) {
if (referer && referer.indexOf(path) !== -1) {
n++;
}
}
});
} else {
return true;
}
return (n > 0 ? true : false);
},
isWindows: function () {
var type = _os.platform();
if (type.toLocaleLowerCase() === "win32") {
return true;
}
return false;
},
mkdirSync: _mkdirSync,
copySync: _copySync,
globmatch: function (config) {
var lsrc, match,
src = config.src,
opt = ("opt" in config ? config.opt : {});
function __match(item, opt) {
var match = _globmatch.sync(item, opt);
if (!match) {
console.warn("[CAT libraries install] Failed match path: ", item, " , skip");
}
return match;
}
if (src) {
if (_.isArray(src)) {
lsrc = [];
src.forEach(function (item) {
var match;
if (item) {
try {
match = __match(item, opt);
if (match && match.length > 0) {
lsrc = lsrc.concat(match);
} else {
lsrc.push(item);
}
} catch (e) {
console.warn("[CAT libraries install] Failed to resolve path: ", item, "with errors: ", e);
lsrc.push(item);
}
}
});
} else if (_.isString(src)) {
try {
match = __match(src, opt);
if (match && match.length > 0) {
lsrc = match;
} else {
lsrc = [src];
}
} catch (e) {
console.warn(" Failed to resolve path: ", src, "with errors: ", e);
lsrc = src;
}
}
}
return lsrc;
},
deleteSync: function (dir) {
if (dir) {
if (_fs.existsSync(dir)) {
try {
_fs.rmrfSync(dir);
} catch (e) {
this.error(_props.get("cat.error").format("[utils (deleteSync)]", e));
}
}
}
},
// log to the console and to the log file
log: function (type, msg) {
if (type && _log[type]) {
_log[type](msg);
}
if (type === "info") {
type = "log";
} else if (type === "warning") {
type = "warn";
}
if (!console[type]) {
msg = type;
type = "log";
}
console[type](msg);
},
error: function () {
function parseArgs(args) {
var i = 0, size = args.length, out = [];
if (size > 0) {
for (; i < size; i++) {
out.push(args[i]);
}
} else {
return "General error occurred";
}
return out.join("; ");
}
_log.error.apply(_log, arguments);
if (console) {
console.error.apply(console, arguments);
}
throw parseArgs(arguments);
},
getRelativePath: function (file, basePath) {
return ((file && basePath) ? file.substring(basePath.length) : undefined);
},
/**
* Inspect a given string and try to resolve its object
*
* @param obj The reference object
* @param query The query to apply over the referenced object
*/
resolveObject: function (obj, query) {
if (!obj || !query) {
return obj;
}
var keys = query.split("."),
size = keys.length,
counter = 0,
key;
while (counter < size) {
key = keys[counter];
if (key && obj[key]) {
obj = obj[key];
counter++;
} else {
counter = size;
_log.warning(_props.get("cat.utils.resolver.warn").format("[utils resolver]", query));
return null;
}
}
return obj;
},
/**
* Prepare code based on line break.
* Looking for character ";" at the end if not exists it will be added
* and each line will be trimmed.
*
* @param codeRows
*/
prepareCode: function (codeRows) {
var row,
nextText,
size = (codeRows && _.isArray(codeRows) ? codeRows.length : 0), idx = 0;
function _row(row, ref, idx) {
var rowTrimmed;
if (row) {
rowTrimmed = (row.trim ? row.trim() : row);
if (rowTrimmed.charAt(rowTrimmed.length - 1) !== ";") {
if (idx !== undefined) {
ref[idx] += ";";
} else {
ref += ";"
}
}
if (idx !== undefined) {
ref[idx] = convertTestDataRexp(ref[idx]);
} else {
ref = convertTestDataRexp(ref);
}
}
return ref;
}
function convertTestDataRexp(codeRows) {
var patt;
patt = new RegExp("(.*)@d\\.([a-z]*\\()\\.(.*)(\\).*\\).*)", "g");
while (codeRows.match(patt)) {
codeRows = codeRows.replace(patt, "$1_cat.utils.TestsDB.$2\".$3\"$4");
}
return codeRows;
}
if (size) {
for (; idx < size; idx++) {
row = codeRows[idx];
row = (row.trim ? row.trim() : row);
codeRows = _row(row, codeRows, idx);
}
} else {
codeRows = (codeRows.trim ? codeRows.trim() : codeRows);
codeRows = _row(codeRows, codeRows);
}
return codeRows;
},
/**
* Check if a given object contains a value
*
* @param obj The object that might contains
* @param value The value to be searched
*
* @returns {boolean} If the value contains in the obj return true else return false
*/
contains: function (obj, value) {
var key;
if (obj) {
for (key in obj) {
if (obj[key] === value) {
return true;
}
}
}
return false;
},
removeArrayItemByIdx: function (arr, idx) {
var newArr = [],
counter = 0;
if (arr && _.isArray(arr)) {
arr.forEach(function (item) {
if (idx !== counter) {
newArr.push(item);
}
counter++;
});
}
return newArr;
},
removeArrayItemByValue: function (arr, value) {
var newArr = [],
counter = 0;
if (arr && _.isArray(arr)) {
arr.forEach(function (item) {
if (item !== value && item !== null && item !== undefined) {
newArr.push(item);
}
counter++;
});
}
return newArr;
},
cleanupArray: function (arr) {
var newArr = [];
if (arr && _.isArray(arr)) {
arr.forEach(function (item) {
if (item !== null && item !== undefined) {
newArr.push(item);
}
});
}
return newArr;
},
/**
* Copy the source object's properties.
* TODO TBD make it more robust, recursion and function support
*
* @param srcObj
* @param destObj
* @param override Override existing property [false as default]
*/
copyObjProps: function (srcObj, destObj, override) {
var name, obj,
me = this,
idx = 0, size = 0, item;
override = (override || false);
if (srcObj && destObj) {
for (name in srcObj) {
if (srcObj.hasOwnProperty(name)) {
obj = destObj[name];
if (_.isArray(srcObj[name])) {
if (!obj) {
destObj[name] = srcObj[name];
} else if (_.isArray(obj)) {
me.cleanupArray(srcObj[name]);
if (override) {
destObj[name] = srcObj[name];
} else {
size = destObj[name].length;
for (idx = 0; idx < size; idx++) {
item = obj[idx];
srcObj[name] = me.removeArrayItemByValue(srcObj[name], item);
}
destObj[name] = destObj[name].concat(srcObj[name]);
}
} else {
_log.warning(_props.get("cat.utils.copy.object.array.warn").format("[utils copy object]", name, typeof(obj)));
}
} else if (_.isObject(srcObj[name])) {
if (!destObj[name]) {
destObj[name] = {};
}
arguments.callee.call(me, srcObj[name], destObj[name], override);
} else {
if (override || obj === undefined) {
if (!destObj[name] || (destObj[name] && override)) {
destObj[name] = srcObj[name];
}
}
}
}
}
}
},
forEachProp: function (srcObj, callback) {
var name;
if (srcObj) {
for (name in srcObj) {
if (srcObj.hasOwnProperty(name)) {
if (callback) {
callback.call(srcObj, name);
}
}
else {
}
}
}
},
kill: function (pids, excludes) {
var me = this;
function process(pid, exclude) {
if (pid !== exclude) {
try {
_log.error("[kill process] sending SIGKILL signal to pid: " + pid);
process.kill(pid, "SIGKILL");
} catch (e) {
// TODO check if the process is running
_log.error("[kill process] failed to kill pid: " + pid + "; The process might not exists");
}
}
}
if (pids) {
pids.forEach(function (pid) {
if (excludes) {
excludes.forEach(function (exclude) {
process(pid, exclude);
});
} else {
process(pid);
}
});
}
}
};
return _module;
}();