refactor app directory structure and add tests
This commit is contained in:
144
tests/node_modules/nightwatch/lib/runner/cli/child-process.js
generated
vendored
Normal file
144
tests/node_modules/nightwatch/lib/runner/cli/child-process.js
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
var child_process = require('child_process');
|
||||
var util = require('util');
|
||||
var events = require('events');
|
||||
|
||||
var Logger = require('../../util/logger.js');
|
||||
|
||||
function ChildProcess(environment, index, env_output, settings, args) {
|
||||
events.EventEmitter.call(this);
|
||||
|
||||
this.env_output = env_output || [];
|
||||
this.mainModule = process.mainModule.filename;
|
||||
this.index = index;
|
||||
this.itemKey = this.getChildProcessEnvKey(environment);
|
||||
this.startDelay = settings.parallel_process_delay || ChildProcess.defaultStartDelay;
|
||||
this.environment = environment;
|
||||
this.settings = settings;
|
||||
this.child = null;
|
||||
this.globalExitCode = 0;
|
||||
this.processRunning = false;
|
||||
this.env_label = '';
|
||||
this.args = args || [];
|
||||
}
|
||||
|
||||
util.inherits(ChildProcess, events.EventEmitter);
|
||||
|
||||
ChildProcess.prevIndex = 0;
|
||||
ChildProcess.defaultStartDelay = 10;
|
||||
|
||||
ChildProcess.prototype.setLabel = function(label) {
|
||||
this.env_itemKey = label;
|
||||
this.env_label = this.settings.disable_colors ?
|
||||
(' ' + label + ' ') : Logger.colors.yellow(' ' + label + ' ', Logger.colors.background.black);
|
||||
return this;
|
||||
};
|
||||
|
||||
ChildProcess.prototype.run = function(colors, done) {
|
||||
this.availColors = colors;
|
||||
|
||||
var cliArgs = this.getArgs();
|
||||
var env = {};
|
||||
Object.keys(process.env).forEach(function(key) {
|
||||
env[key] = process.env[key];
|
||||
});
|
||||
|
||||
var self = this;
|
||||
|
||||
setTimeout(function() {
|
||||
env.__NIGHTWATCH_PARALLEL_MODE = 1;
|
||||
env.__NIGHTWATCH_ENV = self.environment;
|
||||
env.__NIGHTWATCH_ENV_KEY = self.itemKey;
|
||||
env.__NIGHTWATCH_ENV_LABEL = self.env_itemKey;
|
||||
|
||||
self.child = child_process.spawn(process.execPath, cliArgs, {
|
||||
cwd: process.cwd(),
|
||||
encoding: 'utf8',
|
||||
env: env,
|
||||
stdio: [null, null, null, 'ipc']
|
||||
});
|
||||
|
||||
self.child.on('message', function(data) {
|
||||
self.emit('result', JSON.parse(data));
|
||||
});
|
||||
|
||||
self.processRunning = true;
|
||||
|
||||
if (self.settings.output) {
|
||||
console.log('Started child process for:' + self.env_label);
|
||||
}
|
||||
|
||||
self.child.stdout.on('data', function (data) {
|
||||
self.writeToStdout(data);
|
||||
});
|
||||
|
||||
self.child.stderr.on('data', function (data) {
|
||||
self.writeToStdout(data);
|
||||
});
|
||||
|
||||
self.child.on('exit', function (code) {
|
||||
if (self.settings.output) {
|
||||
console.log('\n >>' + self.env_label + 'finished. ', '\n');
|
||||
}
|
||||
|
||||
if (code) {
|
||||
self.globalExitCode = 2;
|
||||
}
|
||||
self.processRunning = false;
|
||||
done(self.env_output, code);
|
||||
});
|
||||
|
||||
|
||||
}, this.index * this.startDelay);
|
||||
};
|
||||
|
||||
ChildProcess.prototype.getChildProcessEnvKey = function(env) {
|
||||
return env + '_' + (this.index+1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an array of cli arguments to be passed to the child process,
|
||||
* based on the args passed to the main process
|
||||
* @returns {Array}
|
||||
*/
|
||||
ChildProcess.prototype.getArgs = function() {
|
||||
var args = [this.mainModule];
|
||||
args.push.apply(args, this.args);
|
||||
args.push('--parallel-mode');
|
||||
|
||||
return args;
|
||||
};
|
||||
|
||||
|
||||
ChildProcess.prototype.writeToStdout = function(data) {
|
||||
data = data.toString().trim();
|
||||
|
||||
var color_pair = this.availColors[this.index%4];
|
||||
var output = '';
|
||||
|
||||
if (ChildProcess.prevIndex !== this.index) {
|
||||
ChildProcess.prevIndex = this.index;
|
||||
if (this.settings.live_output) {
|
||||
output += '\n';
|
||||
}
|
||||
}
|
||||
|
||||
if (this.settings.output) {
|
||||
if (this.settings.disable_colors) {
|
||||
output += ' ' + this.environment + ' ';
|
||||
} else {
|
||||
output += Logger.colors[color_pair[1]](' ' + this.environment + ' ',
|
||||
Logger.colors.background[color_pair[0]]);
|
||||
}
|
||||
output += ' ';
|
||||
}
|
||||
|
||||
output += data;
|
||||
|
||||
if (this.settings.live_output) {
|
||||
process.stdout.write(output + '\n');
|
||||
} else {
|
||||
this.env_output.push(output);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = ChildProcess;
|
174
tests/node_modules/nightwatch/lib/runner/cli/cli.js
generated
vendored
Normal file
174
tests/node_modules/nightwatch/lib/runner/cli/cli.js
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
var opt = require('optimist');
|
||||
|
||||
module.exports = new (function() {
|
||||
|
||||
var _DEFAULTS_ = {};
|
||||
var _COMMANDS_ = {};
|
||||
|
||||
function Command(name) {
|
||||
this.name = name;
|
||||
_DEFAULTS_[this.name] = {};
|
||||
}
|
||||
|
||||
Command.prototype.demand = function(value) {
|
||||
if (!value && _DEFAULTS_[this.name].demand) {
|
||||
return _DEFAULTS_[this.name].demand;
|
||||
}
|
||||
_DEFAULTS_[this.name].demand = value;
|
||||
return this;
|
||||
};
|
||||
|
||||
Command.prototype.description = function(value) {
|
||||
if (!value && _DEFAULTS_[this.name].description) {
|
||||
return _DEFAULTS_[this.name].alias;
|
||||
}
|
||||
_DEFAULTS_[this.name].description = value;
|
||||
return this;
|
||||
};
|
||||
|
||||
Command.prototype.alias = function(value) {
|
||||
if (!value && _DEFAULTS_[this.name].alias) {
|
||||
return _DEFAULTS_[this.name].alias;
|
||||
}
|
||||
_DEFAULTS_[this.name].alias = value;
|
||||
return this;
|
||||
};
|
||||
|
||||
Command.prototype.defaults = function(value) {
|
||||
if (!value && _DEFAULTS_[this.name]['default']) {
|
||||
return _DEFAULTS_[this.name]['default'];
|
||||
}
|
||||
_DEFAULTS_[this.name]['default'] = value;
|
||||
return this;
|
||||
};
|
||||
|
||||
Command.prototype.isDefault = function(value) {
|
||||
return _DEFAULTS_[this.name]['default'] === value;
|
||||
};
|
||||
|
||||
|
||||
this.showHelp = function() {
|
||||
return opt.showHelp();
|
||||
};
|
||||
|
||||
this.command = function(name) {
|
||||
if (_COMMANDS_[name]) {
|
||||
return _COMMANDS_[name];
|
||||
}
|
||||
_COMMANDS_[name] = new Command(name);
|
||||
|
||||
return _COMMANDS_[name];
|
||||
};
|
||||
|
||||
this.init = function() {
|
||||
var argv = opt.usage('Usage: $0 [source] [options]')
|
||||
.option('source', {
|
||||
string : true
|
||||
})
|
||||
.options(_DEFAULTS_).argv;
|
||||
|
||||
return argv;
|
||||
};
|
||||
|
||||
this.setup = function() {
|
||||
// CLI definitions
|
||||
|
||||
// $ nightwatch -c
|
||||
// $ nightwatch --config
|
||||
this.command('config')
|
||||
.demand(true)
|
||||
.description('Path to configuration file')
|
||||
.alias('c')
|
||||
.defaults('./nightwatch.json');
|
||||
|
||||
// $ nightwatch -o
|
||||
// $ nightwatch --output
|
||||
this.command('output')
|
||||
.description('Where to save the (JUnit XML) test reports.')
|
||||
.alias('o')
|
||||
.defaults('tests_output');
|
||||
|
||||
// $ nightwatch -r
|
||||
// $ nightwatch --reporter
|
||||
this.command('reporter')
|
||||
.description('Name of a predefined reporter (e.g. junit) or path to a custom reporter file to use.')
|
||||
.alias('r')
|
||||
.defaults('junit');
|
||||
|
||||
// $ nightwatch -e
|
||||
// $ nightwatch --env saucelabs
|
||||
this.command('env')
|
||||
.description('Testing environment to use.')
|
||||
.alias('e')
|
||||
.defaults('default');
|
||||
|
||||
// $ nightwatch --verbose
|
||||
this.command('verbose')
|
||||
.description('Turns on selenium command logging during the session.');
|
||||
|
||||
// $ nightwatch -t
|
||||
// $ nightwatch --test
|
||||
this.command('test')
|
||||
.description('Runs a single test.')
|
||||
.alias('t');
|
||||
|
||||
// $ nightwatch --testcase
|
||||
this.command('testcase')
|
||||
.description('Used only together with --test. Runs the specified testcase from the current suite/module.');
|
||||
|
||||
// $ nightwatch -g
|
||||
// $ nightwatch --group
|
||||
this.command('group')
|
||||
.description('Runs a group of tests (i.e. a folder)')
|
||||
.alias('g');
|
||||
|
||||
// $ nightwatch -s
|
||||
// $ nightwatch --skipgroup
|
||||
this.command('skipgroup')
|
||||
.description('Skips one or several (comma separated) group of tests.')
|
||||
.alias('s');
|
||||
|
||||
// $ nightwatch -f
|
||||
// $ nightwatch --filter
|
||||
this.command('filter')
|
||||
.description('Specify a filter (glob expression) as the file name format to use when loading the files.')
|
||||
.defaults('')
|
||||
.alias('f');
|
||||
|
||||
// $ nightwatch -a
|
||||
// $ nightwatch --tag
|
||||
this.command('tag')
|
||||
.description('Only run tests with the given tag.')
|
||||
.defaults('')
|
||||
.alias('a');
|
||||
|
||||
// $ nightwatch --skiptags
|
||||
this.command('skiptags')
|
||||
.description('Skips tests that have the specified tag or tags (comma separated).');
|
||||
|
||||
// $ nightwatch --retries
|
||||
this.command('retries')
|
||||
.description('Retries failed or errored testcases up <n> times.');
|
||||
|
||||
// $ nightwatch --suiteRetries
|
||||
this.command('suiteRetries')
|
||||
.description('Retries failed or errored testsuites up <n> times.');
|
||||
|
||||
// $ nightwatch -h
|
||||
// $ nightwatch --help
|
||||
this.command('help')
|
||||
.description('Shows this help.')
|
||||
.alias('h');
|
||||
|
||||
// $ nightwatch -v
|
||||
// $ nightwatch --version
|
||||
this.command('version')
|
||||
.alias('v')
|
||||
.description('Shows version information.');
|
||||
|
||||
return this;
|
||||
};
|
||||
})();
|
977
tests/node_modules/nightwatch/lib/runner/cli/clirunner.js
generated
vendored
Normal file
977
tests/node_modules/nightwatch/lib/runner/cli/clirunner.js
generated
vendored
Normal file
@@ -0,0 +1,977 @@
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var Q = require('q');
|
||||
var clone = require('lodash.clone');
|
||||
var defaults = require('lodash.defaultsdeep');
|
||||
|
||||
var Runner = require('../run.js');
|
||||
var Logger = require('../../util/logger.js');
|
||||
var Utils = require('../../util/utils.js');
|
||||
var Selenium = require('../selenium.js');
|
||||
var ChildProcess = require('./child-process.js');
|
||||
var ErrorHandler = require('./errorhandler.js');
|
||||
|
||||
var SETTINGS_DEPRECTED_VAL = './settings.json';
|
||||
var SETTINGS_JS_FILE = './nightwatch.conf.js';
|
||||
|
||||
function CliRunner(argv) {
|
||||
this.settings = null;
|
||||
this.argv = argv;
|
||||
this.test_settings = null;
|
||||
this.output_folder = '';
|
||||
this.parallelMode = false;
|
||||
this.runningProcesses = {};
|
||||
this.cli = require('./cli.js');
|
||||
}
|
||||
|
||||
CliRunner.prototype = {
|
||||
/**
|
||||
* @param {function} [done]
|
||||
* @deprecated - use .setup instead
|
||||
* @returns {CliRunner}
|
||||
*/
|
||||
init : function(done) {
|
||||
this
|
||||
.readSettings()
|
||||
.parseTestSettings({}, done);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {object} [settings]
|
||||
* @param {function} [done]
|
||||
* @returns {CliRunner}
|
||||
*/
|
||||
setup : function(settings, done) {
|
||||
this
|
||||
.readSettings()
|
||||
.parseTestSettings(settings, done);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Read the provided config json file; defaults to settings.json if one isn't provided
|
||||
*/
|
||||
readSettings : function() {
|
||||
// use default nightwatch.json file if we haven't received another value
|
||||
|
||||
if (this.cli.command('config').isDefault(this.argv.config)) {
|
||||
var defaultValue = this.cli.command('config').defaults();
|
||||
var localJsValue = path.resolve(SETTINGS_JS_FILE);
|
||||
|
||||
if (Utils.fileExistsSync(SETTINGS_JS_FILE)) {
|
||||
this.argv.config = localJsValue;
|
||||
} else if (Utils.fileExistsSync(defaultValue)) {
|
||||
this.argv.config = path.join(path.resolve('./'), this.argv.config);
|
||||
} else if (Utils.fileExistsSync(SETTINGS_DEPRECTED_VAL)) {
|
||||
this.argv.config = path.join(path.resolve('./'), SETTINGS_DEPRECTED_VAL);
|
||||
} else {
|
||||
var binFolder = path.resolve(__dirname + '/../../../bin');
|
||||
var defaultFile = path.join(binFolder, this.argv.config);
|
||||
if (Utils.fileExistsSync(defaultFile)) {
|
||||
this.argv.config = defaultFile;
|
||||
} else {
|
||||
this.argv.config = path.join(binFolder, SETTINGS_DEPRECTED_VAL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.argv.config = path.resolve(this.argv.config);
|
||||
}
|
||||
|
||||
this.argv.env = typeof this.argv.env == 'string' ? this.argv.env : 'default';
|
||||
|
||||
// reading the settings file
|
||||
try {
|
||||
this.settings = require(this.argv.config);
|
||||
this.replaceEnvVariables();
|
||||
|
||||
this.manageSelenium = !this.isParallelMode() && this.settings.selenium &&
|
||||
this.settings.selenium.start_process || false;
|
||||
|
||||
if (typeof this.settings.src_folders == 'string') {
|
||||
this.settings.src_folders = [this.settings.src_folders];
|
||||
}
|
||||
|
||||
this.settings.output = this.settings.output || typeof this.settings.output == 'undefined';
|
||||
this.settings.detailed_output = this.settings.detailed_output || typeof this.settings.detailed_output == 'undefined';
|
||||
} catch (ex) {
|
||||
Logger.error(ex.stack);
|
||||
this.settings = {};
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Looks for pattern ${VAR_NAME} in settings
|
||||
* @param {Object} [target]
|
||||
*/
|
||||
replaceEnvVariables : function(target) {
|
||||
target = target || this.settings;
|
||||
for (var key in target) {
|
||||
switch(typeof target[key]) {
|
||||
case 'object':
|
||||
this.replaceEnvVariables(target[key]);
|
||||
break;
|
||||
case 'string':
|
||||
target[key] = target[key].replace(/\$\{(\w+)\}/g, function(match, varName) {
|
||||
return process.env[varName] || '${' + varName + '}';
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Reads globals from an external js or json file set in the settings file
|
||||
* @return {CliRunner}
|
||||
*/
|
||||
readExternalGlobals : function () {
|
||||
if (!this.settings.globals_path) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var fullPath = path.resolve(this.settings.globals_path);
|
||||
|
||||
try {
|
||||
var externalGlobals = require(fullPath);
|
||||
|
||||
if (!externalGlobals) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// if we already have globals, make a copy of them
|
||||
var globals = this.test_settings.globals ? clone(this.test_settings.globals, true) : {};
|
||||
|
||||
if (externalGlobals.hasOwnProperty(this.argv.env)) {
|
||||
for (var prop in externalGlobals[this.argv.env]) {
|
||||
externalGlobals[prop] = externalGlobals[this.argv.env][prop];
|
||||
}
|
||||
}
|
||||
|
||||
defaults(globals, externalGlobals);
|
||||
this.test_settings.globals = globals;
|
||||
|
||||
return this;
|
||||
} catch (err) {
|
||||
var originalMsg = Logger.colors.red(err.name + ': ' + err.message);
|
||||
|
||||
err.name = 'Error reading external global file failed';
|
||||
err.message = 'using '+ fullPath + ':\n' + originalMsg;
|
||||
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {CliRunner}
|
||||
*/
|
||||
setOutputFolder : function() {
|
||||
var isDisabled = this.settings.output_folder === false && typeof(this.test_settings.output_folder) == 'undefined' ||
|
||||
this.test_settings.output_folder === false;
|
||||
var isDefault = this.cli.command('output').isDefault(this.argv.output);
|
||||
var folder = this.test_settings.output_folder || this.settings.output_folder;
|
||||
|
||||
this.output_folder = isDisabled ? false : (isDefault && folder || this.argv.output);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
singleTestRun: function () {
|
||||
return typeof this.argv.test == 'string';
|
||||
},
|
||||
|
||||
singleSourceFile: function() {
|
||||
if (this.singleTestRun()) {
|
||||
return fs.statSync(this.argv.test).isFile();
|
||||
}
|
||||
|
||||
return (Array.isArray(this.argv._source) && this.argv._source.length == 1) && fs.statSync(this.argv._source[0]).isFile();
|
||||
},
|
||||
|
||||
getTestSourceForSingle: function(targetPath) {
|
||||
var testsource;
|
||||
|
||||
if (targetPath && path.resolve(targetPath) === targetPath) {
|
||||
testsource = targetPath;
|
||||
} else {
|
||||
testsource = path.join(process.cwd(), targetPath);
|
||||
}
|
||||
|
||||
if (testsource.substr(-3) != '.js') {
|
||||
testsource += '.js';
|
||||
}
|
||||
|
||||
return testsource;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the path where the tests are located
|
||||
* @returns {*}
|
||||
*/
|
||||
getTestSource : function() {
|
||||
var testsource;
|
||||
|
||||
if (this.isTestWorker() || this.singleSourceFile()) {
|
||||
testsource = this.getTestSourceForSingle(this.argv.test || this.argv._source[0]);
|
||||
} else {
|
||||
if (this.argv.testcase) {
|
||||
this.argv.testcase = null;
|
||||
|
||||
if (this.test_settings.output) {
|
||||
ErrorHandler.logWarning('Option --testcase used without --test is ignored.');
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(this.argv._source) && (this.argv._source.length > 0)) {
|
||||
testsource = this.argv._source;
|
||||
} else if (this.argv.group) {
|
||||
|
||||
// add support for multiple groups
|
||||
if (typeof this.argv.group == 'string') {
|
||||
this.argv.group = this.argv.group.split(',');
|
||||
}
|
||||
|
||||
var groupTestsource = this.findGroupPathMultiple(this.argv.group);
|
||||
|
||||
// If a group does not exist in the multiple src folder case, it is removed
|
||||
// from the test path list.
|
||||
if (this.settings.src_folders.length === 1) {
|
||||
|
||||
// any incorrect path here will result in a run error
|
||||
testsource = groupTestsource;
|
||||
|
||||
} else {
|
||||
|
||||
// only when all groups fail to match will there be a run error
|
||||
testsource = groupTestsource.filter(Utils.dirExistsSync);
|
||||
|
||||
if (this.argv.verbose) {
|
||||
var ignoredSource = groupTestsource.filter(function(path) {
|
||||
return testsource.indexOf(path) === -1;
|
||||
});
|
||||
|
||||
if (ignoredSource.length) {
|
||||
Logger.warn('The following group paths were not found and will be excluded from the run:\n - ' + ignoredSource.join('\n - '));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
testsource = this.settings.src_folders;
|
||||
}
|
||||
}
|
||||
|
||||
return testsource;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets test paths from each of the src folders for a single group.
|
||||
*
|
||||
* @param {string} groupName
|
||||
* @return {Array}
|
||||
*/
|
||||
findGroupPath : function(groupName) {
|
||||
var fullGroupPath = path.resolve(groupName);
|
||||
|
||||
// for each src folder, append the group to the path
|
||||
// to resolve the full test path
|
||||
|
||||
return this.settings.src_folders.map(function(srcFolder) {
|
||||
|
||||
var fullSrcFolder = path.resolve(srcFolder);
|
||||
if (fullGroupPath.indexOf(fullSrcFolder) === 0) {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
return path.join(srcFolder, groupName);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets test paths for tests from any number of groups.
|
||||
*
|
||||
* @param {Array} groups
|
||||
*/
|
||||
findGroupPathMultiple : function(groups) {
|
||||
var paths = [];
|
||||
|
||||
groups.forEach(function(groupName) {
|
||||
|
||||
// findGroupPath will return an array of paths
|
||||
|
||||
paths = paths.concat(this.findGroupPath(groupName));
|
||||
|
||||
}.bind(this));
|
||||
|
||||
return paths;
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts the selenium server process
|
||||
* @param {function} [callback]
|
||||
* @returns {CliRunner}
|
||||
*/
|
||||
startSelenium : function(callback) {
|
||||
callback = callback || function() {};
|
||||
|
||||
if (this.isTestWorker()) {
|
||||
callback();
|
||||
return this;
|
||||
}
|
||||
|
||||
var globalsContext = this.test_settings && this.test_settings.globals || null;
|
||||
// adding a link to the test_settings object on the globals context
|
||||
if (globalsContext) {
|
||||
globalsContext.test_settings = this.test_settings;
|
||||
}
|
||||
|
||||
var beforeGlobal = Utils.checkFunction('before', globalsContext) || function(done) {done();};
|
||||
var self = this;
|
||||
if (!this.manageSelenium) {
|
||||
beforeGlobal.call(globalsContext, function() {
|
||||
callback();
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
this.settings.parallelMode = this.parallelMode;
|
||||
|
||||
beforeGlobal.call(globalsContext, function() {
|
||||
Selenium.startServer(self.settings, function(error, child, error_out, exitcode) {
|
||||
if (error) {
|
||||
console.error('There was an error while starting the Selenium server:');
|
||||
ErrorHandler.handle({
|
||||
message : error_out
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
});
|
||||
});
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Stops the selenium server if it is running
|
||||
* @return {*|promise}
|
||||
*/
|
||||
stopSelenium : function() {
|
||||
var deferred = Q.defer();
|
||||
|
||||
if (this.manageSelenium) {
|
||||
Selenium.stopServer(function() {
|
||||
deferred.resolve();
|
||||
});
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts the test runner
|
||||
*
|
||||
* @param {function} [finished] optional callback
|
||||
* @returns {CliRunner}
|
||||
*/
|
||||
runTests : function(finished) {
|
||||
if (this.parallelMode) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var handleError = ErrorHandler.handle;
|
||||
|
||||
this.startSelenium(function() {
|
||||
self.runner(function(err, results) {
|
||||
self.stopSelenium().then(function() {
|
||||
if (self.isTestWorker()) {
|
||||
handleError(err, results, finished);
|
||||
return;
|
||||
}
|
||||
|
||||
self.runGlobalAfter().then(function (ex) {
|
||||
handleError(ex || err, results, finished);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
runner : function(fn) {
|
||||
var testRunner = this.settings.test_runner || 'default';
|
||||
var testRunnerType = testRunner.type ? testRunner.type : testRunner;
|
||||
|
||||
// getTestSource() will throw on an error, so we need
|
||||
// to wrap and pass along any error that does occur
|
||||
// to the callback fn
|
||||
|
||||
var source;
|
||||
try {
|
||||
source = this.getTestSource();
|
||||
} catch (err) {
|
||||
fn(err, {});
|
||||
return;
|
||||
}
|
||||
|
||||
switch (testRunnerType) {
|
||||
case 'default':
|
||||
var runner = new Runner(source, this.test_settings, {
|
||||
output_folder : this.output_folder,
|
||||
src_folders : this.settings.src_folders,
|
||||
live_output : this.settings.live_output,
|
||||
detailed_output : this.settings.detailed_output,
|
||||
start_session: this.startSession,
|
||||
reporter : this.argv.reporter,
|
||||
testcase : this.argv.testcase,
|
||||
end_session_on_fail : this.endSessionOnFail,
|
||||
retries : this.argv.retries,
|
||||
test_worker : this.isTestWorker(),
|
||||
suite_retries : this.argv.suiteRetries
|
||||
}, fn);
|
||||
return runner.run();
|
||||
|
||||
case 'mocha':
|
||||
var MochaNightwatch = require('mocha-nightwatch');
|
||||
var mochaOpts = testRunner.options || {
|
||||
ui : 'bdd'
|
||||
};
|
||||
|
||||
var mocha = new MochaNightwatch(mochaOpts);
|
||||
var nightwatch = require('../../index.js');
|
||||
|
||||
Runner.readPaths(source, this.test_settings, function(error, modulePaths) {
|
||||
if (error) {
|
||||
fn(error, {});
|
||||
return;
|
||||
}
|
||||
modulePaths.forEach(function(file) {
|
||||
mocha.addFile(file);
|
||||
});
|
||||
|
||||
mocha.run(nightwatch, this.test_settings, function(failures) {
|
||||
fn(null, {
|
||||
failed : failures
|
||||
});
|
||||
|
||||
if (failures) {
|
||||
process.exit(10);
|
||||
}
|
||||
});
|
||||
|
||||
}.bind(this));
|
||||
|
||||
return mocha;
|
||||
}
|
||||
},
|
||||
|
||||
inheritFromDefaultEnv : function() {
|
||||
if (this.argv.env == 'default') {
|
||||
return;
|
||||
}
|
||||
var defaultEnv = this.settings.test_settings['default'] || {};
|
||||
defaults(this.test_settings, defaultEnv);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
runGlobalAfter : function() {
|
||||
var deferred = Q.defer();
|
||||
|
||||
var globalsContext = this.test_settings && this.test_settings.globals || null;
|
||||
var afterGlobal = Utils.checkFunction('after', globalsContext) || function(done) {done();};
|
||||
try {
|
||||
afterGlobal.call(globalsContext, function done() {
|
||||
deferred.resolve(null);
|
||||
});
|
||||
} catch (ex) {
|
||||
deferred.resolve(ex);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Validates and parses the test settings
|
||||
* @param {object} [settings]
|
||||
* @param {function} [done]
|
||||
* @returns {CliRunner}
|
||||
*/
|
||||
parseTestSettings : function(settings, done) {
|
||||
// checking if the env passed is valid
|
||||
if (!this.settings.test_settings) {
|
||||
throw new Error('No testing environment specified.');
|
||||
}
|
||||
|
||||
var envs = this.argv.env.split(',');
|
||||
for (var i = 0; i < envs.length; i++) {
|
||||
if (!(envs[i] in this.settings.test_settings)) {
|
||||
throw new Error('Invalid testing environment specified: ' + envs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (envs.length > 1) {
|
||||
this.setupParallelMode(envs, done);
|
||||
return this;
|
||||
}
|
||||
|
||||
this.initTestSettings(this.argv.env, settings);
|
||||
|
||||
if (this.parallelModeWorkers()) {
|
||||
this.setupParallelMode(null, done);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
setGlobalOutputOptions: function () {
|
||||
this.test_settings.output = this.test_settings.output || (this.settings.output && typeof this.test_settings.output == 'undefined');
|
||||
this.test_settings.silent = this.test_settings.silent || typeof this.test_settings.silent == 'undefined';
|
||||
if (this.argv.verbose) {
|
||||
this.test_settings.silent = false;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the specific test settings for the specified environment
|
||||
* @param {string} [env]
|
||||
* @param {object} [settings]
|
||||
* @returns {CliRunner}
|
||||
*/
|
||||
initTestSettings : function(env, settings) {
|
||||
// picking the environment specific test settings
|
||||
this.test_settings = env && this.settings.test_settings[env] || {};
|
||||
|
||||
if (env) {
|
||||
this.test_settings.custom_commands_path = this.settings.custom_commands_path || '';
|
||||
this.test_settings.custom_assertions_path = this.settings.custom_assertions_path || '';
|
||||
this.test_settings.page_objects_path = this.settings.page_objects_path || '';
|
||||
|
||||
this.inheritFromDefaultEnv();
|
||||
this.updateTestSettings(settings || {});
|
||||
this.readExternalGlobals();
|
||||
}
|
||||
|
||||
this.setOutputFolder();
|
||||
this.setGlobalOutputOptions();
|
||||
|
||||
if (typeof this.test_settings.test_workers != 'undefined') {
|
||||
this.settings.test_workers = this.test_settings.test_workers;
|
||||
} else if (typeof this.settings.test_workers != 'undefined') {
|
||||
this.test_settings.test_workers = this.settings.test_workers;
|
||||
}
|
||||
|
||||
if (typeof this.test_settings.test_runner != 'undefined') {
|
||||
this.settings.test_runner = this.test_settings.test_runner;
|
||||
}
|
||||
|
||||
if (typeof this.test_settings.detailed_output != 'undefined') {
|
||||
this.settings.detailed_output = this.test_settings.detailed_output;
|
||||
}
|
||||
|
||||
if (typeof this.argv.skipgroup == 'string') {
|
||||
this.test_settings.skipgroup = this.argv.skipgroup.split(',');
|
||||
}
|
||||
|
||||
if (this.argv.filter) {
|
||||
this.test_settings.filename_filter = this.argv.filter;
|
||||
}
|
||||
|
||||
if (this.argv.tag) {
|
||||
this.test_settings.tag_filter = this.argv.tag;
|
||||
}
|
||||
|
||||
if (typeof this.argv.skiptags == 'string') {
|
||||
this.test_settings.skiptags = this.argv.skiptags.split(',');
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Object} [test_settings]
|
||||
* @returns {CliRunner}
|
||||
*/
|
||||
updateTestSettings : function(test_settings) {
|
||||
if (this.parallelMode && !this.parallelModeWorkers()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (test_settings && typeof test_settings == 'object') {
|
||||
for (var key in test_settings) {
|
||||
this.test_settings[key] = test_settings[key];
|
||||
}
|
||||
}
|
||||
|
||||
this.settings.selenium = this.settings.selenium || {};
|
||||
|
||||
// overwrite selenium settings per environment
|
||||
if (Utils.isObject(this.test_settings.selenium)) {
|
||||
for (var prop in this.test_settings.selenium) {
|
||||
this.settings.selenium[prop] = this.test_settings.selenium[prop];
|
||||
}
|
||||
}
|
||||
|
||||
this.manageSelenium = !this.isParallelMode() && this.settings.selenium.start_process || false;
|
||||
this.startSession = this.settings.selenium.start_session || typeof this.settings.selenium.start_session == 'undefined';
|
||||
|
||||
this.mergeSeleniumOptions();
|
||||
this.disableCliColorsIfNeeded();
|
||||
|
||||
this.endSessionOnFail = typeof this.settings.end_session_on_fail == 'undefined' || this.settings.end_session_on_fail;
|
||||
if (typeof this.test_settings.end_session_on_fail != 'undefined') {
|
||||
this.endSessionOnFail = this.test_settings.end_session_on_fail;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
disableCliColorsIfNeeded : function() {
|
||||
if (this.settings.disable_colors || this.test_settings.disable_colors) {
|
||||
Logger.disableColors();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Backwards compatible method which attempts to merge deprecated driver specific options for selenium
|
||||
* @returns {CliRunner}
|
||||
*/
|
||||
mergeSeleniumOptions : function() {
|
||||
if (!this.manageSelenium) {
|
||||
return this;
|
||||
}
|
||||
this.settings.selenium.cli_args = this.settings.selenium.cli_args || {};
|
||||
this.mergeCliArgs();
|
||||
|
||||
var deprecationNotice = function(propertyName, newSettingName) {
|
||||
ErrorHandler.logWarning('DEPRECATION NOTICE: Property ' + propertyName + ' is deprecated since v0.5. Please' +
|
||||
' use the "cli_args" object on the "selenium" property to define "' + newSettingName + '". E.g.:');
|
||||
var demoObj = '{\n' +
|
||||
' "cli_args": {\n' +
|
||||
' "'+ Logger.colors.yellow(newSettingName) +'": "<VALUE>"\n' +
|
||||
' }\n' +
|
||||
'}';
|
||||
|
||||
console.log(demoObj, '\n');
|
||||
};
|
||||
|
||||
if (this.test_settings.firefox_profile) {
|
||||
deprecationNotice('firefox_profile', 'webdriver.firefox.profile');
|
||||
this.settings.selenium.cli_args['webdriver.firefox.profile'] = this.test_settings.firefox_profile;
|
||||
}
|
||||
if (this.test_settings.chrome_driver) {
|
||||
deprecationNotice('chrome_driver', 'webdriver.chrome.driver');
|
||||
this.settings.selenium.cli_args['webdriver.chrome.driver'] = this.test_settings.chrome_driver;
|
||||
}
|
||||
if (this.test_settings.ie_driver) {
|
||||
deprecationNotice('ie_driver', 'webdriver.ie.driver');
|
||||
this.settings.selenium.cli_args['webdriver.ie.driver'] = this.test_settings.ie_driver;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Merge current environment specific cli_args into the main cli_args object to be passed to selenium
|
||||
*
|
||||
* @returns {CliRunner}
|
||||
*/
|
||||
mergeCliArgs : function() {
|
||||
if (Utils.isObject(this.test_settings.cli_args)) {
|
||||
for (var prop in this.test_settings.cli_args) {
|
||||
if (this.test_settings.cli_args.hasOwnProperty(prop)) {
|
||||
this.settings.selenium.cli_args[prop] = this.test_settings.cli_args[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Parallelism related
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
isParallelMode : function() {
|
||||
return process.env.__NIGHTWATCH_PARALLEL_MODE === '1';
|
||||
},
|
||||
|
||||
isTestWorker : function() {
|
||||
return this.isParallelMode() && this.argv['test-worker'];
|
||||
},
|
||||
|
||||
parallelModeWorkers: function () {
|
||||
return !this.isParallelMode() && !this.singleSourceFile() && (this.settings.test_workers === true ||
|
||||
Utils.isObject(this.settings.test_workers) && this.settings.test_workers.enabled);
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables parallel execution mode
|
||||
* @param {Array} envs
|
||||
* @param {function} [done]
|
||||
* @returns {CliRunner}
|
||||
*/
|
||||
setupParallelMode : function(envs, done) {
|
||||
this.parallelMode = true;
|
||||
var self = this;
|
||||
|
||||
this.startSelenium(function() {
|
||||
self.startChildProcesses(envs, function(code) {
|
||||
self.stopSelenium().then(function() {
|
||||
if (self.parallelModeWorkers()) {
|
||||
return self.runGlobalAfter();
|
||||
}
|
||||
|
||||
return true;
|
||||
}).then(function() {
|
||||
if (done) {
|
||||
try {
|
||||
done(self.childProcessOutput, code);
|
||||
} catch (err) {
|
||||
done(err);
|
||||
}
|
||||
}
|
||||
|
||||
if (code) {
|
||||
process.exit(code);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
getAvailableColors : function () {
|
||||
var availColors = [
|
||||
['red', 'light_gray'],
|
||||
['green', 'black'],
|
||||
['blue', 'light_gray'],
|
||||
['magenta', 'light_gray']
|
||||
];
|
||||
var currentIndex = availColors.length, temporaryValue, randomIndex;
|
||||
|
||||
// While there remain elements to shuffle...
|
||||
while (0 !== currentIndex) {
|
||||
randomIndex = Math.floor(Math.random() * currentIndex);
|
||||
currentIndex -= 1;
|
||||
|
||||
// And swap it with the current element.
|
||||
temporaryValue = availColors[currentIndex];
|
||||
availColors[currentIndex] = availColors[randomIndex];
|
||||
availColors[randomIndex] = temporaryValue;
|
||||
}
|
||||
return availColors;
|
||||
},
|
||||
|
||||
/**
|
||||
* Start a new child process for each environment
|
||||
* @param {Array} envs
|
||||
* @param {function} doneCallback
|
||||
*/
|
||||
startChildProcesses : function(envs, doneCallback) {
|
||||
doneCallback = doneCallback || function() {};
|
||||
|
||||
var availColors = this.getAvailableColors();
|
||||
|
||||
this.childProcessOutput = {};
|
||||
ChildProcess.prevIndex = 0;
|
||||
|
||||
var args = this.getChildProcessArgs(envs);
|
||||
|
||||
if (envs === null) {
|
||||
this.startTestWorkers(availColors, args, doneCallback);
|
||||
return this;
|
||||
}
|
||||
|
||||
this.startEnvChildren(envs, availColors, args, doneCallback);
|
||||
},
|
||||
|
||||
startEnvChildren : function(envs, availColors, args, doneCallback) {
|
||||
var self = this;
|
||||
var globalExitCode = 0;
|
||||
|
||||
envs.forEach(function(environment, index) {
|
||||
self.childProcessOutput[environment] = [];
|
||||
var childArgs = args.slice();
|
||||
childArgs.push('--env', environment);
|
||||
|
||||
var child = new ChildProcess(environment, index, self.childProcessOutput[environment], self.settings, childArgs);
|
||||
child.setLabel(environment + ' environment');
|
||||
self.runningProcesses[child.itemKey] = child;
|
||||
self.runningProcesses[child.itemKey].run(availColors, function(output, exitCode) {
|
||||
if (exitCode > 0) {
|
||||
globalExitCode = exitCode;
|
||||
}
|
||||
if (self.processesRunning() === 0) {
|
||||
if (!self.settings.live_output) {
|
||||
self.printChildProcessOutput();
|
||||
}
|
||||
doneCallback(globalExitCode);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
getChildProcessArgs : function(envs) {
|
||||
var childProcessArgs = [];
|
||||
var arg;
|
||||
|
||||
for (var i = 2; i < process.argv.length; i++) {
|
||||
arg = process.argv[i];
|
||||
if (envs && (arg == '-e' || arg == '--env')) {
|
||||
i++;
|
||||
} else {
|
||||
childProcessArgs.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
return childProcessArgs;
|
||||
},
|
||||
|
||||
startTestWorkers : function(availColors, args, doneCallback) {
|
||||
var workerCount = this.getTestWorkersCount();
|
||||
var source = this.getTestSource();
|
||||
var self = this;
|
||||
var globalExitCode = 0;
|
||||
var globalStartTime = new Date().getTime();
|
||||
var globalResults = {
|
||||
errmessages : [],
|
||||
modules : {},
|
||||
passed : 0,
|
||||
failed : 0,
|
||||
errors : 0,
|
||||
skipped : 0,
|
||||
tests : 0
|
||||
};
|
||||
|
||||
var Reporter = require('../../runner/reporter.js');
|
||||
var globalReporter = new Reporter(globalResults, {}, globalStartTime, {start_session: this.startSession});
|
||||
|
||||
Runner.readPaths(source, this.test_settings, function(error, modulePaths) {
|
||||
if (error) {
|
||||
ErrorHandler.handle(error, null, doneCallback);
|
||||
return;
|
||||
}
|
||||
|
||||
var remaining = modulePaths.length;
|
||||
Utils.processAsyncQueue(workerCount, modulePaths, function(modulePath, index, next) {
|
||||
var outputLabel = Utils.getModuleKey(modulePath, self.settings.src_folders, modulePaths);
|
||||
var childOutput = self.childProcessOutput[outputLabel] = [];
|
||||
|
||||
// arguments to the new child process, essentially running a single test suite
|
||||
var childArgs = args.slice();
|
||||
childArgs.push('--test', modulePath, '--test-worker');
|
||||
|
||||
var settings = clone(self.settings);
|
||||
settings.output = settings.output && settings.detailed_output;
|
||||
|
||||
var child = new ChildProcess(outputLabel, index, childOutput, settings, childArgs);
|
||||
child.setLabel(outputLabel);
|
||||
child.on('result', function(childResult) {
|
||||
switch (childResult.type) {
|
||||
case 'testsuite_finished':
|
||||
globalResults.modules[childResult.moduleKey] = childResult.results;
|
||||
if (childResult.errmessages.length) {
|
||||
globalResults.errmessages.concat(childResult.errmessages);
|
||||
}
|
||||
|
||||
globalResults.passed += childResult.passed;
|
||||
globalResults.failed += childResult.failed;
|
||||
globalResults.errors += childResult.errors;
|
||||
globalResults.skipped += childResult.skipped;
|
||||
globalResults.tests += childResult.tests;
|
||||
|
||||
self.printChildProcessOutput(childResult.itemKey);
|
||||
break;
|
||||
case 'testsuite_started':
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
self.runningProcesses[child.itemKey] = child;
|
||||
self.runningProcesses[child.itemKey].run(availColors, function (output, exitCode) {
|
||||
if (exitCode > 0) {
|
||||
globalExitCode = exitCode;
|
||||
}
|
||||
remaining -=1;
|
||||
if (remaining > 0) {
|
||||
next();
|
||||
} else {
|
||||
|
||||
if (!self.settings.live_output) {
|
||||
globalReporter.printTotalResults();
|
||||
}
|
||||
|
||||
doneCallback(globalExitCode);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
printChildProcessOutput : function(label) {
|
||||
var self = this;
|
||||
|
||||
if (label) {
|
||||
self.childProcessOutput[label] = self.childProcessOutput[label].filter(function(item) {
|
||||
return item !== '';
|
||||
}).map(function(item) {
|
||||
if (item == '\\n') {
|
||||
item = '\n';
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
self.childProcessOutput[label].forEach(function(output) {
|
||||
process.stdout.write(output + '\n');
|
||||
});
|
||||
|
||||
self.childProcessOutput[label].length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Object.keys(this.childProcessOutput).forEach(function(environment) {
|
||||
self.printChildProcessOutput(environment);
|
||||
});
|
||||
},
|
||||
|
||||
getTestWorkersCount : function() {
|
||||
var workers = 1;
|
||||
if (this.settings.test_workers === true || this.settings.test_workers.workers === 'auto') {
|
||||
workers = require('os').cpus().length;
|
||||
} else if ('number' === typeof this.settings.test_workers.workers) {
|
||||
workers = this.settings.test_workers.workers;
|
||||
}
|
||||
|
||||
return workers;
|
||||
},
|
||||
|
||||
processesRunning : function() {
|
||||
var running = 0;
|
||||
for (var item in this.runningProcesses) {
|
||||
if (this.runningProcesses.hasOwnProperty(item) && this.runningProcesses[item].processRunning) {
|
||||
running += 1;
|
||||
}
|
||||
}
|
||||
return running;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = CliRunner;
|
70
tests/node_modules/nightwatch/lib/runner/cli/errorhandler.js
generated
vendored
Normal file
70
tests/node_modules/nightwatch/lib/runner/cli/errorhandler.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
var Logger = require('../../util/logger.js');
|
||||
|
||||
var ErrorHandler = module.exports = {
|
||||
handle : function(err, results, finished) {
|
||||
finished = finished || function() {};
|
||||
|
||||
if (results && results.errors) {
|
||||
console.log(results.errmessages.join('\n'));
|
||||
}
|
||||
|
||||
if (err) {
|
||||
Logger.enable();
|
||||
if (!err.message) {
|
||||
err.message = 'There was an error while running the test.';
|
||||
}
|
||||
|
||||
ErrorHandler.logError(err);
|
||||
|
||||
finished(false);
|
||||
|
||||
process.exit(1);
|
||||
} else {
|
||||
var result = true;
|
||||
if (results.failed || results.errors) {
|
||||
result = false;
|
||||
}
|
||||
finished(result);
|
||||
}
|
||||
},
|
||||
|
||||
logWarning : function(message) {
|
||||
console.warn(Logger.colors.brown(message));
|
||||
},
|
||||
|
||||
logError : function(err) {
|
||||
if (!err) {
|
||||
return;
|
||||
}
|
||||
var util = require('util');
|
||||
console.error('');
|
||||
var stackTrace = err && err.stack;
|
||||
|
||||
if (!stackTrace) {
|
||||
var data;
|
||||
if (err.message) {
|
||||
data = err.data;
|
||||
err = err.message;
|
||||
}
|
||||
|
||||
if (typeof err == 'string') {
|
||||
process.stderr.write(Logger.colors.red(err));
|
||||
if (data) {
|
||||
if (typeof data == 'object' && Object.keys(data).length > 0) {
|
||||
data = util.inspect(data);
|
||||
}
|
||||
process.stderr.write(Logger.colors.stack_trace(data) + '\n');
|
||||
}
|
||||
|
||||
process.stderr.write('\n');
|
||||
} else {
|
||||
console.error(err);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var parts = stackTrace.split('\n');
|
||||
process.stderr.write(Logger.colors.red(parts.shift()) + '\n');
|
||||
process.stderr.write(parts.join('\n') + '\n\n');
|
||||
}
|
||||
};
|
206
tests/node_modules/nightwatch/lib/runner/clientmanager.js
generated
vendored
Normal file
206
tests/node_modules/nightwatch/lib/runner/clientmanager.js
generated
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
var util = require('util');
|
||||
var events = require('events');
|
||||
var Q = require('q');
|
||||
var Nightwatch = require('../index.js');
|
||||
|
||||
function ClientManager() {
|
||||
events.EventEmitter.call(this);
|
||||
this.setMaxListeners(0);
|
||||
}
|
||||
|
||||
util.inherits(ClientManager, events.EventEmitter);
|
||||
|
||||
ClientManager.prototype.init = function(opts) {
|
||||
try {
|
||||
this['@client'] = Nightwatch.client(opts);
|
||||
} catch (err) {
|
||||
console.log(err.stack);
|
||||
this.emit('error', err, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this.options = opts;
|
||||
|
||||
this['@client'].once('selenium:session_create', function() {
|
||||
var capabilities = this.api.capabilities || {};
|
||||
var browserName = (capabilities.browserName && capabilities.browserName.toUpperCase()) || '';
|
||||
|
||||
self.options.report_prefix = browserName + '_' + this.api.capabilities.version + '_' + this.api.capabilities.platform + '_';
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
ClientManager.prototype.start = function(done) {
|
||||
var self = this;
|
||||
|
||||
this.resetTerminated();
|
||||
|
||||
this['@client'].once('nightwatch:finished', function(results, errors) {
|
||||
self.emit('complete', results, errors);
|
||||
if (done) {
|
||||
if (results.failed > 0 || results.errors > 0) {
|
||||
done(results.lastError);
|
||||
results.lastError = null;
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this['@client'].once('error', function(error, data) {
|
||||
var result = {
|
||||
message: 'Connection refused! Is selenium server started?\n',
|
||||
data : error || data
|
||||
};
|
||||
|
||||
self.emit('error', result, false);
|
||||
});
|
||||
|
||||
this['@client'].start();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
ClientManager.prototype.get = function() {
|
||||
return this['@client'];
|
||||
};
|
||||
|
||||
ClientManager.prototype.set = function(prop, value) {
|
||||
this['@client'][prop] = value;
|
||||
return this;
|
||||
};
|
||||
|
||||
ClientManager.prototype.publishTestResults = function(testcase, results) {
|
||||
if (!this['@client'].api.currentTest) {
|
||||
return this;
|
||||
}
|
||||
|
||||
results = results || {};
|
||||
|
||||
var currentTestSuite = this['@client'].api.currentTest.results;
|
||||
|
||||
currentTestSuite.passed += results.passed;
|
||||
currentTestSuite.failed += results.failed;
|
||||
currentTestSuite.errors += results.errors;
|
||||
currentTestSuite.skipped += results.skipped;
|
||||
currentTestSuite.tests += results.tests.length;
|
||||
|
||||
currentTestSuite.testcases = currentTestSuite.testcases || {};
|
||||
currentTestSuite.testcases[testcase] = {
|
||||
passed : results.passed,
|
||||
failed : results.failed,
|
||||
errors : results.errors,
|
||||
skipped : results.skipped,
|
||||
tests : results.tests.length,
|
||||
assertions : results.tests,
|
||||
stackTrace : results.stackTrace
|
||||
};
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
ClientManager.prototype.results = function(type, value) {
|
||||
if (typeof value == 'undefined' && typeof type == 'undefined') {
|
||||
return this['@client'].results;
|
||||
}
|
||||
|
||||
if (typeof value == 'undefined') {
|
||||
return this['@client'].results[type] || 0;
|
||||
}
|
||||
this['@client'].results[type] = value;
|
||||
return this;
|
||||
};
|
||||
|
||||
ClientManager.prototype.errors = function() {
|
||||
return this['@client'].errors;
|
||||
};
|
||||
|
||||
ClientManager.prototype.handleException = function(err) {
|
||||
return this['@client'].handleException(err);
|
||||
};
|
||||
|
||||
ClientManager.prototype.clearGlobalResult = function() {
|
||||
return this['@client'].clearResult();
|
||||
};
|
||||
|
||||
ClientManager.prototype.terminated = function() {
|
||||
return this['@client'].terminated;
|
||||
};
|
||||
|
||||
ClientManager.prototype.terminate = function() {
|
||||
this['@client'].terminate();
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
ClientManager.prototype.resetTerminated = function() {
|
||||
this['@client'].resetTerminated();
|
||||
return this;
|
||||
};
|
||||
|
||||
ClientManager.prototype.print = function(startTime) {
|
||||
return this['@client'].printResult(startTime);
|
||||
};
|
||||
|
||||
ClientManager.prototype.api = function(key, value) {
|
||||
if (key && (typeof value != 'undefined')) {
|
||||
this['@client'].api[key] = value;
|
||||
}
|
||||
return this['@client'].api;
|
||||
};
|
||||
|
||||
ClientManager.prototype.globals = function(key, value) {
|
||||
if (key) {
|
||||
if (typeof value != 'undefined') {
|
||||
this['@client'].api.globals[key] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
return this['@client'].api.globals[key];
|
||||
}
|
||||
|
||||
return this['@client'].api.globals;
|
||||
};
|
||||
|
||||
ClientManager.prototype.resetQueue = function() {
|
||||
this['@client'].queue.reset();
|
||||
return this;
|
||||
};
|
||||
|
||||
ClientManager.prototype.restartQueue = function(onComplete) {
|
||||
this.resetQueue();
|
||||
this['@client'].queue.run(onComplete);
|
||||
};
|
||||
|
||||
ClientManager.prototype.shouldRestartQueue = function() {
|
||||
return this['@client'] && this['@client'].queue.list().length > 0;
|
||||
};
|
||||
|
||||
ClientManager.prototype.checkQueue = function() {
|
||||
var deferred = Q.defer();
|
||||
if (this.shouldRestartQueue()) {
|
||||
this.restartQueue(function() {
|
||||
deferred.resolve();
|
||||
});
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
ClientManager.prototype.endSessionOnFail = function(value) {
|
||||
if (typeof value == 'undefined') {
|
||||
return this['@client'].endSessionOnFail();
|
||||
}
|
||||
this['@client'].endSessionOnFail(value);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
ClientManager.prototype.skipTestcasesOnFail = function() {
|
||||
return this.api().options.skip_testcases_on_fail;
|
||||
};
|
||||
|
||||
module.exports = ClientManager;
|
108
tests/node_modules/nightwatch/lib/runner/filematcher.js
generated
vendored
Normal file
108
tests/node_modules/nightwatch/lib/runner/filematcher.js
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
var path = require('path');
|
||||
var minimatch = require('minimatch');
|
||||
|
||||
function adaptFilePath(srcPath, excludedPath) {
|
||||
var resolved = path.resolve(excludedPath);
|
||||
|
||||
if (resolved.indexOf(srcPath) === 0) {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
if (excludedPath.charAt(excludedPath.length-1) === path.sep) {
|
||||
excludedPath = excludedPath.substring(0, excludedPath.length-1);
|
||||
}
|
||||
return path.join(srcPath, excludedPath);
|
||||
}
|
||||
|
||||
function matchFilePath(filePath, pathArr) {
|
||||
for (var i = 0; i < pathArr.length; i++) {
|
||||
if (minimatch(filePath, pathArr[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
tags: {
|
||||
/**
|
||||
* @param {string} testFilePath - file path of a test
|
||||
* @param {object} opts - test options
|
||||
* @returns {boolean} true if specified test matches given tag
|
||||
*/
|
||||
match : function (testFilePath, opts) {
|
||||
var test;
|
||||
|
||||
try {
|
||||
test = require(testFilePath);
|
||||
} catch (e) {
|
||||
// could not load test module
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.checkModuleTags(test, opts);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {object} test - test module
|
||||
* @param {object} opts - test options
|
||||
* @returns {boolean}
|
||||
*/
|
||||
checkModuleTags: function (test, opts) {
|
||||
var moduleTags = test['@tags'] || test.tags;
|
||||
var match = true;
|
||||
|
||||
if (!Array.isArray(moduleTags)) {
|
||||
return typeof opts.tag_filter == 'undefined' && typeof opts.skiptags != 'undefined';
|
||||
}
|
||||
|
||||
if (opts.tag_filter || opts.skiptags){
|
||||
moduleTags = this.convertTagsToString(moduleTags);
|
||||
|
||||
if (opts.tag_filter) {
|
||||
match = this.containsTag(moduleTags, this.convertTagsToString(opts.tag_filter));
|
||||
}
|
||||
if (opts.skiptags) {
|
||||
match = this.excludesTag(moduleTags, this.convertTagsToString(opts.skiptags));
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
},
|
||||
|
||||
convertTagsToString : function(tags) {
|
||||
return [].concat(tags).map(function (tag) {
|
||||
return String(tag).toLowerCase();
|
||||
});
|
||||
},
|
||||
|
||||
containsTag : function(moduleTags, tags) {
|
||||
return moduleTags.some(function (testTag) {
|
||||
return (tags.indexOf(testTag) > -1);
|
||||
});
|
||||
},
|
||||
|
||||
excludesTag : function(moduleTags, tags) {
|
||||
return moduleTags.every(function (testTag) {
|
||||
return (tags.indexOf(testTag) == -1);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
exclude : {
|
||||
adaptFilePath : function(filePath, excludedPath) {
|
||||
if (!Array.isArray(excludedPath)) {
|
||||
excludedPath = [excludedPath];
|
||||
}
|
||||
return excludedPath.map(function(item) {
|
||||
return adaptFilePath(filePath, item);
|
||||
});
|
||||
},
|
||||
match : matchFilePath
|
||||
},
|
||||
|
||||
filter : {
|
||||
adaptFilePath : adaptFilePath,
|
||||
match : matchFilePath
|
||||
}
|
||||
};
|
205
tests/node_modules/nightwatch/lib/runner/module.js
generated
vendored
Normal file
205
tests/node_modules/nightwatch/lib/runner/module.js
generated
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
var path = require('path');
|
||||
var Utils = require('../util/utils.js');
|
||||
|
||||
function Module(modulePath, opts, addtOpts) {
|
||||
|
||||
try {
|
||||
this['@module'] = require(modulePath);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (!this['@module']) {
|
||||
throw new Error('Invalid test suite provided.');
|
||||
}
|
||||
|
||||
var currentTestcase = addtOpts && addtOpts.testcase;
|
||||
|
||||
this['@testSuiteName'] = null;
|
||||
this['@attributes'] = {
|
||||
'@endSessionOnFail' : true,
|
||||
'@disabled' : false,
|
||||
'@desiredCapabilities' : {},
|
||||
'@tags' : []
|
||||
};
|
||||
|
||||
this.groupName = '';
|
||||
this.setTestSuiteName();
|
||||
|
||||
this.keys = this.getKeys(currentTestcase);
|
||||
if (currentTestcase && this.keys.length === 0) {
|
||||
throw new Error('Error: "' + currentTestcase + '" is not a valid testcase in the current test suite.');
|
||||
}
|
||||
this.allKeys = this.keys.slice();
|
||||
this.filePath = modulePath;
|
||||
|
||||
this.modulePathParts = this.filePath.split(path.sep);
|
||||
this.moduleName = this.modulePathParts.pop();
|
||||
this.options = opts;
|
||||
}
|
||||
|
||||
Module.prototype.get = function(key) {
|
||||
if (!key) {
|
||||
return this['@module'];
|
||||
}
|
||||
return this['@module'][key];
|
||||
};
|
||||
|
||||
Module.prototype.set = function(key, value) {
|
||||
if (!key || !value) {
|
||||
return this;
|
||||
}
|
||||
this['@module'][key] = value;
|
||||
return this;
|
||||
};
|
||||
|
||||
Module.prototype.getName = function() {
|
||||
return this.moduleName;
|
||||
};
|
||||
|
||||
Module.prototype.call = function(fnName /* arg1, arg2 ...*/) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return this['@module'][fnName].apply(this['@module'], args);
|
||||
};
|
||||
|
||||
Module.prototype.callAsync = function(fnName, api, done, expectedArgs) {
|
||||
expectedArgs = expectedArgs || 2;
|
||||
var fnAsync = Utils.makeFnAsync(expectedArgs, this['@module'][fnName], this['@module']);
|
||||
fnAsync.name = fnName;
|
||||
|
||||
var args = [done];
|
||||
if (expectedArgs == 2) {
|
||||
args.unshift(api);
|
||||
}
|
||||
|
||||
return fnAsync.apply(this['@module'], args);
|
||||
};
|
||||
|
||||
Module.prototype.setReportKey = function(fullPaths, srcFolders) {
|
||||
var diffInFolder = '', folder, parentFolder = '';
|
||||
var filePath = this.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (diffInFolder.substr(-1) == path.sep) {
|
||||
diffInFolder = diffInFolder.substring(0, diffInFolder.length-1);
|
||||
}
|
||||
|
||||
this.groupName = diffInFolder.split(path.sep).pop(); // in case we're in a sub-folder
|
||||
this.moduleKey = path.join(parentFolder, diffInFolder, this.moduleName);
|
||||
return this;
|
||||
};
|
||||
|
||||
Module.prototype.getKeys = function(currentTestcase) {
|
||||
return Object.keys(this['@module']).filter(function(element) {
|
||||
if (!this['@module'][element]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var isFunction = typeof this['@module'][element] == 'function';
|
||||
if (currentTestcase) {
|
||||
return isFunction && (element === currentTestcase);
|
||||
}
|
||||
return isFunction;
|
||||
}, this);
|
||||
};
|
||||
|
||||
Module.prototype.removeKey = function(key) {
|
||||
var self = this;
|
||||
if (Array.isArray(key)) {
|
||||
key.forEach(function(item) {
|
||||
self.removeKey(item);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var index = this.keys.indexOf(key);
|
||||
if (index > -1) {
|
||||
this.keys.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
Module.prototype.setTestSuiteName = function() {
|
||||
var module = this['@module'];
|
||||
|
||||
var keys = Object.keys(module);
|
||||
var suiteName;
|
||||
|
||||
var hasSubSuite = keys.some(function(item) {
|
||||
var isAttribute = this.isAttribute(item);
|
||||
if (isAttribute) {
|
||||
var attrName = Module.geAttributeName(item);
|
||||
this['@attributes'][attrName] = module[item];
|
||||
} else if (typeof module[item] == 'object' && module[item]) {
|
||||
suiteName = item;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, this);
|
||||
|
||||
if (hasSubSuite && suiteName) {
|
||||
var sections = [];
|
||||
if (this['@testSuiteName']) {
|
||||
sections.push(this['@testSuiteName']);
|
||||
}
|
||||
sections.push(suiteName);
|
||||
this['@testSuiteName'] = sections.join(' :: ');
|
||||
this['@module'] = module[suiteName];
|
||||
|
||||
return this.setTestSuiteName();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Module.geAttributeName = function(item) {
|
||||
return (item.charAt(0) == '@' ? '' : '@') + item;
|
||||
};
|
||||
|
||||
Module.prototype.isAttribute = function(item) {
|
||||
var attrName = Module.geAttributeName(item);
|
||||
return (attrName in this['@attributes']) && (typeof module[item] != 'function');
|
||||
};
|
||||
|
||||
Module.prototype.getTestSuiteName = function() {
|
||||
return this['@testSuiteName'];
|
||||
};
|
||||
|
||||
Module.prototype.getNextKey = function() {
|
||||
if (this.keys.length) {
|
||||
return this.keys.shift();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
Module.prototype.resetKeys = function() {
|
||||
this.keys = this.allKeys.slice();
|
||||
};
|
||||
|
||||
Module.prototype.endSessionOnFail = function() {
|
||||
return this['@attributes']['@endSessionOnFail'];
|
||||
};
|
||||
|
||||
Module.prototype.isDisabled = function() {
|
||||
return this['@attributes']['@disabled'];
|
||||
};
|
||||
|
||||
Module.prototype.desiredCapabilities = function(capability) {
|
||||
if (capability && (capability in this['@attributes']['@desiredCapabilities'])) {
|
||||
return this['@attributes']['@desiredCapabilities'][capability];
|
||||
}
|
||||
|
||||
return this['@attributes']['@desiredCapabilities'];
|
||||
};
|
||||
|
||||
module.exports = Module;
|
283
tests/node_modules/nightwatch/lib/runner/reporter.js
generated
vendored
Normal file
283
tests/node_modules/nightwatch/lib/runner/reporter.js
generated
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var util = require('util');
|
||||
var mkpath = require('mkpath');
|
||||
var Logger = require('../util/logger.js');
|
||||
var colors = Logger.colors;
|
||||
var format = util.format;
|
||||
var Utils = require('../util/utils.js');
|
||||
var Q = require('q');
|
||||
|
||||
var Reporter = module.exports = function(globalResults, testResults, globalStartTime, options) {
|
||||
this.globalResults = globalResults;
|
||||
this.testResults = testResults;
|
||||
this.globalStartTime = globalStartTime;
|
||||
this.options = options;
|
||||
this.reporter = options.reporter || 'junit';
|
||||
};
|
||||
|
||||
var printf = function() {
|
||||
console.log(format.apply(null, arguments));
|
||||
};
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param err
|
||||
* @param testname
|
||||
* @param time
|
||||
* @return {string}
|
||||
*/
|
||||
Reporter.getTestOutput = function (err, testname, time) {
|
||||
var symbol;
|
||||
if (Utils.isErrorObject(err)) {
|
||||
symbol = Logger.colors.red(Utils.symbols.fail);
|
||||
testname = Logger.colors.red(testname);
|
||||
} else {
|
||||
symbol = Logger.colors.green(Utils.symbols.ok);
|
||||
}
|
||||
|
||||
var args = [
|
||||
'%s %s', symbol, testname
|
||||
];
|
||||
|
||||
if (time > 20) {
|
||||
args[0] += ' %s';
|
||||
args.push(Logger.colors.yellow(Utils.format('(%s)', Utils.formatElapsedTime(time))));
|
||||
}
|
||||
|
||||
return Utils.format.apply(null, args);
|
||||
};
|
||||
|
||||
Reporter.printAssertions = function(test) {
|
||||
test.assertions.forEach(function(a) {
|
||||
if (a.failure !== false) {
|
||||
var message = a.stackTrace.split('\n');
|
||||
message.unshift(a.fullMsg);
|
||||
Utils.showStackTrace(message.join('\n'));
|
||||
}
|
||||
});
|
||||
|
||||
if (test.stackTrace) {
|
||||
Utils.showStackTrace(test.stackTrace);
|
||||
}
|
||||
};
|
||||
|
||||
Reporter.prototype.get = function() {
|
||||
var fileName = __dirname + '/reporters/' + this.reporter + '.js';
|
||||
|
||||
if (fs.existsSync(fileName)) {
|
||||
return require(fileName);
|
||||
}
|
||||
|
||||
fileName = path.resolve(this.reporter);
|
||||
|
||||
if (fs.existsSync(fileName)) {
|
||||
var reporter = require(fileName);
|
||||
if (typeof reporter.write == 'function') {
|
||||
return reporter;
|
||||
}
|
||||
throw new Error('The reporter module must have a public `write` method defined.');
|
||||
}
|
||||
|
||||
throw new Error('The reporter file name cannot be resolved. Using path: ' + fileName);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {object} globals
|
||||
* @returns {function}
|
||||
*/
|
||||
Reporter.prototype.globalReporter = function(globals) {
|
||||
var reporterFn = Utils.checkFunction('reporter', globals) || function() {};
|
||||
return Utils.makeFnAsync(2, reporterFn, globals);
|
||||
};
|
||||
|
||||
Reporter.prototype.isDisabled = function() {
|
||||
return this.options.output_folder === false;
|
||||
};
|
||||
|
||||
Reporter.prototype.createFolder = function(cb) {
|
||||
if (this.isDisabled()) {
|
||||
cb(null);
|
||||
} else {
|
||||
mkpath(this.options.output_folder, cb);
|
||||
}
|
||||
};
|
||||
|
||||
Reporter.prototype.save = function() {
|
||||
var self = this;
|
||||
var deferred = Q.defer();
|
||||
this.createFolder(function(err) {
|
||||
if (self.isDisabled()) {
|
||||
deferred.resolve();
|
||||
} else {
|
||||
if (err) {
|
||||
deferred.reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
var reporter = self.get();
|
||||
|
||||
reporter.write(self.globalResults, self.options, function(err) {
|
||||
if (err) {
|
||||
console.log(colors.yellow(format('Warning: Failed to save report file to folder: %s', self.options.output_folder)));
|
||||
console.log(err.stack);
|
||||
}
|
||||
deferred.resolve(err);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
Reporter.prototype.printTotalResults = function() {
|
||||
var elapsedTime = new Date().getTime() - this.globalStartTime;
|
||||
process.stdout.write('\n');
|
||||
|
||||
if (this.testsFailed()) {
|
||||
var countMessage = this.getTestsFailedMessage();
|
||||
|
||||
console.log(colors.light_red(' _________________________________________________'));
|
||||
console.log(
|
||||
format('\n %s', colors.light_red('TEST FAILURE:')),
|
||||
countMessage,
|
||||
format('(%s)', Utils.formatElapsedTime(elapsedTime))
|
||||
);
|
||||
|
||||
|
||||
this.printFailureSummary();
|
||||
console.log('');
|
||||
} else {
|
||||
if (!this.shouldShowSummary()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var message = this.getTestsPassedMessage();
|
||||
printf('%s (%s)', message, Utils.formatElapsedTime(elapsedTime));
|
||||
}
|
||||
};
|
||||
|
||||
Reporter.prototype.testsFailed = function() {
|
||||
return Object.keys(this.globalResults.modules).some(function(moduleKey) {
|
||||
return this.globalResults.modules[moduleKey].failures > 0 || this.globalResults.modules[moduleKey].errors > 0;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
Reporter.prototype.shouldShowSummary = function() {
|
||||
var modules = Object.keys(this.globalResults.modules);
|
||||
if (modules.length > 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (modules.length <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Object.keys(this.globalResults.modules[modules[0]].completed).length > 1;
|
||||
};
|
||||
|
||||
Reporter.prototype.hasAssertionCount = function() {
|
||||
return Object.keys(this.globalResults.modules).length > 0 &&
|
||||
(this.globalResults.failed > 0 || this.globalResults.passed > 0);
|
||||
};
|
||||
|
||||
Reporter.prototype.getTestsPassedMessage = function() {
|
||||
var hasCount = this.hasAssertionCount();
|
||||
var message;
|
||||
var count;
|
||||
|
||||
if (hasCount) {
|
||||
count = this.globalResults.passed;
|
||||
message = colors.green(format('OK. %s %s passed.', count, (count > 1 ? ' total assertions' : ' assertion')));
|
||||
} else {
|
||||
count = this.getTotalTestsCount();
|
||||
message = format('%s tests passed.', colors.green('OK. ' + count));
|
||||
}
|
||||
|
||||
return message;
|
||||
};
|
||||
|
||||
Reporter.prototype.getTotalTestsCount = function() {
|
||||
|
||||
var module;
|
||||
|
||||
return Object.keys(this.globalResults.modules).reduce(function(count, moduleKey) {
|
||||
module = this.globalResults.modules[moduleKey];
|
||||
return count + module.tests - module.skipped.length;
|
||||
}.bind(this), 0);
|
||||
};
|
||||
|
||||
Reporter.prototype.getTestsFailedMessage = function() {
|
||||
var hasCount = this.hasAssertionCount();
|
||||
if (!hasCount && this.testResults.errmessages === 0) {
|
||||
return '';
|
||||
}
|
||||
var errorsMsg = '';
|
||||
var failedMsg = 'assertions';
|
||||
var passedMsg = format('%s passed', colors.green(this.globalResults.passed));
|
||||
|
||||
if (!this.options.start_session) {
|
||||
failedMsg = 'tests';
|
||||
var passedCount = Math.max(0, this.getTotalTestsCount() - this.globalResults.failed);
|
||||
passedMsg = format('%s passed', colors.green(passedCount));
|
||||
}
|
||||
|
||||
var skipped = '';
|
||||
if (this.testResults.skipped) {
|
||||
skipped = format(' and %s skipped', colors.cyan(this.testResults.skipped));
|
||||
}
|
||||
|
||||
if (this.globalResults.errors) {
|
||||
var suffix = this.globalResults.errors > 1 ? 's' : '';
|
||||
errorsMsg += format('%s error%s during execution, ', colors.red(this.globalResults.errors), suffix);
|
||||
}
|
||||
|
||||
return format('%s %s %s failed, %s%s.', errorsMsg, colors.red(this.globalResults.failed), failedMsg, passedMsg, skipped);
|
||||
};
|
||||
|
||||
Reporter.prototype.printFailureSummary = function() {
|
||||
Object.keys(this.globalResults.modules).forEach(function(moduleKey) {
|
||||
var testSuite = this.globalResults.modules[moduleKey];
|
||||
if (testSuite.failures > 0 || testSuite.errors > 0) {
|
||||
|
||||
console.log('\n' + colors.red(format(' %s %s', Utils.symbols.fail, moduleKey)));
|
||||
|
||||
Object.keys(testSuite.completed).forEach(function(testcase) {
|
||||
var test = testSuite.completed[testcase];
|
||||
if (test.failed > 0 || test.errors > 0) {
|
||||
printf('\n - %s %s', testcase, colors.yellow('(' + Utils.formatElapsedTime(test.timeMs) + ')'));
|
||||
|
||||
if (test.assertions.length > 0 && this.options.start_session) {
|
||||
Reporter.printAssertions(test);
|
||||
} else if (test.stackTrace) {
|
||||
Utils.showStackTrace(test.stackTrace);
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
if (Array.isArray(testSuite.errmessages)) {
|
||||
testSuite.errmessages.forEach(function(err) {
|
||||
console.log('');
|
||||
Utils.showStackTrace(err);
|
||||
console.log('');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (testSuite.skipped.length > 0) {
|
||||
console.log(colors.cyan(' SKIPPED:'));
|
||||
testSuite.skipped.forEach(function(testcase) {
|
||||
printf(' - %s', testcase);
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
if (Array.isArray(this.globalResults.errmessages)) {
|
||||
this.globalResults.errmessages.forEach(function(err) {
|
||||
console.log('');
|
||||
Utils.showStackTrace(err);
|
||||
console.log('');
|
||||
}.bind(this));
|
||||
}
|
||||
};
|
96
tests/node_modules/nightwatch/lib/runner/reporters/junit.js
generated
vendored
Normal file
96
tests/node_modules/nightwatch/lib/runner/reporters/junit.js
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* https://svn.jenkins-ci.org/trunk/hudson/dtkit/dtkit-format/dtkit-junit-model/src/main/resources/com/thalesgroup/dtkit/junit/model/xsd/junit-4.xsd
|
||||
* @type {exports}
|
||||
*/
|
||||
var fs = require('fs');
|
||||
var mkpath = require('mkpath');
|
||||
var path = require('path');
|
||||
var ejs = require('ejs');
|
||||
var util = require('util');
|
||||
var Utils = require('../../util/utils.js');
|
||||
|
||||
module.exports = new (function() {
|
||||
|
||||
var tmpl = __dirname + '/junit.xml.ejs';
|
||||
var tmplData;
|
||||
var globalResults;
|
||||
|
||||
function loadTemplate(cb) {
|
||||
if (tmplData) {
|
||||
cb(tmplData);
|
||||
return;
|
||||
}
|
||||
fs.readFile(tmpl, function (err, data) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
tmplData = data.toString();
|
||||
cb(tmplData);
|
||||
});
|
||||
}
|
||||
|
||||
function adaptAssertions(module) {
|
||||
Object.keys(module.completed).forEach(function(item) {
|
||||
var testcase = module.completed[item];
|
||||
var assertions = testcase.assertions;
|
||||
for (var i = 0; i < assertions.length; i++) {
|
||||
if (assertions[i].stackTrace) {
|
||||
assertions[i].stackTrace = Utils.stackTraceFilter(assertions[i].stackTrace.split('\n'));
|
||||
}
|
||||
}
|
||||
|
||||
if (testcase.failed > 0 && testcase.stackTrace) {
|
||||
var stackParts = testcase.stackTrace.split('\n');
|
||||
var errorMessage = stackParts.shift();
|
||||
testcase.stackTrace = Utils.stackTraceFilter(stackParts);
|
||||
testcase.message = errorMessage;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function writeReport(moduleKey, data, opts, callback) {
|
||||
var module = globalResults.modules[moduleKey];
|
||||
var pathParts = moduleKey.split(path.sep);
|
||||
var moduleName = pathParts.pop();
|
||||
var output_folder = opts.output_folder;
|
||||
|
||||
adaptAssertions(module);
|
||||
|
||||
var rendered = ejs.render(data, {
|
||||
locals: {
|
||||
module : module,
|
||||
moduleName : moduleName,
|
||||
systemerr : globalResults.errmessages.join('\n')
|
||||
}
|
||||
});
|
||||
|
||||
if (pathParts.length) {
|
||||
output_folder = path.join(output_folder, pathParts.join(path.sep));
|
||||
mkpath.sync(output_folder);
|
||||
}
|
||||
|
||||
var filename = path.join(output_folder, opts.filename_prefix + moduleName + '.xml');
|
||||
fs.writeFile(filename, rendered, function(err) {
|
||||
callback(err);
|
||||
globalResults.errmessages.length = 0;
|
||||
});
|
||||
}
|
||||
|
||||
this.write = function(results, options, callback) {
|
||||
globalResults = results;
|
||||
var keys = Object.keys(results.modules);
|
||||
|
||||
loadTemplate(function createReport(data) {
|
||||
var moduleKey = keys.shift();
|
||||
|
||||
writeReport(moduleKey, data, options, function(err) {
|
||||
if (err || (keys.length === 0)) {
|
||||
callback(err);
|
||||
} else {
|
||||
createReport(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
})();
|
32
tests/node_modules/nightwatch/lib/runner/reporters/junit.xml.ejs
generated
vendored
Normal file
32
tests/node_modules/nightwatch/lib/runner/reporters/junit.xml.ejs
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<testsuites errors="<%= module.errors %>"
|
||||
failures="<%= module.failures %>"
|
||||
tests="<%= module.tests %>">
|
||||
|
||||
<testsuite name="<%= moduleName %>"
|
||||
errors="<%= module.errors %>" failures="<%= module.failures %>" hostname="" id="" package="<%= module.group || moduleName %>" skipped="<%= (Array.isArray(module.skipped)) ? module.skipped.length : 0 %>"
|
||||
tests="<%= module.tests %>" time="<%= module.time %>" timestamp="<%= module.timestamp %>">
|
||||
<% for (var item in module.completed) {
|
||||
var testcase = module.completed[item];
|
||||
var assertions = testcase.assertions %>
|
||||
<testcase name="<%= item %>" time="<%= testcase.time %>" assertions="<%= assertions.length %>"><%
|
||||
for (var i = 0; i < assertions.length; i++) { %><% if (assertions[i].failure) { %> <failure message="<%= assertions[i].message %>"><%= assertions[i].stackTrace %></failure><% } %>
|
||||
<% if (assertions[i].screenshots && assertions[i].screenshots.length > 0) { %><system-out><% for (var j = 0; j < assertions[i].screenshots.length; j++) { %>[[ATTACHMENT|<%= assertions[i].screenshots[j] %>]]<% } %></system-out><% } %>
|
||||
<% }
|
||||
if (testcase.failed > 0 && testcase.stackTrace) {
|
||||
%><failure message="<%= testcase.message %>"><%= testcase.stackTrace %></failure><% } %>
|
||||
</testcase><% if (systemerr != '') {%>
|
||||
<system-err>
|
||||
<%= systemerr %>
|
||||
</system-err><% } %>
|
||||
<% } %>
|
||||
<% if (module.skipped && (module.skipped.length > 0)) { %>
|
||||
<% for (var j = 0; j < module.skipped.length; j++) { %>
|
||||
<testcase
|
||||
name="<%= module.skipped[j] %>">
|
||||
<skipped />
|
||||
</testcase>
|
||||
<% } %>
|
||||
<% } %>
|
||||
</testsuite>
|
||||
</testsuites>
|
287
tests/node_modules/nightwatch/lib/runner/run.js
generated
vendored
Normal file
287
tests/node_modules/nightwatch/lib/runner/run.js
generated
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
var Walk = require('./walk.js');
|
||||
var TestSuite = require('./testsuite.js');
|
||||
var Logger = require('../util/logger.js');
|
||||
var Reporter = require('./reporter.js');
|
||||
var path = require('path');
|
||||
var Q = require('q');
|
||||
|
||||
var globalResults;
|
||||
var currentTestSuite;
|
||||
var finishCallback;
|
||||
|
||||
function processListener() {
|
||||
process.on('exit', function (code) {
|
||||
var exitCode = code;
|
||||
|
||||
if (exitCode === 0 && globalResults && (globalResults.errors > 0 || globalResults.failed > 0)) {
|
||||
exitCode = 1;
|
||||
}
|
||||
|
||||
process.exit(exitCode);
|
||||
});
|
||||
|
||||
process.on('uncaughtException', function (err) {
|
||||
if (currentTestSuite) {
|
||||
var testCase = currentTestSuite.getCurrentTestCase();
|
||||
if (testCase/* && testCase.running*/) {
|
||||
testCase.catchHandler(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (finishCallback) {
|
||||
finishCallback(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function Runner(testSource, opts, additionalOpts, doneCb) {
|
||||
this.testSource = testSource || [];
|
||||
this.options = opts;
|
||||
this.additionalOpts = additionalOpts;
|
||||
this.doneCb = doneCb || function() {};
|
||||
this.globalStartTime = new Date().getTime();
|
||||
this.currentTestSuite = null;
|
||||
globalResults = this.globalResults = {
|
||||
passed : 0,
|
||||
failed : 0,
|
||||
errors : 0,
|
||||
skipped : 0,
|
||||
tests : 0,
|
||||
errmessages : [],
|
||||
modules : {}
|
||||
};
|
||||
|
||||
this.setOptions();
|
||||
}
|
||||
|
||||
Runner.prototype.setOptions = function() {
|
||||
this.options.parallelMode = process.env.__NIGHTWATCH_PARALLEL_MODE == '1';
|
||||
if (this.options.parallelMode) {
|
||||
this.options.currentEnv = process.env.__NIGHTWATCH_ENV_KEY;
|
||||
}
|
||||
this.options.live_output = this.additionalOpts.live_output;
|
||||
this.options.detailed_output = this.additionalOpts.detailed_output;
|
||||
this.options.start_session = this.additionalOpts.start_session;
|
||||
this.options.report_prefix = '';
|
||||
this.options.test_worker = this.additionalOpts.test_worker;
|
||||
};
|
||||
|
||||
Runner.prototype.runTestModule = function(modulePath, fullPaths) {
|
||||
try {
|
||||
currentTestSuite = this.currentTestSuite = new TestSuite(modulePath, fullPaths, this.options, this.additionalOpts, this.doneCb);
|
||||
} catch (err) {
|
||||
this.doneCb(err);
|
||||
return null;
|
||||
}
|
||||
|
||||
var moduleKey = this.currentTestSuite.getReportKey();
|
||||
|
||||
this.globalResults.modules[moduleKey] = {
|
||||
completed : {},
|
||||
skipped : null,
|
||||
time : null,
|
||||
timestamp : null,
|
||||
group : this.currentTestSuite.getGroupName()
|
||||
};
|
||||
|
||||
return this.currentTestSuite
|
||||
.on('testcase:finished', function(results, errors, time) {
|
||||
this.globalResults.modules[moduleKey].completed[this.currentTestSuite.currentTest] = {
|
||||
passed : results.passed,
|
||||
failed : results.failed,
|
||||
errors : results.errors,
|
||||
skipped : results.skipped,
|
||||
assertions : [].concat(results.tests),
|
||||
timeMs : time,
|
||||
time : (time/1000).toPrecision(4),
|
||||
stackTrace : results.stackTrace
|
||||
};
|
||||
|
||||
if (Array.isArray(errors) && errors.length) {
|
||||
this.globalResults.errmessages = this.globalResults.errmessages.concat(errors);
|
||||
}
|
||||
|
||||
this.globalResults.passed += results.passed;
|
||||
this.globalResults.failed += results.failed;
|
||||
this.globalResults.errors += results.errors;
|
||||
this.globalResults.skipped += results.skipped;
|
||||
this.globalResults.tests += results.tests.length;
|
||||
|
||||
this.globalResults.assertions = this.globalResults.tests;
|
||||
|
||||
if (this.options.output && this.options.detailed_output &&
|
||||
(this.options.modulesNo > 1 || results.tests !== this.globalResults.tests || results.steps.length > 1)
|
||||
) {
|
||||
this.currentTestSuite.printResult(time);
|
||||
} else if (this.options.output && !this.options.detailed_output) {
|
||||
var error = (results.failed > 0 || results.errors > 0) ? new Error('') : null;
|
||||
console.log(Reporter.getTestOutput(error, this.currentTestSuite.currentTest, time));
|
||||
if (error !== null) {
|
||||
Reporter.printAssertions(results.tests);
|
||||
}
|
||||
}
|
||||
|
||||
}.bind(this))
|
||||
.run()
|
||||
.then(function onTestSuiteResolved(testResults) {
|
||||
var testSuiteResult = this.globalResults.modules[moduleKey];
|
||||
testSuiteResult.skipped = testResults.steps;
|
||||
testSuiteResult.timestamp = testResults.timestamp;
|
||||
testSuiteResult.time = (testResults.time/1000).toPrecision(4);
|
||||
testSuiteResult.tests = Object.keys(testSuiteResult.completed).length + (testSuiteResult.skipped && testSuiteResult.skipped.length || 0);
|
||||
|
||||
var failures = 0;
|
||||
var errors = testResults.errors || 0;
|
||||
Object.keys(testSuiteResult.completed).forEach(function(item) {
|
||||
if (testSuiteResult.completed[item].failed > 0) {
|
||||
failures++;
|
||||
}
|
||||
});
|
||||
|
||||
testSuiteResult.errmessages = testResults.errmessages || [];
|
||||
testSuiteResult.failures = failures;
|
||||
testSuiteResult.errors = errors;
|
||||
if (typeof process.send == 'function') {
|
||||
process.send(JSON.stringify({
|
||||
type: 'testsuite_finished',
|
||||
itemKey: process.env.__NIGHTWATCH_ENV_LABEL,
|
||||
moduleKey: moduleKey,
|
||||
results: this.globalResults.modules[moduleKey],
|
||||
errmessages: testSuiteResult.errmessages,
|
||||
passed: this.globalResults.passed,
|
||||
failed: this.globalResults.failed,
|
||||
errors: this.globalResults.errors,
|
||||
skipped: this.globalResults.skipped,
|
||||
tests: this.globalResults.tests
|
||||
}));
|
||||
}
|
||||
|
||||
return testResults;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
Runner.readPaths = function(testSource, opts, cb) {
|
||||
var deferred = Q.defer();
|
||||
cb = cb || function() {};
|
||||
|
||||
if (typeof testSource == 'string') {
|
||||
testSource = [testSource];
|
||||
}
|
||||
|
||||
var fullPaths = testSource.map(function (p) {
|
||||
if (p.indexOf(process.cwd()) === 0 || path.resolve(p) === p) {
|
||||
return p;
|
||||
}
|
||||
|
||||
return path.join(process.cwd(), p);
|
||||
});
|
||||
|
||||
if (fullPaths.length === 0) {
|
||||
throw new Error('No source folder defined. Check configuration.');
|
||||
}
|
||||
|
||||
var errorMessage = ['No tests defined! using source folder:', fullPaths];
|
||||
if (opts.tag_filter) {
|
||||
errorMessage.push('; using tags:', opts.tag_filter);
|
||||
}
|
||||
|
||||
Walk.readPaths(fullPaths, function (err, modules) {
|
||||
if (err) {
|
||||
if (err.code == 'ENOENT') {
|
||||
var error = new Error('Cannot read source folder: ' + err.path);
|
||||
cb(error, false);
|
||||
deferred.reject(error);
|
||||
return;
|
||||
}
|
||||
cb(err, false);
|
||||
deferred.reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
opts.modulesNo = modules.length;
|
||||
|
||||
if (modules.length === 0) {
|
||||
var error2 = new Error(errorMessage.join(' '));
|
||||
cb(error2);
|
||||
deferred.reject(error2);
|
||||
return;
|
||||
}
|
||||
|
||||
cb(null, modules, fullPaths);
|
||||
deferred.resolve([modules, fullPaths]);
|
||||
}, opts);
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
Runner.prototype.run = function runner() {
|
||||
var deferred = Q.defer();
|
||||
var self = this;
|
||||
|
||||
finishCallback = this.doneCb;
|
||||
|
||||
Runner.readPaths(this.testSource, this.options)
|
||||
.spread(function(modulePaths, fullPaths) {
|
||||
|
||||
(function runNextModule() {
|
||||
var modulePath = modulePaths.shift();
|
||||
var promise = self.runTestModule(modulePath, fullPaths);
|
||||
|
||||
if (promise === null) {
|
||||
deferred.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
promise.then(function(testResults) {
|
||||
if (modulePaths.length) {
|
||||
setImmediate(runNextModule);
|
||||
} else {
|
||||
var reporter = new Reporter(self.globalResults, testResults, self.globalStartTime, {
|
||||
output_folder : self.additionalOpts.output_folder,
|
||||
filename_prefix : self.options.report_prefix,
|
||||
globals : self.options.globals,
|
||||
reporter : self.additionalOpts.reporter,
|
||||
start_session : self.options.start_session
|
||||
});
|
||||
|
||||
if (self.options.output) {
|
||||
reporter.printTotalResults(self.globalResults, testResults);
|
||||
}
|
||||
|
||||
reporter.save().then(function() {
|
||||
reporter.globalReporter(self.options.globals)(self.globalResults, function() {
|
||||
try {
|
||||
self.doneCb(null, self.globalResults);
|
||||
deferred.resolve(self.globalResults);
|
||||
} catch (err) {
|
||||
deferred.reject(err);
|
||||
}
|
||||
});
|
||||
}, function(err) {
|
||||
console.log(Logger.colors.yellow('Output folder doesn\'t exist and cannot be created.'));
|
||||
console.log(err.stack);
|
||||
self.doneCb(null);
|
||||
deferred.resolve();
|
||||
});
|
||||
}
|
||||
}, function(err) {
|
||||
self.doneCb(err, self.globalResults);
|
||||
}).catch(function(err) {
|
||||
deferred.reject(err);
|
||||
});
|
||||
})();
|
||||
})
|
||||
.catch(function(err) {
|
||||
self.doneCb(err, false);
|
||||
})
|
||||
.catch(function(err) {
|
||||
deferred.reject(err);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
processListener();
|
||||
|
||||
module.exports = Runner;
|
176
tests/node_modules/nightwatch/lib/runner/selenium.js
generated
vendored
Normal file
176
tests/node_modules/nightwatch/lib/runner/selenium.js
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var child_process = require('child_process');
|
||||
var util = require('util');
|
||||
var Logger = require('../util/logger.js');
|
||||
|
||||
var SENTINEL = ['Started org.openqa.jetty.jetty.Server', 'INFO - Selenium Server is up and running'];
|
||||
var DEFAULT_PORT = 4444;
|
||||
var DEFAULT_HOST = '127.0.0.1';
|
||||
var DEFAULT_LOG_FILE = 'selenium-debug.log';
|
||||
|
||||
function SeleniumServer(settings, callback) {
|
||||
this.settings = settings;
|
||||
this.onStarted = callback;
|
||||
|
||||
this.port = this.settings.selenium.port || DEFAULT_PORT;
|
||||
this.host = this.settings.selenium.host;
|
||||
this.output = '';
|
||||
this.error_out = '';
|
||||
this.process = null;
|
||||
}
|
||||
|
||||
SeleniumServer.prototype.setCliArgs = function() {
|
||||
this.cliOpts = [
|
||||
'-jar', this.settings.selenium.server_path,
|
||||
'-port', this.port
|
||||
];
|
||||
|
||||
if (this.host && this.host != DEFAULT_HOST) {
|
||||
this.cliOpts.push('-host', this.host);
|
||||
Logger.warn('\n\n[!] The host argument has been removed from Selenium 3 and will throw an exception.\n');
|
||||
}
|
||||
|
||||
if (typeof this.settings.selenium.cli_args == 'object') {
|
||||
var cli_args = this.settings.selenium.cli_args;
|
||||
for (var keyName in cli_args) {
|
||||
if (cli_args[keyName]) {
|
||||
var property = '';
|
||||
if (keyName.indexOf('-D') !== 0) {
|
||||
property += '-D';
|
||||
}
|
||||
property += keyName + '=' + cli_args[keyName];
|
||||
this.cliOpts.unshift(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SeleniumServer.prototype.start = function() {
|
||||
if (this.settings.output) {
|
||||
process.stdout.write(Logger.colors.light_purple('Starting selenium server' + (this.settings.parallelMode ? ' in parallel mode' : '') +'... '));
|
||||
}
|
||||
|
||||
this.setCliArgs();
|
||||
this.process = child_process.spawn('java', this.cliOpts, {
|
||||
stdio: ['ignore', 'pipe', 'pipe']
|
||||
});
|
||||
|
||||
this.process.host = this.host;
|
||||
this.process.port = this.port;
|
||||
this.exitHandlerFn = this.exitHandler.bind(this);
|
||||
|
||||
this.process.on('error', this.onError.bind(this));
|
||||
this.process.on('exit', this.exitHandlerFn);
|
||||
this.process.on('close', this.closeHandler.bind(this));
|
||||
|
||||
this.process.stdout.on('data', this.onStdoutData.bind(this));
|
||||
this.process.stderr.on('data', this.onStderrData.bind(this));
|
||||
};
|
||||
|
||||
SeleniumServer.prototype.stop = function(callback) {
|
||||
if (!this.process || this.process.killed) {
|
||||
Logger.warn('Selenium process is not started.');
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.process.kill();
|
||||
this.writeLogFile(callback);
|
||||
} catch (e) {
|
||||
Logger.warn('Selenium process could not be stopped.');
|
||||
console.log(e);
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
SeleniumServer.prototype.exitHandler = function (code) {
|
||||
this.onStarted('Could not start Selenium.', null, this.error_out, code);
|
||||
};
|
||||
|
||||
SeleniumServer.prototype.closeHandler = function() {
|
||||
Logger.info('Selenium process finished.');
|
||||
};
|
||||
|
||||
SeleniumServer.prototype.writeLogFile = function(callback) {
|
||||
if (this.settings.selenium.log_path === false) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof this.settings.selenium.log_path == 'undefined') {
|
||||
this.settings.selenium.log_path = '';
|
||||
}
|
||||
|
||||
var filePath = path.resolve(path.join(this.settings.selenium.log_path, DEFAULT_LOG_FILE));
|
||||
|
||||
fs.writeFile(filePath, this.output, function(err) {
|
||||
if (err) {
|
||||
console.log(Logger.colors.light_red('\nError writing log file to:'), err.path);
|
||||
}
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
SeleniumServer.prototype.onError = function(err) {
|
||||
if (err.code == 'ENOENT') {
|
||||
console.log(Logger.colors.red('\nAn error occurred while trying to start Selenium. ' +
|
||||
'Check if JAVA is installed on your machine.'));
|
||||
console.log(util.inspect(err, false, 1, true));
|
||||
}
|
||||
};
|
||||
|
||||
SeleniumServer.prototype.onStderrData = function(data) {
|
||||
this.error_out += data.toString();
|
||||
this.checkProcessStarted(data);
|
||||
};
|
||||
|
||||
SeleniumServer.prototype.onStdoutData = function(data) {
|
||||
this.checkProcessStarted(data);
|
||||
};
|
||||
|
||||
SeleniumServer.prototype.checkProcessStarted = function(data) {
|
||||
var output = data.toString();
|
||||
this.output += output;
|
||||
var isStarted = SENTINEL.some(function(item) {
|
||||
return output.indexOf(item) != -1;
|
||||
});
|
||||
|
||||
if (isStarted) {
|
||||
var exitHandler = this.exitHandlerFn;
|
||||
|
||||
this.process.removeListener('exit', exitHandler);
|
||||
process.stdout.write(Logger.colors.light_purple('started - PID: ' ) + ' ' +
|
||||
this.process.pid + '\n' + (this.settings.parallelMode ? '\n' : ''));
|
||||
this.onStarted(null, this.process);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = new (function() {
|
||||
var server;
|
||||
|
||||
this.startServer = function (settings, callback) {
|
||||
if (!settings.selenium || !settings.selenium.start_process || !settings.selenium.server_path) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
server = new SeleniumServer(settings, callback);
|
||||
server.start();
|
||||
};
|
||||
|
||||
this.stopServer = function (callback) {
|
||||
callback = callback || function() {};
|
||||
|
||||
if (!server) {
|
||||
console.log('Selenium server is not running.');
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
server.stop(callback);
|
||||
};
|
||||
})();
|
166
tests/node_modules/nightwatch/lib/runner/testcase.js
generated
vendored
Normal file
166
tests/node_modules/nightwatch/lib/runner/testcase.js
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
var path = require('path');
|
||||
var Q = require('q');
|
||||
var Logger = require('../util/logger.js');
|
||||
var Utils = require('../util/utils.js');
|
||||
var Reporter = require('../runner/reporter.js');
|
||||
var DEFAULT_UNITTEST_HOOK_TIMEOUT = 2000;
|
||||
|
||||
function TestCase(suite, testFn, numRetries, maxRetries) {
|
||||
this.suite = suite;
|
||||
this.testFn = testFn;
|
||||
this.numRetries = numRetries;
|
||||
this.maxRetries = maxRetries;
|
||||
this.currentDeferred = null;
|
||||
this._deferredNext = null;
|
||||
this.running = false;
|
||||
this.lastTimerId = null;
|
||||
this.asyncHookTimeout = this.suite.client.globals('asyncHookTimeout') || DEFAULT_UNITTEST_HOOK_TIMEOUT;
|
||||
}
|
||||
|
||||
TestCase.prototype.print = function () {
|
||||
var opts = this.suite.options;
|
||||
|
||||
if (opts.output && opts.start_session && opts.detailed_output) {
|
||||
process.stdout.write('\n');
|
||||
if (this.numRetries > 0) {
|
||||
console.log('Retrying (' + this.numRetries + '/' + this.maxRetries + '): ',
|
||||
Logger.colors.red(this.testFn));
|
||||
} else {
|
||||
console.log((opts.parallelMode && !opts.live_output ? 'Results for: ' : 'Running: '),
|
||||
Logger.colors.green(this.testFn));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
TestCase.prototype.getResults = function () {
|
||||
return this.suite.client.results();
|
||||
};
|
||||
|
||||
TestCase.prototype.getErrors = function () {
|
||||
return this.suite.client.errors();
|
||||
};
|
||||
|
||||
TestCase.prototype.run = function () {
|
||||
var self = this;
|
||||
this.currentDeferred = Q.defer();
|
||||
|
||||
this.startTime = new Date().getTime();
|
||||
this.results = null;
|
||||
this.errors = null;
|
||||
this.running = true;
|
||||
|
||||
this.suite
|
||||
.beforeEach()
|
||||
.then(function() {
|
||||
self._deferredNext = Q.defer();
|
||||
self.suite.client.once('complete', function(results, errors) {
|
||||
if (self.suite.client.options.start_session) {
|
||||
self._deferredNext.resolve({
|
||||
results: self.getResults(),
|
||||
errors: self.getErrors()
|
||||
});
|
||||
}
|
||||
}).on('error', function(result) {
|
||||
self._deferredNext.reject(result);
|
||||
});
|
||||
|
||||
try {
|
||||
if (self.suite.client.options.start_session) {
|
||||
self.suite.module.call(self.testFn, self.suite.client.api());
|
||||
} else {
|
||||
var doneFn = self.setDoneCallbackTimer(self.doneCallback.bind(self), self.testFn, function(timeoutId) {
|
||||
timeoutId.currentTest = self.testFn;
|
||||
self.lastTimerId = timeoutId;
|
||||
});
|
||||
|
||||
self.doneFn = self.suite.module.callAsync(self.testFn, self.suite.client.api(), doneFn, self.suite.expectedAsyncArgs);
|
||||
}
|
||||
} catch (err) {
|
||||
self.catchHandler(err);
|
||||
return self._deferredNext.promise;
|
||||
}
|
||||
|
||||
self.suite.client.start();
|
||||
|
||||
return self._deferredNext.promise;
|
||||
})
|
||||
.then(function onSuccess(response) {
|
||||
return self.suite.afterEach(response.results, response.errors);
|
||||
}, function onError(error) {
|
||||
self.currentDeferred.reject(error);
|
||||
})
|
||||
.then(function() {
|
||||
var time = new Date().getTime() - self.startTime;
|
||||
self.currentDeferred.resolve({
|
||||
results: self.getResults(),
|
||||
errors: self.getErrors(),
|
||||
time : time
|
||||
});
|
||||
|
||||
self.running = false;
|
||||
})
|
||||
.catch(function(error) {
|
||||
self.currentDeferred.reject(error);
|
||||
self.running = false;
|
||||
});
|
||||
|
||||
return self.currentDeferred.promise;
|
||||
};
|
||||
|
||||
TestCase.prototype.setDoneCallbackTimer = function(done, fnName, onTimerStarted) {
|
||||
return Utils.setCallbackTimeout(done, fnName, this.asyncHookTimeout, function(err) {
|
||||
throw err;
|
||||
}, onTimerStarted);
|
||||
};
|
||||
|
||||
TestCase.prototype.doneCallback = function(err) {
|
||||
var self = this;
|
||||
|
||||
if (this.lastTimerId) {
|
||||
clearTimeout(this.lastTimerId);
|
||||
this.lastTimerId = null;
|
||||
}
|
||||
|
||||
if (this.suite.currentHookTimeoutId) {
|
||||
clearTimeout(this.suite.currentHookTimeoutId);
|
||||
this.suite.currentHookTimeoutId = null;
|
||||
}
|
||||
|
||||
setImmediate(function() {
|
||||
if (self._deferredNext) {
|
||||
self._deferredNext.resolve({
|
||||
results : self.getResults(),
|
||||
errors : self.getErrors()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (Utils.isErrorObject(err)) {
|
||||
this.setFailed(err);
|
||||
}
|
||||
|
||||
if (!this.suite.options.output || !this.currentDeferred) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.suite.options.start_session) {
|
||||
this.currentDeferred.promise.then(function(results) {
|
||||
console.log(Reporter.getTestOutput(err, this.testFn, results.time));
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
if (err && this.suite.options.start_session) {
|
||||
this.suite.client.terminate();
|
||||
}
|
||||
};
|
||||
|
||||
TestCase.prototype.setFailed = function(err) {
|
||||
this.suite.client.handleException(err);
|
||||
};
|
||||
|
||||
TestCase.prototype.catchHandler = function(err) {
|
||||
this.doneCallback(err);
|
||||
};
|
||||
|
||||
module.exports = TestCase;
|
589
tests/node_modules/nightwatch/lib/runner/testsuite.js
generated
vendored
Normal file
589
tests/node_modules/nightwatch/lib/runner/testsuite.js
generated
vendored
Normal file
@@ -0,0 +1,589 @@
|
||||
var path = require('path');
|
||||
var util = require('util');
|
||||
var events = require('events');
|
||||
var Q = require('q');
|
||||
var ClientManager = require('./clientmanager.js');
|
||||
var Module = require('./module.js');
|
||||
var TestCase = require('./testcase.js');
|
||||
var Logger = require('../util/logger.js');
|
||||
var Utils = require('../util/utils.js');
|
||||
var DEFAULT_ASYNC_HOOK_TIMEOUT = 10000;
|
||||
|
||||
function noop() {}
|
||||
|
||||
function TestSuite(modulePath, fullPaths, opts, addtOpts) {
|
||||
events.EventEmitter.call(this);
|
||||
|
||||
this['@testCase'] = null;
|
||||
this.deferred = Q.defer();
|
||||
this.module = new Module(modulePath, opts, addtOpts);
|
||||
this.setTestResult();
|
||||
this.currentTest = '';
|
||||
this.module.setReportKey(fullPaths, addtOpts.src_folders);
|
||||
this.options = opts;
|
||||
this.testMaxRetries = addtOpts.retries || 0;
|
||||
this.suiteMaxRetries = addtOpts.suite_retries || 0;
|
||||
this.suiteRetries = 0;
|
||||
this.suiteName = this.module.getTestSuiteName() || Utils.getTestSuiteName(this.module.moduleKey);
|
||||
|
||||
this.setupClient();
|
||||
|
||||
this.expectedAsyncArgs = this.options.compatible_testcase_support ? 1 : 2;
|
||||
this.asyncHookTimeout = this.client.globals('asyncHookTimeout') || DEFAULT_ASYNC_HOOK_TIMEOUT;
|
||||
this.currentHookTimeoutId = null;
|
||||
this.initHooks();
|
||||
}
|
||||
|
||||
util.inherits(TestSuite, events.EventEmitter);
|
||||
|
||||
TestSuite.prototype.setupClient = function() {
|
||||
this.updateDesiredCapabilities();
|
||||
this.client = new ClientManager();
|
||||
var self = this;
|
||||
this.client.on('error', function(err) {
|
||||
self.deferred.reject(err);
|
||||
});
|
||||
this.client.init(this.options);
|
||||
this.client.api('currentEnv', this.options.currentEnv);
|
||||
this.module.set('client', this.client.api());
|
||||
if (this.client.endSessionOnFail() && !this.module.endSessionOnFail()) {
|
||||
this.client.endSessionOnFail(false);
|
||||
}
|
||||
};
|
||||
|
||||
TestSuite.prototype.initHooks = function() {
|
||||
var self = this;
|
||||
var context = this.module.get();
|
||||
var argsCount;
|
||||
|
||||
this.hooks = {};
|
||||
|
||||
var hooks = ['before', 'after', ['beforeEach', 'setUp']];
|
||||
hooks.forEach(function(item) {
|
||||
var key;
|
||||
if (Array.isArray(item)) {
|
||||
key = item[0];
|
||||
} else {
|
||||
key = item;
|
||||
}
|
||||
|
||||
var index = self.testResults.steps.indexOf(key);
|
||||
if (index === -1 && Array.isArray(item)) {
|
||||
index = self.testResults.steps.indexOf(item[1]);
|
||||
}
|
||||
|
||||
|
||||
if (Array.isArray(item) && (item.length == 3)) {
|
||||
argsCount = item[2];
|
||||
} else {
|
||||
argsCount = self.expectedAsyncArgs;
|
||||
}
|
||||
|
||||
self.hooks[key] = (function(item, argsCount) {
|
||||
return function() {
|
||||
return self.makePromise(function(done) {
|
||||
var callbackDeffered = false;
|
||||
var called = false;
|
||||
var originalFn = self.module.get(key);
|
||||
|
||||
var doneFn = function() {
|
||||
called = true;
|
||||
if (callbackDeffered) {
|
||||
return;
|
||||
}
|
||||
return done();
|
||||
};
|
||||
|
||||
self.runHookMethod(item, context, argsCount, key, doneFn, this.deferred);
|
||||
|
||||
if (originalFn && (originalFn.length == self.expectedAsyncArgs) && self.client.shouldRestartQueue()) {
|
||||
callbackDeffered = true;
|
||||
var asyncDoneFn = function(err) {
|
||||
if (called) {
|
||||
done();
|
||||
} else {
|
||||
callbackDeffered = false;
|
||||
}
|
||||
};
|
||||
|
||||
if (key == 'before' || key == 'beforeEach') {
|
||||
self.client.start(asyncDoneFn);
|
||||
} else if (key == 'after') {
|
||||
self.client.restartQueue(asyncDoneFn);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
})(item, argsCount);
|
||||
|
||||
if (index > -1) {
|
||||
self.testResults.steps.splice(index, 1);
|
||||
self.module.removeKey(item);
|
||||
}
|
||||
});
|
||||
this.initAfterEachHook();
|
||||
};
|
||||
|
||||
TestSuite.prototype.initAfterEachHook = function() {
|
||||
var self = this;
|
||||
var api = this.client.api();
|
||||
var module = this.module.get();
|
||||
var key = 'afterEach';
|
||||
var hookFn;
|
||||
var index = self.testResults.steps.indexOf(key);
|
||||
|
||||
if (!module[key]) {
|
||||
// backwards compatibility
|
||||
key = 'tearDown';
|
||||
index = self.testResults.steps.indexOf(key);
|
||||
}
|
||||
|
||||
if (module[key]) {
|
||||
hookFn = module[key];
|
||||
if (index > -1) {
|
||||
// not running with --testcase
|
||||
self.testResults.steps.splice(index, 1);
|
||||
self.module.removeKey(key);
|
||||
}
|
||||
} else {
|
||||
hookFn = function() {};
|
||||
}
|
||||
|
||||
var expectedArgs = hookFn.length;
|
||||
this.hooks.afterEach = function(results, errors) {
|
||||
self.module
|
||||
.set('results', results)
|
||||
.set('errors', errors);
|
||||
var asyncFn, asyncArgsCount;
|
||||
if (expectedArgs <= 1) {
|
||||
asyncArgsCount = 1;
|
||||
} else {
|
||||
asyncArgsCount = 2;
|
||||
}
|
||||
asyncFn = Utils.makeFnAsync(asyncArgsCount, hookFn, module);
|
||||
return self.makePromise(function(done, deferred) {
|
||||
var doneFn = self.adaptDoneCallback(done, 'afterEach', deferred);
|
||||
self.client.publishTestResults(self.currentTest, self.module.get('results'), errors);
|
||||
|
||||
if (expectedArgs < 2) {
|
||||
// user has only supplied the done callback argument (pre v0.6 behaviour), e.g.:
|
||||
// afterEach : function(done) { ... }
|
||||
asyncFn.call(module, doneFn);
|
||||
} else {
|
||||
// user has supplied both the client and the done callback argument (v0.6 behaviour), e.g.:
|
||||
// afterEach : function(browser, done) { ... }
|
||||
// in which case we may need to restart the queue if any selenium related actions are added
|
||||
if (self.options.compatible_testcase_support) {
|
||||
asyncFn.call(module, doneFn);
|
||||
} else {
|
||||
asyncFn.call(module, api, function() {
|
||||
doneFn();
|
||||
});
|
||||
}
|
||||
|
||||
// this will restart the queue if needed
|
||||
self.client.checkQueue();
|
||||
}
|
||||
});
|
||||
};
|
||||
return this;
|
||||
};
|
||||
|
||||
TestSuite.prototype.run = function() {
|
||||
var self = this;
|
||||
this.print();
|
||||
if (this.module.isDisabled()) {
|
||||
if (this.options.output) {
|
||||
console.log(Logger.colors.cyan(this.module.getName()), 'module is disabled, skipping...');
|
||||
}
|
||||
this.deferred.resolve(this.testResults);
|
||||
} else {
|
||||
this.setCurrentTest();
|
||||
this.globalBeforeEach()
|
||||
.then(function() {
|
||||
if (self.client.terminated() && self.client.skipTestcasesOnFail()) {
|
||||
self.testResults.errmessages = self.client.errors();
|
||||
self.deferred.resolve(self.testResults);
|
||||
return null;
|
||||
}
|
||||
return self.runTestSuiteModule();
|
||||
})
|
||||
|
||||
.then(function(results) {
|
||||
return self.globalAfterEach();
|
||||
})
|
||||
|
||||
.then(function() {
|
||||
self.deferred.resolve(self.testResults);
|
||||
})
|
||||
.catch(function(e) {
|
||||
self.deferred.reject(e);
|
||||
});
|
||||
}
|
||||
|
||||
return this.deferred.promise;
|
||||
};
|
||||
|
||||
TestSuite.prototype.getCurrentTestCase = function() {
|
||||
return this['@testCase'];
|
||||
};
|
||||
|
||||
TestSuite.prototype.getReportKey = function() {
|
||||
return this.module.moduleKey;
|
||||
};
|
||||
|
||||
TestSuite.prototype.getGroupName = function() {
|
||||
return this.module.groupName;
|
||||
};
|
||||
|
||||
TestSuite.prototype.printResult = function(startTime) {
|
||||
return this.client.print(startTime);
|
||||
};
|
||||
|
||||
TestSuite.prototype.shouldRetrySuite = function() {
|
||||
return this.suiteMaxRetries > this.suiteRetries && (this.testResults.failed > 0 || this.testResults.errors > 0);
|
||||
};
|
||||
|
||||
TestSuite.prototype.setTestResult = function() {
|
||||
this.testResults = {};
|
||||
this.testResults.steps = this.module.keys.slice(0);
|
||||
this.clearTestResult();
|
||||
return this;
|
||||
};
|
||||
|
||||
TestSuite.prototype.clearTestResult = function() {
|
||||
this.testResults.passed = 0;
|
||||
this.testResults.failed = 0;
|
||||
this.testResults.errors = 0;
|
||||
this.testResults.skipped = 0;
|
||||
this.testResults.tests = 0;
|
||||
this.testResults.testcases = {};
|
||||
this.testResults.timestamp = new Date().toUTCString();
|
||||
this.testResults.time = 0;
|
||||
return this;
|
||||
};
|
||||
|
||||
TestSuite.prototype.clearResult = function() {
|
||||
this.clearTestResult();
|
||||
this.client.clearGlobalResult();
|
||||
return this;
|
||||
};
|
||||
|
||||
TestSuite.prototype.printRetry = function() {
|
||||
if (this.options.output) {
|
||||
console.log('Retrying: ',
|
||||
Logger.colors.red('[' + this.suiteName + '] Test Suite '),
|
||||
'(' + this.suiteRetries + '/' + this.suiteMaxRetries + '): ');
|
||||
}
|
||||
};
|
||||
|
||||
TestSuite.prototype.retryTestSuiteModule = function() {
|
||||
this.client.resetTerminated();
|
||||
this.clearResult();
|
||||
this.suiteRetries +=1;
|
||||
this.resetTestCases();
|
||||
this.printRetry();
|
||||
|
||||
return this.globalBeforeEach().then(function() {
|
||||
return this.runTestSuiteModule();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
TestSuite.prototype.runTestSuiteModule = function() {
|
||||
var self = this;
|
||||
return this.before()
|
||||
.then(function() {
|
||||
return self.runNextTestCase();
|
||||
})
|
||||
.then(function(skipped) {
|
||||
return self.after();
|
||||
})
|
||||
.then(function() {
|
||||
return self.client.checkQueue();
|
||||
})
|
||||
.then(function() {
|
||||
return self.shouldRetrySuite();
|
||||
})
|
||||
.then(function(shouldRetrySuite) {
|
||||
if (shouldRetrySuite) {
|
||||
return self.globalAfterEach().then(function() {
|
||||
return self.retryTestSuiteModule();
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(function(e) {
|
||||
self.testResults.errors++;
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
||||
TestSuite.prototype.onTestCaseFinished = function(results, errors, time) {
|
||||
this.testResults.time += time;
|
||||
this.testResults.testcases[this.currentTest] = this.testResults.testcases[this.currentTest] || {};
|
||||
this.testResults.testcases[this.currentTest].time = (time/1000).toPrecision(4);
|
||||
|
||||
this.emit('testcase:finished', results, errors, time);
|
||||
};
|
||||
|
||||
TestSuite.prototype.resetTestCases = function() {
|
||||
var self = this;
|
||||
this.module.resetKeys();
|
||||
Object.keys(this.hooks).forEach(function(hook) {
|
||||
self.module.removeKey(hook);
|
||||
});
|
||||
};
|
||||
|
||||
TestSuite.prototype.setCurrentTest = function() {
|
||||
var moduleKey = this.getReportKey();
|
||||
this.client.clearGlobalResult();
|
||||
|
||||
this.client.api('currentTest', {
|
||||
name : this.currentTest,
|
||||
module : moduleKey.replace(path.sep , '/'),
|
||||
results : this.testResults,
|
||||
group : this.getGroupName()
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
TestSuite.prototype.runNextTestCase = function(deferred) {
|
||||
this.currentTest = this.module.getNextKey();
|
||||
this.setCurrentTest();
|
||||
|
||||
deferred = deferred || Q.defer();
|
||||
if (this.currentTest) {
|
||||
this.testResults.steps.splice(this.testResults.steps.indexOf(this.currentTest), 1);
|
||||
|
||||
this.runTestCase(this.currentTest, deferred, 0);
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
TestSuite.prototype.runTestCase = function(currentTest, deferred, numRetries) {
|
||||
var self = this;
|
||||
|
||||
this['@testCase'] = new TestCase(this, currentTest, numRetries, this.testMaxRetries);
|
||||
|
||||
if (self.client.terminated() && self.client.skipTestcasesOnFail()) {
|
||||
deferred.resolve(self.module.keys);
|
||||
return deferred;
|
||||
}
|
||||
|
||||
this['@testCase'].print().run().then(function(response) {
|
||||
var foundFailures = !!(response.results.failed || response.results.errors);
|
||||
|
||||
if (foundFailures && numRetries < self.testMaxRetries) {
|
||||
numRetries++;
|
||||
self.client.resetTerminated();
|
||||
self.clearResult();
|
||||
self.runTestCase(currentTest, deferred, numRetries);
|
||||
} else if (foundFailures && self.suiteRetries < self.suiteMaxRetries) {
|
||||
deferred.resolve(self.module.keys);
|
||||
} else {
|
||||
self.onTestCaseFinished(response.results, response.errors, response.time);
|
||||
|
||||
if (self.client.terminated() && self.client.skipTestcasesOnFail()) {
|
||||
deferred.resolve(self.module.keys);
|
||||
} else {
|
||||
process.nextTick(function() {
|
||||
self.runNextTestCase(deferred);
|
||||
});
|
||||
}
|
||||
}
|
||||
}, function(error) {
|
||||
deferred.reject(error);
|
||||
});
|
||||
|
||||
return deferred;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Test suite hooks
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
TestSuite.prototype.before = function() {
|
||||
return this.hooks.before();
|
||||
};
|
||||
|
||||
TestSuite.prototype.after = function() {
|
||||
return this.hooks.after();
|
||||
};
|
||||
|
||||
TestSuite.prototype.beforeEach = function() {
|
||||
return this.hooks.beforeEach();
|
||||
};
|
||||
|
||||
TestSuite.prototype.afterEach = function(results, errors) {
|
||||
return this.hooks.afterEach(results, errors);
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Global hooks
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
TestSuite.prototype.globalBeforeEach = function() {
|
||||
return this.adaptGlobalHook('beforeEach');
|
||||
};
|
||||
|
||||
TestSuite.prototype.globalAfterEach = function() {
|
||||
return this.adaptGlobalHook('afterEach');
|
||||
};
|
||||
|
||||
TestSuite.prototype.adaptGlobalHook = function(hookName) {
|
||||
return this.makePromise(function(done, deffered) {
|
||||
var callbackDeffered = false;
|
||||
var doneFn = function(err) {
|
||||
if (callbackDeffered) {
|
||||
return;
|
||||
}
|
||||
var fn = this.adaptDoneCallback(done, 'global ' + hookName, deffered);
|
||||
return this.onGlobalHookError(err, true, fn);
|
||||
}.bind(this);
|
||||
|
||||
var argsCount;
|
||||
var expectedCount = 1;
|
||||
|
||||
if (Utils.checkFunction(hookName, this.options.globals)) {
|
||||
argsCount = this.options.globals[hookName].length;
|
||||
expectedCount = argsCount == 2 ? 2 : 1;
|
||||
}
|
||||
|
||||
var globalHook = this.adaptHookMethod(hookName, this.options.globals, expectedCount);
|
||||
var args = [doneFn];
|
||||
if (argsCount == 2) {
|
||||
args.unshift(this.client.api());
|
||||
}
|
||||
|
||||
globalHook.apply(this.options.globals, args);
|
||||
|
||||
if (this.client.shouldRestartQueue()) {
|
||||
callbackDeffered = true;
|
||||
if (hookName == 'before' || hookName == 'beforeEach') {
|
||||
this.client.start(function(err) {
|
||||
return this.onGlobalHookError(err, false, done);
|
||||
//if (err) {
|
||||
// this.addErrorToResults(err);
|
||||
//}
|
||||
//done(err);
|
||||
}.bind(this));
|
||||
} else {
|
||||
this.client.restartQueue(function() {
|
||||
done();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
TestSuite.prototype.onGlobalHookError = function(err, hookErr, done) {
|
||||
if (err && err.message) {
|
||||
this.testResults.errors++;
|
||||
this.testResults.errmessages = [err.message];
|
||||
}
|
||||
|
||||
return done(err, hookErr);
|
||||
};
|
||||
|
||||
TestSuite.prototype.addErrorToResults = function(err) {
|
||||
this.testResults.errors++;
|
||||
this.testResults.errmessages = [err.message];
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
TestSuite.prototype.adaptDoneCallback = function(done, hookName, deferred) {
|
||||
return Utils.setCallbackTimeout(done, hookName, this.asyncHookTimeout, function(err) {
|
||||
deferred.reject(err);
|
||||
}, function(timeoutId) {
|
||||
this.currentHookTimeoutId = timeoutId;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Utilities
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
TestSuite.prototype.makePromise = function (fn) {
|
||||
var deferred = Q.defer();
|
||||
try {
|
||||
fn.call(this, function(err, hookErr) {
|
||||
// in case of an exception thrown inside a global hook, we need to reject the promise here
|
||||
if (hookErr && Utils.isErrorObject(err)) {
|
||||
deferred.reject(err);
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
}, deferred);
|
||||
} catch (e) {
|
||||
deferred.reject(e);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
TestSuite.prototype.updateDesiredCapabilities = function() {
|
||||
this.options.desiredCapabilities = this.options.desiredCapabilities || {};
|
||||
if (this.options.sync_test_names || (typeof this.options.sync_test_names == 'undefined')) {
|
||||
// optionally send the local test name (derived from filename)
|
||||
// to the remote selenium server. useful for test reporting in cloud service providers
|
||||
this.options.desiredCapabilities.name = this.suiteName;
|
||||
}
|
||||
|
||||
if (this.module.desiredCapabilities()) {
|
||||
for (var capability in this.module.desiredCapabilities()) {
|
||||
if (this.module.desiredCapabilities().hasOwnProperty(capability)) {
|
||||
this.options.desiredCapabilities[capability] = this.module.desiredCapabilities(capability);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TestSuite.prototype.print = function() {
|
||||
if (this.options.output) {
|
||||
var testSuiteDisplay;
|
||||
if (this.options.start_session) {
|
||||
testSuiteDisplay = '[' + this.suiteName + '] Test Suite';
|
||||
} else {
|
||||
testSuiteDisplay = this.module.getTestSuiteName() || this.module.moduleKey;
|
||||
}
|
||||
|
||||
if (this.options.test_worker && !this.options.live_output) {
|
||||
process.stdout.write('\\n');
|
||||
}
|
||||
|
||||
var output = '\n' + Logger.colors.cyan(testSuiteDisplay) + '\n' + Logger.colors.purple(new Array(testSuiteDisplay.length + 5).join('='));
|
||||
console.log(output);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
TestSuite.prototype.runHookMethod = function(fn, context, asyncArgCount, hookName, doneFn, deferred) {
|
||||
var hookFn = this.adaptHookMethod(fn, context, asyncArgCount);
|
||||
|
||||
doneFn = Utils.setCallbackTimeout(doneFn, hookName, this.asyncHookTimeout, function(err) {
|
||||
this.addErrorToResults(err);
|
||||
|
||||
this.deferred.resolve(this.testResults);
|
||||
}.bind(this));
|
||||
|
||||
if (this.options.compatible_testcase_support) {
|
||||
return hookFn.call(context, doneFn);
|
||||
}
|
||||
|
||||
return hookFn.call(context, this.client.api(), doneFn);
|
||||
};
|
||||
|
||||
TestSuite.prototype.adaptHookMethod = function(fn, context, asyncArgCount) {
|
||||
var hookFn;
|
||||
if (Array.isArray(fn) && (fn.length >= 2)) {
|
||||
hookFn = Utils.checkFunction(fn[0], context) || Utils.checkFunction(fn[1], context) || noop;
|
||||
} else {
|
||||
hookFn = Utils.checkFunction(fn, context) || noop;
|
||||
}
|
||||
|
||||
return Utils.makeFnAsync(asyncArgCount, hookFn, context);
|
||||
};
|
||||
|
||||
module.exports = TestSuite;
|
174
tests/node_modules/nightwatch/lib/runner/walk.js
generated
vendored
Normal file
174
tests/node_modules/nightwatch/lib/runner/walk.js
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var minimatch = require('minimatch');
|
||||
var fileMatcher = require('./filematcher.js');
|
||||
var Matchers = {};
|
||||
|
||||
function isFolderExcluded(resource, opts) {
|
||||
if (!opts.exclude) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Matchers.exclude) {
|
||||
return Matchers.exclude.some(function(item) {
|
||||
if (item.indexOf(resource) === -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return fs.statSync(item).isDirectory();
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function addMatcher(type, filePath, opts) {
|
||||
Matchers[type] = Matchers[type] || [];
|
||||
var matchers = fileMatcher[type].adaptFilePath(filePath, opts[type]);
|
||||
if (Array.isArray(matchers)) {
|
||||
Matchers[type].push.apply(Matchers[type], matchers);
|
||||
} else {
|
||||
Matchers[type].push(matchers);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function walk(dir, done, opts) {
|
||||
var results = [];
|
||||
fs.readdir(dir, function(err, list) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
var pending = list.length;
|
||||
|
||||
if (pending === 0) {
|
||||
return done(null, results);
|
||||
}
|
||||
|
||||
list.forEach(function(resource) {
|
||||
resource = path.join(dir, resource);
|
||||
|
||||
fs.stat(resource, function(err, stat) {
|
||||
if (stat && stat.isDirectory()) {
|
||||
var dirName = resource.split(path.sep).slice(-1)[0];
|
||||
var isExcluded = isFolderExcluded(resource, opts); // prevent loading of files from an excluded folder
|
||||
var isSkipped = opts.skipgroup && opts.skipgroup.indexOf(dirName) > -1;
|
||||
|
||||
if (isExcluded || isSkipped) {
|
||||
pending = pending-1;
|
||||
} else {
|
||||
walk(resource, function(err, res) {
|
||||
results = results.concat(res);
|
||||
pending = pending-1;
|
||||
if (!pending) {
|
||||
done(null, results);
|
||||
}
|
||||
}, opts);
|
||||
}
|
||||
} else {
|
||||
results.push(resource);
|
||||
pending = pending-1;
|
||||
|
||||
if (!pending) {
|
||||
done(null, results);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
readPaths : function (paths, cb, opts) {
|
||||
Matchers.exclude = [];
|
||||
Matchers.filter = [];
|
||||
|
||||
var allmodules = [];
|
||||
var extensionPattern = /\.js$/;
|
||||
var modulePaths = paths.slice(0);
|
||||
|
||||
(function readSourcePaths() {
|
||||
var sourcePath = modulePaths.shift();
|
||||
fs.stat(sourcePath, function(err, stat) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
if (stat.isFile() && extensionPattern.test(sourcePath)) {
|
||||
sourcePath = sourcePath.replace(extensionPattern, '');
|
||||
if (allmodules.indexOf(sourcePath) === -1) {
|
||||
allmodules.push(sourcePath);
|
||||
}
|
||||
|
||||
if (modulePaths.length) {
|
||||
readSourcePaths();
|
||||
} else {
|
||||
cb(null, allmodules);
|
||||
}
|
||||
} else if (stat.isDirectory()) {
|
||||
if (opts.exclude) {
|
||||
addMatcher('exclude', sourcePath, opts);
|
||||
}
|
||||
|
||||
if (opts.filter) {
|
||||
addMatcher('filter', sourcePath, opts);
|
||||
}
|
||||
|
||||
walk(sourcePath, function (err, list) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
list.sort();
|
||||
|
||||
var modules = list.filter(function (filePath) {
|
||||
|
||||
if (!extensionPattern.test(filePath)) {
|
||||
return false;
|
||||
}
|
||||
if (opts.exclude && fileMatcher.exclude.match(filePath, Matchers.exclude)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (opts.filter && !fileMatcher.filter.match(filePath, Matchers.filter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var filename = filePath.split(path.sep).slice(-1)[0];
|
||||
if (opts.filename_filter) {
|
||||
return minimatch(filename, opts.filename_filter);
|
||||
}
|
||||
|
||||
if (opts.tag_filter || opts.skiptags) {
|
||||
return fileMatcher.tags.match(filePath, opts);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
modules.forEach(function(item) {
|
||||
var filename = item.replace(extensionPattern, '');
|
||||
if (allmodules.indexOf(filename) === -1) {
|
||||
allmodules.push(filename);
|
||||
}
|
||||
});
|
||||
|
||||
if (modulePaths.length) {
|
||||
readSourcePaths();
|
||||
} else {
|
||||
cb(null, allmodules);
|
||||
}
|
||||
}, opts);
|
||||
} else {
|
||||
if (modulePaths.length) {
|
||||
readSourcePaths();
|
||||
} else {
|
||||
cb(null, allmodules);
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user