Values returned by webdrivers - selenium

After performing a search using POST /session/{session id}/element, I get this from the Chrome webdriver:
{ sessionId: '3241e7da289f4feb19c1f55dfc87024b',
status: 0,
value: { ELEMENT: '0.12239552668870868-1' } }
Is this what the specs demand?
I am asking because I couldn't find anywhere a spot where it said clearly "ELEMENT" in capital letters. All I can find in the specs is that a key called value is set (which it is: it's set as { ELEMENT: '0.12239552668870868-1' }
Can I always always expect this response, from other browsers' webdrivers? That is, are status and sessionId always returned?
Is that { ELEMENT: '0.12239552668870868-1' } the way chromium makes up the object? Or is this true for any webdrivers? Of not, what do other webdrivers return?

The WebDriver-W3C Candidate Recommendation clearly mentions the following points:
The Find Element command is used to find an element in the current browsing context that can be used for future commands.
Let location strategy be the result of getting a property called "using".
Let selector be the result of getting a property called "value".
The result of getting a property with argument name is defined as being the same as the result of calling Object.GetOwnProperty(propertyName).
GetOwnProperty(propertyName) in ECMAScript® Language Specification is defined as :
String objects use a variation of the GetOwnProperty internal method used for other native ECMAScript objects. This special internal method provides access to named properties corresponding to the individual characters of String objects.
So invoking GetOwnProperty are internal method used for other native ECMAScript objects and are resolved within the internal scope of the Browser Drivers and Browser Clients.
Mozilla have well documented Object.getOwnPropertyNames() and getOwnPropertyDescriptors().
Browser Specific Implementation
I did a small test with all the info you have provided with Search Box of Google Home Page i.e. https://www.google.co.in with all the major variants of WebDrivers and here is the result :
ChromeDriver - OSS :
[[ChromeDriver: chrome on XP (0d24fd038bde751b1e411711271c3e69)] -> name: q]
[[ChromeDriver: chrome on XP (0d24fd038bde751b1e411711271c3e69)] -> name: q]
FirefoxDriver - W3C :
[[FirefoxDriver: firefox on XP (e7a56813-97c5-466e-9c35-24c9f89af6ed)] -> name: q]
[[FirefoxDriver: firefox on XP (e7a56813-97c5-466e-9c35-24c9f89af6ed)] -> name: q]
InternetExplorerDriver - W3C :
[[InternetExplorerDriver: internet explorer on WINDOWS (367257db-cdbc-4be7-aeac-805a21ad9d2d)] -> name: q]
[[InternetExplorerDriver: internet explorer on WINDOWS (367257db-cdbc-4be7-aeac-805a21ad9d2d)] -> name: q]
So as you can observe from the field details of the concerned value field returned is in similar pattern and till the WebDriver variant passes the correct reference to user it shouldn't be a obstacle.
Finally, it is worth to mention at this point of time that like FirefoxDriver and InternetExplorerDriver (both being W3C compliant), ChromeDriver is almost W3C compliant and may vary from a few functional aspects.
Update A
As per your question and update, you are pretty right about ChromeDriver and Chrome communication protocol. Getting more granular we can find some difference in the webdriver call as follows :
Firefox :
1516626575533 webdriver::server DEBUG <- 200 OK {"value":{"element-6066-11e4-a52e-4f735466cecf":"6e35faa4-233f-400c-a6c7-6a66b54a69e5"}}
So, Firefox Browser returns :
"value":{"element-6066-11e4-a52e-4f735466cecf":"6e35faa4-233f-400c-a6c7-6a66b54a69e5"}
Chrome :
[14.921][DEBUG]: DEVTOOLS RESPONSE Runtime.evaluate (id=25) {
"result": {
"type": "object",
"value": {
"status": 0,
"value": {
"ELEMENT": "0.7086986861512812-1"
}
}
}
}
So, Chrome Browser returns :
"value": {"ELEMENT": "0.7086986861512812-1"}
What matters most to we user is the value of the element returned by the browser object which is always referred by an user and correctly identified by the webdriver instance. All these inner logic becomes abstract to the end user.
Update B
Adding some significant bytes from #FlorentB. 's comments :
The earlier versions of Selenium i.e. Selenium v2.x used the keyword ELEMENT to store the reference of a DOM Tree element. This key was changed within the recent versions of Selenium i.e. Selenium v3.x to element-6066-11e4-a52e-4f735466ce. Most of the implementation of the current ChromeDriver is still from the Selenium 2.x specifications.

