288 lines
6.8 KiB
JavaScript
288 lines
6.8 KiB
JavaScript
var path = require('path');
|
|
var fs = require('fs');
|
|
var Util = module.exports = {};
|
|
var Logger = require('./logger.js');
|
|
|
|
var formatRegExp = /%[sdj%]/g;
|
|
var testSuiteNameRegxp = /(_|-|\.)*([A-Z]*)/g;
|
|
var nameSeparatorRegxp = /(\s|\/)/;
|
|
|
|
Util.formatElapsedTime = function(timeMs, includeMs) {
|
|
var seconds = timeMs/1000;
|
|
return (seconds < 1 && timeMs + 'ms') ||
|
|
(seconds > 1 && seconds < 60 && (seconds + 's')) ||
|
|
(Math.floor(seconds/60) + 'm' + ' ' + Math.floor(seconds%60) + 's' + (includeMs ? (' / ' + timeMs + 'ms') : ''));
|
|
};
|
|
|
|
/**
|
|
* Wrap a synchronous function, turning it into an async fn with a callback as
|
|
* the last argument if necessary. `asyncArgCount` is the expected argument
|
|
* count if `fn` is already asynchronous.
|
|
*
|
|
* @param {number} asyncArgCount
|
|
* @param {function} fn
|
|
* @param {object} [context]
|
|
*/
|
|
Util.makeFnAsync = function (asyncArgCount, fn, context) {
|
|
if (fn.length === asyncArgCount) {
|
|
return fn;
|
|
}
|
|
|
|
return function() {
|
|
var args = Array.prototype.slice.call(arguments, 0);
|
|
var done = args.pop();
|
|
context = context || null;
|
|
fn.apply(context, args);
|
|
done();
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Waits a number of ms for a `done` callback to be invoked
|
|
*
|
|
* @param {function} done
|
|
* @param {string} fnName
|
|
* @param {number} timeMs
|
|
* @param {function} [onCatch]
|
|
* @param {function} [onTimerStarted]
|
|
* @return {Function}
|
|
*/
|
|
Util.setCallbackTimeout = function(done, fnName, timeMs, onCatch, onTimerStarted) {
|
|
var timeout = setTimeout(function() {
|
|
if (onCatch) {
|
|
var err = new Error('done() callback timeout of '+ timeMs +' ms was reached while executing "' + fnName + '".' +
|
|
' Make sure to call the done() callback when the operation finishes.');
|
|
onCatch(err, fnName, timeout);
|
|
}
|
|
|
|
}, timeMs);
|
|
|
|
if (onTimerStarted) {
|
|
onTimerStarted(timeout);
|
|
}
|
|
|
|
return function(ex) {
|
|
clearTimeout(timeout);
|
|
done(ex, true);
|
|
};
|
|
};
|
|
|
|
Util.checkFunction = function(name, parent) {
|
|
return parent && (typeof parent[name] == 'function') && parent[name] || false;
|
|
};
|
|
|
|
Util.getTestSuiteName = function(moduleName) {
|
|
var words;
|
|
|
|
moduleName = moduleName.replace(testSuiteNameRegxp, function(match, $0, $1, offset, string) {
|
|
if (!match) {
|
|
return '';
|
|
}
|
|
return (offset > 0 && (string.charAt(offset-1) !== ' ') ? ' ':'') + $1;
|
|
});
|
|
|
|
words = moduleName.split(nameSeparatorRegxp).map(function(word, index, matches) {
|
|
if (word == '/') {
|
|
return ' / ';
|
|
}
|
|
return word.charAt(0).toUpperCase() + word.substr(1);
|
|
});
|
|
|
|
return words.join('');
|
|
};
|
|
|
|
/**
|
|
* A smaller version of util.format that doesn't support json and
|
|
* if a placeholder is missing, it is omitted instead of appended
|
|
*
|
|
* @param f
|
|
* @returns {string}
|
|
*/
|
|
Util.format = function format(f) {
|
|
var i = 1;
|
|
var args = arguments;
|
|
var len = args.length;
|
|
return String(f).replace(formatRegExp, function(x) {
|
|
if (x === '%%') {
|
|
return '%';
|
|
}
|
|
if (i >= len) {
|
|
return x;
|
|
}
|
|
switch (x) {
|
|
case '%s':
|
|
return String(args[i++]);
|
|
case '%d':
|
|
return Number(args[i++]);
|
|
default:
|
|
return x;
|
|
}
|
|
});
|
|
};
|
|
|
|
Util.getScreenshotFileName = function(currentTest, is_error, screenshots_path) {
|
|
var prefix = currentTest.module + '/' + currentTest.name;
|
|
prefix = prefix.replace(/\s/g, '-').replace(/"|'/g, '');
|
|
prefix += is_error ? '_ERROR' : '_FAILED';
|
|
|
|
var d = new Date();
|
|
var dateParts = d.toString().replace(/:/g,'').split(' ');
|
|
dateParts.shift();
|
|
dateParts.pop();
|
|
var dateStamp = dateParts.join('-');
|
|
|
|
return path.resolve(path.join(screenshots_path, prefix + '_' + dateStamp + '.png'));
|
|
};
|
|
|
|
Util.isObject = function(obj) {
|
|
return (typeof obj == 'object') && (obj !== null);
|
|
};
|
|
|
|
Util.processAsyncQueue = function(concurrency, files, cb) {
|
|
var maxWorkers = Math.min(concurrency, files.length);
|
|
var queue = [];
|
|
var add = function(item) {
|
|
queue.push(item);
|
|
};
|
|
|
|
var workers = 0;
|
|
var index = 0;
|
|
var next = function() {
|
|
workers -= 1;
|
|
process();
|
|
};
|
|
|
|
for (var i = 0; i < files.length; i++) {
|
|
add(files[i]);
|
|
}
|
|
|
|
var process = function() {
|
|
while (workers < maxWorkers) {
|
|
workers += 1;
|
|
|
|
if (queue.length) {
|
|
var item = queue.shift();
|
|
cb(item, index++, next);
|
|
}
|
|
}
|
|
};
|
|
|
|
process();
|
|
};
|
|
|
|
Util.getModuleKey = function(filePath, srcFolders, fullPaths) {
|
|
var modulePathParts = filePath.split(path.sep);
|
|
var diffInFolder = '';
|
|
var folder = '';
|
|
var parentFolder = '';
|
|
var moduleName = modulePathParts.pop();
|
|
filePath = modulePathParts.join(path.sep);
|
|
|
|
if (srcFolders) {
|
|
for (var i = 0; i < srcFolders.length; i++) {
|
|
folder = path.resolve(srcFolders[i]);
|
|
if (fullPaths.length > 1) {
|
|
parentFolder = folder.split(path.sep).pop();
|
|
}
|
|
if (filePath.indexOf(folder) === 0) {
|
|
diffInFolder = filePath.substring(folder.length + 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return path.join(parentFolder, diffInFolder, moduleName);
|
|
};
|
|
|
|
Util.showStackTraceWithHeadline = function(headline, stack, isErr) {
|
|
var logMethod = isErr ? 'error' : 'log';
|
|
var stackTrace;
|
|
console[logMethod](Logger.colors.red(headline));
|
|
|
|
if (Array.isArray(stack) && stack.length > 0) {
|
|
stackTrace = Util.stackTraceFilter(stack);
|
|
} else {
|
|
stackTrace = stack;
|
|
}
|
|
|
|
if (stack) {
|
|
console[logMethod](Logger.colors.stack_trace(stackTrace));
|
|
}
|
|
};
|
|
|
|
Util.stackTraceFilter = function(parts) {
|
|
var stack = parts.reduce(function(list, line) {
|
|
if (contains(line, [
|
|
'node_modules',
|
|
'(node.js:',
|
|
'(events.js:'
|
|
])) {
|
|
return list;
|
|
}
|
|
|
|
list.push(line);
|
|
return list;
|
|
}, []);
|
|
|
|
return stack.join('\n');
|
|
};
|
|
|
|
var indentRegex = /^/gm;
|
|
Util.showStackTrace = function(stack) {
|
|
var parts = stack.split('\n');
|
|
var headline = parts.shift();
|
|
|
|
console.log(Logger.colors.red(headline.replace(indentRegex, ' ')));
|
|
if (parts.length > 0) {
|
|
var result = Util.stackTraceFilter(parts);
|
|
console.log(Logger.colors.stack_trace(result.replace(indentRegex, ' ')));
|
|
}
|
|
};
|
|
|
|
Util.symbols = (function() {
|
|
var ok = String.fromCharCode(10004);
|
|
var fail = String.fromCharCode(10006);
|
|
|
|
if (process.platform === 'win32') {
|
|
ok = '\u221A';
|
|
fail = '\u00D7';
|
|
}
|
|
|
|
return {
|
|
ok: ok,
|
|
fail: fail
|
|
};
|
|
})();
|
|
|
|
Util.isErrorObject = function(err) {
|
|
return err instanceof Error || Object.prototype.toString.call(err) === '[object Error]';
|
|
};
|
|
|
|
// util to replace deprecated fs.existsSync
|
|
Util.dirExistsSync = function (path) {
|
|
try {
|
|
return fs.statSync(path).isDirectory();
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
Util.fileExistsSync = function (path) {
|
|
try {
|
|
return fs.statSync(path).isFile();
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
function contains(str, text) {
|
|
if (Array.isArray(text)) {
|
|
for (var i = 0; i < text.length; i++) {
|
|
if (contains(str, text[i])) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return str.indexOf(text) > -1;
|
|
} |