Skip to content

Commit 6be659b

Browse files
authored
Passing options to Selenium Manager (#11866)
1 parent e79b2f2 commit 6be659b

File tree

26 files changed

+286
-174
lines changed

26 files changed

+286
-174
lines changed

dotnet/src/webdriver/Chromium/ChromiumDriver.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using System;
2020
using System.Collections.Generic;
2121
using System.Collections.ObjectModel;
22+
using System.IO;
2223
using OpenQA.Selenium.DevTools;
2324
using OpenQA.Selenium.Remote;
2425

@@ -125,7 +126,7 @@ public class ChromiumDriver : WebDriver, ISupportsLogs, IDevTools
125126
/// <param name="options">The <see cref="ChromiumOptions"/> to be used with the ChromiumDriver.</param>
126127
/// <param name="commandTimeout">The maximum amount of time to wait for each command.</param>
127128
protected ChromiumDriver(ChromiumDriverService service, ChromiumOptions options, TimeSpan commandTimeout)
128-
: base(new DriverServiceCommandExecutor(service, commandTimeout), ConvertOptionsToCapabilities(options))
129+
: base(new DriverServiceCommandExecutor(VerifyDriverServicePath(service, options), commandTimeout), ConvertOptionsToCapabilities(options))
129130
{
130131
this.optionsCapabilityName = options.CapabilityName;
131132
}
@@ -431,6 +432,15 @@ protected override void Dispose(bool disposing)
431432
base.Dispose(disposing);
432433
}
433434