I have just encountered this same issue, and found the change was made around 3.5 of the Selenium server and related images.
I found this comment the most specific to understand the change and identify which version it changed in:
https://github.com/SeleniumHQ/selenium/issues/4773#issuecomment-333092149
I am using Docker images like selenium/node-firefox:3.4.0-actinium, and have found v3.4.0 returns the ELEMENT key from the older JSonWire spec, whereas v3.9 returns the format element-6066-11e4-a52e-4f735466cecf from the new WebDriver spec. (I haven't checked any other versions in between).
It's part of their gradual migration to WebDriver, but it is a bit confusing that they did this breaking change at 3.5 (or thereabouts) and not v3.0.0 which I think everyone would have been OK with.
Also there's a mix of implementations in the "native" drivers like Gecko which is produced by the Firefox team now, and Chrome, as they will have different development roadmaps.
Furthermore, I've found the client-side library I'm using hasn't even implemented the new response yet, so I'll have to hang back for a while (or patch and PR it myself). I've seen similar conversations in other clients (like the Java client 2 years ago).
You can see the differences between the two protocols' definitions of the Element response:
https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#webelement-json-object
https://www.w3.org/TR/webdriver/#elements

Related

sendDevToolsCommand in Selenium 4 alpha

According to this article, Selenium 4 alpha has a sendDevToolsCommand that sends an arbitrary DevTools command to the browser and returns a promise that will be resolved when the command has finished:
Added “sendDevToolsCommand” and “setDownloadPath” for chrome.Driver.
But I can't seem to find how to use it. It sounds a bit like using JavaScript executor in Selenium.
Can someone provide an example usage? I'm using Selenium + Java.
The command to call the devtool api was added a few years back in the Chrome driver.
You can already use it with Selenium even if the method is not yet present:
Take full page screenshot
Print To PDF
Inject some Javascript before the page loads
Block a network URL
Save/restore the cookies for all domains
Get transparent screenshot
This command gives you access to the devtools api, which is used by ChromeDriver internally to drive the browser.
The method takes the name of the command as first argument and a dictionary of parameters as second argument. To figure out how to call a command, add puppeteer in your searches. For instance puppeteer set download location.
Note that executeCdpCommand is implemented in the Java master branch, so it should be available in the next release.
I couldn't find the sendDevToolsCommand in the Selenium documentation yet, but the source actually has the setDownloadPath that you also mentioned above defined right below, which actually uses the sendDevToolsCommand. Based on that usage, it seems like you could do something like:
const { Builder } = require("selenium-webdriver");
const driverInstance = await new Builder()
.withCapabilities({ browserName: "chrome" })
.build();
driverInstance.sendDevToolsCommand('Page.setDownloadBehavior', {
behavior: 'allow',
downloadPath: path
})
or for a visually obvious example:
await driverInstance.sendDevToolsCommand("Emulation.setDefaultBackgroundColorOverride", {
color: { r: 0, g: 255, b: 0, a: 1 } // watch out, it's bright!
});
where the first argument is a Chrome Devtools Protocol Domain method (e.g. or Page.setDownloadBehavior or Emulation.setCPUThrottlingRate) and the second argument is an object containing the options for that Domain method (as described in the same protocol docs).
Edit: just tested and the above works :)
I'm excited that this was added because it means that, in addition to network throttling, it should be pretty trivial to add cpu throttling to Selenium tests now! Something like:
driverInstance.sendDevToolsCommand('Emulation.setCPUThrottlingRate', {
rate: 4 // throttle cpu 4x
}
Selenium 4 release will have a user friendly API for Chrome DevTools protocol.
I just finished implementing Network and Performance domains for the Selenium Java client.
https://github.com/SeleniumHQ/selenium/pull/7212
In addition, there is a generic API for all domains in Java client that was merged a while ago.
All those new features will be released probably in the next Alpha release.

Cannot determine loading status in Google Maps

I had a test written in Java and Selenium that basically does a search for a provider. It then clicks on the provider's Map This Location link and opens a google map. I would wait for an xpath visibility for that map after switching to the new window.
The URL would be something like
https://www.google.com/maps/dir//945+N+12th+St,+Milwaukee,+WI+53233/#43.0426642,-87.9297109,17z/data=!4m8!4m7!1m0!1m5!1m1!1s0x88051979232b79cd:0x905e19b746c46eb3!2m2!1d-87.9275222!2d43.0426642
This has been working fine for a year. Today we got updated to Chrome version Version 74.0.3729.108 (Official Build) (64-bit) so we replaced our old Chromedriver (which was now giving us an error that the Chrome version had to be between 70 and 73) with 74.0.3729.6 which our head developer downloaded from the site.
The problem is, now, and only for certain addresses, I get that error
unknown error: cannot determine loading status from no such execution context
Some Stack Overflow items suggested
1. Updating the Chrome Driver
2. Using a longer timeout
as you can see from above we updated our chromedriver to be consistent with the version of Chrome. I also updated the timeout to 300 seconds (5 minutes), but all in vain.
I am out of ideas about what else could be causing the problem. The xpath I waited for was //div[#aria-label='Map'] but I have tried other xpaths now too, such as "//div[#id='streetviewcard']". I verified that the window I switched to was driver.getWindowHandles().get(1). I had saved the original handle so I could switch back. I looked at all the window handles, and there were only 2, the original one and the one I switched to.
No other searches come up with anything useful.
I had exactly the same error, moving to v74.
Something must have changed with chromedriver, or chrome - I assume that when a new tab is opened, execution continues sooner than it did before. It's hard to tell what's actually changed, but ultimately I fixed our issues with a sleep:
Also, it's worth noting that getWindowHandles() returns in an undefined order - so might need some extra handling depending on your use case.
https://github.com/dvsa/mot-automated-testsuite/compare/ops-OPSTEAM-2827-selenium#diff-1fa0893dd1ad67d9c1a4ee1e777c20cb

Selenium Grid Proxy: how to get the response after a command get executed

I created a Selenium Grid proxy, I want to log every command done, the problem is I can't find a way to get the response of the command for example after "GetTitle" command I want to get the "Title" returned.
Where do you want this logging to be done ? If you attempt at logging this at the Custom Proxy, then these logs would be available only on the machine that runs the hub. Is that what you want ? If yes, then here's how you should be doing it :
Within an overloaded variant of org.openqa.grid.internal.listeners.CommandListener#afterCommand (this method should be available in your DefaultRemoteProxy extension object that you are building), extract this information from within the javax.servlet.http.HttpServletRequest by reading its entity value and then translating that into a proper payload.
Here's how the afterCommand() (or) beforeCommand() method from your customized version of org.openqa.grid.selenium.proxy.DefaultRemoteProxy can look like:
org.openqa.grid.web.servlet.handler.SeleniumBasedResponse ar = new org.openqa.grid.web.servlet.handler.SeleniumBasedResponse(response);
if (ar.getForwardedContent() != null) {
System.err.println("Content" + ar.getForwardedContent());
}
If that's not what you want, then you should be looking at leveraging the EventFiringWebDriver. Take a look at the below blogs to learn how to work with the EventFiringWebDriver. The EventFiringWebDriver does not require customization at the Grid side, it just needs you to make use of the EventFiringWebDriver which would wrap within it an existing RemoteWebDriver object and the listeners you inject to it will help you get this.
http://darrellgrainger.blogspot.in/2011/02/generating-screen-capture-on-exception.html
https://rationaleemotions.wordpress.com/2015/04/18/eavesdropping-into-webdriver/ (This is my blog) Here I talk about not even using EventFiringWebDriver but instead work with a decorated CommandExecutor which would log all these information for you.

How to use webdriver using the dart library?

I am having trouble getting started with the webdriver dart library.
I was hoping for some simple examples.
I do have the seleniumn server standalone running in the background.
I am very new to dart and very experienced with ruby and watir-webdriver.
I was expecting something similar to the code below
import 'package:webdriver/webdriver.dart';
main() {
var url = "http://google.com";
var driver = new WebDriver();
b = driver.newSession(browser:'firefox');
b.getUrl(url);
}
But the error I am getting is
Unhandled exception:
No constructor 'WebDriver' declared in class 'WebDriver'.
Looking at the source
class WebDriver extends WebDriverBase {
WebDriver(host, port, path) : super(host, port, path);
So it seems like the constructor is there; and the defaults are in the WebDriverBase to go to the remote server. What am I doing wrong? I have scoured the internet trying to find simple examples with no luck
Currently, there are known issues with local and session storage, script execution, and log access.
To use these bindings, the Selenium standalone server must be running. You can download it at http://code.google.com/p/selenium/downloads/list.
There are a number of commands that use ids to access page elements. These ids are not the HTML ids; they are opaque ids internal to WebDriver. To get the id for an element you would first need to do a search, get the results, and extract the WebDriver id from the returned Map using the 'ELEMENT' key. see http://commondatastorage.googleapis.com/dartlang-api-docs/13991/webdriver.html

Selenium 2: getScreenshotAs() mixed up when running several tests in parallel

in a continuous integration build environment when running several Selenium tests in parallel (using Firefox driver) for different applications and each tests records its screenshots after every "action" (e.g. navigating to a page, submitting a form etc.) it seems like that whichever application window pops up that one gets on the top of the z-axis and will have the focus.
So using the method getScreenshotAs() from the Selenium API to record images results in mixed up screenshots sometimes showing one application and sometimes the other application.
Recording the HTML responses with getPageSource() on the other hand seems to work correctly using the Firefox driver instance "bound" to the test.
Is there any solution how to deal with the mixed up image screenshots? Is there a possibility how to ensure that getScreenshotAs() only consideres its own Firefox driver instance? Thanks for any hints!
Peter
I don't know what flavor of selenium you are using but here is a reference to the API that looks like it would fix your problem, but I have never tested it.
http://selenium.googlecode.com/svn/trunk/docs/api/dotnet/index.html
What that link shows is the IWrapDriver which according to the documentation Gets the IWebDriver used to find this element.
So from my understanding you could set your IWebDriver in your method and then wrapit with the IWrapDriver and then use that to reference for you getScreenShotAs();