@testim/testim-cli
Version:
Command line interface for running Testing on you CI
193 lines (151 loc) • 5.69 kB
JavaScript
'use strict';
/**
* RequestHandler
*/
var Q = require('q'),
url = require('url'),
request = require('request'),
merge = require('deepmerge'),
errorCodes = require('./errorCodes'),
ErrorHandler = require('./ErrorHandler'),
packageDotJson = require('../../package.json');
module.exports = RequestHandler;
function RequestHandler(options, eventHandler, logger) {
this.sessionID = null;
this.startPath = options.path === '/' ? '' : options.path || '/wd/hub';
this.eventHandler = eventHandler;
this.logger = logger;
this.defaultOptions = options;
// Wdjs calls RequestHandler with `host` badly set
// A host is an hostname+port
if (options.host !== undefined) {
options.hostname = options.host;
delete options.host;
}
// set auth from user and password configs
if(this.defaultOptions.user && this.defaultOptions.key) {
this.auth = {
user: this.defaultOptions.user,
pass: this.defaultOptions.key
};
delete this.defaultOptions.user;
delete this.defaultOptions.key;
}
}
/**
* merges default options with request options
*
* @param {Object} requestOptions request options
*/
RequestHandler.prototype.createOptions = function(requestOptions, data) {
var newOptions = {};
/**
* if we don't have a session id we set it here, unless we call commands that don't require session ids, for
* example /sessions. The call to /sessions is not connected to a session itself and it therefore doesn't
* require it
*/
if (requestOptions.path.match(/\:sessionId/) && !this.sessionID && requestOptions.requiresSession !== false) {
// throw session id error
throw new ErrorHandler(101);
}
newOptions.uri = url.parse(
this.defaultOptions.protocol + '://' +
this.defaultOptions.hostname + ':' + this.defaultOptions.port +
this.startPath +
requestOptions.path.replace(':sessionId', this.sessionID || ''));
// send authentication credentials only when creating new session
if (requestOptions.path === '/session' && this.auth !== undefined) {
newOptions.auth = this.auth;
}
if (requestOptions.method) {
newOptions.method = requestOptions.method;
}
newOptions.json = true;
newOptions.followAllRedirects = true;
newOptions.headers = {
'Connection': 'keep-alive',
'Accept': 'application/json',
'User-Agent': 'webdriverio/webdriverio/' + packageDotJson.version
};
if (Object.keys(data).length > 0) {
var requestData = JSON.stringify(data);
newOptions.body = requestData;
newOptions.method = 'POST';
newOptions.headers = merge(newOptions.headers, {
'Content-Type': 'application/json; charset=UTF-8',
'Content-Length': Buffer.byteLength(requestData, 'UTF-8')
});
}
return newOptions;
};
/**
* creates a http request with its given options and send the protocol
* command to the webdriver server
*
* @param {Object} requestOptions defines url, method and other request options
* @param {Object} data contains request data
*/
RequestHandler.prototype.create = function(requestOptions, data) {
var defer = Q.defer();
if (typeof requestOptions === 'string') {
requestOptions = {
path: requestOptions
};
}
data = data || {};
var fullRequestOptions = this.createOptions(requestOptions, data);
this.eventHandler.emit('command', {
method: fullRequestOptions.method || 'GET',
uri: fullRequestOptions.uri,
data: data
});
request(fullRequestOptions, function(err, response, body) {
var error = null;
if(err || (body && body.status !== 0)) {
if(body && typeof body === 'string') {
error = new ErrorHandler.RuntimeError(body);
} else if(body) {
error = new ErrorHandler.RuntimeError({
status: body.status,
type: errorCodes[body.status] ? errorCodes[body.status].id : 'unknown',
message: errorCodes[body.status] ? errorCodes[body.status].message : 'unknown',
orgStatusMessage: body.value ? body.value.message : ''
});
} else {
error = new ErrorHandler.RuntimeError({
status: -1,
type: 'ECONNREFUSED',
message: 'Couldn\'t connect to selenium server',
orgStatusMessage: 'Couldn\'t connect to selenium server'
});
}
return defer.reject(error);
}
/**
* if no session id was set before we've called the init command
*/
if(this.sessionID === null && requestOptions.requiresSession !== false) {
this.sessionID = body.sessionId;
this.eventHandler.emit('init', {
sessionID: this.sessionID,
options: body.value,
desiredCapabilities: data.desiredCapabilities
});
this.logger.log('SET SESSION ID ' + this.sessionID);
}
if(body === undefined) {
body = {
status: 0,
orgStatusMessage: errorCodes[0].message
};
}
this.eventHandler.emit('result', {
requestData: data,
requestOptions: fullRequestOptions,
response: response,
body: body
});
return defer.resolve(body);
}.bind(this));
return defer.promise;
};