12

I have two simple tests that are using RemoteWebDriver with ChromeOptions and EdgeOptions. Both these tests are using common code to set capabilities, including the browserstack.user and browserstack.key capabilities.

Because I am using DriverOptions (instead of DesiredCapabilities) I have used AddAdditionalCapability(...) to add these capabilities to the Driver.

The Edge test is working but the Chrome test is failing before the test even starts with;

OpenQA.Selenium.WebDriverException: Unexpected error. Authorization required

These tests were previously working with DesiredCapabalities before I upgraded my Selenium Driver to v3.14 (where DesiredCapabalities have been depracated).


Update

I have downgraded to Selenium.WebDriver v3.4.

An example of the code that is passing (EdgeOptions) and failing (with ChromeOptions):

[TestClass]
public class Simple_GridTest_Chrome
{
    private static IWebDriver driver;

    private string _bsUsername = "<username>";
    private string _bsAccessKey = "<myaccesskey>";

    private string _bsProjectName = "TestProject";
    private string _bsBuildName = "Build-0.0.1";

    private void SetOptions(bool useEdge = false)
    {
        DriverOptions options;

        if (useEdge)
        {
            options = new EdgeOptions(); // this works OK
        } else
        {
            options = new ChromeOptions(); // this fails with OpenQA.Selenium.WebDriverException: Unexpected error. Authorization required
        }

        // the account that is running the test
        options.AddAdditionalCapability("browserstack.user", _bsUsername);
        options.AddAdditionalCapability("browserstack.key", _bsAccessKey);

        options.AddAdditionalCapability("project", _bsProjectName);
        options.AddAdditionalCapability("build", _bsBuildName);

        // gather additional data during the test run (screen shots etc)
        options.AddAdditionalCapability("browserstack.debug", "true");

        driver = new RemoteWebDriver(
          new Uri("https://hub-cloud.browserstack.com/wd/hub/"), options
        );

        //driver = new RemoteWebDriver(
        //  new Uri($"https://{_bsUsername}:{_bsAccessKey}@hub-cloud.browserstack.com/wd/hub/"), options
        //);
    }

    [ClassInitialize()]
    public static void MyClassInitialise(TestContext context)
    {
    }

    [TestMethod]
    [TestCategory("grid.BrowserStack.Google")]
    public void NavigateToGoogle_Windows7_Chrome()
    {
        SetOptions(false); // use Chrome
        GoogleTest(driver);
    }

    [TestMethod]
    [TestCategory("grid.BrowserStack.Google")]
    public void NavigateToGoogle_Windows10_Edge()
    {
        SetOptions(true); // use Edge
        GoogleTest(driver);
    }

    private void GoogleTest(IWebDriver driver)
    {
        driver.Navigate().GoToUrl("https://www.google.com/?q=test");
        Console.WriteLine(driver.Title);

        driver.WaitForWebElement(By.XPath("//*[@name=\"btnK\"]")).Click();
        Console.WriteLine(driver.Title);
    }
}

I have the following packages installed:

<packages>
  <package id="Selenium.Firefox.WebDriver" version="0.21.0" targetFramework="net45" />
  <package id="Selenium.Support" version="3.4.0" targetFramework="net45" />
  <package id="Selenium.WebDriver" version="3.4.0" targetFramework="net45" />
  <package id="Selenium.WebDriver.ChromeDriver" version="2.41.0" targetFramework="net45" />
  <package id="Selenium.WebDriver.IEDriver" version="3.14.0" targetFramework="net45" />
</packages>
Ohad Schneider
  • 33,142
  • 10
  • 150
  • 190
Mark Cooper
  • 6,214
  • 5
  • 51
  • 85

6 Answers6

5

This seems an issue specific to how the selenium language bindings generate payload and how browserstack parses it at their end.

Based on the error message you shared, it is quite likely that while parsing the request payload, browserstack is not able to find your username and access key

