0

I know that some selenium capabilities can be obtained with a method, one of them like this :

driver.getCapabilities().getBrowserName();

It returns the value of the browser name.

But if it refers to an available method, if I don't misunderstand it, this seems to be related to custom capabilities, like this I mean :

driver.getCapabilities().getCapability("something ?");

Returns: The value, or null if not set.

get capabilities

So, I've tried to make a simple code to get the value I mean.

    private RemoteWebDriver driver;
    private URL url;
    private DesiredCapabilities dc = new DesiredCapabilities();

    @Before
    public void setUp() throws MalformedURLException {
        url = new URL("http://localhost:4444/wd/hub");
        dc.setCapability(CapabilityType.BROWSER_NAME, BrowserType.CHROME);
        //this is custom capability i mean
        dc.setCapability("testName", "Login");
        driver = new RemoteWebDriver(url, dc);
    }
    
    @Test
    public void test() {
        some code.....
    }
    
    @After
    public void tearDown() {
        System.out.println("Browser Name : "+ driver.getCapabilities().getCapability("browserName"));
        System.out.println("Test Name : "+ driver.getCapabilities().getCapability("testName"));
        driver.quit();
    }

With json, server log say :

Capabilities are: {
  "browserName": "chrome",
  "testName": "Login"
}

server log

But i get a null value.

How to the right setup ? How do you make our server provide the capabilities testName I mean? and can be obtained with driver.getCapabilities().getCapability("testName");

Current result Browser Name : chrome Test Name : null

Expected result Browser Name : chrome Test Name : Login

Thanks advance

Community
  • 1
  • 1
frianH
  • 5,901
  • 6
  • 13
  • 36
  • https://www.w3.org/TR/webdriver1/#capabilities this may help understanding the capabilities . Remote end will not return values if its not supported. – Rahul L Aug 05 '19 at 06:19
  • @RahulL yes correct, if i use `.getCapability("browserName")` `platformName` etc, it will return a value, but it still the default available in selenium. I've used a paid testing platform (platform based on selenium and appium) and for the purposes of the report name I can only setup by adding the `dc.setCapability("testName"," Login ")` method, and I can get the value of `testName` using the method `.getCapability ("testName")`, even I can also get the value of the report url using the `.getCapability ("urlReport")` method. So I assume that the name of the capability can be custom as needed. – frianH Aug 05 '19 at 07:43
  • But in the fact it's not simple as my imagine – frianH Aug 05 '19 at 07:46
  • Sauce lab or Browser stack have their own implementations of remote servers. They don't use selenium remote server as it is . So there server recognize capabilities defined by them. Example https://github.com/aerokube/selenoid implemented in go language – Rahul L Aug 05 '19 at 07:49
  • So, you mean, the capabilities that I mean are made separate from the Selenium framework ? – frianH Aug 05 '19 at 08:05
  • 1
    Answer is Yes.As per W3C protocol -'Remote ends may also introduce extension capabilities that are extra capabilities used to provide configuration or fulfill other vendor-specific needs' Capability dc.setCapability("testName", "Login") It will be sent in Json but it will be ignored by remote server .When you request it back it will not send anything. – Rahul L Aug 05 '19 at 14:52
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/197515/discussion-between-frian-and-rahul-l). – frianH Aug 05 '19 at 16:59

2 Answers2

1

