UNPKG

selenium-standalone

Version:

installs a `selenium-standalone` command line to install and start a standalone selenium server

278 lines (249 loc) 8.5 kB
module.exports = computeDownloadUrls; const got = require('got'); const util = require('util'); const { isSelenium4 } = require('./isSelenium4'); const urls = { selenium: '%s/%s/selenium-server-standalone-%s.jar', seleniumV4: '%s/%s/selenium-server-%s.jar', chrome: '%s/%s/chromedriver_%s.zip', ie: '%s/%s/IEDriverServer_%s_%s.zip', firefox: '%s/%s/%s-%s-%s', chromiumedge: '%s/%s/edgedriver_%s.zip', }; /** * Computes the URL to download selenium.jar and drivers. * * When passing in the `opts.drivers` param, it must be of the following format. Each of the drivers listed * inside is optional * * { * chrome: { ... }, * ie: { ... }, * firefox: { ... } * } * * Each driver must have the following format. * * { * baseURL: '', // Base URL for where to download driver from * version: '', // Version number string that matches the desired driver version * arch: '' // Architecture for the desired driver * } * * @param {string} opts.seleniumVersion - Version number string that matches the desired selenium.jar * @param {string} opts.seleniumBaseURL - Base URL for where to download selenium.jar from * @param {Object} opts.drivers - Object containing options for various drivers. See comment for object format. */ async function computeDownloadUrls(opts) { const downloadUrls = { selenium: opts.seleniumFullURL || util.format( isSelenium4(opts.seleniumVersion) ? urls.seleniumV4 : urls.selenium, opts.seleniumBaseURL, isSelenium4(opts.seleniumVersion) ? `selenium-${getVersionWithZeroedPatchPart(opts.seleniumVersion)}` : `selenium-${opts.seleniumVersion}`, opts.seleniumVersion ), }; if (opts.drivers.chrome) { await resolveLatestVersion(opts, 'chrome', opts.drivers.chrome.baseURL + '/LATEST_RELEASE'); downloadUrls.chrome = opts.drivers.chrome.fullURL || util.format( urls.chrome, opts.drivers.chrome.baseURL, opts.drivers.chrome.version, getChromeDriverArchitecture(opts.drivers.chrome.arch, opts.drivers.chrome.version) ); } if (opts.drivers.ie) { downloadUrls.ie = opts.drivers.ie.fullURL || util.format( urls.ie, opts.drivers.ie.baseURL, opts.drivers.ie.version.slice(0, opts.drivers.ie.version.lastIndexOf('.')), getIeDriverArchitecture(opts.drivers.ie.arch), opts.drivers.ie.version ); } if (opts.drivers.firefox) { await resolveLatestVersion(opts, 'firefox', 'https://api.github.com/repos/mozilla/geckodriver/releases/latest'); downloadUrls.firefox = opts.drivers.firefox.fullURL || util.format( urls.firefox, opts.drivers.firefox.baseURL, `v${opts.drivers.firefox.version}`, 'geckodriver', `v${opts.drivers.firefox.version}`, getFirefoxDriverArchitecture(opts.drivers.firefox.arch) ); } if (opts.drivers.edge) { downloadUrls.edge = opts.drivers.edge.fullURL || getEdgeDriverUrl(opts.drivers.edge.version); } if (opts.drivers.chromiumedge) { await resolveLatestVersion( opts, 'chromiumedge', 'https://msedgewebdriverstorage.blob.core.windows.net/edgewebdriver/LATEST_STABLE' ); downloadUrls.chromiumedge = opts.drivers.chromiumedge.fullURL || util.format( urls.chromiumedge, opts.drivers.chromiumedge.baseURL, opts.drivers.chromiumedge.version, getChromiumEdgeDriverArchitecture(opts.drivers.chromiumedge.arch, opts.drivers.chromiumedge.version) ); } return downloadUrls; } function getChromeDriverArchitecture(wantedArchitecture, version) { let platform; if (process.platform === 'linux') { platform = 'linux64'; } else if (process.platform === 'darwin') { if (process.arch === 'arm64') { const [major] = version.split('.'); platform = parseInt(major, 10) > 105 ? 'mac_arm64' : 'mac64_m1'; } else { platform = 'mac64'; } } else { platform = 'win32'; } return platform; } function getIeDriverArchitecture(wanted) { let platform; if (wanted === 'ia32') { platform = 'Win32'; } else { platform = 'x64'; } return platform; } function getFirefoxDriverArchitecture(wantedArchitecture) { const extension = '.tar.gz'; switch (process.platform) { case 'linux': return getLinuxFirefoxDriverArchitecture(extension, wantedArchitecture); case 'darwin': return getMacFirefoxDriverArchitecture(extension); case 'win32': return getWindowsFirefoxDriverArchitecture(wantedArchitecture); default: throw new Error('No Firefox driver is available for platform "' + process.platform + '"'); } } function getLinuxFirefoxDriverArchitecture(extension, wantedArchitecture = 'x64') { const arch = wantedArchitecture === 'x64' ? '64' : '32'; return 'linux' + arch + extension; } function getMacFirefoxDriverArchitecture(extension) { return 'macos' + (process.arch === 'arm64' ? '-aarch64' : '') + extension; } function getWindowsFirefoxDriverArchitecture(wantedArchitecture = '64') { const arch = wantedArchitecture.substr(-2) === '64' ? '64' : '32'; return `win${arch}.zip`; } const microsoftEdgeReleases = require('./microsoft-edge-releases'); function getEdgeDriverUrl(version) { const release = microsoftEdgeReleases[version]; if (!release) { throw new Error( 'Invalid Microsoft Edge Web Driver version see https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/#downloads' ); } return release.url; } function getChromiumEdgeDriverArchitecture(wantedArchitecture, version) { let platform; if (process.platform === 'linux') { platform = 'linux64'; } else if (process.platform === 'darwin') { if (process.arch === 'arm64') { const [major] = version.split('.'); platform = parseInt(major, 10) > 104 ? 'mac64_m1' : 'mac64'; } else { platform = 'mac64'; } } else if (wantedArchitecture === 'x32') { platform = 'win32'; } else { platform = 'win64'; } return platform; } async function chromiumEdgeBundleAvailable(opts) { const url = util.format( urls.chromiumedge, opts.drivers.chromiumedge.baseURL, opts.drivers.chromiumedge.version, getChromiumEdgeDriverArchitecture(opts.drivers.chromiumedge.platform) ); try { await got.head(url, { timeout: 10000 }); } catch (_) { return false; } return true; } async function resolveLatestVersion(opts, browserDriver, url) { if (opts.drivers[browserDriver].version === 'latest') { try { if (browserDriver === 'firefox') { if (await getLatestGeckodriver(opts, browserDriver, url)) { return true; } /** * it seems that linux releases are not for every version */ } else if (browserDriver === 'chromiumedge') { if (await getLatestChromium(opts, browserDriver, url)) { if (await chromiumEdgeBundleAvailable(opts)) { return true; } } } else if (await getLatestChromium(opts, browserDriver, url)) { return true; } } catch (_) { // eslint-disable-next-line no-empty } // eslint-disable-next-line no-param-reassign opts.drivers[browserDriver].version = opts.drivers[browserDriver].fallbackVersion; } } async function getLatestChromium(opts, browserDriver, url) { const response = await got(url, { timeout: 10000 }); // edgewebdriver latest version file contains invalid characters const version = response.body.replace(/\r|\n/g, '').replace(/[^\d|.]/g, ''); if (!version) { return false; } // eslint-disable-next-line no-param-reassign opts.drivers[browserDriver].version = version; return true; } async function getLatestGeckodriver(opts, browserDriver, url) { const response = await got(url, { timeout: 10000, responseType: 'json' }); if (typeof response.body.name === 'string' && response.body.name) { // eslint-disable-next-line no-param-reassign opts.drivers[browserDriver].version = response.body.name; return true; } } function getVersionWithZeroedPatchPart(fullVersion) { if (!/^\d+\.\d+\.\d+$/i.test(fullVersion)) { // If version longer than just 3 numbers, like '4.0.0-beta-1', do nothing return fullVersion; } // else make version patch part zero: '4.1.1' => '4.1.0' const [major, minor] = fullVersion.split('.'); return `${major}.${minor}.0`; }