435+
private static ChromiumDriverService VerifyDriverServicePath(ChromiumDriverService service, ChromiumOptions options)
436+
{
437+
string driverFullPath = DriverFinder.GetPath(service, options);
438+
service.DriverServicePath = Path.GetDirectoryName(driverFullPath);
439+
service.DriverServiceExecutableName = Path.GetFileName(driverFullPath);
440+
441+
return service;
442+
}
443+
434444
private static ICapabilities ConvertOptionsToCapabilities(ChromiumOptions options)
435445
{
436446
if (options == null)

dotnet/src/webdriver/DriverFinder.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// <copyright file="SeleniumManager.cs" company="WebDriver Committers">
2+
// Licensed to the Software Freedom Conservancy (SFC) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The SFC licenses this file
6+
// to you under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
// </copyright>
18+
19+
using System;
20+
using System.IO;
21+
22+
namespace OpenQA.Selenium
23+
{
24+
/// <summary>
25+
/// Finds a driver, checks if the provided path exists, if not, Selenium Manager is used.
26+
/// This implementation is still in beta, and may change.
27+
/// </summary>
28+
public static class DriverFinder
29+
{
30+
/// <summary>
31+
/// Checks if the driver path exists, else uses Selenium Manager to return it.
32+
/// </summary>
33+
/// <param name="service">DriverService with the current path.</param>
34+
/// <param name="options">DriverOptions with the current browser options.</param>
35+
/// <returns>
36+
/// The path of the driver.
37+
/// </returns>
38+
public static string GetPath(DriverService service, DriverOptions options)
39+
{
40+
string executablePath = Path.Combine(service.DriverServicePath, service.DriverServiceExecutableName);
41+
if (File.Exists(executablePath)) return executablePath;
42+
try
43+
{
44+
return SeleniumManager.DriverPath(options);
45+
}
46+
catch (Exception e)
47+
{
48+
throw new WebDriverException($"Unable to locate driver with path: {executablePath}, for more information on how to install drivers see https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/", e);
49+
}
50+
}
51+
}
52+
}

dotnet/src/webdriver/DriverService.cs

Lines changed: 13 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -58,33 +58,6 @@ public abstract class DriverService : ICommandServer
5858
/// </exception>
5959
protected DriverService(string servicePath, int port, string driverServiceExecutableName, Uri driverServiceDownloadUrl)
6060
{
61-
if (string.IsNullOrEmpty(servicePath))
62-
{
63-
throw new ArgumentException("Path to locate driver executable cannot be null or empty.", nameof(servicePath));
64-
}
65-
66-
string executablePath = Path.Combine(servicePath, driverServiceExecutableName);
67-
if (!File.Exists(executablePath))
68-
{
69-
try
70-
{
71-
executablePath = SeleniumManager.DriverPath(driverServiceExecutableName);
72-
}
73-
catch (Exception e)
74-
{
75-
// No-op; entirely a fall-back feature
76-
}
77-
78-
if (File.Exists(executablePath))
79-
{
80-
servicePath = Path.GetDirectoryName(executablePath);
81-
}
82-
else
83-
{
84-
throw new DriverServiceNotFoundException(string.Format(CultureInfo.InvariantCulture, "The file {0} does not exist. The driver can be downloaded at {1}", executablePath, driverServiceDownloadUrl));
85-
}
86-
}
87-
8861
this.driverServicePath = servicePath;
8962
this.driverServiceExecutableName = driverServiceExecutableName;
9063
this.driverServicePort = port;
@@ -194,11 +167,21 @@ public TimeSpan InitializationTimeout
194167
}
195168

196169
/// <summary>
197-
/// Gets the executable file name of the driver service.
170+
/// Gets or sets the executable file name of the driver service.
198171
/// </summary>
199-
protected string DriverServiceExecutableName
172+
public string DriverServiceExecutableName
200173
{
201174
get { return this.driverServiceExecutableName; }
175+
set { this.driverServiceExecutableName = value; }
176+
}
177+
178+
/// <summary>
179+
/// Gets or sets the path of the driver service.
180+
/// </summary>
181+
public string DriverServicePath
182+
{
183+
get { return this.driverServicePath; }
184+
set { this.driverServicePath = value; }
202185
}
203186

204187
/// <summary>
@@ -312,28 +295,7 @@ public void Start()
312295
/// </exception>
313296
protected static string FindDriverServiceExecutable(string executableName, Uri downloadUrl)
314297
{
315-
string serviceDirectory = FileUtilities.FindFile(executableName);
316-
317-
if (string.IsNullOrEmpty(serviceDirectory))
318-
{
319-
try
320-
{
321-
serviceDirectory = Path.GetDirectoryName(SeleniumManager.DriverPath(executableName));
322-
}
323-
catch (Exception e)
324-
{
325-
// No-op; entirely a fall-back feature
326-
}
327-
328-
if (string.IsNullOrEmpty(serviceDirectory))
329-
{
330-
throw new DriverServiceNotFoundException(string.Format(CultureInfo.InvariantCulture,
331-
"The {0} file does not exist in the current directory or in a directory on the PATH environment variable. The driver can be downloaded at {1}.",
332-
executableName, downloadUrl));
333-
}
334-
}
335-
336-
return serviceDirectory;
298+
return FileUtilities.FindFile(executableName);
337299
}
338300

339301
/// <summary>

dotnet/src/webdriver/Firefox/FirefoxDriver.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ public FirefoxDriver(FirefoxDriverService service, FirefoxOptions options)
186186
/// <param name="options">The <see cref="FirefoxOptions"/> to be used with the Firefox driver.</param>
187187
/// <param name="commandTimeout">The maximum amount of time to wait for each command.</param>
188188
public FirefoxDriver(FirefoxDriverService service, FirefoxOptions options, TimeSpan commandTimeout)
189-
: base(new DriverServiceCommandExecutor(service, commandTimeout), ConvertOptionsToCapabilities(options))
189+
: base(new DriverServiceCommandExecutor(VerifyDriverServicePath(service, options), commandTimeout), ConvertOptionsToCapabilities(options))
190190
{
191191
// Add the custom commands unique to Firefox
192192
this.AddCustomFirefoxCommands();
@@ -439,6 +439,15 @@ private static FirefoxDriverService CreateService(FirefoxOptions options)
439439
return FirefoxDriverService.CreateDefaultService();
440440
}
441441

442+
private static FirefoxDriverService VerifyDriverServicePath(FirefoxDriverService service, FirefoxOptions options)
443+
{
444+
string driverFullPath = DriverFinder.GetPath(service, options);
445+
service.DriverServicePath = Path.GetDirectoryName(driverFullPath);
446+
service.DriverServiceExecutableName = Path.GetFileName(driverFullPath);
447+
448+
return service;
449+
}
450+
442451
private void AddCustomFirefoxCommands()
443452
{
444453
foreach (KeyValuePair<string, CommandInfo> entry in CustomCommandDefinitions)

dotnet/src/webdriver/IE/InternetExplorerDriver.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
// </copyright>
1818

1919
using System;
20-
using System.Collections.Generic;
21-
using OpenQA.Selenium.Internal;
20+
using System.IO;
2221
using OpenQA.Selenium.Remote;
2322

2423
namespace OpenQA.Selenium.IE
@@ -142,7 +141,7 @@ public InternetExplorerDriver(InternetExplorerDriverService service, InternetExp
142141
/// <param name="options">The <see cref="InternetExplorerOptions"/> used to initialize the driver.</param>
143142
/// <param name="commandTimeout">The maximum amount of time to wait for each command.</param>
144143
public InternetExplorerDriver(InternetExplorerDriverService service, InternetExplorerOptions options, TimeSpan commandTimeout)
145-
: base(new DriverServiceCommandExecutor(service, commandTimeout), ConvertOptionsToCapabilities(options))
144+
: base(new DriverServiceCommandExecutor(VerifyDriverServicePath(service, options), commandTimeout), ConvertOptionsToCapabilities(options))
146145
{
147146
}
148147

@@ -162,6 +161,15 @@ public override IFileDetector FileDetector
162161
set { }
163162
}
164163

164+
private static InternetExplorerDriverService VerifyDriverServicePath(InternetExplorerDriverService service, InternetExplorerOptions options)
165+
{
166+
string driverFullPath = DriverFinder.GetPath(service, options);
167+
service.DriverServicePath = Path.GetDirectoryName(driverFullPath);
168+
service.DriverServiceExecutableName = Path.GetFileName(driverFullPath);
169+
170+
return service;
171+
}
172+
165173
private static ICapabilities ConvertOptionsToCapabilities(InternetExplorerOptions options)
166174
{
167175
if (options == null)

dotnet/src/webdriver/SeleniumManager.cs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,6 @@ namespace OpenQA.Selenium
3737
public static class SeleniumManager
3838
{
3939
private static string binary;
40-
private static readonly List<string> KnownDrivers = new List<string>() {
41-
"geckodriver",
42-
"chromedriver",
43-
"msedgedriver",
44-
"IEDriverServer"
45-
};
4640

4741
/// <summary>
4842
/// Determines the location of the correct driver.
@@ -51,17 +45,12 @@ public static class SeleniumManager
5145
/// <returns>
5246
/// The location of the driver.
5347
/// </returns>
54-
public static string DriverPath(string driverName)
48+
public static string DriverPath(DriverOptions options)
5549
{
56-
driverName = driverName.Replace(".exe", "");
57-
if (!KnownDrivers.Contains(driverName))
58-
{
59-
throw new WebDriverException("Unable to locate driver with name: " + driverName);
60-
}
6150
var binaryFile = Binary;
6251
if (binaryFile == null) return null;
6352

64-
var arguments = "--driver " + driverName + " --output json";
53+
var arguments = "--browser " + options.BrowserName + " --output json";
6554
return RunCommand(binaryFile, arguments);
6655
}
6756

@@ -143,7 +132,7 @@ private static string RunCommand(string fileName, string arguments)
143132
}
144133

145134
string output = outputBuilder.ToString().Trim();
146-
string result = "";
135+
string result;
147136
try
148137
{
149138
Dictionary<string, object> deserializedOutput = JsonConvert.DeserializeObject<Dictionary<string, object>>(output, new ResponseValueJsonConverter());

javascript/node/selenium-webdriver/chrome.js

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@
130130
const io = require('./io')
131131
const { Browser } = require('./lib/capabilities')
132132
const chromium = require('./chromium')
133-
const { driverLocation } = require('./common/seleniumManager')
134133

135134
/**
136135
* Name of the ChromeDriver executable.
@@ -158,23 +157,6 @@ class ServiceBuilder extends chromium.ServiceBuilder {
158157
*/
159158
constructor(opt_exe) {
160159
let exe = opt_exe || locateSynchronously()
161-
162-
if (!exe) {
163-
try {
164-
exe = driverLocation(Browser.CHROME)
165-
} catch (err) {
166-
console.log(`Unable to obtain driver using Selenium Manager: ${err}`)
167-
}
168-
}
169-
170-
if (!exe) {
171-
throw Error(
172-
`ChromeDriver could not be found on the PATH.
173-
For more information on how to install drivers see
174-
https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/.`
175-
)
176-
}
177-
178160
super(exe)
179161
}
180162
}

javascript/node/selenium-webdriver/chromium.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ const error = require('./lib/error')
8383
const Symbols = require('./lib/symbols')
8484
const webdriver = require('./lib/webdriver')
8585
const remote = require('./remote')
86+
const { getPath } = require('./common/driverFinder')
8687

8788
/**
8889
* Custom command names supported by Chromium WebDriver.
@@ -684,6 +685,9 @@ class Driver extends webdriver.WebDriver {
684685
configureExecutor(executor, this.VENDOR_COMMAND_PREFIX)
685686
} else {
686687
let service = opt_serviceExecutor || this.getDefaultService()
688+
if (!service.getExecutable()) {
689+
service.setExecutable(getPath(service, caps))
690+
}
687691
onQuit = () => service.kill()
688692
executor = createExecutor(service.start(), this.VENDOR_COMMAND_PREFIX)
689693
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
/**
19+
* This implementation is still in beta, and may change.
20+
*
21+
* Utility to find if a given file is present and executable.
22+
*/
23+
24+
const { driverLocation } = require('./seleniumManager')
25+
const fs = require('fs')
26+
27+
/**
28+
* Determines the path of the correct Selenium Manager binary
29+
* @returns {string}
30+
*/
31+
function getPath(service, capabilities) {
32+
try {
33+
return pathExists(service.getExecutable()) ||
34+
driverLocation(capabilities.getBrowserName())
35+
} catch (e) {
36+
throw Error(
37+
`Unable to obtain browser driver.
38+
For more information on how to install drivers see
39+
https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/. ${e}`
40+
)
41+
}
42+
}
43+
44+
/**
45+
* _Synchronously_ attempts to locate the driver executable on the current
46+
* system.
47+
*
48+
* @param {!string} driverPath
49+
*
50+
* @return {?string} the located executable, or `null`.
51+
*/
52+
function pathExists(driverPath) {
53+
if (!driverPath || !fs.existsSync(driverPath)) {
54+
return null
55+
}
56+
return driverPath
57+
}
58+
59+
// PUBLIC API
60+
module.exports = { getPath }

javascript/node/selenium-webdriver/common/seleniumManager.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const execSync = require('child_process').execSync
3030
* currently supported browsers for selenium-manager
3131
* @type {string[]}
3232
*/
33-
const Browser = ['chrome', 'firefox', 'edge', 'iexplorer']
33+
const Browser = ['chrome', 'firefox', 'edge', 'MicrosoftEdge', 'iexplorer']
3434

3535
/**
3636
* Determines the path of the correct Selenium Manager binary

0 commit comments

Comments
 (0)