You can extract the WebDriver Capabilities e.g. Browser Name, Browser Version, Platform Name, etc using either of the following solutions:

  • Using direct APIs:

    • Code Block:

      System.out.println("Class Name is : "+((RemoteWebDriver) driver).getCapabilities().getClass().toString());
      System.out.println("Browser Name is : "+((RemoteWebDriver) driver).getCapabilities().getBrowserName().toLowerCase());
      System.out.println("Browser Version is : "+((RemoteWebDriver) driver).getCapabilities().getVersion().toString());
      System.out.println("Platform Name is : "+((RemoteWebDriver) driver).getCapabilities().getPlatform().toString());
      
    • Console Output:

      Class Name is : class org.openqa.selenium.MutableCapabilities
      Browser Name is : firefox
      Browser Version is : 67.0
      Platform Name is : WINDOWS
      
  • Using getCapability():

    • Code Block:

      Capabilities cap = ((RemoteWebDriver) driver).getCapabilities();
      System.out.println("acceptInsecureCerts value is: "+cap.getCapability("acceptInsecureCerts"));
      System.out.println("Browser Name is : "+cap.getBrowserName());
      System.out.println("Browser version is : "+cap.getVersion());           
      System.out.println("Platform is : "+cap.getPlatform().toString());
      System.out.println("javascriptEnabled value is: "+cap.getCapability("javascriptEnabled"));
      System.out.println("moz:accessibilityChecks value is: "+cap.getCapability("moz:accessibilityChecks"));
      System.out.println("moz:buildID value is: "+cap.getCapability("moz:buildID"));
      System.out.println("geckodriverVersion value is: "+cap.getCapability("geckodriverVersion"));
      System.out.println("Headless Mozilla value is: "+((RemoteWebDriver) driver).getCapabilities().getCapability("moz:headless"));
      System.out.println("moz:headless value is: "+cap.getCapability("moz:headless"));
      System.out.println("Mozilla Profile value is : "+ ((RemoteWebDriver) driver).getCapabilities().getCapability("moz:profile"));
      System.out.println("moz:processID value is : "+cap.getCapability("moz:processID"));
      System.out.println("moz:profile value is : "+cap.getCapability("moz:profile"));
      System.out.println("moz:shutdownTimeout value is : "+cap.getCapability("moz:shutdownTimeout"));
      System.out.println("moz:useNonSpecCompliantPointerOrigin value is : "+cap.getCapability("moz:useNonSpecCompliantPointerOrigin"));
      System.out.println("moz:webdriverClick value is : "+cap.getCapability("moz:webdriverClick"));
      System.out.println("pageLoadStrategy value is : "+cap.getCapability("pageLoadStrategy"));
      System.out.println("Platform is : "+cap.getPlatform().toString());
      System.out.println("platformName value is : "+cap.getCapability("platformName"));
      System.out.println("platformVersion value is : "+cap.getCapability("platformVersion"));
      System.out.println("rotatable value is : "+cap.getCapability("rotatable"));
      System.out.println("setWindowRect value is : "+cap.getCapability("setWindowRect"));
      System.out.println("strictFileInteractability value is : "+cap.getCapability("strictFileInteractability"));
      System.out.println("timeouts values are : "+cap.getCapability("timeouts"));
      System.out.println("unhandledPromptBehavior value is : "+cap.getCapability("unhandledPromptBehavior"));
      
    • Console Output:

      acceptInsecureCerts value is: true
      Browser Name is : firefox
      Browser version is : 67.0
      Platform is : WINDOWS
      javascriptEnabled value is: true
      moz:accessibilityChecks value is: false
      moz:buildID value is: 20190516215225
      geckodriverVersion value is: null
      Headless Mozilla value is: false
      moz:headless value is: false
      Mozilla Profile value is : C:\Users\Debanjan.B\AppData\Local\Temp\rust_mozprofile.7HI7QUtzF1YP
      moz:processID value is : 7308
      moz:profile value is : C:\Users\Debanjan.B\AppData\Local\Temp\rust_mozprofile.7HI7QUtzF1YP
      moz:shutdownTimeout value is : 60000
      moz:useNonSpecCompliantPointerOrigin value is : false
      moz:webdriverClick value is : true
      pageLoadStrategy value is : normal
      Platform is : WINDOWS
      platformName value is : WINDOWS
      platformVersion value is : 6.2
      rotatable value is : false
      setWindowRect value is : true
      strictFileInteractability value is : false
      timeouts values are : {implicit=0, pageLoad=300000, script=30000}
      unhandledPromptBehavior value is : dismiss and notify
      

You can find the list of the supported capabilities in the Capabilities section within the WebDriver W3C Recommendation

DebanjanB
  • 118,661
  • 30
  • 168
  • 217
1

It sounds like what you're looking for is how to add a custom capability to your Grid configuration. This is possible, but requires several steps.

First, you need to build a capability matcher. The matcher will be its own project, importing the Selenium-Server and Selenium-Java libraries as dependencies. You'll need a single class that extends org.openqa.grid.internal.utils.DefaultCapabilityMatcher, and overrides the matches() method with your own logic to determine whether or not a node possesses the desired capability. When complete, you'll build this project and generate a jar file.

Second, you'll need to attach your new matcher to your Grid Hub. I store my matcher jars in the same directory as my selenium-server-standalone jar, and I alter my normal launch command to accommodate the matcher.

java -cp <custom-matcher>-1.0.0.jar;selenium-server-standalone-3.141.59.jar org.openqa.grid.selenium.GridLauncher -role hub -hubConfig hubConfig.json

In my hubConfig.json, I had to add two lines to the JSON to wire in the matcher:

  "capabilityMatcher": "fully.qualified.path.to.Matcher",
  "throwOnCapabilityNotPresent": true,

Third, you'll need to configure your nodes to accept the new capability. If you're using JSON to also configure your nodes, it's just as simple as adding a new line for your capability:

"capabilityName": "foo"

That's pretty much it. It's also worth noting that DesiredCapabilities does have a capability called applicationName, which is left as a user-definable value. Depending on your specific use case, you might be able to leverage this capability in place of adding something new.

I found a sample repo on Github a while back when I was learning this process myself. It's a basic setup, but it illustrates the steps above pretty well. It should give you a great starting point for your own implementation.

