refactor app directory structure and add tests
This commit is contained in:
583
tests/node_modules/nightwatch/lib/index.js
generated
vendored
Normal file
583
tests/node_modules/nightwatch/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,583 @@
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
var path = require('path');
|
||||
var util = require('util');
|
||||
var events = require('events');
|
||||
var HttpRequest = require('./http/request.js');
|
||||
var CommandQueue = require('./core/queue.js');
|
||||
var Assertion = require('./core/assertion.js');
|
||||
var Logger = require('./util/logger.js');
|
||||
var Api = require('./core/api.js');
|
||||
var Utils = require('./util/utils.js');
|
||||
|
||||
function Nightwatch(options) {
|
||||
events.EventEmitter.call(this);
|
||||
|
||||
this.locateStrategy = 'css selector';
|
||||
|
||||
this.api = {
|
||||
capabilities : {},
|
||||
globals : options && options.persist_globals && options.globals || {},
|
||||
sessionId : null
|
||||
};
|
||||
|
||||
this.setMaxListeners(0);
|
||||
this.sessionId = null;
|
||||
this.context = null;
|
||||
this.terminated = false;
|
||||
|
||||
this.setOptions(options)
|
||||
.setCapabilities()
|
||||
.loadKeyCodes();
|
||||
|
||||
this.errors = [];
|
||||
this.results = {
|
||||
passed:0,
|
||||
failed:0,
|
||||
errors:0,
|
||||
skipped:0,
|
||||
tests:[]
|
||||
};
|
||||
|
||||
Assertion.init(this);
|
||||
Api.init(this).load();
|
||||
|
||||
this.queue = CommandQueue;
|
||||
this.queue.empty();
|
||||
this.queue.reset();
|
||||
}
|
||||
|
||||
Nightwatch.DEFAULT_CAPABILITIES = {
|
||||
browserName: 'firefox',
|
||||
javascriptEnabled: true,
|
||||
acceptSslCerts: true,
|
||||
platform: 'ANY'
|
||||
};
|
||||
|
||||
util.inherits(Nightwatch, events.EventEmitter);
|
||||
|
||||
Nightwatch.prototype.assertion = Assertion.assert;
|
||||
|
||||
Nightwatch.prototype.setOptions = function(options) {
|
||||
this.options = {};
|
||||
this.api.options = {};
|
||||
if (options && typeof options == 'object') {
|
||||
for (var propName in options) {
|
||||
this.options[propName] = options[propName];
|
||||
}
|
||||
}
|
||||
|
||||
this.api.launchUrl = this.options.launchUrl || this.options.launch_url || null;
|
||||
// backwords compatibility
|
||||
this.api.launch_url = this.api.launchUrl;
|
||||
|
||||
if (this.options.globals && typeof this.options.globals == 'object' && !this.options.persist_globals) {
|
||||
for (var globalKey in this.options.globals) {
|
||||
this.api.globals[globalKey] = this.options.globals[globalKey];
|
||||
}
|
||||
}
|
||||
|
||||
var screenshots = this.options.screenshots;
|
||||
var screenshotsEnabled = screenshots && screenshots.enabled || false;
|
||||
|
||||
this.api.options.screenshots = screenshotsEnabled;
|
||||
if (screenshotsEnabled) {
|
||||
if (typeof screenshots.path == 'undefined') {
|
||||
throw new Error('Please specify the screenshots.path in nightwatch.json.');
|
||||
}
|
||||
this.options.screenshots.on_error = this.options.screenshots.on_error ||
|
||||
(typeof this.options.screenshots.on_error == 'undefined');
|
||||
this.api.screenshotsPath = this.api.options.screenshotsPath = screenshots.path;
|
||||
} else {
|
||||
this.options.screenshots = {
|
||||
enabled : false,
|
||||
path : ''
|
||||
};
|
||||
}
|
||||
|
||||
if (this.options.use_xpath) {
|
||||
this.locateStrategy = 'xpath';
|
||||
}
|
||||
|
||||
if (this.options.silent) {
|
||||
Logger.disable();
|
||||
} else {
|
||||
Logger.enable();
|
||||
}
|
||||
|
||||
this.options.start_session = this.options.start_session || (typeof this.options.start_session == 'undefined');
|
||||
|
||||
this.api.options.skip_testcases_on_fail = this.options.skip_testcases_on_fail ||
|
||||
(typeof this.options.skip_testcases_on_fail == 'undefined' && this.options.start_session); // off by default for unit tests
|
||||
|
||||
this.api.options.log_screenshot_data = this.options.log_screenshot_data ||
|
||||
(typeof this.options.log_screenshot_data == 'undefined');
|
||||
var seleniumPort = this.options.seleniumPort || this.options.selenium_port;
|
||||
var seleniumHost = this.options.seleniumHost || this.options.selenium_host;
|
||||
var useSSL = this.options.useSsl || this.options.use_ssl;
|
||||
var proxy = this.options.proxy;
|
||||
|
||||
if (seleniumPort) {
|
||||
HttpRequest.setSeleniumPort(seleniumPort);
|
||||
}
|
||||
if (seleniumHost) {
|
||||
HttpRequest.setSeleniumHost(seleniumHost);
|
||||
}
|
||||
if (useSSL) {
|
||||
HttpRequest.useSSL(true);
|
||||
}
|
||||
if (proxy) {
|
||||
HttpRequest.setProxy(proxy);
|
||||
}
|
||||
|
||||
if (typeof this.options.default_path_prefix == 'string') {
|
||||
HttpRequest.setDefaultPathPrefix(this.options.default_path_prefix);
|
||||
}
|
||||
|
||||
var username = this.options.username;
|
||||
var key = this.options.accesKey || this.options.access_key || this.options.password;
|
||||
|
||||
if (username && key) {
|
||||
this.api.options.username = username;
|
||||
this.api.options.accessKey = key;
|
||||
|
||||
HttpRequest.setCredentials({
|
||||
username : username,
|
||||
key : key
|
||||
});
|
||||
}
|
||||
|
||||
this.endSessionOnFail(typeof this.options.end_session_on_fail == 'undefined' || this.options.end_session_on_fail);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Nightwatch.prototype.endSessionOnFail = function(value) {
|
||||
if (typeof value == 'undefined') {
|
||||
return this.options.end_session_on_fail;
|
||||
}
|
||||
|
||||
this.options.end_session_on_fail = value;
|
||||
return this;
|
||||
};
|
||||
|
||||
Nightwatch.prototype.setCapabilities = function() {
|
||||
this.desiredCapabilities = {};
|
||||
for (var capability in Nightwatch.DEFAULT_CAPABILITIES) {
|
||||
this.desiredCapabilities[capability] = Nightwatch.DEFAULT_CAPABILITIES[capability];
|
||||
}
|
||||
|
||||
if (this.options.desiredCapabilities) {
|
||||
for (var prop in this.options.desiredCapabilities) {
|
||||
if (this.options.desiredCapabilities.hasOwnProperty(prop)) {
|
||||
this.desiredCapabilities[prop] = this.options.desiredCapabilities[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
this.api.options.desiredCapabilities = this.desiredCapabilities;
|
||||
return this;
|
||||
};
|
||||
|
||||
Nightwatch.prototype.loadKeyCodes = function() {
|
||||
this.api.Keys = require('./util/keys.json');
|
||||
return this;
|
||||
};
|
||||
|
||||
Nightwatch.prototype.start = function() {
|
||||
if (!this.sessionId && this.options.start_session) {
|
||||
this
|
||||
.once('selenium:session_create', this.start)
|
||||
.startSession();
|
||||
return this;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
this.queue.reset();
|
||||
this.queue.run(function(error) {
|
||||
if (error) {
|
||||
var stackTrace = '';
|
||||
if (error.stack) {
|
||||
stackTrace = error.stack.split('\n').slice(1).join('\n');
|
||||
}
|
||||
|
||||
self.results.errors++;
|
||||
self.errors.push(error.name + ': ' + error.message + '\n' + stackTrace);
|
||||
if (self.options.output) {
|
||||
Utils.showStackTraceWithHeadline(error.name + ': ' + error.message, stackTrace, true);
|
||||
}
|
||||
|
||||
if (self.options.start_session) {
|
||||
self.terminate();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
self.finished();
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Nightwatch.prototype.terminate = function(deferred) {
|
||||
// in case this was a synchronous command (e.g. assert.ok()) we need to wait for other possible
|
||||
// commands which might have been added afterwards while client is terminated
|
||||
if (deferred) {
|
||||
this.queue.instance().once('queue:started', this.terminateSession.bind(this));
|
||||
} else {
|
||||
this.terminateSession();
|
||||
}
|
||||
|
||||
this.terminated = true;
|
||||
return this;
|
||||
};
|
||||
|
||||
Nightwatch.prototype.resetTerminated = function() {
|
||||
this.terminated = false;
|
||||
return this;
|
||||
};
|
||||
|
||||
Nightwatch.prototype.terminateSession = function() {
|
||||
this.queue.reset();
|
||||
this.queue.empty();
|
||||
|
||||
if (this.options.end_session_on_fail && this.options.start_session) {
|
||||
this.api.end(function() {
|
||||
this.finished();
|
||||
}.bind(this));
|
||||
|
||||
// FIXME: sometimes the queue is incorrectly restarted when another .end() is
|
||||
// scheduled from globalBeforeEach and results into a session command being sent with
|
||||
// null as the sessionId
|
||||
this.queue.run();
|
||||
} else {
|
||||
this.finished();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Nightwatch.prototype.complete = function() {
|
||||
return this.emit('complete');
|
||||
};
|
||||
|
||||
Nightwatch.prototype.finished = function() {
|
||||
Logger.info('FINISHED');
|
||||
|
||||
this.emit('nightwatch:finished', this.results, this.errors);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Nightwatch.prototype.getFailureMessage = function() {
|
||||
var errors = '';
|
||||
|
||||
var failure_msg = [];
|
||||
if (this.results.failed > 0) {
|
||||
failure_msg.push(Logger.colors.red(this.results.failed) +
|
||||
' assertions failed');
|
||||
}
|
||||
if (this.results.errors > 0) {
|
||||
failure_msg.push(Logger.colors.red(this.results.errors) + ' errors');
|
||||
}
|
||||
if (this.results.passed > 0) {
|
||||
failure_msg.push(Logger.colors.green(this.results.passed) + ' passed');
|
||||
}
|
||||
|
||||
if (this.results.skipped > 0) {
|
||||
failure_msg.push(Logger.colors.blue(this.results.skipped) + ' skipped');
|
||||
}
|
||||
|
||||
return failure_msg.join(', ').replace(/,([^,]*)$/g, function($0, $1) {
|
||||
return ' and' + $1;
|
||||
});
|
||||
};
|
||||
|
||||
Nightwatch.prototype.printResult = function(elapsedTime) {
|
||||
if (this.options.output && this.options.start_session) {
|
||||
var ok = false;
|
||||
if (this.results.failed === 0 && this.results.errors === 0) {
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (ok && this.results.passed > 0) {
|
||||
console.log('\n' + Logger.colors.green('OK.'),
|
||||
Logger.colors.green(this.results.passed) + ' assertions passed. (' + Utils.formatElapsedTime(elapsedTime, true) + ')');
|
||||
} else if (ok && this.results.passed === 0) {
|
||||
if (this.options.start_session) {
|
||||
console.log(Logger.colors.green('No assertions ran.'));
|
||||
}
|
||||
} else {
|
||||
var failure_msg = this.getFailureMessage();
|
||||
console.log('\n' + Logger.colors.red('FAILED: '), failure_msg, '(' + Utils.formatElapsedTime(elapsedTime, true) + ')');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Nightwatch.prototype.clearResult = function() {
|
||||
this.errors.length = 0;
|
||||
this.results.passed = 0;
|
||||
this.results.failed = 0;
|
||||
this.results.errors = 0;
|
||||
this.results.skipped = 0;
|
||||
this.results.tests.length = 0;
|
||||
};
|
||||
|
||||
Nightwatch.prototype.handleException = function(err) {
|
||||
var stack = err.stack.split('\n');
|
||||
var failMessage = stack.shift();
|
||||
var firstLine = ' ' + String.fromCharCode(10006) + ' ' + failMessage;
|
||||
if (typeof err.actual != 'undefined' && typeof err.expected != 'undefined') {
|
||||
firstLine += '\033[0;90m - expected ' + Logger.colors.green('"' + err.expected + '"') + ' \033[0;90mbut got: ' + Logger.colors.red('"' + err.actual + '"');
|
||||
}
|
||||
|
||||
if (this.options.output) {
|
||||
Utils.showStackTraceWithHeadline(firstLine, stack);
|
||||
}
|
||||
|
||||
if (err.name == 'AssertionError') {
|
||||
this.results.failed++;
|
||||
stack.unshift(failMessage + ' - expected "' + err.expected + '" but got: "' + err.actual + '"');
|
||||
this.results.stackTrace = stack.join('\n');
|
||||
} else {
|
||||
this.addError('\n ' + err.stack, firstLine);
|
||||
this.terminate();
|
||||
}
|
||||
};
|
||||
|
||||
Nightwatch.prototype.runProtocolAction = function(requestOptions, callback) {
|
||||
var self = this;
|
||||
|
||||
var request = new HttpRequest(requestOptions)
|
||||
.on('result', function(result) {
|
||||
if (typeof callback != 'function') {
|
||||
var error = new Error('Callback parameter is not a function - ' + typeof(callback) + ' passed: "' + callback + '"');
|
||||
self.errors.push(error.stack);
|
||||
self.results.errors++;
|
||||
} else {
|
||||
callback.call(self.api, result);
|
||||
}
|
||||
|
||||
if (result.lastScreenshotFile && self.results.tests.length > 0) {
|
||||
var lastTest = self.results.tests[self.results.tests.length-1];
|
||||
lastTest.screenshots = lastTest.screenshots || [];
|
||||
lastTest.screenshots.push(result.lastScreenshotFile);
|
||||
delete result.lastScreenshotFile;
|
||||
}
|
||||
|
||||
request.emit('complete');
|
||||
})
|
||||
.on('success', function(result, response) {
|
||||
if (result.status && result.status !== 0) {
|
||||
result = self.handleTestError(result);
|
||||
}
|
||||
request.emit('result', result, response);
|
||||
})
|
||||
.on('error', function(result, response, screenshotContent) {
|
||||
result = self.handleTestError(result);
|
||||
|
||||
if (screenshotContent && self.options.screenshots.on_error) {
|
||||
var fileNamePath = Utils.getScreenshotFileName(self.api.currentTest, true, self.options.screenshots.path);
|
||||
self.saveScreenshotToFile(fileNamePath, screenshotContent);
|
||||
result.lastScreenshotFile = fileNamePath;
|
||||
}
|
||||
|
||||
request.emit('result', result, response);
|
||||
});
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
Nightwatch.prototype.addError = function(message, logMessage) {
|
||||
var currentTest;
|
||||
if (this.api.currentTest) {
|
||||
currentTest = '[' + Utils.getTestSuiteName(this.api.currentTest.module) + ' / ' + this.api.currentTest.name + ']';
|
||||
} else {
|
||||
currentTest = 'tests';
|
||||
}
|
||||
|
||||
this.errors.push(' Error while running '+ currentTest + ':\n' + message);
|
||||
this.results.errors++;
|
||||
if (this.options.output) {
|
||||
Logger.warn(' ' + (logMessage || message));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Nightwatch.prototype.saveScreenshotToFile = function(fileName, content, cb) {
|
||||
var mkpath = require('mkpath');
|
||||
var fs = require('fs');
|
||||
var self = this;
|
||||
cb = cb || function() {};
|
||||
|
||||
var dir = path.resolve(fileName, '..');
|
||||
var fail = function(err) {
|
||||
if (self.options.output) {
|
||||
console.log(Logger.colors.yellow('Couldn\'t save screenshot to '), fileName);
|
||||
}
|
||||
|
||||
Logger.warn(err);
|
||||
cb(err);
|
||||
};
|
||||
|
||||
mkpath(dir, function(err) {
|
||||
if (err) {
|
||||
fail(err);
|
||||
} else {
|
||||
fs.writeFile(fileName, content, 'base64', function(err) {
|
||||
if (err) {
|
||||
fail(err);
|
||||
} else {
|
||||
cb(null, fileName);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Nightwatch.prototype.handleTestError = function(result) {
|
||||
var errorMessage = '';
|
||||
if (result && result.status) {
|
||||
var errorCodes = require('./api/errors.json');
|
||||
errorMessage = errorCodes[result.status] && errorCodes[result.status].message || '';
|
||||
}
|
||||
|
||||
return {
|
||||
status: -1,
|
||||
value : result && result.value || null,
|
||||
errorStatus: result && result.status || '',
|
||||
error : errorMessage
|
||||
};
|
||||
};
|
||||
|
||||
Nightwatch.prototype.startSession = function () {
|
||||
if (this.terminated) {
|
||||
return this;
|
||||
}
|
||||
var self = this;
|
||||
var options = {
|
||||
path : '/session',
|
||||
data : {
|
||||
desiredCapabilities : this.desiredCapabilities
|
||||
}
|
||||
};
|
||||
|
||||
var request = new HttpRequest(options);
|
||||
request.on('success', function(data, response, isRedirect) {
|
||||
if (data && data.sessionId) {
|
||||
self.sessionId = self.api.sessionId = data.sessionId;
|
||||
if (data.value) {
|
||||
self.api.capabilities = data.value;
|
||||
}
|
||||
Logger.info('Got sessionId from selenium', self.sessionId);
|
||||
self.emit('selenium:session_create', self.sessionId, request, response);
|
||||
} else if (isRedirect) {
|
||||
self.followRedirect(request, response);
|
||||
} else {
|
||||
request.emit('error', data, null);
|
||||
}
|
||||
})
|
||||
.on('error', function(data, err) {
|
||||
if (self.options.output) {
|
||||
console.error('\n' + Logger.colors.light_red('Error retrieving a new session from the selenium server'));
|
||||
}
|
||||
|
||||
if (typeof data == 'object' && Object.keys(data).length === 0) {
|
||||
data = '';
|
||||
}
|
||||
|
||||
if (!data && err) {
|
||||
data = err;
|
||||
}
|
||||
|
||||
self.emit('error', data);
|
||||
})
|
||||
.send();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Nightwatch.prototype.followRedirect = function (request, response) {
|
||||
if (!response.headers || !response.headers.location) {
|
||||
this.emit('error', null, null);
|
||||
return this;
|
||||
}
|
||||
var url = require('url');
|
||||
var urlParts = url.parse(response.headers.location);
|
||||
request.setOptions({
|
||||
path : urlParts.pathname,
|
||||
host : urlParts.hostname,
|
||||
port : urlParts.port,
|
||||
method : 'GET'
|
||||
}).send();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
exports = module.exports = {};
|
||||
|
||||
exports.client = function(options) {
|
||||
return new Nightwatch(options);
|
||||
};
|
||||
|
||||
exports.cli = function(runTests) {
|
||||
var cli = require('./runner/cli/cli.js');
|
||||
cli.setup();
|
||||
|
||||
var argv = cli.init();
|
||||
if (argv.help) {
|
||||
cli.showHelp();
|
||||
} else if (argv.version) {
|
||||
var packageConfig = require(__dirname + '/../package.json');
|
||||
console.log(packageConfig.name + ' v' + packageConfig.version);
|
||||
} else {
|
||||
if (typeof runTests != 'function') {
|
||||
throw new Error('Supplied argument needs to be a function!');
|
||||
}
|
||||
runTests(argv);
|
||||
}
|
||||
};
|
||||
|
||||
exports.runner = function(argv, done, settings) {
|
||||
var runner = exports.CliRunner(argv);
|
||||
return runner.setup(settings, done).runTests(done);
|
||||
};
|
||||
|
||||
exports.initGrunt = function(grunt) {
|
||||
grunt.registerMultiTask('nightwatch', 'run nightwatch.', function() {
|
||||
var done = this.async();
|
||||
var options = this.options();
|
||||
var settings = this.data && this.data.settings;
|
||||
var argv = this.data && this.data.argv;
|
||||
|
||||
exports.cli(function(a) {
|
||||
Object.keys(argv).forEach(function(key) {
|
||||
if (key === 'env' && a['parallel-mode'] === true) {
|
||||
return;
|
||||
}
|
||||
a[key] = argv[key];
|
||||
});
|
||||
|
||||
if (a.test) {
|
||||
a.test = path.resolve(a.test);
|
||||
}
|
||||
|
||||
if (options.cwd) {
|
||||
process.chdir(options.cwd);
|
||||
}
|
||||
|
||||
exports.runner(a, done, settings);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.CliRunner = function(argv) {
|
||||
var CliRunner = require('./runner/cli/clirunner.js');
|
||||
return new CliRunner(argv);
|
||||
};
|
||||
|
||||
exports.initClient = function(opts) {
|
||||
var Manager = require('./runner/clientmanager.js');
|
||||
var instance = new Manager();
|
||||
return instance.init(opts);
|
||||
};
|
Reference in New Issue
Block a user