Skip to content

feat(max_versions): set max versions based on string matching #369

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 6, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 99 additions & 38 deletions lib/cli/index.ts
Original file line number Diff line number Diff line change
@@ -5,14 +5,16 @@ import * as start from '../cmds/start';
import * as status from '../cmds/status';
import * as update from '../cmds/update';

const CHROME = 'chrome';
const chromeOption: yargs.Options = {
const CHROMEDRIVER_ALIAS = 'chrome';
const CHROMEDRIVER = 'chromedriver';
const chromedriverOption: yargs.Options = {
describe: 'Install or update chromedriver.',
default: true,
type: 'boolean'
};
const CHROME_LOGS = 'chrome_logs';
const chromeLogsOption: yargs.Options = {
const CHROMEDRIVER_LOGS_ALIAS = 'chrome_logs';
const CHROMEDRIVER_LOGS = 'chromedriver_logs';
const chromedriverLogsOption: yargs.Options = {
describe: 'File path to chrome logs.',
type: 'string'
};
@@ -30,8 +32,9 @@ const edgeOption: yargs.Options = {
'"C:\Program Files (x86)\Microsoft Web Driver\MirosoftWebDriver.exe"',
type: 'string'
};
const GECKO = 'gecko';
const geckoOption: yargs.Options = {
const GECKODRIVER_ALIAS = 'gecko';
const GECKODRIVER = 'geckodriver';
const geckodriverOption: yargs.Options = {
describe: 'Install or update geckodriver.',
default: true,
type: 'boolean'
@@ -41,8 +44,9 @@ const githubTokenOption: yargs.Options = {
describe: 'Use a GitHub token to prevent rate limit issues.',
type: 'string'
};
const IEDRIVER_ALIAS = 'ie';
const IEDRIVER = 'iedriver';
const ieOption: yargs.Options = {
const iedriverOption: yargs.Options = {
describe: 'Install or update ie driver.',
default: false,
type: 'boolean'
@@ -58,6 +62,31 @@ const logLevelOption: yargs.Options = {
default: 'info',
type: 'string'
};
const MAX_VERSIONS_CHROMEDRIVER_ALIAS = 'max_versions.chrome';
const MAX_VERSIONS_CHROMEDRIVER = 'max_versions.chromedriver';
const maxVersionsChromedriverOption: yargs.Options = {
describe: 'The chromedriver max version used only for update.',
type: 'string'
};
const MAX_VERSIONS_GECKODRIVER_ALIAS = 'max_versions.gecko';
const MAX_VERSIONS_GECKODRIVER = 'max_versions.geckodriver';
const maxVersionsGeckodriverOption: yargs.Options = {
describe: 'The geckodriver max version used only for update.',
type: 'string'
};
const MAX_VERSIONS_IEDRIVER_ALIAS = 'max_versions.ie';
const MAX_VERSIONS_IEDRIVER = 'max_versions.iedriver';
const maxVersionsIedriverOption: yargs.Options = {
describe: 'The ie driver max version used only for update.',
type: 'string'
};
const MAX_VERSIONS_SELENIUM_ALIAS = 'max_versions.standalone';
const MAX_VERSIONS_SELENIUM = 'max_versions.selenium';
const maxVersionsSeleniumOption: yargs.Options = {
describe: 'The selenium server standalone max version used only for update.',
type: 'string'
};

const OUT_DIR = 'out_dir';
const outDirOption: yargs.Options = {
describe: 'Location of output.',
@@ -79,34 +108,40 @@ const seleniumLogLevelOption: yargs.Options = {
describe: 'Set the -Dselenium.LOGGER.level flag when starting the server',
type: 'string'
};
const STANDALONE = 'standalone';
const standaloneOption: yargs.Options = {
const SELENIUM_ALIAS = 'standalone';
const SELENIUM = 'selenium';
const seleniumOption: yargs.Options = {
describe: 'Install or update selenium server standalone.',
default: true,
type: 'boolean'
};
const STANDALONE_NODE = 'standalone_node';
const standaloneNodeOption: yargs.Options = {
const SELENIUM_NODE_ALIAS = 'standalone_node';
const SELENIUM_NODE = 'selenium_node';
const seleniumNodeOption: yargs.Options = {
describe: 'Start the selenium server standalone with role set to "node".',
type: 'boolean'
};
const VERSIONS_CHROME = 'versions.chrome';
const versionsChromeOption: yargs.Options = {
const VERSIONS_CHROMEDRIVER_ALIAS = 'versions.chrome';
const VERSIONS_CHROMEDRIVER = 'versions.chromedriver';
const versionsChromedriverOption: yargs.Options = {
describe: 'The chromedriver version.',
type: 'string'
};
const VERSIONS_GECKO = 'versions.gecko';
const versionsGeckoOption: yargs.Options = {
const VERSIONS_GECKODRIVER_ALIAS = 'versions.gecko';
const VERSIONS_GECKODRIVER = 'versions.geckodriver';
const versionsGeckodriverOption: yargs.Options = {
describe: 'The geckodriver version.',
type: 'string'
};
const VERSIONS_IE = 'versions.ie';
const versionsIeOption: yargs.Options = {
const VERSIONS_IEDRIVER_ALIAS = 'versions.ie';
const VERSIONS_IEDRIVER = 'versions.iedriver';
const versionsIedriverOption: yargs.Options = {
describe: 'The ie driver version.',
type: 'string'
};
const VERSIONS_STANDALONE = 'versions.standalone';
const versionsStandaloneOption: yargs.Options = {
const VERSIONS_SELENIUM_ALIAS = 'versions.standalone';
const VERSIONS_SELENIUM = 'versions.selenium';
const versionsSeleniumOption: yargs.Options = {
describe: 'The selenium server standalone version.',
type: 'string'
};
@@ -133,22 +168,33 @@ yargs
.command(
'start', 'Start up the selenium server.',
(yargs: yargs.Argv) => {
return yargs.option(CHROME, chromeOption)
.option(CHROME_LOGS, chromeLogsOption)
return yargs
.option(CHROMEDRIVER, chromedriverOption)
.alias(CHROMEDRIVER_ALIAS, CHROMEDRIVER)
.option(CHROMEDRIVER_LOGS, chromedriverLogsOption)
.alias(CHROMEDRIVER_LOGS_ALIAS, CHROMEDRIVER_LOGS)
.option(DETACH, detachOption)
.option(EDGE, edgeOption)
.option(GECKO, geckoOption)
.option(IEDRIVER, ieOption)
.option(GECKODRIVER, geckodriverOption)
.alias(GECKODRIVER_ALIAS, GECKODRIVER)
.option(IEDRIVER, iedriverOption)
.alias(IEDRIVER_ALIAS, IEDRIVER)
.option(LOG_LEVEL, logLevelOption)
.option(OUT_DIR, outDirOption)
.option(SELENIUM_PORT, seleniumPort)
.option(SELENIUM, seleniumOption)
.alias(SELENIUM_ALIAS, SELENIUM)
.option(SELENIUM_LOG_LEVEL, seleniumLogLevelOption)
.option(STANDALONE, standaloneOption)
.option(STANDALONE_NODE, standaloneNodeOption)
.option(VERSIONS_CHROME, versionsChromeOption)
.option(VERSIONS_GECKO, versionsGeckoOption)
.option(VERSIONS_IE, versionsIeOption)
.option(VERSIONS_STANDALONE, versionsStandaloneOption);
.option(SELENIUM_NODE, seleniumNodeOption)
.alias(SELENIUM_NODE_ALIAS, SELENIUM_NODE)
.option(SELENIUM_PORT, seleniumPort)
.option(VERSIONS_CHROMEDRIVER, versionsChromedriverOption)
.alias(VERSIONS_CHROMEDRIVER_ALIAS, VERSIONS_CHROMEDRIVER)
.option(VERSIONS_GECKODRIVER, versionsGeckodriverOption)
.alias(VERSIONS_GECKODRIVER_ALIAS, VERSIONS_GECKODRIVER)
.option(VERSIONS_IEDRIVER, versionsIedriverOption)
.alias(VERSIONS_IEDRIVER_ALIAS, VERSIONS_IEDRIVER)
.option(VERSIONS_SELENIUM, versionsSeleniumOption)
.alias(VERSIONS_SELENIUM_ALIAS, VERSIONS_SELENIUM);
},
(argv: yargs.Arguments) => {
start.handler(argv);
@@ -166,19 +212,34 @@ yargs
'update', 'Install or update selected binaries.',
(yargs: yargs.Argv) => {
return yargs.option(OUT_DIR, outDirOption)
.option(CHROME, chromeOption)
.option(GECKO, geckoOption)
.option(CHROMEDRIVER, chromedriverOption)
.alias(CHROMEDRIVER_ALIAS, CHROMEDRIVER)
.option(GECKODRIVER, geckodriverOption)
.alias(GECKODRIVER_ALIAS, GECKODRIVER)
.option(GITHUB_TOKEN, githubTokenOption)
.option(IEDRIVER, ieOption)
.option(IEDRIVER, iedriverOption)
.alias(IEDRIVER_ALIAS, IEDRIVER)
.option(IGNORE_SSL, ignoreSSLOption)
.option(LOG_LEVEL, logLevelOption)
.option(MAX_VERSIONS_CHROMEDRIVER, maxVersionsChromedriverOption)
.alias(MAX_VERSIONS_CHROMEDRIVER_ALIAS, MAX_VERSIONS_CHROMEDRIVER)
.option(MAX_VERSIONS_GECKODRIVER, maxVersionsGeckodriverOption)
.alias(MAX_VERSIONS_GECKODRIVER_ALIAS, MAX_VERSIONS_GECKODRIVER)
.option(MAX_VERSIONS_IEDRIVER, maxVersionsIedriverOption)
.alias(MAX_VERSIONS_IEDRIVER_ALIAS, MAX_VERSIONS_IEDRIVER)
.option(MAX_VERSIONS_SELENIUM, maxVersionsSeleniumOption)
.option(OUT_DIR, outDirOption)
.option(PROXY, proxyOption)
.option(STANDALONE, standaloneOption)
.option(VERSIONS_CHROME, versionsChromeOption)
.option(VERSIONS_GECKO, versionsGeckoOption)
.option(VERSIONS_IE, versionsIeOption)
.option(VERSIONS_STANDALONE, versionsStandaloneOption);
.option(SELENIUM, seleniumOption)
.alias(SELENIUM_ALIAS, SELENIUM)
.option(VERSIONS_CHROMEDRIVER, versionsChromedriverOption)
.alias(VERSIONS_CHROMEDRIVER_ALIAS, VERSIONS_CHROMEDRIVER)
.option(VERSIONS_GECKODRIVER, versionsGeckodriverOption)
.alias(VERSIONS_GECKODRIVER_ALIAS, VERSIONS_GECKODRIVER)
.option(VERSIONS_IEDRIVER, versionsIedriverOption)
.alias(VERSIONS_IEDRIVER_ALIAS, VERSIONS_IEDRIVER)
.option(VERSIONS_SELENIUM, versionsSeleniumOption)
.alias(VERSIONS_SELENIUM_ALIAS, VERSIONS_SELENIUM);
},
(argv: yargs.Arguments) => {
update.handler(argv);
14 changes: 7 additions & 7 deletions lib/cmds/cmds.spec-e2e.ts
Original file line number Diff line number Diff line change
@@ -39,8 +39,8 @@ describe('using the cli', () => {
it('should download the files', async () => {
const argv = {
_: ['foobar'],
chrome: true,
standalone: true,
chromedriver: true,
selenium: true,
out_dir: tmpDir,
'$0': 'bin\\webdriver-manager'
};
@@ -70,9 +70,9 @@ describe('using the cli', () => {
it('should start the selenium server standalone in role=node', async () => {
const argv = {
_: ['foobar'],
chrome: true,
standalone: true,
standalone_node: true,
chromedriver: true,
selenium: true,
selenium_node: true,
out_dir: tmpDir,
'$0': 'bin\\webdriver-manager'
};
@@ -104,8 +104,8 @@ describe('using the cli', () => {
it('should start the selenium server standalone', async () => {
const argv = {
_: ['foobar'],
chrome: true,
standalone: true,
chromedriver: true,
selenium: true,
out_dir: tmpDir,
'$0': 'bin\\webdriver-manager'
};
8 changes: 7 additions & 1 deletion lib/cmds/options.ts
Original file line number Diff line number Diff line change
@@ -16,14 +16,18 @@ export interface Options {
githubToken?: string;
}

export type BrowserDriverName = 'chromedriver'|'geckodriver'|'iedriver';

/**
* Contains information about a browser driver.
*/
export interface BrowserDriver {
// The name of the browser driver.
name?: 'chromedriver'|'geckodriver'|'iedriver';
name?: BrowserDriverName;
// The version which does not have to follow semver.
version?: string;
// A max version that either fully or partially matches the version.
maxVersion?: string;
}

/**
@@ -35,6 +39,8 @@ export interface Server {
name?: 'selenium';
// The version which does not have to follow semver.
version?: string;
// A max version that either fully or partially matches the version.
maxVersion?: string;
// Run as role = node option.
runAsNode?: boolean;
// The relative or full path to the chrome logs file.
8 changes: 5 additions & 3 deletions lib/cmds/update.ts
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ const log = loglevel.getLogger('webdriver-manager');
* @param argv The argv from yargs.
*/
export async function handler(argv: yargs.Arguments) {
log.setLevel(argv.log_level);
log.setLevel(argv['log_level']);
const options = convertArgs2Options(argv);
await update(options);
}
@@ -35,12 +35,14 @@ export function updateBinary(optionsBinary: OptionsBinary): Promise<void[]> {
const promises = [];
if (optionsBinary.browserDrivers) {
for (const provider of optionsBinary.browserDrivers) {
promises.push(provider.binary.updateBinary(provider.version));
promises.push(provider.binary.updateBinary(provider.version,
provider.maxVersion));
}
}
if (optionsBinary.server && optionsBinary.server.binary) {
promises.push(
optionsBinary.server.binary.updateBinary(optionsBinary.server.version));
optionsBinary.server.binary.updateBinary(optionsBinary.server.version,
optionsBinary.server.maxVersion));
}
return Promise.all(promises);
}
24 changes: 5 additions & 19 deletions lib/cmds/utils.spec-unit.ts
Original file line number Diff line number Diff line change
@@ -6,30 +6,16 @@ describe('utils', () => {
const argv = {
_: ['foobar'],
proxy: 'http://some.proxy.com',
versions: {gecko: '0.16.0', chrome: '2.20'},
versions: {geckodriver: '0.16.0', chromedriver: '2.20'},
out_dir: 'foobar_download',
ignore_ssl: false,
'$0': 'bin\\webdriver-manager'
};
const options = convertArgs2AllOptions(argv);
expect(options.browserDrivers).toBeTruthy();
expect(options.browserDrivers.length).toBe(3);
for (const provider of options.browserDrivers) {
if (provider.name === 'geckodriver') {
expect(provider.version).toBe('0.16.0');
}
if (provider.name === 'chromedriver') {
expect(provider.version).toBe('2.20');
}
if (provider.name === 'iedriver') {
expect(provider.version).toBeUndefined();
}
}
expect(options.server).toBeTruthy();
expect(options.server.name).toBe('selenium');
expect(options.server.version).toBeUndefined();
expect(options.proxy).toBe('http://some.proxy.com');
expect(options.ignoreSSL).toBeFalsy();
expect(options.outDir).toBe('foobar_download');
});
});
@@ -38,10 +24,10 @@ describe('utils', () => {
it('should create the default providers', () => {
const argv = {
_: ['foobar'],
chrome: true,
gecko: true,
standalone: true,
versions: {gecko: '0.16.0', chrome: '2.20'},
chromedriver: true,
geckodriver: true,
selenium: true,
versions: {geckodriver: '0.16.0', chromedriver: '2.20'},
out_dir: 'foobar_download',
'$0': 'bin\\webdriver-manager'
};
76 changes: 33 additions & 43 deletions lib/cmds/utils.ts
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ import {IEDriver} from '../provider/iedriver';
import {ProviderConfig} from '../provider/provider';
import {SeleniumServer, SeleniumServerProviderConfig} from '../provider/selenium_server';

import {Options} from './options';
import {BrowserDriver, BrowserDriverName, Options} from './options';
import {OptionsBinary} from './options_binary';

/**
@@ -49,41 +49,25 @@ export function addOptionsBinary(options: Options): OptionsBinary {
}

/**
* Create the options with all providers. Used for clean and status commands.
* For the clean and status commands ONLY.
* Create the options with all providers.
* @param argv
*/
export function convertArgs2AllOptions(argv: yargs.Arguments): Options {
let versionsChrome, versionsGecko, versionsIe, versionsStandalone = undefined;
if (argv.versions) {
versionsChrome = argv.versions.chrome as string;
versionsGecko = argv.versions.gecko as string;
versionsIe = argv.versions.ie as string;
versionsStandalone = argv.versions.standalone as string;
}
return {
browserDrivers: [
{name: 'chromedriver', version: versionsChrome},
{name: 'geckodriver', version: versionsGecko},
{name: 'iedriver', version: versionsIe}
{name: 'chromedriver'},
{name: 'geckodriver'},
{name: 'iedriver'}
],
server: {
name: 'selenium',
version: versionsStandalone,
runAsNode: argv.standalone_node as boolean,
runAsDetach: argv.detach as boolean,
chromeLogs: argv.chrome_logs as string,
edge: argv.edge as string,
},
ignoreSSL: argv.ignore_ssl as boolean,
outDir: argv.out_dir as string,
proxy: argv.proxy as string,
githubToken: argv.github_token as string,
server: {name: 'selenium'},
outDir: argv['out_dir'] as string
};
}

/**
* Create the options with providers depending on argv's. Used for update and
* start commands.
* For the update and start commands ONLY.
* Create the options with providers depending on argv's.
* @param argv
*/
export function convertArgs2Options(argv: yargs.Arguments): Options {
@@ -96,33 +80,39 @@ export function convertArgs2Options(argv: yargs.Arguments): Options {
githubToken: argv.github_token as string,
};

let versionsChrome, versionsGecko, versionsIe, versionsStandalone = undefined;
if (argv.versions) {
versionsChrome = argv.versions.chrome as string;
versionsGecko = argv.versions.gecko as string;
versionsIe = argv.versions.ie as string;
versionsStandalone = argv.versions.standalone as string;
}
if (argv.chrome as boolean) {
options.browserDrivers.push(
{name: 'chromedriver', version: versionsChrome});
if (argv['chromedriver'] as boolean) {
setVersions('chromedriver', argv, options.browserDrivers);
}
if (argv.gecko as boolean) {
options.browserDrivers.push({name: 'geckodriver', version: versionsGecko});
if (argv['geckodriver'] as boolean) {
setVersions('geckodriver', argv, options.browserDrivers);
}
if (argv.iedriver as boolean) {
options.browserDrivers.push({name: 'iedriver', version: versionsIe});
if (argv['iedriver'] as boolean) {
setVersions('iedriver', argv, options.browserDrivers);
}
if (argv.standalone as boolean) {
if (argv['selenium']) {
options.server = {};
options.server.name = 'selenium';
options.server.runAsNode = argv.standalone_node as boolean;
options.server.runAsNode = argv['selenium_node'] as boolean;
options.server.runAsDetach = argv.detach as boolean;
options.server.version = versionsStandalone;
options.server.version = argv['versions'] && argv['versions']['selenium'] ?
argv['versions']['selenium'] as string : undefined;
options.server.maxVersion = argv['max_versions']
&& argv['max_versions']['selenium'] ?
argv['versions']['selenium'] as string : undefined;
options.server.chromeLogs = argv.chrome_logs as string;
options.server.edge = argv.edge as string;
options.server.port = argv.seleniumPort as number;
options.server.logLevel = argv.seleniumLogLevel as string;
}
return options;
}

function setVersions(name: BrowserDriverName,
argv: yargs.Arguments, browserDrivers: BrowserDriver[]): BrowserDriver[] {
const version = argv['versions'] && argv['versions'][name] ?
argv['versions'][name] as string : undefined;
const maxVersion = argv['max_versions'] && argv['max_versions'][name] ?
argv['max_versions'][name] as string : undefined;
browserDrivers.push({name, version, maxVersion});
return browserDrivers;
}
15 changes: 13 additions & 2 deletions lib/provider/chromedriver.ts
Original file line number Diff line number Diff line change
@@ -18,6 +18,8 @@ export class ChromeDriver extends ProviderClass implements ProviderInterface {
proxy: string = null;
requestUrl = 'https://chromedriver.storage.googleapis.com/';
seleniumFlag = '-Dwebdriver.chrome.driver';
version: string = null;
maxVersion: string = null;

constructor(config?: ProviderConfig) {
super();
@@ -29,14 +31,23 @@ export class ChromeDriver extends ProviderClass implements ProviderInterface {
this.outDir = this.setVar('outDir', this.outDir, config);
this.proxy = this.setVar('proxy', this.proxy, config);
this.requestUrl = this.setVar('requestUrl', this.requestUrl, config);
this.version = this.setVar('version', this.version, config);
this.maxVersion = this.setVar('maxVersion', this.maxVersion, config);
}

/**
* Should update the cache and download, find the version to download,
* then download that binary.
* @param version Optional to provide the version number or latest.
* @param maxVersion Optional to provide the max version.
*/
async updateBinary(version?: string): Promise<void> {
async updateBinary(version?: string, maxVersion?: string): Promise<void> {
if (!version) {
version = this.version;
}
if (!maxVersion) {
maxVersion = this.maxVersion;
}
await updateXml(this.requestUrl, {
fileName: path.resolve(this.outDir, this.cacheFileName),
ignoreSSL: this.ignoreSSL,
@@ -48,7 +59,7 @@ export class ChromeDriver extends ProviderClass implements ProviderInterface {
semanticVersionParser);
const versionObj = getVersion(
versionList, osHelper(this.osType, this.osArch),
formatVersion(version));
formatVersion(version), maxVersion);

const chromeDriverUrl = this.requestUrl + versionObj.url;
const chromeDriverZip = path.resolve(this.outDir, versionObj.name);
16 changes: 14 additions & 2 deletions lib/provider/geckodriver.ts
Original file line number Diff line number Diff line change
@@ -23,6 +23,8 @@ export class GeckoDriver extends ProviderClass implements ProviderInterface {
proxy: string = null;
requestUrl = 'https://api.github.com/repos/mozilla/geckodriver/releases';
seleniumFlag = '-Dwebdriver.gecko.driver';
version: string = null;
maxVersion: string = null;

constructor(config?: GeckoDriverProviderConfig) {
super();
@@ -35,14 +37,23 @@ export class GeckoDriver extends ProviderClass implements ProviderInterface {
this.proxy = this.setVar('proxy', this.proxy, config);
this.requestUrl = this.setVar('requestUrl', this.requestUrl, config);
this.oauthToken = this.setVar('oauthToken', this.oauthToken, config);
this.version = this.setVar('version', this.version, config);
this.maxVersion = this.setVar('maxVersion', this.version, config);
}

/**
* Should update the cache and download, find the version to download,
* then download that binary.
* @param version Optional to provide the version number or latest.
* @param maxVersion Optional to provide the max version.
*/
async updateBinary(version?: string): Promise<void> {
async updateBinary(version?: string, maxVersion?: string): Promise<void> {
if (!version) {
version = this.version;
}
if (!maxVersion) {
maxVersion = this.maxVersion;
}
await updateJson(
this.requestUrl, {
fileName: path.resolve(this.outDir, this.cacheFileName),
@@ -54,7 +65,8 @@ export class GeckoDriver extends ProviderClass implements ProviderInterface {
const versionList =
convertJsonToVersionList(path.resolve(this.outDir, this.cacheFileName));
const versionObj =
getVersion(versionList, osHelper(this.osType, this.osArch), version);
getVersion(versionList, osHelper(this.osType, this.osArch), version,
maxVersion);

const geckoDriverUrl = versionObj.url;
const geckoDriverCompressed = path.resolve(this.outDir, versionObj.name);
16 changes: 14 additions & 2 deletions lib/provider/iedriver.ts
Original file line number Diff line number Diff line change
@@ -18,6 +18,8 @@ export class IEDriver extends ProviderClass implements ProviderInterface {
proxy: string = null;
requestUrl = 'https://selenium-release.storage.googleapis.com/';
seleniumFlag = '-Dwebdriver.ie.driver';
version: string = null;
maxVersion: string = null;

constructor(config?: ProviderConfig) {
super();
@@ -29,14 +31,23 @@ export class IEDriver extends ProviderClass implements ProviderInterface {
this.outDir = this.setVar('outDir', this.outDir, config);
this.proxy = this.setVar('proxy', this.proxy, config);
this.requestUrl = this.setVar('requestUrl', this.requestUrl, config);
this.version = this.setVar('version', this.version, config);
this.maxVersion = this.setVar('maxVersion', this.maxVersion, config);
}

/**
* Should update the cache and download, find the version to download,
* then download that binary.
* @param version Optional to provide the version number or latest.
* @param maxVersion Optional to provide the max version.
*/
async updateBinary(version?: string): Promise<void> {
async updateBinary(version?: string, maxVersion?: string): Promise<void> {
if (!version) {
version = this.version;
}
if (!maxVersion) {
maxVersion = this.maxVersion;
}
await updateXml(this.requestUrl, {
fileName: path.resolve(this.outDir, this.cacheFileName),
ignoreSSL: this.ignoreSSL,
@@ -46,7 +57,8 @@ export class IEDriver extends ProviderClass implements ProviderInterface {
path.resolve(this.outDir, this.cacheFileName), '.zip', versionParser,
semanticVersionParser);
const versionObj =
getVersion(versionList, osHelper(this.osType, this.osArch), version);
getVersion(versionList, osHelper(this.osType, this.osArch), version,
maxVersion);

const chromeDriverUrl = this.requestUrl + versionObj.url;
const chromeDriverZip = path.resolve(this.outDir, versionObj.name);
11 changes: 7 additions & 4 deletions lib/provider/provider.ts
Original file line number Diff line number Diff line change
@@ -11,10 +11,11 @@ export interface ProviderInterface {
cleanFiles?: () => string;
getBinaryPath?: (version?: string) => string | null;
getStatus?: () => string | null;
updateBinary: (version?: string) => Promise<void>;
updateBinary: (version?: string, maxVersion?: string) => Promise<void>;
seleniumFlag?: string;
osType?: string;
versionConfig?: string;
version?: string;
maxVersion?: string;
}

/**
@@ -69,8 +70,10 @@ export interface ProviderConfig {
proxy?: string;
// Set the requests to ignore SSL (optional).
ignoreSSL?: boolean;
// Allow to pass a config for the max versions to download (optional).
versionConfig?: string;
// The version number (optional).
version?: string;
// The max version number. Partially match is okay (optional).
maxVersion?: string;
// Catch all for other things.
[key: string]: string|boolean|number;
}
15 changes: 13 additions & 2 deletions lib/provider/selenium_server.ts
Original file line number Diff line number Diff line change
@@ -35,6 +35,8 @@ export class SeleniumServer extends ProviderClass implements ProviderInterface {
runAsDetach = false;
logLevel: string = null;
javaOpts: {[key: string]: string} = {};
version: string = null;
maxVersion: string = null;

constructor(config?: SeleniumServerProviderConfig) {
super();
@@ -52,6 +54,8 @@ export class SeleniumServer extends ProviderClass implements ProviderInterface {
if (this.runAsDetach) {
this.runAsNode = true;
}
this.version = this.setVar('version', this.version, config);
this.maxVersion = this.setVar('maxVersion', this.maxVersion, config);
this.logLevel = this.setVar('logLevel', this.logLevel, config);
if (this.logLevel) {
this.setJavaFlag('-Dselenium.LOGGER.level', this.logLevel);
@@ -62,8 +66,15 @@ export class SeleniumServer extends ProviderClass implements ProviderInterface {
* Should update the cache and download, find the version to download,
* then download that binary.
* @param version Optional to provide the version number or latest.
* @param maxVersion Optional to provide the max version.
*/
async updateBinary(version?: string): Promise<void> {
async updateBinary(version?: string, maxVersion?: string): Promise<void> {
if (!version) {
version = this.version;
}
if (!maxVersion) {
maxVersion = this.maxVersion;
}
await updateXml(this.requestUrl, {
fileName: path.resolve(this.outDir, this.cacheFileName),
ignoreSSL: this.ignoreSSL,
@@ -72,7 +83,7 @@ export class SeleniumServer extends ProviderClass implements ProviderInterface {
const versionList = convertXmlToVersionList(
path.resolve(this.outDir, this.cacheFileName),
'selenium-server-standalone', versionParser, semanticVersionParser);
const versionObj = getVersion(versionList, '', version);
const versionObj = getVersion(versionList, '', version, maxVersion);

const seleniumServerUrl = this.requestUrl + versionObj.url;
const seleniumServerJar = path.resolve(this.outDir, versionObj.name);
13 changes: 13 additions & 0 deletions lib/provider/utils/version_list.spec-unit.ts
Original file line number Diff line number Diff line change
@@ -48,6 +48,19 @@ describe('version_list', () => {
expect(version['foo_win32']['size']).toBe(10101);
expect(version['foo_linux64']['size']).toBe(10102);
});

it('should return the max version for "2."', () => {
const version = getVersionObjs(versionList, null, '2.');
expect(Object.keys(version).length).toBe(3);
expect(version['foo_mac32']['size']).toBe(20100);
expect(version['foo_win32']['size']).toBe(20101);
expect(version['foo_linux64']['size']).toBe(20102);
});

it('should return undefined with a max version of "4."', () => {
const version = getVersionObjs(versionList, null, '4.');
expect(version).toBeUndefined();
});
});

describe('getVersionObj', () => {
39 changes: 28 additions & 11 deletions lib/provider/utils/version_list.ts
Original file line number Diff line number Diff line change
@@ -39,12 +39,13 @@ export interface VersionObj {
* @param versionList The version list object.
* @param osMatch The OS name and architecture.
* @param version Optional field for the semver version number or latest.
* * @returns Either a VersionObj or null.
* @param maxVersion Optional field to find the max version matching a value.
* @returns Either a VersionObj or null.
*/
export function getVersion(
versionList: VersionList, osMatch: string, version?: string): VersionObj|
null {
const versionObjs = getVersionObjs(versionList, version);
versionList: VersionList, osMatch: string, version?: string,
maxVersion?: string): VersionObj| null {
const versionObjs = getVersionObjs(versionList, version, maxVersion);
return getVersionObj(versionObjs, osMatch);
}

@@ -55,21 +56,37 @@ export function getVersion(
* @returns The object with paritial urls associated with the binary size.
*/
export function getVersionObjs(
versionList: VersionList, version?: string): {[key: string]: VersionObj} {
versionList: VersionList, version?: string, maxVersion?: string
): {[key: string]: VersionObj} {
if (version && version !== 'latest') {
// Exact matches are easy.
return versionList[version];
} else {
let latestVersion = null;
// Either we want the latest or we want to match with the max version.
let retVersion = null;
for (const versionKey of Object.keys(versionList)) {
if (!latestVersion) {
latestVersion = versionKey;
if (maxVersion) {
// Only find the greatest of the max version.
// An example:
// maxVersion = 0.1 might match 0.13, 0.1, 0.14, result is 0.14.
// if the user wants 0.1., then the maxVersion should be "0.1."
if (versionKey.startsWith(maxVersion)) {
if (!retVersion) {
retVersion = versionKey;
} else if (semver.gt(versionKey, retVersion)) {
retVersion = versionKey;
}
}
} else {
if (semver.gt(versionKey, latestVersion)) {
latestVersion = versionKey;
// Always find the latest.
if (!retVersion) {
retVersion = versionKey;
} else if (semver.gt(versionKey, retVersion)) {
retVersion = versionKey;
}
}
}
return versionList[latestVersion];
return versionList[retVersion];
}
}