I just updated selenium in a base framework i use to create browsers and plug in application POM sets.
I'm getting the warning that DesiredCapabilities is obsolete and I should use browser specific options instead.
Below is a cut down version of my code where I pull data from the app settings (set by build server not tests) to specify which browser, configuration and in what environment to run.
How would I go about using specific browser options as with this setup I can cast to a desired capabilities and add settings where they are available whereas the only way i see with browser specific options is to do similar but for each browser type which im not keen on doing.
Is there a better way I could do this, what is the recommended approach in this scenario?
`
/// <summary>
/// Creates a new automation instance.
/// </summary>
/// <param name="driverConfig">The configuration settings for the browser driver.</param>
public Driver(DriverConfig driverConfig)
{
DriverConfig = driverConfig;
ICapabilities caps = new DesiredCapabilities();
//generic Desktop Browser config:
if (DriverConfig.BrowserName != "")
{ ((DesiredCapabilities)caps).SetCapability("browserName", DriverConfig.BrowserName); }
else
{ }
if (DriverConfig.Version != "")
{ ((DesiredCapabilities)caps).SetCapability("version", DriverConfig.Version); }
else
{ }
if (DriverConfig.Platform != "")
{ ((DesiredCapabilities)caps).SetCapability("platform", DriverConfig.Platform); }
else
{ }
//Create browser on remote machine
Instance = new RemoteWebDriver(new Uri(DriverConfig.BrowserExecutionAddress), caps);
// Maximise the window for consistency
Instance.Manage().Window.Maximize();
// Go to the start URL
Instance.Navigate().GoToUrl(DriverConfig.BrowserStartURL);
}`
My run settings are picked up from the app settings which are specified by the build server to test only the desired browsers, below is a small snippet.
`
/// <summary>
/// From the application setting "browser". Name of the desired browser to be automated.
/// </summary>
public string Browser => ConfigurationManager.AppSettings["browser"];
/// <summary>
/// From the application setting "version". Version of the desired browser.
/// </summary>
public string Version => ConfigurationManager.AppSettings["version"];
/// <summary>
/// From the application setting "platform". Platform on which to run i.e. Windows 10.
/// </summary>
public string Platform => ConfigurationManager.AppSettings["platform"];
`
There are challenges with allowing generic “property bag” settings that do not check for type-safety and valid capability names. This is particularly so for remote ends that implement the W3C WebDriver Specification, which has strict rules as to what is acceptable as values for capabilities. As a concrete example taken directly from your own code, passing a capabilities object with a property name of “version” or “platform,” it would be perfectly legal for the remote end to reject the new session request, since those are not valid capability names. And every remote end implementation that implements the spec and directly drives a desktop browser either already implements the spec by default or soon will.
A fairly simple solution to this would be to use a factory pattern to generate a DriverOptions object based on browser name. You can manipulate common options via that base class. You must realize, however, that browser-specific options won’t be settable via the base class, nor should they be.
This is a question, more than an issue, because there is no actionable item here. I’ll leave it open for now, but we should get used to the idea that DesiredCapabilities is being phased out of the .NET bindings, a trend which has been in place for years.
Thanks @jimevans thats really helpful 👍
Now that it's Depricated do we know how long we have before it gets removed?
Any guidance on how frameworks that leverage Selenium, such as Appium, should handle this long term?
Concerns
This change breaks the .Net version of Appium
https://github.com/appium/appium-dotnet-driver/issues/256
DriverOptions do not seem to be compatible with SauceLabs
Example of what does not work:
public void OpenBrowser()
{
DriverOptions options = new ChromeOptions();
options.AddAdditionalCapability("username", "Partner_ZZZZ");
options.AddAdditionalCapability("accessKey", "ZZZZ");
this.WebDriver = new RemoteWebDriver(new Uri("http://ondemand.saucelabs.com:80/wd/hub"), options.ToCapabilities(), TimeSpan.FromSeconds(600));
this.WebDriver.Navigate().GoToUrl(TestSiteUrl);
}
_Throws a OpenQA.Selenium.WebDriverException: Unexpected error. Misconfigured error_
Example of what works:
public void OpenBrowser()
{
DesiredCapabilities caps = new DesiredCapabilities();
caps.SetCapability(CapabilityType.BrowserName, "chrome");
caps.SetCapability("username", "Partner_ZZZZ");
caps.SetCapability("accessKey", "ZZZZ");
this.WebDriver = new RemoteWebDriver(new Uri("http://ondemand.saucelabs.com:80/wd/hub"), caps, TimeSpan.FromSeconds(600));
this.WebDriver.Navigate().GoToUrl(TestSiteUrl);
}
@TroyWalshProf The following should work just fine (note the third argument in the calls to AddAdditionalCapability):
public void OpenBrowser()
{
ChromeOptions options = new ChromeOptions();
options.AddAdditionalCapability("username", "Partner_ZZZZ", true);
options.AddAdditionalCapability("accessKey", "ZZZZ", true);
this.WebDriver = new RemoteWebDriver(new Uri("http://ondemand.saucelabs.com:80/wd/hub"), options.ToCapabilities(), TimeSpan.FromSeconds(600));
this.WebDriver.Navigate().GoToUrl(TestSiteUrl);
}
This still leaves the question of how things like Appium should deal with this change.
Would it be better to create a AppiumOptions class off of DriverOptions or just create AppiumCapablilities off the ICapabilities interface or something else I haven't thought of?
@TroyWalshProf What the Appium (or other downstream projects) do to accommodate this change is not up to me. If I were doing it, I'd probably opt to create descendants of DriverOptions (like AndroidOptions, IOSOptions, and WinAppOptions), but that's just my opinion.
@jimevans I want to pass a browser parameter at runtime say from jenkins builds. Hence I am looking for code that can initialize all different types of browser capabilities. I tried following code:
DriverOptions options = null;
var browser = _jsonList["browser"].ToString();
if (browser.Equals("Chrome"))
{
options = new ChromeOptions();
}
else if (browser.Equals("Firefox"))
{
options = new FirefoxOptions();
}
//Common capabilities
options.AddAdditionalCapability("username", _jsonList["username"].ToString(), true);
options.AddAdditionalCapability("accessKey", _jsonList["accessKey"].ToString(), true);
options.AddAdditionalCapability("name", testName, true);
options.AddAdditionalCapability(CapabilityType.Version, _jsonList["version"].ToString(), true);
options.AddAdditionalCapability(CapabilityType.Platform, _jsonList["os"].ToString(), true);
options.AddAdditionalCapability("screenResolution", _jsonList["screenResolution"].ToString(), true);
However I get error, No overload method for AddAdditionalCapability takes 3 arguments.
This is because DriverOptions do not have a method AddAdditionalCapability that can take 3 arguments.
Can you guys add a method that can take 3 arguments to DriverOptions class, so that it can be used to instantiate and type of browseroptions classes ?
Note: It works fine with Safari browser in following example
DriverOptions options = new SafariOptions();
options.AddAdditionalCapability("username", _jsonList["username"].ToString());
options.AddAdditionalCapability("accessKey", _jsonList["accessKey"].ToString());
options.AddAdditionalCapability("name", testName);
options.PlatformName = "iOS";
options.AddAdditionalCapability("appiumVersion", "1.8.1");
@jimevans See the following for the issue with the code you have suggested: https://github.com/SeleniumHQ/selenium/issues/6563
After installing 4.0.0.4 beta and updating the code to launch classic desktop application:
appiumOptions.AddAdditionalCapability("app", @ExecutablePath);
appiumOptions.AddAdditionalCapability("platformName", "Windows");
appiumOptions.AddAdditionalCapability("deviceName", "WindowsPC");
session = new WindowsDriver(new Uri(WindowsApplicationDriverUrl), appiumOptions, TimeSpan.FromSeconds(1.5));
An exception is thrown, trace states: Could not parce w3c capabilities: 'deviceName' cann't be blank. Falling back to JSONWP protocal.
Test case fails since the execption is thrown but my application is launched. Any idea?
I am going to close this issue in favor of #6563, which has information about the API changes that will be made to the .NET bindings API for the 4.0 release. I will not be replying with further comments on this issue. Please be mindful of your further comments here, as I'd prefer not to lock the issue, and prevent any further discussion.
Most helpful comment
@TroyWalshProf The following should work just fine (note the third argument in the calls to
AddAdditionalCapability):}