tim-slifer
  • 1,028
  • 1
  • 9
  • 17
  • Let me check, i'll back to you. – frianH Aug 09 '19 at 16:06
  • sorry for late response, thank before for the suggest. I've complete the steps like your suggest, long enough in the first step :), but can you correct my job ? wrong or true with your review. Hub and node fine work, indicate by `10:29:44.122 INFO [SelfRegisteringRemote.registerToHub] - The node is registered to the hub and ready to use`. – frianH Aug 15 '19 at 03:39
  • This is the value `custom-capability.jar` : `public class CustomCapability extends DefaultCapabilityMatcher { private final String testName = "testName"; boolean allCapabilitiesAvailability = false;` – frianH Aug 15 '19 at 03:42
  • `@Override public boolean matches(Map nodeCapability, Map requestedCapability){ boolean defaultCapabilitiesAvailability = super.matches(nodeCapability, requestedCapability); if (! requestedCapability.containsKey(testName)){ return defaultCapabilitiesAvailability; }else { boolean nodeOSAvailability = nodeCapability.get(testName).equals(requestedCapability.get(testName)); allCapabilitiesAvailability = (defaultCapabilitiesAvailability && nodeOSAvailability); return allCapabilitiesAvailability; } } }` – frianH Aug 15 '19 at 03:42
  • This is the value `hubConfig.json` : `{ "port": 4444, "newSessionWaitTimeout": -1, "servlets" : [], "withoutServlets": [], "custom": {}, "capabilityMatcher": "com.matcher.CustomCapability", "throwOnCapabilityNotPresent": true, "cleanUpCycle": 5000, "role": "hub", "debug": false, "browserTimeout": 0, "timeout": 1800 }` – frianH Aug 15 '19 at 03:44
  • So execute the hub with this command : `java -cp custom-capability.jar:selenium-server-standalone-3.141.59.jar org.openqa.grid.selenium.GridLauncherV3 -role hub -hubConfig hubConfig.json` – frianH Aug 15 '19 at 03:46
  • This is the value `nodeConfig.json` : `{ "capabilities": [ { "browserName": "firefox", "maxInstances": 5, "seleniumProtocol": "WebDriver", "testName": "untitled" }, { "browserName": "chrome", "maxInstances": 5, "seleniumProtocol": "WebDriver", "testName": "untitled" } ], "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy", "maxSession": 5, "port": 5555, "register": true, "registerCycle": 5000, "hub": "http://localhost:4444"` – frianH Aug 15 '19 at 03:48
  • So execute the node with this command : `java -Dwebdriver.chrome.driver=chromedriver -Dwebdriver.gecko.driver=geckodriver -cp custom-capability.jar:selenium-server-standalone-3.141.59.jar org.openqa.grid.selenium.GridLauncherV3 -role node -nodeConfig nodeConfig.json` – frianH Aug 15 '19 at 03:48
  • My question is, the test script code like this question i've tried set `dc.setCapability("testName", "untitled");` it's fine work, but if i use this command : `driver.getCapabilities().getCapability("testName")` it's return `null`. Then i've tried set `dc.setCapability("testName", "login");`, it's getting error like this : `org.openqa.selenium.WebDriverException: Error forwarding the new session cannot find : Capabilities {browserName: chrome, testName: login}` – frianH Aug 15 '19 at 03:55
  • Did the results of your suggestion really produce this ? if not, then where is my mistake ? Because the point of my question is how `testName` can be made like a parameter, it can be filled with any `string` value, and I can get the `testName` value with this : `driver.getCapabilities().getCapability("testName")`, thanks and please help me again for review :) – frianH Aug 15 '19 at 04:05
  • Just at a quick glance, I think the launch command for your nodes might need to be changed. I'd start by dropping the `-Dwebdriver` args. There is also, apparently, a known issue right now with capability matchers, but workarounds exist. Please see [this](https://github.com/seleniumhq/selenium/issues/3268#issuecomment-451397251) over at Github. – tim-slifer Aug 19 '19 at 13:32
  • I will visit the link and investigate, btw with the correct result, is I can change the value `testName` capability with any string like I mean ? example : `dc.setCapability("testName", "login");` – frianH Aug 21 '19 at 06:15
  • `dc.setCapability()` isn't meant to assign a new value. The Matcher and the JSON configuration define a set of capabilities held by the Node (such as which browser, which OS, etc). In the case of custom capabilities (such as your `testName` option), you'll assign a value to each node in the JSON configuration. Then, when configuring your `DesiredCapabilities` instance to be passed to your `RemoteWebDriver`, you're telling DC which capabilities to seek out when choosing a Node on which to run the test. – tim-slifer Aug 26 '19 at 18:20
  • By invoking `setCapability()`, you are telling DC which of the options to use that you've assigned to your various Nodes. In your example, `dc.setCapability("testName", "login")`, you're instructing DC to find a Node with the `"login"` value for the `"testName"` capability. – tim-slifer Aug 26 '19 at 18:21