-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from cdagli/master
Formatter fixes applied & TravisCI integration & tests added
- Loading branch information
Showing
8 changed files
with
195 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
language: node_js | ||
node_js: | ||
- "node" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[![Build Status](https://travis-ci.org/cdagli/browser-driver-installer.svg?branch=master)](https://travis-ci.org/cdagli/browser-driver-installer) | ||
|
||
# browser-driver-installer | ||
Installs Chrome and Gecko drivers that match with the specified browser versions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,14 @@ | ||
#!/usr/bin/env node | ||
|
||
const program = require('commander'); | ||
const driverInstaller = require('./installer').driverInstaller; | ||
|
||
program | ||
.option('--chrome-version [chromeVersion]', 'Chrome browser major version string e.g. 65') | ||
.option('--chrome-driver-target-path [chromeDriverTargetPath]', 'Path to install Chrome driver executable') | ||
.option('--firefox-version [firefoxVersion]', 'Firefox browser major version string e.g. 57') | ||
.option('--firefox-driver-target-path [firefoxDriverTargetPath]', 'Path to install Firefox driver(geckoDriver) executable') | ||
.option('--firefox-driver-target-path [firefoxDriverTargetPath]', | ||
'Path to install Firefox driver(geckoDriver) executable') | ||
.parse(process.argv); | ||
|
||
driverInstaller(program.chromeVersion, program.chromeDriverTargetPath, program.firefoxVersion, program.firefoxDriverTargetPath); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,110 +1,147 @@ | ||
'use strict'; | ||
'use strict'; | ||
/* eslint-disable no-console */ | ||
|
||
var runNpmChildProcess = require('./runNpmChildProcess'); | ||
var path = require('path'); | ||
var execSync = require('child_process').execSync; | ||
var shell = require('shelljs'); | ||
const runNpmChildProcess = require('./runNpmChildProcess'); | ||
const path = require('path'); | ||
const execSync = require('child_process').execSync; | ||
const shell = require('shelljs'); | ||
|
||
const TEMP_DIR = 'temp'; | ||
const TEMP_DIR = 'temp'; | ||
const CHROME_DRIVER_NAME = 'chromedriver'; | ||
const CHROME_DRIVER_BIN_PATH = path.join('node_modules', 'chromedriver', 'lib', 'chromedriver', CHROME_DRIVER_NAME); | ||
const CHROME_DRIVER_VERSION_REGEX = new RegExp(/\w+ ([0-9]+.[0-9]+).+/); | ||
const GECKO_DRIVER_NAME = 'geckodriver'; | ||
const GECKO_DRIVER_NAME = 'geckodriver'; | ||
const GECKO_DRIVER_BIN_PATH = path.join('node_modules', 'geckodriver', GECKO_DRIVER_NAME); | ||
const GECKO_DRIVER_VERSION_REGEX = new RegExp(/\w+\s(\d+.\d+.\d+)/); | ||
const BROWSER_MAJOR_VERSION_REGEX = new RegExp(/^(\d+)/); | ||
|
||
function installDriverWithVersion(driverName, driverBinPath, installPath, versionObject) | ||
{ | ||
if(checkDirectoryAndVersion(driverName, installPath, versionObject.driverVersion)) | ||
if (checkDirectoryAndVersion(driverName, installPath, versionObject.driverVersion)) | ||
{ | ||
return; | ||
return false; | ||
} | ||
|
||
shell.mkdir('-p', TEMP_DIR); | ||
|
||
runNpmChildProcess(['install', `${driverName}@${versionObject.driverNPMPackageVersion}`, '--prefix', TEMP_DIR]).then(function () | ||
return runNpmChildProcess(['install', `${driverName}@${versionObject.driverNPMPackageVersion}`, '--prefix', | ||
TEMP_DIR | ||
]).then( | ||
function () | ||
{ | ||
shell.mkdir('-p', installPath); | ||
console.log('package dependencies have been installed'); | ||
shell.cp('-n',path.join(TEMP_DIR, driverBinPath), installPath); | ||
shell.cp('-n', path.join(TEMP_DIR, driverBinPath), installPath); | ||
shell.rm('-rf', TEMP_DIR); | ||
}, function (e) | ||
console.log('package dependencies have been installed'); | ||
return true; | ||
}, | ||
function (e) | ||
{ | ||
console.log('package dependencies installation failed with error, details: ' + e.toString()); | ||
throw new Error('package dependencies installation failed with error, details: ' + e.toString()); | ||
}); | ||
} | ||
|
||
function checkDirectoryAndVersion(driverName, installPath, driverExpectedVersion) | ||
{ | ||
if (!shell.test('-e', installPath)) { | ||
return false; | ||
if (!shell.test('-e', installPath)) | ||
{ | ||
return false; | ||
} | ||
console.log(`Directory '${installPath}' does exist.`); | ||
console.log(`Checking if the directory contains a ${driverName}...`); | ||
|
||
if(!shell.test('-e', path.join(installPath, driverName))){ | ||
console.log(`Could not find the ${driverName} in the directory '${installPath}'. Attempting to install it...`); | ||
return false; | ||
if (!shell.test('-e', path.join(installPath, driverName))) | ||
{ | ||
console.log(`Could not find the ${driverName} in the directory '${installPath}'. Attempting to install it...`); | ||
return false; | ||
} | ||
console.log(`${driverName} found.`); | ||
const driverMajorVersion = driverVersionString(driverName, installPath); | ||
if(driverMajorVersion !== driverExpectedVersion) | ||
|
||
console.log(`${driverName} found.`); | ||
const driverMajorVersion = driverVersionString(driverName, installPath); | ||
if (driverMajorVersion !== driverExpectedVersion) | ||
{ | ||
console.log(`${driverName} expected version (${driverExpectedVersion}) does not match with the installed version (${driverMajorVersion}).`); | ||
console.log( | ||
`${driverName} expected version (${driverExpectedVersion}) does not match with the installed version (${driverMajorVersion}).` | ||
); | ||
console.log('Removing the old version...'); | ||
shell.rm(path.join(installPath, driverName)); | ||
return false; | ||
return false; | ||
} | ||
|
||
console.log(`${driverName} version ${driverExpectedVersion} has already been installed!`); | ||
return true; | ||
return true; | ||
} | ||
|
||
function driverVersionString(driverName, installPath) | ||
{ | ||
let versionOutput = null; | ||
if(driverName === CHROME_DRIVER_NAME){ | ||
let versionOutput = null; | ||
if (driverName === CHROME_DRIVER_NAME) | ||
{ | ||
versionOutput = execSync(path.join(installPath, driverName) + ' -v').toString(); | ||
return versionOutput.match(CHROME_DRIVER_VERSION_REGEX)[1]; | ||
} else if (driverName === GECKO_DRIVER_NAME) | ||
} | ||
else if (driverName === GECKO_DRIVER_NAME) | ||
{ | ||
versionOutput = execSync(path.join(installPath, driverName) + ' -V').toString(); | ||
return versionOutput.match(GECKO_DRIVER_VERSION_REGEX)[1]; | ||
} else { | ||
} | ||
else | ||
{ | ||
throw new Error(`No driver exists with the name ${driverName}.`); | ||
} | ||
} | ||
|
||
function driverInstaller(detectedChromeVersion, chromeDriverTargetPath, detectedFirefoxVersion, geckoDriverTargetPath){ | ||
function driverInstaller(detectedChromeVersion, chromeDriverTargetPath, detectedFirefoxVersion, geckoDriverTargetPath) | ||
{ | ||
const browserVersionsObject = JSON.parse(shell.cat(path.resolve(__dirname, 'driverVersions.json'))); | ||
// ChromeDriver NPM package versions are defined according to https://github.com/giggio/node-chromedriver/releases | ||
const chromeDriverVersions = browserVersionsObject.chromeDriverVersions; | ||
const chromeDriverVersions = browserVersionsObject.chromeDriverVersions; | ||
|
||
// GeckoDriver NPM package versions are defined according to https://github.com/mozilla/geckodriver/releases | ||
const geckoDriverVersions = browserVersionsObject.geckoDriverVersions; | ||
|
||
detectedChromeVersion = majorBrowserVersion(detectedChromeVersion); | ||
detectedFirefoxVersion = majorBrowserVersion(detectedFirefoxVersion); | ||
|
||
if(detectedChromeVersion && !chromeDriverVersions[detectedChromeVersion]){ | ||
console.log(`Failed to locate a version of ChromeDriver that matches the installed version of Chrome (${detectedChromeVersion}). Valid Chrome versions are: ${Object.keys(chromeDriverVersions).join(', ')}`) | ||
} else if(detectedChromeVersion){ | ||
installDriverWithVersion(CHROME_DRIVER_NAME, CHROME_DRIVER_BIN_PATH, chromeDriverTargetPath, chromeDriverVersions[detectedChromeVersion]); | ||
if (detectedChromeVersion && !chromeDriverVersions[detectedChromeVersion]) | ||
{ | ||
throw new Error( | ||
`Failed to locate a version of ChromeDriver that matches the installed version of Chrome (${detectedChromeVersion}). Valid Chrome versions are: ${Object.keys(chromeDriverVersions).join(', ')}` | ||
); | ||
} | ||
else if (detectedChromeVersion && typeof (chromeDriverTargetPath) === 'string') | ||
{ | ||
return installDriverWithVersion(CHROME_DRIVER_NAME, CHROME_DRIVER_BIN_PATH, chromeDriverTargetPath, | ||
chromeDriverVersions[detectedChromeVersion]); | ||
} | ||
else | ||
{ | ||
console.log('No Chrome version or target path is provided. Skipping...'); | ||
} | ||
|
||
if(detectedFirefoxVersion && !geckoDriverVersions[detectedFirefoxVersion]){ | ||
console.log(`Failed to locate a version of GeckoDriver that matches the installed version of Firefox (${detectedFirefoxVersion}). Valid Firefox versions are: ${Object.keys(geckoDriverVersions).join(', ')}`) | ||
} else if(detectedFirefoxVersion){ | ||
installDriverWithVersion(GECKO_DRIVER_NAME, GECKO_DRIVER_BIN_PATH, geckoDriverTargetPath, geckoDriverVersions[detectedFirefoxVersion]) | ||
if (detectedFirefoxVersion && !geckoDriverVersions[detectedFirefoxVersion]) | ||
{ | ||
throw new Error( | ||
`Failed to locate a version of GeckoDriver that matches the installed version of Firefox (${detectedFirefoxVersion}). Valid Firefox versions are: ${Object.keys(geckoDriverVersions).join(', ')}` | ||
); | ||
} | ||
else if (detectedFirefoxVersion && (typeof geckoDriverTargetPath) === 'string') | ||
{ | ||
return installDriverWithVersion(GECKO_DRIVER_NAME, GECKO_DRIVER_BIN_PATH, geckoDriverTargetPath, | ||
geckoDriverVersions[ | ||
detectedFirefoxVersion]); | ||
} | ||
else | ||
{ | ||
console.log('No Firefox version or target path is provided. Skipping...'); | ||
} | ||
|
||
return false; | ||
} | ||
|
||
function majorBrowserVersion(browserVersionString) | ||
{ | ||
return browserVersionString && browserVersionString.match(BROWSER_MAJOR_VERSION_REGEX)[0]; | ||
return (typeof browserVersionString) === 'string' && browserVersionString.match(BROWSER_MAJOR_VERSION_REGEX)[0]; | ||
} | ||
|
||
module.exports.driverInstaller = driverInstaller; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
const chai = require('chai'); | ||
const installer = require('./installer'); | ||
const expect = require('chai').expect; | ||
const sinon = require('sinon'); | ||
const chaiSinon = require('chai-sinon'); | ||
const shell = require('shelljs'); | ||
const path = require('path'); | ||
|
||
chai.use(chaiSinon); | ||
|
||
describe('browserDriverInstaller', function () | ||
{ | ||
const DEFAULT_TIMEOUT_IN_MILLIS = 60000; | ||
const DRIVER_OUTPUT_PATH = './output'; | ||
|
||
this.timeout(DEFAULT_TIMEOUT_IN_MILLIS); | ||
|
||
beforeEach(function () | ||
{ | ||
sinon.spy(console, 'log'); | ||
}); | ||
|
||
afterEach(function () | ||
{ | ||
console.log.restore(); | ||
cleanTheOutput(); | ||
}); | ||
|
||
function cleanTheOutput() | ||
{ | ||
shell.rm('-rf', DRIVER_OUTPUT_PATH); | ||
} | ||
|
||
it('should not attempt to install anything if one of the path, version or both parameters are not provided', | ||
function () | ||
{ | ||
expect(installer.driverInstaller()).to.be.false; | ||
expect(console.log).to.have.been.calledWith( | ||
'No Chrome version or target path is provided. Skipping...'); | ||
expect(console.log).to.have.been.calledWith( | ||
'No Firefox version or target path is provided. Skipping...'); | ||
}); | ||
|
||
it('should throw an error if the provided version does not included in the JSON file', function () | ||
{ | ||
const wrongVersionNumber = '1'; | ||
expect(function () { installer.driverInstaller(wrongVersionNumber, '/some/target/path'); }).to.throw( | ||
/Failed to locate a version of ChromeDriver that matches the installed version of Chrome \(1\). Valid Chrome versions are:*/ | ||
); | ||
}); | ||
|
||
it('should install the chromedriver to specified path if the version is included in the JSON file', | ||
function () | ||
{ | ||
return installer.driverInstaller('54', DRIVER_OUTPUT_PATH).then(function () | ||
{ | ||
expect(shell.test('-e', path.resolve(DRIVER_OUTPUT_PATH, 'chromedriver'))).to.be.true; | ||
}); | ||
}); | ||
|
||
it('should install the geckodriver to specified path if the version is included in the JSON file', function () | ||
{ | ||
return installer.driverInstaller(null, null, '55', DRIVER_OUTPUT_PATH).then(function () | ||
{ | ||
expect(shell.test('-e', path.resolve(DRIVER_OUTPUT_PATH, 'geckodriver'))).to.be.true; | ||
}); | ||
}); | ||
|
||
it('should not install again if the wanted version is already installed', function () | ||
{ | ||
return installer.driverInstaller('54', DRIVER_OUTPUT_PATH).then(function () | ||
{ | ||
expect(installer.driverInstaller('54', DRIVER_OUTPUT_PATH)).to.be.false; | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,23 @@ | ||
{ | ||
"bin": { | ||
"browserDriverInstaller": "./index.js" | ||
}, | ||
"name": "browser-driver-installer", | ||
"version": "0.0.1", | ||
"description": "Installs Chrome and Gecko drivers that matches with the specified browser versions", | ||
"main": "index.js", | ||
"dependencies": { | ||
"commander": "2.15.1", | ||
"shelljs": "0.8.1" | ||
}, | ||
"scripts": { | ||
"postinstall": "node ./index.js --chrome-version $CHROME_VERSION --chrome-driver-target-path $CHROMEDRIVER_PATH --firefox-version $FIREFOX_VERSION --firefox-driver-target-path $GECKODRIVER_PATH" | ||
}, | ||
"author": "Unscrambl", | ||
"license": "Apache-2.0" | ||
"author": "Unscrambl", | ||
"bin": { | ||
"browserDriverInstaller": "./index.js" | ||
}, | ||
"dependencies": { | ||
"chai": "4.1.2", | ||
"chai-sinon": "2.8.1", | ||
"commander": "2.15.1", | ||
"mocha": "5.1.1", | ||
"shelljs": "0.8.1", | ||
"sinon": "5.0.2" | ||
}, | ||
"description": "Installs Chrome and Gecko drivers that matches with the specified browser versions", | ||
"license": "Apache-2.0", | ||
"main": "index.js", | ||
"name": "browser-driver-installer", | ||
"scripts": { | ||
"postinstall": "node ./index.js --chrome-version $CHROME_VERSION --chrome-driver-target-path $CHROMEDRIVER_PATH --firefox-version $FIREFOX_VERSION --firefox-driver-target-path $GECKODRIVER_PATH", | ||
"test": "node_modules/mocha/bin/mocha *.spec.js" | ||
}, | ||
"version": "0.0.1" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters