Skip to content

Commit

Permalink
onlyDriver feature (#848)
Browse files Browse the repository at this point in the history
* onlyDriver feature

* linter issues

* fixed issue

* fixed test for firefox

* checking port port existence before killing

* changed naming for driver-starter
  • Loading branch information
udarrr authored Oct 2, 2023
1 parent 7fe121b commit 1822711
Show file tree
Hide file tree
Showing 13 changed files with 343 additions and 62 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ By default, Google Chrome, Firefox and Microsoft Edge are available when install

Starting from `v6.22` chrome, edgechromium, and geckodriver support `latest` as version.

Starting from `v9.0.6` support changes regarding new storage for `latest` versions of chromedriver.
Starting from `v9.0.6` supported changes regarding new storage for `latest` versions of chromedriver.

Starting from `v9.2.0` added new feature 'onlyDriver'

## Install & Run

Expand Down
18 changes: 11 additions & 7 deletions bin/selenium-standalone
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ const actions = {
const killEvents = ['exit', 'SIGTERM', 'SIGINT'];
const cp = await selenium.start(options);

console.log('Selenium started');

killEvents.forEach((evName) => {
process.once(evName, () => cp.kill('SIGTERM'));
});

if (!options.onlyDriver) {
console.log('Selenium started');

killEvents.forEach((evName) => {
process.once(evName, () => cp.kill('SIGTERM'));
});
} else if (cp._handle) {
console.log(`started driver path ${cp.spawnfile}`);
}
return cp;
},
install: async function (options) {
Expand Down Expand Up @@ -56,8 +59,9 @@ const actions = {

bar.tick(chunk);
}
const paths = await selenium.install(options);

await selenium.install(options);
return paths;
},
};

