3

I'm trying to run tests with CDP,

webdriver.execute_cdp_cmd('Network.enable', {}) 

with Remote webdriver (in Selenoid). But getting this error:

AttributeError: 'WebDriver' object has no attribute 'execute_cdp_cmd'. In local environment it works fine. I've tried to use Selenium 3.141.0 and 4.1.3.

I'm familiar with PyCDP documentation (https://py-cdp.readthedocs.io/en/latest/getting_started.html) but I didn't figured out how to properly use it.

Why it does not work with Remote webdriver? Do someone have an example of executing CDP commands using python in Selenium 4?

I use following capabilities, :

capabilities = { 'loggingPrefs': {'browser': 'ALL'}, 'goog:loggingPrefs': {'performance': 'ALL'}, "browserName": "chrome", "browserVersion": "99.0", "selenoid:options": { "enableVNC": True, "enableVideo": False } }

if request.config.getoption('--remote'): driver = webdriver.Remote(command_executor='selenoid.dev:4444/wd/hub', desired_capabilities=capabilities, options=options)

  • How are you setting up the remote webdriver? What are you using remotely? – ewokx May 05 '22 at 03:17
  • This is a client-side issue in your code. Not related to Selenoid. – vania-pooh May 06 '22 at 03:48
  • Hi guys. Here is the setting up code: if request.config.getoption('--remote'): driver = webdriver.Remote(command_executor='http://selenoid.dev:4444/wd/hub', desired_capabilities=capabilities, options=options) Tests are working remotely completely fine, except tests that use CDP – Daniel Proskurin May 06 '22 at 04:32
  • @ewong I use following capabilities, : capabilities = { 'loggingPrefs': {'browser': 'ALL'}, 'goog:loggingPrefs': {'performance': 'ALL'}, "browserName": "chrome", "browserVersion": "99.0", "selenoid:options": { "enableVNC": True, "enableVideo": False } } – Daniel Proskurin May 06 '22 at 04:41
  • Please include that in your original post and not in the comments. – ewokx May 06 '22 at 04:45

2 Answers2

3

Looks like CDP is not supported for remote webdrivers.

Found this sweet workaround the issue:

import json

def send(driver, cmd, params={}):
  resource = "/session/%s/chromium/send_command_and_get_result" % driver.session_id
  url = driver.command_executor._url + resource
  body = json.dumps({'cmd': cmd, 'params': params})
  response = driver.command_executor._request('POST', url, body)
  return response.get('value')

send(webdriver, 'Network.enable', {})

source and relevant discussion: https://github.com/SeleniumHQ/selenium/issues/8672

Hammad
  • 529
  • 7
  • 17
0

The official way to use CDP in Python's Selenium library is to use bidirectional functionality

It's an asyncio API. However, you can turn it into a sync API by using trio. I use a wrapper function to make it easier to use.

from selenium import webdriver
# You may need to change this if you need to use different version of CDP
import selenium.webdriver.common.devtools.v111 as devtools
import trio

def execute_cdp(driver: webdriver.Remote, cmd):
    async def execute_cdp_async():
        async with driver.bidi_connection() as session:
            cdp_session = session.session
            return await cdp_session.execute(cmd)
    # It will have error if we use asyncio.run
    # https://github.com/SeleniumHQ/selenium/issues/11244
    return trio.run(execute_cdp_async)

# Use it this way:
execute_cdp(driver, devtools.network.enable())
mhtml = execute_cdp(driver, devtools.page.capture_snapshot())
link89
  • 1,064
  • 10
  • 13