diff --git a/lib/cli/index.ts b/lib/cli/index.ts index 0968116d..700ba9ad 100644 --- a/lib/cli/index.ts +++ b/lib/cli/index.ts @@ -121,6 +121,12 @@ const seleniumNodeOption: yargs.Options = { describe: 'Start the selenium server standalone with role set to "node".', type: 'boolean' }; +const SELENIUM_GRID_URL_ALIAS = 'standalone_grid_url'; +const SELENIUM_GRID_URL = 'selenium_grid_url'; +const seleniumGridNodeOption: yargs.Options = { + describe: 'Start the selenium grid with role set to "node".', + type: 'string' +}; const VERSIONS_CHROMEDRIVER_ALIAS = 'versions.chrome'; const VERSIONS_CHROMEDRIVER = 'versions.chromedriver'; const versionsChromedriverOption: yargs.Options = { @@ -186,6 +192,8 @@ yargs .option(SELENIUM_LOG_LEVEL, seleniumLogLevelOption) .option(SELENIUM_NODE, seleniumNodeOption) .alias(SELENIUM_NODE_ALIAS, SELENIUM_NODE) + .option(SELENIUM_GRID_URL, seleniumGridNodeOption) + .alias(SELENIUM_GRID_URL_ALIAS, SELENIUM_GRID_URL) .option(SELENIUM_PORT, seleniumPort) .option(VERSIONS_CHROMEDRIVER, versionsChromedriverOption) .alias(VERSIONS_CHROMEDRIVER_ALIAS, VERSIONS_CHROMEDRIVER) diff --git a/lib/cmds/options.ts b/lib/cmds/options.ts index 2728e321..f7fe4ca2 100644 --- a/lib/cmds/options.ts +++ b/lib/cmds/options.ts @@ -43,6 +43,8 @@ export interface Server { maxVersion?: string; // Run as role = node option. runAsNode?: boolean; + // Run as grid node role = hub registration URL path. + gridUrl?: string; // The relative or full path to the chrome logs file. chromeLogs?: string; // The full path to the edge driver server. diff --git a/lib/cmds/utils.ts b/lib/cmds/utils.ts index a1a880c8..f917b1ef 100644 --- a/lib/cmds/utils.ts +++ b/lib/cmds/utils.ts @@ -42,6 +42,7 @@ export function addOptionsBinary(options: Options): OptionsBinary { seleniumProviderConfig.port = optionsBinary.server.port; seleniumProviderConfig.runAsDetach = optionsBinary.server.runAsDetach; seleniumProviderConfig.runAsNode = optionsBinary.server.runAsNode; + seleniumProviderConfig.gridUrl = optionsBinary.server.gridUrl; seleniumProviderConfig.logLevel = optionsBinary.server.logLevel; optionsBinary.server.binary = new SeleniumServer(seleniumProviderConfig); } @@ -89,10 +90,15 @@ export function convertArgs2Options(argv: yargs.Arguments): Options { if (argv['iedriver'] as boolean) { setVersions('iedriver', argv, options.browserDrivers); } + if (argv['gridUrl'] === true) { + console.log('Please specify a grid hub URL...'); + process.exit(); + } if (argv['selenium']) { options.server = {}; options.server.name = 'selenium'; options.server.runAsNode = argv['selenium_node'] as boolean; + options.server.gridUrl = argv['gridUrl'] as string; options.server.runAsDetach = argv.detach as boolean; options.server.version = argv['versions'] && argv['versions']['selenium'] ? argv['versions']['selenium'] as string : undefined; diff --git a/lib/provider/selenium_server.spec-unit.ts b/lib/provider/selenium_server.spec-unit.ts index 0701216d..18d7edd8 100644 --- a/lib/provider/selenium_server.spec-unit.ts +++ b/lib/provider/selenium_server.spec-unit.ts @@ -38,6 +38,8 @@ describe('selenium_server', () => { const javaArgs = '-role node ' + '-servlet org.openqa.grid.web.servlet.LifecycleServlet ' + '-registerCycle 0 -port 4444'; + const javaGridArgs = '-role node ' + + '-hub '; const javaArgsPort = '-port 4444'; it('should use a selenium server with no options', () => { spyOn(fs, 'readFileSync').and.returnValue(configBinaries); @@ -71,6 +73,20 @@ describe('selenium_server', () => { '-Dwebdriver.chrome.driver=path/to/chromedriver ' + '-jar path/to/selenium-server-3.0.jar ' + javaArgs); }); + + it('should use a selenium server with a grid node option', () => { + spyOn(fs, 'readFileSync').and.returnValue(configBinaries); + const seleniumServer = new SeleniumServer(); + seleniumServer.runAsDetach = true; + seleniumServer.runAsNode = true; + seleniumServer.runAsGrid = true; + const cmd = seleniumServer.getCmdStartServer( + {'-Dwebdriver.chrome.driver': 'path/to/chromedriver'}); + expect(cmd.join(' ')) + .toContain( + '-Dwebdriver.chrome.driver=path/to/chromedriver ' + + '-jar path/to/selenium-server-3.0.jar ' + javaGridArgs); + }); }); describe('getStatus', () => { diff --git a/lib/provider/selenium_server.ts b/lib/provider/selenium_server.ts index e56996cd..85db2595 100644 --- a/lib/provider/selenium_server.ts +++ b/lib/provider/selenium_server.ts @@ -15,7 +15,9 @@ const log = loglevel.getLogger('webdriver-manager'); export interface SeleniumServerProviderConfig extends ProviderConfig { port?: number; + gridUrl?: string; runAsNode?: boolean; + runAsGrid?: boolean; runAsDetach?: boolean; logLevel?: string; } @@ -28,10 +30,12 @@ export class SeleniumServer extends ProviderClass implements ProviderInterface { osArch = os.arch(); outDir = OUT_DIR; port = 4444; + gridUrl = ''; proxy: string = null; requestUrl = 'https://selenium-release.storage.googleapis.com/'; seleniumProcess: childProcess.ChildProcess; runAsNode = false; + runAsGrid = false; runAsDetach = false; logLevel: string = null; javaOpts: {[key: string]: string} = {}; @@ -50,10 +54,14 @@ export class SeleniumServer extends ProviderClass implements ProviderInterface { this.proxy = this.setVar('proxy', this.proxy, config); this.requestUrl = this.setVar('requestUrl', this.requestUrl, config); this.runAsNode = this.setVar('runAsNode', this.runAsNode, config); + this.gridUrl = this.setVar('gridUrl', this.gridUrl, config); this.runAsDetach = this.setVar('runAsDetach', this.runAsDetach, config); if (this.runAsDetach) { this.runAsNode = true; } + if (this.gridUrl !== '') { + this.runAsGrid = 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); @@ -192,7 +200,7 @@ export class SeleniumServer extends ProviderClass implements ProviderInterface { options.push('-jar'); options.push(jarFile); - if (this.runAsNode) { + if (this.runAsNode && !this.runAsGrid) { options.push('-role'); options.push('node'); @@ -202,8 +210,17 @@ export class SeleniumServer extends ProviderClass implements ProviderInterface { options.push('-registerCycle'); options.push('0'); } - options.push('-port'); - options.push(this.port.toString()); + if (this.runAsGrid) { + options.push('-role'); + options.push('node'); + + options.push('-hub'); + options.push(this.gridUrl); + } + if (!this.runAsGrid) { + options.push('-port'); + options.push(this.port.toString()); + } return options; }