protractordesiredcapabilitiesselenoidwebdriver-w3c-spec

Protractor W3C capability


I am using Protractor with Selenoid. I need to use the dockerized Windows images so that I can test Internet Explorer and Edge from Linux boxes.

I was able to make it work from curl by running:

curl -X POST http://127.0.0.1:4444/wd/hub/session -d '{"capabilities":{"browserName":"MicrosoftEdge","count":1,"alwaysMatch":{"browserName":"MicrosoftEdge","selenoid:options":{"enableVNC":true,"enableVideo":false,"enableLog":true,"logName":"edge-18.0.log"}}}}'

My protractor config looks like:

  multiCapabilities: [
    {
      browserName: "MicrosoftEdge",
      "alwaysMatch": {
        browserName: "MicrosoftEdge",
        "selenoid:options": {
          enableVNC: true,
          enableVideo: false,
          enableLog: true,
          logName: "edge-18.0.log"
        }
      }
    }
  ]

But protractor send it over the selenoid server like this:

{
    "desiredCapabilities": {
        "browserName": "MicrosoftEdge",
        "count": 1,
        "alwaysMatch": {
            "browserName": "MicrosoftEdge",
            "selenoid:options": {
                "enableVNC": true,
                "enableVideo": false,
                "enableLog": true,
                "logName": "edge-18.0.log"
            }
        }
    }
}

The issue is that desiredCapabilities should just be 'capabilities`. I have been looking everywhere trying to find out where is that created so that I can created some sort of flag to be able to switch it.

Any ideas?


Solution

  • Using Protractor 6.0 solve my issue, but broke all my tests.

    I was able to keep using 5.4.1 by patching the selenium-webdriver package. Looking at the way Protractor 6 did it, I did it to Protractor 5.4.1:

    I edited the file located at node_modules/selenium-webdriver/lib/webdriver.js and added the following:

    // Capability names that are defined in the W3C spec.
    const W3C_CAPABILITY_NAMES = new Set([
        'acceptInsecureCerts',
        'browserName',
        'browserVersion',
        'platformName',
        'pageLoadStrategy',
        'proxy',
        'setWindowRect',
        'timeouts',
        'unhandledPromptBehavior',
    ]);
    

    Then in the same file I modify the static createSession(executor, capabilities, opt_flow, opt_onQuit) method to add the following:

        let W3CCaps = new Capabilities(capabilities);
        for (let k of W3CCaps.keys()) {
          // Any key containing a colon is a vendor-prefixed capability.
          if (!(W3C_CAPABILITY_NAMES.has(k) || k.indexOf(':') >= 0)) {
            W3CCaps.delete(k);
          }
        }
    
        cmd.setParameter('capabilities', W3CCaps);
    

    After all those changes the request getting to Selenoid is like this:

    {
        "desiredCapabilities": {
            "browserName": "MicrosoftEdge",
            "version": "18.0",
            "enableVNC": true,
            "enableVideo": false,
            "count": 1
        },
        "capabilities": {
            "browserName": "MicrosoftEdge"
        }
    }
    

    And my Protractor 5 config looks like this:

      multiCapabilities: [{
        browserName: 'MicrosoftEdge',
        version: '18.0',
        enableVNC: true,
        enableVideo: false
      }]
    

    Note:

    So that I don't have to worry about refresh installs or updates I use the package patch-package (https://github.com/ds300/patch-package) to create a patch that is applied when any of those events happen. Here is a great video explaining how to use that package https://www.youtube.com/watch?v=zBPcVGr6XPk