Expand Down
8 changes: 5 additions & 3 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async function myFn() {
await selenium.install({
// check for more recent versions of selenium here:
// https://selenium-release.storage.googleapis.com/index.html
version: process.env.SELENIUM_VERSION || '4.4.0',
version: process.env.SELENIUM_VERSION || '4.9.0',
baseURL: 'https://selenium-release.storage.googleapis.com',
drivers: {
chrome: {
Expand Down Expand Up @@ -86,6 +86,8 @@ arch [sometimes](https://code.google.com/p/selenium/issues/detail?id=5116#c9).

`opts.requestOpts` can be any valid [`got` options object](https://www.npmjs.com/package/got#proxies). You can use this for example to set a timeout.

`opts.onlyDriver` can be any valid 'chrome' | 'firefox' | 'chromiumedge' it allow to install any driver without selenium server

returns `Promise<void>`

## selenium.start([opts])
Expand Down Expand Up @@ -113,6 +115,8 @@ By default all drivers are loaded, you only control and change the versions or a

`opts.processKiller` set to falsy value, for preventing killing selenium server port.

`opts.onlyDriver` can be any valid 'chrome' | 'firefox' | 'chromiumedge' it allow to start any driver directly without selenium server

returns `Promise<ChildProcess>`

## Error: Port 4444 is already in use.
Expand All @@ -123,8 +127,6 @@ If you're getting this error, it means that you didn't shut down the server succ
pkill -f selenium-standalone
```

or use truthy `opts.processKiller` in config

## 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)
4 changes: 4 additions & 0 deletions docs/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ selenium-standalone start --config=./config/seleniumConfig.js
# prevent killing selenium process before start
selenium-standalone start --processKiller=false

# install or start only certain driver
selenium-standalone install --onlyDriver=chrome
selenium-standalone start --onlyDriver=chrome

```

Config file can be a JSON file or a [module file](https://nodejs.org/api/modules.html#modules_file_modules) that exports options as an object:
Expand Down
6 changes: 5 additions & 1 deletion lib/compute-fs-paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const computeFsPaths = async (options) => {
opts.basePath,
'iedriver',
`${opts.drivers.ie.version}-${detectBrowserPlatformCustom(opts.drivers.ie.arch)}`,
'IEDriverServer.exe'
'IEDriverServer'
),
};
}
Expand Down Expand Up @@ -96,6 +96,10 @@ const computeFsPaths = async (options) => {
downloadPath = acc[name].installPath + '.gz';
} else {
downloadPath = acc[name].installPath + '.zip';

if (process.platform === 'win32') {
acc[name].installPath = `${acc[name].installPath}.exe`;
}
}
acc[name].downloadPath = downloadPath;
return acc;
Expand Down
3 changes: 3 additions & 0 deletions lib/default-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module.exports = () => {
version: 'latest',
channel: 'stable',
arch: process.arch,
onlyDriverArgs: [],
baseURL: 'https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing',
},
ie: {
Expand All @@ -18,6 +19,7 @@ module.exports = () => {
version: 'latest',
fallbackVersion: '0.30.0',
arch: process.arch,
onlyDriverArgs: [],
baseURL: 'https://github.com/mozilla/geckodriver/releases/download',
},
edge: {
Expand All @@ -27,6 +29,7 @@ module.exports = () => {
version: 'latest',
fallbackVersion: '96.0.1054.34',
arch: process.arch,
onlyDriverArgs: [],
baseURL: 'https://msedgedriver.azureedge.net',
},
},
Expand Down
48 changes: 48 additions & 0 deletions lib/driver-starter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const ChildProcess = require('child_process');
const delay = require('./delay');

async function startDriver(pathToDriver, args) {
const options = {
cwd: process.cwd(),
env: process.env,
stdio: 'inherit',
};
let driverProcess;

if (process.platform === 'win32' && !pathToDriver.endsWith('.exe')) {
driverProcess = ChildProcess.spawn('powershell', [
`Start-Process -FilePath "${pathToDriver}"`,
'-Wait',
'-NoNewWindow',
]);
} else {
driverProcess = ChildProcess.spawn(pathToDriver, args, options);
}
await delay.sleep(3000);

driverProcess.on('close', (code) => {
if (code !== null && code !== 0 && code !== 1) {
throw new Error(`Chromedriver exited with error code: ${code}`);
}
});

driverProcess.on('error', (error) => {
throw new Error(error);
});

const killChromeDriver = () => {
try {
driverProcess.kill();
} catch (_) {
// eslint-disable-next-line no-empty
}
};
process.on('exit', killChromeDriver);
process.on('SIGTERM', killChromeDriver);

return driverProcess;
}

module.exports = {
startDriver,
};
4 changes: 3 additions & 1 deletion lib/install-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ async function uncompressDownloadedFile(zipFilePath) {
}
const extractPath = path.join(
path.dirname(zipFilePath),
isBrowserDriver(entry.fileName) ? path.basename(zipFilePath, '.zip') : path.basename(entry.fileName)
isBrowserDriver(entry.fileName)
? path.basename(zipFilePath, '.zip') + `${process.platform === 'win32' ? '.exe' : ''}`
: path.basename(entry.fileName)
);
const extractWriteStream = fs
.createWriteStream(extractPath)
Expand Down
23 changes: 15 additions & 8 deletions lib/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@ async function install(_opts) {
opts.drivers = defaultConfig.drivers;
}

if (opts.singleDriverInstall) {
const singleDriver = opts.drivers[opts.singleDriverInstall];
if (opts.singleDriverInstall || opts.onlyDriver) {
const driver = opts.singleDriverInstall || opts.onlyDriver;
const singleDriver = opts.drivers[driver];

if (singleDriver) {
opts.drivers = {};
opts.drivers[opts.singleDriverInstall] = singleDriver;
opts.drivers[driver] = singleDriver;
}
}

Expand All @@ -85,6 +87,9 @@ async function install(_opts) {
basePath: opts.basePath,
});

if (opts.onlyDriver) {
delete fsPaths.selenium;
}
const urls = await computeDownloadUrls({
seleniumVersion: opts.version,
seleniumBaseURL: opts.baseURL,
Expand All @@ -99,6 +104,7 @@ async function install(_opts) {
download.bind(null, {
urls: urls,
fsPaths: fsPaths,
opts: opts,
}),
asyncLogEnd.bind(null, logger),
];
Expand Down Expand Up @@ -138,13 +144,15 @@ async function install(_opts) {
}

async function download(opts) {
const installers = [
{
const installers = [];

if (!opts.opts.onlyDriver) {
installers.push({
installer: installSelenium,
from: opts.urls.selenium,
to: opts.fsPaths.selenium.downloadPath,
},
];
});
}

if (opts.fsPaths.chrome) {
installers.push({
Expand Down Expand Up @@ -185,7 +193,6 @@ async function install(_opts) {
to: opts.fsPaths.chromiumedge.downloadPath,
});
}

return Promise.all(installers.map((i) => onlyInstallMissingFiles(i)));
}

Expand Down
24 changes: 13 additions & 11 deletions lib/processKiller.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,27 @@ function getConfigProcessesName(drivers) {
processesName.push('IEDriverServer');
} else if (driverName === 'safari') {
processesName.push('safaridriver');
} else {
processesName.push(driverName);
}
}
}
return processesName;
}

async function processKiller(drivers, portValue) {
if (portValue) {
if (!Number.isNaN(Number(`${portValue}`.startsWith(':') ? `${portValue}`.substring(1) : `${portValue}`))) {
const portCast = `${portValue}`.startsWith(':') ? portValue : `:${portValue}`;
async function processKiller(ports, processesName) {
if (ports && ports.length) {
for (const port of ports) {
if (port) {
const portCast = `${port}`.startsWith(':') ? port : `:${port}`;

await killProcessByFkill([portCast]);
await killProcessByCmd([`${portValue}`.startsWith(':') ? `${portValue}`.substring(1) : portValue], 'port');
await killProcessByFkill([portCast]);
await killProcessByCmd([`${port}`.startsWith(':') ? `${port}`.substring(1) : port], 'port');
}
}
}
if (drivers && typeof drivers === 'object' && Object.keys(drivers).length) {
await killProcess(getConfigProcessesName(drivers), 'name');
if (processesName && processesName.length) {
await killProcess(getConfigProcessesName(processesName), 'name');
}
}

Expand Down Expand Up @@ -81,6 +85,4 @@ async function killProcessByFkill(processes) {
}
}

module.exports = {
processKiller,
};
module.exports = processKiller;
Loading

0 comments on commit 1822711

Please sign in to comment.