@theintern/digdug
Version:
Dig Dug. A simple abstraction library for downloading and launching WebDriver service tunnels.
546 lines • 20.3 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 util_1 = require("util");
var path_1 = require("path");
var common_1 = require("@theintern/common");
var util_2 = require("./lib/util");
var semver_1 = require("semver");
var command_exists_1 = require("command-exists");
var webdriversJson = tslib_1.__importStar(require("./webdrivers.json"));
var webdrivers = webdriversJson.drivers;
var SeleniumTunnel = (function (_super) {
tslib_1.__extends(SeleniumTunnel, _super);
function SeleniumTunnel(options) {
var _this = _super.call(this, Object.assign({
seleniumArgs: [],
drivers: ['chrome'],
baseUrl: webdrivers.selenium.baseUrl,
version: webdrivers.selenium.latest,
seleniumTimeout: 5000,
}, options || {})) || this;
_this.webDriverDataUrl = 'https://theintern.io/digdug/resources/2/webdrivers.json';
_this._webDriverDataLoaded = false;
if (!command_exists_1.sync('java')) {
throw new Error('Java must be installed to use SeleniumTunnel');
}
return _this;
}
Object.defineProperty(SeleniumTunnel.prototype, "artifact", {
get: function () {
return "selenium-server-standalone-" + this.version + ".jar";
},
enumerable: false,
configurable: true
});
Object.defineProperty(SeleniumTunnel.prototype, "directory", {
get: function () {
return path_1.join(__dirname, 'selenium-standalone');
},
enumerable: false,
configurable: true
});
Object.defineProperty(SeleniumTunnel.prototype, "executable", {
get: function () {
return 'java';
},
enumerable: false,
configurable: true
});
Object.defineProperty(SeleniumTunnel.prototype, "isDownloaded", {
get: function () {
var directory = this.directory;
return (util_2.fileExists(path_1.join(directory, this.artifact)) &&
this._getDriverConfigs().every(function (config) {
return util_2.fileExists(path_1.join(directory, config.executable));
}));
},
enumerable: false,
configurable: true
});
Object.defineProperty(SeleniumTunnel.prototype, "url", {
get: function () {
var majorMinorVersion = this.version.slice(0, this.version.lastIndexOf('.'));
return util_1.format('%s/%s/%s', this.baseUrl, majorMinorVersion, this.artifact);
},
enumerable: false,
configurable: true
});
SeleniumTunnel.prototype.download = function (forceDownload) {
var _this = this;
if (forceDownload === void 0) { forceDownload = false; }
return this._updateWebDriverData().then(function () {
if (!forceDownload && _this.isDownloaded) {
return common_1.Task.resolve();
}
var tasks;
return new common_1.Task(function (resolve) {
var configs = tslib_1.__spreadArray([
{
url: _this.url,
executable: _this.artifact,
dontExtract: true,
}
], _this._getDriverConfigs());
tasks = configs.map(function (config) {
var executable = config.executable;
var dontExtract = Boolean(config.dontExtract);
var directory = config.directory;
if (util_2.fileExists(path_1.join(_this.directory, executable))) {
return common_1.Task.resolve();
}
return _this._downloadFile(config.url, _this.proxy, {
executable: executable,
dontExtract: dontExtract,
directory: directory,
});
});
resolve(common_1.Task.all(tasks).then(function () { }));
}, function () {
tasks &&
tasks.forEach(function (task) {
task.cancel();
});
});
});
};
SeleniumTunnel.prototype.sendJobState = function () {
return common_1.Task.resolve();
};
SeleniumTunnel.prototype._updateWebDriverData = function () {
var _this = this;
if (this._webDriverDataLoaded || !this.webDriverDataUrl) {
return common_1.Task.resolve();
}
var updatedDataFile = path_1.join(this.directory, 'webdrivers.json');
var updatedData;
return common_1.request(this.webDriverDataUrl, {
proxy: this.proxy,
timeout: 3000,
})
.then(function (resp) {
if (resp.status === 200) {
return resp.json().then(function (data) {
updatedData = data;
_this._webDriverDataLoaded = true;
return util_2.writeFile(JSON.stringify(updatedData), updatedDataFile);
});
}
})
.catch(function (error) {
if (_this.verbose) {
console.warn(error);
}
try {
var data = fs_1.readFileSync(updatedDataFile, { encoding: 'utf8' });
updatedData = JSON.parse(data);
}
catch (_a) {
}
})
.finally(function () {
if (updatedData) {
common_1.deepMixin(webdrivers, updatedData.drivers);
}
});
};
SeleniumTunnel.prototype._getDriverConfigs = function () {
function getDriverConfig(name, options) {
var Constructor = driverNameMap[name];
if (!Constructor) {
throw new Error('Invalid driver name "' + name + '"');
}
return new Constructor(options);
}
return this.drivers.map(function (data) {
if (typeof data === 'string') {
return getDriverConfig(data);
}
if (typeof data === 'object' && data.name) {
return getDriverConfig(data.name, data);
}
return data;
});
};
SeleniumTunnel.prototype._makeArgs = function () {
var directory = this.directory;
var driverConfigs = this._getDriverConfigs();
var args = [];
driverConfigs.reduce(function (args, config) {
var file = path_1.join(directory, config.executable);
args.push('-D' + config.seleniumProperty + '=' + file);
return args;
}, args);
if (this.seleniumArgs) {
args.push.apply(args, this.seleniumArgs);
}
args.push('-jar', path_1.join(this.directory, this.artifact), '-port', this.port);
if (this.verbose) {
args.push('-debug');
if (semver_1.satisfies(this.version, '>=3.1.0 <3.5.0')) {
args.push('true');
}
console.log('Starting with arguments: ', args.join(' '));
}
return args;
};
SeleniumTunnel.prototype._postDownloadFile = function (data, options) {
var executable = options.executable;
if (options.dontExtract) {
return util_2.writeFile(data, path_1.join(this.directory, executable));
}
return _super.prototype._postDownloadFile.call(this, data, options);
};
SeleniumTunnel.prototype._start = function (executor) {
var _this = this;
var handle;
var task = this._makeChild(function (child, resolve, reject) {
handle = util_2.on(child.stderr, 'data', function (data) {
data = String(data);
if (data.indexOf('Selenium Server is up and running') > -1) {
resolve();
}
else if (/Address already in use/.test(data) ||
/Port \d+ is busy/.test(data)) {
reject(new Error('Address is already in use'));
util_2.kill(child.pid);
}
});
if (_this.verbose) {
util_2.on(child.stderr, 'data', function (data) {
process.stderr.write(data);
});
}
executor(child, resolve, reject);
});
task.then(function () { return handle.destroy(); }, function () { return handle.destroy(); });
return task;
};
return SeleniumTunnel;
}(Tunnel_1.default));
exports.default = SeleniumTunnel;
var Config = (function () {
function Config(config) {
Object.assign(this, config);
}
return Config;
}());
function versionGreaterThan(versionStr, version) {
var parts = String(versionStr).split('.').map(Number);
return version.some(function (part, i) {
return parts[i] > part;
});
}
var ChromeConfig = (function (_super) {
tslib_1.__extends(ChromeConfig, _super);
function ChromeConfig(options) {
var _this = this;
var opts = Object.assign({
arch: process.arch,
baseUrl: webdrivers.chrome.baseUrl,
platform: process.platform,
version: webdrivers.chrome.latest,
}, options);
var useNewDriverLocation = versionGreaterThan(opts.version, [114]);
if (useNewDriverLocation && opts.baseUrl == webdrivers.chrome.baseUrl) {
opts.baseUrl =
'https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing';
}
_this = _super.call(this, Object.assign(opts, options)) || this;
_this.useNewDriverLocation = useNewDriverLocation;
return _this;
}
Object.defineProperty(ChromeConfig.prototype, "artifact", {
get: function () {
var platform = this.platform;
if (platform === 'linux') {
platform = 'linux' + (this.arch === 'x86' ? '32' : '64');
}
else if (platform === 'darwin') {
var parts_1 = String(this.version).split('.').map(Number);
var isGreater = [2, 22].some(function (part, i) {
return parts_1[i] > part;
});
platform = isGreater ? 'mac64' : 'mac32';
}
return this.useNewDriverLocation
? util_1.format('chromedriver-%s.zip', platform)
: util_1.format('chromedriver_%s.zip', platform);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ChromeConfig.prototype, "directory", {
get: function () {
return path_1.join(this.version, this.arch);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ChromeConfig.prototype, "url", {
get: function () {
return this.useNewDriverLocation
? util_1.format('%s/%s/%s/%s', this.baseUrl, this.version, this.platform, this.artifact)
: util_1.format('%s/%s/%s', this.baseUrl, this.version, this.artifact);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ChromeConfig.prototype, "executable", {
get: function () {
return this.useNewDriverLocation
? path_1.join(this.directory, util_1.format('chromedriver-%s', this.platform), this.platform === 'win32' || this.platform === 'win64'
? 'chromedriver.exe'
: 'chromedriver')
: path_1.join(this.directory, this.platform === 'win32' ? 'chromedriver.exe' : 'chromedriver');
},
enumerable: false,
configurable: true
});
Object.defineProperty(ChromeConfig.prototype, "seleniumProperty", {
get: function () {
return 'webdriver.chrome.driver';
},
enumerable: false,
configurable: true
});
return ChromeConfig;
}(Config));
var FirefoxConfig = (function (_super) {
tslib_1.__extends(FirefoxConfig, _super);
function FirefoxConfig(options) {
return _super.call(this, Object.assign({
arch: process.arch,
baseUrl: webdrivers.firefox.baseUrl,
platform: process.platform,
version: webdrivers.firefox.latest,
}, options)) || this;
}
Object.defineProperty(FirefoxConfig.prototype, "artifact", {
get: function () {
var platform = this.platform;
if (platform === 'linux') {
platform = 'linux' + (this.arch === 'x64' ? '64' : '32');
}
else if (platform === 'win32') {
platform = 'win' + (this.arch === 'x64' ? '64' : '32');
}
else if (platform === 'darwin') {
platform = 'macos';
}
var extension = /^win/.test(platform) ? '.zip' : '.tar.gz';
return util_1.format('geckodriver-v%s-%s%s', this.version, platform, extension);
},
enumerable: false,
configurable: true
});
Object.defineProperty(FirefoxConfig.prototype, "url", {
get: function () {
return util_1.format('%s/v%s/%s', this.baseUrl, this.version, this.artifact);
},
enumerable: false,
configurable: true
});
Object.defineProperty(FirefoxConfig.prototype, "directory", {
get: function () {
return path_1.join(this.version, this.arch);
},
enumerable: false,
configurable: true
});
Object.defineProperty(FirefoxConfig.prototype, "executable", {
get: function () {
return path_1.join(this.directory, this.platform === 'win32' ? 'geckodriver.exe' : 'geckodriver');
},
enumerable: false,
configurable: true
});
Object.defineProperty(FirefoxConfig.prototype, "seleniumProperty", {
get: function () {
return 'webdriver.gecko.driver';
},
enumerable: false,
configurable: true
});
return FirefoxConfig;
}(Config));
var IEConfig = (function (_super) {
tslib_1.__extends(IEConfig, _super);
function IEConfig(options) {
return _super.call(this, Object.assign({
arch: process.arch,
baseUrl: webdrivers.ie.baseUrl,
version: webdrivers.ie.latest,
}, options)) || this;
}
Object.defineProperty(IEConfig.prototype, "artifact", {
get: function () {
var architecture = this.arch === 'x64' ? 'x64' : 'Win32';
return util_1.format('IEDriverServer_%s_%s.zip', architecture, this.version);
},
enumerable: false,
configurable: true
});
Object.defineProperty(IEConfig.prototype, "url", {
get: function () {
var majorMinorVersion = this.version.slice(0, this.version.lastIndexOf('.'));
return util_1.format('%s/%s/%s', this.baseUrl, majorMinorVersion, this.artifact);
},
enumerable: false,
configurable: true
});
Object.defineProperty(IEConfig.prototype, "directory", {
get: function () {
return path_1.join(this.version, this.arch);
},
enumerable: false,
configurable: true
});
Object.defineProperty(IEConfig.prototype, "executable", {
get: function () {
return path_1.join(this.directory, 'IEDriverServer.exe');
},
enumerable: false,
configurable: true
});
Object.defineProperty(IEConfig.prototype, "seleniumProperty", {
get: function () {
return 'webdriver.ie.driver';
},
enumerable: false,
configurable: true
});
return IEConfig;
}(Config));
var EdgeConfig = (function (_super) {
tslib_1.__extends(EdgeConfig, _super);
function EdgeConfig(options) {
return _super.call(this, Object.assign({
arch: process.arch,
baseUrl: webdrivers.edge.baseUrl,
version: webdrivers.edge.latest,
versions: webdrivers.edge.versions,
}, options)) || this;
}
Object.defineProperty(EdgeConfig.prototype, "dontExtract", {
get: function () {
return true;
},
enumerable: false,
configurable: true
});
Object.defineProperty(EdgeConfig.prototype, "url", {
get: function () {
var uuid = this.uuid;
if (uuid) {
var a = uuid[0];
var b = uuid[1];
var c = uuid[2];
return util_1.format('%s/%s/%s/%s/%s/%s', this.baseUrl, a, b, c, uuid, this.artifact);
}
var urlOrObj = webdrivers.edge.versions[this.version].url;
if (typeof urlOrObj === 'string') {
return urlOrObj;
}
return urlOrObj[this.arch];
},
enumerable: false,
configurable: true
});
Object.defineProperty(EdgeConfig.prototype, "artifact", {
get: function () {
return 'MicrosoftWebDriver.exe';
},
enumerable: false,
configurable: true
});
Object.defineProperty(EdgeConfig.prototype, "directory", {
get: function () {
return this.version;
},
enumerable: false,
configurable: true
});
Object.defineProperty(EdgeConfig.prototype, "executable", {
get: function () {
return path_1.join(this.version, 'MicrosoftWebDriver.exe');
},
enumerable: false,
configurable: true
});
Object.defineProperty(EdgeConfig.prototype, "seleniumProperty", {
get: function () {
return 'webdriver.edge.driver';
},
enumerable: false,
configurable: true
});
return EdgeConfig;
}(Config));
var EdgeChromiumConfig = (function (_super) {
tslib_1.__extends(EdgeChromiumConfig, _super);
function EdgeChromiumConfig(options) {
return _super.call(this, Object.assign({
arch: process.arch,
baseUrl: webdrivers.edgeChromium.baseUrl,
platform: process.platform,
version: webdrivers.edgeChromium.latest,
}, options)) || this;
}
Object.defineProperty(EdgeChromiumConfig.prototype, "artifact", {
get: function () {
var platform = edgePlatformNames[this.platform] || this.platform;
var arch = this.arch === 'x86' ? '32' : '64';
return util_1.format('edgedriver_%s%s.zip', platform, arch);
},
enumerable: false,
configurable: true
});
Object.defineProperty(EdgeChromiumConfig.prototype, "directory", {
get: function () {
return path_1.join(this.version, this.arch);
},
enumerable: false,
configurable: true
});
Object.defineProperty(EdgeChromiumConfig.prototype, "url", {
get: function () {
return util_1.format('%s/%s/%s', this.baseUrl, this.version, this.artifact);
},
enumerable: false,
configurable: true
});
Object.defineProperty(EdgeChromiumConfig.prototype, "executable", {
get: function () {
return path_1.join(this.directory, this.platform === 'win32' ? 'msedgedriver.exe' : 'msedgedriver');
},
enumerable: false,
configurable: true
});
Object.defineProperty(EdgeChromiumConfig.prototype, "seleniumProperty", {
get: function () {
return 'webdriver.edge.driver';
},
enumerable: false,
configurable: true
});
return EdgeChromiumConfig;
}(Config));
var edgePlatformNames = {
darwin: 'mac',
win32: 'win',
win64: 'win',
};
var driverNameMap = {
chrome: ChromeConfig,
firefox: FirefoxConfig,
ie: IEConfig,
'internet explorer': IEConfig,
edge: EdgeConfig,
MicrosoftEdge: EdgeConfig,
edgeChromium: EdgeChromiumConfig,
MicrosoftEdgeChromium: EdgeChromiumConfig,
};
//# sourceMappingURL=SeleniumTunnel.js.map