Chrome Devtools Protocol with Selenium ๐
Hey everyone! ๐
This blog post is a technical blog post about the work that I am doing with my awesome OpenSource team at BrowserStack!
From the official documentation of the ChromeDevtools Protocol (CDP) website.
The Chrome DevTools Protocol allows for tools to instrument, inspect, debug and profile Chromium, Chrome and other Blink-based browsers.
Too much jargon eh? ๐ Let me explain!
As a developer, I think many of us have used the little, yet powerful debugger in our browsers. The one that pops up when you do a right-click on a web page and you choose Inspect Element? Yeah, that one. Thatโs a debugger and it itself uses Chrome Devtools Protocol provided via an interface to manipulate settings that affect the rendering, loading of a web page.
How does it fit with Selenium? ๐
Well, I am sure all of you reading this blog have definitely, at the very least, must have heard of it? Many of you have used it to automate a browser too?
I used it in many of my automation projects while I was in college.
People working on the automation of test suites for a product use it all the time!
I work full-time on developing features for Selenium with the OpenSource Team at BrowserStack. Thatโs so cool, right? ๐ Indeed it is!
So one of the features that I worked on was to build the API support of Devtools Protocol within Selenium. That means you can use the same protocol via Selenium language bindings.
You can access a few of the methods that are supported by the protocol via the Selenium driver
object.
Why few, if you may ask? Well, the Devtools protocol keeps changing frequently, like very frequently and we have no way of knowing what changed when it changed and changes are not backward compatible always. So the selenium tech leadership decided to freeze a version of the protocol and include it in the binary in JSON format and support methods that the community asks for, along with those methods that the technical leadership sees value in. Value is again defined if the method is super useful to the users in general.
This JSON is then used to generate classes supported by Devtools and we use those class objects to invoke methods by implementing a wrapper around that method. The wrapper provides a way to pass a callback in case if it is required, does some validations on the input too. This entire communication happens over the WebSocket URL that browsers use to receive the commands from any source for invoking CDP methods. As a user, you just have to call those method wrappers provided by Selenium, and pass in the required arguments, and you are done! ๐
To learn more about the commands supported (as of Jan 2021) with Selenium language bindings, you can check the documentation page, it has the list of commands, their usage in various bindings (if any).
Letโs dive into some code with JS binding, for some commands that are added!
- Register Basic Auth
const pageCdpConnection = await driver.createCDPConnection('page') await driver.register('username', 'password', pageCdpConnection) await driver.get('<some_protected_url>')
Here, you create a CDP connection and ask the driver to register a username and password. Now this registration will be used whenever you hit a basic auth pop-up in your test. The login is automated now! Yeah, just like that!
2. Listening to DOM events
const cdpConnection = await driver.createCDPConnection('page') await driver.logMutationEvents(cdpConnection, function(event) { assert.equal(event['attribute_name'], 'style') assert.equal(event['current_value'], '') assert.equal(event['old_value'], 'display:none;')
}) await driver.get(<some_url_with_js>)
let element = driver.findElement({id: 'reveal'})
await element.click()
let revealed = driver.findElement({id: 'revealed'});
await driver.wait(until.elementIsVisible(revealed), 5000);
Here, if a js function changes something in the DOM, then the callback is called automatically with the event details as a parameter. You can process that event in any way you want.
3. Listening to console.log
events
const cdpConnection = await driver.createCDPConnection('page')await driver.onLogEvent(cdpConnection, function(event) {
assert.equal(event['args'][0]['value'], 'here')
})await driver.executeScript('console.log("here")')
With the above code, you can listen to console.log
events and trigger the callback that you pass to the onLogEvent
function.
Now, with these superpowers, what you do, is totally up to you! ๐
Selenium now allows you to manipulate the web page which is as good as using Devtools manually, but with automation!
I hope this blog was helpful. Got questions? Hit me up on Twitter!
Thatโs all for this post, folks!
Peace โฎ๏ธ