You may follow the steps mentioned below to debug this:

  • Change the line driver = new RemoteWebDriver(new Uri("https://hub-cloud.browserstack.com/wd/hub/"), options); to driver = new RemoteWebDriver( new Uri("http://localhost:4444/wd/hub/"), options );. You are not required to start selenium-standalone jar locally.

  • Start a proxy that reads traffic on localhost:4444. (You may use a node based implementation for the same if needed. Here is one such implementation: https://gist.github.com/hanikhan/f817bd64b063129cb78dc7ed0b66fdb7)

  • Observe the request payload generated by the selenium client bindings you are using(v3.14 as you mentioned). For example, my java based selenium client generates this when only browser is passed is desiredcapabitlies {"desiredCapabilities":{"browserName":"Chrome"},"capabilities":{"firstMatch":[{"browserName":"Chrome"}]}}

  • Now downgrade your selenium bindings(to a version where it was working) and observe the payload it generates.

Check if the client bindings use strict checks due to which some required capabilities are getting discarded at your end.

If this is true then you will be required to do one of the following:

  • Raise an issue with selenium C# bindings to remove strict checks for your case
  • Contact Browserstack and ask them to provide a capability that passes the strict check
BountyHunter
  • 1,325
  • 15
  • 30
4

You can pass the capabilities as below for both Edge and Chrome using EdgeOptions and ChromeOptions to initiate session on BrowserStack. This is in Java. Port your test accordingly for other languages.

For Edge

EdgeOptions options = new EdgeOptions();

 options.setCapability("browserstack.user","<userName>");
 options.setCapability("browserstack.key","<accessKey>");
 options.setCapability("os_version", "10"); //desired os_version
 options.setCapability("browser", "chrome"); //desired browser

 driver = new RemoteWebDriver(new URL("https://hub-cloud.browserstack.com/wd/hub"), options);

For Chrome

 ChromeOptions options = new ChromeOptions();

    options.setCapability("browserstack.user","<userName>");
    options.setCapability("browserstack.key","<accessKey>");
    options.setCapability("os_version", "10");
    options.setCapability("browser", "chrome");

    driver = new RemoteWebDriver(new URL("https://hub-cloud.browserstack.com/wd/hub"), options);
Kireeti Annamaraj
  • 1,007
  • 1
  • 7
  • 12
  • Thanks. I've already done this. In c# there isn't a `setCapability()` method, instead I use `AddAdditionalCapability()`. My test is working in Edge, but not Chrome, so I know the capabilities must be getting added correctly. – Mark Cooper Sep 06 '18 at 19:13
  • Is it possible for you to share the code snippet you are using for chrome which is working fine for Edge browser. – Kireeti Annamaraj Sep 06 '18 at 20:28
  • 2
    Yes, I could reproduce the same error. There seems to be an issue with ChromeOptions class. I will try to debug this further. However, since you are getting the Authorization error, could you try the below way: var capability = new ChromeOptions(); driver = new RemoteWebDriver( new Uri("http://:@hub-cloud.browserstack.com/wd/hub/"), capability ); – Kireeti Annamaraj Sep 06 '18 at 22:02
  • I have added an example of the code that is failing in c# – Mark Cooper Sep 07 '18 at 13:41
4

I ran into this same issue and resolved it by setting the "isGlobalCapability" to true on every "AddAdditionalCapability" method for ChromeOptions (using Selenium 3.14). If just one of them doesn't have it set, the test fails.

chromeOptions.AddAdditionalCapability("browserstack.user", <user>, true);
chromeOptions.AddAdditionalCapability("browserstack.key", <key>, true);
chromeOptions.AddAdditionalCapability("browser", "chrome", true);
chromeOptions.AddAdditionalCapability("os", "Windows", true);
chromeOptions.AddAdditionalCapability("os_version", "10", true);
_Driver = new RemoteWebDriver(new Uri("http://hub-cloud.browserstack.com/wd/hub/"), chromeOptions);
DJSDev
  • 193
  • 1
  • 12
3

Did you try to add options as options.ToCapabilities()?

driver = new RemoteWebDriver(
    new Uri("https://hub-cloud.browserstack.com/wd/hub/"), options.ToCapabilities()
);

Also try to set as global capability:

options.AddAdditionalCapability("browserstack.user", _bsUsername, true);
Sers
  • 10,960
  • 2
  • 8
  • 25
  • 1
    Yup, I have already tried using `options.ToCapabilities()` and that didn't help. There aren't any overloads for `AddAdditionalCapability` that accept a third parameter. I am using v3.4. – Mark Cooper Sep 10 '18 at 14:10
3

The issue is that AddAdditionalCapability(string capabilityName, object capabilityValue) does not set the capabilities globally when called on ChromeOptions, FirefoxOptions, and InternetExplorerOptions. Rather, it puts them inside the specific browser options in the JSON. For more information see https://github.com/SeleniumHQ/selenium/issues/6563.

As you have noticed, EdgeOption does set them globally which is why that was working for you (SafariOptions would have worked the same BTW).

Now, the reason you don't see the AddAdditionalCapability(string capabilityName, object capabilityValue, bool isGlobalCapability) overload is that your options variable is of type DriverOptions, which does not contain this overload. As a workaround, you could to do something like this:

static void AddGlobalCapability(this DriverOptions options, string name, object value)
{
    switch (options)
    {
        case ChromeOptions chromeOptions:
            chromeOptions.AddAdditionalCapability(name, value, true);
            break;
        case FirefoxOptions firefoxOptions:
            firefoxOptions.AddAdditionalCapability(name, value, true);
            break;
        case InternetExplorerOptions internetExplorerOptions:
            internetExplorerOptions.AddAdditionalCapability(name, value, true);
            break;
        default:
            options.AddAdditionalCapability(name, value);
            break;
    }
}
Ohad Schneider
  • 33,142
  • 10
  • 150
  • 190
-1

We had this same issue. We were trying to use the credentials in our URL, as we do in our Java project.

var browserstackUrl = string.Format(
    "https://{0}:{1}@hub-cloud.browserstack.com/wd/hub", 
    browserstackUsername, 
    browserstackAccessKey
);
var webdriver = new RemoteWebDriver(new Uri(BrowserStackUrl), options);

By moving them to capabilities, we were able to get past this issue:

capabilities.SetCapability("browserstack.user", browserstackUsername);
capabilities.SetCapability("browserstack.key", browserstackAccessKey);
var browserstackUrl = "https://hub-cloud.browserstack.com/wd/hub";
var webdriver = new RemoteWebDriver(new Uri(BrowserStackUrl), options);
Thunderforge
  • 17,419
  • 14
  • 73
  • 117