Skip to content

Commit

Permalink
added proxy complience (#914)
Browse files Browse the repository at this point in the history
* added proxy complience

* fixed linter issues

* updated test case

* excluded for the time being test cases related to reinstalltion in mac

* updated

* excluded when files are installed

* increased timeout for post is reacheble to 2500ms

* fixed linter issues

* increased to 3500

* changed history for complience with breaking change
  • Loading branch information
udarrr committed Jun 25, 2024
1 parent c14ac95 commit caa0b20
Show file tree
Hide file tree
Showing 13 changed files with 132 additions and 94 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
node-version: [12, 14, 16, 18, 20]
node-version: [14, 16, 18, 20]
java-version: [11]
include:
- os: macos-latest
Expand Down
4 changes: 4 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 10.0.0 (2024-06-24)
* BREAKING CHANGE: dropped node12 support, minimum version is node14
* added proxy complience

# 9.2.3 (2023-10-21)
* fixed onCancel bug with got

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Node.js Selenium Standalone [![Test](https://github.com/webdriverio/selenium-standalone/actions/workflows/test.yml/badge.svg?branch=main&event=push)](https://github.com/webdriverio/selenium-standalone/actions/workflows/test.yml) ![Supported node versions](https://img.shields.io/badge/node-12%2C%2013%2C%2014%2C%2015%2C%2016%2C%2017%2C%2018%2C%2019%2C%2020-green)
Node.js Selenium Standalone [![Test](https://github.com/webdriverio/selenium-standalone/actions/workflows/test.yml/badge.svg?branch=main&event=push)](https://github.com/webdriverio/selenium-standalone/actions/workflows/test.yml) ![Supported node versions](https://img.shields.io/badge/node-%2014%2C%2016%2C%2018%2C%2020-green)
===========================

> A node based CLI library for launching [Selenium](http://www.seleniumhq.org/download/) with [WebDriver](https://w3c.github.io/webdriver/) support.
Expand Down
4 changes: 4 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,7 @@ since 9.1.0 it's been checked and killed automatically
## Set `selenium-standalone` Version as NodeJS environment parameter

You can set any version by `process.env.SELENIUM_VERSION=3.141.59` before starting selenium-standalone. Default values are here: [lib/default-config.js](../lib/default-config.js)

## Use the package behind corparate proxy

Should be specified `process.env.HTTP_PROXY=http://proxy-url:port` and `process.env.HTTPS_PROXY=http://proxy-url:port` or the same system envirement variables `HTTP_PROXY=http://proxy-url:port`, `HTTPS_PROXY=http://proxy-url:port`
3 changes: 2 additions & 1 deletion lib/check-started.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module.exports = checkStarted;

const { default: got } = require('got');
const { sleep } = require('./delay');
const { getProxtAgent } = require('./proxyManager');

async function checkStarted(selenium, seleniumStatusUrl) {
const cpState = {
Expand Down Expand Up @@ -49,7 +50,7 @@ async function checkStarted(selenium, seleniumStatusUrl) {

try {
// server has one minute to start
await got(seleniumStatusUrl, gotOptions);
await got(seleniumStatusUrl, { ...getProxtAgent(seleniumStatusUrl), ...gotOptions });
selenium.removeListener('exit', errorIfNeverStarted);
return null;
} catch (err) {
Expand Down
50 changes: 28 additions & 22 deletions lib/compute-download-urls.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const {
getIeDriverArchitectureOld,
getFirefoxDriverArchitectureOld,
} = require('./platformDetection');
const microsoftEdgeReleases = require('./microsoft-edge-releases');
const { getProxtAgent } = require('./proxyManager');

const urls = {
selenium: '%s/%s/selenium-server-standalone-%s.jar',
Expand Down Expand Up @@ -188,8 +190,6 @@ async function computeDownloadUrls(options) {
return downloadUrls;
}

const microsoftEdgeReleases = require('./microsoft-edge-releases');

function getEdgeDriverUrl(version) {
const release = microsoftEdgeReleases[version];
if (!release) {
Expand All @@ -209,7 +209,7 @@ async function chromiumEdgeBundleAvailable(opts) {
getChromiumEdgeDriverArchitectureOld(opts.drivers.chromiumedge.platform, opts.drivers.chromiumedge.version)
);
try {
await got.head(url, { timeout: 10000 });
await got.head(url, { ...getProxtAgent(url), timeout: 10000 });
} catch (_) {
return false;
}
Expand Down Expand Up @@ -247,7 +247,7 @@ async function resolveLatestVersion(opts, browserDriver, url) {

async function getLatestChromium(opts, browserDriver, url) {
try {
const response = await got(url, { timeout: 10000 });
const response = await got(url, { ...getProxtAgent(url), timeout: 10000 });
// edgewebdriver latest version file contains invalid characters
const version = response.body.replace(/\r|\n/g, '').replace(/[^\d|.]/g, '');

Expand All @@ -260,10 +260,10 @@ async function getLatestChromium(opts, browserDriver, url) {
}

async function getLatestGeckodriver(opts, browserDriver, url) {
const response = await got(url, { timeout: 10000, responseType: 'json' });
if (typeof response.body.name === 'string' && response.body.name) {
const response = await got(url, { ...getProxtAgent(url), timeout: 10000 }).json();
if (typeof response.name === 'string' && response.name) {
// eslint-disable-next-line no-param-reassign
opts.drivers[browserDriver].version = response.body.name;
opts.drivers[browserDriver].version = response.name;
return true;
}
}
Expand All @@ -277,15 +277,18 @@ function resolveDownloadPath(platform, buildId) {
}

async function getLastChromedriverVersionFromMajor(version) {
const url = 'https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json';
const response = await got({
method: 'get',
url: 'https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json',
responseType: 'json',
headers: {
'Content-Type': 'application/json',
...getProxtAgent(url),
...{
method: 'get',
url: url,
headers: {
'Content-Type': 'application/json',
},
},
});
const versionsWithMajor = response.body.versions.filter(
}).json();
const versionsWithMajor = response.versions.filter(
(f) =>
validateMajorVersionPrefix(f.version) === validateMajorVersionPrefix(version) && 'chromedriver' in f.downloads
);
Expand All @@ -299,18 +302,21 @@ async function getLastChromedriverVersionFromMajor(version) {
}

async function getLatestChromeVersion(possibleChanel) {
const url = 'https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json';
const response = await got({
method: 'get',
url: 'https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json',
responseType: 'json',
headers: {
'Content-Type': 'application/json',
...getProxtAgent(url),
...{
method: 'get',
url: url,
headers: {
'Content-Type': 'application/json',
},
},
});
const channel = Object.keys(response.body.channels).find((i) => i.toLowerCase() === possibleChanel.toLowerCase());
}).json();
const channel = Object.keys(response.channels).find((i) => i.toLowerCase() === possibleChanel.toLowerCase());

try {
return response.body.channels[channel].version;
return response.channels[channel].version;
} catch (err) {
console.log();
throw new Error(`channel can't be - ${possibleChanel}, possible only Stable, Beta, Dev, Canary`);
Expand Down
2 changes: 2 additions & 0 deletions lib/install-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const { default: got } = require('got');
const debug = require('debug')('selenium-standalone:install');
const { logError } = require('./log-error');
const md5 = require('md5');
const { getProxtAgent } = require('./proxyManager');

const installers = ['selenium', 'chrome', 'ie', 'firefox', 'edge', 'chromiumedge'];

Expand Down Expand Up @@ -107,6 +108,7 @@ async function isUpToDate(url, file, pathToFile) {
}
try {
const response = await got.head(url, {
...getProxtAgent(url),
timeout: 2500,
});
if (response.headers['content-length'] === `${fs.statSync(pathToFile).size}`) {
Expand Down
3 changes: 2 additions & 1 deletion lib/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const {
} = require('./install-utils');
const { checkArgs } = require('./check-args');
const { logError } = require('./log-error');
const { getProxtAgent } = require('./proxyManager');

/**
* used ONLY to deal with progress bar.
Expand Down Expand Up @@ -287,7 +288,7 @@ async function install(_opts) {

async function getDownloadStream(downloadUrl) {
let prevTransferred = 0;
const downloadStream = got.stream(downloadUrl, { ...requestOpts, isStream: true });
const downloadStream = got.stream(downloadUrl, { ...getProxtAgent(downloadUrl), ...requestOpts, isStream: true });
return await new Promise((resolve, reject) => {
downloadStream
.once('response', () => {
Expand Down
19 changes: 19 additions & 0 deletions lib/proxyManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { HttpsProxyAgent } = require('https-proxy-agent');
const { HttpProxyAgent } = require('http-proxy-agent');
/**
* Returns proxy agent if exist.
* @param {string} url
* @returns {any}
*/
function getProxtAgent(url) {
if (url.startsWith('http:') && process.env.HTTP_PROXY) {
const httpProxyAgent = new HttpProxyAgent(process.env.HTTP_PROXY);
return { agent: { http: httpProxyAgent } };
}
if (url.startsWith('https:') && process.env.HTTPS_PROXY) {
const httpProxyAgent = new HttpsProxyAgent(process.env.HTTPS_PROXY);
return { agent: { https: httpProxyAgent } };
}
return {};
}
module.exports = { getProxtAgent };
10 changes: 3 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
"release:patch": "npm run release -- patch",
"release:minor": "npm run release -- minor",
"release:major": "npm run release -- major",
"lint": "eslint --ignore-path .gitignore ."
"lint": "eslint --ignore-path .gitignore .",
"lint:fix": "eslint --fix --ignore-path .gitignore ."
},
"engines": {
"node": ">=12"
"node": ">=14"
},
"bin": {
"selenium-standalone": "./bin/selenium-standalone"
Expand Down Expand Up @@ -49,6 +50,8 @@
"find-process": "^1.4.7",
"fkill": "^7.2.1",
"got": "^11.8.6",
"http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.4",
"is-port-reachable": "^3.0.0",
"lodash.mapvalues": "^4.6.0",
"lodash.merge": "^4.6.2",
Expand Down
73 changes: 38 additions & 35 deletions test/no-reinstall.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,47 @@ const selenium = require('..');

const targetDir = path.join(__dirname, '..', '.selenium');

describe('when files are installed', () => {
it('should not reinstall them', async function () {
this.timeout(120000);
if (process.platform !== 'darwin') {
describe('when files are installed', () => {
it('should not reinstall them', async function () {
this.timeout(120000);

/**
* Recursively find files in the given directory
* @param {string} dirname
* @param {string[]} files
* @returns {string[]}
*/
function walk(dirname, files = []) {
fs.readdirSync(dirname).forEach((name) => {
const filepath = path.join(dirname, name);
if (fs.statSync(filepath).isDirectory()) {
walk(filepath, files);
} else {
files.push(filepath);
}
});
return files;
}
const installedFiles = walk(targetDir);
/**
* Recursively find files in the given directory
* @param {string} dirname
* @param {string[]} files
* @returns {string[]}
*/
function walk(dirname, files = []) {
fs.readdirSync(dirname).forEach((name) => {
const filepath = path.join(dirname, name);
if (fs.statSync(filepath).isDirectory()) {
walk(filepath, files);
} else {
files.push(filepath);
}
});
return files;
}
const installedFiles = walk(targetDir);

// Get last modified time of files that should already be installed in
// the .selenium directory.
const mtimes = installedFiles.reduce((acc, filepath) => {
acc[filepath] = fs.statSync(filepath).mtime.getTime();
return acc;
}, {});
// Get last modified time of files that should already be installed in
// the .selenium directory.
const mtimes = installedFiles.reduce((acc, filepath) => {
acc[filepath] = fs.statSync(filepath).mtime.getTime();
return acc;
}, {});

// Compare last modified time of files after running the installation
// again. It shouldn't download any files, otherwise it fails.
await selenium.install();
// Compare last modified time of files after running the installation
// again. It shouldn't download any files, otherwise it fails.
await selenium.install();

const isModified = !installedFiles.every((filepath) => {
return mtimes[filepath] === fs.statSync(filepath).mtime.getTime();
});
const mtimesAfter = installedFiles.reduce((acc, filepath) => {
acc[filepath] = fs.statSync(filepath).mtime.getTime();
return acc;
}, {});

assert.strictEqual(isModified, false, 'It should not have reinstalled files');
assert.strictEqual(JSON.stringify(mtimes), JSON.stringify(mtimesAfter), 'It should not have reinstalled files');
});
});
});
}
Loading

0 comments on commit caa0b20

Please sign in to comment.