Monday 15 January 2018

The Selenium Server & Creating New Sessions

 I've had the pleasure of  being a co-editor of the W3C's WebDriver spec, as well as the original author and one of the current maintainers of Selenium's Java bindings, and one of the main authors of the current Selenium Server, particularly the pieces to do with implementing the W3C spec. So, as one of the few people on the planet who knows how all the pieces fit together, and why they fit together that way, I thought it might be helpful to explain how and why the Selenium Server handles a request to create a new session.

For this discussion, I'll use the terminology from the spec. A "remote end" refers to the Selenium Server, and a "local end" are the language bindings you're probably familiar with --- there's some in all the major programming languages, and about a million of them in the JS space too.

First of all, it's advisable for the local end to send a single request for a new session that includes the expected payloads for both the W3C and the JSON Wire Protocol dialects at the same time.

Consider the case where you just send the w3c payload ({"capabilities": {"browserName": "chrome"}}). In this case, a w3c server would correctly attempt to start a chrome session. However, a server that only obeys the JSON Wire Protocol will see an empty payload, in which case it's free to do whatever it wants.

Sending just the JSON Wire Protcol payload ({"desiredCapabilities": {"browserName": "firefox"}}) will create a firefox session in a server that understands the JSON Wire Protocol, but will cause a "no session created" error in a W3C compliant server (since that expects at least {"capabilities": {}} to be set).

So, we have the expected, legal behaviour of the remote end layed out.

For historical reasons, most bindings only accept a "desired capabilities" hash as the argument when creating a new driver instance. Converting the old-style payloads to legal W3C ones is a non-trivial exercise (for example, {"firefox_profile": "sdfgh"} is now {"moz:firefoxOptions": {"profile": "sdfgh"}}, but what happens if both are set? Also "platform" has become "platformName", but do the values match? Probably only at the OS family level, according to the note in the spec)

Most local end bindings get this mapping wrong, but the user doesn't care why their session isn't as they'd expected it to be, they just know it's not right. What to do? What, my friends, do we do?

The answer is to be generous about what we receive from the user and attempt to do what they want. Knowing that most local ends have at least a few problems converting the old format to the new format, the selenium server creates an ordered list of capabilities, putting the OSS ones at the front of the list to ensure maximum compatability.

So, now you know.