@theintern/digdug
Version:
Dig Dug. A simple abstraction library for downloading and launching WebDriver service tunnels.
344 lines • 13.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var Tunnel_1 = tslib_1.__importDefault(require("./Tunnel"));
var fs_1 = require("fs");
var os_1 = require("os");
var path_1 = require("path");
var common_1 = require("@theintern/common");
var url_1 = require("url");
var util_1 = require("./lib/util");
var scVersion = '4.7.1';
var SauceLabsTunnel = (function (_super) {
tslib_1.__extends(SauceLabsTunnel, _super);
function SauceLabsTunnel(options) {
return _super.call(this, Object.assign({
accessKey: process.env.SAUCE_ACCESS_KEY,
directDomains: [],
directory: path_1.join(__dirname, 'saucelabs'),
domainAuthentication: [],
environmentUrl: 'https://saucelabs.com/rest/v1/info/platforms/webdriver',
fastFailDomains: [],
isSharedTunnel: false,
logTrafficStats: 0,
scVersion: scVersion,
skipSslDomains: [],
tunnelDomains: [],
useProxyForTunnel: false,
username: process.env.SAUCE_USERNAME,
}, options || {})) || this;
}
Object.defineProperty(SauceLabsTunnel.prototype, "auth", {
get: function () {
return (this.username || '') + ":" + (this.accessKey || '');
},
enumerable: false,
configurable: true
});
Object.defineProperty(SauceLabsTunnel.prototype, "executable", {
get: function () {
var platform = this.platform === 'darwin' ? 'osx' : this.platform;
var architecture = this.architecture;
if (platform === 'osx' ||
platform === 'win32' ||
(platform === 'linux' && architecture === 'x64')) {
return path_1.join(this.directory, 'sc-' +
this.scVersion +
'-' +
platform +
'/bin/sc' +
(platform === 'win32' ? '.exe' : ''));
}
else {
return 'java';
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(SauceLabsTunnel.prototype, "extraCapabilities", {
get: function () {
var capabilities = {};
if (this.tunnelId) {
capabilities['tunnel-identifier'] = this.tunnelId;
}
return capabilities;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SauceLabsTunnel.prototype, "isDownloaded", {
get: function () {
return util_1.fileExists(this.executable === 'java'
? path_1.join(this.directory, 'Sauce-Connect.jar')
: path_1.join(this.executable));
},
enumerable: false,
configurable: true
});
Object.defineProperty(SauceLabsTunnel.prototype, "url", {
get: function () {
var platform = this.platform === 'darwin' ? 'osx' : this.platform;
var architecture = this.architecture;
var url = 'https://saucelabs.com/downloads/sc-' + this.scVersion + '-';
if (platform === 'osx' || platform === 'win32') {
url += platform + '.zip';
}
else if (platform === 'linux' && architecture === 'x64') {
url += platform + '.tar.gz';
}
else {
url = 'https://saucelabs.com/downloads/Sauce-Connect-3.1-r32.zip';
}
return url;
},
enumerable: false,
configurable: true
});
SauceLabsTunnel.prototype._postDownloadFile = function (data, options) {
var _this = this;
return _super.prototype._postDownloadFile.call(this, data, options).then(function () {
if (_this.executable !== 'java') {
fs_1.chmodSync(_this.executable, parseInt('0755', 8));
}
});
};
SauceLabsTunnel.prototype._makeNativeArgs = function (proxy) {
var args = ['-u', this.username, '-k', this.accessKey];
if (proxy) {
if (proxy.host) {
args.push('-p', proxy.host);
}
if (proxy.auth) {
args.push('-w', proxy.auth);
}
}
if (this.domainAuthentication.length) {
this.domainAuthentication.forEach(function (domain) {
var url = url_1.parse(domain);
args.push('-a', url.hostname + ":" + url.port + ":" + url.auth);
});
}
this.logTrafficStats &&
args.push('-z', String(Math.floor(this.logTrafficStats / 1000)));
this.verbose && args.push('-v');
return args;
};
SauceLabsTunnel.prototype._makeJavaArgs = function (proxy) {
var args = ['-jar', 'Sauce-Connect.jar', this.username, this.accessKey];
this.logFileSize && args.push('-g', String(this.logFileSize));
this.squidOptions && args.push('-S', this.squidOptions);
this.verbose && args.push('-d');
if (proxy) {
proxy.hostname &&
args.push('-p', proxy.hostname + (proxy.port ? ':' + proxy.port : ''));
if (proxy.auth) {
var auth = proxy.auth.split(':');
args.push('-u', auth[0], '-X', auth[1]);
}
}
return args;
};
SauceLabsTunnel.prototype._makeArgs = function (readyFile) {
if (!this.username || !this.accessKey) {
throw new Error('SauceLabsTunnel requires a username and access key');
}
var proxy = this.proxy ? url_1.parse(this.proxy) : undefined;
var args = this.executable === 'java'
? this._makeJavaArgs(proxy)
: this._makeNativeArgs(proxy);
args.push('-P', this.port, '-f', readyFile);
this.directDomains.length && args.push('-D', this.directDomains.join(','));
this.tunnelDomains.length && args.push('-t', this.tunnelDomains.join(','));
this.fastFailDomains.length &&
args.push('-F', this.fastFailDomains.join(','));
this.isSharedTunnel && args.push('-s');
this.logFile && args.push('-l', this.logFile);
this.pacFile && args.push('--pac', this.pacFile);
this.pidFile && args.push('--pidfile', this.pidFile);
this.restUrl && args.push('-x', this.restUrl);
this.skipSslDomains.length &&
args.push('-B', this.skipSslDomains.join(','));
this.tunnelId && args.push('-i', this.tunnelId);
this.useProxyForTunnel && args.push('-T');
this.vmVersion && args.push('-V', this.vmVersion);
return args;
};
SauceLabsTunnel.prototype.sendJobState = function (jobId, data) {
var url = url_1.parse(this.restUrl || 'https://saucelabs.com/rest/v1/');
url.auth = this.username + ':' + this.accessKey;
url.pathname += this.username + '/jobs/' + jobId;
var payload = JSON.stringify({
build: data.buildId,
'custom-data': data.extra,
name: data.name,
passed: data.success,
public: data.visibility,
tags: data.tags,
});
return common_1.request(url_1.format(url), {
method: 'put',
data: payload,
headers: {
'Content-Length': String(Buffer.byteLength(payload, 'utf8')),
'Content-Type': 'application/x-www-form-urlencoded',
},
password: this.accessKey,
username: this.username,
proxy: this.proxy,
}).then(function (response) {
return response.text().then(function (text) {
if (text) {
var data_1 = JSON.parse(text);
if (data_1.error) {
throw new Error(data_1.error);
}
if (response.status !== 200) {
throw new Error("Server reported " + response.status + " with: " + text);
}
}
else {
throw new Error("Server reported " + response.status + " with no other data.");
}
});
});
};
SauceLabsTunnel.prototype._start = function (executor) {
var _this = this;
var readyFile = path_1.join(os_1.tmpdir(), 'saucelabs-' + Date.now());
var readMessage;
var readStartupMessage;
var readRunningMessage;
var readStatus;
var task = this._makeChild(function (child, resolve, reject) {
readStartupMessage = function (message) {
function fail(message) {
reject(new Error(message));
return true;
}
if (message.indexOf('Error: response: ') === 0) {
try {
var error = /(\{[\s\S]*\})/.exec(message);
if (error) {
var data = JSON.parse(error[1]);
return fail(data.error);
}
}
catch (error) {
}
}
if (message.indexOf('Error: ') === 0) {
if (/open file limit \d+ is too low/.test(message) ||
/Sauce Labs recommends setting it/.test(message) ||
/HTTP response code indicated failure/.test(message)) {
return false;
}
return fail(message.slice('Error: '.length));
}
if (message.indexOf('Sauce Connect is up, you may start your tests.') ===
0) {
resolve();
return true;
}
return readStatus(message);
};
readRunningMessage = function (message) {
if (message.indexOf('Problem connecting to Sauce Labs REST API') > -1) {
util_1.kill(child.pid);
}
return readStatus(message);
};
readStatus = function (message) {
if (message &&
message.indexOf('Please wait for') === -1 &&
message.indexOf('Sauce Connect is up') === -1 &&
message.indexOf('Sauce Connect') !== 0 &&
message.indexOf('Using CA certificate bundle') === -1 &&
message.indexOf('You may start your tests') === -1) {
_this.emit({
type: 'status',
target: _this,
status: message,
});
}
return false;
};
readMessage = readStartupMessage;
fs_1.watchFile(readyFile, { persistent: false, interval: 1007 }, function (current, previous) {
if (Number(current.mtime) === Number(previous.mtime)) {
return;
}
resolve();
});
_this._handle = util_1.on(child.stdout, 'data', function (data) {
if (!readMessage) {
return;
}
String(data)
.split('\n')
.some(function (message) {
var delimiter = message.indexOf(' - ');
if (delimiter > -1) {
message = message.slice(delimiter + 3);
}
return readMessage(message.trim());
});
});
executor(child, resolve, reject);
}, readyFile);
task
.then(function () {
fs_1.unwatchFile(readyFile);
readMessage = readStatus;
readRunningMessage('');
readMessage = undefined;
})
.catch(function () {
});
return task;
};
SauceLabsTunnel.prototype._normalizeEnvironment = function (environment) {
var windowsMap = {
'Windows 2003': 'Windows XP',
'Windows 2008': 'Windows 7',
'Windows 2012': 'Windows 8',
'Windows 2012 R2': 'Windows 8.1',
'Windows 10': 'Windows 10',
};
var browserMap = {
microsoftedge: 'MicrosoftEdge',
};
var os = environment.os;
var platformName = os;
var platformVersion;
if (os.indexOf('Windows') === 0) {
os = windowsMap[os] || os;
platformName = 'Windows';
platformVersion = os.slice('Windows '.length);
}
else if (os.indexOf('Mac') === 0) {
platformName = 'OS X';
platformVersion = os.slice('Mac '.length);
}
var platform = platformName + (platformVersion ? ' ' + platformVersion : '');
var browserName = browserMap[environment.api_name] || environment.api_name;
var version = environment.short_version;
return {
platform: platform,
platformName: platformName,
platformVersion: platformVersion,
browserName: browserName,
browserVersion: version,
version: version,
descriptor: environment,
intern: {
platform: platform,
browserName: browserName,
version: version,
},
};
};
return SauceLabsTunnel;
}(Tunnel_1.default));
exports.default = SauceLabsTunnel;
//# sourceMappingURL=SauceLabsTunnel.js.map