UNPKG

@theintern/digdug

Version:

Dig Dug. A simple abstraction library for downloading and launching WebDriver service tunnels.

546 lines 20.3 kB
"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